- 7 docs revised.

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-11-24 08:42:58 -03:00
parent f44b81e396
commit af865b87e7
16 changed files with 2084 additions and 1434 deletions

View file

@ -88,11 +88,12 @@
- [Architecture Overview](./chapter-07-gbapp/architecture.md) - [Architecture Overview](./chapter-07-gbapp/architecture.md)
- [Building from Source](./chapter-07-gbapp/building.md) - [Building from Source](./chapter-07-gbapp/building.md)
- [Container Deployment (LXC)](./chapter-07-gbapp/containers.md) - [Container Deployment (LXC)](./chapter-07-gbapp/containers.md)
- [Philosophy](./chapter-07-gbapp/philosophy.md)
- [Example gbapp](./chapter-07-gbapp/example-gbapp.md)
- [Module Structure](./chapter-07-gbapp/crates.md) - [Module Structure](./chapter-07-gbapp/crates.md)
- [Service Layer](./chapter-07-gbapp/services.md) - [Service Layer](./chapter-07-gbapp/services.md)
- [Creating Custom Keywords](./chapter-07-gbapp/custom-keywords.md) - [Creating Custom Keywords](./chapter-07-gbapp/custom-keywords.md)
- [Adding Dependencies](./chapter-07-gbapp/dependencies.md) - [Adding Dependencies](./chapter-07-gbapp/dependencies.md)
- [Prompt Manager](./chapter-07-gbapp/prompt-manager.md)
# Part VIII - Bot Configuration # Part VIII - Bot Configuration

View file

@ -1,251 +1,293 @@
# FIND # FIND
**Search for specific data in storage or knowledge bases.** The FIND keyword performs targeted searches in bot memory, databases, or document collections to locate specific information. Search and retrieve data from database tables using filter criteria.
## Syntax ## Syntax
```basic ```basic
result = FIND(pattern) result = FIND "table_name", "filter_criteria"
result = FIND(pattern, location)
result = FIND(pattern, location, options)
``` ```
## Parameters ## Parameters
- `pattern` - Search pattern or query string - `table_name` - The name of the database table to search
- `location` - Where to search (optional, defaults to current KB) - `filter_criteria` - Filter expression in the format "field=value"
- `options` - Search options like case sensitivity, limit (optional)
## Description ## Description
FIND searches for data matching a pattern. Unlike semantic search with LLM, FIND does exact or pattern-based matching. Useful for structured data, IDs, specific values. FIND searches database tables for records matching specified criteria. It returns an array of matching records that can be iterated over using FOR EACH loops.
## Search Locations
### Bot Memory
```basic
' Find in bot's permanent storage
user_data = FIND("user_*", "BOT_MEMORY")
' Returns all keys starting with "user_"
```
### Session Variables
```basic
' Find in current session
form_fields = FIND("form_*", "SESSION")
' Returns all form-related variables
```
### Knowledge Base
```basic
' Find specific documents
policies = FIND("*.pdf", "policies")
' Returns all PDFs in policies collection
```
### Database
```basic
' Find in database tables
orders = FIND("status:pending", "orders")
' Returns pending orders
```
## Examples ## Examples
### Basic Search ### Basic Search
```basic ```basic
' Find a specific user ' Find records with specific action
user = FIND("email:john@example.com") items = FIND "gb.rob", "ACTION=EMUL"
if user
TALK "Found user: " + user.name
else
TALK "User not found"
end
```
### Pattern Matching
```basic
' Find all items matching pattern
items = FIND("SKU-2024-*")
FOR EACH item IN items FOR EACH item IN items
TALK item.name + ": " + item.price TALK "Found: " + item.company
END NEXT
``` ```
### Multi-Criteria Search ### Single Field Filter
```basic ```basic
' Complex search with multiple conditions ' Find pending orders
results = FIND("type:invoice AND status:unpaid AND date>2024-01-01") orders = FIND "orders", "status=pending"
total = 0 FOR EACH order IN orders
FOR EACH invoice IN results TALK "Order #" + order.id + " is pending"
total = total + invoice.amount NEXT
END
TALK "Total unpaid: $" + total
``` ```
### Search with Options ### Working with Results
```basic ```basic
' Limited, case-insensitive search ' Find and process customer records
matches = FIND("john", "customers", { customers = FIND "customers", "city=Seattle"
case_sensitive: false,
limit: 10, FOR EACH customer IN customers
fields: ["name", "email"] TALK customer.name + " from " + customer.address
})
' Access fields with dot notation
email = customer.email
phone = customer.phone
' Update related data
SET "contacts", "id=" + customer.id, "last_contacted=" + NOW()
NEXT
``` ```
## Return Values ## Return Value
FIND returns different types based on matches: FIND returns an array of records from the specified table. Each record is an object with fields accessible via dot notation.
- **Single match** - Returns the item directly - Returns empty array if no matches found
- **Multiple matches** - Returns array of items - Returns array of matching records if successful
- **No matches** - Returns null or empty array - Each record contains all columns from the table
- **Error** - Returns null with error in ERROR variable
## Field Access
Access fields in returned records using dot notation:
```basic
items = FIND "products", "category=electronics"
FOR EACH item IN items
' Access fields directly
TALK item.name
TALK item.price
TALK item.description
' Use null coalescing for optional fields
website = item.website ?? ""
' Check field existence
IF item.discount != "" THEN
TALK "On sale: " + item.discount + "% off"
END IF
NEXT
```
## Common Patterns ## Common Patterns
### Check Existence ### Process All Matching Records
```basic ```basic
exists = FIND("id:" + user_id) tasks = FIND "tasks", "status=open"
if exists
TALK "User already registered" FOR EACH task IN tasks
else ' Process each task
' Create new user TALK "Processing task: " + task.title
end
' Update task status
SET "tasks", "id=" + task.id, "status=in_progress"
NEXT
``` ```
### Filter Results ### Check If Records Exist
```basic ```basic
all_products = FIND("*", "products") users = FIND "users", "email=john@example.com"
in_stock = []
FOR EACH product IN all_products IF LENGTH(users) > 0 THEN
if product.quantity > 0 TALK "User exists"
in_stock.append(product) ELSE
end TALK "User not found"
END END IF
``` ```
### Aggregate Data ### Data Enrichment
```basic ```basic
sales = FIND("date:" + TODAY(), "transactions") companies = FIND "companies", "needs_update=true"
daily_total = 0
FOR EACH sale IN sales FOR EACH company IN companies
daily_total = daily_total + sale.amount ' Get additional data
END website = company.website ?? ""
TALK "Today's sales: $" + daily_total IF website == "" THEN
' Look up website
website = WEBSITE OF company.name
' Update record
SET "companies", "id=" + company.id, "website=" + website
END IF
' Fetch and process website data
page = GET website
' Process page content...
NEXT
``` ```
### Search History ### Batch Processing with Delays
```basic ```basic
' Find previous conversations emails = FIND "email_queue", "sent=false"
history = FIND("session:" + user_id, "messages", {
sort: "timestamp DESC",
limit: 50
})
TALK "Your last conversation:" FOR EACH email IN emails
FOR EACH message IN history ' Send email
TALK message.timestamp + ": " + message.content SEND MAIL email.to, email.subject, email.body
END
' Mark as sent
SET "email_queue", "id=" + email.id, "sent=true"
' Rate limiting
WAIT 1000
NEXT
``` ```
## Performance Tips ## Filter Expressions
The filter parameter uses simple equality expressions:
- `"field=value"` - Match exact value
- Multiple conditions must be handled in BASIC code after retrieval
### Use Specific Patterns
```basic ```basic
' Good - Specific pattern ' Get all records then filter in BASIC
orders = FIND("order_2024_01_*") all_orders = FIND "orders", "status=active"
' Bad - Too broad FOR EACH order IN all_orders
everything = FIND("*") ' Additional filtering in code
IF order.amount > 1000 AND order.priority == "high" THEN
' Process high-value orders
TALK "Priority order: " + order.id
END IF
NEXT
``` ```
### Limit Results ## Working with Different Data Types
```basic
' Get only what you need
recent = FIND("*", "logs", {limit: 100})
```
### Cache Repeated Searches
```basic ```basic
' Cache for session products = FIND "products", "active=true"
if not cached_products
cached_products = FIND("*", "products") FOR EACH product IN products
end ' String fields
' Use cached_products instead of searching again name = product.name
' Numeric fields
price = product.price
quantity = product.quantity
' Date fields
created = product.created_at
' Boolean-like fields (stored as strings)
IF product.featured == "true" THEN
TALK "Featured: " + name
END IF
NEXT
``` ```
## Error Handling ## Error Handling
```basic ```basic
try ' Handle potential errors
results = FIND(user_query) items = FIND "inventory", "warehouse=main"
if results
TALK "Found " + LENGTH(results) + " matches" IF items == null THEN
else TALK "Error accessing inventory data"
TALK "No results found" ELSE IF LENGTH(items) == 0 THEN
end TALK "No items found in main warehouse"
catch error ELSE
TALK "Search failed. Please try again." TALK "Found " + LENGTH(items) + " items"
LOG "FIND error: " + error ' Process items...
end END IF
``` ```
## Comparison with Other Keywords ## Performance Considerations
| Keyword | Purpose | Use When | 1. **Limit Results**: The system automatically limits to 10 results for safety
|---------|---------|----------| 2. **Use Specific Filters**: More specific filters reduce processing time
| FIND | Exact/pattern search | Looking for specific values | 3. **Avoid Full Table Scans**: Always provide a filter criterion
| LLM | Semantic search | Understanding meaning | 4. **Process in Batches**: For large datasets, process in chunks
| GET | Direct retrieval | Know exact key |
| USE KB | Activate knowledge | Need document context |
## Advanced Usage
### Dynamic Location
```basic ```basic
department = GET user.department ' Process records in batches
data = FIND("*", department + "_records") batch = FIND "large_table", "processed=false"
count = 0
FOR EACH record IN batch
' Process record
SET "large_table", "id=" + record.id, "processed=true"
count = count + 1
IF count >= 10 THEN
EXIT FOR ' Process max 10 at a time
END IF
NEXT
``` ```
### Compound Searches ## Integration with Other Keywords
### With SET for Updates
```basic ```basic
' Find in multiple places users = FIND "users", "newsletter=true"
local = FIND(query, "local_db")
remote = FIND(query, "remote_api") FOR EACH user IN users
results = MERGE(local, remote) ' Update last_notified field
SET "users", "id=" + user.id, "last_notified=" + NOW()
NEXT
``` ```
### Conditional Fields ### With LLM for Processing
```basic ```basic
search_fields = ["name"] articles = FIND "articles", "needs_summary=true"
if advanced_mode
search_fields.append(["email", "phone", "address"])
end
results = FIND(term, "contacts", {fields: search_fields}) FOR EACH article IN articles
summary = LLM "Summarize: " + article.content
SET "articles", "id=" + article.id, "summary=" + summary
NEXT
``` ```
### With CREATE SITE
```basic
companies = FIND "companies", "needs_site=true"
FOR EACH company IN companies
alias = LLM "Create URL alias for: " + company.name
CREATE SITE alias, "template", "Create site for " + company.name
SET "companies", "id=" + company.id, "site_url=" + alias
NEXT
```
## Limitations
- Maximum 10 records returned per query (system limit)
- Filter supports simple equality only
- Complex queries require post-processing in BASIC
- Table must exist in the database
- User must have read permissions on the table
## Best Practices ## Best Practices
**Be specific** - Use precise patterns to avoid large result sets **Always check results** - Verify FIND returned data before processing
**Handle empty results** - Always check if FIND returned data **Use specific filters** - Reduce result set size with precise criteria
**Use appropriate location** - Search where data actually lives **Handle empty results** - Check LENGTH before iterating
**Limit when possible** - Don't retrieve more than needed **Update as you go** - Mark records as processed to avoid reprocessing
**Don't search everything** - Avoid FIND("*") without limits **Don't assume order** - Results may not be sorted
**Don't assume order** - Results may not be sorted unless specified **Don't ignore limits** - Remember the 10-record limit
**Don't ignore errors** - Wrap in try/catch for production **Don't use without filter** - Always provide filter criteria
## See Also ## See Also
- [GET](./keyword-get.md) - Direct key retrieval - [SET](./keyword-set.md) - Update database records
- [SET](./keyword-set.md) - Store data - [GET](./keyword-get.md) - Retrieve single values
- [USE KB](./keyword-use-kb.md) - Semantic document search - [FOR EACH](./keyword-for-each.md) - Iterate over results
- [LLM](./keyword-llm.md) - AI-powered search - [LLM](./keyword-llm.md) - Process found data with AI

View file

@ -242,15 +242,11 @@ END IF
### Authentication Failed ### Authentication Failed
```basic Check SMTP configuration:
' Test SMTP connection 1. Verify credentials in `config.csv`
TEST_SMTP_CONNECTION() 2. Ensure SMTP server allows your connection
IF CONNECTION_OK THEN 3. Check if port 587/465 is open
TALK "SMTP connection successful" 4. Verify TLS/SSL settings match server requirements
ELSE
TALK "Check email-user and email-pass in config.csv"
END IF
```
### Emails Going to Spam ### Emails Going to Spam

View file

