Skip to main content

agent_client_protocol_schema/v1/
nes.rs

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