1#![forbid(unsafe_code)]
2use std::{
5 future::Future,
6 pin::Pin,
7 sync::{
8 atomic::{AtomicBool, Ordering},
9 Arc,
10 },
11};
12
13use futures_core::Stream;
14use tokio::sync::Notify;
15
16mod builder;
17mod client;
18mod error;
19mod stream_json;
20pub mod wrapper_coverage_manifest;
21
22pub use builder::AiderCliClientBuilder;
23pub use client::AiderCliClient;
24pub use error::AiderCliError;
25pub use stream_json::{
26 parse_stream_json_lines, AiderStreamJsonError, AiderStreamJsonErrorCode, AiderStreamJsonEvent,
27 AiderStreamJsonLine, AiderStreamJsonLineOutcome, AiderStreamJsonParser,
28 AiderStreamJsonResultPayload, AiderStreamJsonRunRequest, AiderToolResultError,
29};
30
31pub type DynAiderStreamJsonEventStream =
32 Pin<Box<dyn Stream<Item = Result<AiderStreamJsonEvent, AiderStreamJsonError>> + Send>>;
33
34pub type DynAiderStreamJsonCompletion =
35 Pin<Box<dyn Future<Output = Result<AiderStreamJsonCompletion, AiderCliError>> + Send>>;
36
37#[derive(Clone)]
38pub struct AiderTerminationHandle {
39 inner: Arc<AiderTerminationInner>,
40}
41
42#[derive(Debug)]
43struct AiderTerminationInner {
44 requested: AtomicBool,
45 notify: Notify,
46}
47
48impl AiderTerminationHandle {
49 fn new() -> Self {
50 Self {
51 inner: Arc::new(AiderTerminationInner {
52 requested: AtomicBool::new(false),
53 notify: Notify::new(),
54 }),
55 }
56 }
57
58 pub fn request_termination(&self) {
59 if !self.inner.requested.swap(true, Ordering::SeqCst) {
60 self.inner.notify.notify_waiters();
61 }
62 }
63
64 fn is_requested(&self) -> bool {
65 self.inner.requested.load(Ordering::SeqCst)
66 }
67
68 async fn requested(&self) {
69 if self.is_requested() {
70 return;
71 }
72
73 let notified = self.inner.notify.notified();
74 if self.is_requested() {
75 return;
76 }
77
78 notified.await;
79 }
80}
81
82impl std::fmt::Debug for AiderTerminationHandle {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 f.debug_struct("AiderTerminationHandle")
85 .field("requested", &self.is_requested())
86 .finish()
87 }
88}
89
90#[derive(Debug, Clone)]
91pub struct AiderStreamJsonCompletion {
92 pub status: std::process::ExitStatus,
93 pub final_text: Option<String>,
94 pub session_id: Option<String>,
95 pub model: Option<String>,
96 pub raw_result: Option<serde_json::Value>,
97}
98
99pub struct AiderStreamJsonHandle {
100 pub events: DynAiderStreamJsonEventStream,
101 pub completion: DynAiderStreamJsonCompletion,
102}
103
104impl std::fmt::Debug for AiderStreamJsonHandle {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 f.debug_struct("AiderStreamJsonHandle")
107 .field("events", &"<stream>")
108 .field("completion", &"<future>")
109 .finish()
110 }
111}
112
113pub struct AiderStreamJsonControlHandle {
114 pub events: DynAiderStreamJsonEventStream,
115 pub completion: DynAiderStreamJsonCompletion,
116 pub termination: AiderTerminationHandle,
117}
118
119impl std::fmt::Debug for AiderStreamJsonControlHandle {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 f.debug_struct("AiderStreamJsonControlHandle")
122 .field("events", &"<stream>")
123 .field("completion", &"<future>")
124 .field("termination", &self.termination)
125 .finish()
126 }
127}