@ -1,405 +1,379 @@
# Extending BotServer # gbapp: Virtual Crates Architecture
This chapter covers how to extend and customize BotServer to meet specific requirements, from creating custom keywords to building new channel adapters and integrating with external systems. This chapter explains how BotServer uses the gbapp concept as virtual crates within the `src/` directory, elegantly mapping the old package system to the new Rust architecture.
## Overview ## The gbapp Evolution: From Packages to Virtual Crates
BotServer is designed to be extensible at multiple levels: ### Historical Context (Node.js Era)
- **BASIC Keywords**: Add new commands to the scripting language In previous versions, `.gbapp` packages were external Node.js modules that extended BotServer functionality through a plugin system.
- **Channel Adapters**: Support new messaging platforms
- **Storage Backends**: Integrate different storage systems
- **Authentication Providers**: Connect to various identity services
- **LLM Providers**: Add support for new language models
## Extension Points ### Current Architecture (Rust Era)
The `.gbapp` concept now lives as **virtual crates** inside `src/`:
- **Virtual Crates**: Each gbapp is a module inside `src/` (like `src/core`, `src/basic`, `src/channels`)
- **Same Mental Model**: Developers familiar with the old system can think of each directory as a "package"
- **Native Performance**: All code compiles into a single optimized binary
- **Contribution Path**: Add new gbapps by creating modules in `src/`
### 1. Custom BASIC Keywords ## How gbapp Virtual Crates Work
Create new keywords by implementing them in Rust: ```
src/
├── core/ # core.gbapp (virtual crate)
├── basic/ # basic.gbapp (BASIC interpreter)
├── channels/ # channels.gbapp (communication)
├── storage/ # storage.gbapp (persistence)
├── auth/ # auth.gbapp (authentication)
├── llm/ # llm.gbapp (AI integration)
└── your_feature/ # your_feature.gbapp (your contribution!)
```
Each directory is conceptually a gbapp - a self-contained module that contributes functionality to the whole.
## Why This Change?
1. **Simplicity**: One cohesive codebase instead of fragmented extensions
2. **Performance**: Native Rust performance without extension overhead
3. **Reliability**: Thoroughly tested core features vs. variable-quality plugins
4. **BASIC Power**: BASIC + LLM combination eliminates need for custom code
5. **Maintenance**: Easier to maintain one strong core than many extensions
## Contributing New Keywords
### Contributing a New gbapp Virtual Crate
To add functionality, create a new gbapp as a module in `src/`:
```rust ```rust
// src/basic/keywords/my_keyword.rs // src/your_feature/mod.rs - Your gbapp virtual crate
use rhai::{Engine, Dynamic}; pub mod keywords;
pub mod services;
pub mod models;
// src/your_feature/keywords/mod.rs
use crate::shared::state::AppState; use crate::shared::state::AppState;
use rhai::Engine;
pub fn register_my_keyword(engine: &mut Engine, state: Arc<AppState>) { pub fn register_keywords(engine: &mut Engine, state: Arc<AppState>) {
engine.register_fn("MY_KEYWORD", move |param: String| -> String { engine.register_fn("YOUR KEYWORD", move |param: String| -> String {
// Your implementation here // Implementation
format!("Processed: {}", param) format!("Result: {}", param)
}); });
} }
``` ```
Register in the keyword module: This maintains the conceptual model of packages while leveraging Rust's module system.
### Contribution Process for gbapp Virtual Crates
1. **Fork** the BotServer repository
2. **Create** your gbapp module in `src/your_feature/`
3. **Structure** it like existing gbapps (core, basic, etc.)
4. **Test** thoroughly with unit and integration tests
5. **Document** in the appropriate chapter
6. **Submit PR** describing your gbapp's purpose
Example structure for a new gbapp:
```
src/analytics/ # analytics.gbapp
├── mod.rs # Module definition
├── keywords.rs # BASIC keywords
├── services.rs # Core services
├── models.rs # Data models
└── tests.rs # Unit tests
```
## Adding New Components
Components are features compiled into BotServer via Cargo features:
### Current Components in Cargo.toml
```toml
[features]
# Core features
chat = [] # Chat functionality
drive = [] # Storage system
tasks = [] # Task management
calendar = [] # Calendar integration
meet = [] # Video meetings
mail = [] # Email system
# Enterprise features
compliance = [] # Compliance tools
attendance = [] # Attendance tracking
directory = [] # User directory
```
### Adding a New Component
1. **Define Feature** in `Cargo.toml`:
```toml
[features]
your_feature = ["dep:required_crate"]
```
2. **Implement** in appropriate module:
```rust ```rust
// src/basic/keywords/mod.rs #[cfg(feature = "your_feature")]
pub fn register_all_keywords(engine: &mut Engine, state: Arc<AppState>) { pub mod your_feature {
// ... existing keywords // Implementation
register_my_keyword(engine, state.clone());
} }
``` ```
Use in BASIC scripts: 3. **Register** in `installer.rs`:
```basic ```rust
result = MY_KEYWORD "input data" fn register_your_feature(&mut self) {
TALK result self.components.insert(
"your_feature",
Component {
name: "Your Feature",
description: "Feature description",
port: None,
setup_required: false,
},
);
}
``` ```
### 2. Channel Adapters ## Understanding the gbapp → Virtual Crate Mapping
Implement a new messaging channel: The transition from Node.js packages to Rust modules maintains conceptual familiarity:
| Old (Node.js) | New (Rust) | Location | Purpose |
|---------------|------------|----------|---------|
| `core.gbapp` | `core` module | `src/core/` | Core engine functionality |
| `basic.gbapp` | `basic` module | `src/basic/` | BASIC interpreter |
| `whatsapp.gbapp` | `channels::whatsapp` | `src/channels/whatsapp/` | WhatsApp integration |
| `kb.gbapp` | `storage::kb` | `src/storage/kb/` | Knowledge base |
| `custom.gbapp` | `custom` module | `src/custom/` | Your contribution |
### Creating Private gbapp Virtual Crates
For proprietary features, you can still create private gbapps:
```rust ```rust
// src/channels/my_channel.rs // Fork BotServer, then add your private gbapp
use async_trait::async_trait; // src/proprietary/mod.rs
use crate::channels::traits::ChannelAdapter; #[cfg(feature = "proprietary")]
pub mod my_private_feature {
pub struct MyChannelAdapter { // Your private implementation
config: MyChannelConfig,
}
#[async_trait]
impl ChannelAdapter for MyChannelAdapter {
async fn send_message(&self, recipient: &str, message: &str) -> Result<()> {
// Send message implementation
}
async fn receive_message(&self) -> Result<Message> {
// Receive message implementation
}
async fn send_attachment(&self, recipient: &str, file: &[u8]) -> Result<()> {
// Send file implementation
}
} }
``` ```
### 3. Storage Providers Then in `Cargo.toml`:
```toml
Add support for new storage backends: [features]
proprietary = []
```rust
// src/storage/my_storage.rs
use async_trait::async_trait;
use crate::storage::traits::StorageProvider;
pub struct MyStorageProvider {
client: MyStorageClient,
}
#[async_trait]
impl StorageProvider for MyStorageProvider {
async fn get(&self, key: &str) -> Result<Vec<u8>> {
// Retrieve object
}
async fn put(&self, key: &str, data: &[u8]) -> Result<()> {
// Store object
}
async fn delete(&self, key: &str) -> Result<()> {
// Delete object
}
async fn list(&self, prefix: &str) -> Result<Vec<String>> {
// List objects
}
}
``` ```
## Architecture for Extensions This keeps your code separate while benefiting from core updates.
### Plugin System ### Benefits of the Virtual Crate Approach
BotServer uses a modular architecture that supports plugins: 1. **Familiar Mental Model**: Developers understand "packages"
2. **Clean Separation**: Each gbapp is self-contained
3. **Easy Discovery**: All gbapps visible in `src/`
4. **Native Performance**: Everything compiles together
5. **Type Safety**: Rust ensures interfaces are correct
## Real Examples of gbapp Virtual Crates in src/
``` ```
botserver/ src/
├── src/ ├── core/ # Core gbapp - Bootstrap, package manager
│ ├── core/ # Core functionality │ ├── mod.rs
│ ├── basic/ # BASIC interpreter │ ├── bootstrap.rs
│ │ └── keywords/ # Keyword implementations │ └── package_manager/
│ ├── channels/ # Channel adapters
│ ├── storage/ # Storage providers ├── basic/ # BASIC gbapp - Interpreter and keywords
│ ├── auth/ # Authentication modules │ ├── mod.rs
│ └── llm/ # LLM integrations │ ├── interpreter.rs
│ └── keywords/
│ ├── mod.rs
│ ├── talk.rs
│ ├── hear.rs
│ └── llm.rs
├── channels/ # Channels gbapp - Communication adapters
│ ├── mod.rs
│ ├── whatsapp.rs
│ ├── teams.rs
│ └── email.rs
└── analytics/ # Your new gbapp!
├── mod.rs
├── keywords.rs # ADD ANALYTICS, GET METRICS
└── services.rs # Analytics engine
``` ```
### Dependency Injection ## Development Environment
Extensions use dependency injection for configuration: ### System Requirements
```rust - **Disk Space**: 8GB minimum for development
// Configuration - **RAM**: 8GB recommended
#[derive(Deserialize)] - **Database**: Any SQL database (abstracted)
pub struct ExtensionConfig { - **Storage**: Any S3-compatible storage (abstracted)
pub enabled: bool,
pub options: HashMap<String, String>,
}
// Registration ### No Brand Lock-in
pub fn register_extension(app_state: &mut AppState, config: ExtensionConfig) {
if config.enabled { BotServer uses generic terms:
let extension = MyExtension::new(config.options); - ❌ PostgreSQL → ✅ "database"
app_state.extensions.push(Box::new(extension)); - ❌ MinIO → ✅ "drive storage"
} - ❌ Qdrant → ✅ "vector database"
} - ❌ Redis → ✅ "cache"
This ensures vendor neutrality and flexibility.
## Security Best Practices
### Regular Audits
Run security audits regularly:
```bash
cargo audit
``` ```
## Common Extension Patterns This checks for known vulnerabilities in dependencies.
### 1. API Integration ### Secure Coding
Create a keyword for external API calls: When contributing:
- Validate all inputs
- Use safe Rust patterns
- Avoid `unsafe` blocks
- Handle errors properly
- Add security tests
```rust ## Testing Your Contributions
pub fn register_api_keyword(engine: &mut Engine) {
engine.register_fn("CALL_API", |url: String, method: String| -> Dynamic {
let runtime = tokio::runtime::Runtime::new().unwrap();
runtime.block_on(async {
let client = reqwest::Client::new();
let response = match method.as_str() {
"GET" => client.get(&url).send().await,
"POST" => client.post(&url).send().await,
_ => return Dynamic::from("Invalid method"),
};
match response {
Ok(resp) => Dynamic::from(resp.text().await.unwrap_or_default()),
Err(_) => Dynamic::from("Error calling API"),
}
})
});
}
```
### 2. Database Operations
Add custom database queries:
```rust
pub fn register_db_keyword(engine: &mut Engine, state: Arc<AppState>) {
let state_clone = state.clone();
engine.register_fn("QUERY_DB", move |sql: String| -> Vec<Dynamic> {
let mut conn = state_clone.conn.get().unwrap();
// Execute query (with proper sanitization)
let results = diesel::sql_query(sql)
.load::<CustomResult>(&mut conn)
.unwrap_or_default();
// Convert to Dynamic
results.into_iter()
.map(|r| Dynamic::from(r))
.collect()
});
}
```
### 3. Event Handlers
Implement custom event processing:
```rust
pub trait EventHandler: Send + Sync {
fn handle_event(&self, event: Event) -> Result<()>;
}
pub struct CustomEventHandler;
impl EventHandler for CustomEventHandler {
fn handle_event(&self, event: Event) -> Result<()> {
match event {
Event::MessageReceived(msg) => {
// Process incoming message
},
Event::SessionStarted(session) => {
// Initialize session
},
Event::Error(err) => {
// Handle errors
},
_ => Ok(()),
}
}
}
```
## Testing Extensions
### Unit Tests ### Unit Tests
```rust ```rust
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
#[test] #[test]
fn test_my_keyword() { fn test_keyword() {
let mut engine = Engine::new(); // Test your keyword
register_my_keyword(&mut engine);
let result: String = engine.eval(r#"MY_KEYWORD "test""#).unwrap();
assert_eq!(result, "Processed: test");
} }
} }
``` ```
### Integration Tests ### Integration Tests
```rust ```rust
#[tokio::test] #[tokio::test]
async fn test_channel_adapter() { async fn test_feature() {
let adapter = MyChannelAdapter::new(test_config()); // Test feature integration
// Test sending
let result = adapter.send_message("user123", "Test message").await;
assert!(result.is_ok());
// Test receiving
let message = adapter.receive_message().await.unwrap();
assert_eq!(message.content, "Expected response");
} }
``` ```
## Deployment Considerations ### BASIC Script Tests
```basic
### Configuration ' test_script.bas
result = YOUR KEYWORD "test"
Extensions are configured in `config.csv`: IF result != "expected" THEN
TALK "Test failed"
```csv ELSE
name,value TALK "Test passed"
extension_my_feature,enabled END IF
extension_my_feature_option1,value1
extension_my_feature_option2,value2
``` ```
### Performance Impact ## Documentation Requirements
Consider performance when adding extensions: All contributions must include:
- Use async operations for I/O
- Implement caching where appropriate
- Profile resource usage
- Add metrics and monitoring
### Security 1. **Keyword Documentation** in Chapter 6
2. **Architecture Updates** if structural changes
3. **API Documentation** for new endpoints
4. **BASIC Examples** showing usage
5. **Migration Guide** if breaking changes
Ensure extensions are secure: ## Performance Considerations
- Validate all input
- Use prepared statements for database queries
- Implement rate limiting
- Add authentication where needed
- Follow least privilege principle
## Best Practices ### Benchmarking
### 1. Error Handling Before submitting:
```bash
Always handle errors gracefully: cargo bench
```rust
pub fn my_extension_function() -> Result<String> {
// Use ? operator for error propagation
let data = fetch_data()?;
let processed = process_data(data)?;
Ok(format!("Success: {}", processed))
}
``` ```
### 2. Logging ### Profiling
Add comprehensive logging: Identify bottlenecks:
```bash
```rust cargo flamegraph
use log::{info, warn, error, debug};
pub fn process_request(req: Request) {
debug!("Processing request: {:?}", req);
match handle_request(req) {
Ok(result) => info!("Request successful: {}", result),
Err(e) => error!("Request failed: {}", e),
}
}
``` ```
### 3. Documentation ## Community Guidelines
Document your extensions: ### What We Accept
```rust ✅ New BASIC keywords that benefit many users
/// Custom keyword for data processing ✅ Performance improvements
/// ✅ Bug fixes with tests
/// # Arguments ✅ Documentation improvements
/// * `input` - The data to process ✅ Security enhancements
///
/// # Returns ### What We Don't Accept
/// Processed data as a string
/// ❌ Vendor-specific integrations (use generic interfaces)
/// # Example ❌ Extensions that bypass BASIC
/// ```basic ❌ Features achievable with existing keywords
/// result = PROCESS_DATA "raw input" ❌ Undocumented code
/// ``` ❌ Code without tests
pub fn process_data_keyword(input: String) -> String {
// Implementation ## The Power of BASIC + LLM
}
Remember: In 2025, 100% BASIC/LLM applications are reality. Before adding a keyword, consider:
1. Can this be done with existing keywords + LLM?
2. Will this keyword benefit multiple use cases?
3. Does it follow the BASIC philosophy of simplicity?
### Example: No Custom Code Needed
Instead of custom integration code:
```basic
' Everything in BASIC
data = GET "api.example.com/data"
processed = LLM "Process this data: " + data
result = FIND "table", "criteria=" + processed
SEND MAIL user, "Results", result
``` ```
## Examples of Extensions ## Future Direction
### Weather Integration BotServer's future is:
- **Stronger Core**: More powerful built-in keywords
- **Better LLM Integration**: Smarter AI capabilities
- **Simpler BASIC**: Even easier scripting
- **Community-Driven**: Features requested by users
```rust ## How to Get Started
pub fn register_weather_keyword(engine: &mut Engine) {
engine.register_fn("GET_WEATHER", |city: String| -> String {
// Call weather API
let api_key = std::env::var("WEATHER_API_KEY").unwrap_or_default();
let url = format!("https://api.weather.com/v1/weather?city={}&key={}", city, api_key);
// Fetch and parse response
// Return weather information
});
}
```
### Custom Analytics 1. **Fork** the repository
2. **Read** existing code in `src/basic/keywords/`
```rust 3. **Discuss** your idea in GitHub Issues
pub struct AnalyticsExtension { 4. **Implement** following the patterns
client: AnalyticsClient, 5. **Test** thoroughly
} 6. **Document** completely
7. **Submit** PR with clear explanation
impl AnalyticsExtension {
pub fn track_event(&self, event: &str, properties: HashMap<String, String>) {
self.client.track(Event {
name: event.to_string(),
properties,
timestamp: Utc::now(),
});
}
}
```
## Summary ## Summary
Extending BotServer allows you to: The `.gbapp` concept has elegantly evolved from external Node.js packages to **virtual crates** within `src/`. This approach:
- Add domain-specific functionality - **Preserves the mental model** developers are familiar with
- Integrate with existing systems - **Maps perfectly** to Rust's module system
- Support new communication channels - **Encourages contribution** by making the structure clear
- Implement custom business logic - **Maintains separation** while compiling to a single binary
- Enhance the platform's capabilities
The modular architecture and clear extension points make it straightforward to add new features while maintaining system stability and performance. Each directory in `src/` is effectively a gbapp - contribute by adding your own! With BASIC + LLM handling the complexity, your gbapp just needs to provide the right keywords and services.
## See Also ## See Also
- [Prompt Manager](./prompt-manager.md) - Managing AI prompts and responses - [Philosophy](./philosophy.md) - The gbapp philosophy: Let machines do machine work
- [Hooks System](./hooks.md) - Event-driven extensions - [Architecture](./architecture.md) - System architecture
- [Adapter Development](./adapters.md) - Creating custom adapters - [Building](./building.md) - Build process
- [Chapter 2: Packages](../chapter-02/README.md) - Understanding bot components - [Custom Keywords](./custom-keywords.md) - Keyword implementation
- [Chapter 3: KB and Tools](../chapter-03/kb-and-tools.md) - Knowledge base and tool system - [Services](./services.md) - Core services
- [Chapter 5: BASIC Reference](../chapter-05/README.md) - Complete command reference - [Chapter 6: BASIC Reference](../chapter-06-gbdialog/README.md) - BASIC language
- [Chapter 8: External APIs](../chapter-08/external-apis.md) - API integration patterns - [Chapter 9: API](../chapter-09-api/README.md) - API documentation
- [Chapter 9: Advanced Topics](../chapter-09/README.md) - Advanced features
- [Chapter 10: Development](../chapter-10/README.md) - Development tools and practices

View file

@ -4,50 +4,15 @@ BotServer follows a modular architecture designed for scalability, maintainabili
## Core Architecture ## Core Architecture
### System Architecture Diagram ### Data Flow Architecture
``` ![BotServer Data Flow Architecture](./assets/data-flow.svg)
┌─────────────────────────────────────────────────────────────────────────┐
│ BotServer (Binary) │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Core Engine │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ BASIC │ │ Session │ │ Context │ │ │
│ │ │ Interpreter │ │ Manager │ │ Manager │ │ │
│ │ │ (Rhai) │ │ (Tokio) │ │ (Memory) │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
│ └─────────┼──────────────────┼──────────────────┼───────────────────┘ │
│ │ │ │ │
│ ┌─────────▼──────────────────▼──────────────────▼───────────────────┐ │
│ │ AI & NLP Layer │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ LLM │ │ Embeddings │ │ Knowledge │ │ │
│ │ │ Integration │ │ (BGE) │ │ Base │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
│ └─────────┼──────────────────┼──────────────────┼───────────────────┘ │
│ │ │ │ │
│ ┌─────────▼──────────────────▼──────────────────▼───────────────────┐ │
│ │ Communication Layer │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ WebSocket │ │ REST API │ │ Channels │ │ │
│ │ │ Server │ │ (Axum) │ │ Adapters │ │ │
│ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │
│ └─────────┼──────────────────┼──────────────────┼───────────────────┘ │
│ │ │ │ │
│ ┌─────────▼──────────────────▼──────────────────▼───────────────────┐ │
│ │ Storage Layer │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │PostgreSQL│ │ Valkey │ │ SeaweedFS│ │ Qdrant │ │ │
│ │ │ (Diesel) │ │ Cache │ │ S3 │ │ Vectors │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
### Module Dependency Graph ### System Architecture
![BotServer System Architecture](./assets/system-architecture.svg)
## Module Dependency Graph
``` ```
main.rs main.rs

