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