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