View file

@ -0,0 +1,139 @@
<svg width="800" height="600" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#666" opacity="0.8"/>
</marker>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#4A90E2;stop-opacity:0.1" />
<stop offset="100%" style="stop-color:#4A90E2;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="gradient2" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#50C878;stop-opacity:0.1" />
<stop offset="100%" style="stop-color:#50C878;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="gradient3" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#FF6B6B;stop-opacity:0.1" />
<stop offset="100%" style="stop-color:#FF6B6B;stop-opacity:0.3" />
</linearGradient>
</defs>
<!-- Title -->
<text x="400" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#333">BotServer Data Flow Architecture</text>
<!-- User Input Layer -->
<g id="user-layer">
<rect x="50" y="60" width="700" height="80" fill="url(#gradient1)" stroke="#4A90E2" stroke-width="2" rx="8" opacity="0.8"/>
<text x="400" y="85" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#333">User Input Layer</text>
<!-- Input sources -->
<rect x="80" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
<text x="140" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">Web UI</text>
<rect x="220" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
<text x="280" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">WhatsApp</text>
<rect x="360" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
<text x="420" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">Teams</text>
<rect x="500" y="95" width="120" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
<text x="560" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">Email</text>
<rect x="640" y="95" width="80" height="30" fill="white" stroke="#4A90E2" stroke-width="1" rx="4" opacity="0.9"/>
<text x="680" y="113" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#333">API</text>
</g>
<!-- Arrows from User Layer to Processing -->
<line x1="400" y1="140" x2="400" y2="170" stroke="#666" stroke-width="2" marker-end="url(#arrow)" opacity="0.6"/>
<!-- Processing Layer -->
<g id="processing-layer">
<rect x="50" y="170" width="700" height="200" fill="url(#gradient2)" stroke="#50C878" stroke-width="2" rx="8" opacity="0.8"/>
<text x="400" y="195" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#333">Core Processing Engine</text>
<!-- Session Manager -->
<rect x="80" y="210" width="150" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
<text x="155" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Session Manager</text>
<text x="155" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">User Context</text>
<!-- BASIC Interpreter -->
<rect x="250" y="210" width="150" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
<text x="325" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">BASIC Interpreter</text>
<text x="325" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Script Execution</text>
<!-- LLM Integration -->
<rect x="420" y="210" width="150" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
<text x="495" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">LLM Integration</text>
<text x="495" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">AI Processing</text>
<!-- Knowledge Base -->
<rect x="590" y="210" width="130" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
<text x="655" y="235" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Knowledge Base</text>
<text x="655" y="252" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Vector Search</text>
<!-- Internal flow arrows -->
<line x1="230" y1="240" x2="250" y2="240" stroke="#666" stroke-width="1" marker-end="url(#arrow)" opacity="0.5"/>
<line x1="400" y1="240" x2="420" y2="240" stroke="#666" stroke-width="1" marker-end="url(#arrow)" opacity="0.5"/>
<line x1="570" y1="240" x2="590" y2="240" stroke="#666" stroke-width="1" marker-end="url(#arrow)" opacity="0.5"/>
<!-- Tool System -->
<rect x="80" y="290" width="300" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
<text x="230" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Tool System</text>
<text x="230" y="332" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">External APIs &amp; Functions</text>
<!-- Cache Layer -->
<rect x="420" y="290" width="300" height="60" fill="white" stroke="#50C878" stroke-width="1" rx="4" opacity="0.9"/>
<text x="570" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Cache Layer</text>
<text x="570" y="332" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Response Optimization</text>
</g>
<!-- Arrows from Processing to Storage -->
<line x1="400" y1="370" x2="400" y2="400" stroke="#666" stroke-width="2" marker-end="url(#arrow)" opacity="0.6"/>
<!-- Storage Layer -->
<g id="storage-layer">
<rect x="50" y="400" width="700" height="120" fill="url(#gradient3)" stroke="#FF6B6B" stroke-width="2" rx="8" opacity="0.8"/>
<text x="400" y="425" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#333">Storage &amp; Persistence Layer</text>
<!-- Database -->
<rect x="80" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
<text x="150" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Database</text>
<text x="150" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">User Data</text>
<!-- Vector DB -->
<rect x="240" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
<text x="310" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Vector DB</text>
<text x="310" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Embeddings</text>
<!-- Drive Storage -->
<rect x="400" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
<text x="470" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Drive Storage</text>
<text x="470" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Files &amp; Assets</text>
<!-- Cache -->
<rect x="560" y="450" width="140" height="50" fill="white" stroke="#FF6B6B" stroke-width="1" rx="4" opacity="0.9"/>
<text x="630" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Cache</text>
<text x="630" y="487" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#666">Fast Access</text>
</g>
<!-- Bidirectional arrows showing data flow -->
<g id="flow-arrows" opacity="0.4">
<!-- Vertical flows -->
<line x1="155" y1="270" x2="155" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
<line x1="325" y1="270" x2="310" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
<line x1="495" y1="270" x2="470" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
<line x1="655" y1="270" x2="630" y2="450" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
</g>
<!-- Legend -->
<g id="legend" transform="translate(50, 540)">
<text x="0" y="0" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#333">Data Flow:</text>
<line x1="80" y1="-5" x2="120" y2="-5" stroke="#666" stroke-width="2" marker-end="url(#arrow)"/>
<text x="125" y="0" font-family="Arial, sans-serif" font-size="11" fill="#666">Request/Response</text>
<line x1="250" y1="-5" x2="290" y2="-5" stroke="#666" stroke-width="1" stroke-dasharray="5,5"/>
<text x="295" y="0" font-family="Arial, sans-serif" font-size="11" fill="#666">Data Access</text>
</g>
<!-- Performance Note -->
<text x="400" y="580" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#999">All components run in async Rust for maximum performance</text>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View file

