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
1396/// Request to start an NES session.
1397#[serde_as]
1398#[skip_serializing_none]
1399#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1400#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1401#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME)))]
1402#[serde(rename_all = "camelCase")]
1403#[non_exhaustive]
1404pub struct StartNesRequest {
1405    /// The root URI of the workspace.
1406    #[serde_as(deserialize_as = "DefaultOnError")]
1407    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1408    #[cfg_attr(feature = "schemars", schemars(url))]
1409    #[serde(default)]
1410    pub workspace_uri: Option<String>,
1411    /// The workspace folders.
1412    #[serde(default)]
1413    pub workspace_folders: Option<Vec<WorkspaceFolder>>,
1414    /// Repository metadata, if the workspace is a git repository.
1415    #[serde_as(deserialize_as = "DefaultOnError")]
1416    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1417    #[serde(default)]
1418    pub repository: Option<NesRepository>,
1419    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1420    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1421    /// these keys.
1422    ///
1423    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1424    #[serde_as(deserialize_as = "DefaultOnError")]
1425    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1426    #[serde(default)]
1427    #[serde(rename = "_meta")]
1428    pub meta: Option<Meta>,
1429}
1430
1431impl StartNesRequest {
1432    /// Builds [`StartNesRequest`] with the required request fields set; optional fields start unset or empty.
1433    #[must_use]
1434    pub fn new() -> Self {
1435        Self {
1436            workspace_uri: None,
1437            workspace_folders: None,
1438            repository: None,
1439            meta: None,
1440        }
1441    }
1442
1443    /// Sets or clears the optional `workspaceUri` field.
1444    #[must_use]
1445    pub fn workspace_uri(mut self, workspace_uri: impl IntoOption<String>) -> Self {
1446        self.workspace_uri = workspace_uri.into_option();
1447        self
1448    }
1449
1450    /// Sets or clears the optional `workspaceFolders` field.
1451    #[must_use]
1452    pub fn workspace_folders(
1453        mut self,
1454        workspace_folders: impl IntoOption<Vec<WorkspaceFolder>>,
1455    ) -> Self {
1456        self.workspace_folders = workspace_folders.into_option();
1457        self
1458    }
1459
1460    /// Sets or clears the optional `repository` field.
1461    #[must_use]
1462    pub fn repository(mut self, repository: impl IntoOption<NesRepository>) -> Self {
1463        self.repository = repository.into_option();
1464        self
1465    }
1466
1467    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1468    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1469    /// these keys.
1470    ///
1471    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1472    #[must_use]
1473    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1474        self.meta = meta.into_option();
1475        self
1476    }
1477}
1478
1479impl Default for StartNesRequest {
1480    fn default() -> Self {
1481        Self::new()
1482    }
1483}
1484
1485/// A workspace folder.
1486#[serde_as]
1487#[skip_serializing_none]
1488#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1489#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1490#[serde(rename_all = "camelCase")]
1491#[non_exhaustive]
1492pub struct WorkspaceFolder {
1493    /// The URI of the folder.
1494    #[cfg_attr(feature = "schemars", schemars(url))]
1495    pub uri: String,
1496    /// The display name of the folder.
1497    pub name: String,
1498    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1499    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1500    /// these keys.
1501    ///
1502    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1503    #[serde_as(deserialize_as = "DefaultOnError")]
1504    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1505    #[serde(default)]
1506    #[serde(rename = "_meta")]
1507    pub meta: Option<Meta>,
1508}
1509
1510impl WorkspaceFolder {
1511    /// Builds [`WorkspaceFolder`] with the required fields set; optional fields start unset or empty.
1512    #[must_use]
1513    pub fn new(uri: impl Into<String>, name: impl Into<String>) -> Self {
1514        Self {
1515            uri: uri.into(),
1516            name: name.into(),
1517            meta: None,
1518        }
1519    }
1520
1521    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1522    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1523    /// these keys.
1524    ///
1525    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1526    #[must_use]
1527    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1528        self.meta = meta.into_option();
1529        self
1530    }
1531}
1532
1533/// Repository metadata for an NES session.
1534#[serde_as]
1535#[skip_serializing_none]
1536#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1537#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1538#[serde(rename_all = "camelCase")]
1539#[non_exhaustive]
1540pub struct NesRepository {
1541    /// The repository name.
1542    pub name: String,
1543    /// The repository owner.
1544    pub owner: String,
1545    /// The remote URL of the repository.
1546    pub remote_url: String,
1547    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1548    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1549    /// these keys.
1550    ///
1551    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1552    #[serde_as(deserialize_as = "DefaultOnError")]
1553    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1554    #[serde(default)]
1555    #[serde(rename = "_meta")]
1556    pub meta: Option<Meta>,
1557}
1558
1559impl NesRepository {
1560    /// Builds [`NesRepository`] with the required fields set; optional fields start unset or empty.
1561    #[must_use]
1562    pub fn new(
1563        name: impl Into<String>,
1564        owner: impl Into<String>,
1565        remote_url: impl Into<String>,
1566    ) -> Self {
1567        Self {
1568            name: name.into(),
1569            owner: owner.into(),
1570            remote_url: remote_url.into(),
1571            meta: None,
1572        }
1573    }
1574
1575    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1576    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1577    /// these keys.
1578    ///
1579    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1580    #[must_use]
1581    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1582        self.meta = meta.into_option();
1583        self
1584    }
1585}
1586
1587/// Response to `nes/start`.
1588#[serde_as]
1589#[skip_serializing_none]
1590#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1591#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1592#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_START_METHOD_NAME)))]
1593#[serde(rename_all = "camelCase")]
1594#[non_exhaustive]
1595pub struct StartNesResponse {
1596    /// The session ID for the newly started NES session.
1597    pub session_id: SessionId,
1598    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1599    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1600    /// these keys.
1601    ///
1602    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1603    #[serde_as(deserialize_as = "DefaultOnError")]
1604    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1605    #[serde(default)]
1606    #[serde(rename = "_meta")]
1607    pub meta: Option<Meta>,
1608}
1609
1610impl StartNesResponse {
1611    /// Builds [`StartNesResponse`] with the required response fields set; optional fields start unset or empty.
1612    #[must_use]
1613    pub fn new(session_id: impl Into<SessionId>) -> Self {
1614        Self {
1615            session_id: session_id.into(),
1616            meta: None,
1617        }
1618    }
1619
1620    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1621    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1622    /// these keys.
1623    ///
1624    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1625    #[must_use]
1626    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1627        self.meta = meta.into_option();
1628        self
1629    }
1630}
1631
1632// NES session close
1633
1634/// Request to close an NES session.
1635///
1636/// The agent **must** cancel any ongoing work related to the NES session
1637/// and then free up any resources associated with the session.
1638#[serde_as]
1639#[skip_serializing_none]
1640#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1641#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1642#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME)))]
1643#[serde(rename_all = "camelCase")]
1644#[non_exhaustive]
1645pub struct CloseNesRequest {
1646    /// The ID of the NES session to close.
1647    pub session_id: SessionId,
1648    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1649    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1650    /// these keys.
1651    ///
1652    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1653    #[serde_as(deserialize_as = "DefaultOnError")]
1654    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1655    #[serde(default)]
1656    #[serde(rename = "_meta")]
1657    pub meta: Option<Meta>,
1658}
1659
1660impl CloseNesRequest {
1661    /// Builds [`CloseNesRequest`] with the required request fields set; optional fields start unset or empty.
1662    #[must_use]
1663    pub fn new(session_id: impl Into<SessionId>) -> Self {
1664        Self {
1665            session_id: session_id.into(),
1666            meta: None,
1667        }
1668    }
1669
1670    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1671    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1672    /// these keys.
1673    ///
1674    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1675    #[must_use]
1676    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1677        self.meta = meta.into_option();
1678        self
1679    }
1680}
1681
1682/// Response from closing an NES session.
1683#[serde_as]
1684#[skip_serializing_none]
1685#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1686#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1687#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_CLOSE_METHOD_NAME)))]
1688#[serde(rename_all = "camelCase")]
1689#[non_exhaustive]
1690pub struct CloseNesResponse {
1691    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1692    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1693    /// these keys.
1694    ///
1695    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1696    #[serde_as(deserialize_as = "DefaultOnError")]
1697    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1698    #[serde(default)]
1699    #[serde(rename = "_meta")]
1700    pub meta: Option<Meta>,
1701}
1702
1703impl CloseNesResponse {
1704    /// Builds [`CloseNesResponse`] with the required response fields set; optional fields start unset or empty.
1705    #[must_use]
1706    pub fn new() -> Self {
1707        Self::default()
1708    }
1709
1710    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1711    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1712    /// these keys.
1713    ///
1714    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1715    #[must_use]
1716    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1717        self.meta = meta.into_option();
1718        self
1719    }
1720}
1721
1722// NES suggest request
1723
1724/// What triggered the suggestion request.
1725#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1726#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1727#[non_exhaustive]
1728pub enum NesTriggerKind {
1729    /// Triggered by user typing or cursor movement.
1730    #[serde(rename = "automatic")]
1731    Automatic,
1732    /// Triggered by a diagnostic appearing at or near the cursor.
1733    #[serde(rename = "diagnostic")]
1734    Diagnostic,
1735    /// Triggered by an explicit user action (keyboard shortcut).
1736    #[serde(rename = "manual")]
1737    Manual,
1738    /// Custom or future suggestion trigger kind.
1739    ///
1740    /// Values beginning with `_` are reserved for implementation-specific
1741    /// extensions. Unknown values that do not begin with `_` are reserved for
1742    /// future ACP variants.
1743    #[serde(untagged)]
1744    Other(String),
1745}
1746
1747/// Request for a code suggestion.
1748#[serde_as]
1749#[skip_serializing_none]
1750#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1751#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1752#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME)))]
1753#[serde(rename_all = "camelCase")]
1754#[non_exhaustive]
1755pub struct SuggestNesRequest {
1756    /// The session ID for this request.
1757    pub session_id: SessionId,
1758    /// The URI of the document to suggest for.
1759    #[cfg_attr(feature = "schemars", schemars(url))]
1760    pub uri: String,
1761    /// The version number of the document.
1762    pub version: i64,
1763    /// The current cursor position.
1764    pub position: Position,
1765    /// The current text selection range, if any.
1766    #[serde(default)]
1767    pub selection: Option<Range>,
1768    /// What triggered this suggestion request.
1769    pub trigger_kind: NesTriggerKind,
1770    /// Context for the suggestion, included based on agent capabilities.
1771    #[serde(default)]
1772    pub context: Option<NesSuggestContext>,
1773    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1774    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1775    /// these keys.
1776    ///
1777    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1778    #[serde_as(deserialize_as = "DefaultOnError")]
1779    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1780    #[serde(default)]
1781    #[serde(rename = "_meta")]
1782    pub meta: Option<Meta>,
1783}
1784
1785impl SuggestNesRequest {
1786    /// Builds [`SuggestNesRequest`] with the required request fields set; optional fields start unset or empty.
1787    #[must_use]
1788    pub fn new(
1789        session_id: impl Into<SessionId>,
1790        uri: impl Into<String>,
1791        version: i64,
1792        position: Position,
1793        trigger_kind: NesTriggerKind,
1794    ) -> Self {
1795        Self {
1796            session_id: session_id.into(),
1797            uri: uri.into(),
1798            version,
1799            position,
1800            selection: None,
1801            trigger_kind,
1802            context: None,
1803            meta: None,
1804        }
1805    }
1806
1807    /// Sets or clears the optional `selection` field.
1808    #[must_use]
1809    pub fn selection(mut self, selection: impl IntoOption<Range>) -> Self {
1810        self.selection = selection.into_option();
1811        self
1812    }
1813
1814    /// Sets or clears the optional `context` field.
1815    #[must_use]
1816    pub fn context(mut self, context: impl IntoOption<NesSuggestContext>) -> Self {
1817        self.context = context.into_option();
1818        self
1819    }
1820
1821    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1822    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1823    /// these keys.
1824    ///
1825    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1826    #[must_use]
1827    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1828        self.meta = meta.into_option();
1829        self
1830    }
1831}
1832
1833/// Context attached to a suggestion request.
1834#[serde_as]
1835#[skip_serializing_none]
1836#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1837#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1838#[serde(rename_all = "camelCase")]
1839#[non_exhaustive]
1840pub struct NesSuggestContext {
1841    /// Recently accessed files.
1842    #[serde(default)]
1843    pub recent_files: Option<Vec<NesRecentFile>>,
1844    /// Related code snippets.
1845    #[serde(default)]
1846    pub related_snippets: Option<Vec<NesRelatedSnippet>>,
1847    /// Recent edit history.
1848    #[serde(default)]
1849    pub edit_history: Option<Vec<NesEditHistoryEntry>>,
1850    /// Recent user actions (typing, navigation, etc.).
1851    #[serde(default)]
1852    pub user_actions: Option<Vec<NesUserAction>>,
1853    /// Currently open files in the editor.
1854    #[serde(default)]
1855    pub open_files: Option<Vec<NesOpenFile>>,
1856    /// Current diagnostics (errors, warnings).
1857    #[serde(default)]
1858    pub diagnostics: Option<Vec<NesDiagnostic>>,
1859    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1860    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1861    /// these keys.
1862    ///
1863    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1864    #[serde_as(deserialize_as = "DefaultOnError")]
1865    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1866    #[serde(default)]
1867    #[serde(rename = "_meta")]
1868    pub meta: Option<Meta>,
1869}
1870
1871impl NesSuggestContext {
1872    /// Builds [`NesSuggestContext`] with the required fields set; optional fields start unset or empty.
1873    #[must_use]
1874    pub fn new() -> Self {
1875        Self::default()
1876    }
1877
1878    /// Sets or clears the optional `recentFiles` field.
1879    #[must_use]
1880    pub fn recent_files(mut self, recent_files: impl IntoOption<Vec<NesRecentFile>>) -> Self {
1881        self.recent_files = recent_files.into_option();
1882        self
1883    }
1884
1885    /// Sets or clears the optional `relatedSnippets` field.
1886    #[must_use]
1887    pub fn related_snippets(
1888        mut self,
1889        related_snippets: impl IntoOption<Vec<NesRelatedSnippet>>,
1890    ) -> Self {
1891        self.related_snippets = related_snippets.into_option();
1892        self
1893    }
1894
1895    /// Sets or clears the optional `editHistory` field.
1896    #[must_use]
1897    pub fn edit_history(mut self, edit_history: impl IntoOption<Vec<NesEditHistoryEntry>>) -> Self {
1898        self.edit_history = edit_history.into_option();
1899        self
1900    }
1901
1902    /// Sets or clears the optional `userActions` field.
1903    #[must_use]
1904    pub fn user_actions(mut self, user_actions: impl IntoOption<Vec<NesUserAction>>) -> Self {
1905        self.user_actions = user_actions.into_option();
1906        self
1907    }
1908
1909    /// Sets or clears the optional `openFiles` field.
1910    #[must_use]
1911    pub fn open_files(mut self, open_files: impl IntoOption<Vec<NesOpenFile>>) -> Self {
1912        self.open_files = open_files.into_option();
1913        self
1914    }
1915
1916    /// Sets or clears the optional `diagnostics` field.
1917    #[must_use]
1918    pub fn diagnostics(mut self, diagnostics: impl IntoOption<Vec<NesDiagnostic>>) -> Self {
1919        self.diagnostics = diagnostics.into_option();
1920        self
1921    }
1922
1923    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1924    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1925    /// these keys.
1926    ///
1927    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1928    #[must_use]
1929    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1930        self.meta = meta.into_option();
1931        self
1932    }
1933}
1934
1935/// A recently accessed file.
1936#[serde_as]
1937#[skip_serializing_none]
1938#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1939#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1940#[serde(rename_all = "camelCase")]
1941#[non_exhaustive]
1942pub struct NesRecentFile {
1943    /// The URI of the file.
1944    #[cfg_attr(feature = "schemars", schemars(url))]
1945    pub uri: String,
1946    /// The language identifier.
1947    pub language_id: String,
1948    /// The full text content of the file.
1949    pub text: String,
1950    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1951    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1952    /// these keys.
1953    ///
1954    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1955    #[serde_as(deserialize_as = "DefaultOnError")]
1956    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
1957    #[serde(default)]
1958    #[serde(rename = "_meta")]
1959    pub meta: Option<Meta>,
1960}
1961
1962impl NesRecentFile {
1963    /// Builds [`NesRecentFile`] with the required fields set; optional fields start unset or empty.
1964    #[must_use]
1965    pub fn new(
1966        uri: impl Into<String>,
1967        language_id: impl Into<String>,
1968        text: impl Into<String>,
1969    ) -> Self {
1970        Self {
1971            uri: uri.into(),
1972            language_id: language_id.into(),
1973            text: text.into(),
1974            meta: None,
1975        }
1976    }
1977
1978    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
1979    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
1980    /// these keys.
1981    ///
1982    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
1983    #[must_use]
1984    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
1985        self.meta = meta.into_option();
1986        self
1987    }
1988}
1989
1990/// A related code snippet from a file.
1991#[serde_as]
1992#[skip_serializing_none]
1993#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
1994#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
1995#[serde(rename_all = "camelCase")]
1996#[non_exhaustive]
1997pub struct NesRelatedSnippet {
1998    /// The URI of the file containing the snippets.
1999    #[cfg_attr(feature = "schemars", schemars(url))]
2000    pub uri: String,
2001    /// The code excerpts.
2002    pub excerpts: Vec<NesExcerpt>,
2003    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2004    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2005    /// these keys.
2006    ///
2007    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2008    #[serde_as(deserialize_as = "DefaultOnError")]
2009    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2010    #[serde(default)]
2011    #[serde(rename = "_meta")]
2012    pub meta: Option<Meta>,
2013}
2014
2015impl NesRelatedSnippet {
2016    /// Builds [`NesRelatedSnippet`] with the required fields set; optional fields start unset or empty.
2017    #[must_use]
2018    pub fn new(uri: impl Into<String>, excerpts: Vec<NesExcerpt>) -> Self {
2019        Self {
2020            uri: uri.into(),
2021            excerpts,
2022            meta: None,
2023        }
2024    }
2025
2026    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2027    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2028    /// these keys.
2029    ///
2030    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2031    #[must_use]
2032    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2033        self.meta = meta.into_option();
2034        self
2035    }
2036}
2037
2038/// A code excerpt from a file.
2039#[serde_as]
2040#[skip_serializing_none]
2041#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2042#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2043#[serde(rename_all = "camelCase")]
2044#[non_exhaustive]
2045pub struct NesExcerpt {
2046    /// The start line of the excerpt (zero-based).
2047    pub start_line: u32,
2048    /// The end line of the excerpt (zero-based).
2049    pub end_line: u32,
2050    /// The text content of the excerpt.
2051    pub text: String,
2052    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2053    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2054    /// these keys.
2055    ///
2056    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2057    #[serde_as(deserialize_as = "DefaultOnError")]
2058    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2059    #[serde(default)]
2060    #[serde(rename = "_meta")]
2061    pub meta: Option<Meta>,
2062}
2063
2064impl NesExcerpt {
2065    /// Builds [`NesExcerpt`] with the required fields set; optional fields start unset or empty.
2066    #[must_use]
2067    pub fn new(start_line: u32, end_line: u32, text: impl Into<String>) -> Self {
2068        Self {
2069            start_line,
2070            end_line,
2071            text: text.into(),
2072            meta: None,
2073        }
2074    }
2075
2076    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2077    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2078    /// these keys.
2079    ///
2080    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2081    #[must_use]
2082    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2083        self.meta = meta.into_option();
2084        self
2085    }
2086}
2087
2088/// An entry in the edit history.
2089#[serde_as]
2090#[skip_serializing_none]
2091#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2092#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2093#[serde(rename_all = "camelCase")]
2094#[non_exhaustive]
2095pub struct NesEditHistoryEntry {
2096    /// The URI of the edited file.
2097    #[cfg_attr(feature = "schemars", schemars(url))]
2098    pub uri: String,
2099    /// A diff representing the edit.
2100    pub diff: String,
2101    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2102    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2103    /// these keys.
2104    ///
2105    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2106    #[serde_as(deserialize_as = "DefaultOnError")]
2107    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2108    #[serde(default)]
2109    #[serde(rename = "_meta")]
2110    pub meta: Option<Meta>,
2111}
2112
2113impl NesEditHistoryEntry {
2114    /// Builds [`NesEditHistoryEntry`] with the required fields set; optional fields start unset or empty.
2115    #[must_use]
2116    pub fn new(uri: impl Into<String>, diff: impl Into<String>) -> Self {
2117        Self {
2118            uri: uri.into(),
2119            diff: diff.into(),
2120            meta: None,
2121        }
2122    }
2123
2124    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2125    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2126    /// these keys.
2127    ///
2128    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2129    #[must_use]
2130    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2131        self.meta = meta.into_option();
2132        self
2133    }
2134}
2135
2136/// A user action (typing, cursor movement, etc.).
2137#[serde_as]
2138#[skip_serializing_none]
2139#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2140#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2141#[serde(rename_all = "camelCase")]
2142#[non_exhaustive]
2143pub struct NesUserAction {
2144    /// The kind of action (e.g., "insertChar", "cursorMovement").
2145    pub action: String,
2146    /// The URI of the file where the action occurred.
2147    #[cfg_attr(feature = "schemars", schemars(url))]
2148    pub uri: String,
2149    /// The position where the action occurred.
2150    pub position: Position,
2151    /// Timestamp in milliseconds since epoch.
2152    pub timestamp_ms: u64,
2153    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2154    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2155    /// these keys.
2156    ///
2157    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2158    #[serde_as(deserialize_as = "DefaultOnError")]
2159    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2160    #[serde(default)]
2161    #[serde(rename = "_meta")]
2162    pub meta: Option<Meta>,
2163}
2164
2165impl NesUserAction {
2166    /// Builds [`NesUserAction`] with the required fields set; optional fields start unset or empty.
2167    #[must_use]
2168    pub fn new(
2169        action: impl Into<String>,
2170        uri: impl Into<String>,
2171        position: Position,
2172        timestamp_ms: u64,
2173    ) -> Self {
2174        Self {
2175            action: action.into(),
2176            uri: uri.into(),
2177            position,
2178            timestamp_ms,
2179            meta: None,
2180        }
2181    }
2182
2183    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2184    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2185    /// these keys.
2186    ///
2187    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2188    #[must_use]
2189    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2190        self.meta = meta.into_option();
2191        self
2192    }
2193}
2194
2195/// An open file in the editor.
2196#[serde_as]
2197#[skip_serializing_none]
2198#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2199#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2200#[serde(rename_all = "camelCase")]
2201#[non_exhaustive]
2202pub struct NesOpenFile {
2203    /// The URI of the file.
2204    #[cfg_attr(feature = "schemars", schemars(url))]
2205    pub uri: String,
2206    /// The language identifier.
2207    pub language_id: String,
2208    /// The visible range in the editor, if any.
2209    #[serde_as(deserialize_as = "DefaultOnError")]
2210    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2211    #[serde(default)]
2212    pub visible_range: Option<Range>,
2213    /// Timestamp in milliseconds since epoch of when the file was last focused.
2214    #[serde_as(deserialize_as = "DefaultOnError")]
2215    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2216    #[serde(default)]
2217    pub last_focused_ms: Option<u64>,
2218    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2219    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2220    /// these keys.
2221    ///
2222    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2223    #[serde_as(deserialize_as = "DefaultOnError")]
2224    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2225    #[serde(default)]
2226    #[serde(rename = "_meta")]
2227    pub meta: Option<Meta>,
2228}
2229
2230impl NesOpenFile {
2231    /// Builds [`NesOpenFile`] with the required fields set; optional fields start unset or empty.
2232    #[must_use]
2233    pub fn new(uri: impl Into<String>, language_id: impl Into<String>) -> Self {
2234        Self {
2235            uri: uri.into(),
2236            language_id: language_id.into(),
2237            visible_range: None,
2238            last_focused_ms: None,
2239            meta: None,
2240        }
2241    }
2242
2243    /// Sets or clears the optional `visibleRange` field.
2244    #[must_use]
2245    pub fn visible_range(mut self, visible_range: impl IntoOption<Range>) -> Self {
2246        self.visible_range = visible_range.into_option();
2247        self
2248    }
2249
2250    /// Sets or clears the optional `lastFocusedMs` field.
2251    #[must_use]
2252    pub fn last_focused_ms(mut self, last_focused_ms: impl IntoOption<u64>) -> Self {
2253        self.last_focused_ms = last_focused_ms.into_option();
2254        self
2255    }
2256
2257    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2258    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2259    /// these keys.
2260    ///
2261    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2262    #[must_use]
2263    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2264        self.meta = meta.into_option();
2265        self
2266    }
2267}
2268
2269/// A diagnostic (error, warning, etc.).
2270#[serde_as]
2271#[skip_serializing_none]
2272#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2273#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2274#[serde(rename_all = "camelCase")]
2275#[non_exhaustive]
2276pub struct NesDiagnostic {
2277    /// The URI of the file containing the diagnostic.
2278    #[cfg_attr(feature = "schemars", schemars(url))]
2279    pub uri: String,
2280    /// The range of the diagnostic.
2281    pub range: Range,
2282    /// The severity of the diagnostic.
2283    pub severity: NesDiagnosticSeverity,
2284    /// The diagnostic message.
2285    pub message: String,
2286    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2287    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2288    /// these keys.
2289    ///
2290    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2291    #[serde_as(deserialize_as = "DefaultOnError")]
2292    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2293    #[serde(default)]
2294    #[serde(rename = "_meta")]
2295    pub meta: Option<Meta>,
2296}
2297
2298impl NesDiagnostic {
2299    /// Builds [`NesDiagnostic`] with the required fields set; optional fields start unset or empty.
2300    #[must_use]
2301    pub fn new(
2302        uri: impl Into<String>,
2303        range: Range,
2304        severity: NesDiagnosticSeverity,
2305        message: impl Into<String>,
2306    ) -> Self {
2307        Self {
2308            uri: uri.into(),
2309            range,
2310            severity,
2311            message: message.into(),
2312            meta: None,
2313        }
2314    }
2315
2316    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2317    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2318    /// these keys.
2319    ///
2320    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2321    #[must_use]
2322    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2323        self.meta = meta.into_option();
2324        self
2325    }
2326}
2327
2328/// Severity of a diagnostic.
2329#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2330#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2331#[non_exhaustive]
2332pub enum NesDiagnosticSeverity {
2333    /// An error.
2334    #[serde(rename = "error")]
2335    Error,
2336    /// A warning.
2337    #[serde(rename = "warning")]
2338    Warning,
2339    /// An informational message.
2340    #[serde(rename = "information")]
2341    Information,
2342    /// A hint.
2343    #[serde(rename = "hint")]
2344    Hint,
2345    /// Custom or future diagnostic severity.
2346    ///
2347    /// Values beginning with `_` are reserved for implementation-specific
2348    /// extensions. Unknown values that do not begin with `_` are reserved for
2349    /// future ACP variants.
2350    #[serde(untagged)]
2351    Other(String),
2352}
2353
2354// NES suggest response
2355
2356/// Response to `nes/suggest`.
2357#[serde_as]
2358#[skip_serializing_none]
2359#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2360#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2361#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_SUGGEST_METHOD_NAME)))]
2362#[serde(rename_all = "camelCase")]
2363#[non_exhaustive]
2364pub struct SuggestNesResponse {
2365    /// The list of suggestions.
2366    pub suggestions: Vec<NesSuggestion>,
2367    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2368    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2369    /// these keys.
2370    ///
2371    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2372    #[serde_as(deserialize_as = "DefaultOnError")]
2373    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2374    #[serde(default)]
2375    #[serde(rename = "_meta")]
2376    pub meta: Option<Meta>,
2377}
2378
2379impl SuggestNesResponse {
2380    /// Builds [`SuggestNesResponse`] with the required response fields set; optional fields start unset or empty.
2381    #[must_use]
2382    pub fn new(suggestions: Vec<NesSuggestion>) -> Self {
2383        Self {
2384            suggestions,
2385            meta: None,
2386        }
2387    }
2388
2389    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2390    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2391    /// these keys.
2392    ///
2393    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2394    #[must_use]
2395    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2396        self.meta = meta.into_option();
2397        self
2398    }
2399}
2400
2401/// A suggestion returned by the agent.
2402#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2403#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2404#[serde(tag = "kind", rename_all = "camelCase")]
2405#[non_exhaustive]
2406pub enum NesSuggestion {
2407    /// A text edit suggestion.
2408    Edit(NesEditSuggestion),
2409    /// A jump-to-location suggestion.
2410    Jump(NesJumpSuggestion),
2411    /// A rename symbol suggestion.
2412    Rename(NesRenameSuggestion),
2413    /// A search-and-replace suggestion.
2414    SearchAndReplace(NesSearchAndReplaceSuggestion),
2415    /// Custom or future NES suggestion.
2416    ///
2417    /// Values beginning with `_` are reserved for implementation-specific
2418    /// extensions. Unknown values that do not begin with `_` are reserved for
2419    /// future ACP variants.
2420    ///
2421    /// Receivers that do not understand this suggestion kind should preserve
2422    /// the raw payload when storing, replaying, proxying, or forwarding
2423    /// suggestions, and otherwise ignore it or display it generically.
2424    #[serde(untagged)]
2425    Other(OtherNesSuggestion),
2426}
2427
2428/// Custom or future NES suggestion payload.
2429#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2430#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
2431#[cfg_attr(feature = "schemars", schemars(inline))]
2432#[cfg_attr(feature = "schemars", schemars(transform = other_nes_suggestion_schema))]
2433#[serde(rename_all = "camelCase")]
2434#[non_exhaustive]
2435pub struct OtherNesSuggestion {
2436    /// Custom or future NES suggestion kind.
2437    ///
2438    /// Values beginning with `_` are reserved for implementation-specific
2439    /// extensions. Unknown values that do not begin with `_` are reserved for
2440    /// future ACP variants.
2441    pub kind: String,
2442    /// Unique identifier for accept/reject tracking.
2443    pub suggestion_id: NesSuggestionId,
2444    /// Additional fields from the unknown NES suggestion payload.
2445    #[serde(flatten)]
2446    pub fields: BTreeMap<String, serde_json::Value>,
2447}
2448
2449impl OtherNesSuggestion {
2450    /// Builds [`OtherNesSuggestion`] from an unknown discriminator and preserves the remaining extension fields.
2451    #[must_use]
2452    pub fn new(
2453        kind: impl Into<String>,
2454        suggestion_id: impl Into<NesSuggestionId>,
2455        mut fields: BTreeMap<String, serde_json::Value>,
2456    ) -> Self {
2457        fields.remove("kind");
2458        fields.remove("suggestionId");
2459        Self {
2460            kind: kind.into(),
2461            suggestion_id: suggestion_id.into(),
2462            fields,
2463        }
2464    }
2465}
2466
2467impl<'de> Deserialize<'de> for OtherNesSuggestion {
2468    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2469    where
2470        D: serde::Deserializer<'de>,
2471    {
2472        let mut fields = BTreeMap::<String, serde_json::Value>::deserialize(deserializer)?;
2473        let kind = fields
2474            .remove("kind")
2475            .ok_or_else(|| serde::de::Error::missing_field("kind"))?;
2476        let serde_json::Value::String(kind) = kind else {
2477            return Err(serde::de::Error::custom("`kind` must be a string"));
2478        };
2479        let suggestion_id = fields
2480            .remove("suggestionId")
2481            .ok_or_else(|| serde::de::Error::missing_field("suggestionId"))?;
2482        let serde_json::Value::String(suggestion_id) = suggestion_id else {
2483            return Err(serde::de::Error::custom("`suggestionId` must be a string"));
2484        };
2485
2486        if is_known_nes_suggestion_kind(&kind) {
2487            return Err(serde::de::Error::custom(format!(
2488                "known NES suggestion `{kind}` did not match its schema"
2489            )));
2490        }
2491
2492        Ok(Self {
2493            kind,
2494            suggestion_id: NesSuggestionId::new(suggestion_id),
2495            fields,
2496        })
2497    }
2498}
2499
2500fn is_known_nes_suggestion_kind(kind: &str) -> bool {
2501    matches!(kind, "edit" | "jump" | "rename" | "searchAndReplace")
2502}
2503
2504#[cfg(feature = "schemars")]
2505fn other_nes_suggestion_schema(schema: &mut Schema) {
2506    super::schema_util::reject_known_string_discriminators(
2507        schema,
2508        "kind",
2509        &["edit", "jump", "rename", "searchAndReplace"],
2510    );
2511}
2512
2513/// A text edit suggestion.
2514#[serde_as]
2515#[skip_serializing_none]
2516#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2517#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2518#[serde(rename_all = "camelCase")]
2519#[non_exhaustive]
2520pub struct NesEditSuggestion {
2521    /// Unique identifier for accept/reject tracking.
2522    pub suggestion_id: NesSuggestionId,
2523    /// The URI of the file to edit.
2524    #[cfg_attr(feature = "schemars", schemars(url))]
2525    pub uri: String,
2526    /// The text edits to apply. Must contain at least one edit.
2527    #[cfg_attr(feature = "schemars", schemars(length(min = 1)))]
2528    pub edits: Vec<NesTextEdit>,
2529    /// Optional suggested cursor position after applying edits.
2530    #[serde_as(deserialize_as = "DefaultOnError")]
2531    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2532    #[serde(default)]
2533    pub cursor_position: Option<Position>,
2534    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2535    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2536    /// these keys.
2537    ///
2538    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2539    #[serde_as(deserialize_as = "DefaultOnError")]
2540    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2541    #[serde(default)]
2542    #[serde(rename = "_meta")]
2543    pub meta: Option<Meta>,
2544}
2545
2546impl NesEditSuggestion {
2547    /// Builds [`NesEditSuggestion`] with the required fields set; optional fields start unset or empty.
2548    #[must_use]
2549    pub fn new(
2550        suggestion_id: impl Into<NesSuggestionId>,
2551        uri: impl Into<String>,
2552        edits: Vec<NesTextEdit>,
2553    ) -> Self {
2554        Self {
2555            suggestion_id: suggestion_id.into(),
2556            uri: uri.into(),
2557            edits,
2558            cursor_position: None,
2559            meta: None,
2560        }
2561    }
2562
2563    /// Sets or clears the optional `cursorPosition` field.
2564    #[must_use]
2565    pub fn cursor_position(mut self, cursor_position: impl IntoOption<Position>) -> Self {
2566        self.cursor_position = cursor_position.into_option();
2567        self
2568    }
2569
2570    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2571    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2572    /// these keys.
2573    ///
2574    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2575    #[must_use]
2576    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2577        self.meta = meta.into_option();
2578        self
2579    }
2580}
2581
2582/// A text edit within a suggestion.
2583#[serde_as]
2584#[skip_serializing_none]
2585#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2586#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2587#[serde(rename_all = "camelCase")]
2588#[non_exhaustive]
2589pub struct NesTextEdit {
2590    /// The range to replace.
2591    pub range: Range,
2592    /// The replacement text.
2593    pub new_text: String,
2594    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2595    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2596    /// these keys.
2597    ///
2598    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2599    #[serde_as(deserialize_as = "DefaultOnError")]
2600    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2601    #[serde(default)]
2602    #[serde(rename = "_meta")]
2603    pub meta: Option<Meta>,
2604}
2605
2606impl NesTextEdit {
2607    /// Builds [`NesTextEdit`] with the required fields set; optional fields start unset or empty.
2608    #[must_use]
2609    pub fn new(range: Range, new_text: impl Into<String>) -> Self {
2610        Self {
2611            range,
2612            new_text: new_text.into(),
2613            meta: None,
2614        }
2615    }
2616
2617    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2618    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2619    /// these keys.
2620    ///
2621    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2622    #[must_use]
2623    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2624        self.meta = meta.into_option();
2625        self
2626    }
2627}
2628
2629/// A jump-to-location suggestion.
2630#[serde_as]
2631#[skip_serializing_none]
2632#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2633#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2634#[serde(rename_all = "camelCase")]
2635#[non_exhaustive]
2636pub struct NesJumpSuggestion {
2637    /// Unique identifier for accept/reject tracking.
2638    pub suggestion_id: NesSuggestionId,
2639    /// The file to navigate to.
2640    #[cfg_attr(feature = "schemars", schemars(url))]
2641    pub uri: String,
2642    /// The target position within the file.
2643    pub position: Position,
2644    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2645    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2646    /// these keys.
2647    ///
2648    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2649    #[serde_as(deserialize_as = "DefaultOnError")]
2650    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2651    #[serde(default)]
2652    #[serde(rename = "_meta")]
2653    pub meta: Option<Meta>,
2654}
2655
2656impl NesJumpSuggestion {
2657    /// Builds [`NesJumpSuggestion`] with the required fields set; optional fields start unset or empty.
2658    #[must_use]
2659    pub fn new(
2660        suggestion_id: impl Into<NesSuggestionId>,
2661        uri: impl Into<String>,
2662        position: Position,
2663    ) -> Self {
2664        Self {
2665            suggestion_id: suggestion_id.into(),
2666            uri: uri.into(),
2667            position,
2668            meta: None,
2669        }
2670    }
2671
2672    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2673    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2674    /// these keys.
2675    ///
2676    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2677    #[must_use]
2678    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2679        self.meta = meta.into_option();
2680        self
2681    }
2682}
2683
2684/// A rename symbol suggestion.
2685#[serde_as]
2686#[skip_serializing_none]
2687#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2688#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2689#[serde(rename_all = "camelCase")]
2690#[non_exhaustive]
2691pub struct NesRenameSuggestion {
2692    /// Unique identifier for accept/reject tracking.
2693    pub suggestion_id: NesSuggestionId,
2694    /// The file URI containing the symbol.
2695    #[cfg_attr(feature = "schemars", schemars(url))]
2696    pub uri: String,
2697    /// The position of the symbol to rename.
2698    pub position: Position,
2699    /// The new name for the symbol.
2700    pub new_name: String,
2701    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2702    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2703    /// these keys.
2704    ///
2705    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2706    #[serde_as(deserialize_as = "DefaultOnError")]
2707    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2708    #[serde(default)]
2709    #[serde(rename = "_meta")]
2710    pub meta: Option<Meta>,
2711}
2712
2713impl NesRenameSuggestion {
2714    /// Builds [`NesRenameSuggestion`] with the required fields set; optional fields start unset or empty.
2715    #[must_use]
2716    pub fn new(
2717        suggestion_id: impl Into<NesSuggestionId>,
2718        uri: impl Into<String>,
2719        position: Position,
2720        new_name: impl Into<String>,
2721    ) -> Self {
2722        Self {
2723            suggestion_id: suggestion_id.into(),
2724            uri: uri.into(),
2725            position,
2726            new_name: new_name.into(),
2727            meta: None,
2728        }
2729    }
2730
2731    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2732    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2733    /// these keys.
2734    ///
2735    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2736    #[must_use]
2737    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2738        self.meta = meta.into_option();
2739        self
2740    }
2741}
2742
2743/// A search-and-replace suggestion.
2744#[serde_as]
2745#[skip_serializing_none]
2746#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2747#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2748#[serde(rename_all = "camelCase")]
2749#[non_exhaustive]
2750pub struct NesSearchAndReplaceSuggestion {
2751    /// Unique identifier for accept/reject tracking.
2752    pub suggestion_id: NesSuggestionId,
2753    /// The file URI to search within.
2754    #[cfg_attr(feature = "schemars", schemars(url))]
2755    pub uri: String,
2756    /// The text or pattern to find.
2757    pub search: String,
2758    /// The replacement text.
2759    pub replace: String,
2760    /// Whether `search` is a regular expression. Defaults to `false`.
2761    #[serde(default)]
2762    pub is_regex: Option<bool>,
2763    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2764    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2765    /// these keys.
2766    ///
2767    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2768    #[serde_as(deserialize_as = "DefaultOnError")]
2769    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2770    #[serde(default)]
2771    #[serde(rename = "_meta")]
2772    pub meta: Option<Meta>,
2773}
2774
2775impl NesSearchAndReplaceSuggestion {
2776    /// Builds [`NesSearchAndReplaceSuggestion`] with the required fields set; optional fields start unset or empty.
2777    #[must_use]
2778    pub fn new(
2779        suggestion_id: impl Into<NesSuggestionId>,
2780        uri: impl Into<String>,
2781        search: impl Into<String>,
2782        replace: impl Into<String>,
2783    ) -> Self {
2784        Self {
2785            suggestion_id: suggestion_id.into(),
2786            uri: uri.into(),
2787            search: search.into(),
2788            replace: replace.into(),
2789            is_regex: None,
2790            meta: None,
2791        }
2792    }
2793
2794    /// Sets or clears the optional `isRegex` field.
2795    #[must_use]
2796    pub fn is_regex(mut self, is_regex: impl IntoOption<bool>) -> Self {
2797        self.is_regex = is_regex.into_option();
2798        self
2799    }
2800
2801    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2802    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2803    /// these keys.
2804    ///
2805    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2806    #[must_use]
2807    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2808        self.meta = meta.into_option();
2809        self
2810    }
2811}
2812
2813// NES accept/reject notifications
2814
2815/// Notification sent when a suggestion is accepted.
2816#[serde_as]
2817#[skip_serializing_none]
2818#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2819#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2820#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_ACCEPT_METHOD_NAME)))]
2821#[serde(rename_all = "camelCase")]
2822#[non_exhaustive]
2823pub struct AcceptNesNotification {
2824    /// The session ID for this notification.
2825    pub session_id: SessionId,
2826    /// The ID of the accepted suggestion.
2827    pub suggestion_id: NesSuggestionId,
2828    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2829    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2830    /// these keys.
2831    ///
2832    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2833    #[serde_as(deserialize_as = "DefaultOnError")]
2834    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2835    #[serde(default)]
2836    #[serde(rename = "_meta")]
2837    pub meta: Option<Meta>,
2838}
2839
2840impl AcceptNesNotification {
2841    /// Builds [`AcceptNesNotification`] with the required notification fields set; optional fields start unset or empty.
2842    #[must_use]
2843    pub fn new(
2844        session_id: impl Into<SessionId>,
2845        suggestion_id: impl Into<NesSuggestionId>,
2846    ) -> Self {
2847        Self {
2848            session_id: session_id.into(),
2849            suggestion_id: suggestion_id.into(),
2850            meta: None,
2851        }
2852    }
2853
2854    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2855    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2856    /// these keys.
2857    ///
2858    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2859    #[must_use]
2860    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2861        self.meta = meta.into_option();
2862        self
2863    }
2864}
2865
2866/// Notification sent when a suggestion is rejected.
2867#[serde_as]
2868#[skip_serializing_none]
2869#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2870#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2871#[cfg_attr(feature = "schemars", schemars(extend("x-side" = "agent", "x-method" = NES_REJECT_METHOD_NAME)))]
2872#[serde(rename_all = "camelCase")]
2873#[non_exhaustive]
2874pub struct RejectNesNotification {
2875    /// The session ID for this notification.
2876    pub session_id: SessionId,
2877    /// The ID of the rejected suggestion.
2878    pub suggestion_id: NesSuggestionId,
2879    /// The reason for rejection.
2880    #[serde_as(deserialize_as = "DefaultOnError")]
2881    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2882    #[serde(default)]
2883    pub reason: Option<NesRejectReason>,
2884    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2885    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2886    /// these keys.
2887    ///
2888    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2889    #[serde_as(deserialize_as = "DefaultOnError")]
2890    #[cfg_attr(feature = "schemars", schemars(extend("x-deserialize-default-on-error" = true)))]
2891    #[serde(default)]
2892    #[serde(rename = "_meta")]
2893    pub meta: Option<Meta>,
2894}
2895
2896impl RejectNesNotification {
2897    /// Builds [`RejectNesNotification`] with the required notification fields set; optional fields start unset or empty.
2898    #[must_use]
2899    pub fn new(
2900        session_id: impl Into<SessionId>,
2901        suggestion_id: impl Into<NesSuggestionId>,
2902    ) -> Self {
2903        Self {
2904            session_id: session_id.into(),
2905            suggestion_id: suggestion_id.into(),
2906            reason: None,
2907            meta: None,
2908        }
2909    }
2910
2911    /// Sets or clears the optional `reason` field.
2912    #[must_use]
2913    pub fn reason(mut self, reason: impl IntoOption<NesRejectReason>) -> Self {
2914        self.reason = reason.into_option();
2915        self
2916    }
2917
2918    /// The _meta property is reserved by ACP to allow clients and agents to attach additional
2919    /// metadata to their interactions. Implementations MUST NOT make assumptions about values at
2920    /// these keys.
2921    ///
2922    /// See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)
2923    #[must_use]
2924    pub fn meta(mut self, meta: impl IntoOption<Meta>) -> Self {
2925        self.meta = meta.into_option();
2926        self
2927    }
2928}
2929
2930/// The reason a suggestion was rejected.
2931#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
2932#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2933#[non_exhaustive]
2934pub enum NesRejectReason {
2935    /// The user explicitly dismissed the suggestion.
2936    #[serde(rename = "rejected")]
2937    Rejected,
2938    /// The suggestion was shown but the user continued editing without interacting.
2939    #[serde(rename = "ignored")]
2940    Ignored,
2941    /// The suggestion was superseded by a newer suggestion.
2942    #[serde(rename = "replaced")]
2943    Replaced,
2944    /// The request was cancelled before the agent returned a response.
2945    #[serde(rename = "cancelled")]
2946    Cancelled,
2947    /// Custom or future rejection reason.
2948    ///
2949    /// Values beginning with `_` are reserved for implementation-specific
2950    /// extensions. Unknown values that do not begin with `_` are reserved for
2951    /// future ACP variants.
2952    #[serde(untagged)]
2953    Other(String),
2954}
2955
2956#[cfg(test)]
2957mod tests {
2958    use super::*;
2959    use serde_json::json;
2960
2961    #[test]
2962    fn test_position_encoding_kind_serialization() {
2963        assert_eq!(
2964            serde_json::to_value(&PositionEncodingKind::Utf16).unwrap(),
2965            json!("utf-16")
2966        );
2967        assert_eq!(
2968            serde_json::to_value(&PositionEncodingKind::Utf32).unwrap(),
2969            json!("utf-32")
2970        );
2971        assert_eq!(
2972            serde_json::to_value(&PositionEncodingKind::Utf8).unwrap(),
2973            json!("utf-8")
2974        );
2975
2976        assert_eq!(
2977            serde_json::from_value::<PositionEncodingKind>(json!("utf-16")).unwrap(),
2978            PositionEncodingKind::Utf16
2979        );
2980        assert_eq!(
2981            serde_json::from_value::<PositionEncodingKind>(json!("utf-32")).unwrap(),
2982            PositionEncodingKind::Utf32
2983        );
2984        assert_eq!(
2985            serde_json::from_value::<PositionEncodingKind>(json!("utf-8")).unwrap(),
2986            PositionEncodingKind::Utf8
2987        );
2988        assert!(serde_json::from_value::<PositionEncodingKind>(json!("_future")).is_err());
2989    }
2990
2991    #[test]
2992    fn test_client_capabilities_skip_unknown_position_encodings() {
2993        let caps: crate::v2::ClientCapabilities = serde_json::from_value(json!({
2994            "positionEncodings": ["_future", "utf-8", "utf-16"]
2995        }))
2996        .unwrap();
2997
2998        assert_eq!(
2999            caps.position_encodings,
3000            vec![PositionEncodingKind::Utf8, PositionEncodingKind::Utf16]
3001        );
3002    }
3003
3004    #[test]
3005    fn test_agent_nes_capabilities_serialization() {
3006        let caps = NesCapabilities::new()
3007            .events(
3008                NesEventCapabilities::new().document(
3009                    NesDocumentEventCapabilities::new()
3010                        .did_open(NesDocumentDidOpenCapabilities::default())
3011                        .did_change(NesDocumentDidChangeCapabilities::new(
3012                            TextDocumentSyncKind::Incremental,
3013                        ))
3014                        .did_close(NesDocumentDidCloseCapabilities::default())
3015                        .did_save(NesDocumentDidSaveCapabilities::default())
3016                        .did_focus(NesDocumentDidFocusCapabilities::default()),
3017                ),
3018            )
3019            .context(
3020                NesContextCapabilities::new()
3021                    .recent_files(NesRecentFilesCapabilities {
3022                        max_count: Some(10),
3023                        meta: None,
3024                    })
3025                    .related_snippets(NesRelatedSnippetsCapabilities::default())
3026                    .edit_history(NesEditHistoryCapabilities {
3027                        max_count: Some(6),
3028                        meta: None,
3029                    })
3030                    .user_actions(NesUserActionsCapabilities {
3031                        max_count: Some(16),
3032                        meta: None,
3033                    })
3034                    .open_files(NesOpenFilesCapabilities::default())
3035                    .diagnostics(NesDiagnosticsCapabilities::default()),
3036            );
3037
3038        let json = serde_json::to_value(&caps).unwrap();
3039        assert_eq!(
3040            json,
3041            json!({
3042                "events": {
3043                    "document": {
3044                        "didOpen": {},
3045                        "didChange": {
3046                            "syncKind": "incremental"
3047                        },
3048                        "didClose": {},
3049                        "didSave": {},
3050                        "didFocus": {}
3051                    }
3052                },
3053                "context": {
3054                    "recentFiles": {
3055                        "maxCount": 10
3056                    },
3057                    "relatedSnippets": {},
3058                    "editHistory": {
3059                        "maxCount": 6
3060                    },
3061                    "userActions": {
3062                        "maxCount": 16
3063                    },
3064                    "openFiles": {},
3065                    "diagnostics": {}
3066                }
3067            })
3068        );
3069
3070        // Round-trip
3071        let deserialized: NesCapabilities = serde_json::from_value(json).unwrap();
3072        assert_eq!(deserialized, caps);
3073    }
3074
3075    #[test]
3076    fn test_client_nes_capabilities_serialization() {
3077        let caps = ClientNesCapabilities::new()
3078            .jump(NesJumpCapabilities::default())
3079            .rename(NesRenameCapabilities::default())
3080            .search_and_replace(NesSearchAndReplaceCapabilities::default());
3081
3082        let json = serde_json::to_value(&caps).unwrap();
3083        assert_eq!(
3084            json,
3085            json!({
3086                "jump": {},
3087                "rename": {},
3088                "searchAndReplace": {}
3089            })
3090        );
3091
3092        let deserialized: ClientNesCapabilities = serde_json::from_value(json).unwrap();
3093        assert_eq!(deserialized, caps);
3094    }
3095
3096    #[test]
3097    fn test_document_did_open_serialization() {
3098        let notification = DidOpenDocumentNotification::new(
3099            "session_123",
3100            "file:///path/to/file.rs",
3101            "rust",
3102            1,
3103            "fn main() {\n    println!(\"hello\");\n}\n",
3104        );
3105
3106        let json = serde_json::to_value(&notification).unwrap();
3107        assert_eq!(
3108            json,
3109            json!({
3110                "sessionId": "session_123",
3111                "uri": "file:///path/to/file.rs",
3112                "languageId": "rust",
3113                "version": 1,
3114                "text": "fn main() {\n    println!(\"hello\");\n}\n"
3115            })
3116        );
3117
3118        let deserialized: DidOpenDocumentNotification = serde_json::from_value(json).unwrap();
3119        assert_eq!(deserialized, notification);
3120    }
3121
3122    #[test]
3123    fn test_document_did_change_incremental_serialization() {
3124        let notification = DidChangeDocumentNotification::new(
3125            "session_123",
3126            "file:///path/to/file.rs",
3127            2,
3128            vec![TextDocumentContentChangeEvent::incremental(
3129                Range::new(Position::new(1, 4), Position::new(1, 4)),
3130                "let x = 42;\n    ",
3131            )],
3132        );
3133
3134        let json = serde_json::to_value(&notification).unwrap();
3135        assert_eq!(
3136            json,
3137            json!({
3138                "sessionId": "session_123",
3139                "uri": "file:///path/to/file.rs",
3140                "version": 2,
3141                "contentChanges": [
3142                    {
3143                        "range": {
3144                            "start": { "line": 1, "character": 4 },
3145                            "end": { "line": 1, "character": 4 }
3146                        },
3147                        "text": "let x = 42;\n    "
3148                    }
3149                ]
3150            })
3151        );
3152    }
3153
3154    #[test]
3155    fn test_document_did_change_full_serialization() {
3156        let notification = DidChangeDocumentNotification::new(
3157            "session_123",
3158            "file:///path/to/file.rs",
3159            2,
3160            vec![TextDocumentContentChangeEvent::full(
3161                "fn main() {\n    let x = 42;\n    println!(\"hello\");\n}\n",
3162            )],
3163        );
3164
3165        let json = serde_json::to_value(&notification).unwrap();
3166        assert_eq!(
3167            json,
3168            json!({
3169                "sessionId": "session_123",
3170                "uri": "file:///path/to/file.rs",
3171                "version": 2,
3172                "contentChanges": [
3173                    {
3174                        "text": "fn main() {\n    let x = 42;\n    println!(\"hello\");\n}\n"
3175                    }
3176                ]
3177            })
3178        );
3179    }
3180
3181    #[test]
3182    fn test_document_did_close_serialization() {
3183        let notification =
3184            DidCloseDocumentNotification::new("session_123", "file:///path/to/file.rs");
3185        let json = serde_json::to_value(&notification).unwrap();
3186        assert_eq!(
3187            json,
3188            json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
3189        );
3190    }
3191
3192    #[test]
3193    fn test_document_did_save_serialization() {
3194        let notification =
3195            DidSaveDocumentNotification::new("session_123", "file:///path/to/file.rs");
3196        let json = serde_json::to_value(&notification).unwrap();
3197        assert_eq!(
3198            json,
3199            json!({ "sessionId": "session_123", "uri": "file:///path/to/file.rs" })
3200        );
3201    }
3202
3203    #[test]
3204    fn test_document_did_focus_serialization() {
3205        let notification = DidFocusDocumentNotification::new(
3206            "session_123",
3207            "file:///path/to/file.rs",
3208            2,
3209            Position::new(5, 12),
3210            Range::new(Position::new(0, 0), Position::new(45, 0)),
3211        );
3212
3213        let json = serde_json::to_value(&notification).unwrap();
3214        assert_eq!(
3215            json,
3216            json!({
3217                "sessionId": "session_123",
3218                "uri": "file:///path/to/file.rs",
3219                "version": 2,
3220                "position": { "line": 5, "character": 12 },
3221                "visibleRange": {
3222                    "start": { "line": 0, "character": 0 },
3223                    "end": { "line": 45, "character": 0 }
3224                }
3225            })
3226        );
3227    }
3228
3229    #[test]
3230    fn test_nes_suggestion_edit_serialization() {
3231        let suggestion = NesSuggestion::Edit(
3232            NesEditSuggestion::new(
3233                "sugg_001",
3234                "file:///path/to/other_file.rs",
3235                vec![NesTextEdit::new(
3236                    Range::new(Position::new(5, 0), Position::new(5, 10)),
3237                    "let result = helper();",
3238                )],
3239            )
3240            .cursor_position(Position::new(5, 22)),
3241        );
3242
3243        let json = serde_json::to_value(&suggestion).unwrap();
3244        assert_eq!(
3245            json,
3246            json!({
3247                "kind": "edit",
3248                "suggestionId": "sugg_001",
3249                "uri": "file:///path/to/other_file.rs",
3250                "edits": [
3251                    {
3252                        "range": {
3253                            "start": { "line": 5, "character": 0 },
3254                            "end": { "line": 5, "character": 10 }
3255                        },
3256                        "newText": "let result = helper();"
3257                    }
3258                ],
3259                "cursorPosition": { "line": 5, "character": 22 }
3260            })
3261        );
3262
3263        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3264        assert_eq!(deserialized, suggestion);
3265    }
3266
3267    #[test]
3268    fn test_nes_suggestion_unknown_variant() {
3269        let suggestion: NesSuggestion = serde_json::from_value(json!({
3270            "kind": "_preview",
3271            "suggestionId": "sugg_001",
3272            "label": "Preview generated file"
3273        }))
3274        .unwrap();
3275
3276        let NesSuggestion::Other(unknown) = suggestion else {
3277            panic!("expected unknown NES suggestion");
3278        };
3279
3280        assert_eq!(unknown.kind, "_preview");
3281        assert_eq!(unknown.suggestion_id.to_string(), "sugg_001");
3282        assert!(!unknown.fields.contains_key("suggestionId"));
3283        assert_eq!(
3284            serde_json::to_value(NesSuggestion::Other(unknown)).unwrap(),
3285            json!({
3286                "kind": "_preview",
3287                "suggestionId": "sugg_001",
3288                "label": "Preview generated file"
3289            })
3290        );
3291    }
3292
3293    #[test]
3294    fn test_nes_suggestion_unknown_does_not_hide_malformed_known_variant() {
3295        assert!(
3296            serde_json::from_value::<NesSuggestion>(json!({
3297                "kind": "edit"
3298            }))
3299            .is_err()
3300        );
3301    }
3302
3303    #[test]
3304    fn test_nes_suggestion_jump_serialization() {
3305        let suggestion = NesSuggestion::Jump(NesJumpSuggestion::new(
3306            "sugg_002",
3307            "file:///path/to/other_file.rs",
3308            Position::new(15, 4),
3309        ));
3310
3311        let json = serde_json::to_value(&suggestion).unwrap();
3312        assert_eq!(
3313            json,
3314            json!({
3315                "kind": "jump",
3316                "suggestionId": "sugg_002",
3317                "uri": "file:///path/to/other_file.rs",
3318                "position": { "line": 15, "character": 4 }
3319            })
3320        );
3321
3322        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3323        assert_eq!(deserialized, suggestion);
3324    }
3325
3326    #[test]
3327    fn test_nes_suggestion_rename_serialization() {
3328        let suggestion = NesSuggestion::Rename(NesRenameSuggestion::new(
3329            "sugg_003",
3330            "file:///path/to/file.rs",
3331            Position::new(5, 10),
3332            "calculateTotal",
3333        ));
3334
3335        let json = serde_json::to_value(&suggestion).unwrap();
3336        assert_eq!(
3337            json,
3338            json!({
3339                "kind": "rename",
3340                "suggestionId": "sugg_003",
3341                "uri": "file:///path/to/file.rs",
3342                "position": { "line": 5, "character": 10 },
3343                "newName": "calculateTotal"
3344            })
3345        );
3346
3347        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3348        assert_eq!(deserialized, suggestion);
3349    }
3350
3351    #[test]
3352    fn test_nes_suggestion_search_and_replace_serialization() {
3353        let suggestion = NesSuggestion::SearchAndReplace(
3354            NesSearchAndReplaceSuggestion::new(
3355                "sugg_004",
3356                "file:///path/to/file.rs",
3357                "oldFunction",
3358                "newFunction",
3359            )
3360            .is_regex(false),
3361        );
3362
3363        let json = serde_json::to_value(&suggestion).unwrap();
3364        assert_eq!(
3365            json,
3366            json!({
3367                "kind": "searchAndReplace",
3368                "suggestionId": "sugg_004",
3369                "uri": "file:///path/to/file.rs",
3370                "search": "oldFunction",
3371                "replace": "newFunction",
3372                "isRegex": false
3373            })
3374        );
3375
3376        let deserialized: NesSuggestion = serde_json::from_value(json).unwrap();
3377        assert_eq!(deserialized, suggestion);
3378    }
3379
3380    #[test]
3381    fn test_nes_start_request_serialization() {
3382        let request = StartNesRequest::new()
3383            .workspace_uri("file:///Users/alice/projects/my-app")
3384            .workspace_folders(vec![WorkspaceFolder::new(
3385                "file:///Users/alice/projects/my-app",
3386                "my-app",
3387            )])
3388            .repository(NesRepository::new(
3389                "my-app",
3390                "alice",
3391                "https://github.com/alice/my-app.git",
3392            ));
3393
3394        let json = serde_json::to_value(&request).unwrap();
3395        assert_eq!(
3396            json,
3397            json!({
3398                "workspaceUri": "file:///Users/alice/projects/my-app",
3399                "workspaceFolders": [
3400                    {
3401                        "uri": "file:///Users/alice/projects/my-app",
3402                        "name": "my-app"
3403                    }
3404                ],
3405                "repository": {
3406                    "name": "my-app",
3407                    "owner": "alice",
3408                    "remoteUrl": "https://github.com/alice/my-app.git"
3409                }
3410            })
3411        );
3412    }
3413
3414    #[test]
3415    fn test_nes_start_response_serialization() {
3416        let response = StartNesResponse::new("session_abc123");
3417        let json = serde_json::to_value(&response).unwrap();
3418        assert_eq!(json, json!({ "sessionId": "session_abc123" }));
3419    }
3420
3421    #[test]
3422    fn test_nes_trigger_kind_serialization() {
3423        assert_eq!(
3424            serde_json::to_value(&NesTriggerKind::Automatic).unwrap(),
3425            json!("automatic")
3426        );
3427        assert_eq!(
3428            serde_json::to_value(&NesTriggerKind::Diagnostic).unwrap(),
3429            json!("diagnostic")
3430        );
3431        assert_eq!(
3432            serde_json::to_value(&NesTriggerKind::Manual).unwrap(),
3433            json!("manual")
3434        );
3435    }
3436
3437    #[test]
3438    fn test_nes_reject_reason_serialization() {
3439        assert_eq!(
3440            serde_json::to_value(&NesRejectReason::Rejected).unwrap(),
3441            json!("rejected")
3442        );
3443        assert_eq!(
3444            serde_json::to_value(&NesRejectReason::Ignored).unwrap(),
3445            json!("ignored")
3446        );
3447        assert_eq!(
3448            serde_json::to_value(&NesRejectReason::Replaced).unwrap(),
3449            json!("replaced")
3450        );
3451        assert_eq!(
3452            serde_json::to_value(&NesRejectReason::Cancelled).unwrap(),
3453            json!("cancelled")
3454        );
3455    }
3456
3457    #[test]
3458    fn test_nes_accept_notification_serialization() {
3459        let notification = AcceptNesNotification::new("session_123", "sugg_001");
3460        let json = serde_json::to_value(&notification).unwrap();
3461        assert_eq!(
3462            json,
3463            json!({ "sessionId": "session_123", "suggestionId": "sugg_001" })
3464        );
3465    }
3466
3467    #[test]
3468    fn test_nes_reject_notification_serialization() {
3469        let notification =
3470            RejectNesNotification::new("session_123", "sugg_001").reason(NesRejectReason::Rejected);
3471        let json = serde_json::to_value(&notification).unwrap();
3472        assert_eq!(
3473            json,
3474            json!({ "sessionId": "session_123", "suggestionId": "sugg_001", "reason": "rejected" })
3475        );
3476    }
3477
3478    #[test]
3479    fn test_nes_suggest_request_with_context_serialization() {
3480        let request = SuggestNesRequest::new(
3481            "session_123",
3482            "file:///path/to/file.rs",
3483            2,
3484            Position::new(5, 12),
3485            NesTriggerKind::Automatic,
3486        )
3487        .selection(Range::new(Position::new(5, 4), Position::new(5, 12)))
3488        .context(
3489            NesSuggestContext::new()
3490                .recent_files(vec![NesRecentFile::new(
3491                    "file:///path/to/utils.rs",
3492                    "rust",
3493                    "pub fn helper() -> i32 { 42 }\n",
3494                )])
3495                .diagnostics(vec![NesDiagnostic::new(
3496                    "file:///path/to/file.rs",
3497                    Range::new(Position::new(5, 0), Position::new(5, 10)),
3498                    NesDiagnosticSeverity::Error,
3499                    "cannot find value `foo` in this scope",
3500                )]),
3501        );
3502
3503        let json = serde_json::to_value(&request).unwrap();
3504        assert_eq!(json["sessionId"], "session_123");
3505        assert_eq!(json["uri"], "file:///path/to/file.rs");
3506        assert_eq!(json["version"], 2);
3507        assert_eq!(json["triggerKind"], "automatic");
3508        assert_eq!(
3509            json["context"]["recentFiles"][0]["uri"],
3510            "file:///path/to/utils.rs"
3511        );
3512        assert_eq!(json["context"]["diagnostics"][0]["severity"], "error");
3513    }
3514
3515    #[test]
3516    fn test_text_document_sync_kind_serialization() {
3517        assert_eq!(
3518            serde_json::to_value(&TextDocumentSyncKind::Full).unwrap(),
3519            json!("full")
3520        );
3521        assert_eq!(
3522            serde_json::to_value(&TextDocumentSyncKind::Incremental).unwrap(),
3523            json!("incremental")
3524        );
3525        assert!(serde_json::from_value::<TextDocumentSyncKind>(json!("_future")).is_err());
3526    }
3527
3528    #[test]
3529    fn test_document_event_capabilities_drop_unknown_did_change_sync_kind() {
3530        let caps: NesDocumentEventCapabilities = serde_json::from_value(json!({
3531            "didChange": {
3532                "syncKind": "_future"
3533            }
3534        }))
3535        .unwrap();
3536
3537        assert_eq!(caps.did_change, None);
3538    }
3539
3540    #[test]
3541    fn test_document_did_change_capabilities_requires_sync_kind() {
3542        assert!(serde_json::from_value::<NesDocumentDidChangeCapabilities>(json!({})).is_err());
3543    }
3544
3545    #[test]
3546    fn test_nes_suggest_response_serialization() {
3547        let response = SuggestNesResponse::new(vec![
3548            NesSuggestion::Edit(NesEditSuggestion::new(
3549                "sugg_001",
3550                "file:///path/to/file.rs",
3551                vec![NesTextEdit::new(
3552                    Range::new(Position::new(5, 0), Position::new(5, 10)),
3553                    "let result = helper();",
3554                )],
3555            )),
3556            NesSuggestion::Jump(NesJumpSuggestion::new(
3557                "sugg_002",
3558                "file:///path/to/other.rs",
3559                Position::new(10, 0),
3560            )),
3561        ]);
3562
3563        let json = serde_json::to_value(&response).unwrap();
3564        assert_eq!(json["suggestions"].as_array().unwrap().len(), 2);
3565        assert_eq!(json["suggestions"][0]["kind"], "edit");
3566        assert_eq!(json["suggestions"][1]["kind"], "jump");
3567    }
3568}