MCPcopy Create free account
hub / github.com/AI45Lab/Code / read_process_output

Function read_process_output

core/src/tools/process.rs:9–89  ·  view source on GitHub ↗
(
    child: &mut Child,
    timeout_secs: u64,
    observer: Option<&dyn CommandOutputObserver>,
)

Source from the content-addressed store, hash-verified

7use tokio::process::Child;
8
9pub(crate) async fn read_process_output(
10 child: &mut Child,
11 timeout_secs: u64,
12 observer: Option<&dyn CommandOutputObserver>,
13) -> (String, bool) {
14 let stdout = match child.stdout.take() {
15 Some(s) => s,
16 None => {
17 return ("Internal error: child stdout not piped".to_string(), false);
18 }
19 };
20 let stderr = match child.stderr.take() {
21 Some(s) => s,
22 None => {
23 return ("Internal error: child stderr not piped".to_string(), false);
24 }
25 };
26
27 let mut stdout_reader = BufReader::new(stdout).lines();
28 let mut stderr_reader = BufReader::new(stderr).lines();
29
30 let mut output = String::new();
31 let mut total_size = 0usize;
32 let mut stdout_done = false;
33 let mut stderr_done = false;
34
35 let timeout = tokio::time::Duration::from_secs(timeout_secs);
36 let result = tokio::time::timeout(timeout, async {
37 loop {
38 if stdout_done && stderr_done {
39 break;
40 }
41 tokio::select! {
42 line = stdout_reader.next_line(), if !stdout_done => {
43 match line {
44 Ok(Some(line)) => {
45 if total_size < MAX_OUTPUT_SIZE {
46 output.push_str(&line);
47 output.push('\n');
48 total_size += line.len() + 1;
49 }
50 if let Some(obs) = observer {
51 let mut delta = line;
52 delta.push('\n');
53 obs.on_output_delta(&delta).await;
54 }
55 }
56 Ok(None) => stdout_done = true,
57 Err(_) => stdout_done = true,
58 }
59 }
60 line = stderr_reader.next_line(), if !stderr_done => {
61 match line {
62 Ok(Some(line)) => {
63 if total_size < MAX_OUTPUT_SIZE {
64 output.push_str(&line);
65 output.push('\n');
66 total_size += line.len() + 1;

Callers 1

execMethod · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected