2026-02-12 21:09:30 +00:00
use crate ::core ::package_manager ::component ::ComponentConfig ;
use crate ::core ::package_manager ::os ::detect_os ;
use crate ::core ::package_manager ::{ InstallMode , OsType } ;
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
use crate ::security ::command_guard ::SafeCommand ;
2026-02-14 16:35:24 +00:00
use anyhow ::{ Context , Result } ;
2025-12-15 17:50:03 -03:00
use log ::{ error , info , trace , warn } ;
2026-01-26 20:48:57 -03:00
use once_cell ::sync ::Lazy ;
use serde ::Deserialize ;
2025-11-22 22:55:35 -03:00
use std ::collections ::HashMap ;
use std ::path ::PathBuf ;
2026-02-14 16:35:24 +00:00
#[ cfg(unix) ]
use std ::os ::unix ::fs ::PermissionsExt ;
2026-01-26 20:48:57 -03:00
#[ derive(Deserialize, Debug) ]
struct ComponentEntry {
url : String ,
}
#[ derive(Deserialize, Debug) ]
struct ThirdPartyConfig {
components : HashMap < String , ComponentEntry > ,
}
static THIRDPARTY_CONFIG : Lazy < ThirdPartyConfig > = Lazy ::new ( | | {
let toml_str = include_str! ( " ../../../3rdparty.toml " ) ;
2026-02-08 12:25:37 +00:00
toml ::from_str ( toml_str ) . unwrap_or_else ( | e | {
panic! ( " Failed to parse embedded 3rdparty.toml: {e} " )
} )
2026-01-26 20:48:57 -03:00
} ) ;
fn get_component_url ( name : & str ) -> Option < String > {
THIRDPARTY_CONFIG
. components
. get ( name )
. map ( | c | c . url . clone ( ) )
}
2026-01-27 13:45:54 -03:00
#[ cfg(target_os = " windows " ) ]
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
fn safe_nvcc_version ( ) -> Option < std ::process ::Output > {
SafeCommand ::new ( " nvcc " )
. and_then ( | c | c . arg ( " --version " ) )
. ok ( )
. and_then ( | cmd | cmd . execute ( ) . ok ( ) )
}
fn safe_sh_command ( script : & str ) -> Option < std ::process ::Output > {
SafeCommand ::new ( " sh " )
. and_then ( | c | c . arg ( " -c " ) )
2026-01-09 12:13:35 -03:00
. and_then ( | c | c . trusted_shell_script_arg ( script ) )
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
. ok ( )
. and_then ( | cmd | cmd . execute ( ) . ok ( ) )
}
fn safe_pgrep ( args : & [ & str ] ) -> Option < std ::process ::Output > {
SafeCommand ::new ( " pgrep " )
. and_then ( | c | c . args ( args ) )
. ok ( )
. and_then ( | cmd | cmd . execute ( ) . ok ( ) )
}
2025-12-10 12:54:52 -03:00
const LLAMA_CPP_VERSION : & str = " b7345 " ;
fn get_llama_cpp_url ( ) -> Option < String > {
#[ cfg(target_os = " linux " ) ]
{
#[ cfg(target_arch = " x86_64 " ) ]
{
if std ::path ::Path ::new ( " /usr/local/cuda " ) . exists ( )
| | std ::path ::Path ::new ( " /opt/cuda " ) . exists ( )
| | std ::env ::var ( " CUDA_HOME " ) . is_ok ( )
{
2026-01-26 20:48:57 -03:00
// CUDA versions not currently in 3rdparty.toml for Linux, falling back to Vulkan or CPU if not added
// Or if we had them: get_component_url("llm_linux_cuda12")
2025-12-10 12:54:52 -03:00
}
if std ::path ::Path ::new ( " /usr/share/vulkan " ) . exists ( )
| | std ::env ::var ( " VULKAN_SDK " ) . is_ok ( )
{
info! ( " Detected Vulkan - using Vulkan build " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_linux_vulkan " ) ;
2025-12-10 12:54:52 -03:00
}
info! ( " Using standard Ubuntu x64 build (CPU) " ) ;
2026-02-04 13:29:29 -03:00
get_component_url ( " llm " )
2025-12-10 12:54:52 -03:00
}
#[ cfg(target_arch = " s390x " ) ]
{
info! ( " Detected s390x architecture " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_linux_s390x " ) ;
2025-12-10 12:54:52 -03:00
}
#[ cfg(target_arch = " aarch64 " ) ]
{
info! ( " Detected ARM64 architecture on Linux " ) ;
warn! ( " No pre-built llama.cpp for Linux ARM64 - LLM will not be available " ) ;
return None ;
}
}
#[ cfg(target_os = " macos " ) ]
{
#[ cfg(target_arch = " aarch64 " ) ]
{
info! ( " Detected macOS ARM64 (Apple Silicon) " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_macos_arm64 " ) ;
2025-12-10 12:54:52 -03:00
}
#[ cfg(target_arch = " x86_64 " ) ]
{
info! ( " Detected macOS x64 (Intel) " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_macos_x64 " ) ;
2025-12-10 12:54:52 -03:00
}
}
#[ cfg(target_os = " windows " ) ]
{
#[ cfg(target_arch = " x86_64 " ) ]
{
if std ::env ::var ( " CUDA_PATH " ) . is_ok ( ) {
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
if let Some ( output ) = safe_nvcc_version ( ) {
2025-12-10 12:54:52 -03:00
let version_str = String ::from_utf8_lossy ( & output . stdout ) ;
if version_str . contains ( " 13. " ) {
info! ( " Detected CUDA 13.x on Windows " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_win_cuda13 " ) ;
2025-12-10 12:54:52 -03:00
} else if version_str . contains ( " 12. " ) {
info! ( " Detected CUDA 12.x on Windows " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_win_cuda12 " ) ;
2025-12-10 12:54:52 -03:00
}
}
}
if std ::env ::var ( " VULKAN_SDK " ) . is_ok ( ) {
info! ( " Detected Vulkan SDK on Windows " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_win_vulkan " ) ;
2025-12-10 12:54:52 -03:00
}
info! ( " Using standard Windows x64 CPU build " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_win_cpu_x64 " ) ;
2025-12-10 12:54:52 -03:00
}
#[ cfg(target_arch = " aarch64 " ) ]
{
info! ( " Detected Windows ARM64 " ) ;
2026-01-26 20:48:57 -03:00
return get_component_url ( " llm_win_cpu_arm64 " ) ;
2025-12-10 12:54:52 -03:00
}
}
}
2025-11-22 22:55:35 -03:00
#[ derive(Debug) ]
pub struct PackageManager {
pub mode : InstallMode ,
pub os_type : OsType ,
pub base_path : PathBuf ,
pub tenant : String ,
pub components : HashMap < String , ComponentConfig > ,
}
impl PackageManager {
pub fn new ( mode : InstallMode , tenant : Option < String > ) -> Result < Self > {
let os_type = detect_os ( ) ;
let base_path = if mode = = InstallMode ::Container {
PathBuf ::from ( " /opt/gbo " )
2025-12-06 14:55:42 -03:00
} else if let Ok ( custom_path ) = std ::env ::var ( " BOTSERVER_STACK_PATH " ) {
PathBuf ::from ( custom_path )
2025-11-22 22:55:35 -03:00
} else {
std ::env ::current_dir ( ) ? . join ( " botserver-stack " )
} ;
let tenant = tenant . unwrap_or_else ( | | " default " . to_string ( ) ) ;
2025-12-26 08:59:25 -03:00
let mut pm = Self {
2025-11-22 22:55:35 -03:00
mode ,
os_type ,
base_path ,
tenant ,
components : HashMap ::new ( ) ,
} ;
pm . register_components ( ) ;
Ok ( pm )
}
2025-12-06 14:55:42 -03:00
pub fn with_base_path (
mode : InstallMode ,
tenant : Option < String > ,
base_path : PathBuf ,
) -> Result < Self > {
let os_type = detect_os ( ) ;
let tenant = tenant . unwrap_or_else ( | | " default " . to_string ( ) ) ;
2025-12-26 08:59:25 -03:00
let mut pm = Self {
2025-12-06 14:55:42 -03:00
mode ,
os_type ,
base_path ,
tenant ,
components : HashMap ::new ( ) ,
} ;
pm . register_components ( ) ;
Ok ( pm )
}
2025-11-22 22:55:35 -03:00
fn register_components ( & mut self ) {
2025-12-07 02:13:28 -03:00
self . register_vault ( ) ;
2025-11-22 22:55:35 -03:00
self . register_tables ( ) ;
self . register_cache ( ) ;
self . register_drive ( ) ;
self . register_llm ( ) ;
self . register_email ( ) ;
self . register_proxy ( ) ;
2025-11-29 16:29:28 -03:00
self . register_dns ( ) ;
2025-11-22 22:55:35 -03:00
self . register_directory ( ) ;
self . register_alm ( ) ;
self . register_alm_ci ( ) ;
self . register_meeting ( ) ;
2025-12-02 21:09:43 -03:00
self . register_remote_terminal ( ) ;
2025-11-22 22:55:35 -03:00
self . register_devtools ( ) ;
self . register_vector_db ( ) ;
2025-11-30 15:07:29 -03:00
self . register_timeseries_db ( ) ;
2025-11-30 16:25:51 -03:00
self . register_observability ( ) ;
2025-11-22 22:55:35 -03:00
self . register_host ( ) ;
2025-12-02 21:09:43 -03:00
self . register_webmail ( ) ;
self . register_table_editor ( ) ;
self . register_doc_editor ( ) ;
2025-11-22 22:55:35 -03:00
}
fn register_drive ( & mut self ) {
self . components . insert (
" drive " . to_string ( ) ,
ComponentConfig {
name : " drive " . to_string ( ) ,
2026-02-12 21:09:30 +00:00
ports : vec ! [ 9100 , 9101 ] ,
2025-11-22 22:55:35 -03:00
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " drive " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " minio " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::from ( [
( " MINIO_ROOT_USER " . to_string ( ) , " $DRIVE_ACCESSKEY " . to_string ( ) ) ,
( " MINIO_ROOT_PASSWORD " . to_string ( ) , " $DRIVE_SECRET " . to_string ( ) ) ,
] ) ,
data_download_list : Vec ::new ( ) ,
2026-02-12 21:09:30 +00:00
exec_cmd : " nohup {{BIN_PATH}}/minio server {{DATA_PATH}} --address :9100 --console-address :9101 --certs-dir {{CONF_PATH}}/drive/certs > {{LOGS_PATH}}/minio.log 2>&1 & " . to_string ( ) ,
check_cmd : " curl -sf --cacert {{CONF_PATH}}/drive/certs/CAs/ca.crt https://127.0.0.1:9100/minio/health/live >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_tables ( & mut self ) {
self . components . insert (
" tables " . to_string ( ) ,
ComponentConfig {
name : " tables " . to_string ( ) ,
ports : vec ! [ 5432 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " tables " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " postgres " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [
" chmod +x ./bin/* " . to_string ( ) ,
2025-12-08 00:19:29 -03:00
" if [ ! -d \" {{DATA_PATH}}/pgdata \" ]; then PG_PASSWORD='{{DB_PASSWORD}}' ./bin/initdb -D {{DATA_PATH}}/pgdata -U gbuser --pwfile=<(echo \" $PG_PASSWORD \" ); fi " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
" echo \" data_directory = '{{DATA_PATH}}/pgdata' \" > {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
" echo \" ident_file = '{{CONF_PATH}}/pg_ident.conf' \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
" echo \" port = 5432 \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
" echo \" listen_addresses = '*' \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
2025-11-29 16:29:28 -03:00
" echo \" ssl = on \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
2025-12-08 00:19:29 -03:00
" echo \" ssl_cert_file = '{{CONF_PATH}}/system/certificates/tables/server.crt' \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
" echo \" ssl_key_file = '{{CONF_PATH}}/system/certificates/tables/server.key' \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
2025-11-29 16:29:28 -03:00
" echo \" ssl_ca_file = '{{CONF_PATH}}/system/certificates/ca/ca.crt' \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
" echo \" log_directory = '{{LOGS_PATH}}' \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
" echo \" logging_collector = on \" >> {{CONF_PATH}}/postgresql.conf " . to_string ( ) ,
2025-11-29 16:29:28 -03:00
" echo \" hostssl all all all md5 \" > {{CONF_PATH}}/pg_hba.conf " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
" touch {{CONF_PATH}}/pg_ident.conf " . to_string ( ) ,
" ./bin/pg_ctl -D {{DATA_PATH}}/pgdata -l {{LOGS_PATH}}/postgres.log start -w -t 30 " . to_string ( ) ,
" sleep 5 " . to_string ( ) ,
2026-02-05 20:40:52 -03:00
" for i in $(seq 1 30); do ./bin/pg_isready -h localhost -p 5432 -d postgres >/dev/null 2>&1 && echo 'PostgreSQL is ready' && break || echo \" Waiting for PostgreSQL... attempt $i/30 \" >&2; sleep 2; done " . to_string ( ) ,
" ./bin/pg_isready -h localhost -p 5432 -d postgres || { echo 'ERROR: PostgreSQL failed to start properly' >&2; cat {{LOGS_PATH}}/postgres.log >&2; exit 1; } " . to_string ( ) ,
2025-12-08 00:19:29 -03:00
" PGPASSWORD='{{DB_PASSWORD}}' ./bin/psql -h localhost -p 5432 -U gbuser -d postgres -c \" CREATE DATABASE botserver WITH OWNER gbuser \" 2>&1 | grep -v 'already exists' || true " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [
" chmod +x ./bin/* " . to_string ( ) ,
" if [ ! -d \" {{DATA_PATH}}/pgdata \" ]; then ./bin/initdb -A -D {{DATA_PATH}}/pgdata -U postgres; fi " . to_string ( ) ,
] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " ./bin/pg_ctl -D {{DATA_PATH}}/pgdata -l {{LOGS_PATH}}/postgres.log start -w -t 30 > {{LOGS_PATH}}/stdout.log 2>&1 & " . to_string ( ) ,
2026-02-05 20:40:52 -03:00
check_cmd : " {{BIN_PATH}}/bin/pg_isready -h localhost -p 5432 -d postgres >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_cache ( & mut self ) {
self . components . insert (
" cache " . to_string ( ) ,
ComponentConfig {
name : " cache " . to_string ( ) ,
ports : vec ! [ 6379 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " cache " ) ,
2025-12-08 00:19:29 -03:00
binary_name : Some ( " valkey-server " . to_string ( ) ) ,
2025-11-22 22:55:35 -03:00
pre_install_cmds_linux : vec ! [ ] ,
2025-12-08 00:19:29 -03:00
post_install_cmds_linux : vec ! [
2026-02-15 01:22:14 +00:00
" mkdir -p {{BIN_PATH}}/bin && cd {{BIN_PATH}}/bin && tar -xzf {{CACHE_FILE}} --strip-components=1 -C {{BIN_PATH}}/bin 2>/dev/null || true " . to_string ( ) ,
" chmod +x {{BIN_PATH}}/bin/valkey-server 2>/dev/null || true " . to_string ( ) ,
" chmod +x {{BIN_PATH}}/bin/valkey-cli 2>/dev/null || true " . to_string ( ) ,
" chmod +x {{BIN_PATH}}/bin/valkey-benchmark 2>/dev/null || true " . to_string ( ) ,
" chmod +x {{BIN_PATH}}/bin/valkey-check-aof 2>/dev/null || true " . to_string ( ) ,
" chmod +x {{BIN_PATH}}/bin/valkey-check-rdb 2>/dev/null || true " . to_string ( ) ,
" chmod +x {{BIN_PATH}}/bin/valkey-sentinel 2>/dev/null || true " . to_string ( ) ,
2025-12-08 00:19:29 -03:00
] ,
2025-11-22 22:55:35 -03:00
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
2026-02-15 01:22:14 +00:00
exec_cmd : " nohup {{BIN_PATH}}/bin/valkey-server --port 6379 --dir {{DATA_PATH}} --logfile {{LOGS_PATH}}/valkey.log --daemonize yes > {{LOGS_PATH}}/valkey-startup.log 2>&1 " . to_string ( ) ,
check_cmd : " {{BIN_PATH}}/bin/valkey-cli ping 2>/dev/null | grep -q PONG " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_llm ( & mut self ) {
2025-12-10 12:54:52 -03:00
let download_url = get_llama_cpp_url ( ) ;
if download_url . is_none ( ) {
warn! ( " No llama.cpp binary available for this platform " ) ;
warn! ( " Local LLM will not be available - use external API instead " ) ;
}
info! (
" LLM component using llama.cpp {} for this platform " ,
LLAMA_CPP_VERSION
) ;
2025-11-22 22:55:35 -03:00
self . components . insert (
" llm " . to_string ( ) ,
ComponentConfig {
name : " llm " . to_string ( ) ,
ports : vec ! [ 8081 , 8082 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2025-12-10 12:54:52 -03:00
download_url ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " llama-server " . to_string ( ) ) ,
2025-12-10 09:00:05 -03:00
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
2025-11-22 22:55:35 -03:00
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : vec ! [
2025-12-23 18:40:58 -03:00
2025-11-22 22:55:35 -03:00
" https://huggingface.co/bartowski/DeepSeek-R1-Distill-Qwen-1.5B-GGUF/resolve/main/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf " . to_string ( ) ,
2025-12-23 18:40:58 -03:00
2025-11-22 22:55:35 -03:00
" https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf/resolve/main/bge-small-en-v1.5-f32.gguf " . to_string ( ) ,
] ,
2026-02-04 13:29:29 -03:00
exec_cmd : " nohup {{BIN_PATH}}/build/bin/llama-server --port 8081 --ssl-key-file {{CONF_PATH}}/system/certificates/llm/server.key --ssl-cert-file {{CONF_PATH}}/system/certificates/llm/server.crt -m {{DATA_PATH}}/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf --ubatch-size 512 > {{LOGS_PATH}}/llm.log 2>&1 & nohup {{BIN_PATH}}/build/bin/llama-server --port 8082 --ssl-key-file {{CONF_PATH}}/system/certificates/embedding/server.key --ssl-cert-file {{CONF_PATH}}/system/certificates/embedding/server.crt -m {{DATA_PATH}}/bge-small-en-v1.5-f32.gguf --embedding --ubatch-size 512 > {{LOGS_PATH}}/embedding.log 2>&1 & " . to_string ( ) ,
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
check_cmd : " curl -f -k --connect-timeout 2 -m 5 https://localhost:8081/health >/dev/null 2>&1 && curl -f -k --connect-timeout 2 -m 5 https://localhost:8082/health >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_email ( & mut self ) {
self . components . insert (
" email " . to_string ( ) ,
ComponentConfig {
name : " email " . to_string ( ) ,
2025-11-29 16:29:28 -03:00
ports : vec ! [ 25 , 143 , 465 , 993 , 8025 ] ,
2025-11-22 22:55:35 -03:00
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " email " ) ,
2025-11-29 16:29:28 -03:00
binary_name : Some ( " stalwart-mail " . to_string ( ) ) ,
2025-11-22 22:55:35 -03:00
pre_install_cmds_linux : vec ! [ ] ,
2025-11-29 16:29:28 -03:00
post_install_cmds_linux : vec ! [ ] ,
2025-11-22 22:55:35 -03:00
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
2025-11-29 16:29:28 -03:00
env_vars : HashMap ::from ( [
( " STALWART_TLS_ENABLE " . to_string ( ) , " true " . to_string ( ) ) ,
( " STALWART_TLS_CERT " . to_string ( ) , " {{CONF_PATH}}/system/certificates/email/server.crt " . to_string ( ) ) ,
( " STALWART_TLS_KEY " . to_string ( ) , " {{CONF_PATH}}/system/certificates/email/server.key " . to_string ( ) ) ,
] ) ,
2025-11-22 22:55:35 -03:00
data_download_list : Vec ::new ( ) ,
2025-11-29 16:29:28 -03:00
exec_cmd : " {{BIN_PATH}}/stalwart-mail --config {{CONF_PATH}}/email/config.toml " . to_string ( ) ,
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
check_cmd : " curl -f -k --connect-timeout 2 -m 5 https://localhost:8025/health >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_proxy ( & mut self ) {
self . components . insert (
" proxy " . to_string ( ) ,
ComponentConfig {
name : " proxy " . to_string ( ) ,
ports : vec ! [ 80 , 443 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " proxy " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " caddy " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [
" setcap 'cap_net_bind_service=+ep' {{BIN_PATH}}/caddy " . to_string ( ) ,
] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
env_vars : HashMap ::from ( [ (
" XDG_DATA_HOME " . to_string ( ) ,
" {{DATA_PATH}} " . to_string ( ) ,
) ] ) ,
2025-11-22 22:55:35 -03:00
data_download_list : Vec ::new ( ) ,
exec_cmd : " {{BIN_PATH}}/caddy run --config {{CONF_PATH}}/Caddyfile " . to_string ( ) ,
2026-01-26 20:48:57 -03:00
check_cmd : " curl -f --connect-timeout 2 -m 5 http://localhost >/dev/null 2>&1 "
. to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_directory ( & mut self ) {
self . components . insert (
" directory " . to_string ( ) ,
ComponentConfig {
name : " directory " . to_string ( ) ,
2026-03-01 07:40:11 -03:00
ports : vec ! [ 9000 ] ,
2025-12-07 02:13:28 -03:00
dependencies : vec ! [ " tables " . to_string ( ) ] ,
2025-11-22 22:55:35 -03:00
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " directory " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " zitadel " . to_string ( ) ) ,
2025-12-07 02:13:28 -03:00
pre_install_cmds_linux : vec ! [
" mkdir -p {{CONF_PATH}}/directory " . to_string ( ) ,
2025-12-08 00:19:29 -03:00
" mkdir -p {{LOGS_PATH}} " . to_string ( ) ,
2026-03-01 19:06:09 -03:00
// Create Zitadel steps YAML: configures a machine user (service account)
// with IAM_OWNER role and writes a PAT file for API bootstrap
concat! (
" cat > {{CONF_PATH}}/directory/zitadel-init-steps.yaml << 'STEPSEOF' \n " ,
" FirstInstance: \n " ,
" Org: \n " ,
" Machine: \n " ,
" Machine: \n " ,
" Username: gb-service-account \n " ,
" Name: General Bots Service Account \n " ,
" MachineKey: \n " ,
" Type: 1 \n " ,
" Pat: \n " ,
" ExpirationDate: '2099-01-01T00:00:00Z' \n " ,
" PatPath: {{CONF_PATH}}/directory/admin-pat.txt \n " ,
" MachineKeyPath: {{CONF_PATH}}/directory/machine-key.json \n " ,
" STEPSEOF " ,
) . to_string ( ) ,
2025-12-07 02:13:28 -03:00
] ,
post_install_cmds_linux : vec ! [
2026-03-01 19:06:09 -03:00
// Create zitadel DB user before start-from-init
" PGPASSWORD='{{DB_PASSWORD}}' {{STACK_PATH}}/bin/tables/bin/psql -h localhost -p 5432 -U gbuser -d postgres -c \" CREATE ROLE zitadel WITH LOGIN PASSWORD 'zitadel' \" 2>&1 | grep -v 'already exists' || true " . to_string ( ) ,
" PGPASSWORD='{{DB_PASSWORD}}' {{STACK_PATH}}/bin/tables/bin/psql -h localhost -p 5432 -U gbuser -d postgres -c \" CREATE DATABASE zitadel WITH OWNER zitadel \" 2>&1 | grep -v 'already exists' || true " . to_string ( ) ,
" PGPASSWORD='{{DB_PASSWORD}}' {{STACK_PATH}}/bin/tables/bin/psql -h localhost -p 5432 -U gbuser -d postgres -c \" GRANT ALL PRIVILEGES ON DATABASE zitadel TO zitadel \" 2>&1 || true " . to_string ( ) ,
// Start Zitadel with --steps pointing to our init file (creates machine user + PAT)
concat! (
" ZITADEL_PORT=8300 " ,
" ZITADEL_DATABASE_POSTGRES_HOST=localhost " ,
" ZITADEL_DATABASE_POSTGRES_PORT=5432 " ,
" ZITADEL_DATABASE_POSTGRES_DATABASE=zitadel " ,
" ZITADEL_DATABASE_POSTGRES_USER_USERNAME=zitadel " ,
" ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=zitadel " ,
" ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable " ,
" ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=gbuser " ,
" ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD={{DB_PASSWORD}} " ,
" ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable " ,
" ZITADEL_EXTERNALSECURE=false " ,
" ZITADEL_EXTERNALDOMAIN=localhost " ,
" ZITADEL_EXTERNALPORT=8300 " ,
" ZITADEL_TLS_ENABLED=false " ,
" nohup {{BIN_PATH}}/zitadel start-from-init " ,
" --masterkey MasterkeyNeedsToHave32Characters " ,
" --tlsMode disabled " ,
" --steps {{CONF_PATH}}/directory/zitadel-init-steps.yaml " ,
" > {{LOGS_PATH}}/zitadel.log 2>&1 & " ,
) . to_string ( ) ,
// Wait for Zitadel to be ready
" for i in $(seq 1 120); do curl -sf http://localhost:8300/debug/healthz && echo 'Zitadel is ready!' && break || sleep 2; done " . to_string ( ) ,
// Wait for PAT token to be written to logs with retry loop
// Zitadel may take several seconds to write the PAT after health check passes
" echo 'Waiting for PAT token in logs...'; for i in $(seq 1 30); do sync; if grep -q -E '^[A-Za-z0-9_-]{40,}$' {{LOGS_PATH}}/zitadel.log 2>/dev/null; then echo \" PAT token found in logs after $((i*2)) seconds \" ; break; fi; sleep 2; done " . to_string ( ) ,
// Extract PAT token from logs if Zitadel printed it to stdout instead of file
// The PAT appears as a standalone line (alphanumeric with hyphens/underscores) after machine key JSON
" if [ ! -f '{{CONF_PATH}}/directory/admin-pat.txt' ]; then grep -E '^[A-Za-z0-9_-]{40,}$' {{LOGS_PATH}}/zitadel.log 2>/dev/null | head -1 > {{CONF_PATH}}/directory/admin-pat.txt && echo 'PAT extracted from logs' || echo 'Could not extract PAT from logs'; fi " . to_string ( ) ,
// Verify PAT file was created and is not empty
" sync; sleep 1; if [ -f '{{CONF_PATH}}/directory/admin-pat.txt' ] && [ -s '{{CONF_PATH}}/directory/admin-pat.txt' ]; then echo 'PAT token created successfully'; cat {{CONF_PATH}}/directory/admin-pat.txt; else echo 'WARNING: PAT file not found or empty'; fi " . to_string ( ) ,
2025-12-07 02:13:28 -03:00
] ,
pre_install_cmds_macos : vec ! [
" mkdir -p {{CONF_PATH}}/directory " . to_string ( ) ,
] ,
2025-11-22 22:55:35 -03:00
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
2025-11-29 16:29:28 -03:00
env_vars : HashMap ::from ( [
2026-03-01 19:06:09 -03:00
( " ZITADEL_PORT " . to_string ( ) , " 8300 " . to_string ( ) ) ,
2025-12-07 02:13:28 -03:00
( " ZITADEL_EXTERNALSECURE " . to_string ( ) , " false " . to_string ( ) ) ,
( " ZITADEL_EXTERNALDOMAIN " . to_string ( ) , " localhost " . to_string ( ) ) ,
2026-03-01 09:52:31 -03:00
( " ZITADEL_EXTERNALPORT " . to_string ( ) , " 8300 " . to_string ( ) ) ,
2025-12-07 02:13:28 -03:00
( " ZITADEL_TLS_ENABLED " . to_string ( ) , " false " . to_string ( ) ) ,
2025-11-29 16:29:28 -03:00
] ) ,
2025-11-22 22:55:35 -03:00
data_download_list : Vec ::new ( ) ,
2026-03-01 19:06:09 -03:00
exec_cmd : concat ! (
" ZITADEL_PORT=8300 " ,
" ZITADEL_DATABASE_POSTGRES_HOST=localhost " ,
" ZITADEL_DATABASE_POSTGRES_PORT=5432 " ,
" ZITADEL_DATABASE_POSTGRES_DATABASE=zitadel " ,
" ZITADEL_DATABASE_POSTGRES_USER_USERNAME=zitadel " ,
" ZITADEL_DATABASE_POSTGRES_USER_PASSWORD=zitadel " ,
" ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE=disable " ,
" ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME=gbuser " ,
" ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD={{DB_PASSWORD}} " ,
" ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE=disable " ,
" ZITADEL_EXTERNALSECURE=false " ,
" ZITADEL_EXTERNALDOMAIN=localhost " ,
" ZITADEL_EXTERNALPORT=8300 " ,
" ZITADEL_TLS_ENABLED=false " ,
" nohup {{BIN_PATH}}/zitadel start " ,
" --masterkey MasterkeyNeedsToHave32Characters " ,
" --tlsMode disabled " ,
" > {{LOGS_PATH}}/zitadel.log 2>&1 & " ,
) . to_string ( ) ,
check_cmd : " curl -f --connect-timeout 2 -m 5 http://localhost:8300/debug/healthz >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_alm ( & mut self ) {
self . components . insert (
" alm " . to_string ( ) ,
ComponentConfig {
name : " alm " . to_string ( ) ,
ports : vec ! [ 3000 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " alm " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " forgejo " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::from ( [
( " USER " . to_string ( ) , " alm " . to_string ( ) ) ,
( " HOME " . to_string ( ) , " {{DATA_PATH}} " . to_string ( ) ) ,
] ) ,
data_download_list : Vec ::new ( ) ,
2026-03-12 18:19:18 -03:00
exec_cmd : " nohup {{BIN_PATH}}/forgejo web --work-path {{DATA_PATH}} --port 3000 --cert {{CONF_PATH}}/system/certificates/alm/server.crt --key {{CONF_PATH}}/system/certificates/alm/server.key > {{LOGS_PATH}}/forgejo.log 2>&1 & " . to_string ( ) ,
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
check_cmd : " curl -f -k --connect-timeout 2 -m 5 https://localhost:3000 >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_alm_ci ( & mut self ) {
self . components . insert (
" alm-ci " . to_string ( ) ,
ComponentConfig {
name : " alm-ci " . to_string ( ) ,
ports : vec ! [ ] ,
dependencies : vec ! [ " alm " . to_string ( ) ] ,
2025-11-30 16:25:51 -03:00
linux_packages : vec ! [ ] ,
2025-11-22 22:55:35 -03:00
macos_packages : vec ! [ " git " . to_string ( ) , " node " . to_string ( ) ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " alm_ci " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " forgejo-runner " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [
2025-11-30 16:25:51 -03:00
" mkdir -p {{CONF_PATH}}/alm-ci " . to_string ( ) ,
] ,
post_install_cmds_linux : vec ! [
2025-12-23 18:40:58 -03:00
2025-11-30 16:25:51 -03:00
" echo 'To register the runner, run:' " . to_string ( ) ,
" echo '{{BIN_PATH}}/forgejo-runner register --instance $ALM_URL --token $ALM_RUNNER_TOKEN --name gbo --labels ubuntu-latest:docker://node:20-bookworm' " . to_string ( ) ,
" echo 'Then start with: {{BIN_PATH}}/forgejo-runner daemon --config {{CONF_PATH}}/alm-ci/config.yaml' " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
2025-11-30 16:25:51 -03:00
env_vars : {
let mut env = HashMap ::new ( ) ;
env . insert ( " ALM_URL " . to_string ( ) , " $ALM_URL " . to_string ( ) ) ;
env . insert ( " ALM_RUNNER_TOKEN " . to_string ( ) , " $ALM_RUNNER_TOKEN " . to_string ( ) ) ;
env
} ,
2025-11-22 22:55:35 -03:00
data_download_list : Vec ::new ( ) ,
2026-03-12 18:19:18 -03:00
exec_cmd : " nohup {{BIN_PATH}}/forgejo-runner daemon --config {{CONF_PATH}}/alm-ci/config.yaml > {{LOGS_PATH}}/forgejo-runner.log 2>&1 & " . to_string ( ) ,
2025-12-08 23:35:33 -03:00
check_cmd : " ps -ef | grep forgejo-runner | grep -v grep | grep {{BIN_PATH}} >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_dns ( & mut self ) {
self . components . insert (
" dns " . to_string ( ) ,
ComponentConfig {
name : " dns " . to_string ( ) ,
ports : vec ! [ 53 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " dns " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " coredns " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
2025-11-29 16:29:28 -03:00
post_install_cmds_linux : vec ! [ ] ,
2025-11-22 22:55:35 -03:00
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
2025-11-29 16:29:28 -03:00
exec_cmd : " {{BIN_PATH}}/coredns -conf {{CONF_PATH}}/dns/Corefile " . to_string ( ) ,
check_cmd : " dig @localhost botserver.local >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_webmail ( & mut self ) {
self . components . insert (
" webmail " . to_string ( ) ,
ComponentConfig {
name : " webmail " . to_string ( ) ,
2025-12-11 08:43:28 -03:00
ports : vec ! [ 8300 ] ,
2025-11-22 22:55:35 -03:00
dependencies : vec ! [ " email " . to_string ( ) ] ,
linux_packages : vec ! [
" ca-certificates " . to_string ( ) ,
" apt-transport-https " . to_string ( ) ,
" php8.1 " . to_string ( ) ,
" php8.1-fpm " . to_string ( ) ,
] ,
macos_packages : vec ! [ " php " . to_string ( ) ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " webmail " ) ,
2025-11-22 22:55:35 -03:00
binary_name : None ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
2026-02-18 17:51:47 +00:00
exec_cmd : " php -S 0.0.0.0:9000 -t {{DATA_PATH}}/roundcubemail " . to_string ( ) ,
2026-01-26 20:48:57 -03:00
check_cmd :
" curl -f -k --connect-timeout 2 -m 5 https://localhost:8300 >/dev/null 2>&1 "
. to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_meeting ( & mut self ) {
self . components . insert (
2025-11-29 16:29:28 -03:00
" meet " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
ComponentConfig {
2025-11-29 16:29:28 -03:00
name : " meet " . to_string ( ) ,
ports : vec ! [ 7880 ] ,
2025-11-22 22:55:35 -03:00
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " meet " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " livekit-server " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
2025-11-29 16:29:28 -03:00
exec_cmd : " {{BIN_PATH}}/livekit-server --config {{CONF_PATH}}/meet/config.yaml --key-file {{CONF_PATH}}/system/certificates/meet/server.key --cert-file {{CONF_PATH}}/system/certificates/meet/server.crt " . to_string ( ) ,
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
check_cmd : " curl -f -k --connect-timeout 2 -m 5 https://localhost:7880 >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_table_editor ( & mut self ) {
self . components . insert (
" table_editor " . to_string ( ) ,
ComponentConfig {
name : " table_editor " . to_string ( ) ,
ports : vec ! [ 5757 ] ,
dependencies : vec ! [ " tables " . to_string ( ) ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " table_editor " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " nocodb " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " {{BIN_PATH}}/nocodb " . to_string ( ) ,
2025-12-28 11:50:50 -03:00
check_cmd :
" curl -f -k --connect-timeout 2 -m 5 https://localhost:5757 >/dev/null 2>&1 "
. to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
fn register_doc_editor ( & mut self ) {
self . components . insert (
" doc_editor " . to_string ( ) ,
ComponentConfig {
name : " doc_editor " . to_string ( ) ,
ports : vec ! [ 9980 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
download_url : None ,
binary_name : Some ( " coolwsd " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " coolwsd --config-file={{CONF_PATH}}/coolwsd.xml " . to_string ( ) ,
2025-12-28 11:50:50 -03:00
check_cmd :
" curl -f -k --connect-timeout 2 -m 5 https://localhost:9980 >/dev/null 2>&1 "
. to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
2025-12-02 21:09:43 -03:00
fn register_remote_terminal ( & mut self ) {
2025-11-22 22:55:35 -03:00
self . components . insert (
2025-12-02 21:09:43 -03:00
" remote_terminal " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
ComponentConfig {
2025-12-02 21:09:43 -03:00
name : " remote_terminal " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
ports : vec ! [ 3389 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ " xvfb " . to_string ( ) , " xrdp " . to_string ( ) , " xfce4 " . to_string ( ) ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
download_url : None ,
binary_name : None ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " xrdp --nodaemon " . to_string ( ) ,
check_cmd : " netstat -tln | grep :3389 >/dev/null 2>&1 " . to_string ( ) ,
} ,
) ;
}
fn register_devtools ( & mut self ) {
self . components . insert (
" devtools " . to_string ( ) ,
ComponentConfig {
name : " devtools " . to_string ( ) ,
ports : vec ! [ ] ,
dependencies : vec ! [ ] ,
2026-01-26 11:44:18 -03:00
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
2025-11-22 22:55:35 -03:00
windows_packages : vec ! [ ] ,
download_url : None ,
binary_name : None ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " " . to_string ( ) ,
check_cmd : " " . to_string ( ) ,
} ,
) ;
}
2025-11-27 15:19:17 -03:00
fn _register_botserver ( & mut self ) {
2025-11-22 22:55:35 -03:00
self . components . insert (
" system " . to_string ( ) ,
ComponentConfig {
name : " system " . to_string ( ) ,
ports : vec ! [ 8000 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ " curl " . to_string ( ) , " unzip " . to_string ( ) , " git " . to_string ( ) ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
download_url : None ,
binary_name : None ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " " . to_string ( ) ,
check_cmd : " " . to_string ( ) ,
} ,
) ;
}
fn register_vector_db ( & mut self ) {
self . components . insert (
" vector_db " . to_string ( ) ,
ComponentConfig {
name : " vector_db " . to_string ( ) ,
2025-12-29 18:21:03 -03:00
ports : vec ! [ 6334 ] ,
2025-11-22 22:55:35 -03:00
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " vector_db " ) ,
2025-11-22 22:55:35 -03:00
binary_name : Some ( " qdrant " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [ ] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
2025-12-29 18:21:03 -03:00
exec_cmd : " nohup {{BIN_PATH}}/qdrant --config-path {{CONF_PATH}}/vector_db/config.yaml > {{LOGS_PATH}}/qdrant.log 2>&1 & " . to_string ( ) ,
check_cmd : " curl -sfk https://localhost:6333/collections >/dev/null 2>&1 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
} ,
) ;
}
2025-11-30 15:07:29 -03:00
fn register_timeseries_db ( & mut self ) {
self . components . insert (
" timeseries_db " . to_string ( ) ,
ComponentConfig {
name : " timeseries_db " . to_string ( ) ,
ports : vec ! [ 8086 , 8083 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " timeseries_db " ) ,
2025-11-30 15:07:29 -03:00
binary_name : Some ( " influxd " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [
" mkdir -p {{DATA_PATH}}/influxdb " . to_string ( ) ,
" mkdir -p {{CONF_PATH}}/influxdb " . to_string ( ) ,
] ,
post_install_cmds_linux : vec ! [
2026-01-26 17:00:21 -03:00
" {{BIN_PATH}}/influx setup --org system --bucket metrics --username admin --password {{GENERATED_PASSWORD}} --force " . to_string ( ) ,
2025-11-30 15:07:29 -03:00
] ,
pre_install_cmds_macos : vec ! [
" mkdir -p {{DATA_PATH}}/influxdb " . to_string ( ) ,
] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : {
let mut env = HashMap ::new ( ) ;
env . insert ( " INFLUXD_ENGINE_PATH " . to_string ( ) , " {{DATA_PATH}}/influxdb/engine " . to_string ( ) ) ;
env . insert ( " INFLUXD_BOLT_PATH " . to_string ( ) , " {{DATA_PATH}}/influxdb/influxd.bolt " . to_string ( ) ) ;
env . insert ( " INFLUXD_HTTP_BIND_ADDRESS " . to_string ( ) , " :8086 " . to_string ( ) ) ;
env . insert ( " INFLUXD_REPORTING_DISABLED " . to_string ( ) , " true " . to_string ( ) ) ;
env
} ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " {{BIN_PATH}}/influxd --bolt-path={{DATA_PATH}}/influxdb/influxd.bolt --engine-path={{DATA_PATH}}/influxdb/engine --http-bind-address=:8086 " . to_string ( ) ,
feat(autotask): Implement AutoTask system with intent classification and app generation
- Add IntentClassifier with 7 intent types (APP_CREATE, TODO, MONITOR, ACTION, SCHEDULE, GOAL, TOOL)
- Add AppGenerator with LLM-powered app structure analysis
- Add DesignerAI for modifying apps through conversation
- Add app_server for serving generated apps with clean URLs
- Add db_api for CRUD operations on bot database tables
- Add ask_later keyword for pending info collection
- Add migration 6.1.1 with tables: pending_info, auto_tasks, execution_plans, task_approvals, task_decisions, safety_audit_log, generated_apps, intent_classifications, designer_changes
- Write apps to S3 drive and sync to SITE_ROOT for serving
- Clean URL structure: /apps/{app_name}/
- Integrate with DriveMonitor for file sync
Based on Chapter 17 - Autonomous Tasks specification
2025-12-27 21:10:09 -03:00
check_cmd : " curl -f --connect-timeout 2 -m 5 http://localhost:8086/health >/dev/null 2>&1 " . to_string ( ) ,
2025-11-30 15:07:29 -03:00
} ,
) ;
}
2025-12-07 02:13:28 -03:00
fn register_vault ( & mut self ) {
2025-11-30 16:25:51 -03:00
self . components . insert (
2025-12-07 02:13:28 -03:00
" vault " . to_string ( ) ,
2025-11-30 16:25:51 -03:00
ComponentConfig {
2025-12-07 02:13:28 -03:00
name : " vault " . to_string ( ) ,
2025-11-30 16:25:51 -03:00
ports : vec ! [ 8200 ] ,
dependencies : vec ! [ ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " vault " ) ,
2025-11-30 16:25:51 -03:00
binary_name : Some ( " vault " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [
" mkdir -p {{DATA_PATH}}/vault " . to_string ( ) ,
" mkdir -p {{CONF_PATH}}/vault " . to_string ( ) ,
2025-12-19 09:48:15 -03:00
" mkdir -p {{LOGS_PATH}} " . to_string ( ) ,
r #" cat > {{CONF_PATH}}/vault/config.hcl << 'EOF'
storage " file " {
2025-12-28 11:50:50 -03:00
path = " {{DATA_PATH}}/vault "
2025-12-19 09:48:15 -03:00
}
listener " tcp " {
Fix tasks UI, WebSocket progress, memory monitoring, and app generator
Tasks UI fixes:
- Fix task list to query auto_tasks table instead of tasks table
- Fix task detail endpoint to use UUID binding for auto_tasks query
- Add proper filter handling: complete, active, awaiting, paused, blocked
- Add TaskStats fields: awaiting, paused, blocked, time_saved
- Add /api/tasks/time-saved endpoint
- Add count-all to stats HTML response
App generator improvements:
- Add AgentActivity struct for detailed terminal-style progress
- Add emit_activity method for rich progress events
- Add detailed logging for LLM calls with timing
- Track files_written, tables_synced, bytes_generated
Memory and performance:
- Add memory_monitor module for tracking RSS and thread activity
- Skip 0-byte files in drive monitor and document processor
- Change DRIVE_MONITOR checking logs from info to trace
- Remove unused profile_section macro
WebSocket progress:
- Ensure TaskProgressEvent includes activity field
- Add with_activity builder method
2025-12-30 22:42:32 -03:00
address = " 0.0.0.0:8200 "
tls_disable = false
tls_cert_file = " {{CONF_PATH}}/system/certificates/vault/server.crt "
tls_key_file = " {{CONF_PATH}}/system/certificates/vault/server.key "
2026-01-09 11:19:36 -03:00
tls_client_ca_file = " {{CONF_PATH}}/system/certificates/ca/ca.crt "
2025-12-19 09:48:15 -03:00
}
Fix tasks UI, WebSocket progress, memory monitoring, and app generator
Tasks UI fixes:
- Fix task list to query auto_tasks table instead of tasks table
- Fix task detail endpoint to use UUID binding for auto_tasks query
- Add proper filter handling: complete, active, awaiting, paused, blocked
- Add TaskStats fields: awaiting, paused, blocked, time_saved
- Add /api/tasks/time-saved endpoint
- Add count-all to stats HTML response
App generator improvements:
- Add AgentActivity struct for detailed terminal-style progress
- Add emit_activity method for rich progress events
- Add detailed logging for LLM calls with timing
- Track files_written, tables_synced, bytes_generated
Memory and performance:
- Add memory_monitor module for tracking RSS and thread activity
- Skip 0-byte files in drive monitor and document processor
- Change DRIVE_MONITOR checking logs from info to trace
- Remove unused profile_section macro
WebSocket progress:
- Ensure TaskProgressEvent includes activity field
- Add with_activity builder method
2025-12-30 22:42:32 -03:00
api_addr = " https://localhost:8200 "
cluster_addr = " https://localhost:8201 "
2025-12-19 09:48:15 -03:00
ui = true
disable_mlock = true
EOF " #.to_string(),
2025-11-30 16:25:51 -03:00
] ,
2025-12-23 18:40:58 -03:00
2026-02-14 16:35:24 +00:00
post_install_cmds_linux : vec ! [
" mkdir -p {{CONF_PATH}}/system/certificates/ca " . to_string ( ) ,
" mkdir -p {{CONF_PATH}}/system/certificates/vault " . to_string ( ) ,
" mkdir -p {{CONF_PATH}}/system/certificates/botserver " . to_string ( ) ,
" mkdir -p {{CONF_PATH}}/system/certificates/tables " . to_string ( ) ,
" openssl genrsa -out {{CONF_PATH}}/system/certificates/ca/ca.key 4096 2>/dev/null " . to_string ( ) ,
" openssl req -new -x509 -days 3650 -key {{CONF_PATH}}/system/certificates/ca/ca.key -out {{CONF_PATH}}/system/certificates/ca/ca.crt -subj '/C=BR/ST=SP/L=São Paulo/O=BotServer Internal CA/CN=BotServer CA' 2>/dev/null " . to_string ( ) ,
" openssl genrsa -out {{CONF_PATH}}/system/certificates/vault/server.key 4096 2>/dev/null " . to_string ( ) ,
" openssl req -new -key {{CONF_PATH}}/system/certificates/vault/server.key -out {{CONF_PATH}}/system/certificates/vault/server.csr -subj '/C=BR/ST=SP/L=São Paulo/O=BotServer/CN=localhost' 2>/dev/null " . to_string ( ) ,
" openssl x509 -req -days 3650 -in {{CONF_PATH}}/system/certificates/vault/server.csr -CA {{CONF_PATH}}/system/certificates/ca/ca.crt -CAkey {{CONF_PATH}}/system/certificates/ca/ca.key -CAcreateserial -out {{CONF_PATH}}/system/certificates/vault/server.crt 2>/dev/null " . to_string ( ) ,
" openssl genrsa -out {{CONF_PATH}}/system/certificates/botserver/client.key 4096 2>/dev/null " . to_string ( ) ,
" openssl req -new -key {{CONF_PATH}}/system/certificates/botserver/client.key -out {{CONF_PATH}}/system/certificates/botserver/client.csr -subj '/C=BR/ST=SP/L=São Paulo/O=BotServer/CN=botserver' 2>/dev/null " . to_string ( ) ,
" openssl x509 -req -days 3650 -in {{CONF_PATH}}/system/certificates/botserver/client.csr -CA {{CONF_PATH}}/system/certificates/ca/ca.crt -CAkey {{CONF_PATH}}/system/certificates/ca/ca.key -CAcreateserial -out {{CONF_PATH}}/system/certificates/botserver/client.crt 2>/dev/null " . to_string ( ) ,
" openssl genrsa -out {{CONF_PATH}}/system/certificates/tables/server.key 4096 2>/dev/null " . to_string ( ) ,
" openssl req -new -key {{CONF_PATH}}/system/certificates/tables/server.key -out {{CONF_PATH}}/system/certificates/tables/server.csr -subj '/C=BR/ST=SP/L=São Paulo/O=BotServer/CN=localhost' 2>/dev/null " . to_string ( ) ,
" openssl x509 -req -days 3650 -in {{CONF_PATH}}/system/certificates/tables/server.csr -CA {{CONF_PATH}}/system/certificates/ca/ca.crt -CAkey {{CONF_PATH}}/system/certificates/ca/ca.key -CAcreateserial -out {{CONF_PATH}}/system/certificates/tables/server.crt 2>/dev/null " . to_string ( ) ,
" echo 'Certificates generated successfully' " . to_string ( ) ,
] ,
2025-11-30 16:25:51 -03:00
pre_install_cmds_macos : vec ! [
" mkdir -p {{DATA_PATH}}/vault " . to_string ( ) ,
" mkdir -p {{CONF_PATH}}/vault " . to_string ( ) ,
2025-12-19 09:48:15 -03:00
" mkdir -p {{LOGS_PATH}} " . to_string ( ) ,
r #" cat > {{CONF_PATH}}/vault/config.hcl << 'EOF'
storage " file " {
path = " {{DATA_PATH}}/vault "
}
listener " tcp " {
Fix tasks UI, WebSocket progress, memory monitoring, and app generator
Tasks UI fixes:
- Fix task list to query auto_tasks table instead of tasks table
- Fix task detail endpoint to use UUID binding for auto_tasks query
- Add proper filter handling: complete, active, awaiting, paused, blocked
- Add TaskStats fields: awaiting, paused, blocked, time_saved
- Add /api/tasks/time-saved endpoint
- Add count-all to stats HTML response
App generator improvements:
- Add AgentActivity struct for detailed terminal-style progress
- Add emit_activity method for rich progress events
- Add detailed logging for LLM calls with timing
- Track files_written, tables_synced, bytes_generated
Memory and performance:
- Add memory_monitor module for tracking RSS and thread activity
- Skip 0-byte files in drive monitor and document processor
- Change DRIVE_MONITOR checking logs from info to trace
- Remove unused profile_section macro
WebSocket progress:
- Ensure TaskProgressEvent includes activity field
- Add with_activity builder method
2025-12-30 22:42:32 -03:00
address = " 0.0.0.0:8200 "
tls_disable = false
tls_cert_file = " {{CONF_PATH}}/system/certificates/vault/server.crt "
tls_key_file = " {{CONF_PATH}}/system/certificates/vault/server.key "
2026-01-09 11:19:36 -03:00
tls_client_ca_file = " {{CONF_PATH}}/system/certificates/ca/ca.crt "
2025-12-19 09:48:15 -03:00
}
Fix tasks UI, WebSocket progress, memory monitoring, and app generator
Tasks UI fixes:
- Fix task list to query auto_tasks table instead of tasks table
- Fix task detail endpoint to use UUID binding for auto_tasks query
- Add proper filter handling: complete, active, awaiting, paused, blocked
- Add TaskStats fields: awaiting, paused, blocked, time_saved
- Add /api/tasks/time-saved endpoint
- Add count-all to stats HTML response
App generator improvements:
- Add AgentActivity struct for detailed terminal-style progress
- Add emit_activity method for rich progress events
- Add detailed logging for LLM calls with timing
- Track files_written, tables_synced, bytes_generated
Memory and performance:
- Add memory_monitor module for tracking RSS and thread activity
- Skip 0-byte files in drive monitor and document processor
- Change DRIVE_MONITOR checking logs from info to trace
- Remove unused profile_section macro
WebSocket progress:
- Ensure TaskProgressEvent includes activity field
- Add with_activity builder method
2025-12-30 22:42:32 -03:00
api_addr = " https://localhost:8200 "
cluster_addr = " https://localhost:8201 "
2025-12-19 09:48:15 -03:00
ui = true
disable_mlock = true
EOF " #.to_string(),
2025-11-30 16:25:51 -03:00
] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : {
let mut env = HashMap ::new ( ) ;
2025-12-08 00:19:29 -03:00
env . insert (
" VAULT_ADDR " . to_string ( ) ,
" https://localhost:8200 " . to_string ( ) ,
) ;
Fix tasks UI, WebSocket progress, memory monitoring, and app generator
Tasks UI fixes:
- Fix task list to query auto_tasks table instead of tasks table
- Fix task detail endpoint to use UUID binding for auto_tasks query
- Add proper filter handling: complete, active, awaiting, paused, blocked
- Add TaskStats fields: awaiting, paused, blocked, time_saved
- Add /api/tasks/time-saved endpoint
- Add count-all to stats HTML response
App generator improvements:
- Add AgentActivity struct for detailed terminal-style progress
- Add emit_activity method for rich progress events
- Add detailed logging for LLM calls with timing
- Track files_written, tables_synced, bytes_generated
Memory and performance:
- Add memory_monitor module for tracking RSS and thread activity
- Skip 0-byte files in drive monitor and document processor
- Change DRIVE_MONITOR checking logs from info to trace
- Remove unused profile_section macro
WebSocket progress:
- Ensure TaskProgressEvent includes activity field
- Add with_activity builder method
2025-12-30 22:42:32 -03:00
env . insert (
" VAULT_CACERT " . to_string ( ) ,
" ./botserver-stack/conf/system/certificates/ca/ca.crt " . to_string ( ) ,
) ;
2025-11-30 16:25:51 -03:00
env
} ,
data_download_list : Vec ::new ( ) ,
2025-12-09 01:09:04 -03:00
exec_cmd : " nohup {{BIN_PATH}}/vault server -config={{CONF_PATH}}/vault/config.hcl > {{LOGS_PATH}}/vault.log 2>&1 & "
2025-12-08 00:19:29 -03:00
. to_string ( ) ,
2026-01-09 11:23:49 -03:00
check_cmd : " if [ -f {{CONF_PATH}}/system/certificates/botserver/client.crt ]; then curl -f -sk --connect-timeout 2 -m 5 --cert {{CONF_PATH}}/system/certificates/botserver/client.crt --key {{CONF_PATH}}/system/certificates/botserver/client.key 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1; else curl -f -sk --connect-timeout 2 -m 5 'https://localhost:8200/v1/sys/health?standbyok=true&uninitcode=200&sealedcode=200' >/dev/null 2>&1; fi "
2025-12-08 00:19:29 -03:00
. to_string ( ) ,
2025-11-30 16:25:51 -03:00
} ,
) ;
}
fn register_observability ( & mut self ) {
self . components . insert (
" observability " . to_string ( ) ,
ComponentConfig {
name : " observability " . to_string ( ) ,
2025-12-23 18:40:58 -03:00
ports : vec ! [ 8686 ] ,
2025-11-30 16:25:51 -03:00
dependencies : vec ! [ " timeseries_db " . to_string ( ) ] ,
linux_packages : vec ! [ ] ,
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
2026-01-26 20:48:57 -03:00
download_url : get_component_url ( " observability " ) ,
2025-11-30 16:25:51 -03:00
binary_name : Some ( " vector " . to_string ( ) ) ,
pre_install_cmds_linux : vec ! [
" mkdir -p {{CONF_PATH}}/monitoring " . to_string ( ) ,
" mkdir -p {{DATA_PATH}}/vector " . to_string ( ) ,
] ,
post_install_cmds_linux : vec ! [ ] ,
pre_install_cmds_macos : vec ! [
" mkdir -p {{CONF_PATH}}/monitoring " . to_string ( ) ,
" mkdir -p {{DATA_PATH}}/vector " . to_string ( ) ,
] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
2025-12-23 18:40:58 -03:00
2026-01-26 20:48:57 -03:00
exec_cmd : " {{BIN_PATH}}/vector --config {{CONF_PATH}}/monitoring/vector.toml "
. to_string ( ) ,
check_cmd :
" curl -f --connect-timeout 2 -m 5 http://localhost:8686/health >/dev/null 2>&1 "
. to_string ( ) ,
2025-11-30 16:25:51 -03:00
} ,
) ;
}
2025-11-22 22:55:35 -03:00
fn register_host ( & mut self ) {
self . components . insert (
" host " . to_string ( ) ,
ComponentConfig {
name : " host " . to_string ( ) ,
ports : vec ! [ ] ,
dependencies : vec ! [ ] ,
2026-01-26 11:44:18 -03:00
linux_packages : vec ! [ ] ,
2025-11-22 22:55:35 -03:00
macos_packages : vec ! [ ] ,
windows_packages : vec ! [ ] ,
download_url : None ,
binary_name : None ,
pre_install_cmds_linux : vec ! [
" echo 'net.ipv4.ip_forward=1' | tee -a /etc/sysctl.conf " . to_string ( ) ,
" sysctl -p " . to_string ( ) ,
] ,
post_install_cmds_linux : vec ! [
2026-01-26 11:44:18 -03:00
" lxd init --dump >/dev/null 2>&1 || lxd init --auto " . to_string ( ) ,
" lxc storage show default >/dev/null 2>&1 || lxc storage create default dir " . to_string ( ) ,
" lxc profile device include default root >/dev/null 2>&1 || lxc profile device add default root disk path=/ pool=default " . to_string ( ) ,
" lxc profile device show default | grep lxd-sock >/dev/null 2>&1 || lxc profile device add default lxd-sock proxy connect=unix:/var/lib/lxd/unix.socket listen=unix:/tmp/lxd.sock bind=container uid=0 gid=0 mode=0660 " . to_string ( ) ,
2025-11-22 22:55:35 -03:00
] ,
pre_install_cmds_macos : vec ! [ ] ,
post_install_cmds_macos : vec ! [ ] ,
pre_install_cmds_windows : vec ! [ ] ,
post_install_cmds_windows : vec ! [ ] ,
env_vars : HashMap ::new ( ) ,
data_download_list : Vec ::new ( ) ,
exec_cmd : " " . to_string ( ) ,
check_cmd : " " . to_string ( ) ,
} ,
) ;
}
pub fn start ( & self , component : & str ) -> Result < std ::process ::Child > {
if let Some ( component ) = self . components . get ( component ) {
let bin_path = self . base_path . join ( " bin " ) . join ( & component . name ) ;
let data_path = self . base_path . join ( " data " ) . join ( & component . name ) ;
2025-11-29 16:29:28 -03:00
let conf_path = self . base_path . join ( " conf " ) ;
2025-11-22 22:55:35 -03:00
let logs_path = self . base_path . join ( " logs " ) . join ( & component . name ) ;
let check_cmd = component
. check_cmd
. replace ( " {{BIN_PATH}} " , & bin_path . to_string_lossy ( ) )
. replace ( " {{DATA_PATH}} " , & data_path . to_string_lossy ( ) )
. replace ( " {{CONF_PATH}} " , & conf_path . to_string_lossy ( ) )
. replace ( " {{LOGS_PATH}} " , & logs_path . to_string_lossy ( ) ) ;
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
let check_output = safe_sh_command ( & check_cmd )
. map ( | o | o . status . success ( ) )
. unwrap_or ( false ) ;
2025-11-22 22:55:35 -03:00
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
if check_output {
2025-12-16 10:48:42 -03:00
info! (
" Component {} is already running, skipping start " ,
component . name
) ;
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
return SafeCommand ::noop_child ( )
. map_err ( | e | anyhow ::anyhow! ( " Failed to create noop process: {} " , e ) ) ;
2025-11-22 22:55:35 -03:00
}
let rendered_cmd = component
. exec_cmd
. replace ( " {{BIN_PATH}} " , & bin_path . to_string_lossy ( ) )
. replace ( " {{DATA_PATH}} " , & data_path . to_string_lossy ( ) )
. replace ( " {{CONF_PATH}} " , & conf_path . to_string_lossy ( ) )
. replace ( " {{LOGS_PATH}} " , & logs_path . to_string_lossy ( ) ) ;
2025-12-29 10:34:25 -03:00
trace! (
2025-11-22 22:55:35 -03:00
" Starting component {} with command: {} " ,
2026-01-26 17:00:21 -03:00
component . name ,
rendered_cmd
2025-12-10 08:30:49 -03:00
) ;
2025-12-29 10:34:25 -03:00
trace! (
2025-12-26 08:59:25 -03:00
" Working directory: {}, logs_path: {} " ,
bin_path . display ( ) ,
logs_path . display ( )
2025-11-22 22:55:35 -03:00
) ;
2025-12-08 23:35:33 -03:00
let vault_credentials = Self ::fetch_vault_credentials ( ) ;
2025-11-22 22:55:35 -03:00
let mut evaluated_envs = HashMap ::new ( ) ;
for ( k , v ) in & component . env_vars {
2025-12-26 08:59:25 -03:00
if let Some ( var_name ) = v . strip_prefix ( '$' ) {
2025-12-08 23:35:33 -03:00
let value = vault_credentials
. get ( var_name )
. cloned ( )
. or_else ( | | std ::env ::var ( var_name ) . ok ( ) )
. unwrap_or_default ( ) ;
evaluated_envs . insert ( k . clone ( ) , value ) ;
2025-11-22 22:55:35 -03:00
} else {
evaluated_envs . insert ( k . clone ( ) , v . clone ( ) ) ;
}
}
Add billion-scale database redesign with enums and sharding
Database Schema v7.0.0:
- Create new 'gb' schema with PostgreSQL ENUMs instead of VARCHAR for all domain values
- Add sharding infrastructure (shard_config, tenant_shard_map tables)
- Implement partitioned tables for sessions, messages, and analytics (monthly partitions)
- Add Snowflake-like ID generation for distributed systems
- Design for billion-user scale with proper indexing strategies
Rust Enums:
- Add comprehensive enum types in core/shared/enums.rs
- Implement ToSql/FromSql for Diesel ORM integration
- Include: ChannelType, MessageRole, MessageType, LlmProvider, ContextProvider
- Include: TaskStatus, TaskPriority, ExecutionMode, RiskLevel, ApprovalStatus, IntentType
- All enums stored as SMALLINT for efficiency
Other fixes:
- Fix hardcoded gpt-4 model in auto_task modules to use bot config
- Add vector_db to required bootstrap components
- Add Qdrant health check before KB indexing
- Change verbose START messages to trace level
- Fix episodic memory role handling in Claude client
- Disable auth for /api routes during development
This is a DESTRUCTIVE migration - only for fresh installations.
2025-12-29 11:27:13 -03:00
trace! (
" About to spawn shell command for {}: {} " ,
2026-01-26 17:00:21 -03:00
component . name ,
rendered_cmd
2025-12-15 17:50:03 -03:00
) ;
2026-02-22 15:55:39 -03:00
trace! ( " Working dir: {} " , bin_path . display ( ) ) ;
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
let child = SafeCommand ::new ( " sh " )
. and_then ( | c | c . arg ( " -c " ) )
2026-01-09 12:13:35 -03:00
. and_then ( | c | c . trusted_shell_script_arg ( & rendered_cmd ) )
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
. and_then ( | c | c . working_dir ( & bin_path ) )
. and_then ( | cmd | cmd . spawn_with_envs ( & evaluated_envs ) )
. map_err ( | e | anyhow ::anyhow! ( " Failed to spawn process: {} " , e ) ) ;
2025-11-22 22:55:35 -03:00
2026-01-26 17:00:21 -03:00
trace! ( " Spawn result for {}: {:?} " , component . name , child . is_ok ( ) ) ;
2025-11-22 22:55:35 -03:00
std ::thread ::sleep ( std ::time ::Duration ::from_secs ( 2 ) ) ;
Add billion-scale database redesign with enums and sharding
Database Schema v7.0.0:
- Create new 'gb' schema with PostgreSQL ENUMs instead of VARCHAR for all domain values
- Add sharding infrastructure (shard_config, tenant_shard_map tables)
- Implement partitioned tables for sessions, messages, and analytics (monthly partitions)
- Add Snowflake-like ID generation for distributed systems
- Design for billion-user scale with proper indexing strategies
Rust Enums:
- Add comprehensive enum types in core/shared/enums.rs
- Implement ToSql/FromSql for Diesel ORM integration
- Include: ChannelType, MessageRole, MessageType, LlmProvider, ContextProvider
- Include: TaskStatus, TaskPriority, ExecutionMode, RiskLevel, ApprovalStatus, IntentType
- All enums stored as SMALLINT for efficiency
Other fixes:
- Fix hardcoded gpt-4 model in auto_task modules to use bot config
- Add vector_db to required bootstrap components
- Add Qdrant health check before KB indexing
- Change verbose START messages to trace level
- Fix episodic memory role handling in Claude client
- Disable auth for /api routes during development
This is a DESTRUCTIVE migration - only for fresh installations.
2025-12-29 11:27:13 -03:00
trace! (
" Checking if {} process exists after 2s sleep... " ,
2025-12-15 17:50:03 -03:00
component . name
) ;
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
let check_proc = safe_pgrep ( & [ " -f " , & component . name ] ) ;
if let Some ( output ) = check_proc {
2025-12-10 08:30:49 -03:00
let pids = String ::from_utf8_lossy ( & output . stdout ) ;
2026-01-26 17:00:21 -03:00
trace! ( " pgrep '{}' result: '{}' " , component . name , pids . trim ( ) ) ;
2025-12-10 08:30:49 -03:00
}
2025-11-22 22:55:35 -03:00
match child {
2025-12-10 08:30:49 -03:00
Ok ( c ) = > {
Add billion-scale database redesign with enums and sharding
Database Schema v7.0.0:
- Create new 'gb' schema with PostgreSQL ENUMs instead of VARCHAR for all domain values
- Add sharding infrastructure (shard_config, tenant_shard_map tables)
- Implement partitioned tables for sessions, messages, and analytics (monthly partitions)
- Add Snowflake-like ID generation for distributed systems
- Design for billion-user scale with proper indexing strategies
Rust Enums:
- Add comprehensive enum types in core/shared/enums.rs
- Implement ToSql/FromSql for Diesel ORM integration
- Include: ChannelType, MessageRole, MessageType, LlmProvider, ContextProvider
- Include: TaskStatus, TaskPriority, ExecutionMode, RiskLevel, ApprovalStatus, IntentType
- All enums stored as SMALLINT for efficiency
Other fixes:
- Fix hardcoded gpt-4 model in auto_task modules to use bot config
- Add vector_db to required bootstrap components
- Add Qdrant health check before KB indexing
- Change verbose START messages to trace level
- Fix episodic memory role handling in Claude client
- Disable auth for /api routes during development
This is a DESTRUCTIVE migration - only for fresh installations.
2025-12-29 11:27:13 -03:00
trace! ( " Component {} started successfully " , component . name ) ;
2026-02-14 16:35:24 +00:00
// Initialize Vault after successful start (local mode only)
if component . name = = " vault " & & self . mode = = InstallMode ::Local {
if let Err ( e ) = self . initialize_vault_local ( ) {
warn! ( " Failed to initialize Vault: {} " , e ) ;
warn! ( " Vault started but may need manual initialization " ) ;
}
}
2025-12-10 08:30:49 -03:00
Ok ( c )
}
2025-11-22 22:55:35 -03:00
Err ( e ) = > {
Add billion-scale database redesign with enums and sharding
Database Schema v7.0.0:
- Create new 'gb' schema with PostgreSQL ENUMs instead of VARCHAR for all domain values
- Add sharding infrastructure (shard_config, tenant_shard_map tables)
- Implement partitioned tables for sessions, messages, and analytics (monthly partitions)
- Add Snowflake-like ID generation for distributed systems
- Design for billion-user scale with proper indexing strategies
Rust Enums:
- Add comprehensive enum types in core/shared/enums.rs
- Implement ToSql/FromSql for Diesel ORM integration
- Include: ChannelType, MessageRole, MessageType, LlmProvider, ContextProvider
- Include: TaskStatus, TaskPriority, ExecutionMode, RiskLevel, ApprovalStatus, IntentType
- All enums stored as SMALLINT for efficiency
Other fixes:
- Fix hardcoded gpt-4 model in auto_task modules to use bot config
- Add vector_db to required bootstrap components
- Add Qdrant health check before KB indexing
- Change verbose START messages to trace level
- Fix episodic memory role handling in Claude client
- Disable auth for /api routes during development
This is a DESTRUCTIVE migration - only for fresh installations.
2025-12-29 11:27:13 -03:00
error! ( " Spawn failed for {}: {} " , component . name , e ) ;
2025-11-22 22:55:35 -03:00
let err_msg = e . to_string ( ) ;
if err_msg . contains ( " already running " )
| | err_msg . contains ( " be running " )
| | component . name = = " tables "
{
trace! (
" Component {} may already be running, continuing anyway " ,
component . name
) ;
2026-02-14 16:35:24 +00:00
// Even if vault was already running, ensure .env exists
if component . name = = " vault " & & self . mode = = InstallMode ::Local {
let _ = self . ensure_env_file_exists ( ) ;
}
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
SafeCommand ::noop_child ( )
2026-01-24 22:04:47 -03:00
. map_err ( | e | anyhow ::anyhow! ( " Failed to create noop process: {} " , e ) )
2025-11-22 22:55:35 -03:00
} else {
2026-01-24 22:04:47 -03:00
Err ( e )
2025-11-22 22:55:35 -03:00
}
}
}
} else {
2025-12-08 23:35:33 -03:00
Err ( anyhow ::anyhow! ( " Component not found: {} " , component ) )
2025-11-22 22:55:35 -03:00
}
}
2025-12-08 23:35:33 -03:00
fn fetch_vault_credentials ( ) -> HashMap < String , String > {
let mut credentials = HashMap ::new ( ) ;
2025-12-29 08:07:42 -03:00
dotenvy ::dotenv ( ) . ok ( ) ;
2026-01-09 10:48:13 -03:00
let base_path = std ::env ::var ( " BOTSERVER_STACK_PATH " )
. map ( std ::path ::PathBuf ::from )
. unwrap_or_else ( | _ | {
std ::env ::current_dir ( )
. unwrap_or_else ( | _ | std ::path ::PathBuf ::from ( " . " ) )
. join ( " botserver-stack " )
} ) ;
2025-12-08 23:35:33 -03:00
let vault_addr =
2026-01-09 10:48:13 -03:00
std ::env ::var ( " VAULT_ADDR " ) . unwrap_or_else ( | _ | " https://localhost:8200 " . to_string ( ) ) ;
2025-12-08 23:35:33 -03:00
let vault_token = std ::env ::var ( " VAULT_TOKEN " ) . unwrap_or_default ( ) ;
if vault_token . is_empty ( ) {
2025-12-29 08:07:42 -03:00
warn! ( " VAULT_TOKEN not set, cannot fetch credentials from Vault " ) ;
2025-12-08 23:35:33 -03:00
return credentials ;
}
2025-12-29 18:21:03 -03:00
// Check if Vault is reachable before trying to fetch credentials
2026-01-09 10:48:13 -03:00
// Use -k for self-signed certs and mTLS client cert
let client_cert = base_path . join ( " conf/system/certificates/botserver/client.crt " ) ;
let client_key = base_path . join ( " conf/system/certificates/botserver/client.key " ) ;
let vault_check = safe_sh_command ( & format! (
" curl -sfk --cert {} --key {} {}/v1/sys/health >/dev/null 2>&1 " ,
client_cert . display ( ) ,
client_key . display ( ) ,
vault_addr
) )
2026-01-26 17:00:21 -03:00
. map ( | o | o . status . success ( ) )
. unwrap_or ( false ) ;
2025-12-29 18:21:03 -03:00
if ! vault_check {
2026-01-26 17:00:21 -03:00
trace! (
" Vault not reachable at {}, skipping credential fetch " ,
vault_addr
) ;
2025-12-29 18:21:03 -03:00
return credentials ;
}
2025-12-29 08:07:42 -03:00
let vault_bin = base_path . join ( " bin/vault/vault " ) ;
let vault_bin_str = vault_bin . to_string_lossy ( ) ;
Fix tasks UI, WebSocket progress, memory monitoring, and app generator
Tasks UI fixes:
- Fix task list to query auto_tasks table instead of tasks table
- Fix task detail endpoint to use UUID binding for auto_tasks query
- Add proper filter handling: complete, active, awaiting, paused, blocked
- Add TaskStats fields: awaiting, paused, blocked, time_saved
- Add /api/tasks/time-saved endpoint
- Add count-all to stats HTML response
App generator improvements:
- Add AgentActivity struct for detailed terminal-style progress
- Add emit_activity method for rich progress events
- Add detailed logging for LLM calls with timing
- Track files_written, tables_synced, bytes_generated
Memory and performance:
- Add memory_monitor module for tracking RSS and thread activity
- Skip 0-byte files in drive monitor and document processor
- Change DRIVE_MONITOR checking logs from info to trace
- Remove unused profile_section macro
WebSocket progress:
- Ensure TaskProgressEvent includes activity field
- Add with_activity builder method
2025-12-30 22:42:32 -03:00
// Get CA cert path for Vault TLS
2026-01-26 17:00:21 -03:00
let ca_cert_path = std ::env ::var ( " VAULT_CACERT " ) . unwrap_or_else ( | _ | {
base_path
. join ( " conf/system/certificates/ca/ca.crt " )
. to_string_lossy ( )
. to_string ( )
} ) ;
trace! (
" Fetching drive credentials from Vault at {} using {} " ,
vault_addr ,
vault_bin_str
) ;
2025-12-29 08:07:42 -03:00
let drive_cmd = format! (
Fix tasks UI, WebSocket progress, memory monitoring, and app generator
Tasks UI fixes:
- Fix task list to query auto_tasks table instead of tasks table
- Fix task detail endpoint to use UUID binding for auto_tasks query
- Add proper filter handling: complete, active, awaiting, paused, blocked
- Add TaskStats fields: awaiting, paused, blocked, time_saved
- Add /api/tasks/time-saved endpoint
- Add count-all to stats HTML response
App generator improvements:
- Add AgentActivity struct for detailed terminal-style progress
- Add emit_activity method for rich progress events
- Add detailed logging for LLM calls with timing
- Track files_written, tables_synced, bytes_generated
Memory and performance:
- Add memory_monitor module for tracking RSS and thread activity
- Skip 0-byte files in drive monitor and document processor
- Change DRIVE_MONITOR checking logs from info to trace
- Remove unused profile_section macro
WebSocket progress:
- Ensure TaskProgressEvent includes activity field
- Add with_activity builder method
2025-12-30 22:42:32 -03:00
" VAULT_ADDR={} VAULT_TOKEN={} VAULT_CACERT={} {} kv get -format=json secret/gbo/drive " ,
vault_addr , vault_token , ca_cert_path , vault_bin_str
2025-12-29 08:07:42 -03:00
) ;
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
match safe_sh_command ( & drive_cmd ) {
Some ( output ) = > {
2025-12-29 08:07:42 -03:00
if output . status . success ( ) {
let json_str = String ::from_utf8_lossy ( & output . stdout ) ;
2025-12-29 10:34:25 -03:00
trace! ( " Vault drive response: {} " , json_str ) ;
2025-12-29 08:07:42 -03:00
match serde_json ::from_str ::< serde_json ::Value > ( & json_str ) {
Ok ( json ) = > {
if let Some ( data ) = json . get ( " data " ) . and_then ( | d | d . get ( " data " ) ) {
2026-01-26 17:00:21 -03:00
if let Some ( accesskey ) =
data . get ( " accesskey " ) . and_then ( | v | v . as_str ( ) )
{
2025-12-29 10:34:25 -03:00
trace! ( " Found DRIVE_ACCESSKEY from Vault " ) ;
2026-01-26 17:00:21 -03:00
credentials . insert (
" DRIVE_ACCESSKEY " . to_string ( ) ,
accesskey . to_string ( ) ,
) ;
2025-12-29 08:07:42 -03:00
}
if let Some ( secret ) = data . get ( " secret " ) . and_then ( | v | v . as_str ( ) ) {
2025-12-29 10:34:25 -03:00
trace! ( " Found DRIVE_SECRET from Vault " ) ;
2026-01-26 17:00:21 -03:00
credentials
. insert ( " DRIVE_SECRET " . to_string ( ) , secret . to_string ( ) ) ;
2025-12-29 08:07:42 -03:00
}
} else {
warn! ( " Vault response missing data.data field " ) ;
2025-12-08 23:35:33 -03:00
}
}
2025-12-29 08:07:42 -03:00
Err ( e ) = > warn! ( " Failed to parse Vault JSON: {} " , e ) ,
2025-12-08 23:35:33 -03:00
}
2025-12-29 08:07:42 -03:00
} else {
let stderr = String ::from_utf8_lossy ( & output . stderr ) ;
warn! ( " Vault drive command failed: {} " , stderr ) ;
2025-12-08 23:35:33 -03:00
}
}
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
None = > warn! ( " Failed to execute Vault command " ) ,
2025-12-08 23:35:33 -03:00
}
Add video module, RBAC, security features, billing, contacts, dashboards, learn, social, and multiple new modules
Major additions:
- Video editing engine with AI features (transcription, captions, TTS, scene detection)
- RBAC middleware and organization management
- Security enhancements (MFA, passkey, DLP, encryption, audit)
- Billing and subscription management
- Contacts management
- Dashboards module
- Learn/LMS module
- Social features
- Compliance (SOC2, SOP middleware, vulnerability scanner)
- New migrations for RBAC, learn, and video tables
2026-01-08 13:16:17 -03:00
let cache_cmd = format! (
" VAULT_ADDR={} VAULT_TOKEN={} VAULT_CACERT={} {} kv get -format=json secret/gbo/cache 2>/dev/null " ,
vault_addr , vault_token , ca_cert_path , vault_bin_str
) ;
if let Some ( output ) = safe_sh_command ( & cache_cmd ) {
2025-12-08 23:35:33 -03:00
if output . status . success ( ) {
if let Ok ( json_str ) = String ::from_utf8 ( output . stdout ) {
if let Ok ( json ) = serde_json ::from_str ::< serde_json ::Value > ( & json_str ) {
if let Some ( data ) = json . get ( " data " ) . and_then ( | d | d . get ( " data " ) ) {
if let Some ( password ) = data . get ( " password " ) . and_then ( | v | v . as_str ( ) ) {
2026-01-26 17:00:21 -03:00
credentials
. insert ( " CACHE_PASSWORD " . to_string ( ) , password . to_string ( ) ) ;
2025-12-08 23:35:33 -03:00
}
}
}
}
}
}
trace! ( " Fetched {} credentials from Vault " , credentials . len ( ) ) ;
credentials
}
2026-02-14 16:35:24 +00:00
/// Initialize Vault locally (non-LXC mode) and create .env file
///
/// This function:
/// 1. Checks if Vault is already initialized
/// 2. If not, runs `vault operator init` to get root token and unseal keys
/// 3. Creates .env file with VAULT_ADDR and VAULT_TOKEN
/// 4. Creates vault-unseal-keys file with proper permissions
/// 5. Unseals Vault with 3 keys
fn initialize_vault_local ( & self ) -> Result < ( ) > {
use std ::io ::Write ;
info! ( " Initializing Vault locally (non-LXC mode)... " ) ;
let bin_path = self . base_path . join ( " bin/vault " ) ;
let conf_path = self . base_path . join ( " conf " ) ;
let vault_bin = bin_path . join ( " vault " ) ;
// Check if already initialized
let init_json = self . base_path . join ( " conf/vault/init.json " ) ;
if init_json . exists ( ) {
info! ( " Vault already initialized (init.json exists), skipping initialization " ) ;
// Still ensure .env file exists
self . ensure_env_file_exists ( ) ? ;
return Ok ( ( ) ) ;
}
// Wait for Vault to be ready
info! ( " Waiting for Vault to start... " ) ;
std ::thread ::sleep ( std ::time ::Duration ::from_secs ( 3 ) ) ;
let vault_addr = std ::env ::var ( " VAULT_ADDR " )
. unwrap_or_else ( | _ | " https://localhost:8200 " . to_string ( ) ) ;
let ca_cert = conf_path . join ( " system/certificates/ca/ca.crt " ) ;
// Initialize Vault
let init_cmd = format! (
" {} operator init -tls-skip-verify -key-shares=5 -key-threshold=3 -format=json -address={} " ,
vault_bin . display ( ) ,
vault_addr
) ;
info! ( " Running vault operator init... " ) ;
let output = safe_sh_command ( & init_cmd )
. ok_or_else ( | | anyhow ::anyhow! ( " Failed to execute vault init command " ) ) ? ;
if ! output . status . success ( ) {
let stderr = String ::from_utf8_lossy ( & output . stderr ) ;
if stderr . contains ( " already initialized " ) {
warn! ( " Vault already initialized, skipping file generation " ) ;
return self . ensure_env_file_exists ( ) ;
}
return Err ( anyhow ::anyhow! ( " Failed to initialize Vault: {} " , stderr ) ) ;
}
let init_output = String ::from_utf8_lossy ( & output . stdout ) ;
let init_json_val : serde_json ::Value = serde_json ::from_str ( & init_output )
. context ( " Failed to parse Vault init output " ) ? ;
let unseal_keys = init_json_val [ " unseal_keys_b64 " ]
. as_array ( )
. context ( " No unseal keys in output " ) ? ;
let root_token = init_json_val [ " root_token " ]
. as_str ( )
. context ( " No root token in output " ) ? ;
// Save init.json
std ::fs ::write (
& init_json ,
serde_json ::to_string_pretty ( & init_json_val ) ?
) ? ;
info! ( " Created {} " , init_json . display ( ) ) ;
// Create .env file with Vault credentials
let env_file = std ::path ::PathBuf ::from ( " .env " ) ;
let env_content = format! (
r #"
# Vault Configuration ( auto - generated )
VAULT_ADDR = { }
VAULT_TOKEN = { }
VAULT_CACERT = { }
" #,
vault_addr ,
root_token ,
ca_cert . display ( )
) ;
if env_file . exists ( ) {
let existing = std ::fs ::read_to_string ( & env_file ) ? ;
if existing . contains ( " VAULT_ADDR= " ) {
warn! ( " .env already contains VAULT_ADDR, not overwriting " ) ;
} else {
let mut file = std ::fs ::OpenOptions ::new ( )
. append ( true )
. open ( & env_file ) ? ;
file . write_all ( env_content . as_bytes ( ) ) ? ;
info! ( " Appended Vault config to .env " ) ;
}
} else {
std ::fs ::write ( & env_file , env_content . trim_start ( ) ) ? ;
info! ( " Created .env with Vault config " ) ;
}
// Create vault-unseal-keys file
let unseal_keys_file = std ::path ::PathBuf ::from ( " vault-unseal-keys " ) ;
let keys_content : String = unseal_keys
. iter ( )
. enumerate ( )
. map ( | ( i , key ) : ( usize , & serde_json ::Value ) | {
format! ( " Unseal Key {} : {} \n " , i + 1 , key . as_str ( ) . unwrap_or ( " " ) )
} )
. collect ( ) ;
std ::fs ::write ( & unseal_keys_file , keys_content ) ? ;
#[ cfg(unix) ]
{
std ::fs ::set_permissions ( & unseal_keys_file , std ::fs ::Permissions ::from_mode ( 0o600 ) ) ? ;
}
#[ cfg(not(unix)) ]
{
let _ = & unseal_keys_file ; // suppress unused warning
}
info! ( " Created {} (chmod 600) " , unseal_keys_file . display ( ) ) ;
// Unseal Vault (need 3 keys)
info! ( " Unsealing Vault... " ) ;
for i in 0 .. 3 {
if let Some ( key ) = unseal_keys . get ( i ) {
let key_str : & str = key . as_str ( ) . unwrap_or ( " " ) ;
let unseal_cmd = format! (
" {} operator unseal -tls-skip-verify -address={} {} " ,
vault_bin . display ( ) ,
vault_addr ,
key_str
) ;
let unseal_output = safe_sh_command ( & unseal_cmd ) ;
if let Some ( output ) = unseal_output {
if ! output . status . success ( ) {
warn! ( " Unseal step {} may have failed " , i + 1 ) ;
}
} else {
warn! ( " Unseal step {} command failed to execute " , i + 1 ) ;
}
}
}
info! ( " Vault initialized and unsealed successfully " ) ;
info! ( " ✓ Created .env with VAULT_ADDR, VAULT_TOKEN " ) ;
info! ( " ✓ Created vault-unseal-keys (chmod 600) " ) ;
Ok ( ( ) )
}
/// Ensure .env file exists with Vault credentials
fn ensure_env_file_exists ( & self ) -> Result < ( ) > {
let init_json = self . base_path . join ( " conf/vault/init.json " ) ;
let env_file = std ::path ::PathBuf ::from ( " .env " ) ;
if ! init_json . exists ( ) {
return Ok ( ( ) ) ; // No init, no .env needed yet
}
let init_content = std ::fs ::read_to_string ( & init_json ) ? ;
let init_json_val : serde_json ::Value = serde_json ::from_str ( & init_content ) ? ;
let root_token = init_json_val [ " root_token " ]
. as_str ( )
. context ( " No root_token in init.json " ) ? ;
let conf_path = self . base_path . join ( " conf " ) ;
let ca_cert = conf_path . join ( " system/certificates/ca/ca.crt " ) ;
let vault_addr = std ::env ::var ( " VAULT_ADDR " )
. unwrap_or_else ( | _ | " https://localhost:8200 " . to_string ( ) ) ;
let env_content = format! (
r #"
# Vault Configuration ( auto - generated )
VAULT_ADDR = { }
VAULT_TOKEN = { }
VAULT_CACERT = { }
" #,
vault_addr ,
root_token ,
ca_cert . display ( )
) ;
if env_file . exists ( ) {
let existing = std ::fs ::read_to_string ( & env_file ) ? ;
if existing . contains ( " VAULT_ADDR= " ) {
return Ok ( ( ) ) ;
}
let mut file = std ::fs ::OpenOptions ::new ( )
. append ( true )
. open ( & env_file ) ? ;
use std ::io ::Write ;
file . write_all ( env_content . as_bytes ( ) ) ? ;
} else {
std ::fs ::write ( & env_file , env_content . trim_start ( ) ) ? ;
}
info! ( " Created .env with Vault credentials " ) ;
Ok ( ( ) )
}
2025-11-22 22:55:35 -03:00
}