refactor(config): remove unused S3 bucket configuration and setup logic

Eliminates the `s3_bucket` field from `AppConfig` and deletes related initialization code in `main.rs`. This simplifies configuration management since S3 bucket handling is no longer required or used in the application.
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-10-29 09:54:39 -03:00
parent 21fdb326a6
commit 663864cb78
14 changed files with 120 additions and 71 deletions

View file

@ -20,25 +20,24 @@ done
dirs=(
# "auth"
"automation"
"basic"
# "automation"
# "basic"
# "bot"
"bootstrap"
# "package_manager"
"package_manager"
# "channels"
# "config"
# "context"
# "email"
# "file"
"file"
# "llm"
"drive_monitor"
# "llm_legacy"
# "org"
# "session"
"file"
"kb"
#"kb"
"shared"
"tests"
#"tests"
# "tools"
# "web_automation"
# "whatsapp"

View file

@ -175,7 +175,7 @@ pub async fn get_from_bucket(
"App configuration missing".into()
})?;
let org_prefix = &cfg.minio.org_prefix;
let org_prefix = &cfg.drive.org_prefix;
if org_prefix.contains("..") || org_prefix.contains('/') || org_prefix.contains('\\') {
error!("Invalid org_prefix: {}", org_prefix);

View file

@ -2,11 +2,10 @@ use crate::config::AppConfig;
use crate::package_manager::{InstallMode, PackageManager};
use anyhow::Result;
use diesel::connection::SimpleConnection;
use diesel::{Connection, QueryableByName};
use diesel::RunQueryDsl;
use diesel::{Connection, QueryableByName};
use dotenvy::dotenv;
use log::{error, info};
use opendal::services::S3;
use log::{error, info, trace};
use opendal::Operator;
use rand::distr::Alphanumeric;
use rand::Rng;
@ -29,6 +28,7 @@ pub struct ComponentInfo {
pub struct BootstrapManager {
pub install_mode: InstallMode,
pub tenant: Option<String>,
pub s3_operator: Operator,
}
impl BootstrapManager {
@ -37,9 +37,12 @@ impl BootstrapManager {
"Initializing BootstrapManager with mode {:?} and tenant {:?}",
install_mode, tenant
);
let config = AppConfig::from_env();
let s3_operator = Self::create_s3_operator(&config);
Self {
install_mode,
tenant,
s3_operator,
}
}
@ -289,9 +292,21 @@ impl BootstrapManager {
}
}
self.s3_operator = Self::create_s3_operator(&config);
Ok(config)
}
fn create_s3_operator(config: &AppConfig) -> Operator {
use opendal::Scheme;
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("endpoint".to_string(), config.drive.server.clone());
map.insert("access_key_id".to_string(), config.drive.access_key.clone());
map.insert("secret_access_key".to_string(), config.drive.secret_key.clone());
trace!("Creating S3 operator with endpoint {}", config.drive.server);
Operator::via_iter(Scheme::S3, map).expect("Failed to initialize S3 operator")
}
fn generate_secure_password(&self, length: usize) -> String {
let mut rng = rand::rng();
std::iter::repeat_with(|| rng.sample(Alphanumeric) as char)
@ -307,7 +322,7 @@ impl BootstrapManager {
}
fn update_bot_config(&self, bot_id: &uuid::Uuid, component: &str) -> Result<()> {
use diesel::sql_types::{Uuid as SqlUuid, Text};
use diesel::sql_types::{Text, Uuid as SqlUuid};
let database_url = std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgres://gbuser:@localhost:5432/botserver".to_string());
let mut conn = diesel::pg::PgConnection::establish(&database_url)?;
@ -321,7 +336,7 @@ impl BootstrapManager {
"INSERT INTO bot_configuration (id, bot_id, config_key, config_value, config_type)
VALUES ($1, $2, $3, $4, 'string')
ON CONFLICT (config_key)
DO UPDATE SET config_value = EXCLUDED.config_value, updated_at = NOW()"
DO UPDATE SET config_value = EXCLUDED.config_value, updated_at = NOW()",
)
.bind::<SqlUuid, _>(new_id)
.bind::<SqlUuid, _>(bot_id)
@ -332,39 +347,53 @@ impl BootstrapManager {
Ok(())
}
pub async fn upload_templates_to_minio(&self, config: &AppConfig) -> Result<()> {
pub async fn upload_templates_to_drive(&self, config: &AppConfig) -> Result<()> {
let database_url = std::env::var("DATABASE_URL").unwrap_or_else(|_| config.database_url());
let mut conn = diesel::PgConnection::establish(&database_url)?;
self.create_bots_from_templates(&mut conn)?;
let client = Operator::new(
S3::default()
.root("/")
.endpoint(&config.minio.server)
.access_key_id(&config.minio.access_key)
.secret_access_key(&config.minio.secret_key),
)?
.finish();
let templates_dir = Path::new("templates");
if !templates_dir.exists() {
return Ok(());
}
let operator = &self.s3_operator;
for entry in std::fs::read_dir(templates_dir)? {
let bot_name = templates_dir
.read_dir()?
.filter_map(|e| e.ok())
.find(|e| {
e.path().is_dir()
&& e.path()
.file_name()
.unwrap()
.to_string_lossy()
.ends_with(".gbai")
})
.map(|e| {
let name = e.path().file_name().unwrap().to_string_lossy().to_string();
name
})
.unwrap_or_else(|| "default".to_string());
let entry = entry?;
let path = entry.path();
if path.is_dir() && path.extension().map(|e| e == "gbai").unwrap_or(false) {
if path.is_dir()
&& path
.file_name()
.unwrap()
.to_string_lossy()
.ends_with(".gbai")
{
let bot_name = path.file_name().unwrap().to_string_lossy().to_string();
self.upload_directory_recursive(&client, &path, &bot_name, "")
let bucket = bot_name.clone();
info!("Uploading template {} to Drive bucket {}", bot_name, bucket);
self.upload_directory_recursive(&operator, &path, &bucket, &bot_name)
.await?;
info!("Uploaded template {} to Drive bucket {}", bot_name, bucket);
}
}
Ok(())
}
fn create_bots_from_templates(&self, conn: &mut diesel::PgConnection) -> Result<()> {
use crate::shared::models::schema::bots;
use diesel::prelude::*;
@ -425,6 +454,16 @@ impl BootstrapManager {
prefix: &'a str,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<()>> + 'a>> {
Box::pin(async move {
trace!("Checking bucket existence: {}", bucket);
if client.stat(bucket).await.is_err() {
info!("Bucket {} not found, creating it", bucket);
trace!("Creating bucket: {}", bucket);
client.create_dir(bucket).await?;
trace!("Bucket {} created successfully", bucket);
} else {
trace!("Bucket {} already exists", bucket);
}
trace!("Starting upload from local path: {}", local_path.display());
for entry in std::fs::read_dir(local_path)? {
let entry = entry?;
let path = entry.path();
@ -443,7 +482,18 @@ impl BootstrapManager {
key
);
let content = std::fs::read(&path)?;
trace!(
"Writing file {} to bucket {} with key {}",
path.display(),
bucket,
key
);
client.write(&key, content).await?;
trace!(
"Successfully wrote file {} to bucket {}",
path.display(),
bucket
);
} else if path.is_dir() {
self.upload_directory_recursive(client, &path, bucket, &key)
.await?;

View file

@ -8,14 +8,13 @@ use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct AppConfig {
pub minio: DriveConfig,
pub drive: DriveConfig,
pub server: ServerConfig,
pub database: DatabaseConfig,
pub database_custom: DatabaseConfig,
pub email: EmailConfig,
pub ai: AIConfig,
pub site_path: String,
pub s3_bucket: String,
pub stack_path: PathBuf,
pub db_conn: Option<Arc<Mutex<PgConnection>>>,
}
@ -218,7 +217,7 @@ impl AppConfig {
};
AppConfig {
minio,
drive: minio,
server: ServerConfig {
host: get_str("SERVER_HOST", "127.0.0.1"),
port: get_u16("SERVER_PORT", 8080),
@ -227,7 +226,6 @@ impl AppConfig {
database_custom,
email,
ai,
s3_bucket: get_str("DRIVE_BUCKET", "default"),
site_path: get_str("SITES_ROOT", "./botserver-stack/sites"),
stack_path,
db_conn: None,
@ -300,7 +298,7 @@ impl AppConfig {
};
AppConfig {
minio,
drive: minio,
server: ServerConfig {
host: std::env::var("SERVER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string()),
port: std::env::var("SERVER_PORT")
@ -312,7 +310,6 @@ impl AppConfig {
database_custom,
email,
ai,
s3_bucket: std::env::var("DRIVE_BUCKET").unwrap_or_else(|_| "default".to_string()),
site_path: std::env::var("SITES_ROOT")
.unwrap_or_else(|_| "./botserver-stack/sites".to_string()),
stack_path: PathBuf::from(stack_path),

View file

@ -140,7 +140,7 @@ async fn main() -> std::io::Result<()> {
let _ = bootstrap.start_all();
if let Err(e) = bootstrap.upload_templates_to_minio(&cfg).await {
if let Err(e) = bootstrap.upload_templates_to_drive(&cfg).await {
log::warn!("Failed to upload templates to MinIO: {}", e);
}
@ -193,32 +193,8 @@ async fn main() -> std::io::Result<()> {
));
let tool_api = Arc::new(tools::ToolApi::new());
use opendal::services::S3;
use opendal::Operator;
use opendal::ErrorKind;
async fn ensure_bucket_exists(cfg: &AppConfig) {
let builder = S3::default()
.endpoint(&cfg.minio.server)
.access_key_id(&cfg.minio.access_key)
.secret_access_key(&cfg.minio.secret_key)
.bucket(&cfg.s3_bucket)
.root("/");
let op = Operator::new(builder).unwrap().finish();
match op.stat("/").await {
Ok(_) => info!("Bucket {} exists", cfg.s3_bucket),
Err(e) if e.kind() == ErrorKind::NotFound => {
if let Err(err) = op.create_dir("/").await {
info!("Created bucket {}: {:?}", cfg.s3_bucket, err);
}
}
Err(e) => info!("Bucket check failed: {:?}", e),
}
}
ensure_bucket_exists(&config).await;
let drive = init_drive(&config.minio)
let drive = init_drive(&config.drive)
.await
.expect("Failed to initialize Drive");
@ -279,7 +255,7 @@ async fn main() -> std::io::Result<()> {
let drive_state = app_state.clone();
let bot_guid = std::env::var("BOT_GUID").unwrap_or_else(|_| "default_bot".to_string());
let bucket_name = format!("{}{}.gbai", cfg.minio.org_prefix, bot_guid);
let bucket_name = format!("{}{}.gbai", cfg.drive.org_prefix, bot_guid);
let drive_monitor = Arc::new(DriveMonitor::new(drive_state, bucket_name));
let _drive_handle = drive_monitor.spawn();

View file

@ -0,0 +1,4 @@
name,value
prompt-compact, 10
prompt-cache,true
prompt-fixed-kb,geral
1 name value
2 prompt-compact 10
3 prompt-cache true
4 prompt-fixed-kb geral

View file

@ -0,0 +1,9 @@
PARAM subject as string
DESCRIPTION "Chamado quando alguém quer mudar o assunto da conversa."
kbname = LLM "Devolva uma única palavra circular, comunicado ou geral de acordo com a seguinte frase:" + subject
ADD_KB kbname
TALK "You have chosen to change the subject to " + subject + "."

View file

@ -1,9 +1,17 @@
LET resume = GET_BOT_MEMORY("resume")
LET resume1 = GET_BOT_MEMORY("general")
LET resume2 = GET_BOT_MEMORY("auxiliom")
LET resume3 = GET_BOT_MEMORY("toolbix")
IF resume <> "" THEN
TALK resume
END IF
SET_CONTEXT "general", resume1
SET_CONTEXT "auxiliom", resume2
SET_CONTEXT "toolbix", resume3
ADD_SUGGESTION "general", "Show me the weekly announcements"
ADD_SUGGESTION "auxiliom", "Will Auxiliom help me with what?"
ADD_SUGGESTION "auxiliom", "What does Auxiliom do?"
ADD_SUGGESTION "toolbix", "Show me Toolbix features"
ADD_SUGGESTION "toolbix", "How can Toolbix help my business?"
ADD_KB "weekly"
TALK "You can ask me about any of the announcements or circulars."

View file

@ -1,5 +1,11 @@
let text = GET "default.gbdrive/default.pdf"
let text = GET "announcements.gbkb/news/news.pdf"
let resume = LLM "Resume this document, in a table (DO NOT THINK) no_think: " + text
SET_BOT_MEMORY "resume", resume
let text1 = GET "announcements.gbkb/auxiliom/auxiliom.pdf"
SET_BOT_MEMORY "auxiliom", text1
let text2 = GET "announcements.gbkb/toolbix/toolbix.pdf"
SET_BOT_MEMORY "toolbix", text2

View file

@ -1,8 +1,8 @@
name,value
server_host=0.0.0.0
server_port=8080
sites_root=/tmp
server_host,0.0.0.0
server_port,8080
sites_root,/tmp
llm-key,gsk_
llm-model,openai/gpt-oss-20b

1 name,value name value
2 server_host=0.0.0.0 server_host 0.0.0.0
3 server_port=8080 server_port 8080
4 sites_root=/tmp sites_root /tmp
5 llm-key,gsk_ llm-key gsk_
6 llm-model,openai/gpt-oss-20b llm-model openai/gpt-oss-20b
7 llm-url,https://api.groq.com/openai/v1/chat/completions llm-url https://api.groq.com/openai/v1/chat/completions
8 llm-url,http://localhost:8080/v1 llm-url http://localhost:8080/v1