Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:47:02.358Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

dap_command.rs

1976 lines · 58.8 KB · rust
1use std::sync::Arc;
2
3use anyhow::{Context as _, Ok, Result};
4use base64::Engine;
5use dap::{
6    Capabilities, ContinueArguments, ExceptionFilterOptions, InitializeRequestArguments,
7    InitializeRequestArgumentsPathFormat, NextArguments, SetVariableResponse, SourceBreakpoint,
8    StepInArguments, StepOutArguments, SteppingGranularity, ValueFormat, Variable,
9    VariablesArgumentsFilter,
10    client::SessionId,
11    proto_conversions::ProtoConversion,
12    requests::{Continue, Next},
13};
14
15use rpc::proto;
16use serde_json::Value;
17use util::ResultExt;
18
19pub trait LocalDapCommand: 'static + Send + Sync + std::fmt::Debug {
20    type Response: 'static + Send + std::fmt::Debug;
21    type DapRequest: 'static + Send + dap::requests::Request;
22    /// Is this request idempotent? Is it safe to cache the response for as long as the execution environment is unchanged?
23    const CACHEABLE: bool = false;
24
25    fn is_supported(_capabilities: &Capabilities) -> bool {
26        true
27    }
28
29    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments;
30
31    fn response_from_dap(
32        &self,
33        message: <Self::DapRequest as dap::requests::Request>::Response,
34    ) -> Result<Self::Response>;
35}
36
37pub trait DapCommand: LocalDapCommand {
38    type ProtoRequest: 'static + Send;
39    type ProtoResponse: 'static + Send;
40
41    #[allow(dead_code)]
42    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId;
43
44    #[allow(dead_code)]
45    fn from_proto(request: &Self::ProtoRequest) -> Self;
46
47    #[allow(unused)]
48    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest;
49
50    #[allow(dead_code)]
51    fn response_to_proto(
52        debug_client_id: SessionId,
53        message: Self::Response,
54    ) -> Self::ProtoResponse;
55
56    #[allow(unused)]
57    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response>;
58}
59
60impl<T: LocalDapCommand> LocalDapCommand for Arc<T> {
61    type Response = T::Response;
62    type DapRequest = T::DapRequest;
63
64    fn is_supported(capabilities: &Capabilities) -> bool {
65        T::is_supported(capabilities)
66    }
67
68    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
69        T::to_dap(self)
70    }
71
72    fn response_from_dap(
73        &self,
74        message: <Self::DapRequest as dap::requests::Request>::Response,
75    ) -> Result<Self::Response> {
76        T::response_from_dap(self, message)
77    }
78}
79
80impl<T: DapCommand> DapCommand for Arc<T> {
81    type ProtoRequest = T::ProtoRequest;
82    type ProtoResponse = T::ProtoResponse;
83
84    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
85        T::client_id_from_proto(request)
86    }
87
88    fn from_proto(request: &Self::ProtoRequest) -> Self {
89        Arc::new(T::from_proto(request))
90    }
91
92    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
93        T::to_proto(self, debug_client_id, upstream_project_id)
94    }
95
96    fn response_to_proto(
97        debug_client_id: SessionId,
98        message: Self::Response,
99    ) -> Self::ProtoResponse {
100        T::response_to_proto(debug_client_id, message)
101    }
102
103    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
104        T::response_from_proto(self, message)
105    }
106}
107
108#[derive(Debug, Hash, PartialEq, Eq)]
109pub struct StepCommand {
110    pub thread_id: i64,
111    pub granularity: Option<SteppingGranularity>,
112    pub single_thread: Option<bool>,
113}
114
115impl StepCommand {
116    fn from_proto(message: proto::DapNextRequest) -> Self {
117        const LINE: i32 = proto::SteppingGranularity::Line as i32;
118        const INSTRUCTION: i32 = proto::SteppingGranularity::Instruction as i32;
119
120        let granularity = message.granularity.map(|granularity| match granularity {
121            LINE => SteppingGranularity::Line,
122            INSTRUCTION => SteppingGranularity::Instruction,
123            _ => SteppingGranularity::Statement,
124        });
125
126        Self {
127            thread_id: message.thread_id,
128            granularity,
129            single_thread: message.single_thread,
130        }
131    }
132}
133
134#[derive(Debug, Hash, PartialEq, Eq)]
135pub(crate) struct NextCommand {
136    pub inner: StepCommand,
137}
138
139impl LocalDapCommand for NextCommand {
140    type Response = <Next as dap::requests::Request>::Response;
141    type DapRequest = Next;
142
143    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
144        NextArguments {
145            thread_id: self.inner.thread_id,
146            single_thread: self.inner.single_thread,
147            granularity: self.inner.granularity,
148        }
149    }
150    fn response_from_dap(
151        &self,
152        _message: <Self::DapRequest as dap::requests::Request>::Response,
153    ) -> Result<Self::Response> {
154        Ok(())
155    }
156}
157
158impl DapCommand for NextCommand {
159    type ProtoRequest = proto::DapNextRequest;
160    type ProtoResponse = proto::Ack;
161
162    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
163        SessionId::from_proto(request.client_id)
164    }
165
166    fn from_proto(request: &Self::ProtoRequest) -> Self {
167        Self {
168            inner: StepCommand::from_proto(request.clone()),
169        }
170    }
171
172    fn response_to_proto(
173        _debug_client_id: SessionId,
174        _message: Self::Response,
175    ) -> Self::ProtoResponse {
176        proto::Ack {}
177    }
178
179    fn to_proto(
180        &self,
181        debug_client_id: SessionId,
182        upstream_project_id: u64,
183    ) -> proto::DapNextRequest {
184        proto::DapNextRequest {
185            project_id: upstream_project_id,
186            client_id: debug_client_id.to_proto(),
187            thread_id: self.inner.thread_id,
188            single_thread: self.inner.single_thread,
189            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
190        }
191    }
192
193    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
194        Ok(())
195    }
196}
197
198#[derive(Debug, Hash, PartialEq, Eq)]
199pub(crate) struct StepInCommand {
200    pub inner: StepCommand,
201}
202
203impl LocalDapCommand for StepInCommand {
204    type Response = <dap::requests::StepIn as dap::requests::Request>::Response;
205    type DapRequest = dap::requests::StepIn;
206
207    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
208        StepInArguments {
209            thread_id: self.inner.thread_id,
210            single_thread: self.inner.single_thread,
211            target_id: None,
212            granularity: self.inner.granularity,
213        }
214    }
215
216    fn response_from_dap(
217        &self,
218        _message: <Self::DapRequest as dap::requests::Request>::Response,
219    ) -> Result<Self::Response> {
220        Ok(())
221    }
222}
223
224impl DapCommand for StepInCommand {
225    type ProtoRequest = proto::DapStepInRequest;
226    type ProtoResponse = proto::Ack;
227
228    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
229        SessionId::from_proto(request.client_id)
230    }
231
232    fn from_proto(request: &Self::ProtoRequest) -> Self {
233        Self {
234            inner: StepCommand::from_proto(proto::DapNextRequest {
235                project_id: request.project_id,
236                client_id: request.client_id,
237                thread_id: request.thread_id,
238                single_thread: request.single_thread,
239                granularity: request.granularity,
240            }),
241        }
242    }
243
244    fn response_to_proto(
245        _debug_client_id: SessionId,
246        _message: Self::Response,
247    ) -> Self::ProtoResponse {
248        proto::Ack {}
249    }
250
251    fn to_proto(
252        &self,
253        debug_client_id: SessionId,
254        upstream_project_id: u64,
255    ) -> proto::DapStepInRequest {
256        proto::DapStepInRequest {
257            project_id: upstream_project_id,
258            client_id: debug_client_id.to_proto(),
259            thread_id: self.inner.thread_id,
260            single_thread: self.inner.single_thread,
261            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
262            target_id: None,
263        }
264    }
265
266    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
267        Ok(())
268    }
269}
270
271#[derive(Debug, Hash, PartialEq, Eq)]
272pub(crate) struct StepOutCommand {
273    pub inner: StepCommand,
274}
275
276impl LocalDapCommand for StepOutCommand {
277    type Response = <dap::requests::StepOut as dap::requests::Request>::Response;
278    type DapRequest = dap::requests::StepOut;
279
280    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
281        StepOutArguments {
282            thread_id: self.inner.thread_id,
283            single_thread: self.inner.single_thread,
284            granularity: self.inner.granularity,
285        }
286    }
287
288    fn response_from_dap(
289        &self,
290        _message: <Self::DapRequest as dap::requests::Request>::Response,
291    ) -> Result<Self::Response> {
292        Ok(())
293    }
294}
295
296impl DapCommand for StepOutCommand {
297    type ProtoRequest = proto::DapStepOutRequest;
298    type ProtoResponse = proto::Ack;
299
300    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
301        SessionId::from_proto(request.client_id)
302    }
303
304    fn from_proto(request: &Self::ProtoRequest) -> Self {
305        Self {
306            inner: StepCommand::from_proto(proto::DapNextRequest {
307                project_id: request.project_id,
308                client_id: request.client_id,
309                thread_id: request.thread_id,
310                single_thread: request.single_thread,
311                granularity: request.granularity,
312            }),
313        }
314    }
315
316    fn response_to_proto(
317        _debug_client_id: SessionId,
318        _message: Self::Response,
319    ) -> Self::ProtoResponse {
320        proto::Ack {}
321    }
322
323    fn to_proto(
324        &self,
325        debug_client_id: SessionId,
326        upstream_project_id: u64,
327    ) -> proto::DapStepOutRequest {
328        proto::DapStepOutRequest {
329            project_id: upstream_project_id,
330            client_id: debug_client_id.to_proto(),
331            thread_id: self.inner.thread_id,
332            single_thread: self.inner.single_thread,
333            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
334        }
335    }
336
337    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
338        Ok(())
339    }
340}
341
342#[derive(Debug, Hash, PartialEq, Eq)]
343pub(crate) struct StepBackCommand {
344    pub inner: StepCommand,
345}
346impl LocalDapCommand for StepBackCommand {
347    type Response = <dap::requests::StepBack as dap::requests::Request>::Response;
348    type DapRequest = dap::requests::StepBack;
349
350    fn is_supported(capabilities: &Capabilities) -> bool {
351        capabilities.supports_step_back.unwrap_or_default()
352    }
353
354    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
355        dap::StepBackArguments {
356            thread_id: self.inner.thread_id,
357            single_thread: self.inner.single_thread,
358            granularity: self.inner.granularity,
359        }
360    }
361
362    fn response_from_dap(
363        &self,
364        _message: <Self::DapRequest as dap::requests::Request>::Response,
365    ) -> Result<Self::Response> {
366        Ok(())
367    }
368}
369
370impl DapCommand for StepBackCommand {
371    type ProtoRequest = proto::DapStepBackRequest;
372    type ProtoResponse = proto::Ack;
373
374    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
375        SessionId::from_proto(request.client_id)
376    }
377
378    fn from_proto(request: &Self::ProtoRequest) -> Self {
379        Self {
380            inner: StepCommand::from_proto(proto::DapNextRequest {
381                project_id: request.project_id,
382                client_id: request.client_id,
383                thread_id: request.thread_id,
384                single_thread: request.single_thread,
385                granularity: request.granularity,
386            }),
387        }
388    }
389
390    fn response_to_proto(
391        _debug_client_id: SessionId,
392        _message: Self::Response,
393    ) -> Self::ProtoResponse {
394        proto::Ack {}
395    }
396
397    fn to_proto(
398        &self,
399        debug_client_id: SessionId,
400        upstream_project_id: u64,
401    ) -> proto::DapStepBackRequest {
402        proto::DapStepBackRequest {
403            project_id: upstream_project_id,
404            client_id: debug_client_id.to_proto(),
405            thread_id: self.inner.thread_id,
406            single_thread: self.inner.single_thread,
407            granularity: self.inner.granularity.map(|gran| gran.to_proto() as i32),
408        }
409    }
410
411    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
412        Ok(())
413    }
414}
415
416#[derive(Debug, Hash, PartialEq, Eq)]
417pub(crate) struct ContinueCommand {
418    pub args: ContinueArguments,
419}
420
421impl LocalDapCommand for ContinueCommand {
422    type Response = <Continue as dap::requests::Request>::Response;
423    type DapRequest = Continue;
424
425    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
426        self.args.clone()
427    }
428
429    fn response_from_dap(
430        &self,
431        message: <Self::DapRequest as dap::requests::Request>::Response,
432    ) -> Result<Self::Response> {
433        Ok(message)
434    }
435}
436
437impl DapCommand for ContinueCommand {
438    type ProtoRequest = proto::DapContinueRequest;
439    type ProtoResponse = proto::DapContinueResponse;
440
441    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
442        SessionId::from_proto(request.client_id)
443    }
444
445    fn to_proto(
446        &self,
447        debug_client_id: SessionId,
448        upstream_project_id: u64,
449    ) -> proto::DapContinueRequest {
450        proto::DapContinueRequest {
451            project_id: upstream_project_id,
452            client_id: debug_client_id.to_proto(),
453            thread_id: self.args.thread_id,
454            single_thread: self.args.single_thread,
455        }
456    }
457
458    fn from_proto(request: &Self::ProtoRequest) -> Self {
459        Self {
460            args: ContinueArguments {
461                thread_id: request.thread_id,
462                single_thread: request.single_thread,
463            },
464        }
465    }
466
467    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
468        Ok(Self::Response {
469            all_threads_continued: message.all_threads_continued,
470        })
471    }
472
473    fn response_to_proto(
474        debug_client_id: SessionId,
475        message: Self::Response,
476    ) -> Self::ProtoResponse {
477        proto::DapContinueResponse {
478            client_id: debug_client_id.to_proto(),
479            all_threads_continued: message.all_threads_continued,
480        }
481    }
482}
483
484#[derive(Debug, Hash, PartialEq, Eq)]
485pub(crate) struct PauseCommand {
486    pub thread_id: i64,
487}
488
489impl LocalDapCommand for PauseCommand {
490    type Response = <dap::requests::Pause as dap::requests::Request>::Response;
491    type DapRequest = dap::requests::Pause;
492    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
493        dap::PauseArguments {
494            thread_id: self.thread_id,
495        }
496    }
497
498    fn response_from_dap(
499        &self,
500        _message: <Self::DapRequest as dap::requests::Request>::Response,
501    ) -> Result<Self::Response> {
502        Ok(())
503    }
504}
505
506impl DapCommand for PauseCommand {
507    type ProtoRequest = proto::DapPauseRequest;
508    type ProtoResponse = proto::Ack;
509
510    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
511        SessionId::from_proto(request.client_id)
512    }
513
514    fn from_proto(request: &Self::ProtoRequest) -> Self {
515        Self {
516            thread_id: request.thread_id,
517        }
518    }
519
520    fn to_proto(
521        &self,
522        debug_client_id: SessionId,
523        upstream_project_id: u64,
524    ) -> proto::DapPauseRequest {
525        proto::DapPauseRequest {
526            project_id: upstream_project_id,
527            client_id: debug_client_id.to_proto(),
528            thread_id: self.thread_id,
529        }
530    }
531
532    fn response_to_proto(
533        _debug_client_id: SessionId,
534        _message: Self::Response,
535    ) -> Self::ProtoResponse {
536        proto::Ack {}
537    }
538
539    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
540        Ok(())
541    }
542}
543
544#[derive(Debug, Hash, PartialEq, Eq)]
545pub(crate) struct DisconnectCommand {
546    pub restart: Option<bool>,
547    pub terminate_debuggee: Option<bool>,
548    pub suspend_debuggee: Option<bool>,
549}
550
551impl LocalDapCommand for DisconnectCommand {
552    type Response = <dap::requests::Disconnect as dap::requests::Request>::Response;
553    type DapRequest = dap::requests::Disconnect;
554
555    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
556        dap::DisconnectArguments {
557            restart: self.restart,
558            terminate_debuggee: self.terminate_debuggee,
559            suspend_debuggee: self.suspend_debuggee,
560        }
561    }
562
563    fn response_from_dap(
564        &self,
565        _message: <Self::DapRequest as dap::requests::Request>::Response,
566    ) -> Result<Self::Response> {
567        Ok(())
568    }
569}
570
571impl DapCommand for DisconnectCommand {
572    type ProtoRequest = proto::DapDisconnectRequest;
573    type ProtoResponse = proto::Ack;
574
575    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
576        SessionId::from_proto(request.client_id)
577    }
578
579    fn from_proto(request: &Self::ProtoRequest) -> Self {
580        Self {
581            restart: request.restart,
582            terminate_debuggee: request.terminate_debuggee,
583            suspend_debuggee: request.suspend_debuggee,
584        }
585    }
586
587    fn to_proto(
588        &self,
589        debug_client_id: SessionId,
590        upstream_project_id: u64,
591    ) -> proto::DapDisconnectRequest {
592        proto::DapDisconnectRequest {
593            project_id: upstream_project_id,
594            client_id: debug_client_id.to_proto(),
595            restart: self.restart,
596            terminate_debuggee: self.terminate_debuggee,
597            suspend_debuggee: self.suspend_debuggee,
598        }
599    }
600
601    fn response_to_proto(
602        _debug_client_id: SessionId,
603        _message: Self::Response,
604    ) -> Self::ProtoResponse {
605        proto::Ack {}
606    }
607
608    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
609        Ok(())
610    }
611}
612
613#[derive(Debug, Hash, PartialEq, Eq)]
614pub(crate) struct TerminateThreadsCommand {
615    pub thread_ids: Option<Vec<i64>>,
616}
617
618impl LocalDapCommand for TerminateThreadsCommand {
619    type Response = <dap::requests::TerminateThreads as dap::requests::Request>::Response;
620    type DapRequest = dap::requests::TerminateThreads;
621
622    fn is_supported(capabilities: &Capabilities) -> bool {
623        capabilities
624            .supports_terminate_threads_request
625            .unwrap_or_default()
626    }
627
628    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
629        dap::TerminateThreadsArguments {
630            thread_ids: self.thread_ids.clone(),
631        }
632    }
633
634    fn response_from_dap(
635        &self,
636        _message: <Self::DapRequest as dap::requests::Request>::Response,
637    ) -> Result<Self::Response> {
638        Ok(())
639    }
640}
641
642impl DapCommand for TerminateThreadsCommand {
643    type ProtoRequest = proto::DapTerminateThreadsRequest;
644    type ProtoResponse = proto::Ack;
645
646    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
647        SessionId::from_proto(request.client_id)
648    }
649
650    fn from_proto(request: &Self::ProtoRequest) -> Self {
651        let thread_ids = if request.thread_ids.is_empty() {
652            None
653        } else {
654            Some(request.thread_ids.clone())
655        };
656
657        Self { thread_ids }
658    }
659
660    fn to_proto(
661        &self,
662        debug_client_id: SessionId,
663        upstream_project_id: u64,
664    ) -> proto::DapTerminateThreadsRequest {
665        proto::DapTerminateThreadsRequest {
666            project_id: upstream_project_id,
667            client_id: debug_client_id.to_proto(),
668            thread_ids: self.thread_ids.clone().unwrap_or_default(),
669        }
670    }
671
672    fn response_to_proto(
673        _debug_client_id: SessionId,
674        _message: Self::Response,
675    ) -> Self::ProtoResponse {
676        proto::Ack {}
677    }
678
679    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
680        Ok(())
681    }
682}
683
684#[derive(Debug, Hash, PartialEq, Eq)]
685pub(crate) struct TerminateCommand {
686    pub restart: Option<bool>,
687}
688
689impl LocalDapCommand for TerminateCommand {
690    type Response = <dap::requests::Terminate as dap::requests::Request>::Response;
691    type DapRequest = dap::requests::Terminate;
692
693    fn is_supported(capabilities: &Capabilities) -> bool {
694        capabilities.supports_terminate_request.unwrap_or_default()
695    }
696    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
697        dap::TerminateArguments {
698            restart: self.restart,
699        }
700    }
701
702    fn response_from_dap(
703        &self,
704        _message: <Self::DapRequest as dap::requests::Request>::Response,
705    ) -> Result<Self::Response> {
706        Ok(())
707    }
708}
709
710impl DapCommand for TerminateCommand {
711    type ProtoRequest = proto::DapTerminateRequest;
712    type ProtoResponse = proto::Ack;
713
714    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
715        SessionId::from_proto(request.client_id)
716    }
717
718    fn from_proto(request: &Self::ProtoRequest) -> Self {
719        Self {
720            restart: request.restart,
721        }
722    }
723
724    fn to_proto(
725        &self,
726        debug_client_id: SessionId,
727        upstream_project_id: u64,
728    ) -> proto::DapTerminateRequest {
729        proto::DapTerminateRequest {
730            project_id: upstream_project_id,
731            client_id: debug_client_id.to_proto(),
732            restart: self.restart,
733        }
734    }
735
736    fn response_to_proto(
737        _debug_client_id: SessionId,
738        _message: Self::Response,
739    ) -> Self::ProtoResponse {
740        proto::Ack {}
741    }
742
743    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
744        Ok(())
745    }
746}
747
748#[derive(Debug, Hash, PartialEq, Eq)]
749pub(crate) struct RestartCommand {
750    pub raw: serde_json::Value,
751}
752
753impl LocalDapCommand for RestartCommand {
754    type Response = <dap::requests::Restart as dap::requests::Request>::Response;
755    type DapRequest = dap::requests::Restart;
756
757    fn is_supported(capabilities: &Capabilities) -> bool {
758        capabilities.supports_restart_request.unwrap_or_default()
759    }
760
761    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
762        dap::RestartArguments {
763            raw: self.raw.clone(),
764        }
765    }
766
767    fn response_from_dap(
768        &self,
769        _message: <Self::DapRequest as dap::requests::Request>::Response,
770    ) -> Result<Self::Response> {
771        Ok(())
772    }
773}
774
775impl DapCommand for RestartCommand {
776    type ProtoRequest = proto::DapRestartRequest;
777    type ProtoResponse = proto::Ack;
778
779    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
780        SessionId::from_proto(request.client_id)
781    }
782
783    fn from_proto(request: &Self::ProtoRequest) -> Self {
784        Self {
785            raw: serde_json::from_slice(&request.raw_args)
786                .log_err()
787                .unwrap_or(serde_json::Value::Null),
788        }
789    }
790
791    fn to_proto(
792        &self,
793        debug_client_id: SessionId,
794        upstream_project_id: u64,
795    ) -> proto::DapRestartRequest {
796        let raw_args = serde_json::to_vec(&self.raw).log_err().unwrap_or_default();
797
798        proto::DapRestartRequest {
799            project_id: upstream_project_id,
800            client_id: debug_client_id.to_proto(),
801            raw_args,
802        }
803    }
804
805    fn response_to_proto(
806        _debug_client_id: SessionId,
807        _message: Self::Response,
808    ) -> Self::ProtoResponse {
809        proto::Ack {}
810    }
811
812    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
813        Ok(())
814    }
815}
816
817#[derive(Clone, Debug, Hash, PartialEq, Eq)]
818pub struct VariablesCommand {
819    pub variables_reference: u64,
820    pub filter: Option<VariablesArgumentsFilter>,
821    pub start: Option<u64>,
822    pub count: Option<u64>,
823    pub format: Option<ValueFormat>,
824}
825
826impl LocalDapCommand for VariablesCommand {
827    type Response = Vec<Variable>;
828    type DapRequest = dap::requests::Variables;
829    const CACHEABLE: bool = true;
830
831    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
832        dap::VariablesArguments {
833            variables_reference: self.variables_reference,
834            filter: self.filter,
835            start: self.start,
836            count: self.count,
837            format: self.format.clone(),
838        }
839    }
840
841    fn response_from_dap(
842        &self,
843        message: <Self::DapRequest as dap::requests::Request>::Response,
844    ) -> Result<Self::Response> {
845        Ok(message.variables)
846    }
847}
848
849impl DapCommand for VariablesCommand {
850    type ProtoRequest = proto::VariablesRequest;
851    type ProtoResponse = proto::DapVariables;
852
853    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
854        SessionId::from_proto(request.client_id)
855    }
856
857    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
858        proto::VariablesRequest {
859            project_id: upstream_project_id,
860            client_id: debug_client_id.to_proto(),
861            variables_reference: self.variables_reference,
862            filter: None,
863            start: self.start,
864            count: self.count,
865            format: None,
866        }
867    }
868
869    fn from_proto(request: &Self::ProtoRequest) -> Self {
870        Self {
871            variables_reference: request.variables_reference,
872            filter: None,
873            start: request.start,
874            count: request.count,
875            format: None,
876        }
877    }
878
879    fn response_to_proto(
880        debug_client_id: SessionId,
881        message: Self::Response,
882    ) -> Self::ProtoResponse {
883        proto::DapVariables {
884            client_id: debug_client_id.to_proto(),
885            variables: message.to_proto(),
886        }
887    }
888
889    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
890        Ok(Vec::from_proto(message.variables))
891    }
892}
893
894#[derive(Debug, Hash, PartialEq, Eq)]
895pub(crate) struct SetVariableValueCommand {
896    pub name: String,
897    pub value: String,
898    pub variables_reference: u64,
899}
900impl LocalDapCommand for SetVariableValueCommand {
901    type Response = SetVariableResponse;
902    type DapRequest = dap::requests::SetVariable;
903    fn is_supported(capabilities: &Capabilities) -> bool {
904        capabilities.supports_set_variable.unwrap_or_default()
905    }
906    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
907        dap::SetVariableArguments {
908            format: None,
909            name: self.name.clone(),
910            value: self.value.clone(),
911            variables_reference: self.variables_reference,
912        }
913    }
914    fn response_from_dap(
915        &self,
916        message: <Self::DapRequest as dap::requests::Request>::Response,
917    ) -> Result<Self::Response> {
918        Ok(message)
919    }
920}
921
922impl DapCommand for SetVariableValueCommand {
923    type ProtoRequest = proto::DapSetVariableValueRequest;
924    type ProtoResponse = proto::DapSetVariableValueResponse;
925
926    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
927        SessionId::from_proto(request.client_id)
928    }
929
930    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
931        proto::DapSetVariableValueRequest {
932            project_id: upstream_project_id,
933            client_id: debug_client_id.to_proto(),
934            variables_reference: self.variables_reference,
935            value: self.value.clone(),
936            name: self.name.clone(),
937        }
938    }
939
940    fn from_proto(request: &Self::ProtoRequest) -> Self {
941        Self {
942            variables_reference: request.variables_reference,
943            name: request.name.clone(),
944            value: request.value.clone(),
945        }
946    }
947
948    fn response_to_proto(
949        debug_client_id: SessionId,
950        message: Self::Response,
951    ) -> Self::ProtoResponse {
952        proto::DapSetVariableValueResponse {
953            client_id: debug_client_id.to_proto(),
954            value: message.value,
955            variable_type: message.type_,
956            named_variables: message.named_variables,
957            variables_reference: message.variables_reference,
958            indexed_variables: message.indexed_variables,
959            memory_reference: message.memory_reference,
960        }
961    }
962
963    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
964        Ok(SetVariableResponse {
965            value: message.value,
966            type_: message.variable_type,
967            variables_reference: message.variables_reference,
968            named_variables: message.named_variables,
969            indexed_variables: message.indexed_variables,
970            memory_reference: message.memory_reference,
971            value_location_reference: None, // TODO
972        })
973    }
974}
975
976#[derive(Debug, Clone, Hash, PartialEq, Eq)]
977pub(crate) struct RestartStackFrameCommand {
978    pub stack_frame_id: u64,
979}
980
981impl LocalDapCommand for RestartStackFrameCommand {
982    type Response = <dap::requests::RestartFrame as dap::requests::Request>::Response;
983    type DapRequest = dap::requests::RestartFrame;
984
985    fn is_supported(capabilities: &Capabilities) -> bool {
986        capabilities.supports_restart_frame.unwrap_or_default()
987    }
988
989    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
990        dap::RestartFrameArguments {
991            frame_id: self.stack_frame_id,
992        }
993    }
994
995    fn response_from_dap(
996        &self,
997        _message: <Self::DapRequest as dap::requests::Request>::Response,
998    ) -> Result<Self::Response> {
999        Ok(())
1000    }
1001}
1002
1003impl DapCommand for RestartStackFrameCommand {
1004    type ProtoRequest = proto::DapRestartStackFrameRequest;
1005    type ProtoResponse = proto::Ack;
1006
1007    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1008        SessionId::from_proto(request.client_id)
1009    }
1010
1011    fn from_proto(request: &Self::ProtoRequest) -> Self {
1012        Self {
1013            stack_frame_id: request.stack_frame_id,
1014        }
1015    }
1016
1017    fn to_proto(
1018        &self,
1019        debug_client_id: SessionId,
1020        upstream_project_id: u64,
1021    ) -> proto::DapRestartStackFrameRequest {
1022        proto::DapRestartStackFrameRequest {
1023            project_id: upstream_project_id,
1024            client_id: debug_client_id.to_proto(),
1025            stack_frame_id: self.stack_frame_id,
1026        }
1027    }
1028
1029    fn response_to_proto(
1030        _debug_client_id: SessionId,
1031        _message: Self::Response,
1032    ) -> Self::ProtoResponse {
1033        proto::Ack {}
1034    }
1035
1036    fn response_from_proto(&self, _message: Self::ProtoResponse) -> Result<Self::Response> {
1037        Ok(())
1038    }
1039}
1040
1041#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1042pub(crate) struct ModulesCommand;
1043
1044impl LocalDapCommand for ModulesCommand {
1045    type Response = Vec<dap::Module>;
1046    type DapRequest = dap::requests::Modules;
1047    const CACHEABLE: bool = true;
1048
1049    fn is_supported(capabilities: &Capabilities) -> bool {
1050        capabilities.supports_modules_request.unwrap_or_default()
1051    }
1052
1053    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1054        dap::ModulesArguments {
1055            start_module: None,
1056            module_count: None,
1057        }
1058    }
1059
1060    fn response_from_dap(
1061        &self,
1062        message: <Self::DapRequest as dap::requests::Request>::Response,
1063    ) -> Result<Self::Response> {
1064        Ok(message.modules)
1065    }
1066}
1067
1068impl DapCommand for ModulesCommand {
1069    type ProtoRequest = proto::DapModulesRequest;
1070    type ProtoResponse = proto::DapModulesResponse;
1071
1072    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1073        SessionId::from_proto(request.client_id)
1074    }
1075
1076    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1077        Self {}
1078    }
1079
1080    fn to_proto(
1081        &self,
1082        debug_client_id: SessionId,
1083        upstream_project_id: u64,
1084    ) -> proto::DapModulesRequest {
1085        proto::DapModulesRequest {
1086            project_id: upstream_project_id,
1087            client_id: debug_client_id.to_proto(),
1088        }
1089    }
1090
1091    fn response_to_proto(
1092        debug_client_id: SessionId,
1093        message: Self::Response,
1094    ) -> Self::ProtoResponse {
1095        proto::DapModulesResponse {
1096            modules: message
1097                .into_iter()
1098                .map(|module| module.to_proto())
1099                .collect(),
1100            client_id: debug_client_id.to_proto(),
1101        }
1102    }
1103
1104    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1105        Ok(message
1106            .modules
1107            .into_iter()
1108            .filter_map(|module| dap::Module::from_proto(module).ok())
1109            .collect())
1110    }
1111}
1112
1113#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1114pub(crate) struct LoadedSourcesCommand;
1115
1116impl LocalDapCommand for LoadedSourcesCommand {
1117    type Response = Vec<dap::Source>;
1118    type DapRequest = dap::requests::LoadedSources;
1119    const CACHEABLE: bool = true;
1120
1121    fn is_supported(capabilities: &Capabilities) -> bool {
1122        capabilities
1123            .supports_loaded_sources_request
1124            .unwrap_or_default()
1125    }
1126    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1127        dap::LoadedSourcesArguments {}
1128    }
1129
1130    fn response_from_dap(
1131        &self,
1132        message: <Self::DapRequest as dap::requests::Request>::Response,
1133    ) -> Result<Self::Response> {
1134        Ok(message.sources)
1135    }
1136}
1137
1138impl DapCommand for LoadedSourcesCommand {
1139    type ProtoRequest = proto::DapLoadedSourcesRequest;
1140    type ProtoResponse = proto::DapLoadedSourcesResponse;
1141
1142    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1143        SessionId::from_proto(request.client_id)
1144    }
1145
1146    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1147        Self {}
1148    }
1149
1150    fn to_proto(
1151        &self,
1152        debug_client_id: SessionId,
1153        upstream_project_id: u64,
1154    ) -> proto::DapLoadedSourcesRequest {
1155        proto::DapLoadedSourcesRequest {
1156            project_id: upstream_project_id,
1157            client_id: debug_client_id.to_proto(),
1158        }
1159    }
1160
1161    fn response_to_proto(
1162        debug_client_id: SessionId,
1163        message: Self::Response,
1164    ) -> Self::ProtoResponse {
1165        proto::DapLoadedSourcesResponse {
1166            sources: message
1167                .into_iter()
1168                .map(|source| source.to_proto())
1169                .collect(),
1170            client_id: debug_client_id.to_proto(),
1171        }
1172    }
1173
1174    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1175        Ok(message
1176            .sources
1177            .into_iter()
1178            .map(dap::Source::from_proto)
1179            .collect())
1180    }
1181}
1182
1183#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1184pub(crate) struct StackTraceCommand {
1185    pub thread_id: i64,
1186    pub start_frame: Option<u64>,
1187    pub levels: Option<u64>,
1188}
1189
1190impl LocalDapCommand for StackTraceCommand {
1191    type Response = Vec<dap::StackFrame>;
1192    type DapRequest = dap::requests::StackTrace;
1193    const CACHEABLE: bool = true;
1194
1195    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1196        dap::StackTraceArguments {
1197            thread_id: self.thread_id,
1198            start_frame: self.start_frame,
1199            levels: self.levels,
1200            format: None,
1201        }
1202    }
1203
1204    fn response_from_dap(
1205        &self,
1206        message: <Self::DapRequest as dap::requests::Request>::Response,
1207    ) -> Result<Self::Response> {
1208        Ok(message.stack_frames)
1209    }
1210}
1211
1212impl DapCommand for StackTraceCommand {
1213    type ProtoRequest = proto::DapStackTraceRequest;
1214    type ProtoResponse = proto::DapStackTraceResponse;
1215
1216    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1217        proto::DapStackTraceRequest {
1218            project_id: upstream_project_id,
1219            client_id: debug_client_id.to_proto(),
1220            thread_id: self.thread_id,
1221            start_frame: self.start_frame,
1222            stack_trace_levels: self.levels,
1223        }
1224    }
1225
1226    fn from_proto(request: &Self::ProtoRequest) -> Self {
1227        Self {
1228            thread_id: request.thread_id,
1229            start_frame: request.start_frame,
1230            levels: request.stack_trace_levels,
1231        }
1232    }
1233
1234    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1235        SessionId::from_proto(request.client_id)
1236    }
1237
1238    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1239        Ok(message
1240            .frames
1241            .into_iter()
1242            .map(dap::StackFrame::from_proto)
1243            .collect())
1244    }
1245
1246    fn response_to_proto(
1247        _debug_client_id: SessionId,
1248        message: Self::Response,
1249    ) -> Self::ProtoResponse {
1250        proto::DapStackTraceResponse {
1251            frames: message.to_proto(),
1252        }
1253    }
1254}
1255
1256#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1257pub(crate) struct ScopesCommand {
1258    pub stack_frame_id: u64,
1259}
1260
1261impl LocalDapCommand for ScopesCommand {
1262    type Response = Vec<dap::Scope>;
1263    type DapRequest = dap::requests::Scopes;
1264    const CACHEABLE: bool = true;
1265
1266    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1267        dap::ScopesArguments {
1268            frame_id: self.stack_frame_id,
1269        }
1270    }
1271
1272    fn response_from_dap(
1273        &self,
1274        message: <Self::DapRequest as dap::requests::Request>::Response,
1275    ) -> Result<Self::Response> {
1276        Ok(message.scopes)
1277    }
1278}
1279
1280impl DapCommand for ScopesCommand {
1281    type ProtoRequest = proto::DapScopesRequest;
1282    type ProtoResponse = proto::DapScopesResponse;
1283
1284    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1285        proto::DapScopesRequest {
1286            project_id: upstream_project_id,
1287            client_id: debug_client_id.to_proto(),
1288            stack_frame_id: self.stack_frame_id,
1289        }
1290    }
1291
1292    fn from_proto(request: &Self::ProtoRequest) -> Self {
1293        Self {
1294            stack_frame_id: request.stack_frame_id,
1295        }
1296    }
1297
1298    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1299        SessionId::from_proto(request.client_id)
1300    }
1301
1302    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1303        Ok(Vec::from_proto(message.scopes))
1304    }
1305
1306    fn response_to_proto(
1307        _debug_client_id: SessionId,
1308        message: Self::Response,
1309    ) -> Self::ProtoResponse {
1310        proto::DapScopesResponse {
1311            scopes: message.to_proto(),
1312        }
1313    }
1314}
1315
1316impl LocalDapCommand for super::session::CompletionsQuery {
1317    type Response = dap::CompletionsResponse;
1318    type DapRequest = dap::requests::Completions;
1319    const CACHEABLE: bool = true;
1320
1321    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1322        dap::CompletionsArguments {
1323            text: self.query.clone(),
1324            frame_id: self.frame_id,
1325            column: self.column,
1326            line: None,
1327        }
1328    }
1329
1330    fn response_from_dap(
1331        &self,
1332        message: <Self::DapRequest as dap::requests::Request>::Response,
1333    ) -> Result<Self::Response> {
1334        Ok(message)
1335    }
1336
1337    fn is_supported(capabilities: &Capabilities) -> bool {
1338        capabilities
1339            .supports_completions_request
1340            .unwrap_or_default()
1341    }
1342}
1343
1344impl DapCommand for super::session::CompletionsQuery {
1345    type ProtoRequest = proto::DapCompletionRequest;
1346    type ProtoResponse = proto::DapCompletionResponse;
1347
1348    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1349        proto::DapCompletionRequest {
1350            client_id: debug_client_id.to_proto(),
1351            project_id: upstream_project_id,
1352            frame_id: self.frame_id,
1353            query: self.query.clone(),
1354            column: self.column,
1355            line: self.line,
1356        }
1357    }
1358
1359    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1360        SessionId::from_proto(request.client_id)
1361    }
1362
1363    fn from_proto(request: &Self::ProtoRequest) -> Self {
1364        Self {
1365            query: request.query.clone(),
1366            frame_id: request.frame_id,
1367            column: request.column,
1368            line: request.line,
1369        }
1370    }
1371
1372    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1373        Ok(dap::CompletionsResponse {
1374            targets: Vec::from_proto(message.completions),
1375        })
1376    }
1377
1378    fn response_to_proto(
1379        _debug_client_id: SessionId,
1380        message: Self::Response,
1381    ) -> Self::ProtoResponse {
1382        proto::DapCompletionResponse {
1383            client_id: _debug_client_id.to_proto(),
1384            completions: message.targets.to_proto(),
1385        }
1386    }
1387}
1388
1389#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1390pub(crate) struct EvaluateCommand {
1391    pub expression: String,
1392    pub frame_id: Option<u64>,
1393    pub context: Option<dap::EvaluateArgumentsContext>,
1394    pub source: Option<dap::Source>,
1395}
1396
1397impl LocalDapCommand for EvaluateCommand {
1398    type Response = dap::EvaluateResponse;
1399    type DapRequest = dap::requests::Evaluate;
1400    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1401        dap::EvaluateArguments {
1402            expression: self.expression.clone(),
1403            frame_id: self.frame_id,
1404            context: self.context.clone(),
1405            source: self.source.clone(),
1406            line: None,
1407            column: None,
1408            format: None,
1409        }
1410    }
1411
1412    fn response_from_dap(
1413        &self,
1414        message: <Self::DapRequest as dap::requests::Request>::Response,
1415    ) -> Result<Self::Response> {
1416        Ok(message)
1417    }
1418}
1419impl DapCommand for EvaluateCommand {
1420    type ProtoRequest = proto::DapEvaluateRequest;
1421    type ProtoResponse = proto::DapEvaluateResponse;
1422
1423    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1424        proto::DapEvaluateRequest {
1425            client_id: debug_client_id.to_proto(),
1426            project_id: upstream_project_id,
1427            expression: self.expression.clone(),
1428            frame_id: self.frame_id,
1429            context: self
1430                .context
1431                .clone()
1432                .map(|context| context.to_proto().into()),
1433        }
1434    }
1435
1436    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1437        SessionId::from_proto(request.client_id)
1438    }
1439
1440    fn from_proto(request: &Self::ProtoRequest) -> Self {
1441        Self {
1442            expression: request.expression.clone(),
1443            frame_id: request.frame_id,
1444            context: Some(dap::EvaluateArgumentsContext::from_proto(request.context())),
1445            source: None,
1446        }
1447    }
1448
1449    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1450        Ok(dap::EvaluateResponse {
1451            result: message.result.clone(),
1452            type_: message.evaluate_type.clone(),
1453            presentation_hint: None,
1454            variables_reference: message.variable_reference,
1455            named_variables: message.named_variables,
1456            indexed_variables: message.indexed_variables,
1457            memory_reference: message.memory_reference,
1458            value_location_reference: None, //TODO
1459        })
1460    }
1461
1462    fn response_to_proto(
1463        _debug_client_id: SessionId,
1464        message: Self::Response,
1465    ) -> Self::ProtoResponse {
1466        proto::DapEvaluateResponse {
1467            result: message.result,
1468            evaluate_type: message.type_,
1469            variable_reference: message.variables_reference,
1470            named_variables: message.named_variables,
1471            indexed_variables: message.indexed_variables,
1472            memory_reference: message.memory_reference,
1473        }
1474    }
1475}
1476
1477#[derive(Debug, Clone, Hash, PartialEq, Eq)]
1478pub(crate) struct ThreadsCommand;
1479
1480impl LocalDapCommand for ThreadsCommand {
1481    type Response = Vec<dap::Thread>;
1482    type DapRequest = dap::requests::Threads;
1483    const CACHEABLE: bool = true;
1484
1485    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1486        dap::ThreadsArgument {}
1487    }
1488
1489    fn response_from_dap(
1490        &self,
1491        message: <Self::DapRequest as dap::requests::Request>::Response,
1492    ) -> Result<Self::Response> {
1493        Ok(message.threads)
1494    }
1495}
1496
1497impl DapCommand for ThreadsCommand {
1498    type ProtoRequest = proto::DapThreadsRequest;
1499    type ProtoResponse = proto::DapThreadsResponse;
1500
1501    fn to_proto(&self, debug_client_id: SessionId, upstream_project_id: u64) -> Self::ProtoRequest {
1502        proto::DapThreadsRequest {
1503            project_id: upstream_project_id,
1504            client_id: debug_client_id.to_proto(),
1505        }
1506    }
1507
1508    fn from_proto(_request: &Self::ProtoRequest) -> Self {
1509        Self {}
1510    }
1511
1512    fn client_id_from_proto(request: &Self::ProtoRequest) -> SessionId {
1513        SessionId::from_proto(request.client_id)
1514    }
1515
1516    fn response_from_proto(&self, message: Self::ProtoResponse) -> Result<Self::Response> {
1517        Ok(Vec::from_proto(message.threads))
1518    }
1519
1520    fn response_to_proto(
1521        _debug_client_id: SessionId,
1522        message: Self::Response,
1523    ) -> Self::ProtoResponse {
1524        proto::DapThreadsResponse {
1525            threads: message.to_proto(),
1526        }
1527    }
1528}
1529
1530#[derive(Clone, Debug, Hash, PartialEq)]
1531pub(super) struct Initialize {
1532    pub(super) adapter_id: String,
1533}
1534
1535fn dap_client_capabilities(adapter_id: String) -> InitializeRequestArguments {
1536    InitializeRequestArguments {
1537        client_id: Some("zed".to_owned()),
1538        client_name: Some("Zed".to_owned()),
1539        adapter_id,
1540        locale: Some("en-US".to_owned()),
1541        path_format: Some(InitializeRequestArgumentsPathFormat::Path),
1542        supports_variable_type: Some(true),
1543        supports_variable_paging: Some(false),
1544        supports_run_in_terminal_request: Some(true),
1545        supports_memory_references: Some(true),
1546        supports_progress_reporting: Some(false),
1547        supports_invalidated_event: Some(false),
1548        lines_start_at1: Some(true),
1549        columns_start_at1: Some(true),
1550        supports_memory_event: Some(false),
1551        supports_args_can_be_interpreted_by_shell: Some(false),
1552        supports_start_debugging_request: Some(true),
1553        supports_ansistyling: Some(true),
1554    }
1555}
1556
1557impl LocalDapCommand for Initialize {
1558    type Response = Capabilities;
1559    type DapRequest = dap::requests::Initialize;
1560
1561    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1562        dap_client_capabilities(self.adapter_id.clone())
1563    }
1564
1565    fn response_from_dap(
1566        &self,
1567        message: <Self::DapRequest as dap::requests::Request>::Response,
1568    ) -> Result<Self::Response> {
1569        Ok(message)
1570    }
1571}
1572
1573#[derive(Clone, Debug, Hash, PartialEq)]
1574pub(super) struct ConfigurationDone {}
1575
1576impl LocalDapCommand for ConfigurationDone {
1577    type Response = ();
1578    type DapRequest = dap::requests::ConfigurationDone;
1579
1580    fn is_supported(capabilities: &Capabilities) -> bool {
1581        capabilities
1582            .supports_configuration_done_request
1583            .unwrap_or_default()
1584    }
1585
1586    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1587        dap::ConfigurationDoneArguments {}
1588    }
1589
1590    fn response_from_dap(
1591        &self,
1592        message: <Self::DapRequest as dap::requests::Request>::Response,
1593    ) -> Result<Self::Response> {
1594        Ok(message)
1595    }
1596}
1597
1598#[derive(Clone, Debug, Hash, PartialEq)]
1599pub(super) struct Launch {
1600    pub(super) raw: Value,
1601}
1602
1603impl LocalDapCommand for Launch {
1604    type Response = ();
1605    type DapRequest = dap::requests::Launch;
1606
1607    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1608        dap::LaunchRequestArguments {
1609            raw: self.raw.clone(),
1610        }
1611    }
1612
1613    fn response_from_dap(
1614        &self,
1615        message: <Self::DapRequest as dap::requests::Request>::Response,
1616    ) -> Result<Self::Response> {
1617        Ok(message)
1618    }
1619}
1620
1621#[derive(Clone, Debug, Hash, PartialEq)]
1622pub(super) struct Attach {
1623    pub(super) raw: Value,
1624}
1625
1626impl LocalDapCommand for Attach {
1627    type Response = ();
1628    type DapRequest = dap::requests::Attach;
1629
1630    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1631        dap::AttachRequestArguments {
1632            raw: self.raw.clone(),
1633        }
1634    }
1635
1636    fn response_from_dap(
1637        &self,
1638        message: <Self::DapRequest as dap::requests::Request>::Response,
1639    ) -> Result<Self::Response> {
1640        Ok(message)
1641    }
1642}
1643
1644#[derive(Clone, Debug, Hash, PartialEq)]
1645pub(super) struct SetBreakpoints {
1646    pub(super) source: dap::Source,
1647    pub(super) breakpoints: Vec<SourceBreakpoint>,
1648    pub(super) source_modified: Option<bool>,
1649}
1650
1651impl LocalDapCommand for SetBreakpoints {
1652    type Response = Vec<dap::Breakpoint>;
1653    type DapRequest = dap::requests::SetBreakpoints;
1654
1655    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1656        dap::SetBreakpointsArguments {
1657            lines: None,
1658            source_modified: self.source_modified,
1659            source: self.source.clone(),
1660            breakpoints: Some(self.breakpoints.clone()),
1661        }
1662    }
1663
1664    fn response_from_dap(
1665        &self,
1666        message: <Self::DapRequest as dap::requests::Request>::Response,
1667    ) -> Result<Self::Response> {
1668        Ok(message.breakpoints)
1669    }
1670}
1671
1672#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1673pub enum DataBreakpointContext {
1674    Variable {
1675        variables_reference: u64,
1676        name: String,
1677        bytes: Option<u64>,
1678    },
1679    Expression {
1680        expression: String,
1681        frame_id: Option<u64>,
1682    },
1683    Address {
1684        address: String,
1685        bytes: Option<u64>,
1686    },
1687}
1688
1689impl DataBreakpointContext {
1690    pub fn human_readable_label(&self) -> String {
1691        match self {
1692            DataBreakpointContext::Variable { name, .. } => format!("Variable: {}", name),
1693            DataBreakpointContext::Expression { expression, .. } => {
1694                format!("Expression: {}", expression)
1695            }
1696            DataBreakpointContext::Address { address, bytes } => {
1697                let mut label = format!("Address: {}", address);
1698                if let Some(bytes) = bytes {
1699                    label.push_str(&format!(
1700                        " ({} byte{})",
1701                        bytes,
1702                        if *bytes == 1 { "" } else { "s" }
1703                    ));
1704                }
1705                label
1706            }
1707        }
1708    }
1709}
1710
1711#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1712pub(crate) struct DataBreakpointInfoCommand {
1713    pub context: Arc<DataBreakpointContext>,
1714    pub mode: Option<String>,
1715}
1716
1717impl LocalDapCommand for DataBreakpointInfoCommand {
1718    type Response = dap::DataBreakpointInfoResponse;
1719    type DapRequest = dap::requests::DataBreakpointInfo;
1720    const CACHEABLE: bool = true;
1721
1722    // todo(debugger): We should expand this trait in the future to take a &self
1723    // Depending on this command is_supported could be differentb
1724    fn is_supported(capabilities: &Capabilities) -> bool {
1725        capabilities.supports_data_breakpoints.unwrap_or(false)
1726    }
1727
1728    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1729        let (variables_reference, name, frame_id, as_address, bytes) = match &*self.context {
1730            DataBreakpointContext::Variable {
1731                variables_reference,
1732                name,
1733                bytes,
1734            } => (
1735                Some(*variables_reference),
1736                name.clone(),
1737                None,
1738                Some(false),
1739                *bytes,
1740            ),
1741            DataBreakpointContext::Expression {
1742                expression,
1743                frame_id,
1744            } => (None, expression.clone(), *frame_id, Some(false), None),
1745            DataBreakpointContext::Address { address, bytes } => {
1746                (None, address.clone(), None, Some(true), *bytes)
1747            }
1748        };
1749
1750        dap::DataBreakpointInfoArguments {
1751            variables_reference,
1752            name,
1753            frame_id,
1754            bytes,
1755            as_address,
1756            mode: self.mode.clone(),
1757        }
1758    }
1759
1760    fn response_from_dap(
1761        &self,
1762        message: <Self::DapRequest as dap::requests::Request>::Response,
1763    ) -> Result<Self::Response> {
1764        Ok(message)
1765    }
1766}
1767
1768#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1769pub(crate) struct SetDataBreakpointsCommand {
1770    pub breakpoints: Vec<dap::DataBreakpoint>,
1771}
1772
1773impl LocalDapCommand for SetDataBreakpointsCommand {
1774    type Response = Vec<dap::Breakpoint>;
1775    type DapRequest = dap::requests::SetDataBreakpoints;
1776
1777    fn is_supported(capabilities: &Capabilities) -> bool {
1778        capabilities.supports_data_breakpoints.unwrap_or(false)
1779    }
1780
1781    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1782        dap::SetDataBreakpointsArguments {
1783            breakpoints: self.breakpoints.clone(),
1784        }
1785    }
1786
1787    fn response_from_dap(
1788        &self,
1789        message: <Self::DapRequest as dap::requests::Request>::Response,
1790    ) -> Result<Self::Response> {
1791        Ok(message.breakpoints)
1792    }
1793}
1794
1795#[derive(Clone, Debug, Hash, PartialEq)]
1796pub(super) enum SetExceptionBreakpoints {
1797    Plain {
1798        filters: Vec<String>,
1799    },
1800    WithOptions {
1801        filters: Vec<ExceptionFilterOptions>,
1802    },
1803}
1804
1805impl LocalDapCommand for SetExceptionBreakpoints {
1806    type Response = Vec<dap::Breakpoint>;
1807    type DapRequest = dap::requests::SetExceptionBreakpoints;
1808
1809    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1810        match self {
1811            SetExceptionBreakpoints::Plain { filters } => dap::SetExceptionBreakpointsArguments {
1812                filters: filters.clone(),
1813                exception_options: None,
1814                filter_options: None,
1815            },
1816            SetExceptionBreakpoints::WithOptions { filters } => {
1817                dap::SetExceptionBreakpointsArguments {
1818                    filters: vec![],
1819                    filter_options: Some(filters.clone()),
1820                    exception_options: None,
1821                }
1822            }
1823        }
1824    }
1825
1826    fn response_from_dap(
1827        &self,
1828        message: <Self::DapRequest as dap::requests::Request>::Response,
1829    ) -> Result<Self::Response> {
1830        Ok(message.breakpoints.unwrap_or_default())
1831    }
1832}
1833
1834#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1835pub(super) struct LocationsCommand {
1836    pub(super) reference: u64,
1837}
1838
1839impl LocalDapCommand for LocationsCommand {
1840    type Response = dap::LocationsResponse;
1841    type DapRequest = dap::requests::Locations;
1842    const CACHEABLE: bool = true;
1843
1844    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1845        dap::LocationsArguments {
1846            location_reference: self.reference,
1847        }
1848    }
1849
1850    fn response_from_dap(
1851        &self,
1852        message: <Self::DapRequest as dap::requests::Request>::Response,
1853    ) -> Result<Self::Response> {
1854        Ok(message)
1855    }
1856}
1857
1858impl DapCommand for LocationsCommand {
1859    type ProtoRequest = proto::DapLocationsRequest;
1860    type ProtoResponse = proto::DapLocationsResponse;
1861
1862    fn client_id_from_proto(message: &Self::ProtoRequest) -> SessionId {
1863        SessionId::from_proto(message.session_id)
1864    }
1865
1866    fn from_proto(message: &Self::ProtoRequest) -> Self {
1867        Self {
1868            reference: message.location_reference,
1869        }
1870    }
1871
1872    fn to_proto(&self, session_id: SessionId, project_id: u64) -> Self::ProtoRequest {
1873        proto::DapLocationsRequest {
1874            project_id,
1875            session_id: session_id.to_proto(),
1876            location_reference: self.reference,
1877        }
1878    }
1879
1880    fn response_to_proto(_: SessionId, response: Self::Response) -> Self::ProtoResponse {
1881        proto::DapLocationsResponse {
1882            source: Some(response.source.to_proto()),
1883            line: response.line,
1884            column: response.column,
1885            end_line: response.end_line,
1886            end_column: response.end_column,
1887        }
1888    }
1889
1890    fn response_from_proto(&self, response: Self::ProtoResponse) -> Result<Self::Response> {
1891        Ok(dap::LocationsResponse {
1892            source: response
1893                .source
1894                .map(<dap::Source as ProtoConversion>::from_proto)
1895                .context("Missing `source` field in Locations proto")?,
1896            line: response.line,
1897            column: response.column,
1898            end_line: response.end_line,
1899            end_column: response.end_column,
1900        })
1901    }
1902}
1903
1904#[derive(Clone, Debug, Hash, PartialEq, Eq)]
1905pub(crate) struct ReadMemory {
1906    pub(crate) memory_reference: String,
1907    pub(crate) offset: Option<u64>,
1908    pub(crate) count: u64,
1909}
1910
1911#[derive(Clone, Debug, PartialEq)]
1912pub(crate) struct ReadMemoryResponse {
1913    pub(super) address: Arc<str>,
1914    pub(super) unreadable_bytes: Option<u64>,
1915    pub(super) content: Arc<[u8]>,
1916}
1917
1918impl LocalDapCommand for ReadMemory {
1919    type Response = ReadMemoryResponse;
1920    type DapRequest = dap::requests::ReadMemory;
1921    const CACHEABLE: bool = true;
1922
1923    fn is_supported(capabilities: &Capabilities) -> bool {
1924        capabilities
1925            .supports_read_memory_request
1926            .unwrap_or_default()
1927    }
1928    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1929        dap::ReadMemoryArguments {
1930            memory_reference: self.memory_reference.clone(),
1931            offset: self.offset,
1932            count: self.count,
1933        }
1934    }
1935
1936    fn response_from_dap(
1937        &self,
1938        message: <Self::DapRequest as dap::requests::Request>::Response,
1939    ) -> Result<Self::Response> {
1940        let data = if let Some(data) = message.data {
1941            base64::engine::general_purpose::STANDARD
1942                .decode(data)
1943                .log_err()
1944                .context("parsing base64 data from DAP's ReadMemory response")?
1945        } else {
1946            vec![]
1947        };
1948
1949        Ok(ReadMemoryResponse {
1950            address: message.address.into(),
1951            content: data.into(),
1952            unreadable_bytes: message.unreadable_bytes,
1953        })
1954    }
1955}
1956
1957impl LocalDapCommand for dap::WriteMemoryArguments {
1958    type Response = dap::WriteMemoryResponse;
1959    type DapRequest = dap::requests::WriteMemory;
1960    fn is_supported(capabilities: &Capabilities) -> bool {
1961        capabilities
1962            .supports_write_memory_request
1963            .unwrap_or_default()
1964    }
1965    fn to_dap(&self) -> <Self::DapRequest as dap::requests::Request>::Arguments {
1966        self.clone()
1967    }
1968
1969    fn response_from_dap(
1970        &self,
1971        message: <Self::DapRequest as dap::requests::Request>::Response,
1972    ) -> Result<Self::Response> {
1973        Ok(message)
1974    }
1975}
1976
Served at tenant.openagents/omega Member data and write actions are omitted.