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