All checks were successful
BotServer CI / build (push) Successful in 8m37s
Changed tool loading to use relative path from current directory instead of hardcoded HOME/gb path. This makes the code portable across different deployment environments. - Updated use_tool.rs to use std::env::current_dir() - Updated tool_context.rs to use std::env::current_dir() - Added PathBuf import to both files - Tools now load from botserver-stack/data/system/work/ Fixes issue where tools weren't being loaded because .mcp.json files were in a different location than expected. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
112 lines
3.9 KiB
Rust
112 lines
3.9 KiB
Rust
use diesel::prelude::*;
|
|
use log::{debug, info, warn};
|
|
use serde_json::{json, Value};
|
|
use std::path::{Path, PathBuf};
|
|
use uuid::Uuid;
|
|
|
|
use crate::core::shared::utils::DbPool;
|
|
|
|
/// Loads tools for a bot and returns them formatted for OpenAI API
|
|
pub fn get_session_tools(
|
|
db_pool: &DbPool,
|
|
bot_name: &str,
|
|
session_id: &Uuid,
|
|
) -> Result<Vec<Value>, Box<dyn std::error::Error + Send + Sync>> {
|
|
use crate::core::shared::models::schema::{bots, session_tool_associations};
|
|
|
|
// Get bot_id (we use the query to verify the bot exists)
|
|
let mut conn = db_pool.get()?;
|
|
let _bot_id: Uuid = bots::table
|
|
.filter(bots::name.eq(bot_name))
|
|
.select(bots::id)
|
|
.first(&mut *conn)
|
|
.map_err(|e| format!("Failed to get bot_id for bot '{}': {}", bot_name, e))?;
|
|
|
|
// Get tool names associated with this session
|
|
let session_id_str = session_id.to_string();
|
|
let tool_names: Vec<String> = session_tool_associations::table
|
|
.filter(session_tool_associations::session_id.eq(&session_id_str))
|
|
.select(session_tool_associations::tool_name)
|
|
.load::<String>(&mut *conn)
|
|
.map_err(|e| format!("Failed to get tools for session: {}", e))?;
|
|
|
|
if tool_names.is_empty() {
|
|
debug!("No tools associated with session {}", session_id);
|
|
return Ok(vec![]);
|
|
}
|
|
|
|
// Build path to work/{bot_name}.gbai/{bot_name}.gbdialog directory
|
|
// Use relative path from botserver binary location
|
|
let gb_dir = std::env::current_dir()
|
|
.unwrap_or_else(|_| PathBuf::from("."))
|
|
.join("botserver-stack/data/system");
|
|
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);
|
|
|
|
let mut tools = Vec::new();
|
|
|
|
for tool_name in &tool_names {
|
|
// Find the .mcp.json file for this tool
|
|
let mcp_path = work_path.join(format!("{}.mcp.json", tool_name));
|
|
|
|
if !mcp_path.exists() {
|
|
warn!("Tool JSON file not found: {:?}", mcp_path);
|
|
continue;
|
|
}
|
|
|
|
// Read and parse the .mcp.json file
|
|
let mcp_content = std::fs::read_to_string(&mcp_path)
|
|
.map_err(|e| format!("Failed to read tool file {:?}: {}", mcp_path, e))?;
|
|
|
|
let mcp_json: Value = serde_json::from_str(&mcp_content)
|
|
.map_err(|e| format!("Failed to parse tool JSON from {:?}: {}", mcp_path, e))?;
|
|
|
|
// Extract tool information and format for OpenAI
|
|
if let Some(tool) = format_tool_for_openai(&mcp_json, tool_name) {
|
|
tools.push(tool);
|
|
}
|
|
}
|
|
|
|
info!("Loaded {} tools for session {}", tools.len(), session_id);
|
|
Ok(tools)
|
|
}
|
|
|
|
/// Formats a tool definition from .mcp.json format to OpenAI tool format
|
|
fn format_tool_for_openai(mcp_json: &Value, tool_name: &str) -> Option<Value> {
|
|
let _name = mcp_json.get("name")?.as_str()?;
|
|
let description = mcp_json.get("description")?.as_str()?;
|
|
let input_schema = mcp_json.get("input_schema")?;
|
|
|
|
let parameters = input_schema.get("properties")?.as_object()?;
|
|
let required = input_schema.get("required")?.as_array()?;
|
|
|
|
let mut openai_params = serde_json::Map::new();
|
|
|
|
for (param_name, param_info) in parameters {
|
|
let param_obj = param_info.as_object()?;
|
|
let param_desc = param_obj.get("description")?.as_str().unwrap_or("");
|
|
let param_type = param_obj.get("type")?.as_str().unwrap_or("string");
|
|
|
|
openai_params.insert(
|
|
param_name.clone(),
|
|
json!({
|
|
"type": param_type,
|
|
"description": param_desc
|
|
})
|
|
);
|
|
}
|
|
|
|
Some(json!({
|
|
"type": "function",
|
|
"function": {
|
|
"name": tool_name,
|
|
"description": description,
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": openai_params,
|
|
"required": required
|
|
}
|
|
}
|
|
}))
|
|
}
|