Various updates: dependencies, features, and bug fixes

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2026-01-16 11:29:22 -03:00
parent f42ae6e57c
commit 033bb504b9
24 changed files with 248 additions and 8451 deletions

View file

@ -218,7 +218,7 @@ sha256 = "f96935e7e385e3b2d0189239077c10fe8fd7e95690fea4afec455b1b6c7e3f18"
# Optional larger models (uncomment to include) # Optional larger models (uncomment to include)
# [models.gpt_oss_20b] # [models.gpt_oss_20b]
# name = "GPT-OSS 20B F16 (requires 16GB+ VRAM)" # name = "GPT-OSS 20B F16 (requires 16GB+ VRAM or MoE)"
# url = "https://huggingface.co/unsloth/gpt-oss-20b-GGUF/resolve/main/gpt-oss-20b-F16.gguf" # url = "https://huggingface.co/unsloth/gpt-oss-20b-GGUF/resolve/main/gpt-oss-20b-F16.gguf"
# filename = "gpt-oss-20b-F16.gguf" # filename = "gpt-oss-20b-F16.gguf"
# sha256 = "" # sha256 = ""

8201
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,41 +2,8 @@
name = "botserver" name = "botserver"
version = "6.1.0" version = "6.1.0"
edition = "2021" edition = "2021"
keywords = ["chatbot", "ai", "llm", "automation", "bot-framework"]
categories = ["web-programming", "api-bindings", "development-tools"] # ... [authors, description, license, repository sections remain the same]
authors = [
"Pragmatismo.com.br ",
"General Bots Community ",
"Alan Perdomo",
"Ana Paula Gil",
"Arenas.io",
"Atylla L",
"Christopher de Castilho",
"Dario Junior",
"David Lerner",
"Experimentation Garage",
"Flavio Andrade",
"Heraldo Almeida",
"Joao Parana",
"Jonathas C",
"J Ramos",
"Lucas Picanco",
"Marcos Velasco",
"Matheus 39x",
"Oerlabs Henrique",
"Othon Lima",
"PH Nascimento",
"Phpussente",
"Robson Dantas",
"Rodrigo Rodriguez ",
"Sarah Lourenco",
"Thi Patriota",
"Webgus",
"Zuilho Se",
]
description = "General Bots Server - Open-source bot platform by Pragmatismo.com.br"
license = "AGPL-3.0"
repository = "https://github.com/GeneralBots/BotServer"
[dependencies.botlib] [dependencies.botlib]
path = "../botlib" path = "../botlib"
@ -44,62 +11,106 @@ features = ["database", "i18n"]
[features] [features]
# ===== DEFAULT FEATURE SET ===== # ===== DEFAULT FEATURE SET =====
default = ["console", "chat", "automation", "tasks", "drive", "llm", "cache", "progress-bars", "directory", "calendar", "meet", "email", "whatsapp", "telegram", "learn"] default = ["chat", "drive", "tasks", "automation"]
# ===== UI FEATURES ===== # ===== COMMUNICATION APPS =====
console = ["dep:crossterm", "dep:ratatui", "monitoring"] chat = []
people = []
# ===== CORE INTEGRATIONS ===== mail = ["email", "imap", "lettre", "mailparse", "native-tls"]
vectordb = ["dep:qdrant-client"] meet = ["dep:livekit"]
llm = [] social = []
nvidia = []
# ===== COMMUNICATION CHANNELS =====
email = ["dep:imap", "dep:lettre", "dep:mailparse", "dep:native-tls"]
whatsapp = [] whatsapp = []
telegram = [] telegram = []
instagram = [] instagram = []
msteams = [] msteams = []
communications = ["chat", "people", "mail", "meet", "social", "whatsapp", "telegram", "instagram", "msteams", "cache"]
# ===== PRODUCTIVITY FEATURES ===== # ===== PRODUCTIVITY APPS =====
chat = []
drive = ["dep:aws-config", "dep:aws-sdk-s3", "dep:pdf-extract", "dep:zip", "dep:downloader", "dep:flate2", "dep:tar"]
tasks = ["dep:cron"]
calendar = [] calendar = []
meet = ["dep:livekit"] tasks = ["dep:cron"]
mail = ["email"] project = []
goals = []
workspace = []
productivity = ["calendar", "tasks", "project", "goals", "workspace", "cache"]
# ===== DOCUMENT APPS =====
paper = ["docx-rs", "ooxmlsdk", "dep:pdf-extract"]
docs = ["docx-rs", "ooxmlsdk"]
sheet = ["umya-spreadsheet", "calamine", "rust_xlsxwriter", "spreadsheet-ods"]
slides = ["ooxmlsdk"]
drive = ["dep:aws-config", "dep:aws-sdk-s3", "dep:pdf-extract", "dep:zip", "dep:downloader", "dep:flate2", "dep:tar"]
documents = ["paper", "docs", "sheet", "slides", "drive"]
# ===== MEDIA APPS =====
video = []
player = []
canvas = []
media = ["video", "player", "canvas"]
# ===== LEARNING & RESEARCH APPS =====
learn = [] learn = []
research = ["llm", "vectordb"]
sources = []
learning = ["learn", "research", "sources"]
# ===== ENTERPRISE FEATURES ===== # ===== ANALYTICS APPS =====
compliance = ["dep:csv"] analytics = []
attendance = ["drive"] dashboards = []
directory = []
weba = []
timeseries = []
# ===== OPTIONAL INFRASTRUCTURE =====
cache = ["dep:redis"]
monitoring = ["dep:sysinfo"] monitoring = ["dep:sysinfo"]
automation = ["dep:rhai"] analytics_suite = ["analytics", "dashboards", "monitoring"]
grpc = ["dep:tonic"]
progress-bars = ["dep:indicatif"]
jemalloc = ["dep:tikv-jemallocator", "dep:tikv-jemalloc-ctl"]
# ===== META FEATURES (BUNDLES) ===== # ===== DEVELOPMENT TOOLS =====
designer = []
editor = []
automation = ["dep:rhai", "llm"]
development = ["designer", "editor", "automation"]
# ===== ADMIN APPS =====
attendant = []
security = []
settings = []
admin = ["attendant", "security", "settings"]
# ===== CORE TECHNOLOGIES =====
llm = []
vectordb = ["dep:qdrant-client"]
nvidia = []
email = []
cache = ["dep:redis"]
compliance = ["dep:csv"]
timeseries = []
weba = []
directory = []
progress-bars = ["dep:indicatif"]
grpc = ["dep:tonic"]
jemalloc = ["dep:tikv-jemallocator", "dep:tikv-jemalloc-ctl"]
console = ["dep:crossterm", "dep:ratatui", "monitoring"]
# ===== BUNDLE FEATURES =====
full = [ full = [
"console", # Communication
"vectordb", "llm", "nvidia", "timeseries", "chat", "people", "mail", "meet", "social", "whatsapp", "telegram", "instagram", "msteams",
"email", "whatsapp", "instagram", "msteams", # Productivity
"chat", "drive", "tasks", "calendar", "meet", "mail", "calendar", "tasks", "project", "goals", "workspace",
"compliance", "attendance", "directory", "weba", # Documents
"cache", "monitoring", "automation", "grpc", "progress-bars" "paper", "docs", "sheet", "slides", "drive",
# Media
"video", "player", "canvas",
# Learning
"learn", "research", "sources",
# Analytics
"analytics", "dashboards", "monitoring",
# Development
"designer", "editor", "automation",
# Admin
"attendant", "security", "settings",
# Core tech
"llm", "vectordb", "nvidia", "cache", "compliance", "timeseries", "weba", "directory",
"progress-bars", "grpc", "jemalloc", "console"
] ]
communications = ["email", "whatsapp", "instagram", "msteams", "chat", "cache"]
productivity = ["chat", "drive", "tasks", "calendar", "meet", "mail", "cache", "learn"]
enterprise = ["compliance", "attendance", "directory", "llm", "vectordb", "monitoring", "timeseries"]
minimal = ["chat"] minimal = ["chat"]
lightweight = ["chat", "drive", "tasks"] lightweight = ["chat", "drive", "tasks", "people"]
[dependencies] [dependencies]
# === CORE RUNTIME (Always Required) === # === CORE RUNTIME (Always Required) ===
@ -144,7 +155,6 @@ tokio-stream = "0.1"
tower = "0.4" tower = "0.4"
tower-http = { version = "0.5", features = ["cors", "fs", "trace"] } tower-http = { version = "0.5", features = ["cors", "fs", "trace"] }
tracing = "0.1" tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["fmt"] } tracing-subscriber = { version = "0.3", features = ["fmt"] }
urlencoding = "2.1" urlencoding = "2.1"
uuid = { version = "1.11", features = ["serde", "v4", "v5"] } uuid = { version = "1.11", features = ["serde", "v4", "v5"] }
@ -162,9 +172,9 @@ time = { version = "0.3", features = ["formatting", "parsing"] }
jsonwebtoken = "9.3" jsonwebtoken = "9.3"
tower-cookies = "0.10" tower-cookies = "0.10"
# === FEATURE-SPECIFIC DEPENDENCIES (Optional) === # === APP-SPECIFIC DEPENDENCIES ===
# Email Integration (email feature) # Email Integration (mail feature)
imap = { version = "3.0.0-alpha.15", optional = true } imap = { version = "3.0.0-alpha.15", optional = true }
lettre = { version = "0.11", features = ["smtp-transport", "builder", "tokio1", "tokio1-native-tls"], optional = true } lettre = { version = "0.11", features = ["smtp-transport", "builder", "tokio1", "tokio1-native-tls"], optional = true }
mailparse = { version = "0.15", optional = true } mailparse = { version = "0.15", optional = true }
@ -176,6 +186,14 @@ livekit = { version = "0.7", optional = true }
# Vector Database (vectordb feature) # Vector Database (vectordb feature)
qdrant-client = { version = "1.12", optional = true } qdrant-client = { version = "1.12", optional = true }
# Document Processing (paper, docs, sheet, slides features)
docx-rs = { version = "0.4", optional = true }
ooxmlsdk = { version = "0.3", features = ["docx", "pptx", "parts", "office2021"], optional = true }
umya-spreadsheet = { version = "2.3", optional = true }
calamine = { version = "0.26", optional = true }
rust_xlsxwriter = { version = "0.79", optional = true }
spreadsheet-ods = { version = "1.0", optional = true }
# File Storage & Drive (drive feature) # File Storage & Drive (drive feature)
aws-config = { version = "1.8.8", features = ["behavior-version-latest"], optional = true } aws-config = { version = "1.8.8", features = ["behavior-version-latest"], optional = true }
aws-sdk-s3 = { version = "1.109.0", features = ["behavior-version-latest"], optional = true } aws-sdk-s3 = { version = "1.109.0", features = ["behavior-version-latest"], optional = true }
@ -183,7 +201,6 @@ pdf-extract = { version = "0.10.0", optional = true }
quick-xml = { version = "0.37", features = ["serialize"] } quick-xml = { version = "0.37", features = ["serialize"] }
zip = { version = "2.2", optional = true } zip = { version = "2.2", optional = true }
downloader = { version = "0.2", optional = true } downloader = { version = "0.2", optional = true }
flate2 = { version = "1.0", optional = true } flate2 = { version = "1.0", optional = true }
tar = { version = "0.4", optional = true } tar = { version = "0.4", optional = true }
@ -200,24 +217,10 @@ csv = { version = "1.3", optional = true }
crossterm = { version = "0.29.0", optional = true } crossterm = { version = "0.29.0", optional = true }
ratatui = { version = "0.29", optional = true } ratatui = { version = "0.29", optional = true }
# QR Code Generation (using png directly to avoid image's ravif/paste dependency) # QR Code Generation
png = "0.18" png = "0.18"
qrcode = { version = "0.14", default-features = false } qrcode = { version = "0.14", default-features = false }
# Excel/Spreadsheet Support - MS Office 100% Compatibility
# umya-spreadsheet preserves: Charts, styles, images, formulas, macros, comments
umya-spreadsheet = "2.3"
calamine = "0.26"
rust_xlsxwriter = "0.79"
spreadsheet-ods = "1.0"
# Word/PowerPoint Support - MS Office 100% Compatibility
# ooxmlsdk preserves: Full document structure at XML level (100% round-trip)
docx-rs = "0.4"
ooxmlsdk = { version = "0.3", features = ["docx", "pptx", "parts", "office2021"] }
# ppt-rs disabled due to version conflict - using ooxmlsdk for PPTX support instead
# ppt-rs = { version = "0.2", default-features = false }
# Error handling # Error handling
thiserror = "2.0" thiserror = "2.0"
@ -268,6 +271,5 @@ http-body-util = "0.1.3"
mockito = "1.7.0" mockito = "1.7.0"
tempfile = "3" tempfile = "3"
# === SECURITY AND CODE QUALITY CONFIGURATION ===
[lints] [lints]
workspace = true workspace = true

