2025-11-21 09:28:35 -03:00
|
|
|
use crate::shared::models::UserSession;
|
|
|
|
|
use crate::shared::state::AppState;
|
|
|
|
|
use diesel::prelude::*;
|
|
|
|
|
use log::{error, info, warn};
|
2025-11-21 23:23:53 -03:00
|
|
|
use rhai::{Dynamic, Engine, EvalAltResult};
|
2025-11-21 09:28:35 -03:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
use uuid::Uuid;
|
|
|
|
|
|
2025-11-21 23:23:53 -03:00
|
|
|
#[derive(QueryableByName)]
|
|
|
|
|
struct BotNameResult {
|
|
|
|
|
#[diesel(sql_type = diesel::sql_types::Text)]
|
|
|
|
|
name: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(QueryableByName)]
|
|
|
|
|
struct KbCollectionResult {
|
|
|
|
|
#[diesel(sql_type = diesel::sql_types::Text)]
|
|
|
|
|
folder_path: String,
|
|
|
|
|
#[diesel(sql_type = diesel::sql_types::Text)]
|
|
|
|
|
qdrant_collection: String,
|
|
|
|
|
}
|
|
|
|
|
|
2025-11-22 12:26:16 -03:00
|
|
|
#[derive(QueryableByName, Debug, Clone)]
|
|
|
|
|
pub struct ActiveKbResult {
|
2025-11-21 23:23:53 -03:00
|
|
|
#[diesel(sql_type = diesel::sql_types::Text)]
|
2025-11-22 12:26:16 -03:00
|
|
|
pub kb_name: String,
|
2025-11-21 23:23:53 -03:00
|
|
|
#[diesel(sql_type = diesel::sql_types::Text)]
|
2025-11-22 12:26:16 -03:00
|
|
|
pub kb_folder_path: String,
|
2025-11-21 23:23:53 -03:00
|
|
|
#[diesel(sql_type = diesel::sql_types::Text)]
|
2025-11-22 12:26:16 -03:00
|
|
|
pub qdrant_collection: String,
|
2025-11-21 23:23:53 -03:00
|
|
|
}
|
|
|
|
|
|
Looking at this diff, I can see it's a comprehensive documentation
update and code refactoring focused on:
1. Adding new documentation pages to the table of contents
2. Restructuring the bot templates documentation
3. Changing keyword syntax from underscore format to space format (e.g.,
`SET_BOT_MEMORY` → `SET BOT MEMORY`)
4. Updating compiler and keyword registration to support the new
space-based syntax
5. Adding new keyword modules (social media, lead scoring, templates,
etc.)
Refactor BASIC keywords to use spaces instead of underscores
Change keyword syntax from underscore format (SET_BOT_MEMORY) to more
natural space-separated format (SET BOT MEMORY) throughout the codebase.
Key changes:
- Update Rhai custom syntax registration to use space tokens
- Simplify compiler preprocessing (fewer replacements needed)
- Update all template .bas files to use new syntax
- Expand documentation with consolidated examples and new sections
- Add new keyword modules: social_media, lead_scoring, send_template,
core_functions, qrcode, sms, procedures, import_export, llm_macros,
on_form_submit
2025-11-30 10:53:59 -03:00
|
|
|
/// Register USE KB keyword
|
2025-11-21 09:28:35 -03:00
|
|
|
/// Adds a Knowledge Base to the current session's context
|
Looking at this diff, I can see it's a comprehensive documentation
update and code refactoring focused on:
1. Adding new documentation pages to the table of contents
2. Restructuring the bot templates documentation
3. Changing keyword syntax from underscore format to space format (e.g.,
`SET_BOT_MEMORY` → `SET BOT MEMORY`)
4. Updating compiler and keyword registration to support the new
space-based syntax
5. Adding new keyword modules (social media, lead scoring, templates,
etc.)
Refactor BASIC keywords to use spaces instead of underscores
Change keyword syntax from underscore format (SET_BOT_MEMORY) to more
natural space-separated format (SET BOT MEMORY) throughout the codebase.
Key changes:
- Update Rhai custom syntax registration to use space tokens
- Simplify compiler preprocessing (fewer replacements needed)
- Update all template .bas files to use new syntax
- Expand documentation with consolidated examples and new sections
- Add new keyword modules: social_media, lead_scoring, send_template,
core_functions, qrcode, sms, procedures, import_export, llm_macros,
on_form_submit
2025-11-30 10:53:59 -03:00
|
|
|
/// Usage: USE KB "kbname"
|
|
|
|
|
/// Example: USE KB "circular" or USE KB kbname (where kbname is a variable)
|
2025-11-21 23:23:53 -03:00
|
|
|
pub fn register_use_kb_keyword(
|
2025-11-21 09:28:35 -03:00
|
|
|
engine: &mut Engine,
|
|
|
|
|
state: Arc<AppState>,
|
|
|
|
|
session: Arc<UserSession>,
|
|
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
|
|
|
|
let state_clone = Arc::clone(&state);
|
|
|
|
|
let session_clone = Arc::clone(&session);
|
|
|
|
|
|
Looking at this diff, I can see it's a comprehensive documentation
update and code refactoring focused on:
1. Adding new documentation pages to the table of contents
2. Restructuring the bot templates documentation
3. Changing keyword syntax from underscore format to space format (e.g.,
`SET_BOT_MEMORY` → `SET BOT MEMORY`)
4. Updating compiler and keyword registration to support the new
space-based syntax
5. Adding new keyword modules (social media, lead scoring, templates,
etc.)
Refactor BASIC keywords to use spaces instead of underscores
Change keyword syntax from underscore format (SET_BOT_MEMORY) to more
natural space-separated format (SET BOT MEMORY) throughout the codebase.
Key changes:
- Update Rhai custom syntax registration to use space tokens
- Simplify compiler preprocessing (fewer replacements needed)
- Update all template .bas files to use new syntax
- Expand documentation with consolidated examples and new sections
- Add new keyword modules: social_media, lead_scoring, send_template,
core_functions, qrcode, sms, procedures, import_export, llm_macros,
on_form_submit
2025-11-30 10:53:59 -03:00
|
|
|
// Register with spaces: USE KB "kbname"
|
|
|
|
|
engine.register_custom_syntax(&["USE", "KB", "$expr$"], true, move |context, inputs| {
|
2025-11-21 09:28:35 -03:00
|
|
|
let kb_name = context.eval_expression_tree(&inputs[0])?.to_string();
|
|
|
|
|
|
|
|
|
|
info!(
|
Looking at this diff, I can see it's a comprehensive documentation
update and code refactoring focused on:
1. Adding new documentation pages to the table of contents
2. Restructuring the bot templates documentation
3. Changing keyword syntax from underscore format to space format (e.g.,
`SET_BOT_MEMORY` → `SET BOT MEMORY`)
4. Updating compiler and keyword registration to support the new
space-based syntax
5. Adding new keyword modules (social media, lead scoring, templates,
etc.)
Refactor BASIC keywords to use spaces instead of underscores
Change keyword syntax from underscore format (SET_BOT_MEMORY) to more
natural space-separated format (SET BOT MEMORY) throughout the codebase.
Key changes:
- Update Rhai custom syntax registration to use space tokens
- Simplify compiler preprocessing (fewer replacements needed)
- Update all template .bas files to use new syntax
- Expand documentation with consolidated examples and new sections
- Add new keyword modules: social_media, lead_scoring, send_template,
core_functions, qrcode, sms, procedures, import_export, llm_macros,
on_form_submit
2025-11-30 10:53:59 -03:00
|
|
|
"USE KB keyword executed - KB: {}, Session: {}",
|
2025-11-21 09:28:35 -03:00
|
|
|
kb_name, session_clone.id
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let session_id = session_clone.id;
|
|
|
|
|
let bot_id = session_clone.bot_id;
|
|
|
|
|
let conn = state_clone.conn.clone();
|
2025-11-21 23:23:53 -03:00
|
|
|
let kb_name_clone = kb_name.clone();
|
2025-11-21 09:28:35 -03:00
|
|
|
|
|
|
|
|
// Execute in blocking context since we're working with database
|
|
|
|
|
let result =
|
2025-11-21 23:23:53 -03:00
|
|
|
std::thread::spawn(move || add_kb_to_session(conn, session_id, bot_id, &kb_name_clone))
|
2025-11-21 09:28:35 -03:00
|
|
|
.join();
|
|
|
|
|
|
|
|
|
|
match result {
|
|
|
|
|
Ok(Ok(_)) => {
|
|
|
|
|
info!("✅ KB '{}' added to session {}", kb_name, session_clone.id);
|
|
|
|
|
Ok(Dynamic::UNIT)
|
|
|
|
|
}
|
|
|
|
|
Ok(Err(e)) => {
|
|
|
|
|
error!("Failed to add KB '{}': {}", kb_name, e);
|
2025-11-21 23:23:53 -03:00
|
|
|
Err(format!("USE_KB failed: {}", e).into())
|
2025-11-21 09:28:35 -03:00
|
|
|
}
|
|
|
|
|
Err(e) => {
|
2025-11-21 23:23:53 -03:00
|
|
|
error!("Thread panic in USE_KB: {:?}", e);
|
|
|
|
|
Err("USE_KB failed: thread panic".into())
|
2025-11-21 09:28:35 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Add KB to session in database
|
|
|
|
|
fn add_kb_to_session(
|
|
|
|
|
conn_pool: crate::shared::utils::DbPool,
|
|
|
|
|
session_id: Uuid,
|
|
|
|
|
bot_id: Uuid,
|
|
|
|
|
kb_name: &str,
|
|
|
|
|
) -> Result<(), String> {
|
|
|
|
|
let mut conn = conn_pool
|
|
|
|
|
.get()
|
|
|
|
|
.map_err(|e| format!("Failed to get DB connection: {}", e))?;
|
|
|
|
|
|
|
|
|
|
// Get bot name to construct KB path
|
2025-11-21 23:23:53 -03:00
|
|
|
let bot_result: BotNameResult = diesel::sql_query("SELECT name FROM bots WHERE id = $1")
|
2025-11-21 09:28:35 -03:00
|
|
|
.bind::<diesel::sql_types::Uuid, _>(bot_id)
|
2025-11-21 23:23:53 -03:00
|
|
|
.get_result(&mut conn)
|
|
|
|
|
.map_err(|e| format!("Failed to get bot name: {}", e))?;
|
|
|
|
|
let bot_name = bot_result.name;
|
2025-11-21 09:28:35 -03:00
|
|
|
|
|
|
|
|
// Check if KB collection exists
|
2025-11-21 23:23:53 -03:00
|
|
|
let kb_exists: Option<KbCollectionResult> = diesel::sql_query(
|
2025-11-21 09:28:35 -03:00
|
|
|
"SELECT folder_path, qdrant_collection FROM kb_collections WHERE bot_id = $1 AND name = $2",
|
|
|
|
|
)
|
|
|
|
|
.bind::<diesel::sql_types::Uuid, _>(bot_id)
|
|
|
|
|
.bind::<diesel::sql_types::Text, _>(kb_name)
|
2025-11-21 23:23:53 -03:00
|
|
|
.get_result(&mut conn)
|
2025-11-21 09:28:35 -03:00
|
|
|
.optional()
|
|
|
|
|
.map_err(|e| format!("Failed to check KB existence: {}", e))?;
|
|
|
|
|
|
2025-11-21 23:23:53 -03:00
|
|
|
let (kb_folder_path, qdrant_collection) = if let Some(kb_result) = kb_exists {
|
|
|
|
|
(kb_result.folder_path, kb_result.qdrant_collection)
|
2025-11-21 09:28:35 -03:00
|
|
|
} else {
|
|
|
|
|
// KB doesn't exist in database, construct default path
|
|
|
|
|
let default_path = format!("work/{}/{}.gbkb/{}", bot_name, bot_name, kb_name);
|
|
|
|
|
let default_collection = format!("{}_{}", bot_name, kb_name);
|
|
|
|
|
|
|
|
|
|
warn!(
|
|
|
|
|
"KB '{}' not found in kb_collections for bot {}. Using default path: {}",
|
|
|
|
|
kb_name, bot_name, default_path
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Optionally create KB collection entry
|
|
|
|
|
let kb_id = Uuid::new_v4();
|
|
|
|
|
diesel::sql_query(
|
|
|
|
|
"INSERT INTO kb_collections (id, bot_id, name, folder_path, qdrant_collection, document_count)
|
|
|
|
|
VALUES ($1, $2, $3, $4, $5, 0)
|
|
|
|
|
ON CONFLICT (bot_id, name) DO NOTHING"
|
|
|
|
|
)
|
|
|
|
|
.bind::<diesel::sql_types::Uuid, _>(kb_id)
|
|
|
|
|
.bind::<diesel::sql_types::Uuid, _>(bot_id)
|
|
|
|
|
.bind::<diesel::sql_types::Text, _>(kb_name)
|
|
|
|
|
.bind::<diesel::sql_types::Text, _>(&default_path)
|
|
|
|
|
.bind::<diesel::sql_types::Text, _>(&default_collection)
|
|
|
|
|
.execute(&mut conn)
|
|
|
|
|
.ok(); // Ignore errors if it already exists
|
|
|
|
|
|
|
|
|
|
(default_path, default_collection)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Get the tool name from call stack if available
|
Add .env.example with comprehensive configuration template
The commit adds a complete example environment configuration file
documenting all available settings for BotServer, including logging,
database, server, drive, LLM, Redis, email, and feature flags.
Also removes hardcoded environment variable usage throughout the
codebase, replacing them with configuration via config.csv or
appropriate defaults. This includes:
- WhatsApp, Teams, Instagram adapter configurations
- Weather API key handling
- Email and directory service configurations
- Console feature conditionally compiles monitoring code
- Improved logging configuration with library suppression
2025-11-28 13:19:03 -03:00
|
|
|
let tool_name: Option<String> = None;
|
2025-11-21 09:28:35 -03:00
|
|
|
|
|
|
|
|
// Add or update KB association for this session
|
|
|
|
|
let assoc_id = Uuid::new_v4();
|
|
|
|
|
diesel::sql_query(
|
|
|
|
|
"INSERT INTO session_kb_associations (id, session_id, bot_id, kb_name, kb_folder_path, qdrant_collection, added_by_tool, is_active)
|
|
|
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, true)
|
|
|
|
|
ON CONFLICT (session_id, kb_name)
|
|
|
|
|
DO UPDATE SET
|
|
|
|
|
is_active = true,
|
|
|
|
|
added_at = NOW(),
|
|
|
|
|
added_by_tool = EXCLUDED.added_by_tool"
|
|
|
|
|
)
|
|
|
|
|
.bind::<diesel::sql_types::Uuid, _>(assoc_id)
|
|
|
|
|
.bind::<diesel::sql_types::Uuid, _>(session_id)
|
|
|
|
|
.bind::<diesel::sql_types::Uuid, _>(bot_id)
|
|
|
|
|
.bind::<diesel::sql_types::Text, _>(kb_name)
|
|
|
|
|
.bind::<diesel::sql_types::Text, _>(&kb_folder_path)
|
|
|
|
|
.bind::<diesel::sql_types::Text, _>(&qdrant_collection)
|
|
|
|
|
.bind::<diesel::sql_types::Nullable<diesel::sql_types::Text>, _>(tool_name.as_deref())
|
|
|
|
|
.execute(&mut conn)
|
|
|
|
|
.map_err(|e| format!("Failed to add KB association: {}", e))?;
|
|
|
|
|
|
|
|
|
|
info!(
|
|
|
|
|
"✅ Added KB '{}' to session {} (collection: {}, path: {})",
|
|
|
|
|
kb_name, session_id, qdrant_collection, kb_folder_path
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get all active KBs for a session
|
|
|
|
|
pub fn get_active_kbs_for_session(
|
|
|
|
|
conn_pool: &crate::shared::utils::DbPool,
|
|
|
|
|
session_id: Uuid,
|
|
|
|
|
) -> Result<Vec<(String, String, String)>, String> {
|
|
|
|
|
let mut conn = conn_pool
|
|
|
|
|
.get()
|
|
|
|
|
.map_err(|e| format!("Failed to get DB connection: {}", e))?;
|
|
|
|
|
|
2025-11-21 23:23:53 -03:00
|
|
|
let results: Vec<ActiveKbResult> = diesel::sql_query(
|
2025-11-21 09:28:35 -03:00
|
|
|
"SELECT kb_name, kb_folder_path, qdrant_collection
|
|
|
|
|
FROM session_kb_associations
|
|
|
|
|
WHERE session_id = $1 AND is_active = true
|
|
|
|
|
ORDER BY added_at DESC",
|
|
|
|
|
)
|
|
|
|
|
.bind::<diesel::sql_types::Uuid, _>(session_id)
|
|
|
|
|
.load(&mut conn)
|
|
|
|
|
.map_err(|e| format!("Failed to get active KBs: {}", e))?;
|
|
|
|
|
|
2025-11-21 23:23:53 -03:00
|
|
|
Ok(results
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(|r| (r.kb_name, r.kb_folder_path, r.qdrant_collection))
|
|
|
|
|
.collect())
|
2025-11-21 09:28:35 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests {
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-11-21 23:23:53 -03:00
|
|
|
fn test_use_kb_syntax() {
|
2025-11-21 09:28:35 -03:00
|
|
|
let mut engine = Engine::new();
|
|
|
|
|
// This would normally use real state and session
|
|
|
|
|
// For now just test that the syntax can be registered
|
|
|
|
|
assert!(engine
|
2025-11-21 23:23:53 -03:00
|
|
|
.register_custom_syntax(&["USE_KB", "$expr$"], true, |_, _| Ok(Dynamic::UNIT))
|
2025-11-21 09:28:35 -03:00
|
|
|
.is_ok());
|
|
|
|
|
}
|
|
|
|
|
}
|