@ -0,0 +1,155 @@
<svg width="900" height="700" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 700">
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
<path d="M0,0 L0,6 L9,3 z" fill="#666"/>
</marker>
</defs>
<!-- Title -->
<text x="450" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="22" font-weight="bold" fill="#1F2937">BotServer Architecture - Virtual Crates System</text>
<!-- Main Container -->
<rect x="40" y="50" width="820" height="620" fill="none" stroke="#E5E7EB" stroke-width="2" rx="12" stroke-opacity="0.5"/>
<!-- Binary Output -->
<rect x="350" y="70" width="200" height="40" fill="#EBF8FF" stroke="#2563EB" stroke-width="2" rx="8"/>
<text x="450" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#1F2937">BotServer Binary</text>
<!-- Compilation Arrow -->
<line x1="450" y1="110" x2="450" y2="140" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" stroke-dasharray="5,3" opacity="0.6"/>
<text x="470" y="130" font-family="Arial, sans-serif" font-size="10" fill="#6B7280">compiles to</text>
<!-- Core Layer -->
<g id="core-layer">
<rect x="60" y="140" width="780" height="120" fill="#EBF8FF" fill-opacity="0.3" stroke="#2563EB" stroke-width="2" rx="8"/>
<text x="450" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#1F2937">Core Engine (src/core/)</text>
<!-- Core Components -->
<rect x="80" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
<text x="150" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Bootstrap</text>
<text x="150" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">System Init</text>
<text x="150" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Service Start</text>
<rect x="240" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
<text x="310" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Package Manager</text>
<text x="310" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Component Registry</text>
<text x="310" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Module Loader</text>
<rect x="400" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
<text x="470" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Session Manager</text>
<text x="470" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Context Handling</text>
<text x="470" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">State Management</text>
<rect x="560" y="185" width="140" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
<text x="630" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Shared State</text>
<text x="630" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">AppState</text>
<text x="630" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Configuration</text>
<rect x="720" y="185" width="100" height="55" fill="white" stroke="#2563EB" stroke-width="1" rx="4"/>
<text x="770" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">Utils</text>
<text x="770" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Helpers</text>
<text x="770" y="232" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">Common</text>
</g>
<!-- Bidirectional Arrow -->
<line x1="450" y1="260" x2="450" y2="290" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" opacity="0.6"/>
<line x1="460" y1="290" x2="460" y2="260" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" opacity="0.6"/>
<!-- Virtual Crates Layer (gbapps) -->
<g id="gbapp-layer">
<rect x="60" y="290" width="780" height="180" fill="#D1FAE5" fill-opacity="0.3" stroke="#10B981" stroke-width="2" rx="8"/>
<text x="450" y="315" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#1F2937">Virtual Crates (gbapp modules in src/)</text>
<!-- BASIC gbapp -->
<rect x="80" y="335" width="170" height="115" fill="white" stroke="#10B981" stroke-width="1" rx="4"/>
<text x="165" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">basic.gbapp</text>
<text x="165" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/basic/</text>
<line x1="90" y1="378" x2="240" y2="378" stroke="#E5E7EB" stroke-width="1"/>
<text x="165" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• BASIC Interpreter</text>
<text x="165" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Keywords Registry</text>
<text x="165" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Script Execution</text>
<text x="165" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Rhai Engine</text>
<!-- Channels gbapp -->
<rect x="270" y="335" width="170" height="115" fill="white" stroke="#10B981" stroke-width="1" rx="4"/>
<text x="355" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">channels.gbapp</text>
<text x="355" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/channels/</text>
<line x1="280" y1="378" x2="430" y2="378" stroke="#E5E7EB" stroke-width="1"/>
<text x="355" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• WhatsApp</text>
<text x="355" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Teams</text>
<text x="355" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Email</text>
<text x="355" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Web UI</text>
<!-- Storage gbapp -->
<rect x="460" y="335" width="170" height="115" fill="white" stroke="#10B981" stroke-width="1" rx="4"/>
<text x="545" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">storage.gbapp</text>
<text x="545" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/storage/</text>
<line x1="470" y1="378" x2="620" y2="378" stroke="#E5E7EB" stroke-width="1"/>
<text x="545" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Knowledge Base</text>
<text x="545" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Drive Integration</text>
<text x="545" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Vector DB</text>
<text x="545" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">• Cache</text>
<!-- Custom gbapp (Your Contribution) -->
<rect x="650" y="335" width="170" height="115" fill="#FEF3C7" stroke="#F59E0B" stroke-width="2" rx="4" stroke-dasharray="5,3"/>
<text x="735" y="355" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#1F2937">your_feature.gbapp</text>
<text x="735" y="370" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#6B7280">src/your_feature/</text>
<line x1="660" y1="378" x2="810" y2="378" stroke="#E5E7EB" stroke-width="1"/>
<text x="735" y="393" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-style="italic" fill="#6B7280">• Your Keywords</text>
<text x="735" y="408" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-style="italic" fill="#6B7280">• Your Services</text>
<text x="735" y="423" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-style="italic" fill="#6B7280">• Your Models</text>
<text x="735" y="438" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" font-weight="bold" fill="#F59E0B">+ Add yours!</text>
</g>
<!-- Arrow from gbapp to AI -->
<line x1="450" y1="470" x2="450" y2="500" stroke="#666" stroke-width="2" marker-end="url(#arrowhead)" opacity="0.6"/>
<!-- AI/LLM Layer -->
<g id="ai-layer">
<rect x="60" y="500" width="380" height="80" fill="#EDE9FE" fill-opacity="0.3" stroke="#8B5CF6" stroke-width="2" rx="8"/>
<text x="250" y="525" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#1F2937">AI &amp; LLM Integration</text>
<rect x="80" y="535" width="100" height="35" fill="white" stroke="#8B5CF6" stroke-width="1" rx="4"/>
<text x="130" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">LLM Service</text>
<rect x="195" y="535" width="100" height="35" fill="white" stroke="#8B5CF6" stroke-width="1" rx="4"/>
<text x="245" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Embeddings</text>
<rect x="310" y="535" width="110" height="35" fill="white" stroke="#8B5CF6" stroke-width="1" rx="4"/>
<text x="365" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Semantic Search</text>
</g>
<!-- Storage Layer -->
<g id="storage-layer">
<rect x="460" y="500" width="380" height="80" fill="#FEE2E2" fill-opacity="0.3" stroke="#EF4444" stroke-width="2" rx="8"/>
<text x="650" y="525" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="#1F2937">Persistence Layer</text>
<rect x="480" y="535" width="85" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
<text x="522" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Database</text>
<rect x="580" y="535" width="85" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
<text x="622" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Vector DB</text>
<rect x="680" y="535" width="70" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
<text x="715" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Drive</text>
<rect x="765" y="535" width="60" height="35" fill="white" stroke="#EF4444" stroke-width="1" rx="4"/>
<text x="795" y="555" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#1F2937">Cache</text>
</g>
<!-- Legend -->
<g id="legend" transform="translate(60, 600)">
<text x="0" y="0" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#1F2937">Key Concepts:</text>
<rect x="120" y="-12" width="15" height="15" fill="#D1FAE5" stroke="#10B981" stroke-width="1" rx="2"/>
<text x="140" y="0" font-family="Arial, sans-serif" font-size="11" fill="#4B5563">Virtual Crates = Modules in src/</text>
<rect x="320" y="-12" width="15" height="15" fill="#FEF3C7" stroke="#F59E0B" stroke-width="1" rx="2" stroke-dasharray="3,2"/>
<text x="340" y="0" font-family="Arial, sans-serif" font-size="11" fill="#4B5563">Your Contribution Space</text>
<text x="500" y="0" font-family="Arial, sans-serif" font-size="11" fill="#4B5563">All compile to single optimized binary</text>
</g>
<!-- Philosophy Note -->
<text x="450" y="650" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-style="italic" fill="#6B7280">gbapp virtual crates: The bridge between old Node.js packages and new Rust modules</text>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -9,7 +9,7 @@ This guide covers building BotServer from source, including dependencies, featur
- **Operating System**: Linux, macOS, or Windows - **Operating System**: Linux, macOS, or Windows
- **Rust**: 1.70 or later (2021 edition) - **Rust**: 1.70 or later (2021 edition)
- **Memory**: 4GB RAM minimum (8GB recommended) - **Memory**: 4GB RAM minimum (8GB recommended)
- **Disk Space**: 2GB for dependencies and build artifacts - **Disk Space**: 8GB for development environment
### Install Rust ### Install Rust
@ -412,6 +412,17 @@ Find duplicate dependencies:
cargo tree --duplicates cargo tree --duplicates
``` ```
### Security Audit
Run security audit to check for known vulnerabilities in dependencies:
```bash
cargo install cargo-audit
cargo audit
```
This should be run regularly during development to ensure dependencies are secure.
## Build Artifacts ## Build Artifacts
After a successful release build, you'll have: After a successful release build, you'll have:

View file

@ -0,0 +1,354 @@
# Example: Creating a New gbapp Virtual Crate
This guide walks through creating a new gbapp virtual crate called `analytics` that adds analytics capabilities to BotServer.
## Step 1: Create the Module Structure
Create your gbapp directory in `src/`:
```
src/analytics/ # analytics.gbapp virtual crate
├── mod.rs # Module definition
├── keywords.rs # BASIC keywords
├── services.rs # Core functionality
├── models.rs # Data structures
└── tests.rs # Unit tests
```
## Step 2: Define the Module
**src/analytics/mod.rs**
```rust
//! Analytics gbapp - Provides analytics and reporting functionality
//!
//! This virtual crate adds analytics keywords to BASIC and provides
//! services for tracking and reporting bot interactions.
pub mod keywords;
pub mod services;
pub mod models;
#[cfg(test)]
mod tests;
use crate::shared::state::AppState;
use std::sync::Arc;
/// Initialize the analytics gbapp
pub fn init(state: Arc<AppState>) -> Result<(), Box<dyn std::error::Error>> {
log::info!("Initializing analytics.gbapp virtual crate");
// Initialize analytics services
services::init_analytics_service(&state)?;
Ok(())
}
```
## Step 3: Add BASIC Keywords
**src/analytics/keywords.rs**
```rust
use crate::shared::state::AppState;
use rhai::{Engine, Dynamic};
use std::sync::Arc;
/// Register analytics keywords with the BASIC interpreter
pub fn register_keywords(engine: &mut Engine, state: Arc<AppState>) {
let state_clone = state.clone();
// TRACK EVENT keyword
engine.register_fn("TRACK EVENT", move |event_name: String, properties: String| -> String {
let result = tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(async {
crate::analytics::services::track_event(&state_clone, &event_name, &properties).await
})
});
match result {
Ok(_) => format!("Event '{}' tracked", event_name),
Err(e) => format!("Failed to track event: {}", e),
}
});
// GET ANALYTICS keyword
engine.register_fn("GET ANALYTICS", move |metric: String, timeframe: String| -> Dynamic {
let result = tokio::task::block_in_place(|| {
tokio::runtime::Handle::current().block_on(async {
crate::analytics::services::get_analytics(&metric, &timeframe).await
})
});
match result {
Ok(data) => Dynamic::from(data),
Err(_) => Dynamic::UNIT,
}
});
// GENERATE REPORT keyword
engine.register_fn("GENERATE REPORT", move |report_type: String| -> String {
// Use LLM to generate natural language report
let data = crate::analytics::services::get_report_data(&report_type);
let prompt = format!(
"Generate a {} report from this data: {}",
report_type, data
);
// This would call the LLM service
format!("Report generated for: {}", report_type)
});
}
```
## Step 4: Implement Services
**src/analytics/services.rs**
```rust
use crate::shared::state::AppState;
use crate::shared::models::AnalyticsEvent;
use std::sync::Arc;
use anyhow::Result;
/// Initialize analytics service
pub fn init_analytics_service(state: &Arc<AppState>) -> Result<()> {
// Set up database tables, connections, etc.
log::debug!("Analytics service initialized");
Ok(())
}
/// Track an analytics event
pub async fn track_event(
state: &Arc<AppState>,
event_name: &str,
properties: &str,
) -> Result<()> {
// Store event in database
let conn = state.conn.get()?;
// Implementation details...
log::debug!("Tracked event: {}", event_name);
Ok(())
}
/// Get analytics data
pub async fn get_analytics(metric: &str, timeframe: &str) -> Result<String> {
// Query analytics data
let results = match metric {
"user_count" => get_user_count(timeframe).await?,
"message_volume" => get_message_volume(timeframe).await?,
"engagement_rate" => get_engagement_rate(timeframe).await?,
_ => return Err(anyhow::anyhow!("Unknown metric: {}", metric)),
};
Ok(results)
}
/// Get data for report generation
pub fn get_report_data(report_type: &str) -> String {
// Gather data based on report type
match report_type {
"daily" => get_daily_report_data(),
"weekly" => get_weekly_report_data(),
"monthly" => get_monthly_report_data(),
_ => "{}".to_string(),
}
}
// Helper functions
async fn get_user_count(timeframe: &str) -> Result<String> {
// Implementation
Ok("100".to_string())
}
async fn get_message_volume(timeframe: &str) -> Result<String> {
// Implementation
Ok("5000".to_string())
}
async fn get_engagement_rate(timeframe: &str) -> Result<String> {
// Implementation
Ok("75%".to_string())
}
fn get_daily_report_data() -> String {
// Gather daily metrics
r#"{"users": 100, "messages": 1500, "sessions": 50}"#.to_string()
}
fn get_weekly_report_data() -> String {
// Gather weekly metrics
r#"{"users": 500, "messages": 8000, "sessions": 300}"#.to_string()
}
fn get_monthly_report_data() -> String {
// Gather monthly metrics
r#"{"users": 2000, "messages": 35000, "sessions": 1200}"#.to_string()
}
```
## Step 5: Define Data Models
**src/analytics/models.rs**
```rust
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
#[derive(Debug, Serialize, Deserialize)]
pub struct AnalyticsEvent {
pub id: uuid::Uuid,
pub event_name: String,
pub properties: serde_json::Value,
pub user_id: Option<String>,
pub session_id: String,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MetricSnapshot {
pub metric_name: String,
pub value: f64,
pub timestamp: DateTime<Utc>,
pub dimensions: serde_json::Value,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Report {
pub report_type: String,
pub generated_at: DateTime<Utc>,
pub data: serde_json::Value,
pub summary: String,
}
```
## Step 6: Register with Core
Update `src/basic/keywords/mod.rs` to include your gbapp:
```rust
use crate::analytics;
pub fn register_all_keywords(engine: &mut Engine, state: Arc<AppState>) {
// ... existing keywords
// Register analytics.gbapp keywords
analytics::keywords::register_keywords(engine, state.clone());
}
```
Update `src/main.rs` or initialization code:
```rust
// Initialize analytics gbapp
analytics::init(state.clone())?;
```
## Step 7: Add Tests
**src/analytics/tests.rs**
```rust
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_track_event() {
// Test event tracking
let event_name = "user_login";
let properties = r#"{"user_id": "123"}"#;
// Test implementation
assert!(true);
}
#[tokio::test]
async fn test_get_analytics() {
// Test analytics retrieval
let metric = "user_count";
let timeframe = "daily";
// Test implementation
assert!(true);
}
}
```
## Step 8: Use in BASIC Scripts
Now your gbapp keywords are available in BASIC:
```basic
' Track user actions
TRACK EVENT "button_clicked", "button=submit"
' Get metrics
daily_users = GET ANALYTICS "user_count", "daily"
TALK "Daily active users: " + daily_users
' Generate AI-powered report
report = GENERATE REPORT "weekly"
TALK report
' Combine with LLM for insights
metrics = GET ANALYTICS "all", "monthly"
insights = LLM "Analyze these metrics and provide insights: " + metrics
TALK insights
```
## Step 9: Add Feature Flag (Optional)
If your gbapp should be optional, add it to `Cargo.toml`:
```toml
[features]
analytics = []
# Include in default features if always needed
default = ["ui-server", "chat", "analytics"]
```
Then conditionally compile:
```rust
#[cfg(feature = "analytics")]
pub mod analytics;
#[cfg(feature = "analytics")]
analytics::keywords::register_keywords(engine, state.clone());
```
## Benefits of This Approach
1. **Clean Separation**: Your gbapp is self-contained
2. **Easy Discovery**: Visible in `src/analytics/`
3. **Type Safety**: Rust compiler checks everything
4. **Native Performance**: Compiles into the main binary
5. **Familiar Structure**: Like the old `.gbapp` packages
## Best Practices
✅ **DO:**
- Keep your gbapp focused on one domain
- Provide clear BASIC keywords
- Use LLM for complex logic
- Write comprehensive tests
- Document your keywords
❌ **DON'T:**
- Create overly complex implementations
- Duplicate existing functionality
- Skip error handling
- Forget about async/await
- Ignore the BASIC-first philosophy
## Summary
Creating a gbapp virtual crate is straightforward:
1. Create a module in `src/`
2. Define keywords for BASIC
3. Implement services
4. Register with core
5. Use in BASIC scripts
Your gbapp becomes part of BotServer's compiled binary, providing native performance while maintaining the conceptual clarity of the package system. Most importantly, remember that the implementation should be minimal - let BASIC + LLM handle the complexity!

View file

