Compare commits
3 commits
de017241f2
...
e9dce53412
| Author | SHA1 | Date | |
|---|---|---|---|
| e9dce53412 | |||
| 66a78912e3 | |||
| c07aee708f |
4 changed files with 83 additions and 66 deletions
|
|
@ -199,16 +199,12 @@ fn associate_tool_with_session(
|
||||||
) -> Result<String, String> {
|
) -> Result<String, String> {
|
||||||
use crate::core::shared::models::schema::session_tool_associations;
|
use crate::core::shared::models::schema::session_tool_associations;
|
||||||
|
|
||||||
// Check if tool's .mcp.json file exists in work directory
|
|
||||||
let home_dir = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
|
||||||
let gb_dir = format!("{}/gb", home_dir);
|
|
||||||
|
|
||||||
// Get bot name to construct the path
|
// Get bot name to construct the path
|
||||||
let bot_name = get_bot_name_from_id(state, &user.bot_id)?;
|
let bot_name = get_bot_name_from_id(state, &user.bot_id)?;
|
||||||
let work_path = Path::new(&gb_dir)
|
let bot_subpath = format!("{}.gbai/{}.gbdialog", bot_name, bot_name);
|
||||||
.join("work")
|
let tool_file = format!("{}.mcp.json", tool_name);
|
||||||
.join(format!("{}.gbai/{}.gbdialog", bot_name, bot_name));
|
|
||||||
let mcp_path = work_path.join(format!("{}.mcp.json", tool_name));
|
let mcp_path = Path::new("./work").join(&bot_subpath).join(&tool_file);
|
||||||
|
|
||||||
trace!("Checking for tool .mcp.json at: {:?}", mcp_path);
|
trace!("Checking for tool .mcp.json at: {:?}", mcp_path);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,18 +36,18 @@ pub fn get_session_tools(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build path to work/{bot_name}.gbai/{bot_name}.gbdialog directory
|
// Build path to work/{bot_name}.gbai/{bot_name}.gbdialog directory
|
||||||
let home_dir = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
let bot_subpath = format!("{}.gbai/{}.gbdialog", bot_name, bot_name);
|
||||||
let gb_dir = format!("{}/gb", home_dir);
|
let work_path = Path::new("./work").join(&bot_subpath);
|
||||||
let work_path = Path::new(&gb_dir).join("work").join(format!("{}.gbai/{}.gbdialog", bot_name, bot_name));
|
|
||||||
|
|
||||||
info!("Loading {} tools for session {} from {:?}", tool_names.len(), session_id, work_path);
|
info!("Loading {} tools for session {}", tool_names.len(), session_id);
|
||||||
|
|
||||||
let mut tools = Vec::new();
|
let mut tools = Vec::new();
|
||||||
|
|
||||||
for tool_name in &tool_names {
|
for tool_name in &tool_names {
|
||||||
// Find the .mcp.json file for this tool
|
// Find the .mcp.json file for this tool
|
||||||
let mcp_path = work_path.join(format!("{}.mcp.json", tool_name));
|
let tool_file = format!("{}.mcp.json", tool_name);
|
||||||
|
|
||||||
|
let mcp_path = work_path.join(&tool_file);
|
||||||
if !mcp_path.exists() {
|
if !mcp_path.exists() {
|
||||||
warn!("Tool JSON file not found: {:?}", mcp_path);
|
warn!("Tool JSON file not found: {:?}", mcp_path);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -180,63 +180,84 @@ pub fn to_array(value: Dynamic) -> Array {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "progress-bars")]
|
|
||||||
pub async fn download_file(url: &str, output_path: &str) -> Result<(), anyhow::Error> {
|
pub async fn download_file(url: &str, output_path: &str) -> Result<(), anyhow::Error> {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use tokio::time::{sleep, timeout};
|
||||||
let url = url.to_string();
|
let url = url.to_string();
|
||||||
let output_path = output_path.to_string();
|
let output_path = output_path.to_string();
|
||||||
let download_handle = tokio::spawn(async move {
|
let download_handle = tokio::spawn(async move {
|
||||||
|
let max_retries = 3;
|
||||||
|
for attempt in 1..=max_retries {
|
||||||
let client = Client::builder()
|
let client = Client::builder()
|
||||||
.user_agent("Mozilla/5.0 (compatible; BotServer/1.0)")
|
.user_agent("Mozilla/5.0 (compatible; BotServer/1.0)")
|
||||||
.connect_timeout(Duration::from_secs(30))
|
.connect_timeout(Duration::from_secs(30))
|
||||||
.read_timeout(Duration::from_secs(300))
|
.read_timeout(Duration::from_secs(60))
|
||||||
.pool_idle_timeout(Duration::from_secs(90))
|
.pool_idle_timeout(Duration::from_secs(90))
|
||||||
.tcp_keepalive(Duration::from_secs(60))
|
.tcp_keepalive(Duration::from_secs(60))
|
||||||
.build()?;
|
.build()?;
|
||||||
let response = client.get(&url).send().await?;
|
match client.get(&url).send().await {
|
||||||
if response.status().is_success() {
|
Ok(mut response) if response.status().is_success() => {
|
||||||
let total_size = response.content_length().unwrap_or(0);
|
let total_size = response.content_length();
|
||||||
let pb = ProgressBar::new(total_size);
|
if let Ok(mut file) = TokioFile::create(&output_path).await {
|
||||||
pb.set_style(ProgressStyle::default_bar()
|
let mut downloaded: u64 = 0;
|
||||||
.template("{msg}\n{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {bytes}/{total_bytes} ({eta})")
|
let mut last_percent = 0;
|
||||||
.unwrap_or(ProgressStyle::default_bar())
|
let mut success = true;
|
||||||
.progress_chars("#>-"));
|
loop {
|
||||||
pb.set_message(format!("Downloading {}", url));
|
match timeout(Duration::from_secs(30), response.chunk()).await {
|
||||||
let mut file = TokioFile::create(&output_path).await?;
|
Ok(Ok(Some(chunk))) => {
|
||||||
let bytes = response.bytes().await?;
|
if file.write_all(&chunk).await.is_err() {
|
||||||
file.write_all(&bytes).await?;
|
success = false;
|
||||||
pb.set_position(bytes.len() as u64);
|
break;
|
||||||
pb.finish_with_message(format!("Downloaded {}", output_path));
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(anyhow::anyhow!("HTTP {}: {}", response.status(), url))
|
|
||||||
}
|
}
|
||||||
});
|
downloaded += chunk.len() as u64;
|
||||||
download_handle.await?
|
if let Some(total) = total_size {
|
||||||
}
|
let percent = (downloaded as f64 / total as f64 * 100.0) as u64;
|
||||||
|
if percent > last_percent && percent % 10 == 0 {
|
||||||
#[cfg(not(feature = "progress-bars"))]
|
println!("Downloading {}: {}%", url, percent);
|
||||||
pub async fn download_file(url: &str, output_path: &str) -> Result<(), anyhow::Error> {
|
last_percent = percent;
|
||||||
use std::time::Duration;
|
|
||||||
let url = url.to_string();
|
|
||||||
let output_path = output_path.to_string();
|
|
||||||
let download_handle = tokio::spawn(async move {
|
|
||||||
let client = Client::builder()
|
|
||||||
.user_agent("Mozilla/5.0 (compatible; BotServer/1.0)")
|
|
||||||
.connect_timeout(Duration::from_secs(30))
|
|
||||||
.read_timeout(Duration::from_secs(300))
|
|
||||||
.pool_idle_timeout(Duration::from_secs(90))
|
|
||||||
.tcp_keepalive(Duration::from_secs(60))
|
|
||||||
.build()?;
|
|
||||||
let response = client.get(&url).send().await?;
|
|
||||||
if response.status().is_success() {
|
|
||||||
let mut file = TokioFile::create(&output_path).await?;
|
|
||||||
let bytes = response.bytes().await?;
|
|
||||||
file.write_all(&bytes).await?;
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(anyhow::anyhow!("HTTP {}: {}", response.status(), url))
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Ok(None)) => break,
|
||||||
|
Ok(Err(e)) => {
|
||||||
|
log::warn!("Chunk error: {}", e);
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
log::warn!("Timeout reading chunk");
|
||||||
|
success = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if success {
|
||||||
|
let check_total = total_size.unwrap_or(downloaded);
|
||||||
|
if downloaded >= check_total {
|
||||||
|
println!("Downloaded {}", output_path);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(response) => {
|
||||||
|
if attempt == max_retries {
|
||||||
|
return Err(anyhow::anyhow!("HTTP {}: {}", response.status(), url));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Request failed: {}", e);
|
||||||
|
if attempt == max_retries {
|
||||||
|
return Err(anyhow::anyhow!("Request failed: {} - {}", url, e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if attempt < max_retries {
|
||||||
|
println!("Timeout/Error downloading {}, retrying attempt {}/{}...", url, attempt + 1, max_retries);
|
||||||
|
sleep(Duration::from_secs(5)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(anyhow::anyhow!("Failed to download {} after {} attempts", url, max_retries))
|
||||||
});
|
});
|
||||||
download_handle.await?
|
download_handle.await?
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -340,7 +340,7 @@ impl LLMProvider for GLMClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep unprocessed data in buffer
|
// Keep unprocessed data in buffer
|
||||||
if let Some(last_newline) = data.rfind('\n') {
|
if let Some(last_newline) = buffer.iter().rposition(|&b| b == b'\n') {
|
||||||
buffer = buffer[last_newline + 1..].to_vec();
|
buffer = buffer[last_newline + 1..].to_vec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue