Skip to main content

agent_client_protocol_schema/v2/
nes.rs

1//! Next Edit Suggestions (NES) types and constants.
2//!
3//! NES allows agents to provide predictive code edits via capability negotiation,
4//! document events, and a suggestion request/response flow. NES sessions are
5//! independent of chat sessions and have their own lifecycle.
6
7use std::{collections::BTreeMap, sync::Arc};
8
9use derive_more::{Display, From};
10#[cfg(feature = "schemars")]
11use schemars::Schema;
12use serde::{Deserialize, Serialize};
13use serde_with::{DefaultOnError, VecSkipError, serde_as, skip_serializing_none};
14
15use super::{Meta, SessionId};
16use crate::{IntoOption, SkipListener};
17
18// Method name constants
19
20/// Method name for starting an NES session.
21pub(crate) const NES_START_METHOD_NAME: &str = "nes/start";
22/// Method name for requesting a suggestion.
23pub(crate) const NES_SUGGEST_METHOD_NAME: &str = "nes/suggest";
24/// Method name for accepting a suggestion.
25pub(crate) const NES_ACCEPT_METHOD_NAME: &str = "nes/accept";
26/// Method name for rejecting a suggestion.
27pub(crate) const NES_REJECT_METHOD_NAME: &str = "nes/reject";
28
29/// **UNSTABLE**
30///
31/// This capability is not part of the spec yet, and may be removed or changed at any point.
32///
33/// Unique identifier for an NES suggestion.
34#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, Display, From)]
36#[serde(transparent)]
37#[from(forward)]
38#[non_exhaustive]
39pub struct NesSuggestionId(pub Arc<str>);
40
41impl NesSuggestionId {
42    /// Wraps a protocol string as a typed [`NesSuggestionId`].
43    #[must_use]
44    pub fn new(id: impl Into<Self>) -> Self {
45        id.into()
46    }
47}
48/// Method name for closing an NES session.
49pub(crate) const NES_CLOSE_METHOD_NAME: &str = "nes/close";
50/// Notification name for document open events.
51pub(crate) const DOCUMENT_DID_OPEN_METHOD_NAME: &str = "document/didOpen";
52/// Notification name for document change events.
53pub(crate) const DOCUMENT_DID_CHANGE_METHOD_NAME: &str = "document/didChange";
54/// Notification name for document close events.
55pub(crate) const DOCUMENT_DID_CLOSE_METHOD_NAME: &str = "document/didClose";
56/// Notification name for document save events.
57pub(crate) const DOCUMENT_DID_SAVE_METHOD_NAME: &str = "document/didSave";
58/// Notification name for document focus events.
59pub(crate) const DOCUMENT_DID_FOCUS_METHOD_NAME: &str = "document/didFocus";
60
61// Position primitives
62
63/// The encoding used for character offsets in positions.
64///
65/// Follows the same conventions as LSP 3.17. The default is UTF-16.
66#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
67#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
68#[non_exhaustive]
69pub enum PositionEncodingKind {
70    /// Character offsets count UTF-16 code units. This is the default.
71    #[serde(rename = "utf-16")]
72    Utf16,
73    /// Character offsets count Unicode code points.
74    #[serde(rename = "utf-32")]
75    Utf32,
76    /// Character offsets count UTF-8 code units (bytes).
77    #[serde(rename = "utf-8")]
78    Utf8,
79}
80
81/// A zero-based position in a text document.
82///
83/// The meaning of `character` depends on the negotiated position encoding.
84#[serde_as]
85#[skip_serializing_none]
86#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
87#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
88#[serde(rename_all = "camelCase")]
89#[non_exhaustive]
90pub struct Position {
91    /// Zero-based line number.
92    pub line: u32,
93    /// Zero-based character offset (encoding-dependent).
94    pub character: u32,
95    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
96    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
97    /// these keys.
98    ///
99    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
100    #[serde_as(deserialize_as = "DefaultOnError")]
101    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
102    #[serde(default)]
103    #[serde(rename = "_meta")]
104    pub meta: Option<Meta>,
105}
106
107impl Position {
108    /// Builds a [`Position`] from protocol coordinate values.
109    #[must_use]
110    pub fn new(line: u32, character: u32) -> Self {
111        Self {
112            line,
113            character,
114            meta: None,
115        }
116    }
117
118    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
119    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
120    /// these keys.
121    ///
122    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
123    #[must_use]
124    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
125        self.meta = meta.into_option();
126        self
127    }
128}
129
130/// A range in a text document, expressed as start and end positions.
131#[serde_as]
132#[skip_serializing_none]
133#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
134#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
135#[serde(rename_all = "camelCase")]
136#[non_exhaustive]
137pub struct Range {
138    /// The start position (inclusive).
139    pub start: Position,
140    /// The end position (exclusive).
141    pub end: Position,
142    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
143    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
144    /// these keys.
145    ///
146    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
147    #[serde_as(deserialize_as = "DefaultOnError")]
148    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
149    #[serde(default)]
150    #[serde(rename = "_meta")]
151    pub meta: Option<Meta>,
152}
153
154impl Range {
155    /// Builds a [`Range`] from protocol coordinate values.
156    #[must_use]
157    pub fn new(start: Position, end: Position) -> Self {
158        Self {
159            start,
160            end,
161            meta: None,
162        }
163    }
164
165    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
166    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
167    /// these keys.
168    ///
169    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
170    #[must_use]
171    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
172        self.meta = meta.into_option();
173        self
174    }
175}
176
177// Agent NES capabilities
178
179/// NES capabilities advertised by the agent during initialization.
180///
181/// Supplying `{}` means the agent supports the NES method surface. Omitted or
182/// `null` both mean the agent does not advertise support for `nes/*` methods.
183#[serde_as]
184#[skip_serializing_none]
185#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
186#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
187#[serde(rename_all = "camelCase")]
188#[non_exhaustive]
189pub struct NesCapabilities {
190    /// Events the agent wants to receive.
191    #[serde_as(deserialize_as = "DefaultOnError")]
192    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
193    #[serde(default)]
194    pub events: Option<NesEventCapabilities>,
195    /// Context the agent wants attached to each suggestion request.
196    #[serde_as(deserialize_as = "DefaultOnError")]
197    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
198    #[serde(default)]
199    pub context: Option<NesContextCapabilities>,
200    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
201    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
202    /// these keys.
203    ///
204    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
205    #[serde_as(deserialize_as = "DefaultOnError")]
206    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
207    #[serde(default)]
208    #[serde(rename = "_meta")]
209    pub meta: Option<Meta>,
210}
211
212impl NesCapabilities {
213    /// Builds an empty [`NesCapabilities`]; use builder methods to advertise supported sub-capabilities.
214    #[must_use]
215    pub fn new() -> Self {
216        Self::default()
217    }
218
219    /// Sets or clears the optional `events` field.
220    #[must_use]
221    pub fn events(mut self, events: impl IntoOption<NesEventCapabilities>) -> Self {
222        self.events = events.into_option();
223        self
224    }
225
226    /// Sets or clears the optional `context` field.
227    #[must_use]
228    pub fn context(mut self, context: impl IntoOption<NesContextCapabilities>) -> Self {
229        self.context = context.into_option();
230        self
231    }
232
233    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
234    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
235    /// these keys.
236    ///
237    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
238    #[must_use]
239    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
240        self.meta = meta.into_option();
241        self
242    }
243}
244
245/// Event capabilities the agent can consume.
246#[serde_as]
247#[skip_serializing_none]
248#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
249#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
250#[serde(rename_all = "camelCase")]
251#[non_exhaustive]
252pub struct NesEventCapabilities {
253    /// Document event capabilities.
254    #[serde_as(deserialize_as = "DefaultOnError")]
255    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
256    #[serde(default)]
257    pub document: Option<NesDocumentEventCapabilities>,
258    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
259    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
260    /// these keys.
261    ///
262    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
263    #[serde_as(deserialize_as = "DefaultOnError")]
264    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
265    #[serde(default)]
266    #[serde(rename = "_meta")]
267    pub meta: Option<Meta>,
268}
269
270impl NesEventCapabilities {
271    /// Builds an empty [`NesEventCapabilities`]; use builder methods to advertise supported sub-capabilities.
272    #[must_use]
273    pub fn new() -> Self {
274        Self::default()
275    }
276
277    /// Sets or clears the optional `document` field.
278    #[must_use]
279    pub fn document(mut self, document: impl IntoOption<NesDocumentEventCapabilities>) -> Self {
280        self.document = document.into_option();
281        self
282    }
283
284    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
285    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
286    /// these keys.
287    ///
288    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
289    #[must_use]
290    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
291        self.meta = meta.into_option();
292        self
293    }
294}
295
296/// Document event capabilities the agent wants to receive.
297#[serde_as]
298#[skip_serializing_none]
299#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
300#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
301#[serde(rename_all = "camelCase")]
302#[non_exhaustive]
303pub struct NesDocumentEventCapabilities {
304    /// Whether the agent wants `document/didOpen` events.
305    #[serde_as(deserialize_as = "DefaultOnError")]
306    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
307    #[serde(default)]
308    pub did_open: Option<NesDocumentDidOpenCapabilities>,
309    /// Whether the agent wants `document/didChange` events, and the sync kind.
310    #[serde_as(deserialize_as = "DefaultOnError")]
311    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
312    #[serde(default)]
313    pub did_change: Option<NesDocumentDidChangeCapabilities>,
314    /// Whether the agent wants `document/didClose` events.
315    #[serde_as(deserialize_as = "DefaultOnError")]
316    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
317    #[serde(default)]
318    pub did_close: Option<NesDocumentDidCloseCapabilities>,
319    /// Whether the agent wants `document/didSave` events.
320    #[serde_as(deserialize_as = "DefaultOnError")]
321    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
322    #[serde(default)]
323    pub did_save: Option<NesDocumentDidSaveCapabilities>,
324    /// Whether the agent wants `document/didFocus` events.
325    #[serde_as(deserialize_as = "DefaultOnError")]
326    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
327    #[serde(default)]
328    pub did_focus: Option<NesDocumentDidFocusCapabilities>,
329    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
330    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
331    /// these keys.
332    ///
333    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
334    #[serde_as(deserialize_as = "DefaultOnError")]
335    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
336    #[serde(default)]
337    #[serde(rename = "_meta")]
338    pub meta: Option<Meta>,
339}
340
341impl NesDocumentEventCapabilities {
342    /// Builds an empty [`NesDocumentEventCapabilities`]; use builder methods to advertise supported sub-capabilities.
343    #[must_use]
344    pub fn new() -> Self {
345        Self::default()
346    }
347
348    /// Sets or clears the optional `didOpen` field.
349    #[must_use]
350    pub fn did_open(mut self, did_open: impl IntoOption<NesDocumentDidOpenCapabilities>) -> Self {
351        self.did_open = did_open.into_option();
352        self
353    }
354
355    /// Sets or clears the optional `didChange` field.
356    #[must_use]
357    pub fn did_change(
358        mut self,
359        did_change: impl IntoOption<NesDocumentDidChangeCapabilities>,
360    ) -> Self {
361        self.did_change = did_change.into_option();
362        self
363    }
364
365    /// Sets or clears the optional `didClose` field.
366    #[must_use]
367    pub fn did_close(
368        mut self,
369        did_close: impl IntoOption<NesDocumentDidCloseCapabilities>,
370    ) -> Self {
371        self.did_close = did_close.into_option();
372        self
373    }
374
375    /// Sets or clears the optional `didSave` field.
376    #[must_use]
377    pub fn did_save(mut self, did_save: impl IntoOption<NesDocumentDidSaveCapabilities>) -> Self {
378        self.did_save = did_save.into_option();
379        self
380    }
381
382    /// Sets or clears the optional `didFocus` field.
383    #[must_use]
384    pub fn did_focus(
385        mut self,
386        did_focus: impl IntoOption<NesDocumentDidFocusCapabilities>,
387    ) -> Self {
388        self.did_focus = did_focus.into_option();
389        self
390    }
391
392    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
393    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
394    /// these keys.
395    ///
396    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
397    #[must_use]
398    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
399        self.meta = meta.into_option();
400        self
401    }
402}
403
404/// Marker for `document/didOpen` capability support.
405#[serde_as]
406#[skip_serializing_none]
407#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
408#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
409#[serde(rename_all = "camelCase")]
410#[non_exhaustive]
411pub struct NesDocumentDidOpenCapabilities {
412    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
413    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
414    /// these keys.
415    ///
416    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
417    #[serde_as(deserialize_as = "DefaultOnError")]
418    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
419    #[serde(default)]
420    #[serde(rename = "_meta")]
421    pub meta: Option<Meta>,
422}
423
424impl NesDocumentDidOpenCapabilities {
425    /// Builds an empty [`NesDocumentDidOpenCapabilities`]; use builder methods to advertise supported sub-capabilities.
426    #[must_use]
427    pub fn new() -> Self {
428        Self::default()
429    }
430}
431
432/// Capabilities for `document/didChange` events.
433#[serde_as]
434#[skip_serializing_none]
435#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
436#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
437#[serde(rename_all = "camelCase")]
438#[non_exhaustive]
439pub struct NesDocumentDidChangeCapabilities {
440    /// The sync kind the agent wants: `"full"` or `"incremental"`.
441    pub sync_kind: TextDocumentSyncKind,
442    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
443    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
444    /// these keys.
445    ///
446    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
447    #[serde_as(deserialize_as = "DefaultOnError")]
448    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
449    #[serde(default)]
450    #[serde(rename = "_meta")]
451    pub meta: Option<Meta>,
452}
453
454impl NesDocumentDidChangeCapabilities {
455    /// Builds an empty [`NesDocumentDidChangeCapabilities`]; use builder methods to advertise supported sub-capabilities.
456    #[must_use]
457    pub fn new(sync_kind: TextDocumentSyncKind) -> Self {
458        Self {
459            sync_kind,
460            meta: None,
461        }
462    }
463
464    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
465    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
466    /// these keys.
467    ///
468    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
469    #[must_use]
470    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
471        self.meta = meta.into_option();
472        self
473    }
474}
475
476/// How the agent wants document changes delivered.
477#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
478#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
479#[non_exhaustive]
480pub enum TextDocumentSyncKind {
481    /// Client sends the entire file content on each change.
482    #[serde(rename = "full")]
483    Full,
484    /// Client sends only the changed ranges.
485    #[serde(rename = "incremental")]
486    Incremental,
487}
488
489/// Marker for `document/didClose` capability support.
490#[serde_as]
491#[skip_serializing_none]
492#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
493#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
494#[serde(rename_all = "camelCase")]
495#[non_exhaustive]
496pub struct NesDocumentDidCloseCapabilities {
497    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
498    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
499    /// these keys.
500    ///
501    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
502    #[serde_as(deserialize_as = "DefaultOnError")]
503    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
504    #[serde(default)]
505    #[serde(rename = "_meta")]
506    pub meta: Option<Meta>,
507}
508
509impl NesDocumentDidCloseCapabilities {
510    /// Builds an empty [`NesDocumentDidCloseCapabilities`]; use builder methods to advertise supported sub-capabilities.
511    #[must_use]
512    pub fn new() -> Self {
513        Self::default()
514    }
515}
516
517/// Marker for `document/didSave` capability support.
518#[serde_as]
519#[skip_serializing_none]
520#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
521#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
522#[serde(rename_all = "camelCase")]
523#[non_exhaustive]
524pub struct NesDocumentDidSaveCapabilities {
525    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
526    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
527    /// these keys.
528    ///
529    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
530    #[serde_as(deserialize_as = "DefaultOnError")]
531    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
532    #[serde(default)]
533    #[serde(rename = "_meta")]
534    pub meta: Option<Meta>,
535}
536
537impl NesDocumentDidSaveCapabilities {
538    /// Builds an empty [`NesDocumentDidSaveCapabilities`]; use builder methods to advertise supported sub-capabilities.
539    #[must_use]
540    pub fn new() -> Self {
541        Self::default()
542    }
543}
544
545/// Marker for `document/didFocus` capability support.
546#[serde_as]
547#[skip_serializing_none]
548#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
549#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
550#[serde(rename_all = "camelCase")]
551#[non_exhaustive]
552pub struct NesDocumentDidFocusCapabilities {
553    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
554    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
555    /// these keys.
556    ///
557    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
558    #[serde_as(deserialize_as = "DefaultOnError")]
559    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
560    #[serde(default)]
561    #[serde(rename = "_meta")]
562    pub meta: Option<Meta>,
563}
564
565impl NesDocumentDidFocusCapabilities {
566    /// Builds an empty [`NesDocumentDidFocusCapabilities`]; use builder methods to advertise supported sub-capabilities.
567    #[must_use]
568    pub fn new() -> Self {
569        Self::default()
570    }
571}
572
573/// Context capabilities the agent wants attached to each suggestion request.
574#[serde_as]
575#[skip_serializing_none]
576#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
577#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
578#[serde(rename_all = "camelCase")]
579#[non_exhaustive]
580pub struct NesContextCapabilities {
581    /// Whether the agent wants recent files context.
582    #[serde_as(deserialize_as = "DefaultOnError")]
583    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
584    #[serde(default)]
585    pub recent_files: Option<NesRecentFilesCapabilities>,
586    /// Whether the agent wants related snippets context.
587    #[serde_as(deserialize_as = "DefaultOnError")]
588    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
589    #[serde(default)]
590    pub related_snippets: Option<NesRelatedSnippetsCapabilities>,
591    /// Whether the agent wants edit history context.
592    #[serde_as(deserialize_as = "DefaultOnError")]
593    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
594    #[serde(default)]
595    pub edit_history: Option<NesEditHistoryCapabilities>,
596    /// Whether the agent wants user actions context.
597    #[serde_as(deserialize_as = "DefaultOnError")]
598    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
599    #[serde(default)]
600    pub user_actions: Option<NesUserActionsCapabilities>,
601    /// Whether the agent wants open files context.
602    #[serde_as(deserialize_as = "DefaultOnError")]
603    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
604    #[serde(default)]
605    pub open_files: Option<NesOpenFilesCapabilities>,
606    /// Whether the agent wants diagnostics context.
607    #[serde_as(deserialize_as = "DefaultOnError")]
608    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
609    #[serde(default)]
610    pub diagnostics: Option<NesDiagnosticsCapabilities>,
611    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
612    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
613    /// these keys.
614    ///
615    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
616    #[serde_as(deserialize_as = "DefaultOnError")]
617    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
618    #[serde(default)]
619    #[serde(rename = "_meta")]
620    pub meta: Option<Meta>,
621}
622
623impl NesContextCapabilities {
624    /// Builds an empty [`NesContextCapabilities`]; use builder methods to advertise supported sub-capabilities.
625    #[must_use]
626    pub fn new() -> Self {
627        Self::default()
628    }
629
630    /// Sets or clears the optional `recentFiles` field.
631    #[must_use]
632    pub fn recent_files(
633        mut self,
634        recent_files: impl IntoOption<NesRecentFilesCapabilities>,
635    ) -> Self {
636        self.recent_files = recent_files.into_option();
637        self
638    }
639
640    /// Sets or clears the optional `relatedSnippets` field.
641    #[must_use]
642    pub fn related_snippets(
643        mut self,
644        related_snippets: impl IntoOption<NesRelatedSnippetsCapabilities>,
645    ) -> Self {
646        self.related_snippets = related_snippets.into_option();
647        self
648    }
649
650    /// Sets or clears the optional `editHistory` field.
651    #[must_use]
652    pub fn edit_history(
653        mut self,
654        edit_history: impl IntoOption<NesEditHistoryCapabilities>,
655    ) -> Self {
656        self.edit_history = edit_history.into_option();
657        self
658    }
659
660    /// Sets or clears the optional `userActions` field.
661    #[must_use]
662    pub fn user_actions(
663        mut self,
664        user_actions: impl IntoOption<NesUserActionsCapabilities>,
665    ) -> Self {
666        self.user_actions = user_actions.into_option();
667        self
668    }
669
670    /// Sets or clears the optional `openFiles` field.
671    #[must_use]
672    pub fn open_files(mut self, open_files: impl IntoOption<NesOpenFilesCapabilities>) -> Self {
673        self.open_files = open_files.into_option();
674        self
675    }
676
677    /// Sets or clears the optional `diagnostics` field.
678    #[must_use]
679    pub fn diagnostics(mut self, diagnostics: impl IntoOption<NesDiagnosticsCapabilities>) -> Self {
680        self.diagnostics = diagnostics.into_option();
681        self
682    }
683
684    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
685    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
686    /// these keys.
687    ///
688    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
689    #[must_use]
690    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
691        self.meta = meta.into_option();
692        self
693    }
694}
695
696/// Capabilities for recent files context.
697#[serde_as]
698#[skip_serializing_none]
699#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
700#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
701#[serde(rename_all = "camelCase")]
702#[non_exhaustive]
703pub struct NesRecentFilesCapabilities {
704    /// Maximum number of recent files the agent can use.
705    #[serde_as(deserialize_as = "DefaultOnError")]
706    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
707    #[serde(default)]
708    pub max_count: Option<u32>,
709    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
710    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
711    /// these keys.
712    ///
713    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
714    #[serde_as(deserialize_as = "DefaultOnError")]
715    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
716    #[serde(default)]
717    #[serde(rename = "_meta")]
718    pub meta: Option<Meta>,
719}
720
721impl NesRecentFilesCapabilities {
722    /// Builds an empty [`NesRecentFilesCapabilities`]; use builder methods to advertise supported sub-capabilities.
723    #[must_use]
724    pub fn new() -> Self {
725        Self::default()
726    }
727}
728
729/// Capabilities for related snippets context.
730#[serde_as]
731#[skip_serializing_none]
732#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
733#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
734#[serde(rename_all = "camelCase")]
735#[non_exhaustive]
736pub struct NesRelatedSnippetsCapabilities {
737    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
738    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
739    /// these keys.
740    ///
741    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
742    #[serde_as(deserialize_as = "DefaultOnError")]
743    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
744    #[serde(default)]
745    #[serde(rename = "_meta")]
746    pub meta: Option<Meta>,
747}
748
749impl NesRelatedSnippetsCapabilities {
750    /// Builds an empty [`NesRelatedSnippetsCapabilities`]; use builder methods to advertise supported sub-capabilities.
751    #[must_use]
752    pub fn new() -> Self {
753        Self::default()
754    }
755}
756
757/// Capabilities for edit history context.
758#[serde_as]
759#[skip_serializing_none]
760#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
761#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
762#[serde(rename_all = "camelCase")]
763#[non_exhaustive]
764pub struct NesEditHistoryCapabilities {
765    /// Maximum number of edit history entries the agent can use.
766    #[serde_as(deserialize_as = "DefaultOnError")]
767    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
768    #[serde(default)]
769    pub max_count: Option<u32>,
770    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
771    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
772    /// these keys.
773    ///
774    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
775    #[serde_as(deserialize_as = "DefaultOnError")]
776    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
777    #[serde(default)]
778    #[serde(rename = "_meta")]
779    pub meta: Option<Meta>,
780}
781
782impl NesEditHistoryCapabilities {
783    /// Builds an empty [`NesEditHistoryCapabilities`]; use builder methods to advertise supported sub-capabilities.
784    #[must_use]
785    pub fn new() -> Self {
786        Self::default()
787    }
788}
789
790/// Capabilities for user actions context.
791#[serde_as]
792#[skip_serializing_none]
793#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
794#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
795#[serde(rename_all = "camelCase")]
796#[non_exhaustive]
797pub struct NesUserActionsCapabilities {
798    /// Maximum number of user actions the agent can use.
799    #[serde_as(deserialize_as = "DefaultOnError")]
800    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
801    #[serde(default)]
802    pub max_count: Option<u32>,
803    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
804    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
805    /// these keys.
806    ///
807    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
808    #[serde_as(deserialize_as = "DefaultOnError")]
809    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
810    #[serde(default)]
811    #[serde(rename = "_meta")]
812    pub meta: Option<Meta>,
813}
814
815impl NesUserActionsCapabilities {
816    /// Builds an empty [`NesUserActionsCapabilities`]; use builder methods to advertise supported sub-capabilities.
817    #[must_use]
818    pub fn new() -> Self {
819        Self::default()
820    }
821}
822
823/// Capabilities for open files context.
824#[serde_as]
825#[skip_serializing_none]
826#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
827#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
828#[serde(rename_all = "camelCase")]
829#[non_exhaustive]
830pub struct NesOpenFilesCapabilities {
831    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
832    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
833    /// these keys.
834    ///
835    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
836    #[serde_as(deserialize_as = "DefaultOnError")]
837    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
838    #[serde(default)]
839    #[serde(rename = "_meta")]
840    pub meta: Option<Meta>,
841}
842
843impl NesOpenFilesCapabilities {
844    /// Builds an empty [`NesOpenFilesCapabilities`]; use builder methods to advertise supported sub-capabilities.
845    #[must_use]
846    pub fn new() -> Self {
847        Self::default()
848    }
849}
850
851/// Capabilities for diagnostics context.
852#[serde_as]
853#[skip_serializing_none]
854#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
855#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
856#[serde(rename_all = "camelCase")]
857#[non_exhaustive]
858pub struct NesDiagnosticsCapabilities {
859    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
860    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
861    /// these keys.
862    ///
863    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
864    #[serde_as(deserialize_as = "DefaultOnError")]
865    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
866    #[serde(default)]
867    #[serde(rename = "_meta")]
868    pub meta: Option<Meta>,
869}
870
871impl NesDiagnosticsCapabilities {
872    /// Builds an empty [`NesDiagnosticsCapabilities`]; use builder methods to advertise supported sub-capabilities.
873    #[must_use]
874    pub fn new() -> Self {
875        Self::default()
876    }
877}
878
879// Client NES capabilities
880
881/// NES capabilities advertised by the client during initialization.
882#[serde_as]
883#[skip_serializing_none]
884#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
885#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
886#[serde(rename_all = "camelCase")]
887#[non_exhaustive]
888pub struct ClientNesCapabilities {
889    /// Whether the client supports the `jump` suggestion kind.
890    #[serde_as(deserialize_as = "DefaultOnError")]
891    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
892    #[serde(default)]
893    pub jump: Option<NesJumpCapabilities>,
894    /// Whether the client supports the `rename` suggestion kind.
895    #[serde_as(deserialize_as = "DefaultOnError")]
896    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
897    #[serde(default)]
898    pub rename: Option<NesRenameCapabilities>,
899    /// Whether the client supports the `searchAndReplace` suggestion kind.
900    #[serde_as(deserialize_as = "DefaultOnError")]
901    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
902    #[serde(default)]
903    pub search_and_replace: Option<NesSearchAndReplaceCapabilities>,
904    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
905    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
906    /// these keys.
907    ///
908    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
909    #[serde_as(deserialize_as = "DefaultOnError")]
910    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
911    #[serde(default)]
912    #[serde(rename = "_meta")]
913    pub meta: Option<Meta>,
914}
915
916impl ClientNesCapabilities {
917    /// Builds an empty [`ClientNesCapabilities`]; use builder methods to advertise supported sub-capabilities.
918    #[must_use]
919    pub fn new() -> Self {
920        Self::default()
921    }
922
923    /// Sets or clears the optional `jump` field.
924    #[must_use]
925    pub fn jump(mut self, jump: impl IntoOption<NesJumpCapabilities>) -> Self {
926        self.jump = jump.into_option();
927        self
928    }
929
930    /// Sets or clears the optional `rename` field.
931    #[must_use]
932    pub fn rename(mut self, rename: impl IntoOption<NesRenameCapabilities>) -> Self {
933        self.rename = rename.into_option();
934        self
935    }
936
937    /// Sets or clears the optional `searchAndReplace` field.
938    #[must_use]
939    pub fn search_and_replace(
940        mut self,
941        search_and_replace: impl IntoOption<NesSearchAndReplaceCapabilities>,
942    ) -> Self {
943        self.search_and_replace = search_and_replace.into_option();
944        self
945    }
946
947    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
948    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
949    /// these keys.
950    ///
951    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
952    #[must_use]
953    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
954        self.meta = meta.into_option();
955        self
956    }
957}
958
959/// Marker for jump suggestion support.
960#[serde_as]
961#[skip_serializing_none]
962#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
963#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
964#[serde(rename_all = "camelCase")]
965#[non_exhaustive]
966pub struct NesJumpCapabilities {
967    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
968    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
969    /// these keys.
970    ///
971    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
972    #[serde_as(deserialize_as = "DefaultOnError")]
973    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
974    #[serde(default)]
975    #[serde(rename = "_meta")]
976    pub meta: Option<Meta>,
977}
978
979impl NesJumpCapabilities {
980    /// Builds an empty [`NesJumpCapabilities`]; use builder methods to advertise supported sub-capabilities.
981    #[must_use]
982    pub fn new() -> Self {
983        Self::default()
984    }
985}
986
987/// Marker for rename suggestion support.
988#[serde_as]
989#[skip_serializing_none]
990#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
991#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
992#[serde(rename_all = "camelCase")]
993#[non_exhaustive]
994pub struct NesRenameCapabilities {
995    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
996    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
997    /// these keys.
998    ///
999    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1000    #[serde_as(deserialize_as = "DefaultOnError")]
1001    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1002    #[serde(default)]
1003    #[serde(rename = "_meta")]
1004    pub meta: Option<Meta>,
1005}
1006
1007impl NesRenameCapabilities {
1008    /// Builds an empty [`NesRenameCapabilities`]; use builder methods to advertise supported sub-capabilities.
1009    #[must_use]
1010    pub fn new() -> Self {
1011        Self::default()
1012    }
1013}
1014
1015/// Marker for search and replace suggestion support.
1016#[serde_as]
1017#[skip_serializing_none]
1018#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1019#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1020#[serde(rename_all = "camelCase")]
1021#[non_exhaustive]
1022pub struct NesSearchAndReplaceCapabilities {
1023    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1024    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1025    /// these keys.
1026    ///
1027    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1028    #[serde_as(deserialize_as = "DefaultOnError")]
1029    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1030    #[serde(default)]
1031    #[serde(rename = "_meta")]
1032    pub meta: Option<Meta>,
1033}
1034
1035impl NesSearchAndReplaceCapabilities {
1036    /// Builds an empty [`NesSearchAndReplaceCapabilities`]; use builder methods to advertise supported sub-capabilities.
1037    #[must_use]
1038    pub fn new() -> Self {
1039        Self::default()
1040    }
1041}
1042
1043// Document event notifications (client -> agent)
1044
1045/// Notification sent when a file is opened in the editor.
1046#[serde_as]
1047#[skip_serializing_none]
1048#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1049#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1050#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_OPEN_METHOD_NAME)))]
1051#[serde(rename_all = "camelCase")]
1052#[non_exhaustive]
1053pub struct DidOpenDocumentNotification {
1054    /// The session ID for this notification.
1055    pub session_id: SessionId,
1056    /// The URI of the opened document.
1057    #[cfg_attr(feature = "schemars", schemars(url))]
1058    pub uri: String,
1059    /// The language identifier of the document (e.g., "rust", "python").
1060    pub language_id: String,
1061    /// The version number of the document.
1062    pub version: i64,
1063    /// The full text content of the document.
1064    pub text: String,
1065    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1066    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1067    /// these keys.
1068    ///
1069    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1070    #[serde_as(deserialize_as = "DefaultOnError")]
1071    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1072    #[serde(default)]
1073    #[serde(rename = "_meta")]
1074    pub meta: Option<Meta>,
1075}
1076
1077impl DidOpenDocumentNotification {
1078    /// Builds [`DidOpenDocumentNotification`] with the required notification fields set; optional fields start unset or empty.
1079    #[must_use]
1080    pub fn new(
1081        session_id: impl Into<SessionId>,
1082        uri: impl Into<String>,
1083        language_id: impl Into<String>,
1084        version: i64,
1085        text: impl Into<String>,
1086    ) -> Self {
1087        Self {
1088            session_id: session_id.into(),
1089            uri: uri.into(),
1090            language_id: language_id.into(),
1091            version,
1092            text: text.into(),
1093            meta: None,
1094        }
1095    }
1096
1097    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1098    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1099    /// these keys.
1100    ///
1101    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1102    #[must_use]
1103    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1104        self.meta = meta.into_option();
1105        self
1106    }
1107}
1108
1109/// Notification sent when a file is edited.
1110#[serde_as]
1111#[skip_serializing_none]
1112#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1113#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1114#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CHANGE_METHOD_NAME)))]
1115#[serde(rename_all = "camelCase")]
1116#[non_exhaustive]
1117pub struct DidChangeDocumentNotification {
1118    /// The session ID for this notification.
1119    pub session_id: SessionId,
1120    /// The URI of the changed document.
1121    #[cfg_attr(feature = "schemars", schemars(url))]
1122    pub uri: String,
1123    /// The new version number of the document.
1124    pub version: i64,
1125    /// The content changes.
1126    #[serde_as(deserialize_as = "DefaultOnError<VecSkipError<_, SkipListener>>")]
1127    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true, "x-deserialize-skip-invalid-items" = true)))]
1128    pub content_changes: Vec<TextDocumentContentChangeEvent>,
1129    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1130    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1131    /// these keys.
1132    ///
1133    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1134    #[serde_as(deserialize_as = "DefaultOnError")]
1135    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1136    #[serde(default)]
1137    #[serde(rename = "_meta")]
1138    pub meta: Option<Meta>,
1139}
1140
1141impl DidChangeDocumentNotification {
1142    /// Builds [`DidChangeDocumentNotification`] with the required notification fields set; optional fields start unset or empty.
1143    #[must_use]
1144    pub fn new(
1145        session_id: impl Into<SessionId>,
1146        uri: impl Into<String>,
1147        version: i64,
1148        content_changes: Vec<TextDocumentContentChangeEvent>,
1149    ) -> Self {
1150        Self {
1151            session_id: session_id.into(),
1152            uri: uri.into(),
1153            version,
1154            content_changes,
1155            meta: None,
1156        }
1157    }
1158
1159    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1160    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1161    /// these keys.
1162    ///
1163    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1164    #[must_use]
1165    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1166        self.meta = meta.into_option();
1167        self
1168    }
1169}
1170
1171/// A content change event for a document.
1172///
1173/// When `range` is `None`, `text` is the full content of the document.
1174/// When `range` is `Some`, `text` replaces the given range.
1175#[serde_as]
1176#[skip_serializing_none]
1177#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1178#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1179#[serde(rename_all = "camelCase")]
1180#[non_exhaustive]
1181pub struct TextDocumentContentChangeEvent {
1182    /// The range of the document that changed. If `None`, the entire content is replaced.
1183    #[serde(default)]
1184    pub range: Option<Range>,
1185    /// The new text for the range, or the full document content if `range` is `None`.
1186    pub text: String,
1187    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1188    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1189    /// these keys.
1190    ///
1191    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1192    #[serde_as(deserialize_as = "DefaultOnError")]
1193    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1194    #[serde(default)]
1195    #[serde(rename = "_meta")]
1196    pub meta: Option<Meta>,
1197}
1198
1199impl TextDocumentContentChangeEvent {
1200    /// Builds a full-document change event that replaces the entire document text.
1201    #[must_use]
1202    pub fn full(text: impl Into<String>) -> Self {
1203        Self {
1204            range: None,
1205            text: text.into(),
1206            meta: None,
1207        }
1208    }
1209
1210    /// Builds an incremental document change event for a specific text range.
1211    #[must_use]
1212    pub fn incremental(range: Range, text: impl Into<String>) -> Self {
1213        Self {
1214            range: Some(range),
1215            text: text.into(),
1216            meta: None,
1217        }
1218    }
1219
1220    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1221    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1222    /// these keys.
1223    ///
1224    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1225    #[must_use]
1226    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1227        self.meta = meta.into_option();
1228        self
1229    }
1230}
1231
1232/// Notification sent when a file is closed.
1233#[serde_as]
1234#[skip_serializing_none]
1235#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1236#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1237#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_CLOSE_METHOD_NAME)))]
1238#[serde(rename_all = "camelCase")]
1239#[non_exhaustive]
1240pub struct DidCloseDocumentNotification {
1241    /// The session ID for this notification.
1242    pub session_id: SessionId,
1243    /// The URI of the closed document.
1244    #[cfg_attr(feature = "schemars", schemars(url))]
1245    pub uri: String,
1246    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1247    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1248    /// these keys.
1249    ///
1250    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1251    #[serde_as(deserialize_as = "DefaultOnError")]
1252    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1253    #[serde(default)]
1254    #[serde(rename = "_meta")]
1255    pub meta: Option<Meta>,
1256}
1257
1258impl DidCloseDocumentNotification {
1259    /// Builds [`DidCloseDocumentNotification`] with the required notification fields set; optional fields start unset or empty.
1260    #[must_use]
1261    pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1262        Self {
1263            session_id: session_id.into(),
1264            uri: uri.into(),
1265            meta: None,
1266        }
1267    }
1268
1269    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1270    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1271    /// these keys.
1272    ///
1273    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1274    #[must_use]
1275    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1276        self.meta = meta.into_option();
1277        self
1278    }
1279}
1280
1281/// Notification sent when a file is saved.
1282#[serde_as]
1283#[skip_serializing_none]
1284#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1285#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1286#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_SAVE_METHOD_NAME)))]
1287#[serde(rename_all = "camelCase")]
1288#[non_exhaustive]
1289pub struct DidSaveDocumentNotification {
1290    /// The session ID for this notification.
1291    pub session_id: SessionId,
1292    /// The URI of the saved document.
1293    #[cfg_attr(feature = "schemars", schemars(url))]
1294    pub uri: String,
1295    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1296    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1297    /// these keys.
1298    ///
1299    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1300    #[serde_as(deserialize_as = "DefaultOnError")]
1301    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1302    #[serde(default)]
1303    #[serde(rename = "_meta")]
1304    pub meta: Option<Meta>,
1305}
1306
1307impl DidSaveDocumentNotification {
1308    /// Builds [`DidSaveDocumentNotification`] with the required notification fields set; optional fields start unset or empty.
1309    #[must_use]
1310    pub fn new(session_id: impl Into<SessionId>, uri: impl Into<String>) -> Self {
1311        Self {
1312            session_id: session_id.into(),
1313            uri: uri.into(),
1314            meta: None,
1315        }
1316    }
1317
1318    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1319    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1320    /// these keys.
1321    ///
1322    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1323    #[must_use]
1324    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1325        self.meta = meta.into_option();
1326        self
1327    }
1328}
1329
1330/// Notification sent when a file becomes the active editor tab.
1331#[serde_as]
1332#[skip_serializing_none]
1333#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1334#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1335#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = DOCUMENT_DID_FOCUS_METHOD_NAME)))]
1336#[serde(rename_all = "camelCase")]
1337#[non_exhaustive]
1338pub struct DidFocusDocumentNotification {
1339    /// The session ID for this notification.
1340    pub session_id: SessionId,
1341    /// The URI of the focused document.
1342    #[cfg_attr(feature = "schemars", schemars(url))]
1343    pub uri: String,
1344    /// The version number of the document.
1345    pub version: i64,
1346    /// The current cursor position.
1347    pub position: Position,
1348    /// The portion of the file currently visible in the editor viewport.
1349    pub visible_range: Range,
1350    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1351    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1352    /// these keys.
1353    ///
1354    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1355    #[serde_as(deserialize_as = "DefaultOnError")]
1356    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1357    #[serde(default)]
1358    #[serde(rename = "_meta")]
1359    pub meta: Option<Meta>,
1360}
1361
1362impl DidFocusDocumentNotification {
1363    /// Builds [`DidFocusDocumentNotification`] with the required notification fields set; optional fields start unset or empty.
1364    #[must_use]
1365    pub fn new(
1366        session_id: impl Into<SessionId>,
1367        uri: impl Into<String>,
1368        version: i64,
1369        position: Position,
1370        visible_range: Range,
1371    ) -> Self {
1372        Self {
1373            session_id: session_id.into(),
1374            uri: uri.into(),
1375            version,
1376            position,
1377            visible_range,
1378            meta: None,
1379        }
1380    }
1381
1382    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1383    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1384    /// these keys.
1385    ///
1386    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1387    #[must_use]
1388    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1389        self.meta = meta.into_option();
1390        self
1391    }
1392}
1393
1394// NES session start
1395
1396crate::serde_util::default_on_null! {
1397    /// Request to start an NES session.
1398    #[serde_as]
1399    #[skip_serializing_none]
1400    #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1401    #[derive(Debug, Clone, Serialize, PartialEq, Eq)]
1402    #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME)))]
1403    #[serde(rename_all = "camelCase")]
1404    #[non_exhaustive]
1405    pub struct StartNesRequest {
1406        /// The root URI of the workspace.
1407        #[serde_as(deserialize_as = "DefaultOnError")]
1408        #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1409        #[cfg_attr(feature = "schemars", schemars(url))]
1410        #[serde(default)]
1411        pub workspace_uri: Option<String>,
1412        /// The workspace folders.
1413        #[serde(default)]
1414        pub workspace_folders: Option<Vec<WorkspaceFolder>>,
1415        /// Repository metadata, if the workspace is a git repository.
1416        #[serde_as(deserialize_as = "DefaultOnError")]
1417        #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1418        #[serde(default)]
1419        pub repository: Option<NesRepository>,
1420        /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1421        /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1422        /// these keys.
1423        ///
1424        /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1425        #[serde_as(deserialize_as = "DefaultOnError")]
1426        #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1427        #[serde(default)]
1428        #[serde(rename = "_meta")]
1429        pub meta: Option<Meta>,
1430    }
1431}
1432
1433impl StartNesRequest {
1434    /// Builds [`StartNesRequest`] with the required request fields set; optional fields start unset or empty.
1435    #[must_use]
1436    pub fn new() -> Self {
1437        Self {
1438            workspace_uri: None,
1439            workspace_folders: None,
1440            repository: None,
1441            meta: None,
1442        }
1443    }
1444
1445    /// Sets or clears the optional `workspaceUri` field.
1446    #[must_use]
1447    pub fn workspace_uri(mut self, workspace_uri: impl IntoOption<String>) -> Self {
1448        self.workspace_uri = workspace_uri.into_option();
1449        self
1450    }
1451
1452    /// Sets or clears the optional `workspaceFolders` field.
1453    #[must_use]
1454    pub fn workspace_folders(
1455        mut self,
1456        workspace_folders: impl IntoOption<Vec<WorkspaceFolder>>,
1457    ) -> Self {
1458        self.workspace_folders = workspace_folders.into_option();
1459        self
1460    }
1461
1462    /// Sets or clears the optional `repository` field.
1463    #[must_use]
1464    pub fn repository(mut self, repository: impl IntoOption<NesRepository>) -> Self {
1465        self.repository = repository.into_option();
1466        self
1467    }
1468
1469    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1470    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1471    /// these keys.
1472    ///
1473    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1474    #[must_use]
1475    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1476        self.meta = meta.into_option();
1477        self
1478    }
1479}
1480
1481impl Default for StartNesRequest {
1482    fn default() -> Self {
1483        Self::new()
1484    }
1485}
1486
1487/// A workspace folder.
1488#[serde_as]
1489#[skip_serializing_none]
1490#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1491#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1492#[serde(rename_all = "camelCase")]
1493#[non_exhaustive]
1494pub struct WorkspaceFolder {
1495    /// The URI of the folder.
1496    #[cfg_attr(feature = "schemars", schemars(url))]
1497    pub uri: String,
1498    /// The display name of the folder.
1499    pub name: String,
1500    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1501    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1502    /// these keys.
1503    ///
1504    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1505    #[serde_as(deserialize_as = "DefaultOnError")]
1506    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1507    #[serde(default)]
1508    #[serde(rename = "_meta")]
1509    pub meta: Option<Meta>,
1510}
1511
1512impl WorkspaceFolder {
1513    /// Builds [`WorkspaceFolder`] with the required fields set; optional fields start unset or empty.
1514    #[must_use]
1515    pub fn new(uri: impl Into<String>, name: impl Into<String>) -> Self {
1516        Self {
1517            uri: uri.into(),
1518            name: name.into(),
1519            meta: None,
1520        }
1521    }
1522
1523    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1524    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1525    /// these keys.
1526    ///
1527    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1528    #[must_use]
1529    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1530        self.meta = meta.into_option();
1531        self
1532    }
1533}
1534
1535/// Repository metadata for an NES session.
1536#[serde_as]
1537#[skip_serializing_none]
1538#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1539#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1540#[serde(rename_all = "camelCase")]
1541#[non_exhaustive]
1542pub struct NesRepository {
1543    /// The repository name.
1544    pub name: String,
1545    /// The repository owner.
1546    pub owner: String,
1547    /// The remote URL of the repository.
1548    pub remote_url: String,
1549    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1550    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1551    /// these keys.
1552    ///
1553    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1554    #[serde_as(deserialize_as = "DefaultOnError")]
1555    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1556    #[serde(default)]
1557    #[serde(rename = "_meta")]
1558    pub meta: Option<Meta>,
1559}
1560
1561impl NesRepository {
1562    /// Builds [`NesRepository`] with the required fields set; optional fields start unset or empty.
1563    #[must_use]
1564    pub fn new(
1565        name: impl Into<String>,
1566        owner: impl Into<String>,
1567        remote_url: impl Into<String>,
1568    ) -> Self {
1569        Self {
1570            name: name.into(),
1571            owner: owner.into(),
1572            remote_url: remote_url.into(),
1573            meta: None,
1574        }
1575    }
1576
1577    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1578    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1579    /// these keys.
1580    ///
1581    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1582    #[must_use]
1583    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1584        self.meta = meta.into_option();
1585        self
1586    }
1587}
1588
1589/// Response to `nes/start`.
1590#[serde_as]
1591#[skip_serializing_none]
1592#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1593#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1594#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME)))]
1595#[serde(rename_all = "camelCase")]
1596#[non_exhaustive]
1597pub struct StartNesResponse {
1598    /// The session ID for the newly started NES session.
1599    pub session_id: SessionId,
1600    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1601    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1602    /// these keys.
1603    ///
1604    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1605    #[serde_as(deserialize_as = "DefaultOnError")]
1606    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1607    #[serde(default)]
1608    #[serde(rename = "_meta")]
1609    pub meta: Option<Meta>,
1610}
1611
1612impl StartNesResponse {
1613    /// Builds [`StartNesResponse`] with the required response fields set; optional fields start unset or empty.
1614    #[must_use]
1615    pub fn new(session_id: impl Into<SessionId>) -> Self {
1616        Self {
1617            session_id: session_id.into(),
1618            meta: None,
1619        }
1620    }
1621
1622    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1623    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1624    /// these keys.
1625    ///
1626    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1627    #[must_use]
1628    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1629        self.meta = meta.into_option();
1630        self
1631    }
1632}
1633
1634// NES session close
1635
1636/// Request to close an NES session.
1637///
1638/// The agent **must** cancel any ongoing work related to the NES session
1639/// and then free up any resources associated with the session.
1640#[serde_as]
1641#[skip_serializing_none]
1642#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1643#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1644#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME)))]
1645#[serde(rename_all = "camelCase")]
1646#[non_exhaustive]
1647pub struct CloseNesRequest {
1648    /// The ID of the NES session to close.
1649    pub session_id: SessionId,
1650    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1651    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1652    /// these keys.
1653    ///
1654    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1655    #[serde_as(deserialize_as = "DefaultOnError")]
1656    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1657    #[serde(default)]
1658    #[serde(rename = "_meta")]
1659    pub meta: Option<Meta>,
1660}
1661
1662impl CloseNesRequest {
1663    /// Builds [`CloseNesRequest`] with the required request fields set; optional fields start unset or empty.
1664    #[must_use]
1665    pub fn new(session_id: impl Into<SessionId>) -> Self {
1666        Self {
1667            session_id: session_id.into(),
1668            meta: None,
1669        }
1670    }
1671
1672    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1673    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1674    /// these keys.
1675    ///
1676    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1677    #[must_use]
1678    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1679        self.meta = meta.into_option();
1680        self
1681    }
1682}
1683
1684crate::serde_util::default_on_null! {
1685    /// Response from closing an NES session.
1686    #[serde_as]
1687    #[skip_serializing_none]
1688    #[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1689    #[derive(Default, Debug, Clone, Serialize, PartialEq, Eq)]
1690    #[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME)))]
1691    #[serde(rename_all = "camelCase")]
1692    #[non_exhaustive]
1693    pub struct CloseNesResponse {
1694        /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1695        /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1696        /// these keys.
1697        ///
1698        /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1699        #[serde_as(deserialize_as = "DefaultOnError")]
1700        #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1701        #[serde(default)]
1702        #[serde(rename = "_meta")]
1703        pub meta: Option<Meta>,
1704    }
1705}
1706
1707impl CloseNesResponse {
1708    /// Builds [`CloseNesResponse`] with the required response fields set; optional fields start unset or empty.
1709    #[must_use]
1710    pub fn new() -> Self {
1711        Self::default()
1712    }
1713
1714    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1715    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1716    /// these keys.
1717    ///
1718    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1719    #[must_use]
1720    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1721        self.meta = meta.into_option();
1722        self
1723    }
1724}
1725
1726// NES suggest request
1727
1728/// What triggered the suggestion request.
1729#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1730#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1731#[non_exhaustive]
1732pub enum NesTriggerKind {
1733    /// Triggered by user typing or cursor movement.
1734    #[serde(rename = "automatic")]
1735    Automatic,
1736    /// Triggered by a diagnostic appearing at or near the cursor.
1737    #[serde(rename = "diagnostic")]
1738    Diagnostic,
1739    /// Triggered by an explicit user action (keyboard shortcut).
1740    #[serde(rename = "manual")]
1741    Manual,
1742    /// Custom or future suggestion trigger kind.
1743    ///
1744    /// Values beginning with `_` are reserved for implementation-specific
1745    /// extensions. Unknown values that do not begin with `_` are reserved for
1746    /// future ACP variants.
1747    #[serde(untagged)]
1748    Other(String),
1749}
1750
1751/// Request for a code suggestion.
1752#[serde_as]
1753#[skip_serializing_none]
1754#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1755#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1756#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME)))]
1757#[serde(rename_all = "camelCase")]
1758#[non_exhaustive]
1759pub struct SuggestNesRequest {
1760    /// The session ID for this request.
1761    pub session_id: SessionId,
1762    /// The URI of the document to suggest for.
1763    #[cfg_attr(feature = "schemars", schemars(url))]
1764    pub uri: String,
1765    /// The version number of the document.
1766    pub version: i64,
1767    /// The current cursor position.
1768    pub position: Position,
1769    /// The current text selection range, if any.
1770    #[serde(default)]
1771    pub selection: Option<Range>,
1772    /// What triggered this suggestion request.
1773    pub trigger_kind: NesTriggerKind,
1774    /// Context for the suggestion, included based on agent capabilities.
1775    #[serde(default)]
1776    pub context: Option<NesSuggestContext>,
1777    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1778    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1779    /// these keys.
1780    ///
1781    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1782    #[serde_as(deserialize_as = "DefaultOnError")]
1783    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1784    #[serde(default)]
1785    #[serde(rename = "_meta")]
1786    pub meta: Option<Meta>,
1787}
1788
1789impl SuggestNesRequest {
1790    /// Builds [`SuggestNesRequest`] with the required request fields set; optional fields start unset or empty.
1791    #[must_use]
1792    pub fn new(
1793        session_id: impl Into<SessionId>,
1794        uri: impl Into<String>,
1795        version: i64,
1796        position: Position,
1797        trigger_kind: NesTriggerKind,
1798    ) -> Self {
1799        Self {
1800            session_id: session_id.into(),
1801            uri: uri.into(),
1802            version,
1803            position,
1804            selection: None,
1805            trigger_kind,
1806            context: None,
1807            meta: None,
1808        }
1809    }
1810
1811    /// Sets or clears the optional `selection` field.
1812    #[must_use]
1813    pub fn selection(mut self, selection: impl IntoOption<Range>) -> Self {
1814        self.selection = selection.into_option();
1815        self
1816    }
1817
1818    /// Sets or clears the optional `context` field.
1819    #[must_use]
1820    pub fn context(mut self, context: impl IntoOption<NesSuggestContext>) -> Self {
1821        self.context = context.into_option();
1822        self
1823    }
1824
1825    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1826    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1827    /// these keys.
1828    ///
1829    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1830    #[must_use]
1831    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1832        self.meta = meta.into_option();
1833        self
1834    }
1835}
1836
1837/// Context attached to a suggestion request.
1838#[serde_as]
1839#[skip_serializing_none]
1840#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1841#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1842#[serde(rename_all = "camelCase")]
1843#[non_exhaustive]
1844pub struct NesSuggestContext {
1845    /// Recently accessed files.
1846    #[serde(default)]
1847    pub recent_files: Option<Vec<NesRecentFile>>,
1848    /// Related code snippets.
1849    #[serde(default)]
1850    pub related_snippets: Option<Vec<NesRelatedSnippet>>,
1851    /// Recent edit history.
1852    #[serde(default)]
1853    pub edit_history: Option<Vec<NesEditHistoryEntry>>,
1854    /// Recent user actions (typing, navigation, etc.).
1855    #[serde(default)]
1856    pub user_actions: Option<Vec<NesUserAction>>,
1857    /// Currently open files in the editor.
1858    #[serde(default)]
1859    pub open_files: Option<Vec<NesOpenFile>>,
1860    /// Current diagnostics (errors, warnings).
1861    #[serde(default)]
1862    pub diagnostics: Option<Vec<NesDiagnostic>>,
1863    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1864    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1865    /// these keys.
1866    ///
1867    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1868    #[serde_as(deserialize_as = "DefaultOnError")]
1869    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1870    #[serde(default)]
1871    #[serde(rename = "_meta")]
1872    pub meta: Option<Meta>,
1873}
1874
1875impl NesSuggestContext {
1876    /// Builds [`NesSuggestContext`] with the required fields set; optional fields start unset or empty.
1877    #[must_use]
1878    pub fn new() -> Self {
1879        Self::default()
1880    }
1881
1882    /// Sets or clears the optional `recentFiles` field.
1883    #[must_use]
1884    pub fn recent_files(mut self, recent_files: impl IntoOption<Vec<NesRecentFile>>) -> Self {
1885        self.recent_files = recent_files.into_option();
1886        self
1887    }
1888
1889    /// Sets or clears the optional `relatedSnippets` field.
1890    #[must_use]
1891    pub fn related_snippets(
1892        mut self,
1893        related_snippets: impl IntoOption<Vec<NesRelatedSnippet>>,
1894    ) -> Self {
1895        self.related_snippets = related_snippets.into_option();
1896        self
1897    }
1898
1899    /// Sets or clears the optional `editHistory` field.
1900    #[must_use]
1901    pub fn edit_history(mut self, edit_history: impl IntoOption<Vec<NesEditHistoryEntry>>) -> Self {
1902        self.edit_history = edit_history.into_option();
1903        self
1904    }
1905
1906    /// Sets or clears the optional `userActions` field.
1907    #[must_use]
1908    pub fn user_actions(mut self, user_actions: impl IntoOption<Vec<NesUserAction>>) -> Self {
1909        self.user_actions = user_actions.into_option();
1910        self
1911    }
1912
1913    /// Sets or clears the optional `openFiles` field.
1914    #[must_use]
1915    pub fn open_files(mut self, open_files: impl IntoOption<Vec<NesOpenFile>>) -> Self {
1916        self.open_files = open_files.into_option();
1917        self
1918    }
1919
1920    /// Sets or clears the optional `diagnostics` field.
1921    #[must_use]
1922    pub fn diagnostics(mut self, diagnostics: impl IntoOption<Vec<NesDiagnostic>>) -> Self {
1923        self.diagnostics = diagnostics.into_option();
1924        self
1925    }
1926
1927    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1928    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1929    /// these keys.
1930    ///
1931    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1932    #[must_use]
1933    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1934        self.meta = meta.into_option();
1935        self
1936    }
1937}
1938
1939/// A recently accessed file.
1940#[serde_as]
1941#[skip_serializing_none]
1942#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1943#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1944#[serde(rename_all = "camelCase")]
1945#[non_exhaustive]
1946pub struct NesRecentFile {
1947    /// The URI of the file.
1948    #[cfg_attr(feature = "schemars", schemars(url))]
1949    pub uri: String,
1950    /// The language identifier.
1951    pub language_id: String,
1952    /// The full text content of the file.
1953    pub text: String,
1954    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1955    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1956    /// these keys.
1957    ///
1958    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1959    #[serde_as(deserialize_as = "DefaultOnError")]
1960    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1961    #[serde(default)]
1962    #[serde(rename = "_meta")]
1963    pub meta: Option<Meta>,
1964}
1965
1966impl NesRecentFile {
1967    /// Builds [`NesRecentFile`] with the required fields set; optional fields start unset or empty.
1968    #[must_use]
1969    pub fn new(
1970        uri: impl Into<String>,
1971        language_id: impl Into<String>,
1972        text: impl Into<String>,
1973    ) -> Self {
1974        Self {
1975            uri: uri.into(),
1976            language_id: language_id.into(),
1977            text: text.into(),
1978            meta: None,
1979        }
1980    }
1981
1982    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1983    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1984    /// these keys.
1985    ///
1986    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1987    #[must_use]
1988    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1989        self.meta = meta.into_option();
1990        self
1991    }
1992}
1993
1994/// A related code snippet from a file.
1995#[serde_as]
1996#[skip_serializing_none]
1997#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1998#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1999#[serde(rename_all = "camelCase")]
2000#[non_exhaustive]
2001pub struct NesRelatedSnippet {
2002    /// The URI of the file containing the snippets.
2003    #[cfg_attr(feature = "schemars", schemars(url))]
2004    pub uri: String,
2005    /// The code excerpts.
2006    pub excerpts: Vec<NesExcerpt>,
2007    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2008    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2009    /// these keys.
2010    ///
2011    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2012    #[serde_as(deserialize_as = "DefaultOnError")]
2013    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2014    #[serde(default)]
2015    #[serde(rename = "_meta")]
2016    pub meta: Option<Meta>,
2017}
2018
2019impl NesRelatedSnippet {
2020    /// Builds [`NesRelatedSnippet`] with the required fields set; optional fields start unset or empty.
2021    #[must_use]
2022    pub fn new(uri: impl Into<String>, excerpts: Vec<NesExcerpt>) -> Self {
2023        Self {
2024            uri: uri.into(),
2025            excerpts,
2026            meta: None,
2027        }
2028    }
2029
2030    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2031    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2032    /// these keys.
2033    ///
2034    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2035    #[must_use]
2036    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2037        self.meta = meta.into_option();
2038        self
2039    }
2040}
2041
2042/// A code excerpt from a file.
2043#[serde_as]
2044#[skip_serializing_none]
2045#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2046#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2047#[serde(rename_all = "camelCase")]
2048#[non_exhaustive]
2049pub struct NesExcerpt {
2050    /// The start line of the excerpt (zero-based).
2051    pub start_line: u32,
2052    /// The end line of the excerpt (zero-based).
2053    pub end_line: u32,
2054    /// The text content of the excerpt.
2055    pub text: String,
2056    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2057    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2058    /// these keys.
2059    ///
2060    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2061    #[serde_as(deserialize_as = "DefaultOnError")]
2062    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2063    #[serde(default)]
2064    #[serde(rename = "_meta")]
2065    pub meta: Option<Meta>,
2066}
2067
2068impl NesExcerpt {
2069    /// Builds [`NesExcerpt`] with the required fields set; optional fields start unset or empty.
2070    #[must_use]
2071    pub fn new(start_line: u32, end_line: u32, text: impl Into<String>) -> Self {
2072        Self {
2073            start_line,
2074            end_line,
2075            text: text.into(),
2076            meta: None,
2077        }
2078    }
2079
2080    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2081    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2082    /// these keys.
2083    ///
2084    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2085    #[must_use]
2086    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2087        self.meta = meta.into_option();
2088        self
2089    }
2090}
2091
2092/// An entry in the edit history.
2093#[serde_as]
2094#[skip_serializing_none]
2095#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2096#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2097#[serde(rename_all = "camelCase")]
2098#[non_exhaustive]
2099pub struct NesEditHistoryEntry {
2100    /// The URI of the edited file.
2101    #[cfg_attr(feature = "schemars", schemars(url))]
2102    pub uri: String,
2103    /// A diff representing the edit.
2104    pub diff: String,
2105    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2106    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2107    /// these keys.
2108    ///
2109    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2110    #[serde_as(deserialize_as = "DefaultOnError")]
2111    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2112    #[serde(default)]
2113    #[serde(rename = "_meta")]
2114    pub meta: Option<Meta>,
2115}
2116
2117impl NesEditHistoryEntry {
2118    /// Builds [`NesEditHistoryEntry`] with the required fields set; optional fields start unset or empty.
2119    #[must_use]
2120    pub fn new(uri: impl Into<String>, diff: impl Into<String>) -> Self {
2121        Self {
2122            uri: uri.into(),
2123            diff: diff.into(),
2124            meta: None,
2125        }
2126    }
2127
2128    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2129    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2130    /// these keys.
2131    ///
2132    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2133    #[must_use]
2134    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2135        self.meta = meta.into_option();
2136        self
2137    }
2138}
2139
2140/// A user action (typing, cursor movement, etc.).
2141#[serde_as]
2142#[skip_serializing_none]
2143#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2144#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2145#[serde(rename_all = "camelCase")]
2146#[non_exhaustive]
2147pub struct NesUserAction {
2148    /// The kind of action (e.g., "insertChar", "cursorMovement").
2149    pub action: String,
2150    /// The URI of the file where the action occurred.
2151    #[cfg_attr(feature = "schemars", schemars(url))]
2152    pub uri: String,
2153    /// The position where the action occurred.
2154    pub position: Position,
2155    /// Timestamp in milliseconds since epoch.
2156    pub timestamp_ms: u64,
2157    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2158    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2159    /// these keys.
2160    ///
2161    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2162    #[serde_as(deserialize_as = "DefaultOnError")]
2163    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2164    #[serde(default)]
2165    #[serde(rename = "_meta")]
2166    pub meta: Option<Meta>,
2167}
2168
2169impl NesUserAction {
2170    /// Builds [`NesUserAction`] with the required fields set; optional fields start unset or empty.
2171    #[must_use]
2172    pub fn new(
2173        action: impl Into<String>,
2174        uri: impl Into<String>,
2175        position: Position,
2176        timestamp_ms: u64,
2177    ) -> Self {
2178        Self {
2179            action: action.into(),
2180            uri: uri.into(),
2181            position,
2182            timestamp_ms,
2183            meta: None,
2184        }
2185    }
2186
2187    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2188    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2189    /// these keys.
2190    ///
2191    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2192    #[must_use]
2193    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2194        self.meta = meta.into_option();
2195        self
2196    }
2197}
2198
2199/// An open file in the editor.
2200#[serde_as]
2201#[skip_serializing_none]
2202#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2203#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2204#[serde(rename_all = "camelCase")]
2205#[non_exhaustive]
2206pub struct NesOpenFile {
2207    /// The URI of the file.
2208    #[cfg_attr(feature = "schemars", schemars(url))]
2209    pub uri: String,
2210    /// The language identifier.
2211    pub language_id: String,
2212    /// The visible range in the editor, if any.
2213    #[serde_as(deserialize_as = "DefaultOnError")]
2214    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2215    #[serde(default)]
2216    pub visible_range: Option<Range>,
2217    /// Timestamp in milliseconds since epoch of when the file was last focused.
2218    #[serde_as(deserialize_as = "DefaultOnError")]
2219    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2220    #[serde(default)]
2221    pub last_focused_ms: Option<u64>,
2222    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2223    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2224    /// these keys.
2225    ///
2226    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2227    #[serde_as(deserialize_as = "DefaultOnError")]
2228    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2229    #[serde(default)]
2230    #[serde(rename = "_meta")]
2231    pub meta: Option<Meta>,
2232}
2233
2234impl NesOpenFile {
2235    /// Builds [`NesOpenFile`] with the required fields set; optional fields start unset or empty.
2236    #[must_use]
2237    pub fn new(uri: impl Into<String>, language_id: impl Into<String>) -> Self {
2238        Self {
2239            uri: uri.into(),
2240            language_id: language_id.into(),
2241            visible_range: None,
2242            last_focused_ms: None,
2243            meta: None,
2244        }
2245    }
2246
2247    /// Sets or clears the optional `visibleRange` field.
2248    #[must_use]
2249    pub fn visible_range(mut self, visible_range: impl IntoOption<Range>) -> Self {
2250        self.visible_range = visible_range.into_option();
2251        self
2252    }
2253
2254    /// Sets or clears the optional `lastFocusedMs` field.
2255    #[must_use]
2256    pub fn last_focused_ms(mut self, last_focused_ms: impl IntoOption<u64>) -> Self {
2257        self.last_focused_ms = last_focused_ms.into_option();
2258        self
2259    }
2260
2261    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2262    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2263    /// these keys.
2264    ///
2265    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2266    #[must_use]
2267    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2268        self.meta = meta.into_option();
2269        self
2270    }
2271}
2272
2273/// A diagnostic (error, warning, etc.).
2274#[serde_as]
2275#[skip_serializing_none]
2276#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2277#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2278#[serde(rename_all = "camelCase")]
2279#[non_exhaustive]
2280pub struct NesDiagnostic {
2281    /// The URI of the file containing the diagnostic.
2282    #[cfg_attr(feature = "schemars", schemars(url))]
2283    pub uri: String,
2284    /// The range of the diagnostic.
2285    pub range: Range,
2286    /// The severity of the diagnostic.
2287    pub severity: NesDiagnosticSeverity,
2288    /// The diagnostic message.
2289    pub message: String,
2290    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2291    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2292    /// these keys.
2293    ///
2294    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2295    #[serde_as(deserialize_as = "DefaultOnError")]
2296    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2297    #[serde(default)]
2298    #[serde(rename = "_meta")]
2299    pub meta: Option<Meta>,
2300}
2301
2302impl NesDiagnostic {
2303    /// Builds [`NesDiagnostic`] with the required fields set; optional fields start unset or empty.
2304    #[must_use]
2305    pub fn new(
2306        uri: impl Into<String>,
2307        range: Range,
2308        severity: NesDiagnosticSeverity,
2309        message: impl Into<String>,
2310    ) -> Self {
2311        Self {
2312            uri: uri.into(),
2313            range,
2314            severity,
2315            message: message.into(),
2316            meta: None,
2317        }
2318    }
2319
2320    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2321    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2322    /// these keys.
2323    ///
2324    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2325    #[must_use]
2326    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2327        self.meta = meta.into_option();
2328        self
2329    }
2330}
2331
2332/// Severity of a diagnostic.
2333#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2334#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2335#[non_exhaustive]
2336pub enum NesDiagnosticSeverity {
2337    /// An error.
2338    #[serde(rename = "error")]
2339    Error,
2340    /// A warning.
2341    #[serde(rename = "warning")]
2342    Warning,
2343    /// An informational message.
2344    #[serde(rename = "information")]
2345    Information,
2346    /// A hint.
2347    #[serde(rename = "hint")]
2348    Hint,
2349    /// Custom or future diagnostic severity.
2350    ///
2351    /// Values beginning with `_` are reserved for implementation-specific
2352    /// extensions. Unknown values that do not begin with `_` are reserved for
2353    /// future ACP variants.
2354    #[serde(untagged)]
2355    Other(String),
2356}
2357
2358// NES suggest response
2359
2360/// Response to `nes/suggest`.
2361#[serde_as]
2362#[skip_serializing_none]
2363#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2364#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2365#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME)))]
2366#[serde(rename_all = "camelCase")]
2367#[non_exhaustive]
2368pub struct SuggestNesResponse {
2369    /// The list of suggestions.
2370    pub suggestions: Vec<NesSuggestion>,
2371    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2372    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2373    /// these keys.
2374    ///
2375    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2376    #[serde_as(deserialize_as = "DefaultOnError")]
2377    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2378    #[serde(default)]
2379    #[serde(rename = "_meta")]
2380    pub meta: Option<Meta>,
2381}
2382
2383impl SuggestNesResponse {
2384    /// Builds [`SuggestNesResponse`] with the required response fields set; optional fields start unset or empty.
2385    #[must_use]
2386    pub fn new(suggestions: Vec<NesSuggestion>) -> Self {
2387        Self {
2388            suggestions,
2389            meta: None,
2390        }
2391    }
2392
2393    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2394    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2395    /// these keys.
2396    ///
2397    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2398    #[must_use]
2399    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2400        self.meta = meta.into_option();
2401        self
2402    }
2403}
2404
2405/// A suggestion returned by the agent.
2406#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2407#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2408#[serde(tag = "kind", rename_all = "camelCase")]
2409#[non_exhaustive]
2410pub enum NesSuggestion {
2411    /// A text edit suggestion.
2412    Edit(NesEditSuggestion),
2413    /// A jump-to-location suggestion.
2414    Jump(NesJumpSuggestion),
2415    /// A rename symbol suggestion.
2416    Rename(NesRenameSuggestion),
2417    /// A search-and-replace suggestion.
2418    SearchAndReplace(NesSearchAndReplaceSuggestion),
2419    /// Custom or future NES suggestion.
2420    ///
2421    /// Values beginning with `_` are reserved for implementation-specific
2422    /// extensions. Unknown values that do not begin with `_` are reserved for
2423    /// future ACP variants.
2424    ///
2425    /// Receivers that do not understand this suggestion kind should preserve
2426    /// the raw payload when storing, replaying, proxying, or forwarding
2427    /// suggestions, and otherwise ignore it or display it generically.
2428    #[serde(untagged)]
2429    Other(OtherNesSuggestion),
2430}
2431
2432/// Custom or future NES suggestion payload.
2433#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2434#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
2435#[cfg_attr(feature = "schemars", schemars(inline))]
2436#[cfg_attr(feature = "schemars", schemars(transform = other_nes_suggestion_schema))]
2437#[serde(rename_all = "camelCase")]
2438#[non_exhaustive]
2439pub struct OtherNesSuggestion {
2440    /// Custom or future NES suggestion kind.
2441    ///
2442    /// Values beginning with `_` are reserved for implementation-specific
2443    /// extensions. Unknown values that do not begin with `_` are reserved for
2444    /// future ACP variants.
2445    pub kind: String,
2446    /// Unique identifier for accept/reject tracking.
2447    pub suggestion_id: NesSuggestionId,
2448    /// Additional fields from the unknown NES suggestion payload.
2449    #[serde(flatten)]
2450    pub fields: BTreeMap<String, serde_json::Value>,
2451}
2452
2453impl OtherNesSuggestion {
2454    /// Builds [`OtherNesSuggestion`] from an unknown discriminator and preserves the remaining extension fields.
2455    #[must_use]
2456    pub fn new(
2457        kind: impl Into<String>,
2458        suggestion_id: impl Into<NesSuggestionId>,
2459        mut fields: BTreeMap<String, serde_json::Value>,
2460    ) -> Self {
2461        fields.remove("kind");
2462        fields.remove("suggestionId");
2463        Self {
2464            kind: kind.into(),
2465            suggestion_id: suggestion_id.into(),
2466            fields,
2467        }
2468    }
2469}
2470
2471impl<'de> Deserialize<'de> for OtherNesSuggestion {
2472    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2473    where
2474        D: serde::Deserializer<'de>,
2475    {
2476        let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2477        let kind = fields
2478            .remove("kind")
2479            .ok_or_else(|| serde::de::Error::missing_field("kind"))?;
2480        let serde_json::Value::String(kind) = kind else {
2481            return Err(serde::de::Error::custom("`kind` must be a string"));
2482        };
2483        let suggestion_id = fields
2484            .remove("suggestionId")
2485            .ok_or_else(|| serde::de::Error::missing_field("suggestionId"))?;
2486        let serde_json::Value::String(suggestion_id) = suggestion_id else {
2487            return Err(serde::de::Error::custom("`suggestionId` must be a string"));
2488        };
2489
2490        if is_known_nes_suggestion_kind(&kind) {
2491            return Err(serde::de::Error::custom(format!(
2492                "known NES suggestion `{kind}` did not match its schema"
2493            )));
2494        }
2495
2496        Ok(Self {
2497            kind,
2498            suggestion_id: NesSuggestionId::new(suggestion_id),
2499            fields,
2500        })
2501    }
2502}
2503
2504fn is_known_nes_suggestion_kind(kind: &str) -> bool {
2505    matches!(kind, "edit" | "jump" | "rename" | "searchAndReplace")
2506}
2507
2508#[cfg(feature = "schemars")]
2509fn other_nes_suggestion_schema(schema: &mut Schema) {
2510    super::schema_util::reject_known_string_discriminators(
2511        schema,
2512        "kind",
2513        &["edit", "jump", "rename", "searchAndReplace"],
2514    );
2515}
2516
2517/// A text edit suggestion.
2518#[serde_as]
2519#[skip_serializing_none]
2520#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2521#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2522#[serde(rename_all = "camelCase")]
2523#[non_exhaustive]
2524pub struct NesEditSuggestion {
2525    /// Unique identifier for accept/reject tracking.
2526    pub suggestion_id: NesSuggestionId,
2527    /// The URI of the file to edit.
2528    #[cfg_attr(feature = "schemars", schemars(url))]
2529    pub uri: String,
2530    /// The text edits to apply. Must contain at least one edit.
2531    #[cfg_attr(feature = "schemars", schemars(length(min = 1)))]
2532    pub edits: Vec<NesTextEdit>,
2533    /// Optional suggested cursor position after applying edits.
2534    #[serde_as(deserialize_as = "DefaultOnError")]
2535    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2536    #[serde(default)]
2537    pub cursor_position: Option<Position>,
2538    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2539    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2540    /// these keys.
2541    ///
2542    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2543    #[serde_as(deserialize_as = "DefaultOnError")]
2544    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2545    #[serde(default)]
2546    #[serde(rename = "_meta")]
2547    pub meta: Option<Meta>,
2548}
2549
2550impl NesEditSuggestion {
2551    /// Builds [`NesEditSuggestion`] with the required fields set; optional fields start unset or empty.
2552    #[must_use]
2553    pub fn new(
2554        suggestion_id: impl Into<NesSuggestionId>,
2555        uri: impl Into<String>,
2556        edits: Vec<NesTextEdit>,
2557    ) -> Self {
2558        Self {
2559            suggestion_id: suggestion_id.into(),
2560            uri: uri.into(),
2561            edits,
2562            cursor_position: None,
2563            meta: None,
2564        }
2565    }
2566
2567    /// Sets or clears the optional `cursorPosition` field.
2568    #[must_use]
2569    pub fn cursor_position(mut self, cursor_position: impl IntoOption<Position>) -> Self {
2570        self.cursor_position = cursor_position.into_option();
2571        self
2572    }
2573
2574    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2575    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2576    /// these keys.
2577    ///
2578    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2579    #[must_use]
2580    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2581        self.meta = meta.into_option();
2582        self
2583    }
2584}
2585
2586/// A text edit within a suggestion.
2587#[serde_as]
2588#[skip_serializing_none]
2589#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2590#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2591#[serde(rename_all = "camelCase")]
2592#[non_exhaustive]
2593pub struct NesTextEdit {
2594    /// The range to replace.
2595    pub range: Range,
2596    /// The replacement text.
2597    pub new_text: String,
2598    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2599    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2600    /// these keys.
2601    ///
2602    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2603    #[serde_as(deserialize_as = "DefaultOnError")]
2604    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2605    #[serde(default)]
2606    #[serde(rename = "_meta")]
2607    pub meta: Option<Meta>,
2608}
2609
2610impl NesTextEdit {
2611    /// Builds [`NesTextEdit`] with the required fields set; optional fields start unset or empty.
2612    #[must_use]
2613    pub fn new(range: Range, new_text: impl Into<String>) -> Self {
2614        Self {
2615            range,
2616            new_text: new_text.into(),
2617            meta: None,
2618        }
2619    }
2620
2621    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2622    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2623    /// these keys.
2624    ///
2625    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2626    #[must_use]
2627    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2628        self.meta = meta.into_option();
2629        self
2630    }
2631}
2632
2633/// A jump-to-location suggestion.
2634#[serde_as]
2635#[skip_serializing_none]
2636#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2637#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2638#[serde(rename_all = "camelCase")]
2639#[non_exhaustive]
2640pub struct NesJumpSuggestion {
2641    /// Unique identifier for accept/reject tracking.
2642    pub suggestion_id: NesSuggestionId,
2643    /// The file to navigate to.
2644    #[cfg_attr(feature = "schemars", schemars(url))]
2645    pub uri: String,
2646    /// The target position within the file.
2647    pub position: Position,
2648    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2649    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2650    /// these keys.
2651    ///
2652    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2653    #[serde_as(deserialize_as = "DefaultOnError")]
2654    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2655    #[serde(default)]
2656    #[serde(rename = "_meta")]
2657    pub meta: Option<Meta>,
2658}
2659
2660impl NesJumpSuggestion {
2661    /// Builds [`NesJumpSuggestion`] with the required fields set; optional fields start unset or empty.
2662    #[must_use]
2663    pub fn new(
2664        suggestion_id: impl Into<NesSuggestionId>,
2665        uri: impl Into<String>,
2666        position: Position,
2667    ) -> Self {
2668        Self {
2669            suggestion_id: suggestion_id.into(),
2670            uri: uri.into(),
2671            position,
2672            meta: None,
2673        }
2674    }
2675
2676    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2677    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2678    /// these keys.
2679    ///
2680    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2681    #[must_use]
2682    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2683        self.meta = meta.into_option();
2684        self
2685    }
2686}
2687
2688/// A rename symbol suggestion.
2689#[serde_as]
2690#[skip_serializing_none]
2691#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2692#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2693#[serde(rename_all = "camelCase")]
2694#[non_exhaustive]
2695pub struct NesRenameSuggestion {
2696    /// Unique identifier for accept/reject tracking.
2697    pub suggestion_id: NesSuggestionId,
2698    /// The file URI containing the symbol.
2699    #[cfg_attr(feature = "schemars", schemars(url))]
2700    pub uri: String,
2701    /// The position of the symbol to rename.
2702    pub position: Position,
2703    /// The new name for the symbol.
2704    pub new_name: String,
2705    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2706    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2707    /// these keys.
2708    ///
2709    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2710    #[serde_as(deserialize_as = "DefaultOnError")]
2711    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2712    #[serde(default)]
2713    #[serde(rename = "_meta")]
2714    pub meta: Option<Meta>,
2715}
2716
2717impl NesRenameSuggestion {
2718    /// Builds [`NesRenameSuggestion`] with the required fields set; optional fields start unset or empty.
2719    #[must_use]
2720    pub fn new(
2721        suggestion_id: impl Into<NesSuggestionId>,
2722        uri: impl Into<String>,
2723        position: Position,
2724        new_name: impl Into<String>,
2725    ) -> Self {
2726        Self {
2727            suggestion_id: suggestion_id.into(),
2728            uri: uri.into(),
2729            position,
2730            new_name: new_name.into(),
2731            meta: None,
2732        }
2733    }
2734
2735    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2736    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2737    /// these keys.
2738    ///
2739    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2740    #[must_use]
2741    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2742        self.meta = meta.into_option();
2743        self
2744    }
2745}
2746
2747/// A search-and-replace suggestion.
2748#[serde_as]
2749#[skip_serializing_none]
2750#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2751#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2752#[serde(rename_all = "camelCase")]
2753#[non_exhaustive]
2754pub struct NesSearchAndReplaceSuggestion {
2755    /// Unique identifier for accept/reject tracking.
2756    pub suggestion_id: NesSuggestionId,
2757    /// The file URI to search within.
2758    #[cfg_attr(feature = "schemars", schemars(url))]
2759    pub uri: String,
2760    /// The text or pattern to find.
2761    pub search: String,
2762    /// The replacement text.
2763    pub replace: String,
2764    /// Whether `search` is a regular expression. Defaults to `false`.
2765    #[serde(default)]
2766    pub is_regex: Option<bool>,
2767    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2768    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2769    /// these keys.
2770    ///
2771    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2772    #[serde_as(deserialize_as = "DefaultOnError")]
2773    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2774    #[serde(default)]
2775    #[serde(rename = "_meta")]
2776    pub meta: Option<Meta>,
2777}
2778
2779impl NesSearchAndReplaceSuggestion {
2780    /// Builds [`NesSearchAndReplaceSuggestion`] with the required fields set; optional fields start unset or empty.
2781    #[must_use]
2782    pub fn new(
2783        suggestion_id: impl Into<NesSuggestionId>,
2784        uri: impl Into<String>,
2785        search: impl Into<String>,
2786        replace: impl Into<String>,
2787    ) -> Self {
2788        Self {
2789            suggestion_id: suggestion_id.into(),
2790            uri: uri.into(),
2791            search: search.into(),
2792            replace: replace.into(),
2793            is_regex: None,
2794            meta: None,
2795        }
2796    }
2797
2798    /// Sets or clears the optional `isRegex` field.
2799    #[must_use]
2800    pub fn is_regex(mut self, is_regex: impl IntoOption<bool>) -> Self {
2801        self.is_regex = is_regex.into_option();
2802        self
2803    }
2804
2805    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2806    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2807    /// these keys.
2808    ///
2809    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2810    #[must_use]
2811    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2812        self.meta = meta.into_option();
2813        self
2814    }
2815}
2816
2817// NES accept/reject notifications
2818
2819/// Notification sent when a suggestion is accepted.
2820#[serde_as]
2821#[skip_serializing_none]
2822#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2823#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2824#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_ACCEPT_METHOD_NAME)))]
2825#[serde(rename_all = "camelCase")]
2826#[non_exhaustive]
2827pub struct AcceptNesNotification {
2828    /// The session ID for this notification.
2829    pub session_id: SessionId,
2830    /// The ID of the accepted suggestion.
2831    pub suggestion_id: NesSuggestionId,
2832    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2833    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2834    /// these keys.
2835    ///
2836    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2837    #[serde_as(deserialize_as = "DefaultOnError")]
2838    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2839    #[serde(default)]
2840    #[serde(rename = "_meta")]
2841    pub meta: Option<Meta>,
2842}
2843
2844impl AcceptNesNotification {
2845    /// Builds [`AcceptNesNotification`] with the required notification fields set; optional fields start unset or empty.
2846    #[must_use]
2847    pub fn new(
2848        session_id: impl Into<SessionId>,
2849        suggestion_id: impl Into<NesSuggestionId>,
2850    ) -> Self {
2851        Self {
2852            session_id: session_id.into(),
2853            suggestion_id: suggestion_id.into(),
2854            meta: None,
2855        }
2856    }
2857
2858    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2859    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2860    /// these keys.
2861    ///
2862    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2863    #[must_use]
2864    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2865        self.meta = meta.into_option();
2866        self
2867    }
2868}
2869
2870/// Notification sent when a suggestion is rejected.
2871#[serde_as]
2872#[skip_serializing_none]
2873#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2874#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2875#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_REJECT_METHOD_NAME)))]
2876#[serde(rename_all = "camelCase")]
2877#[non_exhaustive]
2878pub struct RejectNesNotification {
2879    /// The session ID for this notification.
2880    pub session_id: SessionId,
2881    /// The ID of the rejected suggestion.
2882    pub suggestion_id: NesSuggestionId,
2883    /// The reason for rejection.
2884    #[serde_as(deserialize_as = "DefaultOnError")]
2885    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2886    #[serde(default)]
2887    pub reason: Option<NesRejectReason>,
2888    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2889    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2890    /// these keys.
2891    ///
2892    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2893    #[serde_as(deserialize_as = "DefaultOnError")]
2894    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2895    #[serde(default)]
2896    #[serde(rename = "_meta")]
2897    pub meta: Option<Meta>,
2898}
2899
2900impl RejectNesNotification {
2901    /// Builds [`RejectNesNotification`] with the required notification fields set; optional fields start unset or empty.
2902    #[must_use]
2903    pub fn new(
2904        session_id: impl Into<SessionId>,
2905        suggestion_id: impl Into<NesSuggestionId>,
2906    ) -> Self {
2907        Self {
2908            session_id: session_id.into(),
2909            suggestion_id: suggestion_id.into(),
2910            reason: None,
2911            meta: None,
2912        }
2913    }
2914
2915    /// Sets or clears the optional `reason` field.
2916    #[must_use]
2917    pub fn reason(mut self, reason: impl IntoOption<NesRejectReason>) -> Self {
2918        self.reason = reason.into_option();
2919        self
2920    }
2921
2922    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2923    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2924    /// these keys.
2925    ///
2926    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2927    #[must_use]
2928    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2929        self.meta = meta.into_option();
2930        self
2931    }
2932}
2933
2934/// The reason a suggestion was rejected.
2935#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2936#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2937#[non_exhaustive]
2938pub enum NesRejectReason {
2939    /// The user explicitly dismissed the suggestion.
2940    #[serde(rename = "rejected")]
2941    Rejected,
2942    /// The suggestion was shown but the user continued editing without interacting.
2943    #[serde(rename = "ignored")]
2944    Ignored,
2945    /// The suggestion was superseded by a newer suggestion.
2946    #[serde(rename = "replaced")]
2947    Replaced,
2948    /// The request was cancelled before the agent returned a response.
2949    #[serde(rename = "cancelled")]
2950    Cancelled,
2951    /// Custom or future rejection reason.
2952    ///
2953    /// Values beginning with `_` are reserved for implementation-specific
2954    /// extensions. Unknown values that do not begin with `_` are reserved for
2955    /// future ACP variants.
2956    #[serde(untagged)]
2957    Other(String),
2958}
2959
2960#[cfg(test)]
2961mod tests {
2962    use super::*;
2963    use serde_json::json;
2964
2965    #[test]
2966    fn test_position_encoding_kind_serialization() {
2967        assert_eq!(
2968            serde_json::to_value(&PositionEncodingKind::Utf16).unwrap(),
2969            json!("utf-16")
2970        );
2971        assert_eq!(
2972            serde_json::to_value(&PositionEncodingKind::Utf32).unwrap(),
2973            json!("utf-32")
2974        );
2975        assert_eq!(
2976            serde_json::to_value(&PositionEncodingKind::Utf8).unwrap(),
2977            json!("utf-8")
2978        );
2979
2980        assert_eq!(
2981            serde_json::from_value::<PositionEncodingKind>(json!("utf-16")).unwrap(),
2982            PositionEncodingKind::Utf16
2983        );
2984        assert_eq!(
2985            serde_json::from_value::<PositionEncodingKind>(json!("utf-32")).unwrap(),
2986            PositionEncodingKind::Utf32
2987        );
2988        assert_eq!(
2989            serde_json::from_value::<PositionEncodingKind>(json!("utf-8")).unwrap(),
2990            PositionEncodingKind::Utf8
2991        );
2992        assert!(serde_json::from_value::<PositionEncodingKind>(json!("_future")).is_err());
2993    }
2994
2995    #[test]
2996    fn test_client_capabilities_skip_unknown_position_encodings() {
2997        let caps: crate::v2::ClientCapabilities = serde_json::from_value(json!({
2998            "positionEncodings": ["_future", "utf-8", "utf-16"]
2999        }))
3000        .unwrap();
3001
3002        assert_eq!(
3003            caps.position_encodings,
3004            vec![PositionEncodingKind::Utf8, PositionEncodingKind::Utf16]
3005        );
3006    }
3007
3008    #[test]
3009    fn test_agent_nes_capabilities_serialization() {
3010        let caps = NesCapabilities::new()
3011            .events(
3012                NesEventCapabilities::new().document(
3013                    NesDocumentEventCapabilities::new()
3014                        .did_open(NesDocumentDidOpenCapabilities::default())
3015                        .did_change(NesDocumentDidChangeCapabilities::new(
3016                            TextDocumentSyncKind::Incremental,
3017                        ))
3018                        .did_close(NesDocumentDidCloseCapabilities::default())
3019                        .did_save(NesDocumentDidSaveCapabilities::default())
3020                        .did_focus(NesDocumentDidFocusCapabilities::default()),
3021                ),
3022            )
3023            .context(
3024                NesContextCapabilities::new()
3025                    .recent_files(NesRecentFilesCapabilities {
3026                        max_count: Some(10),
3027                        meta: None,
3028                    })
3029                    .related_snippets(NesRelatedSnippetsCapabilities::default())
3030                    .edit_history(NesEditHistoryCapabilities {
3031                        max_count: Some(6),
3032                        meta: None,
3033                    })
3034                    .user_actions(NesUserActionsCapabilities {
3035                        max_count: Some(16),
3036                        meta: None,
3037                    })
3038                    .open_files(NesOpenFilesCapabilities::default())
3039                    .diagnostics(NesDiagnosticsCapabilities::default()),
3040            );
3041
3042        let json = serde_json::to_value(&caps).unwrap();
3043        assert_eq!(
3044            json,
3045            json!({
3046                "events": {
3047                    "document": {
3048                        "didOpen": {},
3049                        "didChange": {
3050                            "syncKind": "incremental"
3051                        },
3052                        "didClose": {},
3053                        "didSave": {},
3054                        "didFocus": {}
3055                    }
3056                },
3057                "context": {
3058                    "recentFiles": {
3059                        "maxCount": 10
3060                    },
3061                    "relatedSnippets": {},
3062                    "editHistory": {
3063                        "maxCount": 6
3064                    },
3065                    "userActions": {
3066                        "maxCount": 16
3067                    },
3068                    "openFiles": {},
3069                    "diagnostics": {}
3070                }
3071            })
3072        );
3073
3074        // Round-trip
3075        let deserialized: NesCapabilities = serde_json::from_value(json).unwrap();
3076        assert_eq!(deserialized, caps);
3077    }
3078
3079    #[test]
3080    fn test_client_nes_capabilities_serialization() {
3081        let caps = ClientNesCapabilities::new()
3082            .jump(NesJumpCapabilities::default())
3083            .rename(NesRenameCapabilities::default())
3084            .search_and_replace(NesSearchAndReplaceCapabilities::default());
3085
3086        let json = serde_json::to_value(&caps).unwrap();
3087        assert_eq!(
3088            json,
3089            json!({
3090                "jump": {},
3091                "rename": {},
3092                "searchAndReplace": {}
3093            })
3094        );
3095
3096        let deserialized: ClientNesCapabilities = serde_json::from_value(json).unwrap();
3097        assert_eq!(deserialized, caps);
3098    }
3099
3100    #[test]
3101    fn test_document_did_open_serialization() {
3102        let notification = DidOpenDocumentNotification::new(
3103            "session_123",
3104            "file:///path/to/file.rs",
3105            "rust",
3106            1,
3107            "fn main() {\n    println!(\"hello\");\n}\n",
3108        );
3109
3110        let json = serde_json::to_value(&notification).unwrap();
3111        assert_eq!(
3112            json,
3113            json!({
3114                "sessionId": "session_123",
3115                "uri": "file:///path/to/file.rs",
3116                "languageId": "rust",
3117                "version": 1,
3118                "text": "fn main() {\n    println!(\"hello\");\n}\n"
3119            })
3120        );
3121
3122        let deserialized: DidOpenDocumentNotification = serde_json::from_value(json).unwrap();
3123        assert_eq!(deserialized, notification);
3124    }
3125
3126    #[test]
3127    fn test_document_did_change_incremental_serialization() {
3128        let notification = DidChangeDocumentNotification::new(
3129            "session_123",
3130            "file:///path/to/file.rs",
3131            2,
3132            vec![TextDocumentContentChangeEvent::incremental(
3133                Range::new(Position::new(1, 4), Position::new(1, 4)),
3134                "let x = 42;\n    ",
3135            )],
3136        );
3137
3138        let json = serde_json::to_value(&notification).unwrap();
3139        assert_eq!(
3140            json,
3141            json!({
3142                "sessionId": "session_123",
3143                "uri": "file:///path/to/file.rs",
3144                "version": 2,
3145                "contentChanges": [
3146                    {
3147                        "range": {
3148                            "start": { "line": 1, "character": 4 },
3149                            "end": { "line": 1, "character": 4 }
3150                        },
3151                        "text": "let x = 42;\n    "
3152                    }
3153                ]
3154            })
3155        );
3156    }
3157
3158    #[test]
3159    fn test_document_did_change_full_serialization() {
3160        let notification = DidChangeDocumentNotification::new(
3161            "session_123",
3162            "file:///path/to/file.rs",
3163            2,
3164            vec![TextDocumentContentChangeEvent::full(
3165                "fn main() {\n    let x = 42;\n    println!(\"hello\");\n}\n",
3166            )],
3167        );
3168
3169        let json = serde_json::to_value(&notification).unwrap();
3170        assert_eq!(
3171            json,
3172            json!({
3173                "sessionId": "session_123",
3174                "uri": "file:///path/to/file.rs",
3175                "version": 2,
3176                "contentChanges": [
3177                    {
3178                        "text": "fn main() {\n    let x = 42;\n    println!(\"hello\");\n}\n"
3179                    }
3180                ]
3181            })
3182        );
3183    }
3184
3185    #[test]
3186    fn test_document_did_close_serialization() {
3187        let notification =
3188            DidCloseDocumentNotification::new("session_123", "file:///path/to/file.rs");
3189        let json = serde_json::to_value(&notification).unwrap();
3190        assert_eq!(
3191            json,
3192            json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
3193        );
3194    }
3195
3196    #[test]
3197    fn test_document_did_save_serialization() {
3198        let notification =
3199            DidSaveDocumentNotification::new("session_123", "file:///path/to/file.rs");
3200        let json = serde_json::to_value(&notification).unwrap();
3201        assert_eq!(
3202            json,
3203            json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
3204        );
3205    }
3206
3207    #[test]
3208    fn test_document_did_focus_serialization() {
3209        let notification = DidFocusDocumentNotification::new(
3210            "session_123",
3211            "file:///path/to/file.rs",
3212            2,
3213            Position::new(5, 12),
3214            Range::new(Position::new(0, 0), Position::new(45, 0)),
3215        );
3216
3217        let json = serde_json::to_value(&notification).unwrap();
3218        assert_eq!(
3219            json,
3220            json!({
3221                "sessionId": "session_123",
3222                "uri": "file:///path/to/file.rs",
3223                "version": 2,
3224                "position": { "line": 5, "character": 12 },
3225                "visibleRange": {
3226                    "start": { "line": 0, "character": 0 },
3227                    "end": { "line": 45, "character": 0 }
3228                }
3229            })
3230        );
3231    }
3232
3233    #[test]
3234    fn test_nes_suggestion_edit_serialization() {
3235        let suggestion = NesSuggestion::Edit(
3236            NesEditSuggestion::new(
3237                "sugg_001",
3238                "file:///path/to/other_file.rs",
3239                vec![NesTextEdit::new(
3240                    Range::new(Position::new(5, 0), Position::new(5, 10)),
3241                    "let result = helper();",
3242                )],
3243            )
3244            .cursor_position(Position::new(5, 22)),
3245        );
3246
3247        let json = serde_json::to_value(&suggestion).unwrap();
3248        assert_eq!(
3249            json,
3250            json!({
3251                "kind": "edit",
3252                "suggestionId": "sugg_001",
3253                "uri": "file:///path/to/other_file.rs",
3254                "edits": [
3255                    {
3256                        "range": {
3257                            "start": { "line": 5, "character": 0 },
3258                            "end": { "line": 5, "character": 10 }
3259                        },
3260                        "newText": "let result = helper();"
3261                    }
3262                ],
3263                "cursorPosition": { "line": 5, "character": 22 }
3264            })
3265        );
3266
3267        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3268        assert_eq!(deserialized, suggestion);
3269    }
3270
3271    #[test]
3272    fn test_nes_suggestion_unknown_variant() {
3273        let suggestion: NesSuggestion = serde_json::from_value(json!({
3274            "kind": "_preview",
3275            "suggestionId": "sugg_001",
3276            "label": "Preview generated file"
3277        }))
3278        .unwrap();
3279
3280        let NesSuggestion::Other(unknown) = suggestion else {
3281            panic!("expected unknown NES suggestion");
3282        };
3283
3284        assert_eq!(unknown.kind, "_preview");
3285        assert_eq!(unknown.suggestion_id.to_string(), "sugg_001");
3286        assert!(!unknown.fields.contains_key("suggestionId"));
3287        assert_eq!(
3288            serde_json::to_value(NesSuggestion::Other(unknown)).unwrap(),
3289            json!({
3290                "kind": "_preview",
3291                "suggestionId": "sugg_001",
3292                "label": "Preview generated file"
3293            })
3294        );
3295    }
3296
3297    #[test]
3298    fn test_nes_suggestion_unknown_does_not_hide_malformed_known_variant() {
3299        assert!(
3300            serde_json::from_value::<NesSuggestion>(json!({
3301                "kind": "edit"
3302            }))
3303            .is_err()
3304        );
3305    }
3306
3307    #[test]
3308    fn test_nes_suggestion_jump_serialization() {
3309        let suggestion = NesSuggestion::Jump(NesJumpSuggestion::new(
3310            "sugg_002",
3311            "file:///path/to/other_file.rs",
3312            Position::new(15, 4),
3313        ));
3314
3315        let json = serde_json::to_value(&suggestion).unwrap();
3316        assert_eq!(
3317            json,
3318            json!({
3319                "kind": "jump",
3320                "suggestionId": "sugg_002",
3321                "uri": "file:///path/to/other_file.rs",
3322                "position": { "line": 15, "character": 4 }
3323            })
3324        );
3325
3326        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3327        assert_eq!(deserialized, suggestion);
3328    }
3329
3330    #[test]
3331    fn test_nes_suggestion_rename_serialization() {
3332        let suggestion = NesSuggestion::Rename(NesRenameSuggestion::new(
3333            "sugg_003",
3334            "file:///path/to/file.rs",
3335            Position::new(5, 10),
3336            "calculateTotal",
3337        ));
3338
3339        let json = serde_json::to_value(&suggestion).unwrap();
3340        assert_eq!(
3341            json,
3342            json!({
3343                "kind": "rename",
3344                "suggestionId": "sugg_003",
3345                "uri": "file:///path/to/file.rs",
3346                "position": { "line": 5, "character": 10 },
3347                "newName": "calculateTotal"
3348            })
3349        );
3350
3351        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3352        assert_eq!(deserialized, suggestion);
3353    }
3354
3355    #[test]
3356    fn test_nes_suggestion_search_and_replace_serialization() {
3357        let suggestion = NesSuggestion::SearchAndReplace(
3358            NesSearchAndReplaceSuggestion::new(
3359                "sugg_004",
3360                "file:///path/to/file.rs",
3361                "oldFunction",
3362                "newFunction",
3363            )
3364            .is_regex(false),
3365        );
3366
3367        let json = serde_json::to_value(&suggestion).unwrap();
3368        assert_eq!(
3369            json,
3370            json!({
3371                "kind": "searchAndReplace",
3372                "suggestionId": "sugg_004",
3373                "uri": "file:///path/to/file.rs",
3374                "search": "oldFunction",
3375                "replace": "newFunction",
3376                "isRegex": false
3377            })
3378        );
3379
3380        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3381        assert_eq!(deserialized, suggestion);
3382    }
3383
3384    #[test]
3385    fn test_nes_start_request_serialization() {
3386        let request = StartNesRequest::new()
3387            .workspace_uri("file:///Users/alice/projects/my-app")
3388            .workspace_folders(vec![WorkspaceFolder::new(
3389                "file:///Users/alice/projects/my-app",
3390                "my-app",
3391            )])
3392            .repository(NesRepository::new(
3393                "my-app",
3394                "alice",
3395                "https://github.com/alice/my-app.git",
3396            ));
3397
3398        let json = serde_json::to_value(&request).unwrap();
3399        assert_eq!(
3400            json,
3401            json!({
3402                "workspaceUri": "file:///Users/alice/projects/my-app",
3403                "workspaceFolders": [
3404                    {
3405                        "uri": "file:///Users/alice/projects/my-app",
3406                        "name": "my-app"
3407                    }
3408                ],
3409                "repository": {
3410                    "name": "my-app",
3411                    "owner": "alice",
3412                    "remoteUrl": "https://github.com/alice/my-app.git"
3413                }
3414            })
3415        );
3416    }
3417
3418    #[test]
3419    fn test_nes_start_response_serialization() {
3420        let response = StartNesResponse::new("session_abc123");
3421        let json = serde_json::to_value(&response).unwrap();
3422        assert_eq!(json, json!({ "sessionId": "session_abc123" }));
3423    }
3424
3425    #[test]
3426    fn test_nes_trigger_kind_serialization() {
3427        assert_eq!(
3428            serde_json::to_value(&NesTriggerKind::Automatic).unwrap(),
3429            json!("automatic")
3430        );
3431        assert_eq!(
3432            serde_json::to_value(&NesTriggerKind::Diagnostic).unwrap(),
3433            json!("diagnostic")
3434        );
3435        assert_eq!(
3436            serde_json::to_value(&NesTriggerKind::Manual).unwrap(),
3437            json!("manual")
3438        );
3439    }
3440
3441    #[test]
3442    fn test_nes_reject_reason_serialization() {
3443        assert_eq!(
3444            serde_json::to_value(&NesRejectReason::Rejected).unwrap(),
3445            json!("rejected")
3446        );
3447        assert_eq!(
3448            serde_json::to_value(&NesRejectReason::Ignored).unwrap(),
3449            json!("ignored")
3450        );
3451        assert_eq!(
3452            serde_json::to_value(&NesRejectReason::Replaced).unwrap(),
3453            json!("replaced")
3454        );
3455        assert_eq!(
3456            serde_json::to_value(&NesRejectReason::Cancelled).unwrap(),
3457            json!("cancelled")
3458        );
3459    }
3460
3461    #[test]
3462    fn test_nes_accept_notification_serialization() {
3463        let notification = AcceptNesNotification::new("session_123", "sugg_001");
3464        let json = serde_json::to_value(&notification).unwrap();
3465        assert_eq!(
3466            json,
3467            json!({ "sessionId": "session_123", "suggestionId": "sugg_001" })
3468        );
3469    }
3470
3471    #[test]
3472    fn test_nes_reject_notification_serialization() {
3473        let notification =
3474            RejectNesNotification::new("session_123", "sugg_001").reason(NesRejectReason::Rejected);
3475        let json = serde_json::to_value(&notification).unwrap();
3476        assert_eq!(
3477            json,
3478            json!({ "sessionId": "session_123", "suggestionId": "sugg_001", "reason": "rejected" })
3479        );
3480    }
3481
3482    #[test]
3483    fn test_nes_suggest_request_with_context_serialization() {
3484        let request = SuggestNesRequest::new(
3485            "session_123",
3486            "file:///path/to/file.rs",
3487            2,
3488            Position::new(5, 12),
3489            NesTriggerKind::Automatic,
3490        )
3491        .selection(Range::new(Position::new(5, 4), Position::new(5, 12)))
3492        .context(
3493            NesSuggestContext::new()
3494                .recent_files(vec![NesRecentFile::new(
3495                    "file:///path/to/utils.rs",
3496                    "rust",
3497                    "pub fn helper() -> i32 { 42 }\n",
3498                )])
3499                .diagnostics(vec![NesDiagnostic::new(
3500                    "file:///path/to/file.rs",
3501                    Range::new(Position::new(5, 0), Position::new(5, 10)),
3502                    NesDiagnosticSeverity::Error,
3503                    "cannot find value `foo` in this scope",
3504                )]),
3505        );
3506
3507        let json = serde_json::to_value(&request).unwrap();
3508        assert_eq!(json["sessionId"], "session_123");
3509        assert_eq!(json["uri"], "file:///path/to/file.rs");
3510        assert_eq!(json["version"], 2);
3511        assert_eq!(json["triggerKind"], "automatic");
3512        assert_eq!(
3513            json["context"]["recentFiles"][0]["uri"],
3514            "file:///path/to/utils.rs"
3515        );
3516        assert_eq!(json["context"]["diagnostics"][0]["severity"], "error");
3517    }
3518
3519    #[test]
3520    fn test_text_document_sync_kind_serialization() {
3521        assert_eq!(
3522            serde_json::to_value(&TextDocumentSyncKind::Full).unwrap(),
3523            json!("full")
3524        );
3525        assert_eq!(
3526            serde_json::to_value(&TextDocumentSyncKind::Incremental).unwrap(),
3527            json!("incremental")
3528        );
3529        assert!(serde_json::from_value::<TextDocumentSyncKind>(json!("_future")).is_err());
3530    }
3531
3532    #[test]
3533    fn test_document_event_capabilities_drop_unknown_did_change_sync_kind() {
3534        let caps: NesDocumentEventCapabilities = serde_json::from_value(json!({
3535            "didChange": {
3536                "syncKind": "_future"
3537            }
3538        }))
3539        .unwrap();
3540
3541        assert_eq!(caps.did_change, None);
3542    }
3543
3544    #[test]
3545    fn test_document_did_change_capabilities_requires_sync_kind() {
3546        assert!(serde_json::from_value::<NesDocumentDidChangeCapabilities>(json!({})).is_err());
3547    }
3548
3549    #[test]
3550    fn test_nes_suggest_response_serialization() {
3551        let response = SuggestNesResponse::new(vec![
3552            NesSuggestion::Edit(NesEditSuggestion::new(
3553                "sugg_001",
3554                "file:///path/to/file.rs",
3555                vec![NesTextEdit::new(
3556                    Range::new(Position::new(5, 0), Position::new(5, 10)),
3557                    "let result = helper();",
3558                )],
3559            )),
3560            NesSuggestion::Jump(NesJumpSuggestion::new(
3561                "sugg_002",
3562                "file:///path/to/other.rs",
3563                Position::new(10, 0),
3564            )),
3565        ]);
3566
3567        let json = serde_json::to_value(&response).unwrap();
3568        assert_eq!(json["suggestions"].as_array().unwrap().len(), 2);
3569        assert_eq!(json["suggestions"][0]["kind"], "edit");
3570        assert_eq!(json["suggestions"][1]["kind"], "jump");
3571    }
3572}