@ -0,0 +1,279 @@
# The gbapp Philosophy: Let Machines Do Machine Work
## Core Principle: Automation First
In 2025, the gbapp philosophy is simple and powerful:
**"If a machine can do the work, let it do the work."**
## The Hierarchy of Development
### 1. LLM First (90% of cases)
Let AI write the code for you:
```basic
' Don't write complex logic - describe what you want
result = LLM "Generate a function that validates email addresses and returns true/false: " + email
```
### 2. BASIC for Flow Control (9% of cases)
Use BASIC only for orchestration:
```basic
' BASIC is just glue between AI calls
data = GET "api/data"
processed = LLM "Process this: " + data
SET "results", processed
```
### 3. Rust for Core Only (1% of cases)
Write Rust only when:
- Contributing new keywords to core
- Building fundamental infrastructure
- Optimizing critical performance paths
## What gbapp Really Is
**gbapp is NOT:**
- ❌ External plugin packages
- ❌ Separate npm modules
- ❌ A way to bypass BASIC
- ❌ Runtime extensions
**gbapp IS:**
- ✅ Virtual crates inside `src/`
- ✅ Rust modules that compile together
- ✅ The bridge between old and new thinking
- ✅ A familiar mental model for contributions
- ✅ A mindset: "Code through automation"
## Real-World Examples
### Wrong Approach (Old Thinking)
```javascript
// 500 lines of custom Node.js, Python or C# code for data validation
function validateComplexBusinessRules(data) {
// ... hundreds of lines of logic
}
```
### Right Approach (2025 Reality)
```basic
' 3 lines - let AI handle complexity
rules = GET "business-rules.txt"
validation = LLM "Validate this data against these rules: " + data + " Rules: " + rules
IF validation CONTAINS "valid" THEN TALK "Approved" ELSE TALK "Rejected: " + validation
```
## The Multi-SDK Reality
You don't need separate SDKs or plugins. Everything integrates through BASIC + LLM:
### Integrating Any API
```basic
' No SDK needed - just describe what you want
data = GET "https://server/data"
answer = LLM "Do a good report from this json: " + data
TALK data
```
### Working with Any Database
```basic
' No ORM needed - AI understands SQL
results = FIND "users", "all users who logged in today"
```
### Processing Any Format
```basic
' No parser library needed
xml_data = GET "complex.xml"
json = LLM "Convert this XML to JSON: " + xml_data
SET BOT MEMORY "processed_data", json
```
## When to Write Code
### Use LLM When:
- Processing unstructured data
- Implementing business logic
- Transforming between formats
- Making decisions
- Generating content
- Analyzing patterns
- **Basically: 90% of everything**
### Use BASIC When:
- Orchestrating AI calls
- Simple flow control
- Managing state
- Connecting systems
- **Just the glue**
### Use Rust When:
- Building new keywords in your gbapp virtual crate
- Creating a new gbapp module in `src/`
- System-level optimization
- Contributing new features as gbapps
- **Only for core enhancements**
## The gbapp Mindset
Stop thinking about:
- "How do I code this?"
- "What library do I need?"
- "How do I extend the system?"
Start thinking about:
- "How do I describe this to AI?"
- "What's the simplest BASIC flow?"
- "How does this help everyone?"
## Examples of Getting Real
### Data Enrichment (Old Way)
```javascript
// 1000+ lines of code
// Multiple NPM packages
// Complex error handling
// Maintenance nightmare
```
### Data Enrichmentay)
```basic
items = FIND "companies", "needs_enrichment=true"
FOR EACH item IN items
website = WEBSITE OF item.company
page = GET website
enriched = LLM "Extract company info from: " + page
SET "companies", "id=" + item.id, "data=" + enriched
NEXT
```
### Report Generation (Old Way)
```python
# Custom reporting engine
# Template systems
# Complex formatting logic
# PDF libraries
```
### Report Generation (Get Real Way)
```basic
data = FIND "sales", "month=current"
report = LLM "Create executive summary from: " + data
CREATE SITE "report", "template", report
```
## The Ultimate Test
Before writing ANY code, ask yourself:
1. **Can LLM do this?** (Usually YES)
2. **Can BASIC orchestrate it?** (Almost always YES)
3. **Do I really need Rust?** (Almost never)
## Benefits of This Approach
### For Developers
- 100x faster development
- No dependency management
- No version conflicts
- No maintenance burden
- Focus on business logic, not implementation
### For Organizations
- Reduced complexity
- Lower maintenance costs
- Faster iterations
- No vendor lock-in
- Anyone can contribute
### For the Community
- Shared improvements benefit everyone
- No fragmentation
- Consistent experience
- Collective advancement
## The Future is Already Here
In 2025, this isn't aspirational - it's reality:
- **100% BASIC/LLM applications** are production-ready
- **Zero custom code** for most use cases
- **AI handles complexity** better than humans
- **Machines do machine work** while humans do human work
## Migration Path
### From Extensions to Virtual Crates
```
Old: node_modules/
└── my-plugin.gbapp/
├── index.js (500 lines)
├── package.json
└── complex logic
New: src/
└── my_feature/ # my_feature.gbapp (virtual crate)
├── mod.rs # 50 lines
└── keywords.rs # Register BASIC keywords
Plus: my-bot.gbdialog/
└── logic.bas (5 lines using LLM)
```
### From Code to Descriptions
```
Old: Write algorithm to process data
New: Describe what you want to LLM
```
### From Libraries to LLM
```
Old: Import 20 NPM packages
New: Single LLM call with description
```
## Get Real Guidelines
✅ **DO:**
- Describe problems to LLM
- Use BASIC as glue
- Contribute keywords to core
- Share your patterns
- Think automation-first
❌ **DON'T:**
- Write complex algorithms
- Build separate plugins
- Create custom frameworks
- Maintain separate codebases
- Fight the machine
## The Virtual Crate Architecture
Each gbapp is now a module in `src/`:
```
src/
├── core/ # core.gbapp
├── basic/ # basic.gbapp
├── channels/ # channels.gbapp
└── your_feature/ # your_feature.gbapp (your contribution!)
```
This elegant mapping preserves the conceptual model while leveraging Rust's power.
## Conclusion
gbapp in 2025 has evolved from external packages to virtual crates - Rust modules inside `src/` that compile into a single, optimized binary. This preserves the familiar mental model while delivering native performance.
The philosophy remains: machines are better at machine work. Your job is to describe what you want, not implement how to do it. The combination of BASIC + LLM eliminates the need for traditional programming in almost all cases.
## Examples Repository
See `/templates/` for real-world examples of 100% BASIC/LLM applications:
- CRM system: 50 lines of BASIC
- Email automation: 30 lines of BASIC
- Data pipeline: 20 lines of BASIC
- Report generator: 15 lines of BASIC
Each would have been thousands of lines in traditional code.

View file

@ -1,262 +1 @@
# Prompt Manager # Prompt Manager
The Prompt Manager module provides centralized management of LLM prompts, templates, and system instructions used throughout BotServer.
## Overview
Located in `src/prompt_manager/`, this module maintains a library of reusable prompts that can be:
- Versioned and updated without code changes
- Customized per bot instance
- Composed dynamically based on context
- Optimized for different LLM models
## Architecture
```
src/prompt_manager/
├── mod.rs # Main module interface
├── prompts.csv # Default prompt library
└── templates/ # Complex prompt templates
├── system.md # System instructions
├── tools.md # Tool-use prompts
└── context.md # Context formatting
```
## Prompt Library Format
The `prompts.csv` file stores prompts in a structured format:
```csv
id,category,name,content,model,version
1,system,default,"You are a helpful assistant...",gpt-4,1.0
2,tools,function_call,"To use a tool, follow this format...",any,1.0
3,context,kb_search,"Search the knowledge base for: {query}",any,1.0
```
### Fields
| Field | Description |
|-------|-------------|
| `id` | Unique identifier |
| `category` | Prompt category (system, tools, context, etc.) |
| `name` | Prompt name for retrieval |
| `content` | The actual prompt text with placeholders |
| `model` | Target model or "any" for universal |
| `version` | Version for tracking changes |
## Usage in BASIC
Prompts are automatically loaded and can be referenced in dialogs:
```basic
' For background processing only - not for interactive conversations
' Generate content for storage
summary = LLM "Use prompt: customer_service"
SET BOT MEMORY "service_info", summary
' For interactive conversations, use SET CONTEXT
SET CONTEXT "support_issue", issue
TALK "How can I help you with your technical issue?"
```
## Rust API
### Loading Prompts
```rust
use crate::prompt_manager::PromptManager;
let manager = PromptManager::new();
manager.load_from_csv("prompts.csv")?;
```
### Retrieving Prompts
```rust
// Get a specific prompt
let prompt = manager.get_prompt("system", "default")?;
// Get prompt with variable substitution
let mut vars = HashMap::new();
vars.insert("query", "user question");
let formatted = manager.format_prompt("context", "kb_search", vars)?;
```
### Dynamic Composition
```rust
// Compose multiple prompts
let system = manager.get_prompt("system", "default")?;
let tools = manager.get_prompt("tools", "available")?;
let context = manager.get_prompt("context", "current")?;
let full_prompt = manager.compose(vec![system, tools, context])?;
```
## Prompt Categories
### System Prompts
Define the AI assistant's role and behavior:
- `default`: Standard helpful assistant
- `professional`: Business-focused responses
- `technical`: Developer-oriented assistance
- `creative`: Creative writing and ideation
### Tool Prompts
Instructions for tool usage:
- `function_call`: How to invoke functions
- `parameter_format`: Parameter formatting rules
- `error_handling`: Tool error responses
### Context Prompts
Templates for providing context:
- `kb_search`: Knowledge base query format
- `conversation_history`: Previous message format
- `user_context`: User information format
### Guardrail Prompts
Safety and compliance instructions:
- `content_filter`: Inappropriate content handling
- `pii_protection`: Personal data protection
- `compliance`: Regulatory compliance rules
## Custom Prompts
Bots can override default prompts by providing their own:
```
mybot.gbai/
└── mybot.gbot/
├── config.csv
└── prompts.csv # Custom prompts override defaults
```
## Model-Specific Optimization
Prompts can be optimized for different models:
```csv
id,category,name,content,model,version
1,system,default,"You are Claude...",claude-3,1.0
2,system,default,"You are GPT-4...",gpt-4,1.0
3,system,default,"You are a helpful assistant",llama-3,1.0
```
The manager automatically selects the best match for the current model.
## Variables and Placeholders
Prompts support variable substitution using `{variable}` syntax:
```
"Search for {query} in {collection} and return {limit} results"
```
Variables are replaced at runtime:
```rust
let vars = hashmap!{
"query" => "pricing information",
"collection" => "docs",
"limit" => "5"
};
let prompt = manager.format_prompt("search", "template", vars)?;
```
## Prompt Versioning
Track prompt evolution:
```csv
id,category,name,content,model,version
1,system,default,"Original prompt...",gpt-4,1.0
2,system,default,"Updated prompt...",gpt-4,1.1
3,system,default,"Latest prompt...",gpt-4,2.0
```
The manager uses the latest version by default but can retrieve specific versions:
```rust
let prompt = manager.get_prompt_version("system", "default", "1.0")?;
```
## Performance Optimization
### Caching
Frequently used prompts are cached in memory:
```rust
manager.cache_prompt("system", "default");
```
### Token Counting
Estimate token usage before sending:
```rust
let tokens = manager.estimate_tokens(prompt, "gpt-4")?;
if tokens > MAX_TOKENS {
prompt = manager.compress_prompt(prompt, MAX_TOKENS)?;
}
```
### Compression
Automatically compress prompts while maintaining meaning:
```rust
let compressed = manager.compress_prompt(original, target_tokens)?;
```
## Best Practices
1. **Modularity**: Keep prompts focused on single responsibilities
2. **Versioning**: Always version prompts for rollback capability
3. **Testing**: Test prompts across different models
4. **Documentation**: Document the purpose and expected output
5. **Variables**: Use placeholders for dynamic content
6. **Optimization**: Tailor prompts to specific model capabilities
## Integration with BASIC
The Prompt Manager is automatically available in BASIC dialogs:
```basic
' Load custom prompt library
LOAD_PROMPTS "custom_prompts.csv"
' For background processing - generate content once
greeting = LLM PROMPT("customer_greeting")
SET BOT MEMORY "standard_greeting", greeting
' For interactive conversations with variables
SET CONTEXT "customer_name", customer_name
SET CONTEXT "support_ticket", support_ticket
TALK "Let me help you with your support request."
```
## Monitoring and Analytics
Track prompt performance:
```rust
// Log prompt usage
manager.log_usage("system", "default", response_quality);
// Get analytics
let stats = manager.get_prompt_stats("system", "default")?;
println!("Success rate: {}%", stats.success_rate);
println!("Avg response time: {}ms", stats.avg_latency);
```
## Error Handling
Handle missing or invalid prompts gracefully:
```rust
match manager.get_prompt("custom", "missing") {
Ok(prompt) => use_prompt(prompt),
Err(PromptError::NotFound) => use_default(),
Err(PromptError::Invalid) => log_and_fallback(),
Err(e) => return Err(e),
}
```

View file

