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