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