@ -1,42 +1,111 @@
## gbot Reference # Bot Configuration
`config.csv` defines the bots behaviour and parameters.
This chapter covers bot configuration through the `config.csv` file system. Each bot's behavior is controlled by a simple CSV configuration file in its `.gbot` package.
## Configuration System
BotServer uses a straightforward name-value CSV format for configuration:
```csv ```csv
# config.csv Bot configuration name,value
bot_name,GeneralBot setting_name,setting_value
language,en another_setting,another_value
theme,default.gbtheme
knowledge_base,default.gbkb
max_context_tokens,2048
``` ```
### Key Columns ## File Location
- **bot_name** Display name of the bot.
- **language** Locale for formatting (used by `FORMAT`).
- **theme** UI theme package (`.gbtheme`).
- **knowledge_base** Default knowledgebase package (`.gbkb`).
- **max_context_tokens** Maximum number of tokens retained in the session context.
- **max_context_tokens** Limit for the amount of context sent to the LLM.
### Editing the Configuration ```
The file is a simple CSV; each line is `key,value`. Comments start with `#`. After editing, restart the server to apply changes. mybot.gbai/
└── mybot.gbot/
└── config.csv
```
### Runtime Effects ## Configuration Categories
- Changing **theme** updates the UI served from `web/static/`.
- Modifying **knowledge_base** switches the vector collection used for semantic search.
- Adjusting **answer_mode** influences the order of tool invocation and LLM calls.
For advanced configuration, see `src/bot/config.rs` which parses this file into the `BotConfig` struct. ### Server Settings
- Web server binding and ports
- Site generation paths
- Service endpoints
### LLM Configuration
- Model paths (local GGUF files)
- Service URLs
- Cache settings
- Server parameters (when embedded)
### Prompt Management
- Context compaction levels
- History retention
- Token management
### Email Integration
- SMTP server settings
- Authentication credentials
- Sender configuration
### Theme Customization
- Color schemes
- Logo URLs
- Bot titles
### Custom Database
- External database connections
- Authentication details
## Key Features
### Simple Format
- Plain CSV with name-value pairs
- No complex syntax
- Human-readable
### Flexible Structure
- Empty rows for visual grouping
- Optional settings with defaults
- Extensible for custom needs
### Local-First
- Designed for local LLM models
- Self-hosted services
- No cloud dependency by default
## Example Configurations
### Minimal Setup
Just the essentials to run a bot:
```csv
name,value
llm-url,http://localhost:8081
llm-model,../../../../data/llm/model.gguf
```
### Production Setup
Full configuration with all services:
```csv
name,value
,
server_host,0.0.0.0
server_port,8080
,
llm-url,http://localhost:8081
llm-model,../../../../data/llm/production-model.gguf
llm-cache,true
,
email-server,smtp.company.com
email-from,bot@company.com
,
theme-title,Company Assistant
```
## Configuration Philosophy
1. **Defaults Work**: Most settings have sensible defaults
2. **Local First**: Assumes local services, not cloud APIs
3. **Simple Values**: All values are strings, parsed as needed
4. **No Magic**: What you see is what you get
## See Also ## See Also
- [config.csv Reference](./config-csv.md) - Complete configuration options - [config.csv Format](./config-csv.md) - Complete reference
- [PostgreSQL Setup](./postgresql.md) - Database configuration - [LLM Configuration](./llm-config.md) - Language model settings
- [MinIO Storage](./minio.md) - Object storage setup - [Parameters](./parameters.md) - All available parameters
- [Qdrant Vector DB](./qdrant.md) - Vector database configuration
- [Valkey Cache](./valkey.md) - Caching layer setup
- [Chapter 2: .gbot](../chapter-02/gbot.md) - Bot configuration package
- [Chapter 3: Knowledge Base](../chapter-03/README.md) - KB configuration
- [Chapter 5: BASIC Reference](../chapter-05/README.md) - Script configuration
- [Chapter 9: Storage](../chapter-09/storage.md) - Storage architecture
- [Chapter 11: Infrastructure](../chapter-11/README.md) - Complete infrastructure guide

View file

@ -1 +0,0 @@
# Answer Modes

View file

@ -1,263 +1,243 @@
# config.csv Format # config.csv Format
The `config.csv` file is the central configuration for each bot instance. Located in the `.gbot` package directory, it controls all bot behavior, integrations, and system settings. The `config.csv` file is the central configuration for each bot, located in the `.gbot` package. It uses a simple name-value pair format.
## File Location ## File Format
```
mybot.gbai/
└── mybot.gbot/
└── config.csv
```
## Format
Configuration uses simple CSV format with two columns: `key` and `value`.
```csv ```csv
key,value name,value
botId,00000000-0000-0000-0000-000000000000 setting_name,setting_value
title,My Bot Name another_setting,another_value
description,Bot description here
``` ```
## Core Settings - **Empty rows** are used for visual grouping
- **No quotes** needed for string values
- **Case-sensitive** names
### Bot Identity ## Core Server Settings
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `botId` | Unique bot identifier (UUID) | Generated | `00000000-0000-0000-0000-000000000000` |
| `title` | Bot display name | Required | `Customer Support Bot` |
| `description` | Bot description | Empty | `Handles customer inquiries` |
| `logoUrl` | Bot avatar/logo URL | Empty | `https://example.com/logo.png` |
| `welcomeMessage` | Initial greeting | Empty | `Hello! How can I help you today?` |
### LLM Configuration
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `llm-model` | Model path or name | Local model | `../../../../data/llm/model.gguf` |
| `llm-key` | API key (if using external) | `none` | `sk-...` for external APIs |
| `llm-url` | LLM endpoint URL | `http://localhost:8081` | Local or external endpoint |
| `llm-cache` | Enable LLM caching | `false` | `true` |
| `llm-cache-ttl` | Cache time-to-live (seconds) | `3600` | `7200` |
### Knowledge Base
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `qdrantUrl` | Vector database URL | `http://localhost:6333` | `http://qdrant:6333` |
| `qdrantApiKey` | Qdrant API key | Empty | `your-api-key` |
| `embeddingModel` | Model for embeddings | `text-embedding-ada-002` | `all-MiniLM-L6-v2` |
| `chunkSize` | Text chunk size | `1000` | `500` |
| `chunkOverlap` | Overlap between chunks | `200` | `100` |
| `topK` | Number of search results | `5` | `10` |
### Storage Configuration
### Server Configuration ### Server Configuration
```csv
| Key | Description | Default | Example | server_host,0.0.0.0
|-----|-------------|---------|---------| server_port,8080
| `server_host` | Server bind address | `0.0.0.0` | `localhost` | sites_root,/tmp
| `server_port` | Server port | `8080` | `3000` |
| `sites_root` | Sites root directory | `/tmp` | `/var/www` |
| `mcp-server` | Enable MCP server | `false` | `true` |
### Database
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `databaseUrl` | PostgreSQL connection | Required | `postgresql://user:pass@localhost/botdb` |
| `maxConnections` | Connection pool size | `10` | `25` |
| `connectionTimeout` | Timeout in seconds | `30` | `60` |
### Email Integration
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `smtpHost` | SMTP server | Empty | `smtp.gmail.com` |
| `smtpPort` | SMTP port | `587` | `465` |
| `smtpUser` | Email username | Empty | `bot@example.com` |
| `smtpPassword` | Email password | Empty | `app-specific-password` |
| `smtpFrom` | From address | Empty | `noreply@example.com` |
| `smtpUseTls` | Use TLS | `true` | `false` |
### Calendar Integration
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `calendarEnabled` | Enable calendar features | `false` | `true` |
| `calendarProvider` | Calendar service | `google` | `microsoft`, `caldav` |
| `calendarApiKey` | Calendar API key | Empty | `your-api-key` |
| `workingHoursStart` | Business hours start | `09:00` | `08:30` |
| `workingHoursEnd` | Business hours end | `17:00` | `18:00` |
| `timezone` | Default timezone | `UTC` | `America/New_York` |
### Authentication
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `authEnabled` | Require authentication | `false` | `true` |
| `authProvider` | Auth provider | `local` | `oauth`, `saml`, `ldap` |
| `authClientId` | OAuth client ID | Empty | `client-id` |
| `authClientSecret` | OAuth secret | Empty | `client-secret` |
| `authCallbackUrl` | OAuth callback | Empty | `https://bot.example.com/auth/callback` |
| `jwtSecret` | JWT signing secret | Generated | `your-secret-key` |
| `sessionTimeout` | Session duration (min) | `1440` | `60` |
### Channel Configuration
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `webEnabled` | Enable web interface | `true` | `false` |
| `whatsappEnabled` | Enable WhatsApp | `false` | `true` |
| `whatsappToken` | WhatsApp API token | Empty | `EAAI...` |
| `whatsappPhoneId` | WhatsApp phone ID | Empty | `123456789` |
| `teamsEnabled` | Enable MS Teams | `false` | `true` |
| `teamsAppId` | Teams app ID | Empty | `app-id` |
| `teamsAppPassword` | Teams app password | Empty | `app-password` |
| `slackEnabled` | Enable Slack | `false` | `true` |
| `slackToken` | Slack bot token | Empty | `xoxb-...` |
### Security
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `corsOrigins` | Allowed CORS origins | `*` | `https://example.com` |
| `rateLimitPerMinute` | API rate limit | `60` | `100` |
| `maxFileSize` | Max upload size (MB) | `10` | `50` |
| `allowedFileTypes` | Permitted file types | `pdf,doc,txt` | `*` |
| `encryptionKey` | Data encryption key | Generated | `base64-key` |
| `requireHttps` | Force HTTPS | `false` | `true` |
### Monitoring
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `metricsEnabled` | Enable metrics | `false` | `true` |
| `metricsEndpoint` | Metrics endpoint | `/metrics` | `/admin/metrics` |
| `loggingLevel` | Log level | `info` | `debug`, `warn`, `error` |
| `logToFile` | Log to file | `false` | `true` |
| `logFilePath` | Log file location | `./logs` | `/var/log/botserver` |
| `sentryDsn` | Sentry error tracking | Empty | `https://...@sentry.io/...` |
### Advanced Features
| Key | Description | Default | Example |
|-----|-------------|---------|---------|
| `webAutomationEnabled` | Enable web scraping | `false` | `true` |
| `ocrEnabled` | Enable OCR | `false` | `true` |
| `speechEnabled` | Enable speech | `false` | `true` |
| `translationEnabled` | Enable translation | `false` | `true` |
| `cacheEnabled` | Enable cache component | `false` | `true` |
| `cacheUrl` | Cache URL | `redis://localhost:6379` | `redis://cache:6379` |
## Environment Variable Override
Any config value can be overridden using environment variables:
```bash
# Override LLM model
export BOT_LLM_MODEL=gpt-4-turbo
# Override database URL
export BOT_DATABASE_URL=postgresql://prod@db/botserver
``` ```
## Multiple Bots Configuration | Name | Description | Default | Example |
|------|-------------|---------|---------|
| `server_host` | Bind address for the web server | `0.0.0.0` | `0.0.0.0` |
| `server_port` | Port for the web interface | `8080` | `8080` |
| `sites_root` | Directory for generated sites | `/tmp` | `/tmp` |
Each bot has its own `config.csv`. The system loads all bot configurations on startup: ## LLM Configuration
``` ### LLM Connection
templates/ ```csv
├── support.gbai/ llm-key,none
│ └── support.gbot/ llm-url,http://localhost:8081
│ └── config.csv # Support bot config llm-model,../../../../data/llm/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf
├── sales.gbai/
│ └── sales.gbot/
│ └── config.csv # Sales bot config
└── default.gbai/
└── default.gbot/
└── config.csv # Default bot config
``` ```
## Configuration Validation | Name | Description | Default | Example |
|------|-------------|---------|---------|
| `llm-key` | API key for LLM service | `none` | `none` or API key |
| `llm-url` | LLM service endpoint | `http://localhost:8081` | `http://localhost:8081` |
| `llm-model` | Path to GGUF model file | Model path | `../../../../data/llm/model.gguf` |
The system validates configuration on startup: ### LLM Cache Settings
- Required fields must be present ```csv
- UUIDs must be valid format llm-cache,false
- URLs must be reachable llm-cache-ttl,3600
- API keys are tested llm-cache-semantic,true
- File paths must exist llm-cache-threshold,0.95
```
## Hot Reload | Name | Description | Default | Example |
|------|-------------|---------|---------|
| `llm-cache` | Enable response caching | `false` | `true` or `false` |
| `llm-cache-ttl` | Cache TTL in seconds | `3600` | `3600` |
| `llm-cache-semantic` | Enable semantic similarity caching | `true` | `true` or `false` |
| `llm-cache-threshold` | Similarity threshold (0-1) | `0.95` | `0.95` |
Changes to `config.csv` can be reloaded without restart: ### LLM Server Settings (when running embedded)
1. Edit the file ```csv
2. Call `/api/admin/reload-config` endpoint llm-server,false
3. Or use the admin UI reload button llm-server-path,botserver-stack/bin/llm/build/bin
llm-server-host,0.0.0.0
llm-server-port,8081
llm-server-gpu-layers,0
llm-server-n-moe,0
llm-server-ctx-size,4096
llm-server-n-predict,1024
llm-server-parallel,6
llm-server-cont-batching,true
llm-server-mlock,false
llm-server-no-mmap,false
```
## Security Best Practices | Name | Description | Default |
|------|-------------|---------|
| `llm-server` | Run embedded LLM server | `false` |
| `llm-server-path` | Path to LLM server binaries | `botserver-stack/bin/llm/build/bin` |
| `llm-server-host` | LLM server bind address | `0.0.0.0` |
| `llm-server-port` | LLM server port | `8081` |
| `llm-server-gpu-layers` | GPU layers to offload | `0` |
| `llm-server-n-moe` | Number of MoE experts | `0` |
| `llm-server-ctx-size` | Context size in tokens | `4096` |
| `llm-server-n-predict` | Max prediction tokens | `1024` |
| `llm-server-parallel` | Parallel requests | `6` |
| `llm-server-cont-batching` | Continuous batching | `true` |
| `llm-server-mlock` | Lock model in memory | `false` |
| `llm-server-no-mmap` | Disable memory mapping | `false` |
1. **Never commit API keys** - Use environment variables ## Prompt Settings
2. **Encrypt sensitive values** - Use `encryptionKey` setting
3. **Rotate credentials regularly** - Update keys monthly
4. **Use strong JWT secrets** - At least 32 characters
5. **Restrict CORS origins** - Don't use `*` in production
6. **Enable HTTPS** - Set `requireHttps=true`
7. **Set rate limits** - Prevent abuse
8. **Monitor access** - Enable logging and metrics
## Troubleshooting
### Bot Won't Start
- Check required fields are set
- Verify database connection
- Ensure bot ID is unique
### LLM Not Responding
- Verify API key is valid
- Check endpoint URL
- Test rate limits
### Storage Issues
- Verify drive is running
- Check access credentials
- Test bucket permissions
### Authentication Problems
- Verify JWT secret matches
- Check session timeout
- Test OAuth callback URL
## Example Configuration
Complete example for a production bot:
```csv ```csv
key,value prompt-compact,4
botId,a1b2c3d4-e5f6-7890-abcd-ef1234567890 prompt-history,2
title,Customer Support Assistant
description,24/7 automated customer support
welcomeMessage,Hello! I'm here to help with any questions.
llmModel,gpt-4
llmApiKey,${LLM_API_KEY}
llmTemperature,0.3
databaseUrl,${DATABASE_URL}
minioEndpoint,storage.example.com
minioAccessKey,${MINIO_ACCESS}
minioSecretKey,${MINIO_SECRET}
minioBucket,support-bot
minioUseSsl,true
authEnabled,true
authProvider,oauth
authClientId,${OAUTH_CLIENT_ID}
authClientSecret,${OAUTH_CLIENT_SECRET}
corsOrigins,https://app.example.com
requireHttps,true
loggingLevel,info
metricsEnabled,true
cacheEnabled,true
cacheUrl,redis://cache:6379
``` ```
| Name | Description | Default | Example |
|------|-------------|---------|---------|
| `prompt-compact` | Context compaction level | `4` | `4` |
| `prompt-history` | Messages to keep in history | Not set | `2` |
## Embedding Configuration
```csv
embedding-url,http://localhost:8082
embedding-model,../../../../data/llm/bge-small-en-v1.5-f32.gguf
```
| Name | Description | Default |
|------|-------------|---------|
| `embedding-url` | Embedding service endpoint | `http://localhost:8082` |
| `embedding-model` | Path to embedding model | Model path |
## Email Configuration
```csv
email-from,from@domain.com
email-server,mail.domain.com
email-port,587
email-user,user@domain.com
email-pass,
```
| Name | Description | Example |
|------|-------------|---------|
| `email-from` | Sender email address | `noreply@example.com` |
| `email-server` | SMTP server hostname | `smtp.gmail.com` |
| `email-port` | SMTP port | `587` |
| `email-user` | SMTP username | `user@example.com` |
| `email-pass` | SMTP password | Password (empty if not set) |
## Theme Configuration
```csv
theme-color1,#0d2b55
theme-color2,#fff9c2
theme-logo,https://pragmatismo.com.br/icons/general-bots.svg
theme-title,Announcements General Bots
```
| Name | Description | Example |
|------|-------------|---------|
| `theme-color1` | Primary theme color | `#0d2b55` |
| `theme-color2` | Secondary theme color | `#fff9c2` |
| `theme-logo` | Logo URL | `https://example.com/logo.svg` |
| `theme-title` | Bot display title | `My Bot` |
## Custom Database
```csv
custom-server,localhost
custom-port,5432
custom-database,mycustomdb
custom-username,
custom-password,
```
| Name | Description | Example |
|------|-------------|---------|
| `custom-server` | Database server | `localhost` |
| `custom-port` | Database port | `5432` |
| `custom-database` | Database name | `mydb` |
| `custom-username` | Database user | Username |
| `custom-password` | Database password | Password |
## MCP Server
```csv
mcp-server,false
```
| Name | Description | Default |
|------|-------------|---------|
| `mcp-server` | Enable MCP server | `false` |
## Complete Example
### Minimal Configuration
```csv
name,value
server_port,8080
llm-url,http://localhost:8081
llm-model,../../../../data/llm/model.gguf
```
### Production Configuration
```csv
name,value
,
server_host,0.0.0.0
server_port,443
sites_root,/var/www/sites
,
llm-key,sk-...
llm-url,https://api.openai.com
llm-model,gpt-4
,
llm-cache,true
llm-cache-ttl,7200
,
email-from,bot@company.com
email-server,smtp.company.com
email-port,587
email-user,bot@company.com
email-pass,secure_password
,
theme-title,Company Assistant
theme-color1,#003366
theme-color2,#ffffff
```
## Configuration Loading
1. Default values are applied first
2. `config.csv` values override defaults
3. Environment variables override config.csv (if implemented)
4. All values are strings - parsed as needed by the application
## Best Practices
✅ **DO:**
- Group related settings with empty rows
- Use descriptive values
- Keep sensitive data in environment variables when possible
- Test configuration changes in development first
❌ **DON'T:**
- Include quotes around values
- Use spaces around commas
- Leave trailing commas
- Include comments with # (use empty name field instead)
## Validation
The system validates:
- Required fields are present
- Port numbers are valid (1-65535)
- URLs are properly formatted
- File paths exist (for model files)
- Email settings are complete if email features are used

