fix: Update multiple modules for i18n and drive monitoring
Some checks failed
BotServer CI / build (push) Failing after 6m22s
Some checks failed
BotServer CI / build (push) Failing after 6m22s
- Update auto_task modules (app_generator, designer_ai, intent_classifier) - Refactor use_tool.rs for better structure - Update bot core and website crawler - Improve drive_monitor and local_file_monitor - Update bootstrap module Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d1d591ddcb
commit
e34848507d
9 changed files with 63 additions and 59 deletions
|
|
@ -1552,7 +1552,7 @@ impl AppGenerator {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (idx, tool) in llm_app.tools.iter().enumerate() {
|
for (idx, tool) in llm_app.tools.iter().enumerate() {
|
||||||
let tool_path = format!(".gbdialog/tools/{}", tool.filename);
|
let tool_path = format!("{}.gbdialog/tools/{}", llm_app.name, tool.filename);
|
||||||
self.files_written.push(format!("tools/{}", tool.filename));
|
self.files_written.push(format!("tools/{}", tool.filename));
|
||||||
self.bytes_generated += tool.content.len() as u64;
|
self.bytes_generated += tool.content.len() as u64;
|
||||||
|
|
||||||
|
|
@ -1624,7 +1624,7 @@ impl AppGenerator {
|
||||||
);
|
);
|
||||||
|
|
||||||
for (idx, scheduler) in llm_app.schedulers.iter().enumerate() {
|
for (idx, scheduler) in llm_app.schedulers.iter().enumerate() {
|
||||||
let scheduler_path = format!(".gbdialog/schedulers/{}", scheduler.filename);
|
let scheduler_path = format!("{}.gbdialog/schedulers/{}", llm_app.name, scheduler.filename);
|
||||||
self.files_written
|
self.files_written
|
||||||
.push(format!("schedulers/{}", scheduler.filename));
|
.push(format!("schedulers/{}", scheduler.filename));
|
||||||
self.bytes_generated += scheduler.content.len() as u64;
|
self.bytes_generated += scheduler.content.len() as u64;
|
||||||
|
|
|
||||||
|
|
@ -330,8 +330,8 @@ Guidelines:
|
||||||
- STYLE: Changes to CSS files (colors, layout, fonts, spacing)
|
- STYLE: Changes to CSS files (colors, layout, fonts, spacing)
|
||||||
- HTML: Changes to HTML structure (forms, buttons, elements)
|
- HTML: Changes to HTML structure (forms, buttons, elements)
|
||||||
- DATABASE: Adding fields to tables.bas or creating new tables
|
- DATABASE: Adding fields to tables.bas or creating new tables
|
||||||
- TOOL: Creating/modifying .gbdialog/tools/*.bas files
|
- TOOL: Creating/modifying {botname}.gbdialog/tools/*.bas files
|
||||||
- SCHEDULER: Creating/modifying .gbdialog/schedulers/*.bas files
|
- SCHEDULER: Creating/modifying {botname}.gbdialog/schedulers/*.bas files
|
||||||
- Require confirmation for: deletions, bulk changes, database schema changes
|
- Require confirmation for: deletions, bulk changes, database schema changes
|
||||||
- Use the current_app and current_page context to determine which files to modify
|
- Use the current_app and current_page context to determine which files to modify
|
||||||
|
|
||||||
|
|
@ -432,7 +432,7 @@ Respond ONLY with valid JSON."#
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
ModificationType::Tool,
|
ModificationType::Tool,
|
||||||
".gbdialog/tools/new-tool.bas".to_string(),
|
"{botname}.gbdialog/tools/new-tool.bas".to_string(),
|
||||||
)
|
)
|
||||||
} else if lower.contains("schedule")
|
} else if lower.contains("schedule")
|
||||||
|| lower.contains("every day")
|
|| lower.contains("every day")
|
||||||
|
|
@ -441,7 +441,7 @@ Respond ONLY with valid JSON."#
|
||||||
{
|
{
|
||||||
(
|
(
|
||||||
ModificationType::Scheduler,
|
ModificationType::Scheduler,
|
||||||
".gbdialog/schedulers/new-scheduler.bas".to_string(),
|
"{botname}.gbdialog/schedulers/new-scheduler.bas".to_string(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(ModificationType::Unknown, "".to_string())
|
(ModificationType::Unknown, "".to_string())
|
||||||
|
|
@ -762,7 +762,7 @@ Respond ONLY with valid JSON."#
|
||||||
session: &UserSession,
|
session: &UserSession,
|
||||||
) -> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let site_path = self.get_site_path();
|
let site_path = self.get_site_path();
|
||||||
let tools_path = format!("{}/{}.gbai/.gbdialog/tools", site_path, session.bot_id);
|
let tools_path = format!("{}/{}.gbai/{}.gbdialog/tools", site_path, session.bot_id, session.bot_id);
|
||||||
|
|
||||||
let mut tools = Vec::new();
|
let mut tools = Vec::new();
|
||||||
if let Ok(entries) = std::fs::read_dir(&tools_path) {
|
if let Ok(entries) = std::fs::read_dir(&tools_path) {
|
||||||
|
|
@ -783,7 +783,7 @@ Respond ONLY with valid JSON."#
|
||||||
session: &UserSession,
|
session: &UserSession,
|
||||||
) -> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let site_path = self.get_site_path();
|
let site_path = self.get_site_path();
|
||||||
let schedulers_path = format!("{}/{}.gbai/.gbdialog/schedulers", site_path, session.bot_id);
|
let schedulers_path = format!("{}/{}.gbai/{}.gbdialog/schedulers", site_path, session.bot_id, session.bot_id);
|
||||||
|
|
||||||
let mut schedulers = Vec::new();
|
let mut schedulers = Vec::new();
|
||||||
if let Ok(entries) = std::fs::read_dir(&schedulers_path) {
|
if let Ok(entries) = std::fs::read_dir(&schedulers_path) {
|
||||||
|
|
|
||||||
|
|
@ -677,8 +677,8 @@ END ON
|
||||||
Utc::now().format("%Y-%m-%d %H:%M")
|
Utc::now().format("%Y-%m-%d %H:%M")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Save to .gbdialog/events/
|
// Save to {bot_id}.gbdialog/events/
|
||||||
let event_path = format!(".gbdialog/events/{handler_name}");
|
let event_path = format!("{}.gbdialog/events/{handler_name}", session.bot_id);
|
||||||
self.save_basic_file(session.bot_id, &event_path, &basic_code)?;
|
self.save_basic_file(session.bot_id, &event_path, &basic_code)?;
|
||||||
|
|
||||||
Ok(IntentResult {
|
Ok(IntentResult {
|
||||||
|
|
@ -889,8 +889,8 @@ END SCHEDULE
|
||||||
classification.original_text
|
classification.original_text
|
||||||
);
|
);
|
||||||
|
|
||||||
// Save to .gbdialog/schedulers/
|
// Save to {bot_id}.gbdialog/schedulers/
|
||||||
let scheduler_path = format!(".gbdialog/schedulers/{scheduler_file}");
|
let scheduler_path = format!("{}.gbdialog/schedulers/{scheduler_file}", session.bot_id);
|
||||||
self.save_basic_file(session.bot_id, &scheduler_path, &basic_code)?;
|
self.save_basic_file(session.bot_id, &scheduler_path, &basic_code)?;
|
||||||
|
|
||||||
let schedule_id = Uuid::new_v4();
|
let schedule_id = Uuid::new_v4();
|
||||||
|
|
@ -962,7 +962,7 @@ END GOAL
|
||||||
|
|
||||||
// Save to .gbdialog/goals/
|
// Save to .gbdialog/goals/
|
||||||
let goal_file = format!("{}.bas", goal_name.to_lowercase().replace(' ', "-"));
|
let goal_file = format!("{}.bas", goal_name.to_lowercase().replace(' ', "-"));
|
||||||
let goal_path = format!(".gbdialog/goals/{goal_file}");
|
let goal_path = format!("{}.gbdialog/goals/{goal_file}", session.bot_id);
|
||||||
self.save_basic_file(session.bot_id, &goal_path, &basic_code)?;
|
self.save_basic_file(session.bot_id, &goal_path, &basic_code)?;
|
||||||
|
|
||||||
Ok(IntentResult {
|
Ok(IntentResult {
|
||||||
|
|
@ -1029,8 +1029,8 @@ END TRIGGER
|
||||||
classification.original_text
|
classification.original_text
|
||||||
);
|
);
|
||||||
|
|
||||||
// Save to .gbdialog/tools/
|
// Save to {bot_id}.gbdialog/tools/
|
||||||
let tool_path = format!(".gbdialog/tools/{tool_file}");
|
let tool_path = format!("{}.gbdialog/tools/{tool_file}", session.bot_id);
|
||||||
self.save_basic_file(session.bot_id, &tool_path, &basic_code)?;
|
self.save_basic_file(session.bot_id, &tool_path, &basic_code)?;
|
||||||
|
|
||||||
Ok(IntentResult {
|
Ok(IntentResult {
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,14 @@ pub fn use_tool_keyword(state: Arc<AppState>, user: UserSession, engine: &mut En
|
||||||
tool_path_str,
|
tool_path_str,
|
||||||
user_clone.id
|
user_clone.id
|
||||||
);
|
);
|
||||||
let tool_name = tool_path_str
|
// Strip {bot_name}.gbdialog/ or .gbdialog/ prefix, and .bas suffix
|
||||||
.strip_prefix(".gbdialog/")
|
let tool_name = if let Some(idx) = tool_path_str.find(".gbdialog/") {
|
||||||
.unwrap_or(&tool_path_str)
|
tool_path_str[idx + 10..] // Skip past ".gbdialog/"
|
||||||
|
} else {
|
||||||
|
&tool_path_str
|
||||||
|
}
|
||||||
.strip_suffix(".bas")
|
.strip_suffix(".bas")
|
||||||
.unwrap_or(&tool_path_str)
|
.unwrap_or_else(|| &tool_path_str)
|
||||||
.to_string();
|
.to_string();
|
||||||
if tool_name.is_empty() {
|
if tool_name.is_empty() {
|
||||||
return Err(Box::new(rhai::EvalAltResult::ErrorRuntime(
|
return Err(Box::new(rhai::EvalAltResult::ErrorRuntime(
|
||||||
|
|
@ -86,11 +89,14 @@ pub fn use_tool_keyword(state: Arc<AppState>, user: UserSession, engine: &mut En
|
||||||
tool_path_str,
|
tool_path_str,
|
||||||
user_clone2.id
|
user_clone2.id
|
||||||
);
|
);
|
||||||
let tool_name = tool_path_str
|
// Strip {bot_name}.gbdialog/ or .gbdialog/ prefix, and .bas suffix
|
||||||
.strip_prefix(".gbdialog/")
|
let tool_name = if let Some(idx) = tool_path_str.find(".gbdialog/") {
|
||||||
.unwrap_or(&tool_path_str)
|
&tool_path_str[idx + 10..] // Skip past ".gbdialog/"
|
||||||
|
} else {
|
||||||
|
&tool_path_str
|
||||||
|
}
|
||||||
.strip_suffix(".bas")
|
.strip_suffix(".bas")
|
||||||
.unwrap_or(&tool_path_str)
|
.unwrap_or_else(|| &tool_path_str)
|
||||||
.to_string();
|
.to_string();
|
||||||
if tool_name.is_empty() {
|
if tool_name.is_empty() {
|
||||||
return Dynamic::from("ERROR: Invalid tool name");
|
return Dynamic::from("ERROR: Invalid tool name");
|
||||||
|
|
@ -140,11 +146,14 @@ pub fn use_tool_keyword(state: Arc<AppState>, user: UserSession, engine: &mut En
|
||||||
tool_path_str,
|
tool_path_str,
|
||||||
user_clone3.id
|
user_clone3.id
|
||||||
);
|
);
|
||||||
let tool_name = tool_path_str
|
// Strip {bot_name}.gbdialog/ or .gbdialog/ prefix, and .bas suffix
|
||||||
.strip_prefix(".gbdialog/")
|
let tool_name = if let Some(idx) = tool_path_str.find(".gbdialog/") {
|
||||||
.unwrap_or(&tool_path_str)
|
&tool_path_str[idx + 10..] // Skip past ".gbdialog/"
|
||||||
|
} else {
|
||||||
|
&tool_path_str
|
||||||
|
}
|
||||||
.strip_suffix(".bas")
|
.strip_suffix(".bas")
|
||||||
.unwrap_or(&tool_path_str)
|
.unwrap_or_else(|| &tool_path_str)
|
||||||
.to_string();
|
.to_string();
|
||||||
if tool_name.is_empty() {
|
if tool_name.is_empty() {
|
||||||
return Dynamic::from("ERROR: Invalid tool name");
|
return Dynamic::from("ERROR: Invalid tool name");
|
||||||
|
|
|
||||||
|
|
@ -227,8 +227,7 @@ impl BotOrchestrator {
|
||||||
let mut bots_mounted = 0;
|
let mut bots_mounted = 0;
|
||||||
let mut bots_created = 0;
|
let mut bots_created = 0;
|
||||||
|
|
||||||
let home_dir = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
let data_dir = "/opt/gbo/data";
|
||||||
let data_dir = format!("{}/data", home_dir);
|
|
||||||
|
|
||||||
let directories_to_scan: Vec<std::path::PathBuf> = vec![
|
let directories_to_scan: Vec<std::path::PathBuf> = vec![
|
||||||
self.state
|
self.state
|
||||||
|
|
@ -293,9 +292,9 @@ impl BotOrchestrator {
|
||||||
*bots_mounted += 1;
|
*bots_mounted += 1;
|
||||||
}
|
}
|
||||||
Ok(false) => {
|
Ok(false) => {
|
||||||
// Auto-create bots found in ~/data
|
// Auto-create bots found in /opt/gbo/data
|
||||||
if dir_path.to_string_lossy().contains("/data") {
|
if dir_path.to_string_lossy().contains("/data") {
|
||||||
info!("Auto-creating bot '{}' from ~/data", bot_name);
|
info!("Auto-creating bot '{}' from /opt/gbo/data", bot_name);
|
||||||
match self.create_bot_simple(bot_name) {
|
match self.create_bot_simple(bot_name) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
info!("Bot '{}' created successfully", bot_name);
|
info!("Bot '{}' created successfully", bot_name);
|
||||||
|
|
@ -489,8 +488,7 @@ impl BotOrchestrator {
|
||||||
|
|
||||||
if should_execute_start_bas {
|
if should_execute_start_bas {
|
||||||
// Always execute start.bas for this session (blocking - wait for completion)
|
// Always execute start.bas for this session (blocking - wait for completion)
|
||||||
let home_dir = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
let data_dir = "/opt/gbo/data";
|
||||||
let data_dir = format!("{}/data", home_dir);
|
|
||||||
let start_script_path = format!("{}/{}.gbai/{}.gbdialog/start.bas", data_dir, bot_name_for_context, bot_name_for_context);
|
let start_script_path = format!("{}/{}.gbai/{}.gbdialog/start.bas", data_dir, bot_name_for_context, bot_name_for_context);
|
||||||
|
|
||||||
info!("[START_BAS] Executing start.bas for session {} at: {}", actual_session_id, start_script_path);
|
info!("[START_BAS] Executing start.bas for session {} at: {}", actual_session_id, start_script_path);
|
||||||
|
|
@ -1088,8 +1086,7 @@ async fn handle_websocket(
|
||||||
};
|
};
|
||||||
|
|
||||||
if should_execute_start_bas {
|
if should_execute_start_bas {
|
||||||
let home_dir = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
let data_dir = "/opt/gbo/data";
|
||||||
let data_dir = format!("{}/data", home_dir);
|
|
||||||
let start_script_path = format!("{}/{}.gbai/{}.gbdialog/start.bas", data_dir, bot_name, bot_name);
|
let start_script_path = format!("{}/{}.gbai/{}.gbdialog/start.bas", data_dir, bot_name, bot_name);
|
||||||
|
|
||||||
info!("Looking for start.bas at: {}", start_script_path);
|
info!("Looking for start.bas at: {}", start_script_path);
|
||||||
|
|
|
||||||
|
|
@ -352,7 +352,7 @@ impl WebsiteCrawlerService {
|
||||||
Err(_) => continue, // Skip if bot not found
|
Err(_) => continue, // Skip if bot not found
|
||||||
};
|
};
|
||||||
|
|
||||||
// Scan .gbdialog directory for .bas files
|
// Scan {bot_name}.gbdialog directory for .bas files
|
||||||
let dialog_dir = path.join(format!("{}.gbdialog", bot_name));
|
let dialog_dir = path.join(format!("{}.gbdialog", bot_name));
|
||||||
if dialog_dir.exists() {
|
if dialog_dir.exists() {
|
||||||
self.scan_directory_for_websites(&dialog_dir, bot_id, &mut conn)?;
|
self.scan_directory_for_websites(&dialog_dir, bot_id, &mut conn)?;
|
||||||
|
|
|
||||||
|
|
@ -462,7 +462,7 @@ impl DriveMonitor {
|
||||||
&self,
|
&self,
|
||||||
client: &Client,
|
client: &Client,
|
||||||
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
let prefix = ".gbdialog/";
|
// No prefix filter - list all and filter by *.gbdialog pattern below
|
||||||
let mut current_files = HashMap::new();
|
let mut current_files = HashMap::new();
|
||||||
let mut continuation_token = None;
|
let mut continuation_token = None;
|
||||||
loop {
|
loop {
|
||||||
|
|
@ -486,6 +486,7 @@ impl DriveMonitor {
|
||||||
for obj in list_objects.contents.unwrap_or_default() {
|
for obj in list_objects.contents.unwrap_or_default() {
|
||||||
let path = obj.key().unwrap_or_default().to_string();
|
let path = obj.key().unwrap_or_default().to_string();
|
||||||
let path_parts: Vec<&str> = path.split('/').collect();
|
let path_parts: Vec<&str> = path.split('/').collect();
|
||||||
|
// Filter for paths matching *.gbdialog/*.bas pattern
|
||||||
if path_parts.len() < 2 || !path_parts[0].ends_with(".gbdialog") {
|
if path_parts.len() < 2 || !path_parts[0].ends_with(".gbdialog") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,10 +30,8 @@ pub struct LocalFileMonitor {
|
||||||
|
|
||||||
impl LocalFileMonitor {
|
impl LocalFileMonitor {
|
||||||
pub fn new(state: Arc<AppState>) -> Self {
|
pub fn new(state: Arc<AppState>) -> Self {
|
||||||
// Use ~/data as the base directory
|
// Use /opt/gbo/data as the base directory
|
||||||
let data_dir = PathBuf::from(std::env::var("HOME")
|
let data_dir = PathBuf::from("/opt/gbo/data");
|
||||||
.unwrap_or_else(|_| ".".to_string()))
|
|
||||||
.join("data");
|
|
||||||
|
|
||||||
// Use botserver/work as the work directory for generated files
|
// Use botserver/work as the work directory for generated files
|
||||||
let work_root = PathBuf::from("work");
|
let work_root = PathBuf::from("work");
|
||||||
|
|
@ -50,7 +48,7 @@ impl LocalFileMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn start_monitoring(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
pub async fn start_monitoring(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
info!("[LOCAL_MONITOR] Starting local file monitor for ~/data/*.gbai directories");
|
info!("[LOCAL_MONITOR] Starting local file monitor for /opt/gbo/data/*.gbai directories");
|
||||||
|
|
||||||
// Create data directory if it doesn't exist
|
// Create data directory if it doesn't exist
|
||||||
if let Err(e) = tokio::fs::create_dir_all(&self.data_dir).await {
|
if let Err(e) = tokio::fs::create_dir_all(&self.data_dir).await {
|
||||||
|
|
@ -157,7 +155,7 @@ impl LocalFileMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_gbdialog_file(&self, path: &Path) -> bool {
|
fn is_gbdialog_file(&self, path: &Path) -> bool {
|
||||||
// Check if path is something like ~/data/*.gbai/.gbdialog/*.bas
|
// Check if path is something like /opt/gbo/data/*.gbai/.gbdialog/*.bas
|
||||||
path.extension()
|
path.extension()
|
||||||
.and_then(|e| e.to_str())
|
.and_then(|e| e.to_str())
|
||||||
.map(|e| e.eq_ignore_ascii_case("bas"))
|
.map(|e| e.eq_ignore_ascii_case("bas"))
|
||||||
|
|
@ -167,7 +165,7 @@ impl LocalFileMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn scan_and_compile_all(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
async fn scan_and_compile_all(&self) -> Result<(), Box<dyn Error + Send + Sync>> {
|
||||||
debug!("[LOCAL_MONITOR] Scanning ~/data for .gbai directories");
|
debug!("[LOCAL_MONITOR] Scanning /opt/gbo/data for .gbai directories");
|
||||||
|
|
||||||
let entries = match tokio::fs::read_dir(&self.data_dir).await {
|
let entries = match tokio::fs::read_dir(&self.data_dir).await {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
|
|
@ -252,7 +250,7 @@ impl LocalFileMonitor {
|
||||||
.and_then(|s| s.to_str())
|
.and_then(|s| s.to_str())
|
||||||
.unwrap_or("unknown");
|
.unwrap_or("unknown");
|
||||||
|
|
||||||
// Extract bot name from path like ~/data/cristo.gbai/.gbdialog/file.bas
|
// Extract bot name from path like /opt/gbo/data/cristo.gbai/.gbdialog/file.bas
|
||||||
let bot_name = file_path
|
let bot_name = file_path
|
||||||
.ancestors()
|
.ancestors()
|
||||||
.find(|p| p.extension().and_then(|e| e.to_str()).map(|e| e.eq_ignore_ascii_case("gbai")).unwrap_or(false))
|
.find(|p| p.extension().and_then(|e| e.to_str()).map(|e| e.eq_ignore_ascii_case("gbai")).unwrap_or(false))
|
||||||
|
|
|
||||||
|
|
@ -795,29 +795,28 @@ async fn start_drive_monitors(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start local file monitor for ~/data/*.gbai directories
|
// Start local file monitor for /opt/gbo/data/*.gbai directories
|
||||||
let local_monitor_state = app_state.clone();
|
let local_monitor_state = app_state.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
register_thread("local-file-monitor", "drive");
|
register_thread("local-file-monitor", "drive");
|
||||||
trace!("Starting LocalFileMonitor for ~/data/*.gbai directories");
|
trace!("Starting LocalFileMonitor for /opt/gbo/data/*.gbai directories");
|
||||||
let monitor = crate::drive::local_file_monitor::LocalFileMonitor::new(local_monitor_state);
|
let monitor = crate::drive::local_file_monitor::LocalFileMonitor::new(local_monitor_state);
|
||||||
if let Err(e) = monitor.start_monitoring().await {
|
if let Err(e) = monitor.start_monitoring().await {
|
||||||
error!("LocalFileMonitor failed: {}", e);
|
error!("LocalFileMonitor failed: {}", e);
|
||||||
} else {
|
} else {
|
||||||
info!("LocalFileMonitor started - watching ~/data/*.gbai/.gbdialog/*.bas");
|
info!("LocalFileMonitor started - watching /opt/gbo/data/*.gbai/*.gbdialog/*.bas");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Start config file watcher for ~/data/*.gbai/*.gbot/config.csv
|
// Start config file watcher for /opt/gbo/data/*.gbai/*.gbot/config.csv
|
||||||
let config_watcher_state = app_state.clone();
|
let config_watcher_state = app_state.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
register_thread("config-file-watcher", "drive");
|
register_thread("config-file-watcher", "drive");
|
||||||
trace!("Starting ConfigWatcher for ~/data/*.gbai/*.gbot/config.csv");
|
trace!("Starting ConfigWatcher for /opt/gbo/data/*.gbai/*.gbot/config.csv");
|
||||||
|
|
||||||
// Determine data directory
|
// Determine data directory
|
||||||
let data_dir = std::env::var("DATA_DIR")
|
let data_dir = std::env::var("DATA_DIR")
|
||||||
.or_else(|_| std::env::var("HOME").map(|h| format!("{}/data", h)))
|
.unwrap_or_else(|_| "/opt/gbo/data".to_string());
|
||||||
.unwrap_or_else(|_| "./botserver-stack/data".to_string());
|
|
||||||
let data_dir = std::path::PathBuf::from(data_dir);
|
let data_dir = std::path::PathBuf::from(data_dir);
|
||||||
|
|
||||||
let watcher = crate::core::config::watcher::ConfigWatcher::new(
|
let watcher = crate::core::config::watcher::ConfigWatcher::new(
|
||||||
|
|
@ -826,6 +825,6 @@ async fn start_drive_monitors(
|
||||||
);
|
);
|
||||||
Arc::new(watcher).spawn();
|
Arc::new(watcher).spawn();
|
||||||
|
|
||||||
info!("ConfigWatcher started - watching ~/data/*.gbai/*.gbot/config.csv");
|
info!("ConfigWatcher started - watching /opt/gbo/data/*.gbai/*.gbot/config.csv");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue