| 903 | } |
| 904 | |
| 905 | async fn wait_for_server_ready( |
| 906 | base_url: &str, |
| 907 | timeout: Duration, |
| 908 | server_handle: Option<&mut tokio::task::JoinHandle<anyhow::Result<()>>>, |
| 909 | ) -> anyhow::Result<()> { |
| 910 | let client = reqwest::Client::new(); |
| 911 | let start = tokio::time::Instant::now(); |
| 912 | let health = server_url(base_url, "/health"); |
| 913 | let mut server_handle = server_handle; |
| 914 | |
| 915 | loop { |
| 916 | if let Some(handle) = server_handle.as_mut() { |
| 917 | if handle.is_finished() { |
| 918 | match handle.await { |
| 919 | Ok(Ok(())) => { |
| 920 | anyhow::bail!("Local server exited before becoming ready at {}", base_url) |
| 921 | } |
| 922 | Ok(Err(error)) => anyhow::bail!("Local server failed to start: {}", error), |
| 923 | Err(join_error) => anyhow::bail!("Local server task failed: {}", join_error), |
| 924 | } |
| 925 | } |
| 926 | } |
| 927 | |
| 928 | if start.elapsed() > timeout { |
| 929 | anyhow::bail!( |
| 930 | "Timed out waiting for local server to start at {}", |
| 931 | base_url |
| 932 | ); |
| 933 | } |
| 934 | if let Ok(resp) = client.get(&health).send().await { |
| 935 | if resp.status().is_success() { |
| 936 | return Ok(()); |
| 937 | } |
| 938 | } |
| 939 | tokio::time::sleep(Duration::from_millis(100)).await; |
| 940 | } |
| 941 | } |
| 942 | |
| 943 | fn parse_model_and_provider(model: Option<String>) -> (Option<String>, Option<String>) { |
| 944 | let Some(raw) = model else { |