View file

@ -1,16 +1,10 @@
# LLM Configuration # LLM Configuration
Configure Large Language Model providers for bot conversations. BotServer prioritizes local models for privacy and cost-effectiveness. Configuration for Language Model integration in BotServer, supporting both local GGUF models and external API services.
## Overview ## Local Model Configuration
BotServer supports both local models (GGUF format) and cloud APIs. The default configuration uses local models running on your hardware. BotServer is designed to work with local GGUF models by default:
## Local Models (Default)
### Configuration
From `default.gbai/default.gbot/config.csv`:
```csv ```csv
llm-key,none llm-key,none
@ -18,13 +12,35 @@ llm-url,http://localhost:8081
llm-model,../../../../data/llm/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf llm-model,../../../../data/llm/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf
``` ```
### LLM Server Settings ### Model Path
The `llm-model` parameter accepts:
- **Relative paths**: `../../../../data/llm/model.gguf`
- **Absolute paths**: `/opt/models/model.gguf`
- **Model names**: When using external APIs like `gpt-4`
### Supported Model Formats
- **GGUF**: Quantized models for CPU/GPU inference
- **Q3_K_M, Q4_K_M, Q5_K_M**: Different quantization levels
- **F16, F32**: Full precision models
## LLM Server Configuration
### Running Embedded Server
BotServer can run its own LLM server:
```csv ```csv
llm-server,false llm-server,true
llm-server-path,botserver-stack/bin/llm/build/bin llm-server-path,botserver-stack/bin/llm/build/bin
llm-server-host,0.0.0.0 llm-server-host,0.0.0.0
llm-server-port,8081 llm-server-port,8081
```
### Server Performance Parameters
```csv
llm-server-gpu-layers,0 llm-server-gpu-layers,0
llm-server-ctx-size,4096 llm-server-ctx-size,4096
llm-server-n-predict,1024 llm-server-n-predict,1024
@ -32,136 +48,174 @@ llm-server-parallel,6
llm-server-cont-batching,true llm-server-cont-batching,true
``` ```
### Supported Local Models | Parameter | Description | Impact |
|-----------|-------------|---------|
| `llm-server-gpu-layers` | Layers to offload to GPU | 0 = CPU only, higher = more GPU |
| `llm-server-ctx-size` | Context window size | More context = more memory |
| `llm-server-n-predict` | Max tokens to generate | Limits response length |
| `llm-server-parallel` | Concurrent requests | Higher = more throughput |
| `llm-server-cont-batching` | Continuous batching | Improves multi-user performance |
- **DeepSeek-R1-Distill-Qwen** - Efficient reasoning model ### Memory Management
- **Llama-3** - Open source, high quality
- **Mistral** - Fast and capable
- **Phi-3** - Microsoft's small but powerful model
- **Qwen** - Multilingual support
### GPU Acceleration
```csv ```csv
llm-server-gpu-layers,33 # Number of layers to offload to GPU llm-server-mlock,false
llm-server-no-mmap,false
``` ```
Set to 0 for CPU-only operation. - **mlock**: Locks model in RAM (prevents swapping)
- **no-mmap**: Disables memory mapping (uses more RAM)
## Embeddings Configuration ## Cache Configuration
For semantic search and vector operations: ### Basic Cache Settings
```csv ```csv
embedding-url,http://localhost:8082 llm-cache,false
embedding-model,../../../../data/llm/bge-small-en-v1.5-f32.gguf
```
## Caching Configuration
Reduce latency and costs with intelligent caching:
```csv
llm-cache,true
llm-cache-ttl,3600 llm-cache-ttl,3600
```
Caching reduces repeated LLM calls for identical inputs.
### Semantic Cache
```csv
llm-cache-semantic,true llm-cache-semantic,true
llm-cache-threshold,0.95 llm-cache-threshold,0.95
``` ```
## Cloud Providers (Optional) Semantic caching matches similar (not just identical) queries:
- **threshold**: 0.95 = 95% similarity required
- Lower threshold = more cache hits but less accuracy
### External API Configuration ## External API Configuration
For cloud LLM services, configure: ### OpenAI-Compatible APIs
```csv ```csv
llm-key,your-api-key llm-key,sk-your-api-key
llm-url,https://api.provider.com/v1 llm-url,https://api.openai.com/v1
llm-model,model-name llm-model,gpt-4
``` ```
### Provider Examples ### Local API Servers
| Provider | URL | Model Examples | ```csv
|----------|-----|----------------| llm-key,none
| Local | http://localhost:8081 | GGUF models | llm-url,http://localhost:8081
| API Compatible | Various | Various models | llm-model,local-model-name
| Custom | Your endpoint | Your models | ```
## Configuration Examples
### Minimal Local Setup
```csv
name,value
llm-url,http://localhost:8081
llm-model,../../../../data/llm/model.gguf
```
### High-Performance Local
```csv
name,value
llm-server,true
llm-server-gpu-layers,32
llm-server-ctx-size,8192
llm-server-parallel,8
llm-server-cont-batching,true
llm-cache,true
llm-cache-semantic,true
```
### Low-Resource Setup
```csv
name,value
llm-server-ctx-size,2048
llm-server-n-predict,512
llm-server-parallel,2
llm-cache,false
llm-server-mlock,false
```
### External API
```csv
name,value
llm-key,sk-...
llm-url,https://api.anthropic.com
llm-model,claude-3
llm-cache,true
llm-cache-ttl,7200
```
## Performance Tuning ## Performance Tuning
### Context Size ### For Responsiveness
- Decrease `llm-server-ctx-size`
- Decrease `llm-server-n-predict`
- Enable `llm-cache`
- Enable `llm-cache-semantic`
```csv ### For Quality
llm-server-ctx-size,4096 # Maximum context window - Increase `llm-server-ctx-size`
prompt-compact,4 # Compact after N exchanges - Increase `llm-server-n-predict`
``` - Use higher quantization (Q5_K_M or F16)
- Disable semantic cache or increase threshold
### Parallel Processing ### For Multiple Users
- Enable `llm-server-cont-batching`
- Increase `llm-server-parallel`
- Enable caching
- Consider GPU offloading
```csv ## Model Selection Guidelines
llm-server-parallel,6 # Concurrent requests
llm-server-cont-batching,true # Continuous batching
```
### Memory Settings ### Small Models (1-3B parameters)
- Fast responses
- Low memory usage
- Good for simple tasks
- Example: `DeepSeek-R1-Distill-Qwen-1.5B`
```csv ### Medium Models (7-13B parameters)
llm-server-mlock,false # Lock model in memory - Balanced performance
llm-server-no-mmap,false # Disable memory mapping - Moderate memory usage
``` - Good general purpose
- Example: `Llama-2-7B`, `Mistral-7B`
## Model Selection Guide ### Large Models (30B+ parameters)
- Best quality
| Use Case | Recommended Model | Configuration | - High memory requirements
|----------|------------------|---------------| - Complex reasoning
| General chat | DeepSeek-R1-Distill | Default config | - Example: `Llama-2-70B`, `Mixtral-8x7B`
| Code assistance | Qwen-Coder | Increase context |
| Multilingual | Qwen-Multilingual | Add language params |
| Fast responses | Phi-3-mini | Reduce predict tokens |
| High accuracy | Llama-3-70B | Increase GPU layers |
## Monitoring
Check LLM server status:
```bash
curl http://localhost:8081/health
```
View model information:
```bash
curl http://localhost:8081/v1/models
```
## Troubleshooting ## Troubleshooting
### Model Not Loading ### Model Won't Load
- Check file path exists
1. Check file path is correct - Verify sufficient RAM
2. Verify GGUF format - Ensure compatible GGUF version
3. Ensure sufficient memory
4. Check GPU drivers (if using GPU)
### Slow Responses ### Slow Responses
- Reduce context size
- Enable caching
- Use GPU offloading
- Choose smaller model
1. Reduce context size ### Out of Memory
2. Enable GPU acceleration - Reduce `llm-server-ctx-size`
3. Use smaller model - Reduce `llm-server-parallel`
4. Enable caching - Use more quantized model (Q3 instead of Q5)
- Disable `llm-server-mlock`
### High Memory Usage ### Connection Refused
- Verify `llm-server` is true
1. Use quantized models (Q4, Q5) - Check port not in use
2. Reduce batch size - Ensure firewall allows connection
3. Enable memory mapping
4. Lower context size
## Best Practices ## Best Practices
1. **Start with local models** - Better privacy and no API costs 1. **Start Small**: Begin with small models and scale up
2. **Use appropriate model size** - Balance quality vs speed 2. **Use Caching**: Enable for production deployments
3. **Enable caching** - Reduce redundant computations 3. **Monitor Memory**: Watch RAM usage during operation
4. **Monitor resources** - Watch CPU/GPU/memory usage 4. **Test Thoroughly**: Verify responses before production
5. **Test different models** - Find the best fit for your use case 5. **Document Models**: Keep notes on model performance
6. **Version Control**: Track config.csv changes

View file

