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