Skip to main content

agent_client_protocol_schema/v1/
nes.rs

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