@ -1,295 +1,188 @@
# Bot Parameters # Configuration Parameters
Comprehensive reference for all bot configuration parameters available in `config.csv`. Complete reference of all available parameters in `config.csv`.
## Parameter Categories ## Server Parameters
Bot parameters are organized into functional groups for easier management and understanding. ### Web Server
| Parameter | Description | Default | Type |
|-----------|-------------|---------|------|
| `server_host` | Server bind address | `0.0.0.0` | IP address |
| `server_port` | Server listen port | `8080` | Number (1-65535) |
| `sites_root` | Generated sites directory | `/tmp` | Path |
## Core Bot Settings ### MCP Server
| Parameter | Description | Default | Type |
### Identity Parameters |-----------|-------------|---------|------|
| `mcp-server` | Enable MCP protocol server | `false` | Boolean |
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `botId` | UUID | Yes | Generated | Unique bot identifier |
| `title` | String | Yes | None | Bot display name |
| `description` | String | No | Empty | Bot description |
| `version` | String | No | "1.0" | Bot version |
| `author` | String | No | Empty | Bot creator |
| `language` | String | No | "en" | Default language |
| `timezone` | String | No | "UTC" | Bot timezone |
### Behavior Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `welcomeMessage` | String | No | Empty | Initial greeting |
| `fallbackMessage` | String | No | "I don't understand" | Default error response |
| `goodbyeMessage` | String | No | "Goodbye!" | Session end message |
| `typingDelay` | Number | No | 1000 | Typing indicator delay (ms) |
| `responseTimeout` | Number | No | 30000 | Response timeout (ms) |
| `maxRetries` | Number | No | 3 | Maximum retry attempts |
| `debugMode` | Boolean | No | false | Enable debug logging |
## LLM Parameters ## LLM Parameters
### Model Configuration ### Core LLM Settings
| Parameter | Description | Default | Type |
|-----------|-------------|---------|------|
| `llm-key` | API key for LLM service | `none` | String |
| `llm-url` | LLM service endpoint | `http://localhost:8081` | URL |
| `llm-model` | Model path or identifier | Required | Path/String |
| Parameter | Type | Required | Default | Description | ### LLM Cache
|-----------|------|----------|---------|-------------| | Parameter | Description | Default | Type |
| `llmProvider` | String | Yes | "openai" | LLM provider (openai, anthropic, google, local) | |-----------|-------------|---------|------|
| `llmModel` | String | Yes | "gpt-4" | Model name | | `llm-cache` | Enable response caching | `false` | Boolean |
| `llmApiKey` | String | Yes* | None | API key (*not required for local) | | `llm-cache-ttl` | Cache time-to-live | `3600` | Seconds |
| `llmEndpoint` | String | No | Provider default | Custom API endpoint | | `llm-cache-semantic` | Semantic similarity cache | `true` | Boolean |
| `llmOrganization` | String | No | Empty | Organization ID (OpenAI) | | `llm-cache-threshold` | Similarity threshold | `0.95` | Float (0-1) |
| `llmProject` | String | No | Empty | Project ID (Google) |
### Response Control ### Embedded LLM Server
| Parameter | Description | Default | Type |
|-----------|-------------|---------|------|
| `llm-server` | Run embedded server | `false` | Boolean |
| `llm-server-path` | Server binary path | `botserver-stack/bin/llm/build/bin` | Path |
| `llm-server-host` | Server bind address | `0.0.0.0` | IP address |
| `llm-server-port` | Server port | `8081` | Number |
| `llm-server-gpu-layers` | GPU offload layers | `0` | Number |
| `llm-server-n-moe` | MoE experts count | `0` | Number |
| `llm-server-ctx-size` | Context size | `4096` | Tokens |
| `llm-server-n-predict` | Max predictions | `1024` | Tokens |
| `llm-server-parallel` | Parallel requests | `6` | Number |
| `llm-server-cont-batching` | Continuous batching | `true` | Boolean |
| `llm-server-mlock` | Lock in memory | `false` | Boolean |
| `llm-server-no-mmap` | Disable mmap | `false` | Boolean |
| Parameter | Type | Required | Default | Description | ## Embedding Parameters
|-----------|------|----------|---------|-------------|
| `llmTemperature` | Float | No | 0.7 | Creativity (0.0-1.0) |
| `llmMaxTokens` | Number | No | 2000 | Max response tokens |
| `llmTopP` | Float | No | 1.0 | Nucleus sampling |
| `llmFrequencyPenalty` | Float | No | 0.0 | Reduce repetition |
| `llmPresencePenalty` | Float | No | 0.0 | Encourage new topics |
| `llmStopSequences` | String | No | Empty | Stop generation sequences |
| `llmSystemPrompt` | String | No | Default | System instruction |
### Cost Management | Parameter | Description | Default | Type |
|-----------|-------------|---------|------|
| `embedding-url` | Embedding service endpoint | `http://localhost:8082` | URL |
| `embedding-model` | Embedding model path | Required for KB | Path |
| Parameter | Type | Required | Default | Description | ## Prompt Parameters
|-----------|------|----------|---------|-------------|
| `llmCostLimit` | Number | No | 100 | Monthly cost limit ($) |
| `llmTokenLimit` | Number | No | 1000000 | Monthly token limit |
| `llmRequestLimit` | Number | No | 10000 | Daily request limit |
| `llmCacheEnabled` | Boolean | No | true | Enable response caching |
| `llmCacheTTL` | Number | No | 3600 | Cache duration (seconds) |
## Knowledge Base Parameters | Parameter | Description | Default | Type |
|-----------|-------------|---------|------|
| `prompt-compact` | Context compaction level | `4` | Number |
| `prompt-history` | Messages in history | Not set | Number |
### Vector Database ## Email Parameters
| Parameter | Type | Required | Default | Description | | Parameter | Description | Default | Type |
|-----------|------|----------|---------|-------------| |-----------|-------------|---------|------|
| `vectorDbUrl` | String | No | "http://localhost:6333" | Qdrant URL | | `email-from` | Sender address | Required for email | Email |
| `vectorDbApiKey` | String | No | Empty | Qdrant API key | | `email-server` | SMTP hostname | Required for email | Hostname |
| `vectorDbCollection` | String | No | Bot name | Default collection | | `email-port` | SMTP port | `587` | Number |
| `embeddingModel` | String | No | "text-embedding-ada-002" | Embedding model | | `email-user` | SMTP username | Required for email | String |
| `embeddingDimension` | Number | No | 1536 | Vector dimension | | `email-pass` | SMTP password | Required for email | String |
### Search Configuration ## Theme Parameters
| Parameter | Type | Required | Default | Description | | Parameter | Description | Default | Type |
|-----------|------|----------|---------|-------------| |-----------|-------------|---------|------|
| `searchTopK` | Number | No | 5 | Results to return | | `theme-color1` | Primary color | Not set | Hex color |
| `searchThreshold` | Float | No | 0.7 | Minimum similarity | | `theme-color2` | Secondary color | Not set | Hex color |
| `searchRerank` | Boolean | No | false | Enable reranking | | `theme-logo` | Logo URL | Not set | URL |
| `chunkSize` | Number | No | 1000 | Text chunk size | | `theme-title` | Bot display title | Not set | String |
| `chunkOverlap` | Number | No | 200 | Chunk overlap |
## Storage Parameters ## Custom Database Parameters
### Object Storage | Parameter | Description | Default | Type |
|-----------|-------------|---------|------|
| `custom-server` | Database server | `localhost` | Hostname |
| `custom-port` | Database port | `5432` | Number |
| `custom-database` | Database name | Not set | String |
| `custom-username` | Database user | Not set | String |
| `custom-password` | Database password | Not set | String |
| Parameter | Type | Required | Default | Description | ## Parameter Types
|-----------|------|----------|---------|-------------|
| `storageProvider` | String | No | "drive" | Storage provider |
| `storageEndpoint` | String | Yes | "localhost:9000" | S3-compatible drive endpoint |
| `storageAccessKey` | String | Yes | None | Access key |
| `storageSecretKey` | String | Yes | None | Secret key |
| `storageBucket` | String | No | "botserver" | Default bucket |
| `storageRegion` | String | No | "us-east-1" | AWS region |
| `storageUseSsl` | Boolean | No | false | Use HTTPS |
### File Handling ### Boolean
Values: `true` or `false` (case-sensitive)
| Parameter | Type | Required | Default | Description | ### Number
|-----------|------|----------|---------|-------------| Integer values, must be within valid ranges:
| `maxFileSize` | Number | No | 10 | Max file size (MB) | - Ports: 1-65535
| `allowedFileTypes` | String | No | "pdf,doc,txt,csv" | Allowed extensions | - Tokens: Positive integers
| `fileRetention` | Number | No | 90 | Days to keep files | - Percentages: 0-100
| `autoDeleteTemp` | Boolean | No | true | Auto-delete temp files |
## Communication Parameters ### Float
Decimal values:
- Thresholds: 0.0 to 1.0
### Email Settings ### Path
File system paths:
- Relative: `../../../../data/model.gguf`
- Absolute: `/opt/models/model.gguf`
| Parameter | Type | Required | Default | Description | ### URL
|-----------|------|----------|---------|-------------| Valid URLs:
| `emailEnabled` | Boolean | No | false | Enable email | - HTTP: `http://localhost:8081`
| `smtpHost` | String | No* | Empty | SMTP server | - HTTPS: `https://api.example.com`
| `smtpPort` | Number | No | 587 | SMTP port |
| `smtpUser` | String | No* | Empty | Email username |
| `smtpPassword` | String | No* | Empty | Email password |
| `smtpFrom` | String | No* | Empty | From address |
| `smtpUseTls` | Boolean | No | true | Use TLS |
| `smtpUseStarttls` | Boolean | No | true | Use STARTTLS |
### Channel Configuration ### String
Any text value (no quotes needed in CSV)
| Parameter | Type | Required | Default | Description | ### Email
|-----------|------|----------|---------|-------------| Valid email format: `user@domain.com`
| `webEnabled` | Boolean | No | true | Web interface |
| `webPort` | Number | No | 8080 | Web port |
| `whatsappEnabled` | Boolean | No | false | WhatsApp integration |
| `whatsappToken` | String | No* | Empty | WhatsApp token |
| `teamsEnabled` | Boolean | No | false | Teams integration |
| `teamsAppId` | String | No* | Empty | Teams app ID |
| `slackEnabled` | Boolean | No | false | Slack integration |
| `slackToken` | String | No* | Empty | Slack token |
## Security Parameters ### Hex Color
HTML color codes: `#RRGGBB` format
### Authentication ## Required vs Optional
| Parameter | Type | Required | Default | Description | ### Always Required
|-----------|------|----------|---------|-------------| - None - all parameters have defaults or are optional
| `authRequired` | Boolean | No | false | Require authentication |
| `authProvider` | String | No | "local" | Auth provider |
| `jwtSecret` | String | Yes* | Generated | JWT secret |
| `jwtExpiration` | Number | No | 86400 | Token expiration (s) |
| `sessionTimeout` | Number | No | 3600 | Session timeout (s) |
| `maxSessions` | Number | No | 100 | Max concurrent sessions |
### Access Control ### Required for Features
- **LLM**: `llm-model` must be set
- **Email**: `email-from`, `email-server`, `email-user`
- **Embeddings**: `embedding-model` for knowledge base
- **Custom DB**: `custom-database` if using external database
| Parameter | Type | Required | Default | Description | ## Configuration Precedence
|-----------|------|----------|---------|-------------|
| `corsOrigins` | String | No | "*" | Allowed origins |
| `ipWhitelist` | String | No | Empty | Allowed IPs |
| `ipBlacklist` | String | No | Empty | Blocked IPs |
| `rateLimitPerMinute` | Number | No | 60 | Requests per minute |
| `rateLimitPerHour` | Number | No | 1000 | Requests per hour |
| `requireHttps` | Boolean | No | false | Force HTTPS |
### Data Protection 1. **Built-in defaults** (hardcoded)
2. **config.csv values** (override defaults)
3. **Environment variables** (if implemented, override config)
| Parameter | Type | Required | Default | Description | ## Special Values
|-----------|------|----------|---------|-------------|
| `encryptData` | Boolean | No | true | Encrypt stored data |
| `encryptionKey` | String | Yes* | Generated | Encryption key |
| `maskPii` | Boolean | No | true | Mask personal data |
| `auditLogging` | Boolean | No | true | Enable audit logs |
| `dataRetention` | Number | No | 365 | Data retention (days) |
## Performance Parameters - `none` - Explicitly no value (for `llm-key`)
- Empty string - Unset/use default
- `false` - Feature disabled
- `true` - Feature enabled
### Caching ## Performance Tuning
| Parameter | Type | Required | Default | Description | ### For Local Models
|-----------|------|----------|---------|-------------| ```csv
| `cacheEnabled` | Boolean | No | true | Enable caching | llm-server-ctx-size,8192
| `cacheProvider` | String | No | "cache" | Cache provider | llm-server-n-predict,2048
| `cacheUrl` | String | No | "redis://localhost:6379" | Cache URL | llm-server-parallel,4
| `cacheTtl` | Number | No | 3600 | Default TTL (s) | llm-cache,true
| `cacheMaxSize` | Number | No | 100 | Max cache size (MB) | llm-cache-ttl,7200
### Resource Limits
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `maxCpu` | Number | No | 2 | CPU cores limit |
| `maxMemory` | Number | No | 2048 | Memory limit (MB) |
| `maxConnections` | Number | No | 100 | DB connections |
| `maxWorkers` | Number | No | 4 | Worker threads |
| `queueSize` | Number | No | 1000 | Task queue size |
## Monitoring Parameters
### Logging
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `logLevel` | String | No | "info" | Log level |
| `logToFile` | Boolean | No | true | Log to file |
| `logFilePath` | String | No | "./logs" | Log directory |
| `logRotation` | String | No | "daily" | Rotation schedule |
| `logRetention` | Number | No | 30 | Keep logs (days) |
### Metrics
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `metricsEnabled` | Boolean | No | false | Enable metrics |
| `metricsEndpoint` | String | No | "/metrics" | Metrics endpoint |
| `sentryDsn` | String | No | Empty | Sentry DSN |
| `datadogApiKey` | String | No | Empty | Datadog API key |
| `prometheusPort` | Number | No | 9090 | Prometheus port |
## Feature Flags
### Experimental Features
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `betaFeatures` | Boolean | No | false | Enable beta features |
| `webAutomation` | Boolean | No | false | Web scraping |
| `ocrEnabled` | Boolean | No | false | OCR support |
| `speechEnabled` | Boolean | No | false | Speech I/O |
| `visionEnabled` | Boolean | No | false | Image analysis |
| `codeExecution` | Boolean | No | false | Code running |
## Environment-Specific Parameters
### Development
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `devMode` | Boolean | No | false | Development mode |
| `hotReload` | Boolean | No | false | Hot reload |
| `mockServices` | Boolean | No | false | Use mock services |
| `verboseErrors` | Boolean | No | false | Detailed errors |
### Production
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `prodMode` | Boolean | No | true | Production mode |
| `clustering` | Boolean | No | false | Enable clustering |
| `loadBalancing` | Boolean | No | false | Load balancing |
| `autoScale` | Boolean | No | false | Auto-scaling |
## Parameter Validation
Parameters are validated on startup:
1. Required parameters must be present
2. Types are checked and coerced
3. Ranges are enforced
4. Dependencies verified
5. Conflicts detected
## Environment Variable Override
Any parameter can be overridden via environment:
```bash
BOT_TITLE="My Bot" BOT_LLM_MODEL="gpt-4-turbo" botserver
``` ```
## Dynamic Parameter Updates ### For Production
```csv
Some parameters can be updated at runtime: llm-server-cont-batching,true
- Log level llm-cache-semantic,true
- Rate limits llm-cache-threshold,0.90
- Cache settings llm-server-parallel,8
- Feature flags
Use the admin API to update:
```
POST /api/admin/config
{
"logLevel": "debug",
"rateLimitPerMinute": 120
}
``` ```
## Best Practices ### For Low Memory
```csv
llm-server-ctx-size,2048
llm-server-n-predict,512
llm-server-mlock,false
llm-server-no-mmap,false
llm-cache,false
```
1. **Start with defaults**: Most parameters have sensible defaults ## Validation Rules
2. **Override only what's needed**: Don't set everything
3. **Use environment variables**: For sensitive values 1. **Paths**: Model files must exist
4. **Document custom values**: Explain why changed 2. **URLs**: Must be valid format
5. **Test configuration**: Validate before production 3. **Ports**: Must be 1-65535
6. **Monitor performance**: Adjust based on metrics 4. **Emails**: Must contain @ and domain
7. **Version control**: Track configuration changes 5. **Colors**: Must be valid hex format
6. **Booleans**: Exactly `true` or `false`