View file

@ -27,6 +27,7 @@ General Bots is a **self-hosted AI automation platform** that provides:
- **Rust** (1.75+) - [Install from rustup.rs](https://rustup.rs/) - **Rust** (1.75+) - [Install from rustup.rs](https://rustup.rs/)
- **Git** - [Download from git-scm.com](https://git-scm.com/downloads) - **Git** - [Download from git-scm.com](https://git-scm.com/downloads)
- Mold sudo apt-get install mold
### Installation ### Installation

View file

@ -13,8 +13,7 @@ command -v xclip >/dev/null 2>&1 || { echo "xclip is required but not installed"
echo "Please, fix this consolidated LLM Context" > "$OUTPUT_FILE" echo "Please, fix this consolidated LLM Context" > "$OUTPUT_FILE"
prompts=( prompts=(
"./prompts/dev/platform/fix-errors.md" "./PROMPT.md"
"./prompts/dev/platform/shared.md"
"./Cargo.toml" "./Cargo.toml"
) )
@ -32,29 +31,7 @@ for file in "${prompts[@]}"; do
done done
dirs=( dirs=(
# "auth"
# "automation"
#"basic"
# "bot"
"bootstrap"
# "package_manager"
# "channels"
# "config"
# "context"
# "email"
# "file"
# "llm"
"drive_monitor"
# "llm_legacy"
# "org"
# "session"
"file"
"kb"
"shared"
#"tests"
# "tools"
# "web_automation"
# "whatsapp"
) )
for dir in "${dirs[@]}"; do for dir in "${dirs[@]}"; do
if [ -d "$PROJECT_ROOT/src/$dir" ]; then if [ -d "$PROJECT_ROOT/src/$dir" ]; then
@ -72,12 +49,36 @@ done
echo "$PROJECT_ROOT/src/main.rs" >> "$OUTPUT_FILE" echo "$PROJECT_ROOT/src/main.rs" >> "$OUTPUT_FILE"
cat "$PROJECT_ROOT/src/main.rs" >> "$OUTPUT_FILE" cat "$PROJECT_ROOT/src/main.rs" >> "$OUTPUT_FILE"
echo "$PROJECT_ROOT/src/basic/keywords/get.rs" >> "$OUTPUT_FILE" # Files with config import errors
cat "$PROJECT_ROOT/src/basic/keywords/get.rs" >> "$OUTPUT_FILE" error_files=(
"src/main.rs"
"src/basic/keywords/kb_statistics.rs"
"src/core/bootstrap/mod.rs"
"src/core/kb/kb_indexer.rs"
"src/core/kb/website_crawler_service.rs"
"src/core/shared/utils.rs"
"src/multimodal/mod.rs"
"src/console/status_panel.rs"
"src/drive/drive_monitor/mod.rs"
"src/email/mod.rs"
"src/llm/cache.rs"
"src/llm/local.rs"
"src/llm/episodic_memory.rs"
"src/basic/keywords/create_site.rs"
"src/basic/keywords/save_from_unstructured.rs"
)
for file in "${error_files[@]}"; do
echo "$PROJECT_ROOT/$file" >> "$OUTPUT_FILE"
cat "$PROJECT_ROOT/$file" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo "---" >> "$OUTPUT_FILE"
done
echo "" >> "$OUTPUT_FILE" echo "" >> "$OUTPUT_FILE"
echo "Compiling..." echo "Compiling..."
cargo build --message-format=short 2>&1 | grep -E 'error' >> "$OUTPUT_FILE" cargo build --message-format=short 2>&1 | grep -E 'error' >> "$OUTPUT_FILE"
# Calculate and display token count (approximation: words * 1.3) # Calculate and display token count (approximation: words * 1.3)

View file

@ -57,7 +57,7 @@ pub fn create_site_keyword(state: &AppState, user: UserSession, engine: &mut Eng
} }
async fn create_site( async fn create_site(
config: crate::config::AppConfig, config: crate::core::config::AppConfig,
s3: Option<std::sync::Arc<aws_sdk_s3::Client>>, s3: Option<std::sync::Arc<aws_sdk_s3::Client>>,
bucket: String, bucket: String,
bot_id: String, bot_id: String,

View file

@ -1,4 +1,4 @@
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
use crate::shared::models::UserSession; use crate::shared::models::UserSession;
use crate::shared::state::AppState; use crate::shared::state::AppState;
use crate::shared::utils::create_tls_client; use crate::shared::utils::create_tls_client;

View file

@ -1,5 +1,4 @@
use crate::bot::get_default_bot; use crate::bot::get_default_bot;
use crate::core::shared::schema::products;
use crate::multimodal::BotModelsClient; use crate::multimodal::BotModelsClient;
use crate::shared::models::UserSession; use crate::shared::models::UserSession;
use crate::shared::state::AppState; use crate::shared::state::AppState;
@ -9,7 +8,6 @@ use diesel::sql_types::{Integer, Text};
use log::{error, trace}; use log::{error, trace};
use rhai::{Dynamic, Engine}; use rhai::{Dynamic, Engine};
use serde_json::{json, Value}; use serde_json::{json, Value};
use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
#[derive(QueryableByName)] #[derive(QueryableByName)]

View file

@ -260,7 +260,7 @@ Return ONLY the JSON object, no explanations or markdown formatting."#,
} }
async fn call_llm_for_extraction(state: &AppState, prompt: &str) -> Result<Value, String> { async fn call_llm_for_extraction(state: &AppState, prompt: &str) -> Result<Value, String> {
let config_manager = crate::config::ConfigManager::new(state.conn.clone()); let config_manager = crate::core::config::ConfigManager::new(state.conn.clone());
let model = config_manager let model = config_manager
.get_config(&Uuid::nil(), "llm-model", None) .get_config(&Uuid::nil(), "llm-model", None)
.unwrap_or_else(|_| "gpt-3.5-turbo".to_string()); .unwrap_or_else(|_| "gpt-3.5-turbo".to_string());

View file

@ -1,7 +1,6 @@
use axum::{ use axum::{
extract::{Path, Query, State}, extract::{Path, Query, State},
response::IntoResponse, Json,
Json,
}; };
use chrono::Utc; use chrono::Utc;
use diesel::prelude::*; use diesel::prelude::*;
@ -583,8 +582,8 @@ pub async fn handle_get_report(
} }
pub async fn handle_upload_evidence( pub async fn handle_upload_evidence(
State(_state): State<Arc<AppState>>, State(_state): State<Arc<AppState>>,
axum::extract::Multipart(mut multipart): axum::extract::Multipart, mut multipart: axum::extract::Multipart,
) -> Result<Json<serde_json::Value>, ComplianceError> { ) -> Result<Json<serde_json::Value>, ComplianceError> {
let mut file_name = String::new(); let mut file_name = String::new();
let mut category = String::new(); let mut category = String::new();

View file

@ -411,13 +411,13 @@ impl VulnerabilityScannerService {
let mut vulnerabilities = Vec::new(); let mut vulnerabilities = Vec::new();
let now = Utc::now(); let now = Utc::now();
let secret_patterns = vec![ let secret_patterns = vec![
("API Key Pattern", r"(?i)(api[_-]?key|apikey)\s*[:=]\s*['\"]?[\w-]{20,}", "CWE-798"), ("API Key Pattern", r#"(?i)(api[_-]?key|apikey)\s*[:=]\s*['"]?[\w-]{20,}"#, "CWE-798"),
("AWS Access Key", r"AKIA[0-9A-Z]{16}", "CWE-798"), ("AWS Access Key ", r"AKIA[0-9A-Z]{16}", "CWE-798"),
("Private Key", r"-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----", "CWE-321"), ("Private Key ", r"-----BEGIN (RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----", "CWE-321"),
("JWT Token", r"eyJ[A-Za-z0-9-_]+\.eyJ[A-Za-z0-9-_]+\.[A-Za-z0-9-_.+/]*", "CWE-522"), ("JWT Token ", r#"eyJ[A-Za-z0-9-]+.[A-Za-z0-9-]+.[A-Za-z0-9-_.+/]*"#, "CWE-522"),
("Database URL", r"(?i)(postgres|mysql|mongodb)://[^\s]+:[^\s]+@", "CWE-798"), ("Database URL ", r#"(?i)(postgres|mysql|mongodb)://[^\s]+:[^\s]+@"#, "CWE-798"),
]; ];
for (name, pattern, cwe) in secret_patterns { for (name, pattern, cwe) in secret_patterns {
let regex_result = regex::Regex::new(pattern); let regex_result = regex::Regex::new(pattern);

View file

@ -1,4 +1,4 @@
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
#[cfg(feature = "nvidia")] #[cfg(feature = "nvidia")]
use crate::nvidia::get_system_metrics; use crate::nvidia::get_system_metrics;
use crate::security::command_guard::SafeCommand; use crate::security::command_guard::SafeCommand;

View file

@ -1,4 +1,4 @@
use crate::config::AppConfig; use crate::core::config::AppConfig;
use crate::package_manager::setup::{DirectorySetup, EmailSetup, VectorDbSetup}; use crate::package_manager::setup::{DirectorySetup, EmailSetup, VectorDbSetup};
use crate::package_manager::{InstallMode, PackageManager}; use crate::package_manager::{InstallMode, PackageManager};
use crate::security::command_guard::SafeCommand; use crate::security::command_guard::SafeCommand;

View file

@ -5,7 +5,7 @@ use std::collections::HashMap;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use uuid::Uuid; use uuid::Uuid;
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
use crate::core::shared::memory_monitor::{log_jemalloc_stats, MemoryStats}; use crate::core::shared::memory_monitor::{log_jemalloc_stats, MemoryStats};
use crate::shared::utils::{create_tls_client, DbPool}; use crate::shared::utils::{create_tls_client, DbPool};

View file

@ -1,4 +1,4 @@
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
use crate::core::kb::web_crawler::{WebCrawler, WebsiteCrawlConfig}; use crate::core::kb::web_crawler::{WebCrawler, WebsiteCrawlConfig};
use crate::core::kb::KnowledgeBaseManager; use crate::core::kb::KnowledgeBaseManager;
use crate::shared::state::AppState; use crate::shared::state::AppState;

View file

@ -1,4 +1,4 @@
use crate::config::DriveConfig; use crate::core::config::DriveConfig;
use crate::core::secrets::SecretsManager; use crate::core::secrets::SecretsManager;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use aws_config::BehaviorVersion; use aws_config::BehaviorVersion;

View file

@ -1,5 +1,5 @@
use crate::basic::compiler::BasicCompiler; use crate::basic::compiler::BasicCompiler;
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
use crate::core::kb::embedding_generator::is_embedding_server_ready; use crate::core::kb::embedding_generator::is_embedding_server_ready;
use crate::core::kb::KnowledgeBaseManager; use crate::core::kb::KnowledgeBaseManager;
use crate::core::shared::memory_monitor::{log_jemalloc_stats, MemoryStats}; use crate::core::shared::memory_monitor::{log_jemalloc_stats, MemoryStats};

View file

@ -1,6 +1,6 @@
pub mod ui; pub mod ui;
use crate::{config::EmailConfig, core::urls::ApiUrls, shared::state::AppState}; use crate::{core::config::EmailConfig, core::urls::ApiUrls, shared::state::AppState};
use crate::core::middleware::AuthenticatedUser; use crate::core::middleware::AuthenticatedUser;
use axum::{ use axum::{
extract::{Path, Query, State}, extract::{Path, Query, State},

View file

@ -10,7 +10,7 @@ use tokio::sync::mpsc;
use uuid::Uuid; use uuid::Uuid;
use super::LLMProvider; use super::LLMProvider;
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
use crate::shared::utils::{estimate_token_count, DbPool}; use crate::shared::utils::{estimate_token_count, DbPool};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]

View file

@ -141,7 +141,7 @@ async fn process_episodic_memory(
let llm_provider = state.llm_provider.clone(); let llm_provider = state.llm_provider.clone();
let mut filtered = String::new(); let mut filtered = String::new();
let config_manager = crate::config::ConfigManager::new(state.conn.clone()); let config_manager = crate::core::config::ConfigManager::new(state.conn.clone());
let model = config_manager let model = config_manager
.get_config(&Uuid::nil(), "llm-model", None) .get_config(&Uuid::nil(), "llm-model", None)
.unwrap_or_default(); .unwrap_or_default();

View file

@ -1,4 +1,4 @@
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
use crate::core::kb::embedding_generator::set_embedding_server_ready; use crate::core::kb::embedding_generator::set_embedding_server_ready;
use crate::core::shared::memory_monitor::{log_jemalloc_stats, MemoryStats}; use crate::core::shared::memory_monitor::{log_jemalloc_stats, MemoryStats};
use crate::security::command_guard::SafeCommand; use crate::security::command_guard::SafeCommand;

View file

@ -45,7 +45,7 @@ pub mod botmodels;
pub mod legal; pub mod legal;
pub mod settings; pub mod settings;
#[cfg(feature = "attendance")] #[cfg(feature = "attendant")]
pub mod attendance; pub mod attendance;
#[cfg(feature = "calendar")] #[cfg(feature = "calendar")]
@ -139,8 +139,6 @@ use std::sync::Arc;
use tower_http::services::ServeDir; use tower_http::services::ServeDir;
use tower_http::trace::TraceLayer; use tower_http::trace::TraceLayer;
use crate::embedded_ui;
async fn ensure_vendor_files_in_minio(drive: &aws_sdk_s3::Client) { async fn ensure_vendor_files_in_minio(drive: &aws_sdk_s3::Client) {
use aws_sdk_s3::primitives::ByteStream; use aws_sdk_s3::primitives::ByteStream;
@ -213,7 +211,6 @@ use crate::shared::state::AppState;
use crate::shared::utils::create_conn; use crate::shared::utils::create_conn;
use crate::shared::utils::create_s3_operator; use crate::shared::utils::create_s3_operator;
use crate::BootstrapProgress;
async fn health_check(State(state): State<Arc<AppState>>) -> (StatusCode, Json<serde_json::Value>) { async fn health_check(State(state): State<Arc<AppState>>) -> (StatusCode, Json<serde_json::Value>) {
let db_ok = state.conn.get().is_ok(); let db_ok = state.conn.get().is_ok();
@ -410,7 +407,7 @@ async fn run_axum_server(
.route(ApiUrls::SESSION_HISTORY, get(get_session_history)) .route(ApiUrls::SESSION_HISTORY, get(get_session_history))
.route(ApiUrls::SESSION_START, post(start_session)) .route(ApiUrls::SESSION_START, post(start_session))
.route(ApiUrls::WS, get(websocket_handler)) .route(ApiUrls::WS, get(websocket_handler))
.merge(botserver::drive::configure()); .merge(crate::drive::configure());
#[cfg(feature = "directory")] #[cfg(feature = "directory")]
{ {
@ -434,14 +431,14 @@ async fn run_axum_server(
#[cfg(feature = "calendar")] #[cfg(feature = "calendar")]
{ {
let calendar_engine = let calendar_engine =
Arc::new(botserver::basic::keywords::book::CalendarEngine::new(app_state.conn.clone())); Arc::new(crate::basic::keywords::book::CalendarEngine::new(app_state.conn.clone()));
api_router = api_router.merge(crate::calendar::caldav::create_caldav_router( api_router = api_router.merge(crate::calendar::caldav::create_caldav_router(
calendar_engine, calendar_engine,
)); ));
} }
api_router = api_router.merge(botserver::tasks::configure_task_routes()); api_router = api_router.merge(crate::tasks::configure_task_routes());
#[cfg(feature = "calendar")] #[cfg(feature = "calendar")]
{ {
@ -449,61 +446,61 @@ async fn run_axum_server(
api_router = api_router.merge(crate::calendar::ui::configure_calendar_ui_routes()); api_router = api_router.merge(crate::calendar::ui::configure_calendar_ui_routes());
} }
api_router = api_router.merge(botserver::analytics::configure_analytics_routes()); api_router = api_router.merge(crate::analytics::configure_analytics_routes());
api_router = api_router.merge(crate::core::i18n::configure_i18n_routes()); api_router = api_router.merge(crate::core::i18n::configure_i18n_routes());
api_router = api_router.merge(botserver::docs::configure_docs_routes()); api_router = api_router.merge(crate::docs::configure_docs_routes());
api_router = api_router.merge(botserver::paper::configure_paper_routes()); api_router = api_router.merge(crate::paper::configure_paper_routes());
api_router = api_router.merge(botserver::sheet::configure_sheet_routes()); api_router = api_router.merge(crate::sheet::configure_sheet_routes());
api_router = api_router.merge(botserver::slides::configure_slides_routes()); api_router = api_router.merge(crate::slides::configure_slides_routes());
api_router = api_router.merge(botserver::video::configure_video_routes()); api_router = api_router.merge(crate::video::configure_video_routes());
api_router = api_router.merge(botserver::video::ui::configure_video_ui_routes()); api_router = api_router.merge(crate::video::ui::configure_video_ui_routes());
api_router = api_router.merge(botserver::research::configure_research_routes()); api_router = api_router.merge(crate::research::configure_research_routes());
api_router = api_router.merge(botserver::research::ui::configure_research_ui_routes()); api_router = api_router.merge(crate::research::ui::configure_research_ui_routes());
api_router = api_router.merge(botserver::sources::configure_sources_routes()); api_router = api_router.merge(crate::sources::configure_sources_routes());
api_router = api_router.merge(botserver::sources::ui::configure_sources_ui_routes()); api_router = api_router.merge(crate::sources::ui::configure_sources_ui_routes());
api_router = api_router.merge(botserver::designer::configure_designer_routes()); api_router = api_router.merge(crate::designer::configure_designer_routes());
api_router = api_router.merge(botserver::designer::ui::configure_designer_ui_routes()); api_router = api_router.merge(crate::designer::ui::configure_designer_ui_routes());
api_router = api_router.merge(botserver::dashboards::configure_dashboards_routes()); api_router = api_router.merge(crate::dashboards::configure_dashboards_routes());
api_router = api_router.merge(botserver::dashboards::ui::configure_dashboards_ui_routes()); api_router = api_router.merge(crate::dashboards::ui::configure_dashboards_ui_routes());
api_router = api_router.merge(botserver::legal::configure_legal_routes()); api_router = api_router.merge(crate::legal::configure_legal_routes());
api_router = api_router.merge(botserver::legal::ui::configure_legal_ui_routes()); api_router = api_router.merge(crate::legal::ui::configure_legal_ui_routes());
#[cfg(feature = "compliance")] #[cfg(feature = "compliance")]
{ {
api_router = api_router.merge(botserver::compliance::configure_compliance_routes()); api_router = api_router.merge(crate::compliance::configure_compliance_routes());
api_router = api_router.merge(botserver::compliance::ui::configure_compliance_ui_routes()); api_router = api_router.merge(crate::compliance::ui::configure_compliance_ui_routes());
} }
api_router = api_router.merge(botserver::monitoring::configure()); api_router = api_router.merge(crate::monitoring::configure());
api_router = api_router.merge(botserver::security::configure_protection_routes()); api_router = api_router.merge(crate::security::configure_protection_routes());
api_router = api_router.merge(botserver::settings::configure_settings_routes()); api_router = api_router.merge(crate::settings::configure_settings_routes());
api_router = api_router.merge(botserver::basic::keywords::configure_db_routes()); api_router = api_router.merge(crate::basic::keywords::configure_db_routes());
api_router = api_router.merge(botserver::basic::keywords::configure_app_server_routes()); api_router = api_router.merge(crate::basic::keywords::configure_app_server_routes());
api_router = api_router.merge(botserver::auto_task::configure_autotask_routes()); api_router = api_router.merge(crate::auto_task::configure_autotask_routes());
api_router = api_router.merge(crate::core::shared::admin::configure()); api_router = api_router.merge(crate::core::shared::admin::configure());
api_router = api_router.merge(botserver::workspaces::configure_workspaces_routes()); api_router = api_router.merge(crate::workspaces::configure_workspaces_routes());
api_router = api_router.merge(botserver::workspaces::ui::configure_workspaces_ui_routes()); api_router = api_router.merge(crate::workspaces::ui::configure_workspaces_ui_routes());
api_router = api_router.merge(botserver::project::configure()); api_router = api_router.merge(crate::project::configure());
api_router = api_router.merge(botserver::analytics::goals::configure_goals_routes()); api_router = api_router.merge(crate::analytics::goals::configure_goals_routes());
api_router = api_router.merge(botserver::analytics::goals_ui::configure_goals_ui_routes()); api_router = api_router.merge(crate::analytics::goals_ui::configure_goals_ui_routes());
api_router = api_router.merge(botserver::player::configure_player_routes()); api_router = api_router.merge(crate::player::configure_player_routes());
api_router = api_router.merge(botserver::canvas::configure_canvas_routes()); api_router = api_router.merge(crate::canvas::configure_canvas_routes());
api_router = api_router.merge(botserver::canvas::ui::configure_canvas_ui_routes()); api_router = api_router.merge(crate::canvas::ui::configure_canvas_ui_routes());
api_router = api_router.merge(botserver::social::configure_social_routes()); api_router = api_router.merge(crate::social::configure_social_routes());
api_router = api_router.merge(botserver::social::ui::configure_social_ui_routes()); api_router = api_router.merge(crate::social::ui::configure_social_ui_routes());
api_router = api_router.merge(botserver::email::ui::configure_email_ui_routes()); api_router = api_router.merge(crate::email::ui::configure_email_ui_routes());
api_router = api_router.merge(botserver::learn::ui::configure_learn_ui_routes()); api_router = api_router.merge(crate::learn::ui::configure_learn_ui_routes());
api_router = api_router.merge(botserver::meet::ui::configure_meet_ui_routes()); api_router = api_router.merge(crate::meet::ui::configure_meet_ui_routes());
api_router = api_router.merge(botserver::contacts::crm_ui::configure_crm_routes()); api_router = api_router.merge(crate::contacts::crm_ui::configure_crm_routes());
api_router = api_router.merge(botserver::contacts::crm::configure_crm_api_routes()); api_router = api_router.merge(crate::contacts::crm::configure_crm_api_routes());
api_router = api_router.merge(botserver::billing::billing_ui::configure_billing_routes()); api_router = api_router.merge(crate::billing::billing_ui::configure_billing_routes());
api_router = api_router.merge(botserver::billing::api::configure_billing_api_routes()); api_router = api_router.merge(crate::billing::api::configure_billing_api_routes());
api_router = api_router.merge(botserver::products::configure_products_routes()); api_router = api_router.merge(crate::products::configure_products_routes());
api_router = api_router.merge(botserver::products::api::configure_products_api_routes()); api_router = api_router.merge(crate::products::api::configure_products_api_routes());
api_router = api_router.merge(botserver::tickets::configure_tickets_routes()); api_router = api_router.merge(crate::tickets::configure_tickets_routes());
api_router = api_router.merge(botserver::tickets::ui::configure_tickets_ui_routes()); api_router = api_router.merge(crate::tickets::ui::configure_tickets_ui_routes());
api_router = api_router.merge(botserver::people::configure_people_routes()); api_router = api_router.merge(crate::people::configure_people_routes());
api_router = api_router.merge(botserver::people::ui::configure_people_ui_routes()); api_router = api_router.merge(crate::people::ui::configure_people_ui_routes());
api_router = api_router.merge(botserver::attendant::configure_attendant_routes()); api_router = api_router.merge(crate::attendant::configure_attendant_routes());
api_router = api_router.merge(botserver::attendant::ui::configure_attendant_ui_routes()); api_router = api_router.merge(crate::attendant::ui::configure_attendant_ui_routes());
#[cfg(feature = "whatsapp")] #[cfg(feature = "whatsapp")]
{ {
@ -512,10 +509,10 @@ async fn run_axum_server(
#[cfg(feature = "telegram")] #[cfg(feature = "telegram")]
{ {
api_router = api_router.merge(botserver::telegram::configure()); api_router = api_router.merge(crate::telegram::configure());
} }
#[cfg(feature = "attendance")] #[cfg(feature = "attendant")]
{ {
api_router = api_router.merge(crate::attendance::configure_attendance_routes()); api_router = api_router.merge(crate::attendance::configure_attendance_routes());
} }
@ -608,21 +605,21 @@ async fn run_axum_server(
.layer(middleware::from_fn(move |req: axum::http::Request<axum::body::Body>, next: axum::middleware::Next| { .layer(middleware::from_fn(move |req: axum::http::Request<axum::body::Body>, next: axum::middleware::Next| {
let rbac = Arc::clone(&rbac_manager_for_middleware); let rbac = Arc::clone(&rbac_manager_for_middleware);
async move { async move {
botserver::security::rbac_middleware_fn(req, next, rbac).await crate::security::rbac_middleware_fn(req, next, rbac).await
} }
})) }))
// Authentication middleware - MUST run before RBAC (so added after) // Authentication middleware - MUST run before RBAC (so added after)
.layer(middleware::from_fn(move |req: axum::http::Request<axum::body::Body>, next: axum::middleware::Next| { .layer(middleware::from_fn(move |req: axum::http::Request<axum::body::Body>, next: axum::middleware::Next| {
let state = auth_middleware_state.clone(); let state = auth_middleware_state.clone();
async move { async move {
botserver::security::auth_middleware_with_providers(req, next, state).await crate::security::auth_middleware_with_providers(req, next, state).await
} }
})) }))
// Panic handler catches panics and returns safe 500 responses // Panic handler catches panics and returns safe 500 responses
.layer(middleware::from_fn(move |req, next| { .layer(middleware::from_fn(move |req, next| {
let config = panic_config.clone(); let config = panic_config.clone();
async move { async move {
botserver::security::panic_handler_middleware_with_config(req, next, &config).await crate::security::panic_handler_middleware_with_config(req, next, &config).await
} }
})) }))
.layer(Extension(app_state.clone())) .layer(Extension(app_state.clone()))
@ -749,8 +746,8 @@ async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", &rust_log); std::env::set_var("RUST_LOG", &rust_log);
use crate::llm::local::ensure_llama_servers_running; use crate::llm::local::ensure_llama_servers_running;
use botserver::config::ConfigManager; use crate::core::config::ConfigManager;
if no_console || no_ui { if no_console || no_ui {
botlib::logging::init_compact_logger_with_style("info"); botlib::logging::init_compact_logger_with_style("info");
@ -800,7 +797,7 @@ async fn main() -> std::io::Result<()> {
std::thread::Builder::new() std::thread::Builder::new()
.name("ui-thread".to_string()) .name("ui-thread".to_string())
.spawn(move || { .spawn(move || {
let mut ui = botserver::console::XtreeUI::new(); let mut ui =crate::console::XtreeUI::new();
ui.set_progress_channel(progress_rx); ui.set_progress_channel(progress_rx);
ui.set_state_channel(state_rx); ui.set_state_channel(state_rx);
@ -1063,7 +1060,7 @@ async fn main() -> std::io::Result<()> {
info!("Loaded Zitadel config from {}: url={}", config_path, base_url); info!("Loaded Zitadel config from {}: url={}", config_path, base_url);
botserver::directory::client::ZitadelConfig { crate::directory::client::ZitadelConfig {
issuer_url: base_url.to_string(), issuer_url: base_url.to_string(),
issuer: base_url.to_string(), issuer: base_url.to_string(),
client_id: client_id.to_string(), client_id: client_id.to_string(),
@ -1075,7 +1072,7 @@ async fn main() -> std::io::Result<()> {
} }
} else { } else {
warn!("Failed to parse directory_config.json, using defaults"); warn!("Failed to parse directory_config.json, using defaults");
botserver::directory::client::ZitadelConfig { crate::directory::client::ZitadelConfig {
issuer_url: "http://localhost:8300".to_string(), issuer_url: "http://localhost:8300".to_string(),
issuer: "http://localhost:8300".to_string(), issuer: "http://localhost:8300".to_string(),
client_id: String::new(), client_id: String::new(),
@ -1088,7 +1085,7 @@ async fn main() -> std::io::Result<()> {
} }
} else { } else {
warn!("directory_config.json not found, using default Zitadel config"); warn!("directory_config.json not found, using default Zitadel config");
botserver::directory::client::ZitadelConfig { crate::directory::client::ZitadelConfig {
issuer_url: "http://localhost:8300".to_string(), issuer_url: "http://localhost:8300".to_string(),
issuer: "http://localhost:8300".to_string(), issuer: "http://localhost:8300".to_string(),
client_id: String::new(), client_id: String::new(),
@ -1102,7 +1099,7 @@ async fn main() -> std::io::Result<()> {
}; };
#[cfg(feature = "directory")] #[cfg(feature = "directory")]
let auth_service = Arc::new(tokio::sync::Mutex::new( let auth_service = Arc::new(tokio::sync::Mutex::new(
botserver::directory::AuthService::new(zitadel_config.clone()).map_err(|e| std::io::Error::other(format!("Failed to create auth service: {}", e)))?, crate::directory::AuthService::new(zitadel_config.clone()).map_err(|e| std::io::Error::other(format!("Failed to create auth service: {}", e)))?,
)); ));
#[cfg(feature = "directory")] #[cfg(feature = "directory")]
@ -1113,22 +1110,22 @@ async fn main() -> std::io::Result<()> {
Ok(pat_token) => { Ok(pat_token) => {
let pat_token = pat_token.trim().to_string(); let pat_token = pat_token.trim().to_string();
info!("Using admin PAT token for bootstrap authentication"); info!("Using admin PAT token for bootstrap authentication");
botserver::directory::client::ZitadelClient::with_pat_token(zitadel_config, pat_token) crate::directory::client::ZitadelClient::with_pat_token(zitadel_config, pat_token)
.map_err(|e| std::io::Error::other(format!("Failed to create bootstrap client with PAT: {}", e)))? .map_err(|e| std::io::Error::other(format!("Failed to create bootstrap client with PAT: {}", e)))?
} }
Err(e) => { Err(e) => {
warn!("Failed to read admin PAT token: {}, falling back to OAuth2", e); warn!("Failed to read admin PAT token: {}, falling back to OAuth2", e);
botserver::directory::client::ZitadelClient::new(zitadel_config) crate::directory::client::ZitadelClient::new(zitadel_config)
.map_err(|e| std::io::Error::other(format!("Failed to create bootstrap client: {}", e)))? .map_err(|e| std::io::Error::other(format!("Failed to create bootstrap client: {}", e)))?
} }
} }
} else { } else {
info!("Admin PAT not found, using OAuth2 client credentials for bootstrap"); info!("Admin PAT not found, using OAuth2 client credentials for bootstrap");
botserver::directory::client::ZitadelClient::new(zitadel_config) crate::directory::client::ZitadelClient::new(zitadel_config)
.map_err(|e| std::io::Error::other(format!("Failed to create bootstrap client: {}", e)))? .map_err(|e| std::io::Error::other(format!("Failed to create bootstrap client: {}", e)))?
}; };
match botserver::directory::bootstrap::check_and_bootstrap_admin(&bootstrap_client).await { match crate::directory::bootstrap::check_and_bootstrap_admin(&bootstrap_client).await {
Ok(Some(_)) => { Ok(Some(_)) => {
info!("Bootstrap completed - admin credentials displayed in console"); info!("Bootstrap completed - admin credentials displayed in console");
} }
@ -1165,14 +1162,14 @@ async fn main() -> std::io::Result<()> {
.get_config(&default_bot_id, "llm-key", Some("")) .get_config(&default_bot_id, "llm-key", Some(""))
.unwrap_or_default(); .unwrap_or_default();
let base_llm_provider = botserver::llm::create_llm_provider_from_url( let base_llm_provider =crate::llm::create_llm_provider_from_url(
&llm_url, &llm_url,
if llm_model.is_empty() { None } else { Some(llm_model.clone()) }, if llm_model.is_empty() { None } else { Some(llm_model.clone()) },
); );
let dynamic_llm_provider = Arc::new(botserver::llm::DynamicLLMProvider::new(base_llm_provider)); let dynamic_llm_provider = Arc::new(crate::llm::DynamicLLMProvider::new(base_llm_provider));
let llm_provider: Arc<dyn botserver::llm::LLMProvider> = if let Some(ref cache) = redis_client { let llm_provider: Arc<dyn crate::llm::LLMProvider> = if let Some(ref cache) = redis_client {
let embedding_url = config_manager let embedding_url = config_manager
.get_config( .get_config(
&default_bot_id, &default_bot_id,
@ -1186,13 +1183,13 @@ async fn main() -> std::io::Result<()> {
info!("Embedding URL: {}", embedding_url); info!("Embedding URL: {}", embedding_url);
info!("Embedding Model: {}", embedding_model); info!("Embedding Model: {}", embedding_model);
let embedding_service = Some(Arc::new(botserver::llm::cache::LocalEmbeddingService::new( let embedding_service = Some(Arc::new(crate::llm::cache::LocalEmbeddingService::new(
embedding_url, embedding_url,
embedding_model, embedding_model,
)) ))
as Arc<dyn botserver::llm::cache::EmbeddingService>); as Arc<dyn crate::llm::cache::EmbeddingService>);
let cache_config = botserver::llm::cache::CacheConfig { let cache_config =crate::llm::cache::CacheConfig {
ttl: 3600, ttl: 3600,
semantic_matching: true, semantic_matching: true,
similarity_threshold: 0.85, similarity_threshold: 0.85,
@ -1200,31 +1197,31 @@ async fn main() -> std::io::Result<()> {
key_prefix: "llm_cache".to_string(), key_prefix: "llm_cache".to_string(),
}; };
Arc::new(botserver::llm::cache::CachedLLMProvider::with_db_pool( Arc::new(crate::llm::cache::CachedLLMProvider::with_db_pool(
dynamic_llm_provider.clone() as Arc<dyn botserver::llm::LLMProvider>, dynamic_llm_provider.clone() as Arc<dyn crate::llm::LLMProvider>,
cache.clone(), cache.clone(),
cache_config, cache_config,
embedding_service, embedding_service,
pool.clone(), pool.clone(),
)) ))
} else { } else {
dynamic_llm_provider.clone() as Arc<dyn botserver::llm::LLMProvider> dynamic_llm_provider.clone() as Arc<dyn crate::llm::LLMProvider>
}; };
let kb_manager = Arc::new(botserver::core::kb::KnowledgeBaseManager::new("work")); let kb_manager = Arc::new(crate::core::kb::KnowledgeBaseManager::new("work"));
let task_engine = Arc::new(botserver::tasks::TaskEngine::new(pool.clone())); let task_engine = Arc::new(crate::tasks::TaskEngine::new(pool.clone()));
let metrics_collector = botserver::core::shared::analytics::MetricsCollector::new(); let metrics_collector =crate::core::shared::analytics::MetricsCollector::new();
let task_scheduler = None; let task_scheduler = None;
let (attendant_tx, _attendant_rx) = tokio::sync::broadcast::channel::< let (attendant_tx, _attendant_rx) = tokio::sync::broadcast::channel::<
botserver::core::shared::state::AttendantNotification, crate::core::shared::state::AttendantNotification,
>(1000); >(1000);
let (task_progress_tx, _task_progress_rx) = tokio::sync::broadcast::channel::< let (task_progress_tx, _task_progress_rx) = tokio::sync::broadcast::channel::<
botserver::core::shared::state::TaskProgressEvent, crate::core::shared::state::TaskProgressEvent,
>(1000); >(1000);
// Initialize BotDatabaseManager for per-bot database support // Initialize BotDatabaseManager for per-bot database support
@ -1269,7 +1266,7 @@ async fn main() -> std::io::Result<()> {
let mut map = HashMap::new(); let mut map = HashMap::new();
map.insert( map.insert(
"web".to_string(), "web".to_string(),
web_adapter.clone() as Arc<dyn botserver::core::bot::channels::ChannelAdapter>, web_adapter.clone() as Arc<dyn crate::core::bot::channels::ChannelAdapter>,
); );
map map
})), })),
@ -1279,7 +1276,7 @@ async fn main() -> std::io::Result<()> {
kb_manager: Some(kb_manager.clone()), kb_manager: Some(kb_manager.clone()),
task_engine, task_engine,
extensions: { extensions: {
let ext = botserver::core::shared::state::Extensions::new(); let ext =crate::core::shared::state::Extensions::new();
ext.insert_blocking(Arc::clone(&dynamic_llm_provider)); ext.insert_blocking(Arc::clone(&dynamic_llm_provider));
ext ext
}, },
@ -1287,20 +1284,20 @@ async fn main() -> std::io::Result<()> {
task_progress_broadcast: Some(task_progress_tx), task_progress_broadcast: Some(task_progress_tx),
billing_alert_broadcast: None, billing_alert_broadcast: None,
task_manifests: Arc::new(std::sync::RwLock::new(HashMap::new())), task_manifests: Arc::new(std::sync::RwLock::new(HashMap::new())),
project_service: Arc::new(tokio::sync::RwLock::new(botserver::project::ProjectService::new())), project_service: Arc::new(tokio::sync::RwLock::new(crate::project::ProjectService::new())),
legal_service: Arc::new(tokio::sync::RwLock::new(botserver::legal::LegalService::new())), legal_service: Arc::new(tokio::sync::RwLock::new(crate::legal::LegalService::new())),
jwt_manager: None, jwt_manager: None,
auth_provider_registry: None, auth_provider_registry: None,
rbac_manager: None, rbac_manager: None,
}); });
let task_scheduler = Arc::new(botserver::tasks::scheduler::TaskScheduler::new( let task_scheduler = Arc::new(crate::tasks::scheduler::TaskScheduler::new(
app_state.clone(), app_state.clone(),
)); ));
task_scheduler.start(); task_scheduler.start();
if let Err(e) = botserver::core::kb::ensure_crawler_service_running(app_state.clone()).await { if let Err(e) =crate::core::kb::ensure_crawler_service_running(app_state.clone()).await {
log::warn!("Failed to start website crawler service: {}", e); log::warn!("Failed to start website crawler service: {}", e);
} }
@ -1334,7 +1331,7 @@ async fn main() -> std::io::Result<()> {
tokio::spawn(async move { tokio::spawn(async move {
register_thread("drive-monitor", "drive"); register_thread("drive-monitor", "drive");
trace!("DriveMonitor::new starting..."); trace!("DriveMonitor::new starting...");
let monitor = botserver::DriveMonitor::new( let monitor =crate::DriveMonitor::new(
drive_monitor_state, drive_monitor_state,
bucket_name.clone(), bucket_name.clone(),
monitor_bot_id, monitor_bot_id,

View file

@ -1,4 +1,4 @@
use crate::config::ConfigManager; use crate::core::config::ConfigManager;
use crate::shared::utils::create_tls_client; use crate::shared::utils::create_tls_client;
use crate::shared::state::AppState; use crate::shared::state::AppState;
use log::{error, info, trace}; use log::{error, info, trace};

View file

@ -318,7 +318,7 @@ async fn process_attendant_command(
let current_session = get_attendant_active_session(state, phone).await; let current_session = get_attendant_active_session(state, phone).await;
#[cfg(feature = "attendance")] #[cfg(feature = "attendant")]
{ {
match crate::attendance::llm_assist::process_attendant_command( match crate::attendance::llm_assist::process_attendant_command(
state, state,
@ -333,7 +333,7 @@ async fn process_attendant_command(
} }
} }
#[cfg(not(feature = "attendance"))] #[cfg(not(feature = "attendant"))]
{ {
let _ = current_session; let _ = current_session;
Some(format!( Some(format!(