Skip to main content

ahp_types/
state.rs

1// Generated from types/*.ts — do not edit.
2//
3// Regenerate with: npm run generate:rust
4
5#![allow(missing_docs)]
6
7#[allow(unused_imports)]
8use crate::common::{AnyValue, JsonObject, StringOrMarkdown, Uri};
9#[allow(unused_imports)]
10use serde::{Deserialize, Serialize};
11#[allow(unused_imports)]
12use serde_repr::{Deserialize_repr, Serialize_repr};
13
14// ─── Enums ────────────────────────────────────────────────────────────
15
16/// Policy configuration state for a model.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
18pub enum PolicyState {
19    #[serde(rename = "enabled")]
20    Enabled,
21    #[serde(rename = "disabled")]
22    Disabled,
23    #[serde(rename = "unconfigured")]
24    Unconfigured,
25}
26
27/// Discriminant for pending message kinds.
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub enum PendingMessageKind {
30    /// Injected into the current turn at a convenient point
31    #[serde(rename = "steering")]
32    Steering,
33    /// Sent automatically as a new turn after the current turn finishes
34    #[serde(rename = "queued")]
35    Queued,
36}
37
38/// Session initialization state.
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
40pub enum SessionLifecycle {
41    #[serde(rename = "creating")]
42    Creating,
43    #[serde(rename = "ready")]
44    Ready,
45    #[serde(rename = "creationFailed")]
46    CreationFailed,
47}
48
49/// Bitset of summary-level session status flags.
50///
51/// Use bitwise checks instead of equality for non-terminal activity. For example,
52/// `status & SessionStatus.InProgress` matches both ordinary in-progress turns
53/// and turns that are paused waiting for input.
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize_repr, Deserialize_repr)]
55#[repr(u32)]
56pub enum SessionStatus {
57    /// Session is idle — no turn is active.
58    Idle = 1,
59    /// Session ended with an error.
60    Error = 2,
61    /// A turn is actively streaming.
62    InProgress = 8,
63    /// A turn is in progress but blocked waiting for user input or tool confirmation.
64    InputNeeded = 24,
65    /// The client has viewed this session since its last modification.
66    IsRead = 32,
67    /// The session has been archived by the client.
68    IsArchived = 64,
69}
70
71/// Answer lifecycle state.
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
73pub enum SessionInputAnswerState {
74    #[serde(rename = "draft")]
75    Draft,
76    #[serde(rename = "submitted")]
77    Submitted,
78    #[serde(rename = "skipped")]
79    Skipped,
80}
81
82/// Answer value kind.
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
84pub enum SessionInputAnswerValueKind {
85    #[serde(rename = "text")]
86    Text,
87    #[serde(rename = "number")]
88    Number,
89    #[serde(rename = "boolean")]
90    Boolean,
91    #[serde(rename = "selected")]
92    Selected,
93    #[serde(rename = "selected-many")]
94    SelectedMany,
95}
96
97/// Question/input control kind.
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
99pub enum SessionInputQuestionKind {
100    #[serde(rename = "text")]
101    Text,
102    #[serde(rename = "number")]
103    Number,
104    #[serde(rename = "integer")]
105    Integer,
106    #[serde(rename = "boolean")]
107    Boolean,
108    #[serde(rename = "single-select")]
109    SingleSelect,
110    #[serde(rename = "multi-select")]
111    MultiSelect,
112}
113
114/// How a client completed an input request.
115#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
116pub enum SessionInputResponseKind {
117    #[serde(rename = "accept")]
118    Accept,
119    #[serde(rename = "decline")]
120    Decline,
121    #[serde(rename = "cancel")]
122    Cancel,
123}
124
125/// How a turn ended.
126#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
127pub enum TurnState {
128    #[serde(rename = "complete")]
129    Complete,
130    #[serde(rename = "cancelled")]
131    Cancelled,
132    #[serde(rename = "error")]
133    Error,
134}
135
136/// Discriminant for {@link MessageAttachment} variants.
137#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
138pub enum MessageAttachmentKind {
139    /// A simple, opaque attachment whose representation is described by the producer.
140    #[serde(rename = "simple")]
141    Simple,
142    /// An attachment whose data is embedded inline as a base64 string.
143    #[serde(rename = "embeddedResource")]
144    EmbeddedResource,
145    /// An attachment that references a resource by URI.
146    #[serde(rename = "resource")]
147    Resource,
148}
149
150/// Discriminant for response part types.
151#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
152pub enum ResponsePartKind {
153    #[serde(rename = "markdown")]
154    Markdown,
155    #[serde(rename = "contentRef")]
156    ContentRef,
157    #[serde(rename = "toolCall")]
158    ToolCall,
159    #[serde(rename = "reasoning")]
160    Reasoning,
161    #[serde(rename = "systemNotification")]
162    SystemNotification,
163}
164
165/// Status of a tool call in the lifecycle state machine.
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
167pub enum ToolCallStatus {
168    #[serde(rename = "streaming")]
169    Streaming,
170    #[serde(rename = "pending-confirmation")]
171    PendingConfirmation,
172    #[serde(rename = "running")]
173    Running,
174    #[serde(rename = "pending-result-confirmation")]
175    PendingResultConfirmation,
176    #[serde(rename = "completed")]
177    Completed,
178    #[serde(rename = "cancelled")]
179    Cancelled,
180}
181
182/// How a tool call was confirmed for execution.
183///
184/// - `NotNeeded` — No confirmation required (auto-approved)
185/// - `UserAction` — User explicitly approved
186/// - `Setting` — Approved by a persistent user setting
187#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
188pub enum ToolCallConfirmationReason {
189    #[serde(rename = "not-needed")]
190    NotNeeded,
191    #[serde(rename = "user-action")]
192    UserAction,
193    #[serde(rename = "setting")]
194    Setting,
195}
196
197/// Why a tool call was cancelled.
198#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
199pub enum ToolCallCancellationReason {
200    #[serde(rename = "denied")]
201    Denied,
202    #[serde(rename = "skipped")]
203    Skipped,
204    #[serde(rename = "result-denied")]
205    ResultDenied,
206}
207
208/// Whether a confirmation option represents an approval or denial action.
209#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
210pub enum ConfirmationOptionKind {
211    #[serde(rename = "approve")]
212    Approve,
213    #[serde(rename = "deny")]
214    Deny,
215}
216
217/// Discriminant for tool result content types.
218#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
219pub enum ToolResultContentType {
220    #[serde(rename = "text")]
221    Text,
222    #[serde(rename = "embeddedResource")]
223    EmbeddedResource,
224    #[serde(rename = "resource")]
225    Resource,
226    #[serde(rename = "fileEdit")]
227    FileEdit,
228    #[serde(rename = "terminal")]
229    Terminal,
230    #[serde(rename = "subagent")]
231    Subagent,
232}
233
234/// Discriminant for the kind of customization.
235///
236/// Top-level entries in {@link SessionState.customizations} and
237/// {@link AgentInfo.customizations} are always
238/// {@link CustomizationType.Plugin | `Plugin`} or
239/// {@link CustomizationType.Directory | `Directory`}; the remaining
240/// types appear only as children of those containers.
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
242pub enum CustomizationType {
243    #[serde(rename = "plugin")]
244    Plugin,
245    #[serde(rename = "directory")]
246    Directory,
247    #[serde(rename = "agent")]
248    Agent,
249    #[serde(rename = "skill")]
250    Skill,
251    #[serde(rename = "prompt")]
252    Prompt,
253    #[serde(rename = "rule")]
254    Rule,
255    #[serde(rename = "hook")]
256    Hook,
257    #[serde(rename = "mcpServer")]
258    McpServer,
259}
260
261/// Discriminant values for {@link CustomizationLoadState}.
262#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
263pub enum CustomizationLoadStatus {
264    #[serde(rename = "loading")]
265    Loading,
266    #[serde(rename = "loaded")]
267    Loaded,
268    #[serde(rename = "degraded")]
269    Degraded,
270    #[serde(rename = "error")]
271    Error,
272}
273
274/// Discriminant for terminal claim kinds.
275#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
276pub enum TerminalClaimKind {
277    #[serde(rename = "client")]
278    Client,
279    #[serde(rename = "session")]
280    Session,
281}
282
283/// Computation lifecycle of a {@link ChangesetState}.
284#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
285pub enum ChangesetStatus {
286    /// The server is still computing the contents of this changeset.
287    #[serde(rename = "computing")]
288    Computing,
289    /// The changeset has been fully computed and is up-to-date.
290    #[serde(rename = "ready")]
291    Ready,
292    /// Computation failed. The cause is described by
293    /// {@link ChangesetState.error}.
294    #[serde(rename = "error")]
295    Error,
296}
297
298/// Where a {@link ChangesetOperation} can be invoked.
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
300pub enum ChangesetOperationScope {
301    /// Applies to the whole changeset.
302    #[serde(rename = "changeset")]
303    Changeset,
304    /// Applies to a single file within the changeset.
305    #[serde(rename = "resource")]
306    Resource,
307    /// Applies to a line range within a single file.
308    #[serde(rename = "range")]
309    Range,
310}
311
312/// Discriminant for {@link ResourceChange.type}.
313#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
314pub enum ResourceChangeType {
315    #[serde(rename = "added")]
316    Added,
317    #[serde(rename = "updated")]
318    Updated,
319    #[serde(rename = "deleted")]
320    Deleted,
321}
322
323// ─── Structs ──────────────────────────────────────────────────────────
324
325/// An optionally-sized icon that can be displayed in a user interface.
326#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
327#[serde(rename_all = "camelCase")]
328pub struct Icon {
329    /// A standard URI pointing to an icon resource. May be an HTTP/HTTPS URL or a
330    /// `data:` URI with Base64-encoded image data.
331    ///
332    /// Consumers SHOULD take steps to ensure URLs serving icons are from the
333    /// same domain as the client/server or a trusted domain.
334    ///
335    /// Consumers SHOULD take appropriate precautions when consuming SVGs as they can contain
336    /// executable JavaScript.
337    pub src: Uri,
338    /// Optional MIME type override if the source MIME type is missing or generic.
339    /// For example: `"image/png"`, `"image/jpeg"`, or `"image/svg+xml"`.
340    #[serde(default, skip_serializing_if = "Option::is_none")]
341    pub content_type: Option<String>,
342    /// Optional array of strings that specify sizes at which the icon can be used.
343    /// Each string should be in WxH format (e.g., `"48x48"`, `"96x96"`) or `"any"` for scalable formats like SVG.
344    ///
345    /// If not provided, the client should assume that the icon can be used at any size.
346    #[serde(default, skip_serializing_if = "Option::is_none")]
347    pub sizes: Option<Vec<String>>,
348    /// Optional specifier for the theme this icon is designed for. `"light"` indicates
349    /// the icon is designed to be used with a light background, and `"dark"` indicates
350    /// the icon is designed to be used with a dark background.
351    ///
352    /// If not provided, the client should assume the icon can be used with any theme.
353    #[serde(default, skip_serializing_if = "Option::is_none")]
354    pub theme: Option<String>,
355}
356
357/// Describes a protected resource's authentication requirements using
358/// [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) (OAuth 2.0
359/// Protected Resource Metadata) semantics.
360///
361/// Field names use snake_case to match the RFC 9728 JSON format.
362#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
363#[serde(rename_all = "camelCase")]
364pub struct ProtectedResourceMetadata {
365    /// REQUIRED. The protected resource's resource identifier, a URL using the
366    /// `https` scheme with no fragment component (e.g. `"https://api.github.com"`).
367    pub resource: String,
368    /// OPTIONAL. Human-readable name of the protected resource.
369    #[serde(
370        rename = "resource_name",
371        default,
372        skip_serializing_if = "Option::is_none"
373    )]
374    pub resource_name: Option<String>,
375    /// OPTIONAL. JSON array of OAuth authorization server identifier URLs.
376    #[serde(
377        rename = "authorization_servers",
378        default,
379        skip_serializing_if = "Option::is_none"
380    )]
381    pub authorization_servers: Option<Vec<String>>,
382    /// OPTIONAL. URL of the protected resource's JWK Set document.
383    #[serde(rename = "jwks_uri", default, skip_serializing_if = "Option::is_none")]
384    pub jwks_uri: Option<String>,
385    /// RECOMMENDED. JSON array of OAuth 2.0 scope values used in authorization requests.
386    #[serde(
387        rename = "scopes_supported",
388        default,
389        skip_serializing_if = "Option::is_none"
390    )]
391    pub scopes_supported: Option<Vec<String>>,
392    /// OPTIONAL. JSON array of Bearer Token presentation methods supported.
393    #[serde(
394        rename = "bearer_methods_supported",
395        default,
396        skip_serializing_if = "Option::is_none"
397    )]
398    pub bearer_methods_supported: Option<Vec<String>>,
399    /// OPTIONAL. JSON array of JWS signing algorithms supported.
400    #[serde(
401        rename = "resource_signing_alg_values_supported",
402        default,
403        skip_serializing_if = "Option::is_none"
404    )]
405    pub resource_signing_alg_values_supported: Option<Vec<String>>,
406    /// OPTIONAL. JSON array of JWE encryption algorithms (alg) supported.
407    #[serde(
408        rename = "resource_encryption_alg_values_supported",
409        default,
410        skip_serializing_if = "Option::is_none"
411    )]
412    pub resource_encryption_alg_values_supported: Option<Vec<String>>,
413    /// OPTIONAL. JSON array of JWE encryption algorithms (enc) supported.
414    #[serde(
415        rename = "resource_encryption_enc_values_supported",
416        default,
417        skip_serializing_if = "Option::is_none"
418    )]
419    pub resource_encryption_enc_values_supported: Option<Vec<String>>,
420    /// OPTIONAL. URL of human-readable documentation for the resource.
421    #[serde(
422        rename = "resource_documentation",
423        default,
424        skip_serializing_if = "Option::is_none"
425    )]
426    pub resource_documentation: Option<String>,
427    /// OPTIONAL. URL of the resource's data-usage policy.
428    #[serde(
429        rename = "resource_policy_uri",
430        default,
431        skip_serializing_if = "Option::is_none"
432    )]
433    pub resource_policy_uri: Option<String>,
434    /// OPTIONAL. URL of the resource's terms of service.
435    #[serde(
436        rename = "resource_tos_uri",
437        default,
438        skip_serializing_if = "Option::is_none"
439    )]
440    pub resource_tos_uri: Option<String>,
441    /// AHP extension. Whether authentication is required for this resource.
442    ///
443    /// - `true` (default) — the agent cannot be used without a valid token.
444    ///   The server SHOULD return `AuthRequired` (`-32007`) if the client
445    ///   attempts to use the agent without authenticating.
446    /// - `false` — the agent works without authentication but MAY offer
447    ///   enhanced capabilities when a token is provided.
448    ///
449    /// Clients SHOULD treat an absent field the same as `true`.
450    #[serde(default, skip_serializing_if = "Option::is_none")]
451    pub required: Option<bool>,
452}
453
454/// Global state shared with every client subscribed to `ahp-root://`.
455#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
456#[serde(rename_all = "camelCase")]
457pub struct RootState {
458    /// Available agent backends and their models
459    pub agents: Vec<AgentInfo>,
460    /// Number of active (non-disposed) sessions on the server
461    #[serde(default, skip_serializing_if = "Option::is_none")]
462    pub active_sessions: Option<i64>,
463    /// Known terminals on the server. Subscribe to individual terminal URIs for full state.
464    #[serde(default, skip_serializing_if = "Option::is_none")]
465    pub terminals: Option<Vec<TerminalInfo>>,
466    /// Agent host configuration schema and current values
467    #[serde(default, skip_serializing_if = "Option::is_none")]
468    pub config: Option<RootConfigState>,
469}
470
471/// Live agent-host configuration metadata.
472///
473/// The schema describes the available configuration properties and the values
474/// contain the current value for each resolved property.
475#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
476#[serde(rename_all = "camelCase")]
477pub struct RootConfigState {
478    /// JSON Schema describing available configuration properties
479    pub schema: ConfigSchema,
480    /// Current configuration values
481    pub values: JsonObject,
482}
483
484#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
485#[serde(rename_all = "camelCase")]
486pub struct AgentInfo {
487    /// Agent provider ID (e.g. `'copilot'`)
488    pub provider: String,
489    /// Human-readable name
490    pub display_name: String,
491    /// Description string
492    pub description: String,
493    /// Available models for this agent
494    pub models: Vec<SessionModelInfo>,
495    /// Protected resources this agent requires authentication for.
496    ///
497    /// Each entry describes an OAuth 2.0 protected resource using
498    /// [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) semantics.
499    /// Clients should obtain tokens from the declared `authorization_servers`
500    /// and push them via the `authenticate` command before creating sessions
501    /// with this agent.
502    #[serde(default, skip_serializing_if = "Option::is_none")]
503    pub protected_resources: Option<Vec<ProtectedResourceMetadata>>,
504    /// Customizations associated with this agent.
505    ///
506    /// Always container customizations —
507    /// {@link PluginCustomization | `PluginCustomization`} entries the agent
508    /// bundles, plus {@link DirectoryCustomization | `DirectoryCustomization`}
509    /// entries it watches in any workspace it's used with. When a session is
510    /// created with this agent, these entries are augmented (e.g. directory
511    /// URIs are resolved against the workspace, children are parsed) and
512    /// propagated into the session's `customizations` list.
513    #[serde(default, skip_serializing_if = "Option::is_none")]
514    pub customizations: Option<Vec<Customization>>,
515}
516
517#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
518#[serde(rename_all = "camelCase")]
519pub struct SessionModelInfo {
520    /// Model identifier
521    pub id: String,
522    /// Provider this model belongs to
523    pub provider: String,
524    /// Human-readable model name
525    pub name: String,
526    /// Maximum context window size
527    #[serde(default, skip_serializing_if = "Option::is_none")]
528    pub max_context_window: Option<i64>,
529    /// Whether the model supports vision
530    #[serde(default, skip_serializing_if = "Option::is_none")]
531    pub supports_vision: Option<bool>,
532    /// Policy configuration state
533    #[serde(default, skip_serializing_if = "Option::is_none")]
534    pub policy_state: Option<PolicyState>,
535    /// Configuration schema describing model-specific options (e.g. thinking
536    /// level). Clients present this as a form and pass the resolved values in
537    /// {@link ModelSelection.config} when creating or changing sessions.
538    #[serde(default, skip_serializing_if = "Option::is_none")]
539    pub config_schema: Option<ConfigSchema>,
540    /// Additional provider-specific metadata for this model.
541    ///
542    /// Clients MAY look for well-known keys here to provide enhanced UI.
543    /// For example, a `pricing` key may carry model pricing metadata.
544    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
545    pub meta: Option<JsonObject>,
546}
547
548/// A model selection: the chosen model ID together with any model-specific
549/// configuration values whose keys correspond to the model's
550/// {@link SessionModelInfo.configSchema}.
551#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
552#[serde(rename_all = "camelCase")]
553pub struct ModelSelection {
554    /// Model identifier
555    pub id: String,
556    /// Model-specific configuration values
557    #[serde(default, skip_serializing_if = "Option::is_none")]
558    pub config: Option<std::collections::HashMap<String, String>>,
559}
560
561/// A selected custom agent for a session.
562///
563/// The `uri` identifies a specific custom agent (matching an
564/// {@link AgentCustomization.uri | `AgentCustomization.uri`} exposed via
565/// the session's effective customizations). Consumers resolve the agent's
566/// display name by looking up `uri` in the session's customization tree.
567///
568/// A session with no `agent` selected uses the provider's default behavior.
569#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
570#[serde(rename_all = "camelCase")]
571pub struct AgentSelection {
572    /// Stable agent URI (matches an {@link AgentCustomization.uri}).
573    pub uri: Uri,
574}
575
576/// A JSON Schema-compatible property descriptor with display extensions.
577///
578/// Standard JSON Schema fields (`type`, `title`, `description`, `default`,
579/// `enum`) allow validators to process the schema. Display extensions
580/// (`enumLabels`, `enumDescriptions`) are parallel arrays that provide UI
581/// metadata for each `enum` value.
582///
583/// This is the generic base type. See {@link SessionConfigPropertySchema} for
584/// session-specific extensions.
585#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
586#[serde(rename_all = "camelCase")]
587pub struct ConfigPropertySchema {
588    /// JSON Schema: property type
589    pub r#type: String,
590    /// JSON Schema: human-readable label for the property
591    pub title: String,
592    /// JSON Schema: description / tooltip
593    #[serde(default, skip_serializing_if = "Option::is_none")]
594    pub description: Option<String>,
595    /// JSON Schema: default value
596    #[serde(default, skip_serializing_if = "Option::is_none")]
597    pub default: Option<AnyValue>,
598    /// JSON Schema: allowed values (typically used with `string` type)
599    #[serde(default, skip_serializing_if = "Option::is_none")]
600    pub r#enum: Option<Vec<String>>,
601    /// Display extension: human-readable label per enum value (parallel array)
602    #[serde(default, skip_serializing_if = "Option::is_none")]
603    pub enum_labels: Option<Vec<String>>,
604    /// Display extension: description per enum value (parallel array)
605    #[serde(default, skip_serializing_if = "Option::is_none")]
606    pub enum_descriptions: Option<Vec<String>>,
607    /// JSON Schema: when `true`, the property is displayed but cannot be modified by the user
608    #[serde(default, skip_serializing_if = "Option::is_none")]
609    pub read_only: Option<bool>,
610    /// JSON Schema: schema for array items (used when `type` is `'array'`)
611    #[serde(default, skip_serializing_if = "Option::is_none")]
612    pub items: Option<Box<ConfigPropertySchema>>,
613    /// JSON Schema: property descriptors for object properties (used when `type` is `'object'`)
614    #[serde(default, skip_serializing_if = "Option::is_none")]
615    pub properties: Option<std::collections::HashMap<String, Box<ConfigPropertySchema>>>,
616    /// JSON Schema: list of required property ids (used when `type` is `'object'`)
617    #[serde(default, skip_serializing_if = "Option::is_none")]
618    pub required: Option<Vec<String>>,
619}
620
621/// A JSON Schema object describing available configuration properties.
622///
623/// This is the generic base type. See {@link SessionConfigSchema} for
624/// session-specific usage.
625#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
626#[serde(rename_all = "camelCase")]
627pub struct ConfigSchema {
628    /// JSON Schema: always `'object'`
629    pub r#type: String,
630    /// JSON Schema: property descriptors keyed by property id
631    pub properties: std::collections::HashMap<String, ConfigPropertySchema>,
632    /// JSON Schema: list of required property ids
633    #[serde(default, skip_serializing_if = "Option::is_none")]
634    pub required: Option<Vec<String>>,
635}
636
637/// A message queued for future delivery to the agent.
638///
639/// Steering messages are injected into the current turn mid-flight.
640/// Queued messages are automatically started as new turns after the
641/// current turn naturally finishes.
642#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
643#[serde(rename_all = "camelCase")]
644pub struct PendingMessage {
645    /// Unique identifier for this pending message
646    pub id: String,
647    /// The message content
648    pub user_message: UserMessage,
649}
650
651/// Full state for a single session, loaded when a client subscribes to the session's URI.
652#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
653#[serde(rename_all = "camelCase")]
654pub struct SessionState {
655    /// Lightweight session metadata
656    pub summary: SessionSummary,
657    /// Session initialization state
658    pub lifecycle: SessionLifecycle,
659    /// Error details if creation failed
660    #[serde(default, skip_serializing_if = "Option::is_none")]
661    pub creation_error: Option<ErrorInfo>,
662    /// Tools provided by the server (agent host) for this session
663    #[serde(default, skip_serializing_if = "Option::is_none")]
664    pub server_tools: Option<Vec<ToolDefinition>>,
665    /// The client currently providing tools and interactive capabilities to this session
666    #[serde(default, skip_serializing_if = "Option::is_none")]
667    pub active_client: Option<SessionActiveClient>,
668    /// Completed turns
669    pub turns: Vec<Turn>,
670    /// Currently in-progress turn
671    #[serde(default, skip_serializing_if = "Option::is_none")]
672    pub active_turn: Option<ActiveTurn>,
673    /// Message to inject into the current turn at a convenient point
674    #[serde(default, skip_serializing_if = "Option::is_none")]
675    pub steering_message: Option<PendingMessage>,
676    /// Messages to send automatically as new turns after the current turn finishes
677    #[serde(default, skip_serializing_if = "Option::is_none")]
678    pub queued_messages: Option<Vec<PendingMessage>>,
679    /// Requests for user input that are currently blocking or informing session progress
680    #[serde(default, skip_serializing_if = "Option::is_none")]
681    pub input_requests: Option<Vec<SessionInputRequest>>,
682    /// Session configuration schema and current values
683    #[serde(default, skip_serializing_if = "Option::is_none")]
684    pub config: Option<SessionConfigState>,
685    /// Top-level customizations active in this session.
686    ///
687    /// Always container customizations — {@link PluginCustomization} or
688    /// {@link DirectoryCustomization}. Children (agents, skills, prompts,
689    /// rules, hooks, MCP servers) live in each container's
690    /// {@link ContainerCustomizationBase.children | `children`} array.
691    ///
692    /// Client-published plugins arrive via
693    /// {@link SessionActiveClient.customizations | `activeClient.customizations`}
694    /// and the host propagates them into this list (typically with the
695    /// container's `clientId` set and `children` populated).
696    #[serde(default, skip_serializing_if = "Option::is_none")]
697    pub customizations: Option<Vec<Customization>>,
698    /// Additional provider-specific metadata for this session.
699    ///
700    /// Clients MAY look for well-known keys here to provide enhanced UI.
701    /// For example, a `git` key may provide extra git metadata about the session's
702    /// workingDirectory.
703    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
704    pub meta: Option<JsonObject>,
705}
706
707/// The client currently providing tools and interactive capabilities to a session.
708///
709/// Only one client may be active per session at a time. The server SHOULD
710/// automatically unset the active client if that client disconnects.
711#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
712#[serde(rename_all = "camelCase")]
713pub struct SessionActiveClient {
714    /// Client identifier (matches `clientId` from `initialize`)
715    pub client_id: String,
716    /// Human-readable client name (e.g. `"VS Code"`)
717    #[serde(default, skip_serializing_if = "Option::is_none")]
718    pub display_name: Option<String>,
719    /// Tools this client provides to the session
720    pub tools: Vec<ToolDefinition>,
721    /// Plugin customizations this client contributes to the session.
722    ///
723    /// Clients publish in [Open Plugins](https://open-plugins.com/) format
724    /// — i.e. always container-shaped plugins. They MAY synthesize virtual
725    /// plugins in memory and rely on the host to expand them into concrete
726    /// children inside {@link SessionState.customizations}.
727    #[serde(default, skip_serializing_if = "Option::is_none")]
728    pub customizations: Option<Vec<ClientPluginCustomization>>,
729}
730
731#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
732#[serde(rename_all = "camelCase")]
733pub struct SessionSummary {
734    /// Session URI
735    pub resource: Uri,
736    /// Agent provider ID
737    pub provider: String,
738    /// Session title
739    pub title: String,
740    /// Current session status
741    pub status: u32,
742    /// Human-readable description of what the session is currently doing
743    #[serde(default, skip_serializing_if = "Option::is_none")]
744    pub activity: Option<String>,
745    /// Creation timestamp
746    pub created_at: i64,
747    /// Last modification timestamp
748    pub modified_at: i64,
749    /// Server-owned project for this session
750    #[serde(default, skip_serializing_if = "Option::is_none")]
751    pub project: Option<ProjectInfo>,
752    /// Currently selected model
753    #[serde(default, skip_serializing_if = "Option::is_none")]
754    pub model: Option<ModelSelection>,
755    /// Currently selected custom agent.
756    ///
757    /// Absent (`undefined`) means no custom agent is selected for this session
758    /// — the session uses the provider's default behavior.
759    #[serde(default, skip_serializing_if = "Option::is_none")]
760    pub agent: Option<AgentSelection>,
761    /// The working directory URI for this session
762    #[serde(default, skip_serializing_if = "Option::is_none")]
763    pub working_directory: Option<Uri>,
764    /// Catalogue of changesets the server can produce for this session. Each
765    /// entry advertises a subscribable view of file changes (uncommitted,
766    /// session-wide, per-turn, etc.) and the URI template the client expands
767    /// before subscribing. See {@link ChangesetSummary} for the full shape and
768    /// {@link /guide/changesets | Changesets} for an overview of the model.
769    #[serde(default, skip_serializing_if = "Option::is_none")]
770    pub changesets: Option<Vec<ChangesetSummary>>,
771}
772
773/// Server-owned project metadata for a session.
774#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
775#[serde(rename_all = "camelCase")]
776pub struct ProjectInfo {
777    /// Project URI
778    pub uri: Uri,
779    /// Human-readable project name
780    pub display_name: String,
781}
782
783/// A session configuration property descriptor.
784///
785/// Extends the generic {@link ConfigPropertySchema} with session-specific
786/// display extensions.
787#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
788#[serde(rename_all = "camelCase")]
789pub struct SessionConfigPropertySchema {
790    /// JSON Schema: property type
791    pub r#type: String,
792    /// JSON Schema: human-readable label for the property
793    pub title: String,
794    /// JSON Schema: description / tooltip
795    #[serde(default, skip_serializing_if = "Option::is_none")]
796    pub description: Option<String>,
797    /// JSON Schema: default value
798    #[serde(default, skip_serializing_if = "Option::is_none")]
799    pub default: Option<AnyValue>,
800    /// JSON Schema: allowed values (typically used with `string` type)
801    #[serde(default, skip_serializing_if = "Option::is_none")]
802    pub r#enum: Option<Vec<String>>,
803    /// Display extension: human-readable label per enum value (parallel array)
804    #[serde(default, skip_serializing_if = "Option::is_none")]
805    pub enum_labels: Option<Vec<String>>,
806    /// Display extension: description per enum value (parallel array)
807    #[serde(default, skip_serializing_if = "Option::is_none")]
808    pub enum_descriptions: Option<Vec<String>>,
809    /// JSON Schema: when `true`, the property is displayed but cannot be modified by the user
810    #[serde(default, skip_serializing_if = "Option::is_none")]
811    pub read_only: Option<bool>,
812    /// JSON Schema: schema for array items (used when `type` is `'array'`)
813    #[serde(default, skip_serializing_if = "Option::is_none")]
814    pub items: Option<ConfigPropertySchema>,
815    /// JSON Schema: property descriptors for object properties (used when `type` is `'object'`)
816    #[serde(default, skip_serializing_if = "Option::is_none")]
817    pub properties: Option<std::collections::HashMap<String, ConfigPropertySchema>>,
818    /// JSON Schema: list of required property ids (used when `type` is `'object'`)
819    #[serde(default, skip_serializing_if = "Option::is_none")]
820    pub required: Option<Vec<String>>,
821    /// Display extension: when `true`, the full set of allowed values is too large
822    /// to enumerate statically. The client SHOULD use `sessionConfigCompletions`
823    /// to fetch matching values based on user input. Any values in `enum` are
824    /// seed/recent values for initial display.
825    #[serde(default, skip_serializing_if = "Option::is_none")]
826    pub enum_dynamic: Option<bool>,
827    /// When `true`, the user may change this property after session creation
828    #[serde(default, skip_serializing_if = "Option::is_none")]
829    pub session_mutable: Option<bool>,
830}
831
832/// A JSON Schema object describing available session configuration metadata.
833#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
834#[serde(rename_all = "camelCase")]
835pub struct SessionConfigSchema {
836    /// JSON Schema: always `'object'`
837    pub r#type: String,
838    /// JSON Schema: property descriptors keyed by property id
839    pub properties: std::collections::HashMap<String, SessionConfigPropertySchema>,
840    /// JSON Schema: list of required property ids
841    #[serde(default, skip_serializing_if = "Option::is_none")]
842    pub required: Option<Vec<String>>,
843}
844
845/// Live session configuration metadata.
846///
847/// The schema describes the available configuration properties and the values
848/// contain the current value for each resolved property.
849#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
850#[serde(rename_all = "camelCase")]
851pub struct SessionConfigState {
852    /// JSON Schema describing available configuration properties
853    pub schema: SessionConfigSchema,
854    /// Current configuration values
855    pub values: JsonObject,
856}
857
858/// A completed request/response cycle.
859#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
860#[serde(rename_all = "camelCase")]
861pub struct Turn {
862    /// Turn identifier
863    pub id: String,
864    /// The user's input
865    pub user_message: UserMessage,
866    /// All response content in stream order: text, tool calls, reasoning, and content refs.
867    ///
868    /// Consumers should derive display text by concatenating markdown parts,
869    /// and find tool calls by filtering for `ToolCall` parts.
870    pub response_parts: Vec<ResponsePart>,
871    /// Token usage info
872    #[serde(default, skip_serializing_if = "Option::is_none")]
873    pub usage: Option<UsageInfo>,
874    /// How the turn ended
875    pub state: TurnState,
876    /// Error details if state is `'error'`
877    #[serde(default, skip_serializing_if = "Option::is_none")]
878    pub error: Option<ErrorInfo>,
879}
880
881/// An in-progress turn — the assistant is actively streaming.
882#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
883#[serde(rename_all = "camelCase")]
884pub struct ActiveTurn {
885    /// Turn identifier
886    pub id: String,
887    /// The user's input
888    pub user_message: UserMessage,
889    /// All response content in stream order: text, tool calls, reasoning, and content refs.
890    ///
891    /// Tool call parts include `pendingPermissions` when permissions are awaiting user approval.
892    pub response_parts: Vec<ResponsePart>,
893    /// Token usage info
894    #[serde(default, skip_serializing_if = "Option::is_none")]
895    pub usage: Option<UsageInfo>,
896}
897
898/// A user message and its associated attachments.
899///
900/// Attachments MAY be referenced inside {@link UserMessage.text} via their
901/// {@link MessageAttachmentBase.range} field. Attachments without a range are
902/// still associated with the message but do not correspond to a specific span
903/// in the text.
904#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
905#[serde(rename_all = "camelCase")]
906pub struct UserMessage {
907    /// Message text
908    pub text: String,
909    /// File/selection attachments
910    #[serde(default, skip_serializing_if = "Option::is_none")]
911    pub attachments: Option<Vec<MessageAttachment>>,
912    /// Additional provider-specific metadata for this message.
913    ///
914    /// Clients MAY look for well-known keys here to provide enhanced UI, and
915    /// agent hosts MAY use it to carry context that does not fit any other
916    /// field. Mirrors the MCP `_meta` convention.
917    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
918    pub meta: Option<JsonObject>,
919}
920
921/// A choice in a select-style question.
922#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
923#[serde(rename_all = "camelCase")]
924pub struct SessionInputOption {
925    /// Stable option identifier; for MCP enum values this is the enum string
926    pub id: String,
927    /// Display label
928    pub label: String,
929    /// Optional secondary text
930    #[serde(default, skip_serializing_if = "Option::is_none")]
931    pub description: Option<String>,
932    /// Whether this option is the recommended/default choice
933    #[serde(default, skip_serializing_if = "Option::is_none")]
934    pub recommended: Option<bool>,
935}
936
937/// Value captured for one answer.
938#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
939#[serde(rename_all = "camelCase")]
940pub struct SessionInputTextAnswerValue {
941    pub value: String,
942}
943
944#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
945#[serde(rename_all = "camelCase")]
946pub struct SessionInputNumberAnswerValue {
947    pub value: f64,
948}
949
950#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
951#[serde(rename_all = "camelCase")]
952pub struct SessionInputBooleanAnswerValue {
953    pub value: bool,
954}
955
956#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
957#[serde(rename_all = "camelCase")]
958pub struct SessionInputSelectedAnswerValue {
959    pub value: String,
960    /// Free-form text entered instead of selecting an option
961    #[serde(default, skip_serializing_if = "Option::is_none")]
962    pub freeform_values: Option<Vec<String>>,
963}
964
965#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
966#[serde(rename_all = "camelCase")]
967pub struct SessionInputSelectedManyAnswerValue {
968    pub value: Vec<String>,
969    /// Free-form text entered in addition to selected options
970    #[serde(default, skip_serializing_if = "Option::is_none")]
971    pub freeform_values: Option<Vec<String>>,
972}
973
974#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
975#[serde(rename_all = "camelCase")]
976pub struct SessionInputAnswered {
977    /// Answer value
978    pub value: SessionInputAnswerValue,
979}
980
981#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
982#[serde(rename_all = "camelCase")]
983pub struct SessionInputSkipped {
984    /// Free-form reason or value captured while skipping, if any
985    #[serde(default, skip_serializing_if = "Option::is_none")]
986    pub freeform_values: Option<Vec<String>>,
987}
988
989/// Text question within a session input request.
990#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
991#[serde(rename_all = "camelCase")]
992pub struct SessionInputTextQuestion {
993    /// Stable question identifier used as the key in `answers`
994    pub id: String,
995    /// Short display title
996    #[serde(default, skip_serializing_if = "Option::is_none")]
997    pub title: Option<String>,
998    /// Prompt shown to the user
999    pub message: String,
1000    /// Whether the user must answer this question to accept the request
1001    #[serde(default, skip_serializing_if = "Option::is_none")]
1002    pub required: Option<bool>,
1003    /// Format hint for text questions, such as `email`, `uri`, `date`, or `date-time`
1004    #[serde(default, skip_serializing_if = "Option::is_none")]
1005    pub format: Option<String>,
1006    /// Minimum string length
1007    #[serde(default, skip_serializing_if = "Option::is_none")]
1008    pub min: Option<i64>,
1009    /// Maximum string length
1010    #[serde(default, skip_serializing_if = "Option::is_none")]
1011    pub max: Option<i64>,
1012    /// Default text
1013    #[serde(default, skip_serializing_if = "Option::is_none")]
1014    pub default_value: Option<String>,
1015}
1016
1017/// Numeric question within a session input request.
1018#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1019#[serde(rename_all = "camelCase")]
1020pub struct SessionInputNumberQuestion {
1021    /// Stable question identifier used as the key in `answers`
1022    pub id: String,
1023    /// Short display title
1024    #[serde(default, skip_serializing_if = "Option::is_none")]
1025    pub title: Option<String>,
1026    /// Prompt shown to the user
1027    pub message: String,
1028    /// Whether the user must answer this question to accept the request
1029    #[serde(default, skip_serializing_if = "Option::is_none")]
1030    pub required: Option<bool>,
1031    /// Minimum value
1032    #[serde(default, skip_serializing_if = "Option::is_none")]
1033    pub min: Option<f64>,
1034    /// Maximum value
1035    #[serde(default, skip_serializing_if = "Option::is_none")]
1036    pub max: Option<f64>,
1037    /// Default numeric value
1038    #[serde(default, skip_serializing_if = "Option::is_none")]
1039    pub default_value: Option<f64>,
1040}
1041
1042/// Boolean question within a session input request.
1043#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1044#[serde(rename_all = "camelCase")]
1045pub struct SessionInputBooleanQuestion {
1046    /// Stable question identifier used as the key in `answers`
1047    pub id: String,
1048    /// Short display title
1049    #[serde(default, skip_serializing_if = "Option::is_none")]
1050    pub title: Option<String>,
1051    /// Prompt shown to the user
1052    pub message: String,
1053    /// Whether the user must answer this question to accept the request
1054    #[serde(default, skip_serializing_if = "Option::is_none")]
1055    pub required: Option<bool>,
1056    /// Default boolean value
1057    #[serde(default, skip_serializing_if = "Option::is_none")]
1058    pub default_value: Option<bool>,
1059}
1060
1061/// Single-select question within a session input request.
1062#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1063#[serde(rename_all = "camelCase")]
1064pub struct SessionInputSingleSelectQuestion {
1065    /// Stable question identifier used as the key in `answers`
1066    pub id: String,
1067    /// Short display title
1068    #[serde(default, skip_serializing_if = "Option::is_none")]
1069    pub title: Option<String>,
1070    /// Prompt shown to the user
1071    pub message: String,
1072    /// Whether the user must answer this question to accept the request
1073    #[serde(default, skip_serializing_if = "Option::is_none")]
1074    pub required: Option<bool>,
1075    /// Options the user may select from
1076    pub options: Vec<SessionInputOption>,
1077    /// Whether the user may enter text instead of selecting an option
1078    #[serde(default, skip_serializing_if = "Option::is_none")]
1079    pub allow_freeform_input: Option<bool>,
1080}
1081
1082/// Multi-select question within a session input request.
1083#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1084#[serde(rename_all = "camelCase")]
1085pub struct SessionInputMultiSelectQuestion {
1086    /// Stable question identifier used as the key in `answers`
1087    pub id: String,
1088    /// Short display title
1089    #[serde(default, skip_serializing_if = "Option::is_none")]
1090    pub title: Option<String>,
1091    /// Prompt shown to the user
1092    pub message: String,
1093    /// Whether the user must answer this question to accept the request
1094    #[serde(default, skip_serializing_if = "Option::is_none")]
1095    pub required: Option<bool>,
1096    /// Options the user may select from
1097    pub options: Vec<SessionInputOption>,
1098    /// Whether the user may enter text in addition to selecting options
1099    #[serde(default, skip_serializing_if = "Option::is_none")]
1100    pub allow_freeform_input: Option<bool>,
1101    /// Minimum selected item count
1102    #[serde(default, skip_serializing_if = "Option::is_none")]
1103    pub min: Option<i64>,
1104    /// Maximum selected item count
1105    #[serde(default, skip_serializing_if = "Option::is_none")]
1106    pub max: Option<i64>,
1107}
1108
1109/// A live request for user input.
1110///
1111/// The server creates or replaces requests with `session/inputRequested`.
1112/// Clients sync drafts with `session/inputAnswerChanged` and complete requests
1113/// with `session/inputCompleted`.
1114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1115#[serde(rename_all = "camelCase")]
1116pub struct SessionInputRequest {
1117    /// Stable request identifier
1118    pub id: String,
1119    /// Display message for the request as a whole
1120    #[serde(default, skip_serializing_if = "Option::is_none")]
1121    pub message: Option<String>,
1122    /// URL the user should review or open, for URL-style elicitations
1123    #[serde(default, skip_serializing_if = "Option::is_none")]
1124    pub url: Option<Uri>,
1125    /// Ordered questions to ask the user
1126    #[serde(default, skip_serializing_if = "Option::is_none")]
1127    pub questions: Option<Vec<SessionInputQuestion>>,
1128    /// Current draft or submitted answers, keyed by question ID
1129    #[serde(default, skip_serializing_if = "Option::is_none")]
1130    pub answers: Option<std::collections::HashMap<String, SessionInputAnswer>>,
1131}
1132
1133/// A zero-based position within a textual document.
1134#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1135#[serde(rename_all = "camelCase")]
1136pub struct TextPosition {
1137    /// Zero-based line number.
1138    pub line: i64,
1139    /// Zero-based character offset within the line.
1140    pub character: i64,
1141}
1142
1143/// A range within a textual document.
1144#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1145#[serde(rename_all = "camelCase")]
1146pub struct TextRange {
1147    /// Start position of the range.
1148    pub start: TextPosition,
1149    /// End position of the range.
1150    pub end: TextPosition,
1151}
1152
1153/// A selection within a textual resource.
1154///
1155/// This is only meaningful for textual resources. Binary resources may still
1156/// use resource or embedded resource attachments, but they should not use this
1157/// text selection field.
1158#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1159#[serde(rename_all = "camelCase")]
1160pub struct TextSelection {
1161    /// The range covered by the selection.
1162    pub range: TextRange,
1163}
1164
1165/// A simple, opaque attachment whose model representation is described by
1166/// the producer.
1167#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1168#[serde(rename_all = "camelCase")]
1169pub struct SimpleMessageAttachment {
1170    /// A human-readable label for the attachment (e.g. the filename of a file
1171    /// attachment). Used for display in UI.
1172    pub label: String,
1173    /// If defined, the range in {@link UserMessage.text} that references this
1174    /// attachment. This is a text range, not a byte range.
1175    #[serde(default, skip_serializing_if = "Option::is_none")]
1176    pub range: Option<TextRange>,
1177    /// Advisory display hint for clients rendering this attachment. Recognized
1178    /// values include:
1179    ///
1180    /// - `'image'`: the attachment is an image
1181    /// - `'document'`: the attachment is a textual document
1182    /// - `'symbol'`: the attachment is a code symbol (e.g. a function or class)
1183    /// - `'directory'`: the attachment is a folder
1184    /// - `'selection'`: the attachment is a selection within a document
1185    ///
1186    /// Implementations MAY provide additional values; clients SHOULD fall back
1187    /// to a reasonable default when an unknown value is encountered.
1188    #[serde(default, skip_serializing_if = "Option::is_none")]
1189    pub display_kind: Option<String>,
1190    /// Additional implementation-defined metadata for the attachment.
1191    ///
1192    /// If the attachment was produced by the `completions` command, the client
1193    /// MUST preserve every property of `_meta` originally returned by the agent
1194    /// host when sending the user message containing the accepted completion.
1195    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1196    pub meta: Option<JsonObject>,
1197    /// Representation of the attachment as it should be shown to the model.
1198    ///
1199    /// If the attachment was produced by the client, this property MUST be
1200    /// defined so the agent host can correctly interpret the attachment. This
1201    /// property MAY be omitted when the attachment originated from a
1202    /// `completions` response.
1203    #[serde(default, skip_serializing_if = "Option::is_none")]
1204    pub model_representation: Option<String>,
1205}
1206
1207/// An attachment whose data is embedded inline as a base64 string.
1208///
1209/// Use this for small binary payloads (e.g. a pasted image) that should be
1210/// delivered with the user message itself rather than fetched separately.
1211#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1212#[serde(rename_all = "camelCase")]
1213pub struct MessageEmbeddedResourceAttachment {
1214    /// A human-readable label for the attachment (e.g. the filename of a file
1215    /// attachment). Used for display in UI.
1216    pub label: String,
1217    /// If defined, the range in {@link UserMessage.text} that references this
1218    /// attachment. This is a text range, not a byte range.
1219    #[serde(default, skip_serializing_if = "Option::is_none")]
1220    pub range: Option<TextRange>,
1221    /// Advisory display hint for clients rendering this attachment. Recognized
1222    /// values include:
1223    ///
1224    /// - `'image'`: the attachment is an image
1225    /// - `'document'`: the attachment is a textual document
1226    /// - `'symbol'`: the attachment is a code symbol (e.g. a function or class)
1227    /// - `'directory'`: the attachment is a folder
1228    /// - `'selection'`: the attachment is a selection within a document
1229    ///
1230    /// Implementations MAY provide additional values; clients SHOULD fall back
1231    /// to a reasonable default when an unknown value is encountered.
1232    #[serde(default, skip_serializing_if = "Option::is_none")]
1233    pub display_kind: Option<String>,
1234    /// Additional implementation-defined metadata for the attachment.
1235    ///
1236    /// If the attachment was produced by the `completions` command, the client
1237    /// MUST preserve every property of `_meta` originally returned by the agent
1238    /// host when sending the user message containing the accepted completion.
1239    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1240    pub meta: Option<JsonObject>,
1241    /// Base64-encoded binary data
1242    pub data: String,
1243    /// Content MIME type (e.g. `"image/png"`, `"application/pdf"`)
1244    pub content_type: String,
1245    /// Optional selection within the attached textual resource.
1246    ///
1247    /// Only meaningful for textual resources.
1248    #[serde(default, skip_serializing_if = "Option::is_none")]
1249    pub selection: Option<TextSelection>,
1250}
1251
1252/// An attachment that references a resource by URI. The content is not
1253/// delivered inline; consumers can fetch it via `resourceRead` when needed.
1254#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1255#[serde(rename_all = "camelCase")]
1256pub struct MessageResourceAttachment {
1257    /// A human-readable label for the attachment (e.g. the filename of a file
1258    /// attachment). Used for display in UI.
1259    pub label: String,
1260    /// If defined, the range in {@link UserMessage.text} that references this
1261    /// attachment. This is a text range, not a byte range.
1262    #[serde(default, skip_serializing_if = "Option::is_none")]
1263    pub range: Option<TextRange>,
1264    /// Advisory display hint for clients rendering this attachment. Recognized
1265    /// values include:
1266    ///
1267    /// - `'image'`: the attachment is an image
1268    /// - `'document'`: the attachment is a textual document
1269    /// - `'symbol'`: the attachment is a code symbol (e.g. a function or class)
1270    /// - `'directory'`: the attachment is a folder
1271    /// - `'selection'`: the attachment is a selection within a document
1272    ///
1273    /// Implementations MAY provide additional values; clients SHOULD fall back
1274    /// to a reasonable default when an unknown value is encountered.
1275    #[serde(default, skip_serializing_if = "Option::is_none")]
1276    pub display_kind: Option<String>,
1277    /// Additional implementation-defined metadata for the attachment.
1278    ///
1279    /// If the attachment was produced by the `completions` command, the client
1280    /// MUST preserve every property of `_meta` originally returned by the agent
1281    /// host when sending the user message containing the accepted completion.
1282    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1283    pub meta: Option<JsonObject>,
1284    /// Content URI
1285    pub uri: Uri,
1286    /// Approximate size in bytes
1287    #[serde(default, skip_serializing_if = "Option::is_none")]
1288    pub size_hint: Option<i64>,
1289    /// Content MIME type
1290    #[serde(default, skip_serializing_if = "Option::is_none")]
1291    pub content_type: Option<String>,
1292    /// Optional selection within the referenced textual resource.
1293    ///
1294    /// Only meaningful for textual resources.
1295    #[serde(default, skip_serializing_if = "Option::is_none")]
1296    pub selection: Option<TextSelection>,
1297}
1298
1299#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1300#[serde(rename_all = "camelCase")]
1301pub struct MarkdownResponsePart {
1302    /// Part identifier, used by `session/delta` to target this part for content appends
1303    pub id: String,
1304    /// Markdown content
1305    pub content: String,
1306}
1307
1308/// A reference to large content stored outside the state tree.
1309#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1310#[serde(rename_all = "camelCase")]
1311pub struct ContentRef {
1312    /// Content URI
1313    pub uri: Uri,
1314    /// Approximate size in bytes
1315    #[serde(default, skip_serializing_if = "Option::is_none")]
1316    pub size_hint: Option<i64>,
1317    /// Content MIME type
1318    #[serde(default, skip_serializing_if = "Option::is_none")]
1319    pub content_type: Option<String>,
1320}
1321
1322/// A content part that's a reference to large content stored outside the state tree.
1323#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1324#[serde(rename_all = "camelCase")]
1325pub struct ResourceResponsePart {
1326    /// Content URI
1327    pub uri: Uri,
1328    /// Approximate size in bytes
1329    #[serde(default, skip_serializing_if = "Option::is_none")]
1330    pub size_hint: Option<i64>,
1331    /// Content MIME type
1332    #[serde(default, skip_serializing_if = "Option::is_none")]
1333    pub content_type: Option<String>,
1334}
1335
1336/// A tool call represented as a response part.
1337///
1338/// Tool calls are part of the response stream, interleaved with text and
1339/// reasoning. The `toolCall.toolCallId` serves as the part identifier for
1340/// actions that target this part.
1341#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1342#[serde(rename_all = "camelCase")]
1343pub struct ToolCallResponsePart {
1344    /// Full tool call lifecycle state
1345    pub tool_call: ToolCallState,
1346}
1347
1348/// Reasoning/thinking content from the model.
1349#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1350#[serde(rename_all = "camelCase")]
1351pub struct ReasoningResponsePart {
1352    /// Part identifier, used by `session/reasoning` to target this part for content appends
1353    pub id: String,
1354    /// Accumulated reasoning text
1355    pub content: String,
1356}
1357
1358/// A system notification surfaced as part of the response stream.
1359///
1360/// System notifications are messages authored by the agent harness
1361/// that need to be visible to both the agent (for situational awareness) and
1362/// the user (for transcript continuity). Examples include "background subagent
1363/// X completed" or "task Y was cancelled".
1364#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1365#[serde(rename_all = "camelCase")]
1366pub struct SystemNotificationResponsePart {
1367    /// The text of the system notification
1368    pub content: StringOrMarkdown,
1369}
1370
1371/// Tool execution result details, available after execution completes.
1372#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1373#[serde(rename_all = "camelCase")]
1374pub struct ToolCallResult {
1375    /// Whether the tool succeeded
1376    pub success: bool,
1377    /// Past-tense description of what the tool did
1378    pub past_tense_message: StringOrMarkdown,
1379    /// Unstructured result content blocks.
1380    ///
1381    /// This mirrors the `content` field of MCP `CallToolResult`.
1382    #[serde(default, skip_serializing_if = "Option::is_none")]
1383    pub content: Option<Vec<ToolResultContent>>,
1384    /// Optional structured result object.
1385    ///
1386    /// This mirrors the `structuredContent` field of MCP `CallToolResult`.
1387    #[serde(default, skip_serializing_if = "Option::is_none")]
1388    pub structured_content: Option<JsonObject>,
1389    /// Error details if the tool failed
1390    #[serde(default, skip_serializing_if = "Option::is_none")]
1391    pub error: Option<AnyValue>,
1392}
1393
1394/// A confirmation option that the server offers for a tool call awaiting
1395/// approval. Allows richer choices beyond simple approve/deny — for example,
1396/// "Approve in this Session" or "Deny with reason."
1397#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1398#[serde(rename_all = "camelCase")]
1399pub struct ConfirmationOption {
1400    /// Unique identifier for the option, returned in the confirmed action
1401    pub id: String,
1402    /// Human-readable label displayed to the user
1403    pub label: String,
1404    /// Whether this option represents an approval or denial
1405    pub kind: ConfirmationOptionKind,
1406    /// Logical group number for visual categorisation.
1407    ///
1408    /// Clients SHOULD display options in the order they are defined and MAY
1409    /// use differing group numbers to insert dividers between logical clusters
1410    /// of options.
1411    #[serde(default, skip_serializing_if = "Option::is_none")]
1412    pub group: Option<i64>,
1413}
1414
1415/// LM is streaming the tool call parameters.
1416#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1417#[serde(rename_all = "camelCase")]
1418pub struct ToolCallStreamingState {
1419    /// Unique tool call identifier
1420    pub tool_call_id: String,
1421    /// Internal tool name (for debugging/logging)
1422    pub tool_name: String,
1423    /// Human-readable tool name
1424    pub display_name: String,
1425    /// If this tool is provided by a client, the `clientId` of the owning client.
1426    /// Absent for server-side tools.
1427    ///
1428    /// When set, the identified client is responsible for executing the tool and
1429    /// dispatching `session/toolCallComplete` with the result.
1430    #[serde(default, skip_serializing_if = "Option::is_none")]
1431    pub tool_client_id: Option<String>,
1432    /// Additional provider-specific metadata for this tool call.
1433    ///
1434    /// Clients MAY look for well-known keys here to provide enhanced UI.
1435    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
1436    /// indicates the tool operated on a terminal (both `input` and `output` may
1437    /// contain escape sequences).
1438    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1439    pub meta: Option<JsonObject>,
1440    /// Partial parameters accumulated so far
1441    #[serde(default, skip_serializing_if = "Option::is_none")]
1442    pub partial_input: Option<String>,
1443    /// Progress message shown while parameters are streaming
1444    #[serde(default, skip_serializing_if = "Option::is_none")]
1445    pub invocation_message: Option<StringOrMarkdown>,
1446}
1447
1448/// Parameters are complete, or a running tool requires re-confirmation
1449/// (e.g. a mid-execution permission check).
1450#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1451#[serde(rename_all = "camelCase")]
1452pub struct ToolCallPendingConfirmationState {
1453    /// Unique tool call identifier
1454    pub tool_call_id: String,
1455    /// Internal tool name (for debugging/logging)
1456    pub tool_name: String,
1457    /// Human-readable tool name
1458    pub display_name: String,
1459    /// If this tool is provided by a client, the `clientId` of the owning client.
1460    /// Absent for server-side tools.
1461    ///
1462    /// When set, the identified client is responsible for executing the tool and
1463    /// dispatching `session/toolCallComplete` with the result.
1464    #[serde(default, skip_serializing_if = "Option::is_none")]
1465    pub tool_client_id: Option<String>,
1466    /// Additional provider-specific metadata for this tool call.
1467    ///
1468    /// Clients MAY look for well-known keys here to provide enhanced UI.
1469    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
1470    /// indicates the tool operated on a terminal (both `input` and `output` may
1471    /// contain escape sequences).
1472    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1473    pub meta: Option<JsonObject>,
1474    /// Message describing what the tool will do
1475    pub invocation_message: StringOrMarkdown,
1476    /// Raw tool input
1477    #[serde(default, skip_serializing_if = "Option::is_none")]
1478    pub tool_input: Option<String>,
1479    /// Short title for the confirmation prompt (e.g. `"Run in terminal"`, `"Write file"`)
1480    #[serde(default, skip_serializing_if = "Option::is_none")]
1481    pub confirmation_title: Option<StringOrMarkdown>,
1482    /// File edits that this tool call will perform, for preview before confirmation
1483    #[serde(default, skip_serializing_if = "Option::is_none")]
1484    pub edits: Option<AnyValue>,
1485    /// Whether the agent host allows the client to edit the tool's input parameters before confirming
1486    #[serde(default, skip_serializing_if = "Option::is_none")]
1487    pub editable: Option<bool>,
1488    /// Options the server offers for this confirmation. When present, the client
1489    /// SHOULD render these instead of a plain approve/deny UI. Each option
1490    /// belongs to a {@link ConfirmationOptionGroup} so the client can still
1491    /// categorise the choices.
1492    #[serde(default, skip_serializing_if = "Option::is_none")]
1493    pub options: Option<Vec<ConfirmationOption>>,
1494}
1495
1496/// Tool is actively executing.
1497#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1498#[serde(rename_all = "camelCase")]
1499pub struct ToolCallRunningState {
1500    /// Unique tool call identifier
1501    pub tool_call_id: String,
1502    /// Internal tool name (for debugging/logging)
1503    pub tool_name: String,
1504    /// Human-readable tool name
1505    pub display_name: String,
1506    /// If this tool is provided by a client, the `clientId` of the owning client.
1507    /// Absent for server-side tools.
1508    ///
1509    /// When set, the identified client is responsible for executing the tool and
1510    /// dispatching `session/toolCallComplete` with the result.
1511    #[serde(default, skip_serializing_if = "Option::is_none")]
1512    pub tool_client_id: Option<String>,
1513    /// Additional provider-specific metadata for this tool call.
1514    ///
1515    /// Clients MAY look for well-known keys here to provide enhanced UI.
1516    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
1517    /// indicates the tool operated on a terminal (both `input` and `output` may
1518    /// contain escape sequences).
1519    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1520    pub meta: Option<JsonObject>,
1521    /// Message describing what the tool will do
1522    pub invocation_message: StringOrMarkdown,
1523    /// Raw tool input
1524    #[serde(default, skip_serializing_if = "Option::is_none")]
1525    pub tool_input: Option<String>,
1526    /// How the tool was confirmed for execution
1527    pub confirmed: ToolCallConfirmationReason,
1528    /// The confirmation option the user selected, if confirmation options were provided
1529    #[serde(default, skip_serializing_if = "Option::is_none")]
1530    pub selected_option: Option<ConfirmationOption>,
1531    /// Partial content produced while the tool is still executing.
1532    ///
1533    /// For example, a terminal content block lets clients subscribe to live
1534    /// output before the tool completes.
1535    #[serde(default, skip_serializing_if = "Option::is_none")]
1536    pub content: Option<Vec<ToolResultContent>>,
1537}
1538
1539/// Tool finished executing, waiting for client to approve the result.
1540#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1541#[serde(rename_all = "camelCase")]
1542pub struct ToolCallPendingResultConfirmationState {
1543    /// Unique tool call identifier
1544    pub tool_call_id: String,
1545    /// Internal tool name (for debugging/logging)
1546    pub tool_name: String,
1547    /// Human-readable tool name
1548    pub display_name: String,
1549    /// If this tool is provided by a client, the `clientId` of the owning client.
1550    /// Absent for server-side tools.
1551    ///
1552    /// When set, the identified client is responsible for executing the tool and
1553    /// dispatching `session/toolCallComplete` with the result.
1554    #[serde(default, skip_serializing_if = "Option::is_none")]
1555    pub tool_client_id: Option<String>,
1556    /// Additional provider-specific metadata for this tool call.
1557    ///
1558    /// Clients MAY look for well-known keys here to provide enhanced UI.
1559    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
1560    /// indicates the tool operated on a terminal (both `input` and `output` may
1561    /// contain escape sequences).
1562    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1563    pub meta: Option<JsonObject>,
1564    /// Message describing what the tool will do
1565    pub invocation_message: StringOrMarkdown,
1566    /// Raw tool input
1567    #[serde(default, skip_serializing_if = "Option::is_none")]
1568    pub tool_input: Option<String>,
1569    /// Whether the tool succeeded
1570    pub success: bool,
1571    /// Past-tense description of what the tool did
1572    pub past_tense_message: StringOrMarkdown,
1573    /// Unstructured result content blocks.
1574    ///
1575    /// This mirrors the `content` field of MCP `CallToolResult`.
1576    #[serde(default, skip_serializing_if = "Option::is_none")]
1577    pub content: Option<Vec<ToolResultContent>>,
1578    /// Optional structured result object.
1579    ///
1580    /// This mirrors the `structuredContent` field of MCP `CallToolResult`.
1581    #[serde(default, skip_serializing_if = "Option::is_none")]
1582    pub structured_content: Option<JsonObject>,
1583    /// Error details if the tool failed
1584    #[serde(default, skip_serializing_if = "Option::is_none")]
1585    pub error: Option<AnyValue>,
1586    /// How the tool was confirmed for execution
1587    pub confirmed: ToolCallConfirmationReason,
1588    /// The confirmation option the user selected, if confirmation options were provided
1589    #[serde(default, skip_serializing_if = "Option::is_none")]
1590    pub selected_option: Option<ConfirmationOption>,
1591}
1592
1593/// Tool completed successfully or with an error.
1594#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1595#[serde(rename_all = "camelCase")]
1596pub struct ToolCallCompletedState {
1597    /// Unique tool call identifier
1598    pub tool_call_id: String,
1599    /// Internal tool name (for debugging/logging)
1600    pub tool_name: String,
1601    /// Human-readable tool name
1602    pub display_name: String,
1603    /// If this tool is provided by a client, the `clientId` of the owning client.
1604    /// Absent for server-side tools.
1605    ///
1606    /// When set, the identified client is responsible for executing the tool and
1607    /// dispatching `session/toolCallComplete` with the result.
1608    #[serde(default, skip_serializing_if = "Option::is_none")]
1609    pub tool_client_id: Option<String>,
1610    /// Additional provider-specific metadata for this tool call.
1611    ///
1612    /// Clients MAY look for well-known keys here to provide enhanced UI.
1613    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
1614    /// indicates the tool operated on a terminal (both `input` and `output` may
1615    /// contain escape sequences).
1616    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1617    pub meta: Option<JsonObject>,
1618    /// Message describing what the tool will do
1619    pub invocation_message: StringOrMarkdown,
1620    /// Raw tool input
1621    #[serde(default, skip_serializing_if = "Option::is_none")]
1622    pub tool_input: Option<String>,
1623    /// Whether the tool succeeded
1624    pub success: bool,
1625    /// Past-tense description of what the tool did
1626    pub past_tense_message: StringOrMarkdown,
1627    /// Unstructured result content blocks.
1628    ///
1629    /// This mirrors the `content` field of MCP `CallToolResult`.
1630    #[serde(default, skip_serializing_if = "Option::is_none")]
1631    pub content: Option<Vec<ToolResultContent>>,
1632    /// Optional structured result object.
1633    ///
1634    /// This mirrors the `structuredContent` field of MCP `CallToolResult`.
1635    #[serde(default, skip_serializing_if = "Option::is_none")]
1636    pub structured_content: Option<JsonObject>,
1637    /// Error details if the tool failed
1638    #[serde(default, skip_serializing_if = "Option::is_none")]
1639    pub error: Option<AnyValue>,
1640    /// How the tool was confirmed for execution
1641    pub confirmed: ToolCallConfirmationReason,
1642    /// The confirmation option the user selected, if confirmation options were provided
1643    #[serde(default, skip_serializing_if = "Option::is_none")]
1644    pub selected_option: Option<ConfirmationOption>,
1645}
1646
1647/// Tool call was cancelled before execution.
1648#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1649#[serde(rename_all = "camelCase")]
1650pub struct ToolCallCancelledState {
1651    /// Unique tool call identifier
1652    pub tool_call_id: String,
1653    /// Internal tool name (for debugging/logging)
1654    pub tool_name: String,
1655    /// Human-readable tool name
1656    pub display_name: String,
1657    /// If this tool is provided by a client, the `clientId` of the owning client.
1658    /// Absent for server-side tools.
1659    ///
1660    /// When set, the identified client is responsible for executing the tool and
1661    /// dispatching `session/toolCallComplete` with the result.
1662    #[serde(default, skip_serializing_if = "Option::is_none")]
1663    pub tool_client_id: Option<String>,
1664    /// Additional provider-specific metadata for this tool call.
1665    ///
1666    /// Clients MAY look for well-known keys here to provide enhanced UI.
1667    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
1668    /// indicates the tool operated on a terminal (both `input` and `output` may
1669    /// contain escape sequences).
1670    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1671    pub meta: Option<JsonObject>,
1672    /// Message describing what the tool will do
1673    pub invocation_message: StringOrMarkdown,
1674    /// Raw tool input
1675    #[serde(default, skip_serializing_if = "Option::is_none")]
1676    pub tool_input: Option<String>,
1677    /// Why the tool was cancelled
1678    pub reason: ToolCallCancellationReason,
1679    /// Optional message explaining the cancellation
1680    #[serde(default, skip_serializing_if = "Option::is_none")]
1681    pub reason_message: Option<StringOrMarkdown>,
1682    /// What the user suggested doing instead
1683    #[serde(default, skip_serializing_if = "Option::is_none")]
1684    pub user_suggestion: Option<UserMessage>,
1685    /// The confirmation option the user selected, if confirmation options were provided
1686    #[serde(default, skip_serializing_if = "Option::is_none")]
1687    pub selected_option: Option<ConfirmationOption>,
1688}
1689
1690/// Describes a tool available in a session, provided by either the server or the active client.
1691#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1692#[serde(rename_all = "camelCase")]
1693pub struct ToolDefinition {
1694    /// Unique tool identifier
1695    pub name: String,
1696    /// Human-readable display name
1697    #[serde(default, skip_serializing_if = "Option::is_none")]
1698    pub title: Option<String>,
1699    /// Description of what the tool does
1700    #[serde(default, skip_serializing_if = "Option::is_none")]
1701    pub description: Option<String>,
1702    /// JSON Schema defining the expected input parameters.
1703    ///
1704    /// Optional because client-provided tools may not have formal schemas.
1705    /// Mirrors MCP `Tool.inputSchema`.
1706    #[serde(default, skip_serializing_if = "Option::is_none")]
1707    pub input_schema: Option<AnyValue>,
1708    /// JSON Schema defining the structure of the tool's output.
1709    ///
1710    /// Mirrors MCP `Tool.outputSchema`.
1711    #[serde(default, skip_serializing_if = "Option::is_none")]
1712    pub output_schema: Option<AnyValue>,
1713    /// Behavioral hints about the tool. All properties are advisory.
1714    #[serde(default, skip_serializing_if = "Option::is_none")]
1715    pub annotations: Option<ToolAnnotations>,
1716    /// Additional provider-specific metadata.
1717    ///
1718    /// Mirrors the MCP `_meta` convention.
1719    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1720    pub meta: Option<JsonObject>,
1721}
1722
1723/// Behavioral hints about a tool. All properties are advisory and not
1724/// guaranteed to faithfully describe tool behavior.
1725///
1726/// Mirrors MCP `ToolAnnotations` from the Model Context Protocol specification.
1727#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1728#[serde(rename_all = "camelCase")]
1729pub struct ToolAnnotations {
1730    /// Alternate human-readable title
1731    #[serde(default, skip_serializing_if = "Option::is_none")]
1732    pub title: Option<String>,
1733    /// Tool does not modify its environment (default: false)
1734    #[serde(default, skip_serializing_if = "Option::is_none")]
1735    pub read_only_hint: Option<bool>,
1736    /// Tool may perform destructive updates (default: true)
1737    #[serde(default, skip_serializing_if = "Option::is_none")]
1738    pub destructive_hint: Option<bool>,
1739    /// Repeated calls with the same arguments have no additional effect (default: false)
1740    #[serde(default, skip_serializing_if = "Option::is_none")]
1741    pub idempotent_hint: Option<bool>,
1742    /// Tool may interact with external entities (default: true)
1743    #[serde(default, skip_serializing_if = "Option::is_none")]
1744    pub open_world_hint: Option<bool>,
1745}
1746
1747/// Text content in a tool result.
1748///
1749/// Mirrors MCP `TextContent`.
1750#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1751#[serde(rename_all = "camelCase")]
1752pub struct ToolResultTextContent {
1753    /// The text content
1754    pub text: String,
1755}
1756
1757/// Base64-encoded binary content embedded in a tool result.
1758///
1759/// Mirrors MCP `EmbeddedResource` for inline binary data.
1760#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1761#[serde(rename_all = "camelCase")]
1762pub struct ToolResultEmbeddedResourceContent {
1763    /// Base64-encoded data
1764    pub data: String,
1765    /// Content type (e.g. `"image/png"`, `"application/pdf"`)
1766    pub content_type: String,
1767}
1768
1769/// A reference to a resource stored outside the tool result.
1770///
1771/// Wraps {@link ContentRef} for lazy-loading large results.
1772#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1773#[serde(rename_all = "camelCase")]
1774pub struct ToolResultResourceContent {
1775    /// Content URI
1776    pub uri: Uri,
1777    /// Approximate size in bytes
1778    #[serde(default, skip_serializing_if = "Option::is_none")]
1779    pub size_hint: Option<i64>,
1780    /// Content MIME type
1781    #[serde(default, skip_serializing_if = "Option::is_none")]
1782    pub content_type: Option<String>,
1783}
1784
1785/// Describes a file modification performed by a tool.
1786#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1787#[serde(rename_all = "camelCase")]
1788pub struct ToolResultFileEditContent {
1789    /// The file state before the edit. Absent for file creations or for in-place file edits.
1790    #[serde(default, skip_serializing_if = "Option::is_none")]
1791    pub before: Option<AnyValue>,
1792    /// The file state after the edit. Absent for file deletions.
1793    #[serde(default, skip_serializing_if = "Option::is_none")]
1794    pub after: Option<AnyValue>,
1795    /// Optional diff display metadata
1796    #[serde(default, skip_serializing_if = "Option::is_none")]
1797    pub diff: Option<AnyValue>,
1798}
1799
1800/// A reference to a terminal whose output is relevant to this tool result.
1801///
1802/// Clients can subscribe to the terminal's URI to stream its output in real
1803/// time, providing live feedback while a tool is executing.
1804#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1805#[serde(rename_all = "camelCase")]
1806pub struct ToolResultTerminalContent {
1807    /// Terminal URI (subscribable for full terminal state)
1808    pub resource: Uri,
1809    /// Display title for the terminal content
1810    pub title: String,
1811}
1812
1813/// A reference to a subagent session spawned by a tool.
1814///
1815/// Clients can subscribe to the subagent's session URI to stream its
1816/// progress in real time, including inner tool calls and responses.
1817#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1818#[serde(rename_all = "camelCase")]
1819pub struct ToolResultSubagentContent {
1820    /// Subagent session URI (subscribable for full session state)
1821    pub resource: Uri,
1822    /// Display title for the subagent
1823    pub title: String,
1824    /// Internal agent name
1825    #[serde(default, skip_serializing_if = "Option::is_none")]
1826    pub agent_name: Option<String>,
1827    /// Human-readable description of the subagent's task
1828    #[serde(default, skip_serializing_if = "Option::is_none")]
1829    pub description: Option<String>,
1830}
1831
1832/// Container is being loaded by the host.
1833#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1834#[serde(rename_all = "camelCase")]
1835pub struct CustomizationLoadingState {}
1836
1837/// Container loaded successfully.
1838#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1839#[serde(rename_all = "camelCase")]
1840pub struct CustomizationLoadedState {}
1841
1842/// Container partially loaded but has warnings.
1843#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1844#[serde(rename_all = "camelCase")]
1845pub struct CustomizationDegradedState {
1846    /// Human-readable description of the warning.
1847    pub message: String,
1848}
1849
1850/// Container failed to load.
1851#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1852#[serde(rename_all = "camelCase")]
1853pub struct CustomizationErrorState {
1854    /// Human-readable error message.
1855    pub message: String,
1856}
1857
1858/// An [Open Plugins](https://open-plugins.com/) plugin.
1859#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1860#[serde(rename_all = "camelCase")]
1861pub struct PluginCustomization {
1862    /// Session-unique opaque identifier. Used by every action that targets a
1863    /// specific customization. Minted by whoever publishes the customization
1864    /// (typically the agent host).
1865    pub id: String,
1866    /// Source URI for this customization. A plugin URL, a file URI, or a
1867    /// directory URI.
1868    ///
1869    /// For declarations that live inside a larger file — e.g. an MCP
1870    /// server declared inline in a `plugins.json` manifest — `uri` points
1871    /// to the containing file and {@link CustomizationBase.range | `range`}
1872    /// narrows it to the declaration's span.
1873    pub uri: Uri,
1874    /// Human-readable name.
1875    pub name: String,
1876    /// Icons for UI display.
1877    #[serde(default, skip_serializing_if = "Option::is_none")]
1878    pub icons: Option<Vec<Icon>>,
1879    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
1880    /// customization is a subset of a larger file (for example, one entry
1881    /// in an inline `mcpServers` block of a `plugins.json` manifest).
1882    /// Absent when the customization covers the whole resource.
1883    #[serde(default, skip_serializing_if = "Option::is_none")]
1884    pub range: Option<TextRange>,
1885    /// Whether this container is currently enabled.
1886    pub enabled: bool,
1887    /// `clientId` of the client that contributed this container. Absent for
1888    /// server-originated entries.
1889    #[serde(default, skip_serializing_if = "Option::is_none")]
1890    pub client_id: Option<String>,
1891    /// Host-reported load state. Absent means the host has not yet reported
1892    /// a load state for this container.
1893    #[serde(default, skip_serializing_if = "Option::is_none")]
1894    pub load: Option<CustomizationLoadState>,
1895    /// Children discovered inside this container.
1896    ///
1897    /// Absent means the host has not parsed this container yet. An empty
1898    /// array means the host parsed the container and it contributes
1899    /// nothing.
1900    #[serde(default, skip_serializing_if = "Option::is_none")]
1901    pub children: Option<Vec<ChildCustomization>>,
1902}
1903
1904/// A {@link PluginCustomization} as published by a client. Extends the
1905/// server-facing shape with an opaque `nonce` so the host can detect when
1906/// the client's view of a plugin has changed and re-parse only as needed.
1907///
1908/// Clients SHOULD include a `nonce`. Server-side fields like
1909/// {@link ContainerCustomizationBase.children | `children`} and
1910/// {@link ContainerCustomizationBase.load | `load`} are typically left
1911/// absent on publication and populated by the host when the resolved
1912/// plugin appears in {@link SessionState.customizations}.
1913#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1914#[serde(rename_all = "camelCase")]
1915pub struct ClientPluginCustomization {
1916    /// Session-unique opaque identifier. Used by every action that targets a
1917    /// specific customization. Minted by whoever publishes the customization
1918    /// (typically the agent host).
1919    pub id: String,
1920    /// Source URI for this customization. A plugin URL, a file URI, or a
1921    /// directory URI.
1922    ///
1923    /// For declarations that live inside a larger file — e.g. an MCP
1924    /// server declared inline in a `plugins.json` manifest — `uri` points
1925    /// to the containing file and {@link CustomizationBase.range | `range`}
1926    /// narrows it to the declaration's span.
1927    pub uri: Uri,
1928    /// Human-readable name.
1929    pub name: String,
1930    /// Icons for UI display.
1931    #[serde(default, skip_serializing_if = "Option::is_none")]
1932    pub icons: Option<Vec<Icon>>,
1933    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
1934    /// customization is a subset of a larger file (for example, one entry
1935    /// in an inline `mcpServers` block of a `plugins.json` manifest).
1936    /// Absent when the customization covers the whole resource.
1937    #[serde(default, skip_serializing_if = "Option::is_none")]
1938    pub range: Option<TextRange>,
1939    /// Whether this container is currently enabled.
1940    pub enabled: bool,
1941    /// `clientId` of the client that contributed this container. Absent for
1942    /// server-originated entries.
1943    #[serde(default, skip_serializing_if = "Option::is_none")]
1944    pub client_id: Option<String>,
1945    /// Host-reported load state. Absent means the host has not yet reported
1946    /// a load state for this container.
1947    #[serde(default, skip_serializing_if = "Option::is_none")]
1948    pub load: Option<CustomizationLoadState>,
1949    /// Children discovered inside this container.
1950    ///
1951    /// Absent means the host has not parsed this container yet. An empty
1952    /// array means the host parsed the container and it contributes
1953    /// nothing.
1954    #[serde(default, skip_serializing_if = "Option::is_none")]
1955    pub children: Option<Vec<ChildCustomization>>,
1956    /// Opaque version token used by the host to detect changes.
1957    #[serde(default, skip_serializing_if = "Option::is_none")]
1958    pub nonce: Option<String>,
1959}
1960
1961/// A directory the host watches for this session.
1962///
1963/// Presence in the customization list signals that the host may discover
1964/// customizations from this directory. When `writable` is `true`, clients
1965/// MAY persist new customizations into the directory using
1966/// [`resourceWrite`](/reference/common#resourcewrite); the host will
1967/// then surface the resulting child via the customization actions.
1968///
1969/// The directory may not yet exist on disk.
1970#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1971#[serde(rename_all = "camelCase")]
1972pub struct DirectoryCustomization {
1973    /// Session-unique opaque identifier. Used by every action that targets a
1974    /// specific customization. Minted by whoever publishes the customization
1975    /// (typically the agent host).
1976    pub id: String,
1977    /// Source URI for this customization. A plugin URL, a file URI, or a
1978    /// directory URI.
1979    ///
1980    /// For declarations that live inside a larger file — e.g. an MCP
1981    /// server declared inline in a `plugins.json` manifest — `uri` points
1982    /// to the containing file and {@link CustomizationBase.range | `range`}
1983    /// narrows it to the declaration's span.
1984    pub uri: Uri,
1985    /// Human-readable name.
1986    pub name: String,
1987    /// Icons for UI display.
1988    #[serde(default, skip_serializing_if = "Option::is_none")]
1989    pub icons: Option<Vec<Icon>>,
1990    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
1991    /// customization is a subset of a larger file (for example, one entry
1992    /// in an inline `mcpServers` block of a `plugins.json` manifest).
1993    /// Absent when the customization covers the whole resource.
1994    #[serde(default, skip_serializing_if = "Option::is_none")]
1995    pub range: Option<TextRange>,
1996    /// Whether this container is currently enabled.
1997    pub enabled: bool,
1998    /// `clientId` of the client that contributed this container. Absent for
1999    /// server-originated entries.
2000    #[serde(default, skip_serializing_if = "Option::is_none")]
2001    pub client_id: Option<String>,
2002    /// Host-reported load state. Absent means the host has not yet reported
2003    /// a load state for this container.
2004    #[serde(default, skip_serializing_if = "Option::is_none")]
2005    pub load: Option<CustomizationLoadState>,
2006    /// Children discovered inside this container.
2007    ///
2008    /// Absent means the host has not parsed this container yet. An empty
2009    /// array means the host parsed the container and it contributes
2010    /// nothing.
2011    #[serde(default, skip_serializing_if = "Option::is_none")]
2012    pub children: Option<Vec<ChildCustomization>>,
2013    /// Which child customization type this directory holds.
2014    pub contents: CustomizationType,
2015    /// Whether clients may write into this directory.
2016    pub writable: bool,
2017}
2018
2019/// A custom agent contributed by a plugin or directory.
2020///
2021/// Mirrors the [Open Plugins agent](https://open-plugins.com/agent-builders/components/agents)
2022/// format: a markdown file with YAML frontmatter, where the body is the
2023/// agent's system prompt.
2024#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2025#[serde(rename_all = "camelCase")]
2026pub struct AgentCustomization {
2027    /// Session-unique opaque identifier. Used by every action that targets a
2028    /// specific customization. Minted by whoever publishes the customization
2029    /// (typically the agent host).
2030    pub id: String,
2031    /// Source URI for this customization. A plugin URL, a file URI, or a
2032    /// directory URI.
2033    ///
2034    /// For declarations that live inside a larger file — e.g. an MCP
2035    /// server declared inline in a `plugins.json` manifest — `uri` points
2036    /// to the containing file and {@link CustomizationBase.range | `range`}
2037    /// narrows it to the declaration's span.
2038    pub uri: Uri,
2039    /// Human-readable name.
2040    pub name: String,
2041    /// Icons for UI display.
2042    #[serde(default, skip_serializing_if = "Option::is_none")]
2043    pub icons: Option<Vec<Icon>>,
2044    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
2045    /// customization is a subset of a larger file (for example, one entry
2046    /// in an inline `mcpServers` block of a `plugins.json` manifest).
2047    /// Absent when the customization covers the whole resource.
2048    #[serde(default, skip_serializing_if = "Option::is_none")]
2049    pub range: Option<TextRange>,
2050    /// Short description of what the agent specializes in and when to
2051    /// invoke it. Sourced from the agent file's frontmatter `description`.
2052    #[serde(default, skip_serializing_if = "Option::is_none")]
2053    pub description: Option<String>,
2054}
2055
2056/// A skill contributed by a plugin or directory.
2057///
2058/// Covers both [Open Plugins skill formats](https://open-plugins.com/agent-builders/components/skills)
2059/// — the `skills/` directory layout (one subdirectory per skill, each with
2060/// a `SKILL.md`) and the flatter `commands/` directory of slash-command
2061/// skills.
2062#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2063#[serde(rename_all = "camelCase")]
2064pub struct SkillCustomization {
2065    /// Session-unique opaque identifier. Used by every action that targets a
2066    /// specific customization. Minted by whoever publishes the customization
2067    /// (typically the agent host).
2068    pub id: String,
2069    /// Source URI for this customization. A plugin URL, a file URI, or a
2070    /// directory URI.
2071    ///
2072    /// For declarations that live inside a larger file — e.g. an MCP
2073    /// server declared inline in a `plugins.json` manifest — `uri` points
2074    /// to the containing file and {@link CustomizationBase.range | `range`}
2075    /// narrows it to the declaration's span.
2076    pub uri: Uri,
2077    /// Human-readable name.
2078    pub name: String,
2079    /// Icons for UI display.
2080    #[serde(default, skip_serializing_if = "Option::is_none")]
2081    pub icons: Option<Vec<Icon>>,
2082    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
2083    /// customization is a subset of a larger file (for example, one entry
2084    /// in an inline `mcpServers` block of a `plugins.json` manifest).
2085    /// Absent when the customization covers the whole resource.
2086    #[serde(default, skip_serializing_if = "Option::is_none")]
2087    pub range: Option<TextRange>,
2088    /// Short description used for help text and auto-invocation matching.
2089    /// Sourced from the skill's frontmatter `description`.
2090    #[serde(default, skip_serializing_if = "Option::is_none")]
2091    pub description: Option<String>,
2092    /// When `true`, only the user can invoke this skill — the agent will not
2093    /// auto-invoke it. Sourced from the command skill's frontmatter
2094    /// `disable-model-invocation` flag.
2095    #[serde(default, skip_serializing_if = "Option::is_none")]
2096    pub disable_model_invocation: Option<bool>,
2097}
2098
2099/// A prompt contributed by a plugin or directory.
2100#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2101#[serde(rename_all = "camelCase")]
2102pub struct PromptCustomization {
2103    /// Session-unique opaque identifier. Used by every action that targets a
2104    /// specific customization. Minted by whoever publishes the customization
2105    /// (typically the agent host).
2106    pub id: String,
2107    /// Source URI for this customization. A plugin URL, a file URI, or a
2108    /// directory URI.
2109    ///
2110    /// For declarations that live inside a larger file — e.g. an MCP
2111    /// server declared inline in a `plugins.json` manifest — `uri` points
2112    /// to the containing file and {@link CustomizationBase.range | `range`}
2113    /// narrows it to the declaration's span.
2114    pub uri: Uri,
2115    /// Human-readable name.
2116    pub name: String,
2117    /// Icons for UI display.
2118    #[serde(default, skip_serializing_if = "Option::is_none")]
2119    pub icons: Option<Vec<Icon>>,
2120    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
2121    /// customization is a subset of a larger file (for example, one entry
2122    /// in an inline `mcpServers` block of a `plugins.json` manifest).
2123    /// Absent when the customization covers the whole resource.
2124    #[serde(default, skip_serializing_if = "Option::is_none")]
2125    pub range: Option<TextRange>,
2126    /// Short description of what the prompt does.
2127    #[serde(default, skip_serializing_if = "Option::is_none")]
2128    pub description: Option<String>,
2129}
2130
2131/// A rule contributed by a plugin or directory.
2132///
2133/// Mirrors the [Open Plugins rule](https://open-plugins.com/agent-builders/components/rules)
2134/// format: a markdown file (e.g. `.mdc`) whose body is injected into
2135/// context while the rule is active. This type also covers tool-specific
2136/// "instruction" formats (e.g. VS Code Copilot's
2137/// `.github/instructions/*.md`), which differ only in naming — they
2138/// share the same semantics of `description`, optional always-on
2139/// activation, and optional glob scoping.
2140#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2141#[serde(rename_all = "camelCase")]
2142pub struct RuleCustomization {
2143    /// Session-unique opaque identifier. Used by every action that targets a
2144    /// specific customization. Minted by whoever publishes the customization
2145    /// (typically the agent host).
2146    pub id: String,
2147    /// Source URI for this customization. A plugin URL, a file URI, or a
2148    /// directory URI.
2149    ///
2150    /// For declarations that live inside a larger file — e.g. an MCP
2151    /// server declared inline in a `plugins.json` manifest — `uri` points
2152    /// to the containing file and {@link CustomizationBase.range | `range`}
2153    /// narrows it to the declaration's span.
2154    pub uri: Uri,
2155    /// Human-readable name.
2156    pub name: String,
2157    /// Icons for UI display.
2158    #[serde(default, skip_serializing_if = "Option::is_none")]
2159    pub icons: Option<Vec<Icon>>,
2160    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
2161    /// customization is a subset of a larger file (for example, one entry
2162    /// in an inline `mcpServers` block of a `plugins.json` manifest).
2163    /// Absent when the customization covers the whole resource.
2164    #[serde(default, skip_serializing_if = "Option::is_none")]
2165    pub range: Option<TextRange>,
2166    /// Description of what the rule enforces.
2167    #[serde(default, skip_serializing_if = "Option::is_none")]
2168    pub description: Option<String>,
2169    /// When `true`, the rule is always active (subject to `globs` if any).
2170    /// When `false` or absent, the agent or user decides whether to apply
2171    /// the rule.
2172    #[serde(default, skip_serializing_if = "Option::is_none")]
2173    pub always_apply: Option<bool>,
2174    /// Glob patterns the rule applies to. When present, the rule is only
2175    /// active for matching files.
2176    #[serde(default, skip_serializing_if = "Option::is_none")]
2177    pub globs: Option<Vec<String>>,
2178}
2179
2180/// A hook manifest contributed by a plugin or directory.
2181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2182#[serde(rename_all = "camelCase")]
2183pub struct HookCustomization {
2184    /// Session-unique opaque identifier. Used by every action that targets a
2185    /// specific customization. Minted by whoever publishes the customization
2186    /// (typically the agent host).
2187    pub id: String,
2188    /// Source URI for this customization. A plugin URL, a file URI, or a
2189    /// directory URI.
2190    ///
2191    /// For declarations that live inside a larger file — e.g. an MCP
2192    /// server declared inline in a `plugins.json` manifest — `uri` points
2193    /// to the containing file and {@link CustomizationBase.range | `range`}
2194    /// narrows it to the declaration's span.
2195    pub uri: Uri,
2196    /// Human-readable name.
2197    pub name: String,
2198    /// Icons for UI display.
2199    #[serde(default, skip_serializing_if = "Option::is_none")]
2200    pub icons: Option<Vec<Icon>>,
2201    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
2202    /// customization is a subset of a larger file (for example, one entry
2203    /// in an inline `mcpServers` block of a `plugins.json` manifest).
2204    /// Absent when the customization covers the whole resource.
2205    #[serde(default, skip_serializing_if = "Option::is_none")]
2206    pub range: Option<TextRange>,
2207}
2208
2209/// An MCP manifest contributed by a plugin or directory.
2210///
2211/// When the server is declared inline in the containing plugin manifest,
2212/// `uri` points at the manifest file and
2213/// {@link CustomizationBase.range | `range`} narrows it to the
2214/// declaration's span.
2215#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2216#[serde(rename_all = "camelCase")]
2217pub struct McpServerCustomization {
2218    /// Session-unique opaque identifier. Used by every action that targets a
2219    /// specific customization. Minted by whoever publishes the customization
2220    /// (typically the agent host).
2221    pub id: String,
2222    /// Source URI for this customization. A plugin URL, a file URI, or a
2223    /// directory URI.
2224    ///
2225    /// For declarations that live inside a larger file — e.g. an MCP
2226    /// server declared inline in a `plugins.json` manifest — `uri` points
2227    /// to the containing file and {@link CustomizationBase.range | `range`}
2228    /// narrows it to the declaration's span.
2229    pub uri: Uri,
2230    /// Human-readable name.
2231    pub name: String,
2232    /// Icons for UI display.
2233    #[serde(default, skip_serializing_if = "Option::is_none")]
2234    pub icons: Option<Vec<Icon>>,
2235    /// Optional span within {@link CustomizationBase.uri | `uri`} when this
2236    /// customization is a subset of a larger file (for example, one entry
2237    /// in an inline `mcpServers` block of a `plugins.json` manifest).
2238    /// Absent when the customization covers the whole resource.
2239    #[serde(default, skip_serializing_if = "Option::is_none")]
2240    pub range: Option<TextRange>,
2241}
2242
2243/// Describes a file modification with before/after state and diff metadata.
2244///
2245/// Supports creates (only `after`), deletes (only `before`), renames/moves
2246/// (different `uri` in `before` and `after`), and edits (same `uri`, different content).
2247#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
2248#[serde(rename_all = "camelCase")]
2249pub struct FileEdit {
2250    /// The file state before the edit. Absent for file creations or for in-place file edits.
2251    #[serde(default, skip_serializing_if = "Option::is_none")]
2252    pub before: Option<AnyValue>,
2253    /// The file state after the edit. Absent for file deletions.
2254    #[serde(default, skip_serializing_if = "Option::is_none")]
2255    pub after: Option<AnyValue>,
2256    /// Optional diff display metadata
2257    #[serde(default, skip_serializing_if = "Option::is_none")]
2258    pub diff: Option<AnyValue>,
2259}
2260
2261/// Lightweight terminal metadata exposed on the root state.
2262#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2263#[serde(rename_all = "camelCase")]
2264pub struct TerminalInfo {
2265    /// Terminal URI (subscribable for full terminal state)
2266    pub resource: Uri,
2267    /// Human-readable terminal title
2268    pub title: String,
2269    /// Who currently holds this terminal
2270    pub claim: TerminalClaim,
2271    /// Process exit code, if the terminal process has exited
2272    #[serde(default, skip_serializing_if = "Option::is_none")]
2273    pub exit_code: Option<i64>,
2274}
2275
2276/// A terminal claimed by a connected client.
2277#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2278#[serde(rename_all = "camelCase")]
2279pub struct TerminalClientClaim {
2280    /// The `clientId` of the claiming client
2281    pub client_id: String,
2282}
2283
2284/// A terminal claimed by a session, optionally scoped to a specific turn or tool call.
2285#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2286#[serde(rename_all = "camelCase")]
2287pub struct TerminalSessionClaim {
2288    /// Session URI that claimed the terminal
2289    pub session: Uri,
2290    /// Optional turn identifier within the session
2291    #[serde(default, skip_serializing_if = "Option::is_none")]
2292    pub turn_id: Option<String>,
2293    /// Optional tool call identifier within the turn
2294    #[serde(default, skip_serializing_if = "Option::is_none")]
2295    pub tool_call_id: Option<String>,
2296}
2297
2298/// Full state for a single terminal, loaded when a client subscribes to the terminal's URI.
2299#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2300#[serde(rename_all = "camelCase")]
2301pub struct TerminalState {
2302    /// Human-readable terminal title
2303    pub title: String,
2304    /// Current working directory of the terminal process
2305    #[serde(default, skip_serializing_if = "Option::is_none")]
2306    pub cwd: Option<Uri>,
2307    /// Terminal width in columns
2308    #[serde(default, skip_serializing_if = "Option::is_none")]
2309    pub cols: Option<i64>,
2310    /// Terminal height in rows
2311    #[serde(default, skip_serializing_if = "Option::is_none")]
2312    pub rows: Option<i64>,
2313    /// Typed content parts, replacing the flat `content: string`.
2314    ///
2315    /// Naive consumers that only need the raw VT stream can reconstruct it with:
2316    ///   `content.map(p => p.type === 'command' ? p.output : p.value).join('')`
2317    ///
2318    /// Consumers that need command boundaries can filter by part type.
2319    pub content: Vec<TerminalContentPart>,
2320    /// Process exit code, set when the terminal process exits
2321    #[serde(default, skip_serializing_if = "Option::is_none")]
2322    pub exit_code: Option<i64>,
2323    /// Who currently holds this terminal
2324    pub claim: TerminalClaim,
2325    /// Whether this terminal emits `terminal/commandExecuted` and
2326    /// `terminal/commandFinished` actions and populates `command`-typed parts.
2327    ///
2328    /// Clients MUST check this flag before relying on command detection.
2329    /// Do NOT use the presence of a `command` part as a feature flag — parts
2330    /// are absent in the normal idle state.
2331    #[serde(default, skip_serializing_if = "Option::is_none")]
2332    pub supports_command_detection: Option<bool>,
2333}
2334
2335/// Unstructured terminal output — content before, between, or after commands,
2336/// or from terminals that do not support command detection.
2337#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2338#[serde(rename_all = "camelCase")]
2339pub struct TerminalUnclassifiedPart {
2340    /// Accumulated VT output. Appended to by `terminal/data` when no command is executing.
2341    pub value: String,
2342}
2343
2344/// A single command: its command line and the output it produced.
2345///
2346/// While `isComplete` is false the command is still executing; `output` grows
2347/// as `terminal/data` actions arrive. At `terminal/commandFinished` the part
2348/// is mutated in-place with `isComplete: true` and the completion metadata.
2349#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2350#[serde(rename_all = "camelCase")]
2351pub struct TerminalCommandPart {
2352    /// Stable id matching the `commandId` on the corresponding
2353    /// `terminal/commandExecuted` and `terminal/commandFinished` actions.
2354    pub command_id: String,
2355    /// The command line submitted to the shell.
2356    pub command_line: String,
2357    /// Accumulated VT output. Appended to by `terminal/data` while `isComplete`
2358    /// is false. Shell integration escape sequences are stripped by the server.
2359    pub output: String,
2360    /// Unix timestamp (ms) when execution started, as reported by the server.
2361    pub timestamp: i64,
2362    /// Whether the command has finished.
2363    pub is_complete: bool,
2364    /// Shell exit code. Set at completion. `undefined` if unknown.
2365    #[serde(default, skip_serializing_if = "Option::is_none")]
2366    pub exit_code: Option<i64>,
2367    /// Wall-clock duration in milliseconds. Set at completion.
2368    #[serde(default, skip_serializing_if = "Option::is_none")]
2369    pub duration_ms: Option<i64>,
2370}
2371
2372#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
2373#[serde(rename_all = "camelCase")]
2374pub struct UsageInfo {
2375    /// Input tokens consumed
2376    #[serde(default, skip_serializing_if = "Option::is_none")]
2377    pub input_tokens: Option<i64>,
2378    /// Output tokens generated
2379    #[serde(default, skip_serializing_if = "Option::is_none")]
2380    pub output_tokens: Option<i64>,
2381    /// Model used
2382    #[serde(default, skip_serializing_if = "Option::is_none")]
2383    pub model: Option<String>,
2384    /// Tokens read from cache
2385    #[serde(default, skip_serializing_if = "Option::is_none")]
2386    pub cache_read_tokens: Option<i64>,
2387    /// Additional provider-specific metadata for this usage report.
2388    /// Clients MAY look for well-known optional keys here to provide enhanced UI.
2389    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2390    pub meta: Option<JsonObject>,
2391}
2392
2393#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2394#[serde(rename_all = "camelCase")]
2395pub struct ErrorInfo {
2396    /// Error type identifier
2397    pub error_type: String,
2398    /// Human-readable error message
2399    pub message: String,
2400    /// Stack trace
2401    #[serde(default, skip_serializing_if = "Option::is_none")]
2402    pub stack: Option<String>,
2403}
2404
2405/// A point-in-time snapshot of a subscribed resource's state, returned by
2406/// `initialize`, `reconnect`, and `subscribe`.
2407#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2408#[serde(rename_all = "camelCase")]
2409pub struct Snapshot {
2410    /// The subscribed channel URI (e.g. `ahp-root://` or `ahp-session:/<uuid>`)
2411    pub resource: Uri,
2412    /// The current state of the resource
2413    pub state: SnapshotState,
2414    /// The `serverSeq` at which this snapshot was taken. Subsequent actions will have `serverSeq > fromSeq`.
2415    pub from_seq: i64,
2416}
2417
2418/// Catalogue entry describing one changeset the server can produce for a
2419/// session.
2420///
2421/// Catalogue entries are intentionally lightweight — just enough to render a
2422/// chip or list row without subscribing. Full per-changeset detail
2423/// ({@link ChangesetState}) lives on the subscribable URI obtained by
2424/// expanding {@link uriTemplate}.
2425#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2426#[serde(rename_all = "camelCase")]
2427pub struct ChangesetSummary {
2428    /// Human-readable label, e.g. `"Uncommitted Changes"`.
2429    pub label: String,
2430    /// RFC 6570 URI template. Clients parse the variables directly out of the
2431    /// template using the standard `{name}` syntax — they are not redeclared
2432    /// here.
2433    ///
2434    /// Only the following template shapes are defined by this protocol; any
2435    /// other variable name MUST be ignored by clients (there is no
2436    /// protocol-defined way to obtain values for unknown variables):
2437    ///
2438    /// | Variables in template                       | Meaning                                                                              |
2439    /// | ------------------------------------------- | ------------------------------------------------------------------------------------ |
2440    /// | _(none)_                                    | A static, session-wide changeset. The template is itself a subscribable URI.         |
2441    /// | `{turnId}`                                  | Per-turn slice. Expand with a `Turn.id` from the session.                            |
2442    /// | `{originalTurnId}` and `{modifiedTurnId}`   | Diff between two turns. Both variables MUST be present.                              |
2443    ///
2444    /// Future protocol versions MAY add new well-known variables.
2445    pub uri_template: String,
2446    /// Optional longer description.
2447    #[serde(default, skip_serializing_if = "Option::is_none")]
2448    pub description: Option<String>,
2449    /// Aggregate line additions across the changeset, when known.
2450    #[serde(default, skip_serializing_if = "Option::is_none")]
2451    pub additions: Option<i64>,
2452    /// Aggregate line deletions across the changeset, when known.
2453    #[serde(default, skip_serializing_if = "Option::is_none")]
2454    pub deletions: Option<i64>,
2455    /// Number of files in the changeset, when known.
2456    #[serde(default, skip_serializing_if = "Option::is_none")]
2457    pub files: Option<i64>,
2458}
2459
2460/// Full state for a single changeset, returned when a client subscribes to
2461/// an expanded changeset URI.
2462///
2463/// The client already knows the URI it subscribed to, so this state does
2464/// not redundantly carry it (or the catalogue's `id`, `label`, etc.).
2465/// Aggregate counts (`additions`, `deletions`, `files`) are likewise
2466/// omitted: clients trivially compute them from `files[].edit.diff`.
2467#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2468#[serde(rename_all = "camelCase")]
2469pub struct ChangesetState {
2470    /// Computation lifecycle.
2471    pub status: ChangesetStatus,
2472    /// Present iff `status === ChangesetStatus.Error`.
2473    #[serde(default, skip_serializing_if = "Option::is_none")]
2474    pub error: Option<ErrorInfo>,
2475    /// Files in this changeset, keyed by {@link ChangesetFile.id}.
2476    pub files: Vec<ChangesetFile>,
2477    /// Operations the client may invoke against this changeset. Omit when no
2478    /// operations are available.
2479    #[serde(default, skip_serializing_if = "Option::is_none")]
2480    pub operations: Option<Vec<ChangesetOperation>>,
2481}
2482
2483/// One file entry within a {@link ChangesetState}.
2484#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2485#[serde(rename_all = "camelCase")]
2486pub struct ChangesetFile {
2487    /// Stable identifier within the changeset. Typically `after.uri`
2488    /// (or `before.uri` for deletions).
2489    pub id: String,
2490    /// Reuses the existing {@link FileEdit} shape. Clients derive line
2491    /// additions, deletions, and rename/create/delete semantics from this.
2492    pub edit: FileEdit,
2493    /// Server-defined opaque metadata, surfaced to operations and tooling
2494    /// but not interpreted by the protocol.
2495    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
2496    pub meta: Option<JsonObject>,
2497}
2498
2499/// A server-declared invokable verb the client can run against a
2500/// changeset, a file, or a range — `"stage"`, `"revert"`, `"create-pr"`,
2501/// and so on.
2502///
2503/// The term "operation" is used deliberately to avoid colliding with the
2504/// protocol-level [Actions](/guide/actions) that mutate state.
2505#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2506#[serde(rename_all = "camelCase")]
2507pub struct ChangesetOperation {
2508    /// Stable identifier, unique within this changeset.
2509    pub id: String,
2510    /// Human-readable button/menu label.
2511    pub label: String,
2512    /// Optional longer description shown on hover or in tooltips.
2513    #[serde(default, skip_serializing_if = "Option::is_none")]
2514    pub description: Option<String>,
2515    /// Where this operation can be invoked.
2516    pub scopes: Vec<ChangesetOperationScope>,
2517    /// Optional confirmation prompt to show before invoking. When present,
2518    /// the client MUST display this message to the user (typically in a
2519    /// confirmation dialog) and only invoke the operation after the user
2520    /// accepts. The presence of this field also signals that the operation
2521    /// is destructive — clients SHOULD style the affirmative button
2522    /// accordingly (e.g. with a warning colour).
2523    #[serde(default, skip_serializing_if = "Option::is_none")]
2524    pub confirmation: Option<StringOrMarkdown>,
2525    /// Optional generic icon hint, e.g. `"check"`, `"trash"`.
2526    #[serde(default, skip_serializing_if = "Option::is_none")]
2527    pub icon: Option<String>,
2528}
2529
2530/// OTLP telemetry channels the agent host emits.
2531///
2532/// Each field, when present, is either a literal channel URI or an
2533/// [RFC 6570](https://datatracker.ietf.org/doc/html/rfc6570) URI template
2534/// a client expands and then subscribes to. Absent fields indicate the host
2535/// does not emit that signal.
2536///
2537/// Channel URIs use the `ahp-otlp:` scheme. The scheme identifies the
2538/// protocol (OpenTelemetry over AHP) so clients can recognise the channel
2539/// type by URI alone; the host is free to choose any authority/path that
2540/// makes sense for its implementation. Clients MUST treat the URI as
2541/// opaque (apart from expanding any well-known template variables defined
2542/// below) and subscribe with the resulting concrete URI.
2543///
2544/// Payloads delivered on these channels are OTLP/JSON values — see
2545/// [opentelemetry-proto](https://github.com/open-telemetry/opentelemetry-proto)
2546/// for the wire shapes (`ExportLogsServiceRequest`,
2547/// `ExportTraceServiceRequest`, `ExportMetricsServiceRequest`).
2548#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
2549#[serde(rename_all = "camelCase")]
2550pub struct TelemetryCapabilities {
2551    /// Channel URI (or RFC 6570 URI template) for OTLP log records
2552    /// (`otlp/exportLogs` notifications).
2553    ///
2554    /// The following template variables are defined by this protocol; any
2555    /// other variable name MUST be ignored by clients (there is no
2556    /// protocol-defined way to obtain values for unknown variables):
2557    ///
2558    /// | Variables in template | Meaning                                                                                                 |
2559    /// | --------------------- | ------------------------------------------------------------------------------------------------------- |
2560    /// | _(none)_              | The host does not support subscriber-side severity filtering. The template is itself a subscribable URI. |
2561    /// | `{level}`             | Minimum OTLP severity to deliver. Expand to one of the [OTLP `SeverityNumber`](https://opentelemetry.io/docs/specs/otel/logs/data-model/#field-severitynumber) short names (case-insensitive): `trace`, `debug`, `info`, `warn`, `error`, `fatal`. The server delivers log records whose `severityNumber` falls in the corresponding band or above. |
2562    ///
2563    /// Hosts SHOULD honour the expanded `{level}`; clients MUST still filter
2564    /// defensively in case a host ignores the parameter. Hosts that do not
2565    /// advertise `{level}` deliver all severities.
2566    ///
2567    /// Future protocol versions MAY add new well-known variables (e.g. scope
2568    /// or attribute filters).
2569    #[serde(default, skip_serializing_if = "Option::is_none")]
2570    pub logs: Option<Uri>,
2571    /// Channel URI for OTLP spans (`otlp/exportTraces` notifications). No
2572    /// template variables are defined by this protocol version.
2573    #[serde(default, skip_serializing_if = "Option::is_none")]
2574    pub traces: Option<Uri>,
2575    /// Channel URI for OTLP metric data points (`otlp/exportMetrics`
2576    /// notifications). No template variables are defined by this protocol
2577    /// version.
2578    #[serde(default, skip_serializing_if = "Option::is_none")]
2579    pub metrics: Option<Uri>,
2580}
2581
2582/// Full state for a single resource watch, returned when a client subscribes
2583/// to an `ahp-resource-watch:` URI.
2584///
2585/// Watches are otherwise stateless: the watcher exists to deliver
2586/// {@link ResourceWatchChangedAction} events. The state carries only the
2587/// descriptor of what is being watched so a re-subscribing client can
2588/// recover the watch configuration after reconnecting.
2589#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2590#[serde(rename_all = "camelCase")]
2591pub struct ResourceWatchState {
2592    /// The URI being watched. For recursive watches this is the root of the
2593    /// subtree; for non-recursive watches this is the single file or
2594    /// directory.
2595    pub root: Uri,
2596    /// `true` if the watcher reports changes for descendants of `root`;
2597    /// `false` if it only reports changes to `root` itself (and, when
2598    /// `root` is a directory, its direct children).
2599    pub recursive: bool,
2600    /// Optional glob patterns or paths relative to `root` to exclude from
2601    /// change reporting.
2602    #[serde(default, skip_serializing_if = "Option::is_none")]
2603    pub excludes: Option<AnyValue>,
2604    /// Optional glob patterns or paths relative to `root` to restrict
2605    /// change reporting to. Omit to report every change under `root`
2606    /// subject to `excludes`.
2607    #[serde(default, skip_serializing_if = "Option::is_none")]
2608    pub includes: Option<AnyValue>,
2609}
2610
2611/// A single change observed by a resource watcher.
2612#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2613#[serde(rename_all = "camelCase")]
2614pub struct ResourceChange {
2615    /// The URI of the resource that changed.
2616    pub uri: Uri,
2617    /// The kind of change observed.
2618    pub r#type: ResourceChangeType,
2619}
2620
2621// ─── Discriminated Unions ─────────────────────────────────────────────
2622
2623/// A single part of a response stream (text, tool call, reasoning, content reference).
2624#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2625#[serde(tag = "kind")]
2626pub enum ResponsePart {
2627    #[serde(rename = "markdown")]
2628    Markdown(MarkdownResponsePart),
2629    #[serde(rename = "contentRef")]
2630    ContentRef(ResourceResponsePart),
2631    #[serde(rename = "toolCall")]
2632    ToolCall(Box<ToolCallResponsePart>),
2633    #[serde(rename = "reasoning")]
2634    Reasoning(ReasoningResponsePart),
2635    #[serde(rename = "systemNotification")]
2636    SystemNotification(SystemNotificationResponsePart),
2637    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2638    /// Reducers treat this as a no-op.
2639    #[serde(untagged)]
2640    Unknown(serde_json::Value),
2641}
2642
2643/// Full tool call lifecycle state.
2644#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2645#[serde(tag = "status")]
2646pub enum ToolCallState {
2647    #[serde(rename = "streaming")]
2648    Streaming(ToolCallStreamingState),
2649    #[serde(rename = "pending-confirmation")]
2650    PendingConfirmation(ToolCallPendingConfirmationState),
2651    #[serde(rename = "running")]
2652    Running(ToolCallRunningState),
2653    #[serde(rename = "pending-result-confirmation")]
2654    PendingResultConfirmation(ToolCallPendingResultConfirmationState),
2655    #[serde(rename = "completed")]
2656    Completed(ToolCallCompletedState),
2657    #[serde(rename = "cancelled")]
2658    Cancelled(ToolCallCancelledState),
2659    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2660    /// Reducers treat this as a no-op.
2661    #[serde(untagged)]
2662    Unknown(serde_json::Value),
2663}
2664
2665/// Who currently holds a terminal.
2666#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2667#[serde(tag = "kind")]
2668pub enum TerminalClaim {
2669    #[serde(rename = "client")]
2670    Client(TerminalClientClaim),
2671    #[serde(rename = "session")]
2672    Session(TerminalSessionClaim),
2673    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2674    /// Reducers treat this as a no-op.
2675    #[serde(untagged)]
2676    Unknown(serde_json::Value),
2677}
2678
2679/// A content part within terminal output.
2680#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2681#[serde(tag = "type")]
2682pub enum TerminalContentPart {
2683    #[serde(rename = "unclassified")]
2684    Unclassified(TerminalUnclassifiedPart),
2685    #[serde(rename = "command")]
2686    Command(TerminalCommandPart),
2687    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2688    /// Reducers treat this as a no-op.
2689    #[serde(untagged)]
2690    Unknown(serde_json::Value),
2691}
2692
2693/// One question within a session input request.
2694#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2695#[serde(tag = "kind")]
2696pub enum SessionInputQuestion {
2697    #[serde(rename = "text")]
2698    Text(SessionInputTextQuestion),
2699    #[serde(rename = "number")]
2700    Number(SessionInputNumberQuestion),
2701    #[serde(rename = "integer")]
2702    Integer(SessionInputNumberQuestion),
2703    #[serde(rename = "boolean")]
2704    Boolean(SessionInputBooleanQuestion),
2705    #[serde(rename = "single-select")]
2706    SingleSelect(SessionInputSingleSelectQuestion),
2707    #[serde(rename = "multi-select")]
2708    MultiSelect(SessionInputMultiSelectQuestion),
2709    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2710    /// Reducers treat this as a no-op.
2711    #[serde(untagged)]
2712    Unknown(serde_json::Value),
2713}
2714
2715/// Value captured for one answer.
2716#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2717#[serde(tag = "kind")]
2718pub enum SessionInputAnswerValue {
2719    #[serde(rename = "text")]
2720    Text(SessionInputTextAnswerValue),
2721    #[serde(rename = "number")]
2722    Number(SessionInputNumberAnswerValue),
2723    #[serde(rename = "boolean")]
2724    Boolean(SessionInputBooleanAnswerValue),
2725    #[serde(rename = "selected")]
2726    Selected(SessionInputSelectedAnswerValue),
2727    #[serde(rename = "selected-many")]
2728    SelectedMany(SessionInputSelectedManyAnswerValue),
2729    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2730    /// Reducers treat this as a no-op.
2731    #[serde(untagged)]
2732    Unknown(serde_json::Value),
2733}
2734
2735/// Draft, submitted, or skipped answer for one question.
2736#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2737#[serde(tag = "state")]
2738pub enum SessionInputAnswer {
2739    #[serde(rename = "draft")]
2740    Draft(SessionInputAnswered),
2741    #[serde(rename = "submitted")]
2742    Submitted(SessionInputAnswered),
2743    #[serde(rename = "skipped")]
2744    Skipped(SessionInputSkipped),
2745    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2746    /// Reducers treat this as a no-op.
2747    #[serde(untagged)]
2748    Unknown(serde_json::Value),
2749}
2750
2751/// Content block in a tool result.
2752#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2753#[serde(tag = "type")]
2754pub enum ToolResultContent {
2755    #[serde(rename = "text")]
2756    Text(ToolResultTextContent),
2757    #[serde(rename = "embeddedResource")]
2758    EmbeddedResource(ToolResultEmbeddedResourceContent),
2759    #[serde(rename = "resource")]
2760    Resource(ToolResultResourceContent),
2761    #[serde(rename = "fileEdit")]
2762    FileEdit(ToolResultFileEditContent),
2763    #[serde(rename = "terminal")]
2764    Terminal(ToolResultTerminalContent),
2765    #[serde(rename = "subagent")]
2766    Subagent(ToolResultSubagentContent),
2767    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2768    /// Reducers treat this as a no-op.
2769    #[serde(untagged)]
2770    Unknown(serde_json::Value),
2771}
2772
2773/// An attachment associated with a `UserMessage`.
2774#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2775#[serde(tag = "type")]
2776pub enum MessageAttachment {
2777    #[serde(rename = "simple")]
2778    Simple(SimpleMessageAttachment),
2779    #[serde(rename = "embeddedResource")]
2780    EmbeddedResource(MessageEmbeddedResourceAttachment),
2781    #[serde(rename = "resource")]
2782    Resource(MessageResourceAttachment),
2783    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2784    /// Reducers treat this as a no-op.
2785    #[serde(untagged)]
2786    Unknown(serde_json::Value),
2787}
2788
2789/// A top-level customization (plugin or directory).
2790#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2791#[serde(tag = "type")]
2792pub enum Customization {
2793    #[serde(rename = "plugin")]
2794    Plugin(PluginCustomization),
2795    #[serde(rename = "directory")]
2796    Directory(DirectoryCustomization),
2797    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2798    /// Reducers treat this as a no-op.
2799    #[serde(untagged)]
2800    Unknown(serde_json::Value),
2801}
2802
2803/// A child customization living inside a plugin or directory.
2804#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2805#[serde(tag = "type")]
2806pub enum ChildCustomization {
2807    #[serde(rename = "agent")]
2808    Agent(AgentCustomization),
2809    #[serde(rename = "skill")]
2810    Skill(SkillCustomization),
2811    #[serde(rename = "prompt")]
2812    Prompt(PromptCustomization),
2813    #[serde(rename = "rule")]
2814    Rule(RuleCustomization),
2815    #[serde(rename = "hook")]
2816    Hook(HookCustomization),
2817    #[serde(rename = "mcpServer")]
2818    McpServer(McpServerCustomization),
2819    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2820    /// Reducers treat this as a no-op.
2821    #[serde(untagged)]
2822    Unknown(serde_json::Value),
2823}
2824
2825/// Host-reported load state for a container customization.
2826#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2827#[serde(tag = "kind")]
2828pub enum CustomizationLoadState {
2829    #[serde(rename = "loading")]
2830    Loading(CustomizationLoadingState),
2831    #[serde(rename = "loaded")]
2832    Loaded(CustomizationLoadedState),
2833    #[serde(rename = "degraded")]
2834    Degraded(CustomizationDegradedState),
2835    #[serde(rename = "error")]
2836    Error(CustomizationErrorState),
2837    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
2838    /// Reducers treat this as a no-op.
2839    #[serde(untagged)]
2840    Unknown(serde_json::Value),
2841}
2842
2843/// The state payload of a snapshot — root, session, terminal, or
2844/// changeset state.
2845///
2846/// Deserialized by trying session first (has required `summary`), then
2847/// terminal (has required `content`), then changeset (has required
2848/// `status` and `files`), then root.
2849#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
2850#[serde(untagged)]
2851pub enum SnapshotState {
2852    Session(Box<SessionState>),
2853    Terminal(Box<TerminalState>),
2854    Changeset(Box<ChangesetState>),
2855    Root(Box<RootState>),
2856}