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