Skip to main content

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