Remove documentation files that have been merged into the mdbook

structure under docs/src/. These files were either duplicates, outdated,
or have been properly integrated into the structured documentation.
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-11-30 18:07:22 -03:00
parent 10e578b1a3
commit 430ec12357
33 changed files with 7236 additions and 3309 deletions

View file

@ -1,788 +0,0 @@
# HEAR Keyword - Input Validation Reference
> Complete reference for HEAR keyword with automatic input validation in General Bots BASIC
## Overview
The `HEAR` keyword waits for user input with optional automatic validation. When using `HEAR AS <TYPE>`, the system will:
1. Wait for user input
2. Validate against the specified type
3. **Automatically retry** with a helpful error message if invalid
4. Return the normalized/parsed value once valid
This eliminates the need for manual validation loops and provides a consistent, user-friendly experience.
---
## Table of Contents
1. [Basic HEAR](#basic-hear)
2. [Text Validation Types](#text-validation-types)
3. [Numeric Types](#numeric-types)
4. [Date/Time Types](#datetime-types)
5. [Brazilian Document Types](#brazilian-document-types)
6. [Contact Types](#contact-types)
7. [Menu Selection](#menu-selection)
8. [Media Types](#media-types)
9. [Authentication Types](#authentication-types)
10. [Examples](#examples)
11. [Best Practices](#best-practices)
---
## Basic HEAR
```basic
' Simple HEAR without validation - accepts any input
HEAR response
TALK "You said: " + response
```
---
## Text Validation Types
### HEAR AS EMAIL
Validates email address format and normalizes to lowercase.
```basic
TALK "What's your email address?"
HEAR email AS EMAIL
TALK "We'll send confirmation to: " + email
```
**Validation:**
- Must contain `@` symbol
- Must have valid domain format
- Normalized to lowercase
**Error message:** "Please enter a valid email address (e.g., user@example.com)"
---
### HEAR AS NAME
Validates name format (letters, spaces, hyphens, apostrophes).
```basic
TALK "What's your full name?"
HEAR name AS NAME
TALK "Nice to meet you, " + name + "!"
```
**Validation:**
- Minimum 2 characters
- Maximum 100 characters
- Only letters, spaces, hyphens, apostrophes
- Auto-capitalizes first letter of each word
**Error message:** "Please enter a valid name (letters and spaces only)"
---
### HEAR AS URL
Validates and normalizes URL format.
```basic
TALK "Enter your website URL:"
HEAR website AS URL
TALK "I'll check " + website
```
**Validation:**
- Valid URL format
- Auto-adds `https://` if protocol missing
**Error message:** "Please enter a valid URL"
---
### HEAR AS PASSWORD
Validates password strength (minimum requirements).
```basic
TALK "Create a password (minimum 8 characters):"
HEAR password AS PASSWORD
' Returns "[PASSWORD SET]" - actual password stored securely
```
**Validation:**
- Minimum 8 characters
- Returns strength indicator (weak/medium/strong)
- Never echoes the actual password
**Error message:** "Password must be at least 8 characters"
---
### HEAR AS COLOR
Validates and normalizes color values.
```basic
TALK "Pick a color:"
HEAR color AS COLOR
TALK "You selected: " + color ' Returns hex format like #FF0000
```
**Accepts:**
- Named colors: "red", "blue", "green", etc.
- Hex format: "#FF0000" or "FF0000"
- RGB format: "rgb(255, 0, 0)"
**Returns:** Normalized hex format (#RRGGBB)
---
### HEAR AS UUID
Validates UUID/GUID format.
```basic
TALK "Enter the transaction ID:"
HEAR transaction_id AS UUID
```
---
## Numeric Types
### HEAR AS INTEGER
Validates and parses integer numbers.
```basic
TALK "How old are you?"
HEAR age AS INTEGER
TALK "In 10 years you'll be " + STR(age + 10)
```
**Validation:**
- Accepts whole numbers only
- Removes formatting (commas, spaces)
- Returns numeric value
**Error message:** "Please enter a valid whole number"
---
### HEAR AS FLOAT / DECIMAL
Validates and parses decimal numbers.
```basic
TALK "Enter the temperature:"
HEAR temperature AS FLOAT
TALK "Temperature is " + STR(temperature) + "°C"
```
**Validation:**
- Accepts decimal numbers
- Handles both `.` and `,` as decimal separator
- Returns numeric value rounded to 2 decimal places
---
### HEAR AS MONEY / CURRENCY / AMOUNT
Validates and normalizes monetary amounts.
```basic
TALK "How much would you like to transfer?"
HEAR amount AS MONEY
TALK "Transferring R$ " + FORMAT(amount, "#,##0.00")
```
**Accepts:**
- "100"
- "100.00"
- "1,234.56" (US format)
- "1.234,56" (Brazilian/European format)
- "R$ 100,00"
- "$100.00"
**Returns:** Normalized decimal value (e.g., "1234.56")
**Error message:** "Please enter a valid amount (e.g., 100.00 or R$ 100,00)"
---
### HEAR AS CREDITCARD / CARD
Validates credit card number using Luhn algorithm.
```basic
TALK "Enter your card number:"
HEAR card AS CREDITCARD
' Returns masked format: "4111 **** **** 1111"
```
**Validation:**
- 13-19 digits
- Passes Luhn checksum
- Detects card type (Visa, Mastercard, Amex, etc.)
**Returns:** Masked card number with metadata about card type
---
## Date/Time Types
### HEAR AS DATE
Validates and parses date input.
```basic
TALK "When is your birthday?"
HEAR birthday AS DATE
TALK "Your birthday is " + FORMAT(birthday, "MMMM d")
```
**Accepts multiple formats:**
- "25/12/2024" (DD/MM/YYYY)
- "12/25/2024" (MM/DD/YYYY)
- "2024-12-25" (ISO format)
- "25 Dec 2024"
- "December 25, 2024"
- "today", "tomorrow", "yesterday"
- "hoje", "amanhã", "ontem" (Portuguese)
**Returns:** Normalized ISO date (YYYY-MM-DD)
**Error message:** "Please enter a valid date (e.g., 25/12/2024 or 2024-12-25)"
---
### HEAR AS HOUR / TIME
Validates and parses time input.
```basic
TALK "What time should we schedule the meeting?"
HEAR meeting_time AS HOUR
TALK "Meeting scheduled for " + meeting_time
```
**Accepts:**
- "14:30" (24-hour format)
- "2:30 PM" (12-hour format)
- "14:30:00" (with seconds)
**Returns:** Normalized 24-hour format (HH:MM)
**Error message:** "Please enter a valid time (e.g., 14:30 or 2:30 PM)"
---
## Brazilian Document Types
### HEAR AS CPF
Validates Brazilian CPF (individual taxpayer ID).
```basic
TALK "Enter your CPF:"
HEAR cpf AS CPF
TALK "CPF validated: " + cpf ' Returns formatted: 123.456.789-09
```
**Validation:**
- 11 digits
- Valid check digits (mod 11 algorithm)
- Rejects known invalid patterns (all same digit)
**Returns:** Formatted CPF (XXX.XXX.XXX-XX)
**Error message:** "Please enter a valid CPF (11 digits)"
---
### HEAR AS CNPJ
Validates Brazilian CNPJ (company taxpayer ID).
```basic
TALK "Enter your company's CNPJ:"
HEAR cnpj AS CNPJ
TALK "CNPJ validated: " + cnpj ' Returns formatted: 12.345.678/0001-95
```
**Validation:**
- 14 digits
- Valid check digits
**Returns:** Formatted CNPJ (XX.XXX.XXX/XXXX-XX)
**Error message:** "Please enter a valid CNPJ (14 digits)"
---
## Contact Types
### HEAR AS MOBILE / PHONE / TELEPHONE
Validates phone number format.
```basic
TALK "What's your phone number?"
HEAR phone AS MOBILE
TALK "We'll send SMS to: " + phone
```
**Validation:**
- 10-15 digits
- Auto-formats based on detected country
**Returns:** Formatted phone number
**Error message:** "Please enter a valid mobile number"
---
### HEAR AS ZIPCODE / CEP / POSTALCODE
Validates postal code format.
```basic
TALK "What's your ZIP code?"
HEAR cep AS ZIPCODE
TALK "Your ZIP code is: " + cep
```
**Supports:**
- Brazilian CEP: 8 digits → "12345-678"
- US ZIP: 5 or 9 digits → "12345" or "12345-6789"
- UK postcode: alphanumeric → "SW1A 1AA"
**Returns:** Formatted postal code with country detection
---
## Menu Selection
### HEAR AS "Option1", "Option2", "Option3"
Presents a menu and validates selection.
```basic
TALK "Choose your preferred fruit:"
HEAR fruit AS "Apple", "Banana", "Orange", "Mango"
TALK "You selected: " + fruit
```
**Accepts:**
- Exact match: "Apple"
- Case-insensitive: "apple"
- Numeric selection: "1", "2", "3"
- Partial match: "app" → "Apple" (if unique)
**Automatically adds suggestions** for the menu options.
**Error message:** "Please select one of: Apple, Banana, Orange, Mango"
---
### HEAR AS BOOLEAN
Validates yes/no response.
```basic
TALK "Do you agree to the terms?"
HEAR agreed AS BOOLEAN
IF agreed THEN
TALK "Thank you for agreeing!"
ELSE
TALK "You must agree to continue."
END IF
```
**Accepts (true):** "yes", "y", "true", "1", "sim", "ok", "sure", "confirm"
**Accepts (false):** "no", "n", "false", "0", "não", "cancel", "deny"
**Returns:** "true" or "false" (with boolean metadata)
**Error message:** "Please answer yes or no"
---
### HEAR AS LANGUAGE
Validates language code or name.
```basic
TALK "What language do you prefer?"
HEAR language AS LANGUAGE
SET CONTEXT LANGUAGE language
TALK "Language set to: " + language
```
**Accepts:**
- ISO codes: "en", "pt", "es", "fr", "de"
- Full names: "English", "Portuguese", "Spanish"
- Native names: "Português", "Español", "Français"
**Returns:** ISO 639-1 language code
---
## Media Types
### HEAR AS IMAGE / PHOTO / PICTURE
Waits for image upload.
```basic
TALK "Please send a photo of your document:"
HEAR document_photo AS IMAGE
TALK "Image received: " + document_photo
' Returns URL to the uploaded image
```
**Validation:**
- Must receive image attachment
- Accepts: JPG, PNG, GIF, WebP
**Error message:** "Please send an image"
---
### HEAR AS QRCODE
Waits for image with QR code and reads it.
```basic
TALK "Send me a photo of the QR code:"
HEAR qr_data AS QRCODE
TALK "QR code contains: " + qr_data
```
**Process:**
1. Waits for image upload
2. Calls BotModels vision API to decode QR
3. Returns the decoded data
**Error message:** "Please send an image containing a QR code"
---
### HEAR AS AUDIO / VOICE / SOUND
Waits for audio input and transcribes to text.
```basic
TALK "Send me a voice message:"
HEAR transcription AS AUDIO
TALK "You said: " + transcription
```
**Process:**
1. Waits for audio attachment
2. Calls BotModels speech-to-text API
3. Returns transcribed text
**Error message:** "Please send an audio file or voice message"
---
### HEAR AS VIDEO
Waits for video upload and describes content.
```basic
TALK "Send a video of the problem:"
HEAR video_description AS VIDEO
TALK "I can see: " + video_description
```
**Process:**
1. Waits for video attachment
2. Calls BotModels vision API to describe
3. Returns AI-generated description
**Error message:** "Please send a video"
---
### HEAR AS FILE / DOCUMENT / DOC / PDF
Waits for document upload.
```basic
TALK "Please upload your contract:"
HEAR contract AS DOCUMENT
TALK "Document received: " + contract
```
**Accepts:** PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, CSV
**Returns:** URL to the uploaded file
---
## Authentication Types
### HEAR AS LOGIN
Waits for Active Directory/OAuth login completion.
```basic
TALK "Please click the link to authenticate:"
HEAR user AS LOGIN
TALK "Welcome, " + user.name + "!"
```
**Process:**
1. Generates authentication URL
2. Waits for OAuth callback
3. Returns user object with tokens
---
## Examples
### Complete Registration Flow
```basic
TALK "Let's create your account!"
TALK "What's your full name?"
HEAR name AS NAME
TALK "Enter your email address:"
HEAR email AS EMAIL
TALK "Enter your CPF:"
HEAR cpf AS CPF
TALK "What's your phone number?"
HEAR phone AS MOBILE
TALK "Choose a password:"
HEAR password AS PASSWORD
TALK "What's your birth date?"
HEAR birthdate AS DATE
TALK "Select your gender:"
HEAR gender AS "Male", "Female", "Other", "Prefer not to say"
' All inputs are now validated and normalized
TALK "Creating account for " + name + "..."
TABLE new_user
ROW name, email, cpf, phone, birthdate, gender, NOW()
END TABLE
SAVE "users.csv", new_user
TALK "✅ Account created successfully!"
```
### Payment Flow
```basic
TALK "💳 Let's process your payment"
TALK "Enter the amount:"
HEAR amount AS MONEY
IF amount < 1 THEN
TALK "Minimum payment is R$ 1.00"
RETURN
END IF
TALK "How would you like to pay?"
HEAR method AS "Credit Card", "Debit Card", "PIX", "Boleto"
IF method = "PIX" THEN
TALK "Enter the PIX key (phone, email, or CPF):"
' Note: We could create HEAR AS PIX_KEY if needed
HEAR pix_key
ELSEIF method = "Boleto" THEN
TALK "Enter the barcode (47-48 digits):"
HEAR barcode AS INTEGER
END IF
TALK "Confirm payment of R$ " + FORMAT(amount, "#,##0.00") + "?"
HEAR confirm AS BOOLEAN
IF confirm THEN
TALK "✅ Processing payment..."
ELSE
TALK "Payment cancelled."
END IF
```
### Customer Support with Media
```basic
TALK "How can I help you today?"
HEAR issue AS "Report a bug", "Request feature", "Billing question", "Other"
IF issue = "Report a bug" THEN
TALK "Please describe the problem:"
HEAR description
TALK "Can you send a screenshot of the issue?"
HEAR screenshot AS IMAGE
TALK "Thank you! We've logged your bug report."
TALK "Reference: BUG-" + FORMAT(NOW(), "yyyyMMddHHmmss")
ELSEIF issue = "Billing question" THEN
TALK "Please upload your invoice or send the transaction ID:"
HEAR reference
END IF
```
---
## Best Practices
### 1. Always Use Appropriate Types
```basic
' ❌ Bad - no validation
HEAR email
IF NOT email CONTAINS "@" THEN
TALK "Invalid email"
' Need to implement retry logic...
END IF
' ✅ Good - automatic validation and retry
HEAR email AS EMAIL
' Guaranteed to be valid when we get here
```
### 2. Combine with Context
```basic
SET CONTEXT "You are a helpful banking assistant.
When asking for monetary values, always confirm before processing."
TALK "How much would you like to withdraw?"
HEAR amount AS MONEY
' LLM and validation work together
```
### 3. Use Menu for Limited Options
```basic
' ❌ Bad - open-ended when options are known
HEAR payment_method
IF payment_method <> "credit" AND payment_method <> "debit" THEN
' Handle unknown input...
END IF
' ✅ Good - constrained to valid options
HEAR payment_method AS "Credit Card", "Debit Card", "PIX"
```
### 4. Provide Context Before HEAR
```basic
' ❌ Bad - no context
HEAR value AS MONEY
' ✅ Good - user knows what to enter
TALK "Enter the transfer amount (minimum R$ 1.00):"
HEAR amount AS MONEY
```
### 5. Use HEAR AS for Security-Sensitive Data
```basic
' CPF is automatically validated
HEAR cpf AS CPF
' Credit card passes Luhn check and is masked
HEAR card AS CREDITCARD
' Password never echoed back
HEAR password AS PASSWORD
```
---
## Error Handling
Validation errors are handled automatically, but you can customize:
```basic
' The system automatically retries up to 3 times
' After 3 failures, execution continues with empty value
' You can check if validation succeeded:
HEAR email AS EMAIL
IF email = "" THEN
TALK "Unable to validate email after multiple attempts."
TALK "Please contact support for assistance."
RETURN
END IF
```
---
## Metadata Access
Some validation types provide additional metadata:
```basic
HEAR card AS CREDITCARD
' card = "**** **** **** 1234"
' Metadata available: card_type, last_four
HEAR date AS DATE
' date = "2024-12-25"
' Metadata available: original input, parsed format
HEAR audio AS AUDIO
' audio = "transcribed text here"
' Metadata available: language, confidence
```
---
## Integration with BotModels
Media types (QRCODE, AUDIO, VIDEO) automatically call BotModels services:
| Type | BotModels Endpoint | Service |
|------|-------------------|---------|
| QRCODE | `/api/v1/vision/qrcode` | QR Code detection |
| AUDIO | `/api/v1/speech/to-text` | Whisper transcription |
| VIDEO | `/api/v1/vision/describe-video` | BLIP2 video description |
| IMAGE (with question) | `/api/v1/vision/vqa` | Visual Q&A |
Configure BotModels URL in `config.csv`:
```
botmodels-url,http://localhost:8001
botmodels-enabled,true
```
---
## Summary Table
| Type | Example Input | Normalized Output |
|------|---------------|-------------------|
| EMAIL | "User@Example.COM" | "user@example.com" |
| NAME | "john DOE" | "John Doe" |
| INTEGER | "1,234" | 1234 |
| MONEY | "R$ 1.234,56" | "1234.56" |
| DATE | "25/12/2024" | "2024-12-25" |
| HOUR | "2:30 PM" | "14:30" |
| BOOLEAN | "yes" / "sim" | "true" |
| CPF | "12345678909" | "123.456.789-09" |
| MOBILE | "11999998888" | "(11) 99999-8888" |
| CREDITCARD | "4111111111111111" | "4111 **** **** 1111" |
| QRCODE | [image] | "decoded QR data" |
| AUDIO | [audio file] | "transcribed text" |
---
*HEAR AS validation - Making input handling simple, secure, and user-friendly.*

View file

@ -1,242 +0,0 @@
# Minimal UI and Bot Core API Compliance Documentation
## Overview
This document outlines the compliance between the Minimal UI (`ui/minimal/`) and the Bot Core API (`src/core/bot/`), ensuring proper integration and functionality.
## API Endpoints Compliance
### ✅ Implemented Endpoints
The Minimal UI correctly integrates with the following Bot Core API endpoints:
| Endpoint | Method | UI Function | Status |
|----------|--------|-------------|--------|
| `/ws` | WebSocket | `connectWebSocket()` | ✅ Working |
| `/api/auth` | GET | `initializeAuth()` | ✅ Working |
| `/api/sessions` | GET | `loadSessions()` | ✅ Working |
| `/api/sessions` | POST | `createNewSession()` | ✅ Working |
| `/api/sessions/{id}` | GET | `loadSessionHistory()` | ✅ Working |
| `/api/sessions/{id}/history` | GET | `loadSessionHistory()` | ✅ Working |
| `/api/sessions/{id}/start` | POST | `startSession()` | ✅ Working |
| `/api/voice/start` | POST | `startVoiceSession()` | ✅ Working |
| `/api/voice/stop` | POST | `stopVoiceSession()` | ✅ Working |
### WebSocket Protocol Compliance
The Minimal UI implements the WebSocket protocol correctly:
#### Message Types
```javascript
// UI Implementation matches Bot Core expectations
const MessageTypes = {
TEXT: 1, // Regular text message
VOICE: 2, // Voice message
CONTINUE: 3, // Continue interrupted response
CONTEXT: 4, // Context change
SYSTEM: 5 // System message
};
```
#### Message Format
```javascript
// Minimal UI message structure (matches bot core)
{
bot_id: string,
user_id: string,
session_id: string,
channel: "web",
content: string,
message_type: number,
media_url: string | null,
timestamp: ISO8601 string,
is_suggestion?: boolean,
context_name?: string
}
```
## Feature Compliance Matrix
| Feature | Bot Core Support | Minimal UI Support | Status |
|---------|-----------------|-------------------|---------|
| Text Chat | ✅ | ✅ | Fully Compliant |
| Voice Input | ✅ | ✅ | Fully Compliant |
| Session Management | ✅ | ✅ | Fully Compliant |
| Context Switching | ✅ | ✅ | Fully Compliant |
| Streaming Responses | ✅ | ✅ | Fully Compliant |
| Markdown Rendering | ✅ | ✅ | Fully Compliant |
| Suggestions | ✅ | ✅ | Fully Compliant |
| Multi-tenant | ✅ | ✅ | Fully Compliant |
| Authentication | ✅ | ✅ | Fully Compliant |
| Reconnection | ✅ | ✅ | Fully Compliant |
## Connection Flow Compliance
### 1. Initial Connection
```
Minimal UI Bot Core
| |
|---> GET /api/auth -------->|
|<--- {user_id, session_id} -|
| |
|---> WebSocket Connect ----->|
|<--- Connection Established -|
```
### 2. Message Exchange
```
Minimal UI Bot Core
| |
|---> Send Message --------->|
|<--- Streaming Response <----|
|<--- Suggestions ------------|
|<--- Context Update ---------|
```
### 3. Session Management
```
Minimal UI Bot Core
| |
|---> Create Session -------->|
|<--- Session ID -------------|
| |
|---> Load History ---------->|
|<--- Message Array ----------|
```
## Error Handling Compliance
The Minimal UI properly handles all Bot Core error scenarios:
### Connection Errors
- ✅ WebSocket disconnection with automatic reconnection
- ✅ Maximum retry attempts (10 attempts)
- ✅ Exponential backoff (1s to 10s)
- ✅ User notification of connection status
### API Errors
- ✅ HTTP error status handling
- ✅ Timeout handling
- ✅ Network failure recovery
- ✅ Graceful degradation
## Security Compliance
### CORS Headers
Bot Core provides appropriate CORS headers that Minimal UI expects:
- `Access-Control-Allow-Origin: *`
- `Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS`
- `Access-Control-Allow-Headers: Content-Type, Authorization`
### Authentication Flow
1. Minimal UI requests auth token from `/api/auth`
2. Bot Core generates and returns session credentials
3. UI includes credentials in WebSocket connection parameters
4. Bot Core validates credentials on connection
## Performance Compliance
### Resource Usage
| Metric | Bot Core Expectation | Minimal UI Usage | Status |
|--------|---------------------|------------------|---------|
| Initial Load | < 500KB | ~50KB | Excellent |
| WebSocket Payload | < 64KB | < 5KB avg | Excellent |
| Memory Usage | < 100MB | < 20MB | Excellent |
| CPU Usage | < 5% idle | < 1% idle | Excellent |
### Response Times
| Operation | Bot Core SLA | Minimal UI | Status |
|-----------|--------------|------------|---------|
| Initial Connect | < 1s | ~200ms | Excellent |
| Message Send | < 100ms | ~50ms | Excellent |
| Session Switch | < 500ms | ~300ms | Excellent |
| Voice Start | < 2s | ~1.5s | Excellent |
## Browser Compatibility
The Minimal UI is compatible with Bot Core across all modern browsers:
| Browser | Minimum Version | WebSocket | Voice | Status |
|---------|----------------|-----------|-------|---------|
| Chrome | 90+ | ✅ | ✅ | Fully Supported |
| Firefox | 88+ | ✅ | ✅ | Fully Supported |
| Safari | 14+ | ✅ | ✅ | Fully Supported |
| Edge | 90+ | ✅ | ✅ | Fully Supported |
| Mobile Chrome | 90+ | ✅ | ✅ | Fully Supported |
| Mobile Safari | 14+ | ✅ | ✅ | Fully Supported |
## Known Limitations
### Current Limitations
1. **File Upload**: Not implemented in Minimal UI (available in Suite UI)
2. **Rich Media**: Limited to images and links (full support in Suite UI)
3. **Multi-modal**: Text and voice only (video in Suite UI)
4. **Collaborative**: Single user sessions (multi-user in Suite UI)
### Planned Enhancements
1. **Progressive Web App**: Add service worker for offline support
2. **File Attachments**: Implement drag-and-drop file upload
3. **Rich Formatting**: Add toolbar for text formatting
4. **Keyboard Shortcuts**: Implement power user shortcuts
## Testing Checklist
### Manual Testing
- [ ] Load minimal UI at `http://localhost:8080`
- [ ] Verify WebSocket connection establishes
- [ ] Send text message and receive response
- [ ] Test voice input (if microphone available)
- [ ] Create new session
- [ ] Switch between sessions
- [ ] Test reconnection (kill and restart server)
- [ ] Verify markdown rendering
- [ ] Test suggestion buttons
- [ ] Check responsive design on mobile
### Automated Testing
```bash
# Run API compliance tests
cargo test --test minimal_ui_compliance
# Run WebSocket tests
cargo test --test websocket_protocol
# Run performance tests
cargo bench --bench minimal_ui_performance
```
## Debugging
### Common Issues and Solutions
1. **WebSocket Connection Fails**
- Check if server is running on port 8080
- Verify no CORS blocking in browser console
- Check WebSocket URL format in `getWebSocketUrl()`
2. **Session Not Persisting**
- Verify session_id is being stored
- Check localStorage is not disabled
- Ensure cookies are enabled
3. **Voice Not Working**
- Check microphone permissions
- Verify HTTPS or localhost (required for getUserMedia)
- Check LiveKit server connection
4. **Messages Not Displaying**
- Verify markdown parser is loaded
- Check message format matches expected structure
- Inspect browser console for JavaScript errors
## Conclusion
The Minimal UI is **fully compliant** with the Bot Core API. All critical features are implemented and working correctly. The interface provides a lightweight, fast, and responsive experience while maintaining complete compatibility with the backend services.
### Compliance Score: 98/100
Points deducted for:
- Missing file upload capability (-1)
- Limited rich media support (-1)
These are intentional design decisions to keep the Minimal UI lightweight. Full feature support is available in the Suite UI at `/suite`.

View file

@ -1,860 +0,0 @@
# General Bots - New Keywords Reference
> Complete reference for all new BASIC keywords implemented for General Bots Office Suite
## Table of Contents
1. [Social Media Keywords](#social-media-keywords)
2. [Form Handling & Webhooks](#form-handling--webhooks)
3. [Template Messaging](#template-messaging)
4. [Lead Scoring & CRM](#lead-scoring--crm)
5. [Math Functions](#math-functions)
6. [Date/Time Functions](#datetime-functions)
7. [String Functions](#string-functions)
8. [Validation Functions](#validation-functions)
9. [Array Functions](#array-functions)
10. [Error Handling](#error-handling)
---
## Social Media Keywords
### POST TO
Post content to social media platforms.
```basic
' Post to single platform
POST TO INSTAGRAM image, "Check out our new feature! #AI #Automation"
' Post to specific platforms
POST TO FACEBOOK image, caption
POST TO LINKEDIN image, caption
POST TO TWITTER image, caption
' Post to multiple platforms at once
POST TO "instagram,facebook,linkedin" image, caption
```
### POST TO ... AT (Scheduled Posting)
Schedule posts for future publishing.
```basic
' Schedule a post
POST TO INSTAGRAM AT "2025-02-01 10:00" image, caption
POST TO FACEBOOK AT "2025-02-15 09:00" image, "Coming soon!"
```
### GET METRICS
Retrieve engagement metrics for posts.
```basic
' Get Instagram metrics
metrics = GET INSTAGRAM METRICS "post-id"
TALK "Likes: " + metrics.likes + ", Comments: " + metrics.comments
' Get Facebook metrics
fb_metrics = GET FACEBOOK METRICS "post-id"
TALK "Shares: " + fb_metrics.shares
' Get LinkedIn metrics
li_metrics = GET LINKEDIN METRICS "post-id"
' Get Twitter metrics
tw_metrics = GET TWITTER METRICS "post-id"
```
### GET POSTS
List posts from a platform.
```basic
' Get all Instagram posts
posts = GET INSTAGRAM POSTS
' Get Facebook posts
fb_posts = GET FACEBOOK POSTS
```
### DELETE POST
Remove a scheduled or published post.
```basic
DELETE POST "post-id"
```
---
## Form Handling & Webhooks
### ON FORM SUBMIT
Register webhook handlers for form submissions from landing pages.
```basic
' Basic form handler
ON FORM SUBMIT "landing-page-form"
' Access form fields
name = fields.name
email = fields.email
phone = fields.phone
' Access metadata
source = metadata.utm_source
referrer = metadata.referrer
' Process the submission
SAVE "leads.csv", name, email, phone, source
SEND MAIL email, "Welcome!", "Thank you for your interest..."
END ON
' Form handler with validation
ON FORM SUBMIT "contact-form" WITH VALIDATION
' Validation is automatically applied
' Required fields, email format, phone format checked
END ON
```
### WEBHOOK
Create custom webhook endpoints.
```basic
' Register a webhook endpoint
WEBHOOK "order-received"
' The webhook will be available at:
' https://your-server/bot-name/webhook/order-received
```
### SET SCHEDULE
Schedule scripts to run at specific times.
```basic
' Run daily at 9 AM
SET SCHEDULE "0 9 * * *", "daily-report.bas"
' Run every Monday at 10 AM
SET SCHEDULE "0 10 * * 1", "weekly-summary.bas"
' Run on specific date
SET SCHEDULE DATEADD(TODAY(), 3, "day"), "followup.bas"
```
---
## Template Messaging
### SEND TEMPLATE
Send templated messages across multiple channels.
```basic
' Send email template
SEND TEMPLATE "welcome", "email", "user@example.com", #{name: "John", product: "Pro Plan"}
' Send WhatsApp template
SEND TEMPLATE "order-confirmation", "whatsapp", "+1234567890", #{order_id: "12345"}
' Send SMS template
SEND TEMPLATE "verification", "sms", "+1234567890", #{code: "123456"}
' Send to multiple channels at once
SEND TEMPLATE "announcement", "email,whatsapp", recipient, variables
' Simplified syntax without variables
SEND TEMPLATE "reminder", "email", "user@example.com"
```
### SEND TEMPLATE TO (Bulk)
Send templates to multiple recipients.
```basic
' Bulk email send
recipients = ["a@example.com", "b@example.com", "c@example.com"]
count = SEND TEMPLATE "newsletter" TO "email" recipients, #{month: "January"}
TALK "Sent to " + count + " recipients"
```
### CREATE TEMPLATE
Create new message templates.
```basic
' Create email template
CREATE TEMPLATE "welcome", "email", "Welcome to {{company}}!", "Hello {{name}}, thank you for joining us!"
' Create WhatsApp template
CREATE TEMPLATE "order-update", "whatsapp", "", "Your order {{order_id}} is {{status}}."
```
### GET TEMPLATE
Retrieve a template.
```basic
template = GET TEMPLATE "welcome"
TALK "Template body: " + template.body
```
---
## Lead Scoring & CRM
### SCORE LEAD
Calculate lead score based on profile and behavior data.
```basic
' Score a lead
lead_data = NEW OBJECT
lead_data.email = "john@company.com"
lead_data.name = "John Smith"
lead_data.company = "Acme Corp"
lead_data.job_title = "VP of Engineering"
lead_data.industry = "Technology"
lead_data.company_size = "Enterprise"
score = SCORE LEAD lead_data
TALK "Score: " + score.score
TALK "Grade: " + score.grade
TALK "Status: " + score.status
TALK "Recommendations: " + score.recommendations[0]
```
### AI SCORE LEAD
Use AI/LLM-enhanced scoring for better accuracy.
```basic
' AI-enhanced scoring
score = AI SCORE LEAD lead_data
TALK "AI Score: " + score.score
TALK "AI Confidence: " + score.breakdown.ai_confidence
```
### GET LEAD SCORE
Retrieve existing lead score.
```basic
' Get stored score
score = GET LEAD SCORE "lead-id"
TALK "Current score: " + score.score
```
### QUALIFY LEAD
Check if lead meets qualification threshold.
```basic
' Default threshold (70)
result = QUALIFY LEAD "lead-id"
IF result.qualified THEN
TALK "Lead is qualified: " + result.status
END IF
' Custom threshold
result = QUALIFY LEAD "lead-id", 80
IF result.qualified THEN
TALK "Lead meets 80+ threshold"
END IF
```
### UPDATE LEAD SCORE
Manually adjust a lead's score.
```basic
' Add points for engagement
new_score = UPDATE LEAD SCORE "lead-id", 10, "Attended webinar"
' Deduct points for inactivity
new_score = UPDATE LEAD SCORE "lead-id", -5, "No response to email"
```
---
## Math Functions
### Basic Math
```basic
' Absolute value
result = ABS(-42) ' Returns 42
' Rounding
result = ROUND(3.7) ' Returns 4
result = ROUND(3.14159, 2) ' Returns 3.14
' Integer conversion
result = INT(3.9) ' Returns 3
result = FIX(-3.9) ' Returns -3
result = FLOOR(3.7) ' Returns 3
result = CEIL(3.2) ' Returns 4
```
### Min/Max
```basic
' Two values
result = MAX(10, 20) ' Returns 20
result = MIN(10, 20) ' Returns 10
' Array values
arr = [5, 2, 8, 1, 9]
result = MAX(arr) ' Returns 9
result = MIN(arr) ' Returns 1
```
### Other Math Functions
```basic
' Modulo
result = MOD(17, 5) ' Returns 2
' Random numbers
result = RANDOM() ' Random 0-1
result = RANDOM(100) ' Random 0-99
result = RANDOM(1, 10) ' Random 1-10
' Sign
result = SGN(-5) ' Returns -1
result = SGN(5) ' Returns 1
result = SGN(0) ' Returns 0
' Square root
result = SQR(16) ' Returns 4
result = SQRT(25) ' Returns 5
' Logarithms
result = LOG(10) ' Natural log
result = LOG10(100) ' Base 10 log
' Exponential
result = EXP(2) ' e^2
' Power
result = POW(2, 8) ' Returns 256
result = POWER(3, 4) ' Returns 81
' Trigonometry
result = SIN(0) ' Returns 0
result = COS(0) ' Returns 1
result = TAN(0) ' Returns 0
pi = PI() ' Returns 3.14159...
' Aggregation
arr = [10, 20, 30, 40, 50]
result = SUM(arr) ' Returns 150
result = AVG(arr) ' Returns 30
result = AVERAGE(arr) ' Returns 30
```
---
## Date/Time Functions
### Current Date/Time
```basic
' Current date and time
now = NOW() ' "2025-01-22 14:30:45"
now_utc = NOW_UTC() ' UTC time
' Current date only
today = TODAY() ' "2025-01-22"
' Current time only
time = TIME() ' "14:30:45"
' Unix timestamp
ts = TIMESTAMP() ' 1737556245
```
### Date Components
```basic
date = "2025-01-22"
year = YEAR(date) ' Returns 2025
month = MONTH(date) ' Returns 1
day = DAY(date) ' Returns 22
weekday = WEEKDAY(date) ' Returns 4 (Wednesday)
week = WEEKNUM(date) ' Returns 4
datetime = "2025-01-22 14:30:45"
hour = HOUR(datetime) ' Returns 14
minute = MINUTE(datetime) ' Returns 30
second = SECOND(datetime) ' Returns 45
```
### Date Arithmetic
```basic
' Add to date
future = DATEADD("2025-01-22", 7, "day") ' "2025-01-29"
future = DATEADD("2025-01-22", 1, "month") ' "2025-02-22"
future = DATEADD("2025-01-22", 1, "year") ' "2026-01-22"
future = DATEADD("2025-01-22 10:00", 2, "hour") ' "2025-01-22 12:00:00"
' Subtract from date (negative values)
past = DATEADD("2025-01-22", -7, "day") ' "2025-01-15"
' Date difference
days = DATEDIFF("2025-01-01", "2025-01-22", "day") ' 21
months = DATEDIFF("2025-01-01", "2025-06-01", "month") ' 5
years = DATEDIFF("2020-01-01", "2025-01-01", "year") ' 5
```
### Date Formatting
```basic
' Format date
formatted = FORMAT_DATE("2025-01-22", "DD/MM/YYYY") ' "22/01/2025"
formatted = FORMAT_DATE("2025-01-22", "MMMM DD, YYYY") ' "January 22, 2025"
```
### Date Validation
```basic
' Check if valid date
valid = ISDATE("2025-01-22") ' true
valid = ISDATE("invalid") ' false
```
### End of Month
```basic
' Get last day of month
eom = EOMONTH("2025-01-15", 0) ' "2025-01-31"
eom = EOMONTH("2025-01-15", 1) ' "2025-02-28"
eom = EOMONTH("2025-01-15", -1) ' "2024-12-31"
```
---
## String Functions
### Length and Substrings
```basic
' String length
length = LEN("Hello World") ' Returns 11
' Left portion
result = LEFT("Hello World", 5) ' Returns "Hello"
' Right portion
result = RIGHT("Hello World", 5) ' Returns "World"
' Middle portion
result = MID("Hello World", 7) ' Returns "World"
result = MID("Hello World", 7, 3) ' Returns "Wor"
```
### Case Conversion
```basic
' Uppercase
result = UCASE("hello") ' Returns "HELLO"
result = UPPER("hello") ' Returns "HELLO"
' Lowercase
result = LCASE("HELLO") ' Returns "hello"
result = LOWER("HELLO") ' Returns "hello"
```
### Trimming
```basic
' Trim whitespace
result = TRIM(" hello ") ' Returns "hello"
result = LTRIM(" hello") ' Returns "hello"
result = RTRIM("hello ") ' Returns "hello"
```
### Search and Replace
```basic
' Find position (1-based)
pos = INSTR("Hello World", "World") ' Returns 7
pos = INSTR(5, "one two one", "one") ' Returns 9 (starting from position 5)
' Replace
result = REPLACE("Hello World", "World", "Universe") ' Returns "Hello Universe"
```
### Split and Join
```basic
' Split string to array
parts = SPLIT("a,b,c,d", ",") ' Returns ["a", "b", "c", "d"]
' Join array to string
arr = ["a", "b", "c"]
result = JOIN(arr, "-") ' Returns "a-b-c"
```
---
## Validation Functions
### Type Conversion
```basic
' String to number
num = VAL("42") ' Returns 42.0
num = VAL("3.14") ' Returns 3.14
num = CINT("42.7") ' Returns 43 (rounded integer)
num = CDBL("3.14") ' Returns 3.14
' Number to string
str = STR(42) ' Returns "42"
str = CSTR(3.14) ' Returns "3.14"
```
### Null/Empty Checks
```basic
' Check for null
result = ISNULL(value) ' true if null/unit
' Check for empty
result = ISEMPTY("") ' true
result = ISEMPTY([]) ' true (empty array)
result = ISEMPTY(#{}) ' true (empty map)
```
### Type Checks
```basic
' Check types
result = ISSTRING("hello") ' true
result = ISNUMBER(42) ' true
result = ISNUMBER(3.14) ' true
result = ISBOOL(true) ' true
result = ISARRAY([1, 2, 3]) ' true
result = ISOBJECT(#{a: 1}) ' true
result = IS_NUMERIC("42") ' true
result = IS_DATE("2025-01-22") ' true
' Get type name
type = TYPEOF(value) ' Returns type name as string
```
### Coalesce/Default Values
```basic
' Return first non-null value
result = NVL(null_value, "default") ' Returns "default"
result = COALESCE(null_value, "default") ' Same as NVL
```
### Conditional
```basic
' Inline if
result = IIF(score >= 70, "Pass", "Fail")
' Choose from list (1-based index)
result = CHOOSE(2, ["A", "B", "C"]) ' Returns "B"
```
---
## Array Functions
### Creating Arrays
```basic
' Create array
arr = ARRAY(1, 2, 3, 4, 5)
' Create range
arr = RANGE(1, 10) ' [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
arr = RANGE(0, 10, 2) ' [0, 2, 4, 6, 8, 10]
```
### Array Info
```basic
' Array bounds
arr = [10, 20, 30, 40, 50]
upper = UBOUND(arr) ' Returns 4 (last index)
lower = LBOUND(arr) ' Returns 0 (first index)
count = COUNT(arr) ' Returns 5 (length)
```
### Searching
```basic
' Check if contains
result = CONTAINS(arr, 30) ' true
result = IN_ARRAY(30, arr) ' true (alternate syntax)
' Find index
index = INDEX_OF(arr, 30) ' Returns 2 (-1 if not found)
```
### Sorting
```basic
' Sort ascending
sorted = SORT(arr)
' Sort descending
sorted = SORT_DESC(arr)
```
### Uniqueness
```basic
' Remove duplicates
arr = [1, 2, 2, 3, 3, 3]
unique = UNIQUE(arr) ' [1, 2, 3]
unique = DISTINCT(arr) ' Same as UNIQUE
```
### Manipulation
```basic
' Add to end
arr = PUSH(arr, 60)
' Remove from end
last = POP(arr)
' Add to beginning
arr = UNSHIFT(arr, 0)
' Remove from beginning
first = SHIFT(arr)
' Reverse
reversed = REVERSE(arr)
' Get slice
part = SLICE(arr, 1) ' From index 1 to end
part = SLICE(arr, 1, 3) ' From index 1 to 3 (exclusive)
```
### Combining
```basic
' Concatenate arrays
combined = CONCAT(arr1, arr2)
' Flatten nested arrays
nested = [[1, 2], [3, 4], [5]]
flat = FLATTEN(nested) ' [1, 2, 3, 4, 5]
```
### Element Access
```basic
' First and last elements
first = FIRST_ELEM(arr)
last = LAST_ELEM(arr)
```
---
## Error Handling
### Throwing Errors
```basic
' Throw an error
THROW "Something went wrong"
' Raise (alias for THROW)
RAISE "Invalid input"
```
### Error Objects
```basic
' Create error object (for inspection)
err = ERROR("Validation failed")
' err.error = true
' err.message = "Validation failed"
' err.timestamp = "2025-01-22 14:30:45"
' Check if value is error
IF IS_ERROR(result) THEN
msg = GET_ERROR_MESSAGE(result)
TALK "Error occurred: " + msg
END IF
```
### Assertions
```basic
' Assert condition
ASSERT score >= 0, "Score cannot be negative"
ASSERT NOT ISEMPTY(name), "Name is required"
' If assertion fails, throws error with message
```
### Logging
```basic
' Log messages at different levels
LOG_ERROR "Critical failure in processing"
LOG_WARN "Unusual condition detected"
LOG_INFO "Processing completed"
LOG_DEBUG "Variable value: " + STR(x)
```
### TRY/CATCH Pattern
While Rhai doesn't support traditional TRY...CATCH, use this pattern:
```basic
' Using error checking pattern
result = potentially_failing_operation()
IF IS_ERROR(result) THEN
LOG_ERROR GET_ERROR_MESSAGE(result)
result = TRY_RESULT(false, (), "Operation failed")
ELSE
result = TRY_RESULT(true, result, "")
END IF
' result.success = true/false
' result.value = the actual value if successful
' result.error = error message if failed
```
---
## Campaign Examples
### Welcome Campaign
```basic
' Start welcome campaign for new lead
lead_email = "newuser@example.com"
lead_name = "John"
' Send immediate welcome
vars = #{name: lead_name, company: "Acme"}
SEND TEMPLATE "welcome-email-1", "email", lead_email, vars
' Schedule follow-ups
SET SCHEDULE DATEADD(TODAY(), 2, "day"), "send-welcome-2.bas"
SET SCHEDULE DATEADD(TODAY(), 5, "day"), "send-welcome-3.bas"
SET SCHEDULE DATEADD(TODAY(), 14, "day"), "send-welcome-final.bas"
' Score the lead
score = SCORE LEAD #{email: lead_email, name: lead_name}
TALK "Welcome campaign started. Initial score: " + score.score
```
### Social Media Campaign
```basic
' Product launch social media campaign
product_name = "AI Assistant Pro"
launch_date = "2025-02-15"
' Generate image
product_image = IMAGE "Product launch graphic for " + product_name
' Schedule posts across platforms
hashtags = "#AI #Automation #NewProduct"
' Day -7: Teaser
POST TO "instagram,facebook,linkedin" AT DATEADD(launch_date, -7, "day") + " 10:00" product_image, "Something big is coming... 🔥 " + hashtags
' Day -3: Feature preview
POST TO "instagram,twitter" AT DATEADD(launch_date, -3, "day") + " 10:00" product_image, "Sneak peek! " + hashtags
' Launch day
POST TO "instagram,facebook,twitter,linkedin" AT launch_date + " 09:00" product_image, "🚀 IT'S HERE! " + product_name + " is now LIVE! " + hashtags
TALK "Social media campaign scheduled with " + 6 + " posts"
```
### Lead Nurturing with AI Scoring
```basic
' Process form submission
ON FORM SUBMIT "landing-page"
' Extract data
lead = #{
email: fields.email,
name: fields.name,
company: fields.company,
job_title: fields.title,
industry: fields.industry
}
' AI-powered scoring
score = AI SCORE LEAD lead
' Route based on score
IF score.score >= 85 THEN
' Hot lead - immediate action
CREATE TASK "Contact hot lead: " + lead.email, "sales", "high"
SEND TEMPLATE "hot-lead-welcome", "email,sms", lead.email, lead
ELSE IF score.score >= 70 THEN
' Warm lead - accelerated nurture
SEND TEMPLATE "warm-welcome", "email", lead.email, lead
SET SCHEDULE DATEADD(NOW(), 3, "day"), "warm-nurture-2.bas"
ELSE
' Cold lead - standard drip
SEND TEMPLATE "cold-welcome", "email", lead.email, lead
SET SCHEDULE DATEADD(NOW(), 7, "day"), "cold-nurture-2.bas"
END IF
' Save to CRM
SAVE "leads", lead.email, lead.name, score.score, score.grade, NOW()
END ON
```
---
## Configuration
### Social Media Credentials
Store in `bot_settings` table:
- `instagram_credentials`: `{access_token, user_id}`
- `facebook_credentials`: `{access_token, page_id}`
- `linkedin_credentials`: `{access_token, person_urn}`
- `twitter_credentials`: `{bearer_token}`
### Lead Scoring Weights
Default weights (customizable per bot):
| Factor | Default Weight |
|--------|---------------|
| Company Size | 10 |
| Industry Match | 15 |
| Job Title | 15 |
| Location | 5 |
| Email Opens | 5 |
| Email Clicks | 10 |
| Page Visits | 5 |
| Form Submissions | 15 |
| Content Downloads | 10 |
| Pricing Page Visits | 20 |
| Demo Requests | 25 |
| Trial Signups | 30 |
| Inactivity Penalty | -15 |
---
*Last updated: January 2025*
*General Bots v5.0*

View file

@ -1,264 +0,0 @@
# Quick Start Guide
## Prerequisites
- Rust 1.75+ and Cargo
- PostgreSQL 14+ (or Docker)
- Optional: MinIO for S3-compatible storage
- Optional: Redis/Valkey for caching
## Installation
### 1. Clone the Repository
```bash
git clone https://github.com/GeneralBots/BotServer.git
cd BotServer
```
### 2. Build the Project
```bash
# Build with default features (includes console UI)
cargo build
# Build with all features
cargo build --all-features
# Build for release
cargo build --release
```
## Running BotServer
### Default Mode (with Console UI)
```bash
# Run with console UI showing real-time status, logs, and file browser
cargo run
# The console UI provides:
# - System metrics (CPU, Memory, GPU if available)
# - Service status monitoring
# - Real-time logs
# - File browser for drive storage
# - Database status
```
### Background Service Mode
```bash
# Run without console UI (background service)
cargo run -- --noconsole
# Run without any UI
cargo run -- --noui
```
### Desktop Mode
```bash
# Run with Tauri desktop application
cargo run -- --desktop
```
### Advanced Options
```bash
# Specify a tenant
cargo run -- --tenant my-organization
# Container deployment mode
cargo run -- --container
# Combine options
cargo run -- --noconsole --tenant production
```
## First-Time Setup
When you run BotServer for the first time, it will:
1. **Automatically start required services:**
- PostgreSQL database (if not running)
- MinIO S3-compatible storage (if configured)
- Redis cache (if configured)
2. **Run database migrations automatically:**
- Creates all required tables and indexes
- Sets up initial schema
3. **Bootstrap initial configuration:**
- Creates `.env` file with defaults
- Sets up bot templates
- Configures service endpoints
## Configuration
### Environment Variables
Copy the example environment file and customize:
```bash
cp .env.example .env
```
Key configuration options in `.env`:
```bash
# Database
DATABASE_URL=postgres://postgres:postgres@localhost:5432/botserver
# Server
SERVER_HOST=127.0.0.1
SERVER_PORT=8080
# Drive (MinIO)
DRIVE_SERVER=http://localhost:9000
DRIVE_ACCESSKEY=minioadmin
DRIVE_SECRET=minioadmin
# LLM Configuration
LLM_SERVER=http://localhost:8081
LLM_MODEL=llama2
# Logging (automatically configured)
# All external library traces are suppressed by default
# Use RUST_LOG=botserver=trace for detailed debugging
RUST_LOG=info
```
## Accessing the Application
### Web Interface
Once running, access the web interface at:
```
http://localhost:8080
```
### API Endpoints
- Health Check: `GET http://localhost:8080/api/health`
- Chat: `POST http://localhost:8080/api/chat`
- Tasks: `GET/POST http://localhost:8080/api/tasks`
- Drive: `GET http://localhost:8080/api/drive/files`
## Console UI Controls
When running with the console UI (default):
### Keyboard Shortcuts
- `Tab` - Switch between panels
- `↑/↓` - Navigate lists
- `Enter` - Select/Open
- `Esc` - Go back/Cancel
- `q` - Quit application
- `l` - View logs
- `f` - File browser
- `s` - System status
- `h` - Help
### Panels
1. **Status Panel** - System metrics and service health
2. **Logs Panel** - Real-time application logs
3. **File Browser** - Navigate drive storage
4. **Database Panel** - Connection status and stats
## Troubleshooting
### Database Connection Issues
```bash
# Check if PostgreSQL is running
ps aux | grep postgres
# Start PostgreSQL manually if needed
sudo systemctl start postgresql
# Verify connection
psql -U postgres -h localhost
```
### Drive/MinIO Issues
```bash
# Check if MinIO is running
ps aux | grep minio
# Start MinIO manually
./botserver-stack/bin/drive/minio server ./botserver-stack/data/drive
```
### Console UI Not Showing
```bash
# Ensure console feature is compiled
cargo build --features console
# Check terminal compatibility
echo $TERM # Should be xterm-256color or similar
```
### High CPU/Memory Usage
```bash
# Run without console for lower resource usage
cargo run -- --noconsole
# Check running services
htop
```
## Development
### Running Tests
```bash
# Run all tests
cargo test
# Run with specific features
cargo test --features console
# Run integration tests
cargo test --test '*'
```
### Enable Detailed Logging
```bash
# Trace level for botserver only
RUST_LOG=botserver=trace cargo run
# Debug level
RUST_LOG=botserver=debug cargo run
# Info level (default)
RUST_LOG=info cargo run
```
### Building Documentation
```bash
# Build and open Rust documentation
cargo doc --open
# Build book documentation
cd docs && mdbook build
```
## Next Steps
1. **Configure your first bot** - See [Bot Configuration Guide](./BOT_CONFIGURATION.md)
2. **Set up integrations** - See [Integration Guide](./05-INTEGRATION_STATUS.md)
3. **Deploy to production** - See [Deployment Guide](./DEPLOYMENT.md)
4. **Explore the API** - See [API Documentation](./API.md)
## Getting Help
- **Documentation**: [Complete Docs](./INDEX.md)
- **Issues**: [GitHub Issues](https://github.com/GeneralBots/BotServer/issues)
- **Community**: [Discussions](https://github.com/GeneralBots/BotServer/discussions)

View file

@ -1,230 +0,0 @@
# SET SCHEDULE Keyword Reference
> Documentation for scheduling scripts and automations in General Bots
## Overview
SET SCHEDULE has two distinct usages:
1. **File-level scheduler**: When placed at the top of a `.bas` file, defines when the script runs automatically
2. **Runtime scheduling**: When used within code, schedules another script to run at a specific time
## Usage 1: File-Level Scheduler
When SET SCHEDULE appears at the top of a file (before any executable code), it registers the entire script to run on a cron schedule.
### Syntax
```basic
SET SCHEDULE "cron_expression"
' Rest of script follows
TALK "This runs on schedule"
```
### Examples
```basic
' Run every day at 9 AM
SET SCHEDULE "0 9 * * *"
TALK "Good morning! Running daily report..."
stats = AGGREGATE "sales", "SUM", "amount", "date = TODAY()"
SEND TEMPLATE "daily-report", "email", "team@company.com", #{total: stats}
```
```basic
' Run every Monday at 10 AM
SET SCHEDULE "0 10 * * 1"
TALK "Weekly summary starting..."
' Generate weekly report
```
```basic
' Run first day of every month at midnight
SET SCHEDULE "0 0 1 * *"
TALK "Monthly billing cycle..."
' Process monthly billing
```
### Cron Expression Reference
```
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)
│ │ │ │ │
* * * * *
```
| Expression | Description |
|------------|-------------|
| `0 9 * * *` | Every day at 9:00 AM |
| `0 9 * * 1-5` | Weekdays at 9:00 AM |
| `0 */2 * * *` | Every 2 hours |
| `30 8 * * 1` | Mondays at 8:30 AM |
| `0 0 1 * *` | First of each month at midnight |
| `0 12 * * 0` | Sundays at noon |
| `*/15 * * * *` | Every 15 minutes |
| `0 9,17 * * *` | At 9 AM and 5 PM daily |
## Usage 2: Runtime Scheduling
When used within code (not at file top), schedules another script to run at a specified time.
### Syntax
```basic
' Schedule with cron + date
SET SCHEDULE "cron_expression" date, "script.bas"
' Schedule for specific date/time
SET SCHEDULE datetime, "script.bas"
```
### Examples
```basic
' Schedule script to run in 3 days at 9 AM
SET SCHEDULE "0 9 * * *" DATEADD(TODAY(), 3, "day"), "followup-email.bas"
```
```basic
' Schedule for specific datetime
SET SCHEDULE "2025-02-15 10:00", "product-launch.bas"
```
```basic
' Schedule relative to now
SET SCHEDULE DATEADD(NOW(), 1, "hour"), "reminder.bas"
SET SCHEDULE DATEADD(NOW(), 30, "minute"), "check-status.bas"
```
```basic
' Campaign scheduling example
ON FORM SUBMIT "signup"
' Welcome email immediately
SEND TEMPLATE "welcome", "email", fields.email, #{name: fields.name}
' Schedule follow-up sequence
SET SCHEDULE DATEADD(NOW(), 2, "day"), "nurture-day-2.bas"
SET SCHEDULE DATEADD(NOW(), 5, "day"), "nurture-day-5.bas"
SET SCHEDULE DATEADD(NOW(), 14, "day"), "nurture-day-14.bas"
END ON
```
## Passing Data to Scheduled Scripts
Use SET BOT MEMORY to pass data to scheduled scripts:
```basic
' In the scheduling script
SET BOT MEMORY "scheduled_lead_" + lead_id, lead_email
SET SCHEDULE DATEADD(NOW(), 7, "day"), "followup.bas"
' In followup.bas
PARAM lead_id AS string
lead_email = GET BOT MEMORY "scheduled_lead_" + lead_id
SEND TEMPLATE "followup", "email", lead_email, #{id: lead_id}
```
## Campaign Drip Sequence Example
```basic
' welcome-sequence.bas - File-level scheduler not used here
' This is triggered by form submission
PARAM email AS string
PARAM name AS string
DESCRIPTION "Start welcome email sequence"
' Day 0: Immediate welcome
WITH vars
.name = name
.date = TODAY()
END WITH
SEND TEMPLATE "welcome-1", "email", email, vars
' Store lead info for scheduled scripts
SET BOT MEMORY "welcome_" + email + "_name", name
' Schedule remaining emails
SET SCHEDULE DATEADD(NOW(), 2, "day"), "welcome-day-2.bas"
SET SCHEDULE DATEADD(NOW(), 5, "day"), "welcome-day-5.bas"
SET SCHEDULE DATEADD(NOW(), 7, "day"), "welcome-day-7.bas"
TALK "Welcome sequence started for " + email
```
## Daily Report Example
```basic
' daily-sales-report.bas
SET SCHEDULE "0 18 * * 1-5"
' This runs every weekday at 6 PM
today_sales = AGGREGATE "orders", "SUM", "total", "date = TODAY()"
order_count = AGGREGATE "orders", "COUNT", "id", "date = TODAY()"
avg_order = IIF(order_count > 0, today_sales / order_count, 0)
WITH report
.date = TODAY()
.total_sales = today_sales
.order_count = order_count
.average_order = ROUND(avg_order, 2)
END WITH
SEND TEMPLATE "daily-sales", "email", "sales@company.com", report
TALK "Daily report sent: $" + today_sales
```
## Canceling Scheduled Tasks
Scheduled tasks are stored in `system_automations` table. To cancel:
```basic
' Remove scheduled automation
DELETE "system_automations", "param = 'followup.bas' AND bot_id = '" + bot_id + "'"
```
## Best Practices
1. **Use descriptive script names**: `welcome-day-2.bas` not `email2.bas`
2. **Store context in BOT MEMORY**: Pass lead ID, not entire objects
3. **Check for unsubscribes**: Before sending scheduled emails
4. **Handle errors gracefully**: Scheduled scripts should not crash
5. **Log execution**: Track when scheduled scripts run
6. **Use appropriate times**: Consider timezone and recipient preferences
7. **Avoid overlapping schedules**: Don't schedule too many scripts at same time
## Database Schema
Scheduled tasks are stored in `system_automations`:
| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Automation ID |
| `bot_id` | UUID | Bot owner |
| `kind` | INT | Trigger type (Scheduled = 1) |
| `schedule` | TEXT | Cron expression |
| `param` | TEXT | Script filename |
| `is_active` | BOOL | Active status |
| `last_triggered` | TIMESTAMP | Last execution time |
## Comparison
| Feature | File-Level | Runtime |
|---------|------------|---------|
| Location | Top of file | Anywhere in code |
| Purpose | Recurring execution | One-time scheduling |
| Timing | Cron-based recurring | Specific date/time |
| Script | Self (current file) | Other script |
| Use case | Reports, cleanup | Drip campaigns, reminders |

View file

@ -1,243 +0,0 @@
# UI Structure Documentation
## Overview
The BotServer UI system consists of two main interface implementations designed for different use cases and deployment scenarios.
## Directory Structure
```
ui/
├── suite/ # Full-featured suite interface (formerly desktop)
│ ├── index.html
│ ├── js/
│ ├── css/
│ ├── public/
│ ├── drive/
│ ├── chat/
│ ├── mail/
│ ├── tasks/
│ ├── default.gbui
│ └── single.gbui
└── minimal/ # Lightweight minimal interface (formerly html)
├── index.html
├── styles.css
└── app.js
```
## Interface Types
### Suite Interface (`ui/suite/`)
The **Suite** interface is the comprehensive, full-featured UI that provides:
- **Multi-application integration**: Chat, Drive, Tasks, Mail modules
- **Desktop-class experience**: Rich interactions and complex workflows
- **Responsive design**: Works on desktop, tablet, and mobile
- **GBUI templates**: Customizable interface templates
- `default.gbui`: Full multi-app layout
- `single.gbui`: Streamlined chat-focused interface
- **Tauri integration**: Can be packaged as a desktop application
**Use Cases:**
- Enterprise deployments
- Power users requiring full functionality
- Desktop application distribution
- Multi-service integrations
**Access:**
- Web: `http://localhost:8080/suite` (explicit suite access)
- Desktop: Via Tauri build with `--desktop` flag
### Minimal Interface (`ui/minimal/`)
The **Minimal** interface is a lightweight, fast-loading UI that provides:
- **Essential features only**: Core chat and basic interactions
- **Fast loading**: Minimal dependencies and assets
- **Low resource usage**: Optimized for constrained environments
- **Easy embedding**: Simple to integrate into existing applications
- **Mobile-first**: Designed primarily for mobile and embedded use
**Use Cases:**
- Mobile web access
- Embedded chatbots
- Low-bandwidth environments
- Quick access terminals
- Kiosk deployments
**Access:**
- Direct: `http://localhost:8080` (default)
- Explicit: `http://localhost:8080/minimal`
- Embedded: Via iframe or WebView
## Configuration
### Server Configuration
The UI paths are configured in multiple locations:
1. **Main Server** (`src/main.rs`):
```rust
let static_path = std::path::Path::new("./web/suite");
```
2. **UI Server Module** (`src/core/ui_server/mod.rs`):
```rust
let static_path = PathBuf::from("./ui/suite");
```
3. **Tauri Configuration** (`tauri.conf.json`):
```json
{
"build": {
"frontendDist": "./ui/suite"
}
}
```
### Switching Between Interfaces
#### Default Interface Selection
The minimal interface is served by default at the root path. This provides faster loading and lower resource usage for most users.
1. Update `ui_server/mod.rs`:
```rust
// For minimal (default)
match fs::read_to_string("ui/minimal/index.html")
// For suite
match fs::read_to_string("ui/suite/index.html")
```
#### Routing Configuration
Both interfaces can be served simultaneously with different routes:
```rust
Router::new()
.route("/", get(serve_minimal)) // Minimal at root (default)
.route("/minimal", get(serve_minimal)) // Explicit minimal route
.route("/suite", get(serve_suite)) // Suite at /suite
```
## Development Guidelines
### When to Use Suite Interface
Choose the Suite interface when you need:
- Full application functionality
- Multi-module integration
- Desktop-like user experience
- Complex workflows and data management
- Rich media handling
### When to Use Minimal Interface
Choose the Minimal interface when you need:
- Fast, lightweight deployment
- Mobile-optimized experience
- Embedded chatbot functionality
- Limited bandwidth scenarios
- Simple, focused interactions
## Migration Notes
### From Previous Structure
The UI directories were renamed for clarity:
- `ui/desktop``ui/suite` (reflects full-featured nature)
- `ui/html``ui/minimal` (reflects lightweight design)
### Updating Existing Code
When migrating existing code:
1. Update static file paths:
```rust
// Old
let static_path = PathBuf::from("./ui/desktop");
// New
let static_path = PathBuf::from("./ui/suite");
```
2. Update documentation references:
```markdown
<!-- Old -->
Location: `ui/desktop/default.gbui`
<!-- New -->
Location: `ui/suite/default.gbui`
```
3. Update build configurations:
```json
// Old
"frontendDist": "./ui/desktop"
// New
"frontendDist": "./ui/suite"
```
## Future Enhancements
### Planned Features
1. **Dynamic UI Selection**: Runtime switching between suite and minimal
2. **Progressive Enhancement**: Start with minimal, upgrade to suite as needed
3. **Custom Themes**: User-selectable themes for both interfaces
4. **Module Lazy Loading**: Load suite modules on-demand
5. **Offline Support**: Service worker implementation for both UIs
### Interface Convergence
Future versions may introduce:
- **Adaptive Interface**: Single UI that adapts based on device capabilities
- **Micro-frontends**: Independent module deployment
- **WebAssembly Components**: High-performance UI components
- **Native Mobile Apps**: React Native or Flutter implementations
## Troubleshooting
### Common Issues
1. **404 Errors After Rename**:
- Clear browser cache
- Rebuild the project: `cargo clean && cargo build`
- Verify file paths in `ui/suite/` or `ui/minimal/`
2. **Tauri Build Failures**:
- Update `tauri.conf.json` with correct `frontendDist` path
- Ensure `ui/suite/index.html` exists
3. **Static Files Not Loading**:
- Check `ServeDir` configuration in router
- Verify subdirectories (js, css, public) exist in new location
### Debug Commands
```bash
# Verify UI structure
ls -la ui/suite/
ls -la ui/minimal/
# Test minimal interface (default)
curl http://localhost:8080/
# Test suite interface
curl http://localhost:8080/suite/
# Check static file serving
curl http://localhost:8080/js/app.js
curl http://localhost:8080/css/styles.css
```
## Related Documentation
- [GBUI Templates](./chapter-04-gbui/README.md)
- [UI Server Module](../src/core/ui_server/README.md)
- [Desktop Application](./DESKTOP.md)
- [Web Deployment](./WEB_DEPLOYMENT.md)

View file

@ -1,191 +0,0 @@
# Multimodal Configuration Guide
This document describes how to configure botserver to use the botmodels service for image, video, audio generation, and vision/captioning capabilities.
## Overview
The multimodal feature connects botserver to botmodels - a Python-based service similar to llama.cpp but for multimodal AI tasks. This enables BASIC scripts to generate images, videos, audio, and analyze visual content.
## Configuration Keys
Add the following configuration to your bot's `config.csv` file:
### Image Generator Settings
| Key | Default | Description |
|-----|---------|-------------|
| `image-generator-model` | - | Path to the image generation model (e.g., `../../../../data/diffusion/sd_turbo_f16.gguf`) |
| `image-generator-steps` | `4` | Number of inference steps for image generation |
| `image-generator-width` | `512` | Output image width in pixels |
| `image-generator-height` | `512` | Output image height in pixels |
| `image-generator-gpu-layers` | `20` | Number of layers to offload to GPU |
| `image-generator-batch-size` | `1` | Batch size for generation |
### Video Generator Settings
| Key | Default | Description |
|-----|---------|-------------|
| `video-generator-model` | - | Path to the video generation model (e.g., `../../../../data/diffusion/zeroscope_v2_576w`) |
| `video-generator-frames` | `24` | Number of frames to generate |
| `video-generator-fps` | `8` | Frames per second for output video |
| `video-generator-width` | `320` | Output video width in pixels |
| `video-generator-height` | `576` | Output video height in pixels |
| `video-generator-gpu-layers` | `15` | Number of layers to offload to GPU |
| `video-generator-batch-size` | `1` | Batch size for generation |
### BotModels Service Settings
| Key | Default | Description |
|-----|---------|-------------|
| `botmodels-enabled` | `false` | Enable/disable botmodels integration |
| `botmodels-host` | `0.0.0.0` | Host address for botmodels service |
| `botmodels-port` | `8085` | Port for botmodels service |
| `botmodels-api-key` | - | API key for authentication with botmodels |
| `botmodels-https` | `false` | Use HTTPS for connection to botmodels |
## Example config.csv
```csv
key,value
image-generator-model,../../../../data/diffusion/sd_turbo_f16.gguf
image-generator-steps,4
image-generator-width,512
image-generator-height,512
image-generator-gpu-layers,20
image-generator-batch-size,1
video-generator-model,../../../../data/diffusion/zeroscope_v2_576w
video-generator-frames,24
video-generator-fps,8
video-generator-width,320
video-generator-height,576
video-generator-gpu-layers,15
video-generator-batch-size,1
botmodels-enabled,true
botmodels-host,0.0.0.0
botmodels-port,8085
botmodels-api-key,your-secret-key
botmodels-https,false
```
## BASIC Keywords
Once configured, the following keywords become available in BASIC scripts:
### IMAGE
Generate an image from a text prompt.
```basic
file = IMAGE "a cute cat playing with yarn"
SEND FILE TO user, file
```
### VIDEO
Generate a video from a text prompt.
```basic
file = VIDEO "a rocket launching into space"
SEND FILE TO user, file
```
### AUDIO
Generate speech audio from text.
```basic
file = AUDIO "Hello, welcome to our service!"
SEND FILE TO user, file
```
### SEE
Get a caption/description of an image or video file.
```basic
caption = SEE "/path/to/image.jpg"
TALK caption
// Also works with video files
description = SEE "/path/to/video.mp4"
TALK description
```
## Starting BotModels Service
Before using multimodal features, start the botmodels service:
```bash
cd botmodels
python -m uvicorn src.main:app --host 0.0.0.0 --port 8085
```
Or with HTTPS:
```bash
python -m uvicorn src.main:app --host 0.0.0.0 --port 8085 --ssl-keyfile key.pem --ssl-certfile cert.pem
```
## API Endpoints (BotModels)
The botmodels service exposes these REST endpoints:
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/image/generate` | POST | Generate image from prompt |
| `/api/video/generate` | POST | Generate video from prompt |
| `/api/speech/generate` | POST | Generate speech from text |
| `/api/speech/totext` | POST | Convert audio to text |
| `/api/vision/describe` | POST | Get description of an image |
| `/api/vision/describe_video` | POST | Get description of a video |
| `/api/vision/vqa` | POST | Visual question answering |
| `/api/health` | GET | Health check |
All endpoints require the `X-API-Key` header for authentication.
## Architecture
```
┌─────────────┐ HTTPS ┌─────────────┐
│ botserver │ ────────────▶ │ botmodels │
│ (Rust) │ │ (Python) │
└─────────────┘ └─────────────┘
│ │
│ BASIC Keywords │ AI Models
│ - IMAGE │ - Stable Diffusion
│ - VIDEO │ - Zeroscope
│ - AUDIO │ - TTS/Whisper
│ - SEE │ - BLIP2
▼ ▼
┌─────────────┐ ┌─────────────┐
│ config │ │ outputs │
│ .csv │ │ (files) │
└─────────────┘ └─────────────┘
```
## Troubleshooting
### "BotModels is not enabled"
Set `botmodels-enabled=true` in your config.csv.
### Connection refused
1. Ensure botmodels service is running
2. Check host/port configuration
3. Verify firewall settings
### Authentication failed
Ensure `botmodels-api-key` in config.csv matches `API_KEY` environment variable in botmodels.
### Model not found
Verify model paths are correct and models are downloaded to the expected locations.
## Security Notes
1. Always use HTTPS in production (`botmodels-https=true`)
2. Use strong, unique API keys
3. Restrict network access to botmodels service
4. Consider running botmodels on a separate GPU server

View file

@ -36,6 +36,7 @@
# Part IV - User Interface # Part IV - User Interface
- [Chapter 04: .gbui Interface Reference](./chapter-04-gbui/README.md) - [Chapter 04: .gbui Interface Reference](./chapter-04-gbui/README.md)
- [UI Structure](./chapter-04-gbui/ui-structure.md)
- [default.gbui - Full Desktop](./chapter-04-gbui/default-gbui.md) - [default.gbui - Full Desktop](./chapter-04-gbui/default-gbui.md)
- [single.gbui - Simple Chat](./chapter-04-gbui/single-gbui.md) - [single.gbui - Simple Chat](./chapter-04-gbui/single-gbui.md)
- [Console Mode](./chapter-04-gbui/console-mode.md) - [Console Mode](./chapter-04-gbui/console-mode.md)
@ -54,6 +55,7 @@
- [Dialog Basics](./chapter-06-gbdialog/basics.md) - [Dialog Basics](./chapter-06-gbdialog/basics.md)
- [Universal Messaging & Multi-Channel](./chapter-06-gbdialog/universal-messaging.md) - [Universal Messaging & Multi-Channel](./chapter-06-gbdialog/universal-messaging.md)
- [BASIC vs n8n/Zapier/Make](./chapter-06-gbdialog/basic-vs-automation-tools.md) - [BASIC vs n8n/Zapier/Make](./chapter-06-gbdialog/basic-vs-automation-tools.md)
- [Template Variables](./chapter-06-gbdialog/template-variables.md)
- [Template Examples](./chapter-06-gbdialog/templates.md) - [Template Examples](./chapter-06-gbdialog/templates.md)
- [start.bas](./chapter-06-gbdialog/templates/start.md) - [start.bas](./chapter-06-gbdialog/templates/start.md)
- [enrollment.bas](./chapter-06-gbdialog/templates/enrollment.md) - [enrollment.bas](./chapter-06-gbdialog/templates/enrollment.md)
@ -99,6 +101,8 @@
- [KB DOCUMENTS ADDED SINCE](./chapter-06-gbdialog/keyword-kb-documents-added-since.md) - [KB DOCUMENTS ADDED SINCE](./chapter-06-gbdialog/keyword-kb-documents-added-since.md)
- [KB LIST COLLECTIONS](./chapter-06-gbdialog/keyword-kb-list-collections.md) - [KB LIST COLLECTIONS](./chapter-06-gbdialog/keyword-kb-list-collections.md)
- [KB STORAGE SIZE](./chapter-06-gbdialog/keyword-kb-storage-size.md) - [KB STORAGE SIZE](./chapter-06-gbdialog/keyword-kb-storage-size.md)
- [Social Media Keywords](./chapter-06-gbdialog/keywords-social-media.md)
- [Lead Scoring Keywords](./chapter-06-gbdialog/keywords-lead-scoring.md)
- [HTTP & API Operations](./chapter-06-gbdialog/keywords-http.md) - [HTTP & API Operations](./chapter-06-gbdialog/keywords-http.md)
- [POST](./chapter-06-gbdialog/keyword-post.md) - [POST](./chapter-06-gbdialog/keyword-post.md)
- [PUT](./chapter-06-gbdialog/keyword-put.md) - [PUT](./chapter-06-gbdialog/keyword-put.md)
@ -158,6 +162,7 @@
- [LLM Configuration](./chapter-08-config/llm-config.md) - [LLM Configuration](./chapter-08-config/llm-config.md)
- [Context Configuration](./chapter-08-config/context-config.md) - [Context Configuration](./chapter-08-config/context-config.md)
- [Drive Integration](./chapter-08-config/drive.md) - [Drive Integration](./chapter-08-config/drive.md)
- [Multimodal Configuration](./chapter-08-config/multimodal.md)
- [Secrets Management](./chapter-08-config/secrets-management.md) - [Secrets Management](./chapter-08-config/secrets-management.md)
# Part IX - Tools and Integration # Part IX - Tools and Integration
@ -173,7 +178,6 @@
- [LLM REST Server](./chapter-09-api/llm-rest-server.md) - [LLM REST Server](./chapter-09-api/llm-rest-server.md)
- [NVIDIA GPU Setup for LXC](./chapter-09-api/nvidia-gpu-setup.md) - [NVIDIA GPU Setup for LXC](./chapter-09-api/nvidia-gpu-setup.md)
- [Chapter 10: REST API Reference](./chapter-10-api/README.md) - [Chapter 10: REST API Reference](./chapter-10-api/README.md)
- [Files API](./chapter-10-api/files-api.md) - [Files API](./chapter-10-api/files-api.md)
- [Document Processing API](./chapter-10-api/document-processing.md) - [Document Processing API](./chapter-10-api/document-processing.md)
@ -213,7 +217,10 @@
- [Storage and Data](./chapter-11-features/storage.md) - [Storage and Data](./chapter-11-features/storage.md)
- [Multi-Channel Support](./chapter-11-features/channels.md) - [Multi-Channel Support](./chapter-11-features/channels.md)
- [Drive Monitor](./chapter-11-features/drive-monitor.md) - [Drive Monitor](./chapter-11-features/drive-monitor.md)
- [Platform Comparison](./chapter-11-features/platform-comparison.md) - [Platform Capabilities](./chapter-11-features/platform-comparison.md)
- [Enterprise Platform Migration](./chapter-11-features/m365-comparison.md)
- [Projects](./chapter-11-features/projects.md)
- [Multi-Agent Office Suite Design](./chapter-11-features/multi-agent-design.md)
# Part XI - Security # Part XI - Security
@ -243,10 +250,19 @@
- [Chapter 14: Migration Guide](./chapter-14-migration/README.md) - [Chapter 14: Migration Guide](./chapter-14-migration/README.md)
- [Migration Overview](./chapter-14-migration/overview.md) - [Migration Overview](./chapter-14-migration/overview.md)
- [Platform Comparison Matrix](./chapter-14-migration/comparison-matrix.md)
- [Migration Resources](./chapter-14-migration/resources.md)
- [Common Concepts](./chapter-14-migration/common-concepts.md) - [Common Concepts](./chapter-14-migration/common-concepts.md)
- [Knowledge Base Migration](./chapter-14-migration/kb-migration.md) - [Knowledge Base Migration](./chapter-14-migration/kb-migration.md)
- [Google Workspace Integration](./chapter-14-migration/google-workspace.md) - [Cloud Productivity Migration](./chapter-14-migration/google-workspace.md)
- [Microsoft 365 Integration](./chapter-14-migration/microsoft-365.md) - [Enterprise Platform Migration](./chapter-14-migration/microsoft-365.md)
- [n8n Migration](./chapter-14-migration/n8n.md)
- [Notion Migration](./chapter-14-migration/notion.md)
- [Perplexity Migration](./chapter-14-migration/perplexity.md)
- [Zapier and Make Migration](./chapter-14-migration/zapier-make.md)
- [Intercom Migration](./chapter-14-migration/intercom.md)
- [Dialogflow Migration](./chapter-14-migration/dialogflow.md)
- [Botpress Migration](./chapter-14-migration/botpress.md)
- [Automation Migration](./chapter-14-migration/automation.md) - [Automation Migration](./chapter-14-migration/automation.md)
- [Validation and Testing](./chapter-14-migration/validation.md) - [Validation and Testing](./chapter-14-migration/validation.md)

View file

@ -0,0 +1,207 @@
<svg width="1400" height="800" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Modern Gradients -->
<linearGradient id="gbGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:1" />
<stop offset="50%" style="stop-color:#8B5CF6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#A855F7;stop-opacity:1" />
</linearGradient>
<linearGradient id="cloudGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#64748B;stop-opacity:1" />
<stop offset="100%" style="stop-color:#94A3B8;stop-opacity:1" />
</linearGradient>
<linearGradient id="successGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#10B981;stop-opacity:1" />
<stop offset="100%" style="stop-color:#34D399;stop-opacity:1" />
</linearGradient>
<linearGradient id="headerGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#1E1B4B;stop-opacity:0.05" />
<stop offset="50%" style="stop-color:#312E81;stop-opacity:0.08" />
<stop offset="100%" style="stop-color:#1E1B4B;stop-opacity:0.05" />
</linearGradient>
<linearGradient id="flowLine" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:0.2" />
<stop offset="50%" style="stop-color:#8B5CF6;stop-opacity:0.6" />
<stop offset="100%" style="stop-color:#A855F7;stop-opacity:0.2" />
</linearGradient>
<filter id="softGlow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<filter id="dropShadow" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="2" stdDeviation="4" flood-color="#000" flood-opacity="0.1"/>
</filter>
<!-- Arrow marker -->
<marker id="arrowGreen" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#10B981"/>
</marker>
</defs>
<style>
.main-text { fill: #1a1a1a; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.secondary-text { fill: #64748B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.white-text { fill: #ffffff; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.mono-text { fill: #475569; font-family: 'SF Mono', 'Fira Code', Consolas, monospace; }
.accent-text { fill: #6366F1; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
@media (prefers-color-scheme: dark) {
.main-text { fill: #F1F5F9; }
.secondary-text { fill: #94A3B8; }
.mono-text { fill: #CBD5E1; }
}
</style>
<!-- Background subtle pattern -->
<rect width="1400" height="800" fill="#FAFBFC"/>
<rect x="0" y="0" width="1400" height="120" fill="url(#headerGradient)"/>
<!-- Title Section -->
<text x="700" y="50" text-anchor="middle" font-size="28" font-weight="600" class="main-text">API Migration Matrix</text>
<text x="700" y="80" text-anchor="middle" font-size="16" class="secondary-text">Enterprise Cloud APIs → General Bots Keywords</text>
<!-- Platform Labels -->
<g transform="translate(100, 130)">
<!-- Cloud Platform Box -->
<rect x="0" y="0" width="180" height="50" rx="8" fill="url(#cloudGradient)" filter="url(#dropShadow)"/>
<text x="90" y="32" text-anchor="middle" font-size="16" font-weight="600" class="white-text">Cloud Platform</text>
</g>
<g transform="translate(1120, 130)">
<!-- General Bots Box -->
<rect x="0" y="0" width="180" height="50" rx="8" fill="url(#gbGradient)" filter="url(#dropShadow)"/>
<text x="90" y="32" text-anchor="middle" font-size="16" font-weight="600" class="white-text">General Bots</text>
</g>
<!-- Flow Arrow -->
<path d="M300 155 Q700 155 1100 155" stroke="url(#flowLine)" stroke-width="3" fill="none" stroke-dasharray="8,4"/>
<text x="700" y="150" text-anchor="middle" font-size="12" font-weight="500" class="accent-text">MIGRATION PATH</text>
<!-- Comparison Rows -->
<g transform="translate(50, 200)">
<!-- Row 1: Mail -->
<g transform="translate(0, 0)">
<rect x="0" y="0" width="1300" height="60" rx="6" fill="#F8FAFC" stroke="#E2E8F0" stroke-width="1"/>
<circle cx="30" cy="30" r="8" fill="#10B981"/>
<text x="55" y="26" font-size="13" font-weight="600" class="main-text">Email / Mail</text>
<text x="55" y="44" font-size="11" class="mono-text">Messages, Send, Folders</text>
<text x="650" y="35" text-anchor="middle" font-size="20" class="accent-text"></text>
<text x="900" y="26" font-size="13" font-weight="600" class="main-text">SEND MAIL keyword</text>
<text x="900" y="44" font-size="11" class="mono-text">SEND MAIL TO email SUBJECT s BODY b</text>
<rect x="1200" y="15" width="70" height="28" rx="14" fill="url(#successGradient)"/>
<text x="1235" y="34" text-anchor="middle" font-size="11" font-weight="600" class="white-text">READY</text>
</g>
<!-- Row 2: Calendar -->
<g transform="translate(0, 70)">
<rect x="0" y="0" width="1300" height="60" rx="6" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1"/>
<circle cx="30" cy="30" r="8" fill="#10B981"/>
<text x="55" y="26" font-size="13" font-weight="600" class="main-text">Calendar Events</text>
<text x="55" y="44" font-size="11" class="mono-text">Events, Scheduling, Free/Busy</text>
<text x="650" y="35" text-anchor="middle" font-size="20" class="accent-text"></text>
<text x="900" y="26" font-size="13" font-weight="600" class="main-text">BOOK keyword + Calendar API</text>
<text x="900" y="44" font-size="11" class="mono-text">BOOK "Meeting" AT datetime</text>
<rect x="1200" y="15" width="70" height="28" rx="14" fill="url(#successGradient)"/>
<text x="1235" y="34" text-anchor="middle" font-size="11" font-weight="600" class="white-text">READY</text>
</g>
<!-- Row 3: Drive/Files -->
<g transform="translate(0, 140)">
<rect x="0" y="0" width="1300" height="60" rx="6" fill="#F8FAFC" stroke="#E2E8F0" stroke-width="1"/>
<circle cx="30" cy="30" r="8" fill="#10B981"/>
<text x="55" y="26" font-size="13" font-weight="600" class="main-text">Cloud Storage / Files</text>
<text x="55" y="44" font-size="11" class="mono-text">Files, Versions, Sharing</text>
<text x="650" y="35" text-anchor="middle" font-size="20" class="accent-text"></text>
<text x="900" y="26" font-size="13" font-weight="600" class="main-text">SeaweedFS + File Keywords</text>
<text x="900" y="44" font-size="11" class="mono-text">READ, WRITE, LIST, COPY, MOVE, DELETE</text>
<rect x="1200" y="15" width="70" height="28" rx="14" fill="url(#successGradient)"/>
<text x="1235" y="34" text-anchor="middle" font-size="11" font-weight="600" class="white-text">READY</text>
</g>
<!-- Row 4: Tasks -->
<g transform="translate(0, 210)">
<rect x="0" y="0" width="1300" height="60" rx="6" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1"/>
<circle cx="30" cy="30" r="8" fill="#10B981"/>
<text x="55" y="26" font-size="13" font-weight="600" class="main-text">Tasks / Planning</text>
<text x="55" y="44" font-size="11" class="mono-text">Tasks, Lists, Assignments</text>
<text x="650" y="35" text-anchor="middle" font-size="20" class="accent-text"></text>
<text x="900" y="26" font-size="13" font-weight="600" class="main-text">CREATE TASK + Projects</text>
<text x="900" y="44" font-size="11" class="mono-text">CREATE TASK "title" DUE date IN PROJECT id</text>
<rect x="1200" y="15" width="70" height="28" rx="14" fill="url(#successGradient)"/>
<text x="1235" y="34" text-anchor="middle" font-size="11" font-weight="600" class="white-text">READY</text>
</g>
<!-- Row 5: Messaging -->
<g transform="translate(0, 280)">
<rect x="0" y="0" width="1300" height="60" rx="6" fill="#F8FAFC" stroke="#E2E8F0" stroke-width="1"/>
<circle cx="30" cy="30" r="8" fill="#10B981"/>
<text x="55" y="26" font-size="13" font-weight="600" class="main-text">Team Messaging</text>
<text x="55" y="44" font-size="11" class="mono-text">Chat, Channels, Messages</text>
<text x="650" y="35" text-anchor="middle" font-size="20" class="accent-text"></text>
<text x="900" y="26" font-size="13" font-weight="600" class="main-text">TALK + Multi-Channel</text>
<text x="900" y="44" font-size="11" class="mono-text">Web, WhatsApp, Teams, Slack, Telegram</text>
<rect x="1200" y="15" width="70" height="28" rx="14" fill="url(#successGradient)"/>
<text x="1235" y="34" text-anchor="middle" font-size="11" font-weight="600" class="white-text">READY</text>
</g>
<!-- Row 6: Users -->
<g transform="translate(0, 350)">
<rect x="0" y="0" width="1300" height="60" rx="6" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1"/>
<circle cx="30" cy="30" r="8" fill="#10B981"/>
<text x="55" y="26" font-size="13" font-weight="600" class="main-text">Users / Directory</text>
<text x="55" y="44" font-size="11" class="mono-text">Users, Groups, Permissions</text>
<text x="650" y="35" text-anchor="middle" font-size="20" class="accent-text"></text>
<text x="900" y="26" font-size="13" font-weight="600" class="main-text">Zitadel IAM + Users API</text>
<text x="900" y="44" font-size="11" class="mono-text">OIDC/OAuth2 + SCIM provisioning</text>
<rect x="1200" y="15" width="70" height="28" rx="14" fill="url(#successGradient)"/>
<text x="1235" y="34" text-anchor="middle" font-size="11" font-weight="600" class="white-text">READY</text>
</g>
<!-- Row 7: Automation -->
<g transform="translate(0, 420)">
<rect x="0" y="0" width="1300" height="60" rx="6" fill="#F8FAFC" stroke="#E2E8F0" stroke-width="1"/>
<circle cx="30" cy="30" r="8" fill="#10B981"/>
<text x="55" y="26" font-size="13" font-weight="600" class="main-text">Workflow Automation</text>
<text x="55" y="44" font-size="11" class="mono-text">Flows, Triggers, Connectors</text>
<text x="650" y="35" text-anchor="middle" font-size="20" class="accent-text"></text>
<text x="900" y="26" font-size="13" font-weight="600" class="main-text">BASIC Scripts + SET SCHEDULE</text>
<text x="900" y="44" font-size="11" class="mono-text">90+ keywords, webhooks, cron, full logic</text>
<rect x="1200" y="15" width="70" height="28" rx="14" fill="url(#gbGradient)"/>
<text x="1235" y="34" text-anchor="middle" font-size="11" font-weight="600" class="white-text">BETTER</text>
</g>
</g>
<!-- Summary Stats -->
<g transform="translate(100, 720)">
<rect x="0" y="0" width="250" height="60" rx="8" fill="#EEF2FF" stroke="#C7D2FE" stroke-width="1"/>
<text x="125" y="28" text-anchor="middle" font-size="24" font-weight="700" class="accent-text">100%</text>
<text x="125" y="48" text-anchor="middle" font-size="12" class="secondary-text">Feature Parity</text>
</g>
<g transform="translate(400, 720)">
<rect x="0" y="0" width="250" height="60" rx="8" fill="#ECFDF5" stroke="#A7F3D0" stroke-width="1"/>
<text x="125" y="28" text-anchor="middle" font-size="24" font-weight="700" fill="#10B981">90+</text>
<text x="125" y="48" text-anchor="middle" font-size="12" class="secondary-text">BASIC Keywords</text>
</g>
<g transform="translate(700, 720)">
<rect x="0" y="0" width="250" height="60" rx="8" fill="#FEF3C7" stroke="#FCD34D" stroke-width="1"/>
<text x="125" y="28" text-anchor="middle" font-size="24" font-weight="700" fill="#D97706">$0</text>
<text x="125" y="48" text-anchor="middle" font-size="12" class="secondary-text">Per-User Licensing</text>
</g>
<g transform="translate(1000, 720)">
<rect x="0" y="0" width="300" height="60" rx="8" fill="#F0FDF4" stroke="#86EFAC" stroke-width="1"/>
<text x="150" y="28" text-anchor="middle" font-size="24" font-weight="700" fill="#16A34A">Self-Hosted</text>
<text x="150" y="48" text-anchor="middle" font-size="12" class="secondary-text">Full Data Sovereignty</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,234 @@
<svg width="1200" height="500" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Modern Gradients -->
<linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:1" />
<stop offset="100%" style="stop-color:#8B5CF6;stop-opacity:1" />
</linearGradient>
<linearGradient id="cyanGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#06B6D4;stop-opacity:1" />
<stop offset="100%" style="stop-color:#0EA5E9;stop-opacity:1" />
</linearGradient>
<linearGradient id="greenGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#10B981;stop-opacity:1" />
<stop offset="100%" style="stop-color:#34D399;stop-opacity:1" />
</linearGradient>
<linearGradient id="orangeGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#F59E0B;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FBBF24;stop-opacity:1" />
</linearGradient>
<linearGradient id="flowGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:0.2" />
<stop offset="50%" style="stop-color:#8B5CF6;stop-opacity:0.5" />
<stop offset="100%" style="stop-color:#A855F7;stop-opacity:0.2" />
</linearGradient>
<!-- Filters -->
<filter id="cardShadow" x="-10%" y="-10%" width="120%" height="130%">
<feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#6366F1" flood-opacity="0.15"/>
</filter>
<filter id="softGlow" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="2" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<!-- Arrow markers -->
<marker id="arrowPurple" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#8B5CF6"/>
</marker>
<!-- Dot pattern -->
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
</defs>
<style>
.title-text { fill: #1E1B4B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.main-text { fill: #334155; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.secondary-text { fill: #64748B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.white-text { fill: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.mono-text { fill: #475569; font-family: 'SF Mono', 'Fira Code', Consolas, monospace; }
@media (prefers-color-scheme: dark) {
.title-text { fill: #F1F5F9; }
.main-text { fill: #E2E8F0; }
.secondary-text { fill: #94A3B8; }
.mono-text { fill: #CBD5E1; }
}
</style>
<!-- Background -->
<rect width="1200" height="500" fill="#FAFBFC"/>
<rect width="1200" height="500" fill="url(#dots)"/>
<!-- Title -->
<text x="600" y="40" text-anchor="middle" font-size="22" font-weight="600" class="title-text">General Bots Architecture</text>
<text x="600" y="65" text-anchor="middle" font-size="13" class="secondary-text">Single binary • Zero dependencies • Production ready</text>
<!-- Input Layer -->
<g transform="translate(50, 100)">
<text x="80" y="0" text-anchor="middle" font-size="12" font-weight="600" class="secondary-text">CHANNELS</text>
<!-- Web -->
<rect x="0" y="20" width="160" height="50" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<circle cx="30" cy="45" r="15" fill="url(#cyanGrad)"/>
<text x="28" y="50" text-anchor="middle" font-size="12" font-weight="700" class="white-text">W</text>
<text x="100" y="42" text-anchor="middle" font-size="12" font-weight="500" class="main-text">Web Chat</text>
<text x="100" y="56" text-anchor="middle" font-size="10" class="mono-text">WebSocket</text>
<!-- WhatsApp -->
<rect x="0" y="80" width="160" height="50" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<circle cx="30" cy="105" r="15" fill="url(#greenGrad)"/>
<text x="28" y="110" text-anchor="middle" font-size="12" font-weight="700" class="white-text">WA</text>
<text x="100" y="102" text-anchor="middle" font-size="12" font-weight="500" class="main-text">WhatsApp</text>
<text x="100" y="116" text-anchor="middle" font-size="10" class="mono-text">Business API</text>
<!-- Teams -->
<rect x="0" y="140" width="160" height="50" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<circle cx="30" cy="165" r="15" fill="url(#primaryGrad)"/>
<text x="28" y="170" text-anchor="middle" font-size="12" font-weight="700" class="white-text">T</text>
<text x="100" y="162" text-anchor="middle" font-size="12" font-weight="500" class="main-text">Teams</text>
<text x="100" y="176" text-anchor="middle" font-size="10" class="mono-text">Bot Framework</text>
<!-- Voice -->
<rect x="0" y="200" width="160" height="50" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<circle cx="30" cy="225" r="15" fill="url(#orangeGrad)"/>
<text x="28" y="230" text-anchor="middle" font-size="12" font-weight="700" class="white-text">V</text>
<text x="100" y="222" text-anchor="middle" font-size="12" font-weight="500" class="main-text">Voice</text>
<text x="100" y="236" text-anchor="middle" font-size="10" class="mono-text">LiveKit</text>
</g>
<!-- Flow Arrows to Core -->
<g stroke="url(#flowGrad)" stroke-width="2" fill="none">
<path d="M220 145 Q280 145 340 200" marker-end="url(#arrowPurple)"/>
<path d="M220 180 Q270 180 340 210" marker-end="url(#arrowPurple)"/>
<path d="M220 240 Q270 240 340 230" marker-end="url(#arrowPurple)"/>
<path d="M220 320 Q280 320 340 260" marker-end="url(#arrowPurple)"/>
</g>
<!-- Core Processing -->
<g transform="translate(350, 100)">
<text x="225" y="0" text-anchor="middle" font-size="12" font-weight="600" class="secondary-text">CORE RUNTIME</text>
<!-- Main processing box -->
<rect x="0" y="20" width="450" height="260" rx="12" fill="#FFFFFF" stroke="#C7D2FE" stroke-width="2" filter="url(#cardShadow)"/>
<rect x="0" y="20" width="450" height="40" rx="12" fill="url(#primaryGrad)"/>
<rect x="0" y="48" width="450" height="12" fill="url(#primaryGrad)"/>
<text x="225" y="47" text-anchor="middle" font-size="14" font-weight="600" class="white-text">BotServer (Rust)</text>
<!-- Session Manager -->
<rect x="20" y="75" width="200" height="45" rx="6" fill="#EEF2FF" stroke="#C7D2FE" stroke-width="1"/>
<text x="120" y="95" text-anchor="middle" font-size="11" font-weight="600" class="main-text">Session Manager</text>
<text x="120" y="110" text-anchor="middle" font-size="9" class="mono-text">Tokio Async Runtime</text>
<!-- BASIC Interpreter -->
<rect x="230" y="75" width="200" height="45" rx="6" fill="#FEF3C7" stroke="#FCD34D" stroke-width="1"/>
<text x="330" y="95" text-anchor="middle" font-size="11" font-weight="600" class="main-text">BASIC Interpreter</text>
<text x="330" y="110" text-anchor="middle" font-size="9" class="mono-text">90+ Keywords</text>
<!-- LLM Integration -->
<rect x="20" y="130" width="200" height="45" rx="6" fill="#F5F3FF" stroke="#DDD6FE" stroke-width="1"/>
<text x="120" y="150" text-anchor="middle" font-size="11" font-weight="600" class="main-text">LLM Integration</text>
<text x="120" y="165" text-anchor="middle" font-size="9" class="mono-text">OpenAI, Anthropic, Local</text>
<!-- Package Manager -->
<rect x="230" y="130" width="200" height="45" rx="6" fill="#ECFDF5" stroke="#A7F3D0" stroke-width="1"/>
<text x="330" y="150" text-anchor="middle" font-size="11" font-weight="600" class="main-text">Package Manager</text>
<text x="330" y="165" text-anchor="middle" font-size="9" class="mono-text">.gbai, .gbkb, .gbdialog</text>
<!-- RAG Engine -->
<rect x="20" y="185" width="130" height="40" rx="6" fill="#F0FDF4" stroke="#86EFAC" stroke-width="1"/>
<text x="85" y="202" text-anchor="middle" font-size="10" font-weight="600" class="main-text">RAG Engine</text>
<text x="85" y="216" text-anchor="middle" font-size="8" class="mono-text">Qdrant Vectors</text>
<!-- Tool Executor -->
<rect x="160" y="185" width="130" height="40" rx="6" fill="#FFF7ED" stroke="#FDBA74" stroke-width="1"/>
<text x="225" y="202" text-anchor="middle" font-size="10" font-weight="600" class="main-text">Tool Executor</text>
<text x="225" y="216" text-anchor="middle" font-size="8" class="mono-text">Function Calling</text>
<!-- API Server -->
<rect x="300" y="185" width="130" height="40" rx="6" fill="#EFF6FF" stroke="#93C5FD" stroke-width="1"/>
<text x="365" y="202" text-anchor="middle" font-size="10" font-weight="600" class="main-text">REST API</text>
<text x="365" y="216" text-anchor="middle" font-size="8" class="mono-text">Axum Server</text>
<!-- Data services bar -->
<rect x="20" y="235" width="410" height="35" rx="6" fill="#F8FAFC" stroke="#E2E8F0" stroke-width="1"/>
<text x="60" y="257" text-anchor="middle" font-size="9" class="mono-text">PostgreSQL</text>
<text x="140" y="257" text-anchor="middle" font-size="9" class="mono-text">SeaweedFS</text>
<text x="220" y="257" text-anchor="middle" font-size="9" class="mono-text">Valkey</text>
<text x="300" y="257" text-anchor="middle" font-size="9" class="mono-text">Zitadel</text>
<text x="380" y="257" text-anchor="middle" font-size="9" class="mono-text">Stalwart</text>
</g>
<!-- Flow Arrows to Output -->
<g stroke="url(#flowGrad)" stroke-width="2" fill="none">
<path d="M810 200 Q870 200 920 150" marker-end="url(#arrowPurple)"/>
<path d="M810 230 Q870 230 920 230" marker-end="url(#arrowPurple)"/>
<path d="M810 260 Q870 260 920 310" marker-end="url(#arrowPurple)"/>
</g>
<!-- Output Layer -->
<g transform="translate(930, 100)">
<text x="110" y="0" text-anchor="middle" font-size="12" font-weight="600" class="secondary-text">OUTPUT</text>
<!-- Responses -->
<rect x="0" y="30" width="220" height="50" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<circle cx="30" cy="55" r="15" fill="url(#primaryGrad)"/>
<text x="28" y="60" text-anchor="middle" font-size="10" font-weight="700" class="white-text">💬</text>
<text x="130" y="52" text-anchor="middle" font-size="12" font-weight="500" class="main-text">Conversations</text>
<text x="130" y="66" text-anchor="middle" font-size="10" class="mono-text">Text, Voice, Rich Media</text>
<!-- Actions -->
<rect x="0" y="95" width="220" height="50" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<circle cx="30" cy="120" r="15" fill="url(#greenGrad)"/>
<text x="28" y="125" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="130" y="117" text-anchor="middle" font-size="12" font-weight="500" class="main-text">Automations</text>
<text x="130" y="131" text-anchor="middle" font-size="10" class="mono-text">Webhooks, Schedules</text>
<!-- Data -->
<rect x="0" y="160" width="220" height="50" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<circle cx="30" cy="185" r="15" fill="url(#cyanGrad)"/>
<text x="28" y="190" text-anchor="middle" font-size="10" font-weight="700" class="white-text">📊</text>
<text x="130" y="182" text-anchor="middle" font-size="12" font-weight="500" class="main-text">Data & Files</text>
<text x="130" y="196" text-anchor="middle" font-size="10" class="mono-text">Drive, Mail, Calendar</text>
</g>
<!-- Bottom stats bar -->
<g transform="translate(100, 420)">
<rect x="0" y="0" width="1000" height="60" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#cardShadow)"/>
<g transform="translate(50, 15)">
<rect x="0" y="0" width="150" height="30" rx="6" fill="#EEF2FF"/>
<text x="75" y="20" text-anchor="middle" font-size="12" font-weight="600" class="main-text">Single Binary</text>
</g>
<g transform="translate(230, 15)">
<rect x="0" y="0" width="150" height="30" rx="6" fill="#ECFDF5"/>
<text x="75" y="20" text-anchor="middle" font-size="12" font-weight="600" class="main-text">Self-Hosted</text>
</g>
<g transform="translate(410, 15)">
<rect x="0" y="0" width="150" height="30" rx="6" fill="#FEF3C7"/>
<text x="75" y="20" text-anchor="middle" font-size="12" font-weight="600" class="main-text">Open Source</text>
</g>
<g transform="translate(590, 15)">
<rect x="0" y="0" width="150" height="30" rx="6" fill="#F0FDF4"/>
<text x="75" y="20" text-anchor="middle" font-size="12" font-weight="600" class="main-text">AI-First</text>
</g>
<g transform="translate(770, 15)">
<rect x="0" y="0" width="150" height="30" rx="6" fill="#F5F3FF"/>
<text x="75" y="20" text-anchor="middle" font-size="12" font-weight="600" class="main-text">No Forms</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,261 @@
<svg width="1200" height="650" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Modern Gradients -->
<linearGradient id="primaryGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:1" />
<stop offset="100%" style="stop-color:#8B5CF6;stop-opacity:1" />
</linearGradient>
<linearGradient id="secondaryGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#06B6D4;stop-opacity:1" />
<stop offset="100%" style="stop-color:#0EA5E9;stop-opacity:1" />
</linearGradient>
<linearGradient id="successGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#10B981;stop-opacity:1" />
<stop offset="100%" style="stop-color:#34D399;stop-opacity:1" />
</linearGradient>
<linearGradient id="warningGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#F59E0B;stop-opacity:1" />
<stop offset="100%" style="stop-color:#FBBF24;stop-opacity:1" />
</linearGradient>
<linearGradient id="flowLineGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:0.3" />
<stop offset="50%" style="stop-color:#8B5CF6;stop-opacity:0.7" />
<stop offset="100%" style="stop-color:#A855F7;stop-opacity:0.3" />
</linearGradient>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#F8FAFC;stop-opacity:1" />
<stop offset="100%" style="stop-color:#F1F5F9;stop-opacity:1" />
</linearGradient>
<!-- Filters -->
<filter id="cardShadow" x="-10%" y="-10%" width="120%" height="130%">
<feDropShadow dx="0" dy="4" stdDeviation="8" flood-color="#6366F1" flood-opacity="0.15"/>
</filter>
<filter id="glowEffect" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<!-- Arrow markers -->
<marker id="arrowPrimary" markerWidth="12" markerHeight="12" refX="10" refY="4" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,8 L12,4 z" fill="#8B5CF6"/>
</marker>
<marker id="arrowSuccess" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L10,3 z" fill="#10B981"/>
</marker>
<!-- Dot pattern -->
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.1"/>
</pattern>
</defs>
<style>
.title-text { fill: #1E1B4B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.main-text { fill: #334155; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.secondary-text { fill: #64748B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.white-text { fill: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.mono-text { fill: #475569; font-family: 'SF Mono', 'Fira Code', Consolas, monospace; }
.accent-text { fill: #6366F1; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
@media (prefers-color-scheme: dark) {
.title-text { fill: #F1F5F9; }
.main-text { fill: #E2E8F0; }
.secondary-text { fill: #94A3B8; }
.mono-text { fill: #CBD5E1; }
}
</style>
<!-- Background -->
<rect width="1200" height="650" fill="url(#bgGradient)"/>
<rect width="1200" height="650" fill="url(#dots)"/>
<!-- Title -->
<text x="600" y="45" text-anchor="middle" font-size="26" font-weight="700" class="title-text">Feature Parity Flow</text>
<text x="600" y="72" text-anchor="middle" font-size="14" class="secondary-text">From Enterprise Cloud Services to Self-Hosted Freedom</text>
<!-- Source Platform Box -->
<g transform="translate(50, 110)">
<rect x="0" y="0" width="300" height="400" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect x="0" y="0" width="300" height="50" rx="12" fill="url(#secondaryGradient)"/>
<rect x="0" y="38" width="300" height="12" fill="url(#secondaryGradient)"/>
<text x="150" y="32" text-anchor="middle" font-size="16" font-weight="600" class="white-text">Enterprise Cloud</text>
<!-- Service items -->
<g transform="translate(20, 70)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F1F5F9"/>
<circle cx="20" cy="20" r="12" fill="#0078D4"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">Exchange Online</text>
<text x="45" y="32" font-size="10" class="mono-text">Mail, Calendar, Contacts</text>
</g>
<g transform="translate(20, 120)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F8FAFC"/>
<circle cx="20" cy="20" r="12" fill="#0078D4"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">OneDrive / SharePoint</text>
<text x="45" y="32" font-size="10" class="mono-text">Files, Versioning, Sharing</text>
</g>
<g transform="translate(20, 170)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F1F5F9"/>
<circle cx="20" cy="20" r="12" fill="#0078D4"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">Teams</text>
<text x="45" y="32" font-size="10" class="mono-text">Chat, Video, Collaboration</text>
</g>
<g transform="translate(20, 220)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F8FAFC"/>
<circle cx="20" cy="20" r="12" fill="#0078D4"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">Power Automate</text>
<text x="45" y="32" font-size="10" class="mono-text">Workflows, Triggers</text>
</g>
<g transform="translate(20, 270)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F1F5F9"/>
<circle cx="20" cy="20" r="12" fill="#0078D4"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">Copilot</text>
<text x="45" y="32" font-size="10" class="mono-text">AI Assistant ($30/user)</text>
</g>
<g transform="translate(20, 320)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F8FAFC"/>
<circle cx="20" cy="20" r="12" fill="#0078D4"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">Azure AD / Entra</text>
<text x="45" y="32" font-size="10" class="mono-text">Identity, Auth, SSO</text>
</g>
</g>
<!-- Migration Arrow Center -->
<g transform="translate(380, 250)">
<!-- Flow line -->
<path d="M0,60 Q220,60 440,60" stroke="url(#flowLineGradient)" stroke-width="4" fill="none" marker-end="url(#arrowPrimary)"/>
<!-- Migration badge -->
<rect x="170" y="20" width="100" height="80" rx="10" fill="url(#primaryGradient)" filter="url(#glowEffect)"/>
<text x="220" y="55" text-anchor="middle" font-size="11" font-weight="600" class="white-text">MIGRATE</text>
<text x="220" y="72" text-anchor="middle" font-size="10" class="white-text" opacity="0.8">100% Parity</text>
<!-- Checkmarks -->
<g transform="translate(190, 95)">
<circle cx="0" cy="0" r="10" fill="url(#successGradient)"/>
<path d="M-4,0 L-1,3 L5,-3" stroke="#FFF" stroke-width="2" fill="none"/>
</g>
<g transform="translate(220, 95)">
<circle cx="0" cy="0" r="10" fill="url(#successGradient)"/>
<path d="M-4,0 L-1,3 L5,-3" stroke="#FFF" stroke-width="2" fill="none"/>
</g>
<g transform="translate(250, 95)">
<circle cx="0" cy="0" r="10" fill="url(#successGradient)"/>
<path d="M-4,0 L-1,3 L5,-3" stroke="#FFF" stroke-width="2" fill="none"/>
</g>
</g>
<!-- Target Platform Box -->
<g transform="translate(850, 110)">
<rect x="0" y="0" width="300" height="400" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect x="0" y="0" width="300" height="50" rx="12" fill="url(#primaryGradient)"/>
<rect x="0" y="38" width="300" height="12" fill="url(#primaryGradient)"/>
<text x="150" y="32" text-anchor="middle" font-size="16" font-weight="600" class="white-text">General Bots</text>
<!-- Service items -->
<g transform="translate(20, 70)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#EEF2FF"/>
<circle cx="20" cy="20" r="12" fill="url(#primaryGradient)"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">Stalwart Mail</text>
<text x="45" y="32" font-size="10" class="mono-text">IMAP/SMTP/JMAP + CalDAV</text>
</g>
<g transform="translate(20, 120)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F5F3FF"/>
<circle cx="20" cy="20" r="12" fill="url(#primaryGradient)"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">SeaweedFS Drive</text>
<text x="45" y="32" font-size="10" class="mono-text">S3-compatible + Versioning</text>
</g>
<g transform="translate(20, 170)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#EEF2FF"/>
<circle cx="20" cy="20" r="12" fill="url(#primaryGradient)"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">LiveKit Meet</text>
<text x="45" y="32" font-size="10" class="mono-text">WebRTC + Multi-channel</text>
</g>
<g transform="translate(20, 220)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F5F3FF"/>
<circle cx="20" cy="20" r="12" fill="url(#primaryGradient)"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">BASIC Scripts</text>
<text x="45" y="32" font-size="10" class="mono-text">90+ Keywords + Cron</text>
</g>
<g transform="translate(20, 270)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#EEF2FF"/>
<circle cx="20" cy="20" r="12" fill="url(#primaryGradient)"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">LLM Integration</text>
<text x="45" y="32" font-size="10" class="mono-text">Any Provider (Free)</text>
</g>
<g transform="translate(20, 320)">
<rect x="0" y="0" width="260" height="40" rx="6" fill="#F5F3FF"/>
<circle cx="20" cy="20" r="12" fill="url(#primaryGradient)"/>
<text x="45" y="17" font-size="12" font-weight="600" class="main-text">Zitadel IAM</text>
<text x="45" y="32" font-size="10" class="mono-text">OIDC/OAuth2 + MFA</text>
</g>
</g>
<!-- Benefits Bar -->
<g transform="translate(50, 540)">
<rect x="0" y="0" width="1100" height="80" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1"/>
<!-- Benefit 1 -->
<g transform="translate(50, 15)">
<rect x="0" y="0" width="200" height="50" rx="8" fill="#ECFDF5"/>
<circle cx="25" cy="25" r="15" fill="url(#successGradient)"/>
<text x="22" y="30" text-anchor="middle" font-size="14" font-weight="700" class="white-text"></text>
<text x="55" y="22" font-size="12" font-weight="600" class="main-text">Self-Hosted</text>
<text x="55" y="38" font-size="10" class="secondary-text">Full Data Control</text>
</g>
<!-- Benefit 2 -->
<g transform="translate(280, 15)">
<rect x="0" y="0" width="200" height="50" rx="8" fill="#EEF2FF"/>
<circle cx="25" cy="25" r="15" fill="url(#primaryGradient)"/>
<text x="25" y="31" text-anchor="middle" font-size="14" font-weight="700" class="white-text">$0</text>
<text x="55" y="22" font-size="12" font-weight="600" class="main-text">No Per-User Fee</text>
<text x="55" y="38" font-size="10" class="secondary-text">Unlimited Users</text>
</g>
<!-- Benefit 3 -->
<g transform="translate(510, 15)">
<rect x="0" y="0" width="200" height="50" rx="8" fill="#FEF3C7"/>
<circle cx="25" cy="25" r="15" fill="url(#warningGradient)"/>
<text x="25" y="31" text-anchor="middle" font-size="12" font-weight="700" class="white-text">AI</text>
<text x="55" y="22" font-size="12" font-weight="600" class="main-text">Native LLM</text>
<text x="55" y="38" font-size="10" class="secondary-text">Built-in RAG + Tools</text>
</g>
<!-- Benefit 4 -->
<g transform="translate(740, 15)">
<rect x="0" y="0" width="200" height="50" rx="8" fill="#F0FDF4"/>
<circle cx="25" cy="25" r="15" fill="url(#successGradient)"/>
<text x="25" y="31" text-anchor="middle" font-size="10" font-weight="700" class="white-text">OSS</text>
<text x="55" y="22" font-size="12" font-weight="600" class="main-text">Open Source</text>
<text x="55" y="38" font-size="10" class="secondary-text">AGPL Licensed</text>
</g>
<!-- Benefit 5 -->
<g transform="translate(970, 15)">
<rect x="0" y="0" width="80" height="50" rx="8" fill="#EEF2FF"/>
<text x="40" y="30" text-anchor="middle" font-size="20" font-weight="700" class="accent-text">90+</text>
<text x="40" y="45" text-anchor="middle" font-size="9" class="secondary-text">Keywords</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -0,0 +1,124 @@
<svg width="1200" height="200" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Primary brand gradient -->
<linearGradient id="brandGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:1" />
<stop offset="30%" style="stop-color:#8B5CF6;stop-opacity:1" />
<stop offset="60%" style="stop-color:#A855F7;stop-opacity:1" />
<stop offset="100%" style="stop-color:#D946EF;stop-opacity:1" />
</linearGradient>
<!-- Accent gradient -->
<linearGradient id="accentGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#06B6D4;stop-opacity:1" />
<stop offset="50%" style="stop-color:#3B82F6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#6366F1;stop-opacity:1" />
</linearGradient>
<!-- Subtle mesh gradient background -->
<radialGradient id="meshGradient1" cx="20%" cy="30%" r="60%" fx="20%" fy="30%">
<stop offset="0%" style="stop-color:#818CF8;stop-opacity:0.15" />
<stop offset="100%" style="stop-color:#818CF8;stop-opacity:0" />
</radialGradient>
<radialGradient id="meshGradient2" cx="80%" cy="70%" r="50%" fx="80%" fy="70%">
<stop offset="0%" style="stop-color:#C084FC;stop-opacity:0.12" />
<stop offset="100%" style="stop-color:#C084FC;stop-opacity:0" />
</radialGradient>
<radialGradient id="meshGradient3" cx="50%" cy="20%" r="40%" fx="50%" fy="20%">
<stop offset="0%" style="stop-color:#22D3EE;stop-opacity:0.1" />
<stop offset="100%" style="stop-color:#22D3EE;stop-opacity:0" />
</radialGradient>
<!-- Glow filter -->
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="4" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<!-- Soft shadow -->
<filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="2" stdDeviation="6" flood-color="#6366F1" flood-opacity="0.25"/>
</filter>
<!-- Wave pattern -->
<pattern id="wavePattern" patternUnits="userSpaceOnUse" width="100" height="20" patternTransform="rotate(-5)">
<path d="M0 10 Q25 0 50 10 T100 10" stroke="url(#brandGradient)" stroke-width="0.5" fill="none" opacity="0.3"/>
</pattern>
<!-- Dot pattern -->
<pattern id="dotPattern" patternUnits="userSpaceOnUse" width="30" height="30">
<circle cx="15" cy="15" r="1" fill="#6366F1" opacity="0.15"/>
</pattern>
</defs>
<style>
.header-text { fill: #1E1B4B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.sub-text { fill: #64748B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
@media (prefers-color-scheme: dark) {
.header-text { fill: #F1F5F9; }
.sub-text { fill: #94A3B8; }
}
</style>
<!-- Background layers -->
<rect width="1200" height="200" fill="#FAFBFC"/>
<rect width="1200" height="200" fill="url(#dotPattern)"/>
<rect width="1200" height="200" fill="url(#meshGradient1)"/>
<rect width="1200" height="200" fill="url(#meshGradient2)"/>
<rect width="1200" height="200" fill="url(#meshGradient3)"/>
<!-- Decorative wave lines -->
<rect x="0" y="60" width="1200" height="80" fill="url(#wavePattern)" opacity="0.5"/>
<!-- Decorative circles -->
<circle cx="100" cy="100" r="80" fill="none" stroke="url(#brandGradient)" stroke-width="1" opacity="0.2"/>
<circle cx="100" cy="100" r="60" fill="none" stroke="url(#accentGradient)" stroke-width="0.5" opacity="0.3"/>
<circle cx="100" cy="100" r="40" fill="none" stroke="url(#brandGradient)" stroke-width="0.5" opacity="0.4"/>
<circle cx="1100" cy="100" r="70" fill="none" stroke="url(#brandGradient)" stroke-width="1" opacity="0.2"/>
<circle cx="1100" cy="100" r="50" fill="none" stroke="url(#accentGradient)" stroke-width="0.5" opacity="0.3"/>
<circle cx="1100" cy="100" r="30" fill="none" stroke="url(#brandGradient)" stroke-width="0.5" opacity="0.4"/>
<!-- Floating shapes -->
<g opacity="0.6">
<rect x="200" y="30" width="12" height="12" rx="2" fill="url(#brandGradient)" transform="rotate(15 206 36)"/>
<rect x="950" y="150" width="10" height="10" rx="2" fill="url(#accentGradient)" transform="rotate(-20 955 155)"/>
<circle cx="300" cy="160" r="5" fill="#A855F7" opacity="0.5"/>
<circle cx="850" cy="40" r="4" fill="#06B6D4" opacity="0.6"/>
<circle cx="1000" cy="80" r="3" fill="#8B5CF6" opacity="0.5"/>
<circle cx="180" cy="70" r="3" fill="#3B82F6" opacity="0.5"/>
</g>
<!-- Central decorative element -->
<g transform="translate(600, 100)" filter="url(#softShadow)">
<!-- Outer ring -->
<circle cx="0" cy="0" r="45" fill="none" stroke="url(#brandGradient)" stroke-width="2" stroke-dasharray="8 4" opacity="0.4"/>
<!-- Inner hexagon shape -->
<path d="M0,-30 L26,-15 L26,15 L0,30 L-26,15 L-26,-15 Z"
fill="none" stroke="url(#accentGradient)" stroke-width="1.5" opacity="0.5"/>
<!-- Center dot -->
<circle cx="0" cy="0" r="8" fill="url(#brandGradient)" filter="url(#glow)"/>
<circle cx="0" cy="0" r="4" fill="#FFFFFF"/>
</g>
<!-- Connecting lines -->
<g stroke="url(#brandGradient)" stroke-width="1" opacity="0.2">
<line x1="170" y1="100" x2="555" y2="100"/>
<line x1="645" y1="100" x2="1030" y2="100"/>
</g>
<!-- Gradient accent line at bottom -->
<rect x="0" y="195" width="1200" height="5" fill="url(#brandGradient)" opacity="0.8"/>
<!-- Corner accents -->
<path d="M0,0 L50,0 L50,5 L5,5 L5,50 L0,50 Z" fill="url(#brandGradient)" opacity="0.3"/>
<path d="M1200,0 L1150,0 L1150,5 L1195,5 L1195,50 L1200,50 Z" fill="url(#brandGradient)" opacity="0.3"/>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -0,0 +1,329 @@
<svg width="1200" height="700" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- Gradients -->
<linearGradient id="gbGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#6366F1;stop-opacity:1" />
<stop offset="50%" style="stop-color:#8B5CF6;stop-opacity:1" />
<stop offset="100%" style="stop-color:#A855F7;stop-opacity:1" />
</linearGradient>
<linearGradient id="successGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#10B981;stop-opacity:1" />
<stop offset="100%" style="stop-color:#34D399;stop-opacity:1" />
</linearGradient>
<linearGradient id="grayGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#64748B;stop-opacity:1" />
<stop offset="100%" style="stop-color:#94A3B8;stop-opacity:1" />
</linearGradient>
<linearGradient id="headerBg" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#1E1B4B;stop-opacity:0.05" />
<stop offset="50%" style="stop-color:#312E81;stop-opacity:0.08" />
<stop offset="100%" style="stop-color:#1E1B4B;stop-opacity:0.05" />
</linearGradient>
<!-- Filters -->
<filter id="shadow" x="-10%" y="-10%" width="120%" height="130%">
<feDropShadow dx="0" dy="4" stdDeviation="6" flood-color="#6366F1" flood-opacity="0.15"/>
</filter>
<!-- Pattern -->
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
</defs>
<style>
.title-text { fill: #1E1B4B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.main-text { fill: #334155; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.secondary-text { fill: #64748B; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.white-text { fill: #FFFFFF; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
.accent-text { fill: #6366F1; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
@media (prefers-color-scheme: dark) {
.title-text { fill: #F1F5F9; }
.main-text { fill: #E2E8F0; }
.secondary-text { fill: #94A3B8; }
}
</style>
<!-- Background -->
<rect width="1200" height="700" fill="#FAFBFC"/>
<rect width="1200" height="700" fill="url(#dots)"/>
<rect x="0" y="0" width="1200" height="100" fill="url(#headerBg)"/>
<!-- Title -->
<text x="600" y="45" text-anchor="middle" font-size="26" font-weight="700" class="title-text">Platform Comparison Summary</text>
<text x="600" y="75" text-anchor="middle" font-size="14" class="secondary-text">General Bots vs Enterprise Cloud Platforms</text>
<!-- General Bots Card (Highlighted) -->
<g transform="translate(50, 120)">
<rect x="0" y="0" width="280" height="460" rx="12" fill="#FFFFFF" stroke="#C7D2FE" stroke-width="2" filter="url(#shadow)"/>
<rect x="0" y="0" width="280" height="60" rx="12" fill="url(#gbGradient)"/>
<rect x="0" y="48" width="280" height="12" fill="url(#gbGradient)"/>
<text x="140" y="40" text-anchor="middle" font-size="18" font-weight="700" class="white-text">General Bots</text>
<!-- Features -->
<g transform="translate(20, 80)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Self-Hosted</text>
</g>
<g transform="translate(20, 115)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Open Source (AGPL)</text>
</g>
<g transform="translate(20, 150)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">No Per-User Fees</text>
</g>
<g transform="translate(20, 185)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Native AI (Any LLM)</text>
</g>
<g transform="translate(20, 220)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Full Productivity Suite</text>
</g>
<g transform="translate(20, 255)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Multi-Channel Chat</text>
</g>
<g transform="translate(20, 290)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Unlimited Automation</text>
</g>
<g transform="translate(20, 325)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">BASIC Scripting</text>
</g>
<g transform="translate(20, 360)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Data Sovereignty</text>
</g>
<!-- Price -->
<rect x="20" y="395" width="240" height="45" rx="8" fill="#ECFDF5" stroke="#A7F3D0" stroke-width="1"/>
<text x="140" y="418" text-anchor="middle" font-size="14" font-weight="700" fill="#10B981">$3K-12K/year</text>
<text x="140" y="433" text-anchor="middle" font-size="10" class="secondary-text">100 users • Infrastructure only</text>
</g>
<!-- Enterprise Cloud Card -->
<g transform="translate(360, 120)">
<rect x="0" y="0" width="280" height="460" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#shadow)"/>
<rect x="0" y="0" width="280" height="60" rx="12" fill="url(#grayGradient)"/>
<rect x="0" y="48" width="280" height="12" fill="url(#grayGradient)"/>
<text x="140" y="40" text-anchor="middle" font-size="18" font-weight="700" class="white-text">Enterprise Cloud</text>
<!-- Features -->
<g transform="translate(20, 80)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Cloud Only</text>
</g>
<g transform="translate(20, 115)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Proprietary</text>
</g>
<g transform="translate(20, 150)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">$12-57/user/month</text>
</g>
<g transform="translate(20, 185)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">$</text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">AI Extra ($30/user)</text>
</g>
<g transform="translate(20, 220)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Full Productivity Suite</text>
</g>
<g transform="translate(20, 255)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">$</text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Limited Channels</text>
</g>
<g transform="translate(20, 290)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">$</text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Per-Flow Fees</text>
</g>
<g transform="translate(20, 325)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">~</text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Limited Scripting</text>
</g>
<g transform="translate(20, 360)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="30" y="16" font-size="13" font-weight="500" class="main-text">Vendor Controlled</text>
</g>
<!-- Price -->
<rect x="20" y="395" width="240" height="45" rx="8" fill="#FEF2F2" stroke="#FECACA" stroke-width="1"/>
<text x="140" y="418" text-anchor="middle" font-size="14" font-weight="700" fill="#DC2626">$50K-90K/year</text>
<text x="140" y="433" text-anchor="middle" font-size="10" class="secondary-text">100 users • Base + AI + Automation</text>
</g>
<!-- Automation Platforms Card -->
<g transform="translate(670, 120)">
<rect x="0" y="0" width="230" height="460" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#shadow)"/>
<rect x="0" y="0" width="230" height="60" rx="12" fill="url(#grayGradient)"/>
<rect x="0" y="48" width="230" height="12" fill="url(#grayGradient)"/>
<text x="115" y="40" text-anchor="middle" font-size="16" font-weight="700" class="white-text">Automation Tools</text>
<g transform="translate(15, 80)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">~</text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Some Self-Host</text>
</g>
<g transform="translate(15, 115)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">~</text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Fair-code/Proprietary</text>
</g>
<g transform="translate(15, 150)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">$</text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Per-Task Pricing</text>
</g>
<g transform="translate(15, 185)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">$</text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">AI via Connectors</text>
</g>
<g transform="translate(15, 220)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">No Productivity Suite</text>
</g>
<g transform="translate(15, 255)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">No Native Chat</text>
</g>
<g transform="translate(15, 290)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Visual Workflows</text>
</g>
<g transform="translate(15, 325)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">~</text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">JS/Visual Only</text>
</g>
<g transform="translate(15, 360)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">~</text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Partial Control</text>
</g>
<rect x="15" y="395" width="200" height="45" rx="8" fill="#FEF3C7" stroke="#FCD34D" stroke-width="1"/>
<text x="115" y="418" text-anchor="middle" font-size="14" font-weight="700" fill="#D97706">$15K-30K/year</text>
<text x="115" y="433" text-anchor="middle" font-size="10" class="secondary-text">+ external tools needed</text>
</g>
<!-- AI Assistants Card -->
<g transform="translate(920, 120)">
<rect x="0" y="0" width="230" height="460" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1" filter="url(#shadow)"/>
<rect x="0" y="0" width="230" height="60" rx="12" fill="url(#grayGradient)"/>
<rect x="0" y="48" width="230" height="12" fill="url(#grayGradient)"/>
<text x="115" y="40" text-anchor="middle" font-size="16" font-weight="700" class="white-text">AI Assistants</text>
<g transform="translate(15, 80)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Cloud Only</text>
</g>
<g transform="translate(15, 115)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Proprietary</text>
</g>
<g transform="translate(15, 150)">
<circle cx="10" cy="12" r="8" fill="#FBBF24"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text">$</text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Subscription Based</text>
</g>
<g transform="translate(15, 185)">
<circle cx="10" cy="12" r="8" fill="url(#successGradient)"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Strong AI Built-in</text>
</g>
<g transform="translate(15, 220)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">No Productivity Suite</text>
</g>
<g transform="translate(15, 255)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">Web Interface Only</text>
</g>
<g transform="translate(15, 290)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">No Automation</text>
</g>
<g transform="translate(15, 325)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">No Scripting</text>
</g>
<g transform="translate(15, 360)">
<circle cx="10" cy="12" r="8" fill="#F87171"/>
<text x="8" y="16" text-anchor="middle" font-size="10" font-weight="700" class="white-text"></text>
<text x="28" y="16" font-size="12" font-weight="500" class="main-text">No Data Control</text>
</g>
<rect x="15" y="395" width="200" height="45" rx="8" fill="#F8FAFC" stroke="#E2E8F0" stroke-width="1"/>
<text x="115" y="418" text-anchor="middle" font-size="14" font-weight="700" class="secondary-text">$2K-5K/year</text>
<text x="115" y="433" text-anchor="middle" font-size="10" class="secondary-text">Chat only • Limited scope</text>
</g>
<!-- Bottom Summary -->
<g transform="translate(50, 605)">
<rect x="0" y="0" width="1100" height="70" rx="10" fill="#FFFFFF" stroke="#C7D2FE" stroke-width="2" filter="url(#shadow)"/>
<g transform="translate(30, 15)">
<rect x="0" y="0" width="200" height="40" rx="6" fill="#EEF2FF"/>
<text x="100" y="18" text-anchor="middle" font-size="18" font-weight="700" class="accent-text">75-95%</text>
<text x="100" y="33" text-anchor="middle" font-size="10" class="secondary-text">Cost Reduction</text>
</g>
<g transform="translate(260, 15)">
<rect x="0" y="0" width="200" height="40" rx="6" fill="#ECFDF5"/>
<text x="100" y="18" text-anchor="middle" font-size="18" font-weight="700" fill="#10B981">100%</text>
<text x="100" y="33" text-anchor="middle" font-size="10" class="secondary-text">Data Sovereignty</text>
</g>
<g transform="translate(490, 15)">
<rect x="0" y="0" width="200" height="40" rx="6" fill="#F5F3FF"/>
<text x="100" y="18" text-anchor="middle" font-size="18" font-weight="700" class="accent-text">90+</text>
<text x="100" y="33" text-anchor="middle" font-size="10" class="secondary-text">BASIC Keywords</text>
</g>
<g transform="translate(720, 15)">
<rect x="0" y="0" width="200" height="40" rx="6" fill="#FEF3C7"/>
<text x="100" y="18" text-anchor="middle" font-size="18" font-weight="700" fill="#D97706"></text>
<text x="100" y="33" text-anchor="middle" font-size="10" class="secondary-text">Unlimited Users</text>
</g>
<g transform="translate(950, 15)">
<rect x="0" y="0" width="120" height="40" rx="6" fill="url(#gbGradient)"/>
<text x="60" y="27" text-anchor="middle" font-size="12" font-weight="600" class="white-text">Open Source</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,240 @@
# UI Structure
The BotServer UI system provides two interface implementations designed for different deployment scenarios. Choose the right interface based on your use case and performance requirements.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Directory Layout
```
ui/
├── suite/ # Full-featured interface
│ ├── index.html
│ ├── js/
│ ├── css/
│ ├── public/
│ ├── drive/
│ ├── chat/
│ ├── mail/
│ ├── tasks/
│ ├── default.gbui
│ └── single.gbui
└── minimal/ # Lightweight interface
├── index.html
├── styles.css
└── app.js
```
## Suite Interface
The Suite interface (`ui/suite/`) delivers a comprehensive, desktop-class experience with multi-application integration. It includes Chat, Drive, Tasks, and Mail modules in a unified workspace.
**Capabilities:**
- Multi-application integration with seamless navigation
- Rich interactions and complex workflows
- Responsive design across desktop, tablet, and mobile
- Customizable GBUI templates (`default.gbui` for full layout, `single.gbui` for chat-focused)
- Tauri integration for native desktop packaging
**When to use Suite:**
- Enterprise deployments requiring full functionality
- Power users working with multiple services
- Desktop application distribution via Tauri
- Multi-service integrations where context switching matters
**Access:**
- Web: `http://localhost:8080/suite`
- Desktop: Via Tauri build with `--desktop` flag
## Minimal Interface
The Minimal interface (`ui/minimal/`) prioritizes speed and simplicity. It loads fast, uses minimal resources, and focuses on essential chat interactions.
**Capabilities:**
- Core chat and basic interactions only
- Fast loading with minimal dependencies
- Low resource usage for constrained environments
- Easy embedding into existing applications
- Mobile-first design approach
**When to use Minimal:**
- Mobile web access
- Embedded chatbots in external websites
- Low-bandwidth environments
- Quick access terminals and kiosks
- Scenarios where simplicity matters more than features
**Access:**
- Default: `http://localhost:8080` (served at root)
- Explicit: `http://localhost:8080/minimal`
- Embedded: Via iframe or WebView
## Configuration
### Server Configuration
UI paths are configured in several locations:
**Main Server** (`src/main.rs`):
```rust
let static_path = std::path::Path::new("./web/suite");
```
**UI Server Module** (`src/core/ui_server/mod.rs`):
```rust
let static_path = PathBuf::from("./ui/suite");
```
**Tauri Configuration** (`tauri.conf.json`):
```json
{
"build": {
"frontendDist": "./ui/suite"
}
}
```
### Routing
Both interfaces can be served simultaneously with different routes:
```rust
Router::new()
.route("/", get(serve_minimal))
.route("/minimal", get(serve_minimal))
.route("/suite", get(serve_suite))
```
The minimal interface serves at root by default, providing faster loading for most users.
## API Compliance
The Minimal UI implements full compliance with the Bot Core API. Both interfaces support the same backend endpoints.
**Supported Endpoints:**
| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/ws` | WebSocket | Real-time messaging |
| `/api/auth` | GET | Authentication |
| `/api/sessions` | GET/POST | Session management |
| `/api/sessions/{id}` | GET | Session details |
| `/api/sessions/{id}/history` | GET | Message history |
| `/api/sessions/{id}/start` | POST | Start session |
| `/api/voice/start` | POST | Voice input start |
| `/api/voice/stop` | POST | Voice input stop |
**WebSocket Protocol:**
Both interfaces use the same message types:
- `TEXT (1)` - Regular text messages
- `VOICE (2)` - Voice messages
- `CONTINUE (3)` - Continue interrupted responses
- `CONTEXT (4)` - Context changes
- `SYSTEM (5)` - System messages
## Performance Characteristics
### Suite Interface
| Metric | Typical Value |
|--------|---------------|
| Initial load | ~500KB |
| Time to interactive | ~1.5s |
| Memory usage | ~80MB |
| Best for | Full productivity |
### Minimal Interface
| Metric | Typical Value |
|--------|---------------|
| Initial load | ~50KB |
| Time to interactive | ~200ms |
| Memory usage | ~20MB |
| Best for | Quick interactions |
## Browser Support
Both interfaces support modern browsers:
| Browser | Minimum Version | WebSocket | Voice |
|---------|----------------|-----------|-------|
| Chrome | 90+ | ✅ | ✅ |
| Firefox | 88+ | ✅ | ✅ |
| Safari | 14+ | ✅ | ✅ |
| Edge | 90+ | ✅ | ✅ |
| Mobile Chrome | 90+ | ✅ | ✅ |
| Mobile Safari | 14+ | ✅ | ✅ |
## Switching Interfaces
Users can switch between interfaces by navigating to the appropriate URL. For programmatic switching, update the `ui_server/mod.rs` to change the default:
```rust
// Serve minimal at root (default)
match fs::read_to_string("ui/minimal/index.html")
// Or serve suite at root
match fs::read_to_string("ui/suite/index.html")
```
## Troubleshooting
**404 Errors:**
- Clear browser cache
- Rebuild: `cargo clean && cargo build`
- Verify files exist in `ui/suite/` or `ui/minimal/`
**Tauri Build Failures:**
- Check `tauri.conf.json` has correct `frontendDist` path
- Ensure `ui/suite/index.html` exists
**Static Files Not Loading:**
- Verify `ServeDir` configuration in router
- Check subdirectories (js, css, public) exist
**Debug Commands:**
```bash
# Verify UI structure
ls -la ui/suite/
ls -la ui/minimal/
# Test interfaces
curl http://localhost:8080/
curl http://localhost:8080/suite/
# Check static file serving
curl http://localhost:8080/js/app.js
```
## Customization
### GBUI Templates
The Suite interface uses GBUI templates for layout customization:
- `default.gbui` - Full multi-app layout with sidebar
- `single.gbui` - Streamlined chat-focused view
Edit these files to customize the interface structure without modifying core code.
### CSS Theming
Both interfaces support CSS customization through their respective stylesheets. The Suite interface provides more theming options through CSS custom properties.
## Future Enhancements
Planned improvements include:
- Dynamic UI selection based on device capabilities
- Progressive enhancement from minimal to suite
- Service worker implementation for offline support
- WebAssembly components for high-performance features
## See Also
- [default.gbui Reference](./default-gbui.md) - Full desktop template
- [single.gbui Reference](./single-gbui.md) - Simple chat template
- [Console Mode](./console-mode.md) - Terminal interface
- [Monitoring Dashboard](./monitoring.md) - System observability

View file

@ -1 +1,158 @@
# DELETE FILE # DELETE
The `DELETE` keyword removes resources using dynamic path interpretation, similar to how `GET` works. The system automatically determines the appropriate operation based on the path provided.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Syntax
```basic
DELETE path
DELETE path, options
```
## Dynamic Path Interpretation
Like `GET`, `DELETE` interprets the path and selects the appropriate engine:
| Path Pattern | Operation |
|--------------|-----------|
| `/files/document.pdf` | Delete file from storage |
| `/users/user-id` | Delete user |
| `/tasks/task-id` | Delete task |
| `/projects/project-id` | Delete project |
| `https://api.example.com/items/123` | HTTP DELETE to external API |
## Examples
### Delete a File
```basic
DELETE "/reports/old-report.pdf"
TALK "File deleted"
```
### Delete from External API
```basic
DELETE "https://api.crm.com/contacts/12345"
```
### Delete with Condition
```basic
' Delete all files older than 30 days
files = LIST "/temp/"
FOR EACH file IN files
IF DATEDIFF("day", file.modified, NOW()) > 30 THEN
DELETE "/temp/" + file.name
END IF
NEXT file
```
### Delete a Task
```basic
DELETE "/tasks/" + task_id
TALK "Task removed"
```
### Delete a User
```basic
DELETE "/users/" + user_id
```
### Delete a Project
```basic
DELETE "/projects/" + project_id
```
## Options
Pass options as a second parameter for additional control:
```basic
' Soft delete (archive instead of permanent removal)
DELETE "/files/report.pdf", #{soft: true}
' Force delete (bypass confirmation)
DELETE "/files/temp/", #{force: true, recursive: true}
```
## Return Value
`DELETE` returns information about the operation:
```basic
result = DELETE "/files/document.pdf"
IF result.success THEN
TALK "Deleted: " + result.path
ELSE
TALK "Failed: " + result.error
END IF
```
## HTTP DELETE
When the path is a full URL, `DELETE` performs an HTTP DELETE request:
```basic
' Delete via REST API
DELETE "https://api.service.com/items/456"
' With authentication
SET HEADER "Authorization", "Bearer " + token
DELETE "https://api.service.com/items/456"
```
## Database Records
For database operations, use the `DELETE` keyword with table syntax:
```basic
' Delete specific records
DELETE "orders", "status = 'cancelled' AND created_at < '2024-01-01'"
' Delete by ID
DELETE "customers", "id = '" + customer_id + "'"
```
## Best Practices
**Verify before deleting.** Confirm the resource exists and the user has permission:
```basic
file = GET "/files/" + filename
IF file THEN
DELETE "/files/" + filename
ELSE
TALK "File not found"
END IF
```
**Use soft deletes for important data.** Archive rather than permanently remove:
```basic
' Move to archive instead of delete
MOVE "/active/" + filename, "/archive/" + filename
```
**Log deletions for audit trails:**
```basic
DELETE "/files/" + filename
INSERT "audit_log", #{
action: "delete",
path: filename,
user: user.id,
timestamp: NOW()
}
```
## See Also
- [GET](./keyword-get.md) - Dynamic resource retrieval
- [LIST](./keyword-list.md) - List resources before deletion
- [MOVE](./keyword-move.md) - Move instead of delete

View file

@ -1,26 +1,398 @@
# HEAR Keyword # HEAR Keyword
**Syntax** The `HEAR` keyword pauses script execution and waits for user input. With optional type validation, it automatically verifies and normalizes input, retrying with helpful error messages when validation fails.
``` <img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
HEAR variable_name
```
**Parameters** ## Basic Syntax
- `variable_name` Identifier where the users next message will be stored.
**Description**
`HEAR` pauses script execution and waits for the next user input. The received text is assigned to the specified variable, which can then be used in subsequent commands.
**Example (from `start.bas`)**
```basic ```basic
HEAR user_input HEAR variable_name
IF user_input = "help" THEN HEAR variable_name AS TYPE
TALK "Sure, I can assist with account info, orders, or support." HEAR variable_name AS "Option1", "Option2", "Option3"
ENDIF
``` ```
The script waits for the user to type a message, stores it in `user_input`, and then evaluates the condition. The simplest form accepts any input. Adding `AS TYPE` enables automatic validation with user-friendly retry prompts.
## Simple HEAR
```basic
TALK "What would you like to know?"
HEAR question
TALK "You asked: " + question
```
The script waits for any user message and stores it in the variable.
## Validated Input Types
When using `HEAR AS <TYPE>`, the system validates input automatically, retries up to 3 times with helpful messages, and returns normalized values.
### Text Types
**EMAIL** validates email format and normalizes to lowercase:
```basic
TALK "What's your email address?"
HEAR email AS EMAIL
TALK "We'll send confirmation to: " + email
```
Accepts: `User@Example.COM` → Returns: `user@example.com`
**NAME** validates name format with proper capitalization:
```basic
TALK "What's your full name?"
HEAR name AS NAME
```
Accepts letters, spaces, hyphens, apostrophes. Auto-capitalizes: `john doe``John Doe`
**URL** validates and normalizes URLs:
```basic
TALK "Enter your website:"
HEAR website AS URL
```
Auto-adds `https://` if protocol missing.
**PASSWORD** validates minimum strength:
```basic
TALK "Create a password (minimum 8 characters):"
HEAR password AS PASSWORD
```
Requires 8+ characters. Never echoes the actual password back.
**COLOR** accepts color names or hex values:
```basic
HEAR color AS COLOR
```
Accepts: `red`, `#FF0000`, `rgb(255, 0, 0)` → Returns: `#FF0000`
### Numeric Types
**INTEGER** validates whole numbers:
```basic
TALK "How many items?"
HEAR quantity AS INTEGER
```
Removes formatting (commas, spaces). Returns numeric value.
**FLOAT** / **DECIMAL** validates decimal numbers:
```basic
TALK "Enter the temperature:"
HEAR temperature AS FLOAT
```
Handles both `.` and `,` as decimal separators.
**MONEY** / **CURRENCY** / **AMOUNT** validates monetary values:
```basic
TALK "How much to transfer?"
HEAR amount AS MONEY
```
Accepts: `100`, `1,234.56`, `R$ 100,00`, `$100.00` → Returns: `1234.56`
**CREDITCARD** / **CARD** validates card numbers with Luhn algorithm:
```basic
TALK "Enter your card number:"
HEAR card AS CREDITCARD
```
Returns masked format: `4111 **** **** 1111`
### Date and Time Types
**DATE** validates and parses dates:
```basic
TALK "When is your birthday?"
HEAR birthday AS DATE
```
Accepts: `25/12/2024`, `12/25/2024`, `2024-12-25`, `December 25, 2024`, `today`, `tomorrow`, `hoje`, `amanhã`
Returns: ISO format `YYYY-MM-DD`
**HOUR** / **TIME** validates time input:
```basic
TALK "What time for the meeting?"
HEAR meeting_time AS HOUR
```
Accepts: `14:30`, `2:30 PM` → Returns: `14:30`
### Brazilian Document Types
**CPF** validates Brazilian individual taxpayer ID:
```basic
TALK "Enter your CPF:"
HEAR cpf AS CPF
```
Validates 11 digits with mod 11 check. Returns: `123.456.789-09`
**CNPJ** validates Brazilian company taxpayer ID:
```basic
TALK "Enter your company's CNPJ:"
HEAR cnpj AS CNPJ
```
Validates 14 digits. Returns: `12.345.678/0001-95`
### Contact Types
**MOBILE** / **PHONE** validates phone numbers:
```basic
TALK "What's your phone number?"
HEAR phone AS MOBILE
```
Accepts 10-15 digits, auto-formats based on detected country.
**ZIPCODE** / **CEP** / **POSTALCODE** validates postal codes:
```basic
HEAR cep AS ZIPCODE
```
Supports Brazilian CEP, US ZIP, UK postcode formats.
### Menu Selection
Provide options directly in the HEAR statement:
```basic
TALK "Choose your fruit:"
HEAR fruit AS "Apple", "Banana", "Orange", "Mango"
```
Accepts exact match, case-insensitive match, numeric selection (`1`, `2`, `3`), or partial match if unique.
**BOOLEAN** validates yes/no responses:
```basic
TALK "Do you agree to the terms?"
HEAR agreed AS BOOLEAN
IF agreed THEN
TALK "Thank you!"
END IF
```
True: `yes`, `y`, `sim`, `ok`, `sure`, `confirm`
False: `no`, `n`, `não`, `cancel`, `deny`
**LANGUAGE** validates language codes:
```basic
HEAR language AS LANGUAGE
```
Accepts: `en`, `pt`, `English`, `Português` → Returns: ISO 639-1 code
### Media Types
**IMAGE** / **PHOTO** waits for image upload:
```basic
TALK "Send a photo of your document:"
HEAR document_photo AS IMAGE
```
Returns URL to uploaded image.
**QRCODE** waits for image and decodes QR:
```basic
TALK "Send me the QR code:"
HEAR qr_data AS QRCODE
```
Uses vision API to decode. Returns decoded data.
**AUDIO** / **VOICE** transcribes audio input:
```basic
TALK "Send a voice message:"
HEAR transcription AS AUDIO
```
Uses Whisper for transcription. Returns text.
**VIDEO** analyzes video content:
```basic
TALK "Send a video of the issue:"
HEAR video_description AS VIDEO
```
Uses vision API to describe. Returns description.
**FILE** / **DOCUMENT** waits for file upload:
```basic
TALK "Upload your contract:"
HEAR contract AS DOCUMENT
```
Accepts PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT, CSV. Returns URL.
### Authentication
**LOGIN** waits for OAuth completion:
```basic
TALK "Click the link to authenticate:"
HEAR user AS LOGIN
```
Returns user object with tokens after OAuth callback.
## Complete Examples
### Registration Flow
```basic
TALK "Let's create your account!"
TALK "What's your full name?"
HEAR name AS NAME
TALK "Enter your email address:"
HEAR email AS EMAIL
TALK "Enter your CPF:"
HEAR cpf AS CPF
TALK "What's your phone number?"
HEAR phone AS MOBILE
TALK "Choose a password:"
HEAR password AS PASSWORD
TALK "What's your birth date?"
HEAR birthdate AS DATE
TALK "Select your gender:"
HEAR gender AS "Male", "Female", "Other", "Prefer not to say"
SAVE "users.csv", name, email, cpf, phone, birthdate, gender, NOW()
TALK "Account created for " + name + "!"
```
### Payment Flow
```basic
TALK "Enter the amount:"
HEAR amount AS MONEY
IF amount < 1 THEN
TALK "Minimum payment is R$ 1.00"
RETURN
END IF
TALK "How would you like to pay?"
HEAR method AS "Credit Card", "Debit Card", "PIX", "Boleto"
TALK "Confirm payment of R$ " + FORMAT(amount, "#,##0.00") + "?"
HEAR confirm AS BOOLEAN
IF confirm THEN
TALK "Processing payment..."
ELSE
TALK "Payment cancelled."
END IF
```
## Validation Behavior
When validation fails, the system automatically prompts for correction:
```
User: my email
Bot: Please enter a valid email address (e.g., user@example.com)
User: test@example.com
Bot: Email confirmed!
```
After 3 failed attempts, execution continues with an empty value. Check for this:
```basic
HEAR email AS EMAIL
IF email = "" THEN
TALK "Unable to validate email. Please contact support."
RETURN
END IF
```
## Best Practices
**Always use appropriate types** — automatic validation is safer than manual checking:
```basic
' Good
HEAR email AS EMAIL
' Avoid
HEAR email
IF NOT email CONTAINS "@" THEN ...
```
**Provide context before HEAR** — users should know what to enter:
```basic
TALK "Enter the transfer amount (minimum R$ 1.00):"
HEAR amount AS MONEY
```
**Use menus for limited options**:
```basic
HEAR method AS "Credit Card", "Debit Card", "PIX"
```
**Combine with SET CONTEXT** for AI-enhanced input handling:
```basic
SET CONTEXT "You are a banking assistant. Confirm amounts before processing."
HEAR amount AS MONEY
```
## Validation Summary
| Type | Example Input | Normalized Output |
|------|---------------|-------------------|
| EMAIL | `User@Example.COM` | `user@example.com` |
| NAME | `john DOE` | `John Doe` |
| INTEGER | `1,234` | `1234` |
| MONEY | `R$ 1.234,56` | `1234.56` |
| DATE | `25/12/2024` | `2024-12-25` |
| HOUR | `2:30 PM` | `14:30` |
| BOOLEAN | `yes` / `sim` | `true` |
| CPF | `12345678909` | `123.456.789-09` |
| MOBILE | `11999998888` | `(11) 99999-8888` |
| CREDITCARD | `4111111111111111` | `4111 **** **** 1111` |
| QRCODE | [image] | decoded data |
| AUDIO | [audio file] | transcribed text |
## See Also
- [TALK Keyword](./keyword-talk.md) - Output messages
- [Dialog Basics](./basics.md) - Conversation patterns
- [Template Variables](./template-variables.md) - Variable substitution

View file

@ -0,0 +1,342 @@
# Lead Scoring Keywords
General Bots includes native lead scoring capabilities through BASIC keywords, enabling automated lead qualification, AI-enhanced scoring, and CRM integration directly from conversational flows.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Lead scoring assigns numeric values to prospects based on their attributes and behaviors. Higher scores indicate greater sales readiness. General Bots provides both rule-based and AI-enhanced scoring approaches.
## SCORE LEAD
Calculate a lead score based on profile and behavior data using configurable rules.
### Syntax
```basic
score = SCORE LEAD lead_data
```
### Example
```basic
lead_data = NEW OBJECT
lead_data.email = "john@company.com"
lead_data.name = "John Smith"
lead_data.company = "Acme Corp"
lead_data.job_title = "VP of Engineering"
lead_data.industry = "Technology"
lead_data.company_size = "Enterprise"
score = SCORE LEAD lead_data
TALK "Score: " + score.score
TALK "Grade: " + score.grade
TALK "Status: " + score.status
TALK "Top recommendation: " + score.recommendations[0]
```
### Return Object
The `SCORE LEAD` keyword returns an object containing:
| Property | Type | Description |
|----------|------|-------------|
| `score` | Integer | Numeric score (0-100) |
| `grade` | String | Letter grade (A, B, C, D, F) |
| `status` | String | hot, warm, cold, or unqualified |
| `breakdown` | Object | Score components by category |
| `recommendations` | Array | Suggested next actions |
### Score Breakdown
```basic
score = SCORE LEAD lead_data
TALK "Demographic score: " + score.breakdown.demographic
TALK "Firmographic score: " + score.breakdown.firmographic
TALK "Behavioral score: " + score.breakdown.behavioral
TALK "Engagement score: " + score.breakdown.engagement
```
## AI SCORE LEAD
Use AI/LLM-enhanced scoring for more nuanced lead evaluation.
```basic
score = AI SCORE LEAD lead_data
TALK "AI Score: " + score.score
TALK "Confidence: " + score.breakdown.ai_confidence
TALK "Reasoning: " + score.breakdown.ai_reasoning
```
AI scoring considers factors that rule-based scoring might miss, such as company news, market conditions, and subtle signals in communication patterns.
### When to Use AI Scoring
AI scoring works best for complex B2B scenarios where context matters significantly. Rule-based scoring is faster and sufficient for high-volume B2C leads with clear qualification criteria.
```basic
' Use AI for enterprise leads, rules for SMB
IF lead_data.company_size = "Enterprise" THEN
score = AI SCORE LEAD lead_data
ELSE
score = SCORE LEAD lead_data
END IF
```
## GET LEAD SCORE
Retrieve an existing lead score from the database.
```basic
score = GET LEAD SCORE "lead-id"
TALK "Current score: " + score.score
TALK "Last updated: " + score.updated_at
```
## QUALIFY LEAD
Check if a lead meets the qualification threshold for sales handoff.
### Default Threshold (70)
```basic
result = QUALIFY LEAD "lead-id"
IF result.qualified THEN
TALK "Lead is qualified: " + result.status
' Notify sales team
SEND MAIL TO "sales@company.com" SUBJECT "New Qualified Lead" BODY result
ELSE
TALK "Lead needs more nurturing. Score: " + result.score
END IF
```
### Custom Threshold
```basic
' Enterprise deals require higher qualification
result = QUALIFY LEAD "lead-id", 85
IF result.qualified THEN
TALK "Enterprise lead qualified for sales"
END IF
```
### Qualification Result
| Property | Type | Description |
|----------|------|-------------|
| `qualified` | Boolean | Meets threshold |
| `score` | Integer | Current score |
| `threshold` | Integer | Applied threshold |
| `status` | String | Current lead status |
| `gap` | Integer | Points needed if not qualified |
## UPDATE LEAD SCORE
Manually adjust a lead's score based on specific actions or behaviors.
### Add Points
```basic
' Lead attended webinar
new_score = UPDATE LEAD SCORE "lead-id", 10, "Attended product webinar"
TALK "Score updated to: " + new_score.score
```
### Deduct Points
```basic
' Lead unsubscribed from newsletter
new_score = UPDATE LEAD SCORE "lead-id", -15, "Unsubscribed from email"
```
### Behavioral Scoring
```basic
ON "webinar:attended"
UPDATE LEAD SCORE params.lead_id, 15, "Webinar attendance"
END ON
ON "pricing:viewed"
UPDATE LEAD SCORE params.lead_id, 20, "Viewed pricing page"
END ON
ON "demo:requested"
UPDATE LEAD SCORE params.lead_id, 30, "Requested demo"
END ON
ON "email:bounced"
UPDATE LEAD SCORE params.lead_id, -25, "Email bounced"
END ON
```
## Complete Lead Nurturing Flow
```basic
' lead-nurturing.bas
PARAM email AS string
PARAM name AS string
PARAM company AS string
PARAM source AS string
DESCRIPTION "Process and score new leads"
' Build lead profile
WITH lead
.email = email
.name = name
.company = company
.source = source
.created_at = NOW()
END WITH
' Initial scoring
score = SCORE LEAD lead
' Store lead
INSERT "leads", lead
SET BOT MEMORY "lead_" + email + "_score", score.score
' Route based on score
IF score.status = "hot" THEN
' Immediate sales notification
SEND MAIL TO "sales@company.com" SUBJECT "Hot Lead: " + name BODY score
SEND TEMPLATE "hot-lead-welcome", "email", email, #{name: name}
ELSEIF score.status = "warm" THEN
' Schedule nurture sequence
SEND TEMPLATE "welcome", "email", email, #{name: name}
SET SCHEDULE DATEADD(NOW(), 3, "day"), "nurture-day-3.bas"
ELSE
' Cold lead - educational content
SEND TEMPLATE "educational", "email", email, #{name: name}
END IF
TALK "Lead " + name + " processed with score " + score.score + " (" + score.status + ")"
```
## Lead Scoring Configuration
Configure scoring weights in your bot's `config.csv`:
```csv
key,value
lead-score-job-title-weight,20
lead-score-company-size-weight,15
lead-score-industry-weight,10
lead-score-engagement-weight,25
lead-score-behavioral-weight,30
lead-score-qualification-threshold,70
```
### Title-Based Scoring
| Job Title Pattern | Points |
|-------------------|--------|
| C-Level (CEO, CTO, CFO) | 25 |
| VP / Vice President | 20 |
| Director | 15 |
| Manager | 10 |
| Individual Contributor | 5 |
### Company Size Scoring
| Company Size | Points |
|--------------|--------|
| Enterprise (1000+) | 20 |
| Mid-Market (100-999) | 15 |
| SMB (10-99) | 10 |
| Small (1-9) | 5 |
### Behavioral Actions
| Action | Typical Points |
|--------|---------------|
| Demo request | +30 |
| Pricing page view | +20 |
| Case study download | +15 |
| Webinar attendance | +15 |
| Blog subscription | +10 |
| Email open | +2 |
| Email click | +5 |
| Unsubscribe | -15 |
| Email bounce | -25 |
## Scheduled Score Decay
Implement score decay for inactive leads:
```basic
' score-decay.bas
SET SCHEDULE "every day at 2am"
' Find leads with no activity in 30 days
stale_leads = FIND "leads", "last_activity < DATEADD(NOW(), -30, 'day') AND score > 20"
FOR EACH lead IN stale_leads
UPDATE LEAD SCORE lead.id, -5, "Inactivity decay"
NEXT lead
TALK "Processed " + LEN(stale_leads) + " stale leads"
```
## Integration with CRM
Push qualified leads to external CRM systems:
```basic
result = QUALIFY LEAD lead_id
IF result.qualified THEN
' Push to Salesforce
crm_payload = NEW OBJECT
crm_payload.email = lead.email
crm_payload.name = lead.name
crm_payload.score = result.score
crm_payload.status = "Qualified"
POST "https://api.salesforce.com/leads", crm_payload
' Mark as synced
UPDATE "leads", "id = " + lead_id, #{crm_synced: true, synced_at: NOW()}
END IF
```
## Best Practices
**Start with simple rules.** Begin with basic demographic and firmographic scoring, then add behavioral triggers as you gather data.
**Align scoring with sales.** Work with your sales team to define what makes a "qualified" lead. Their input ensures scores reflect actual sales readiness.
**Review and adjust regularly.** Analyze conversion rates by score range monthly. Adjust weights if high-scoring leads aren't converting.
**Combine rule-based and AI scoring.** Use rule-based scoring for speed and consistency, AI scoring for complex enterprise deals requiring nuanced evaluation.
**Implement score decay.** Leads that go cold should have their scores decrease over time to keep the pipeline accurate.
**Track score history.** Store score changes with timestamps and reasons for audit trails and analysis.
```basic
' Log all score changes
ON "lead:score:changed"
INSERT "score_history", #{
lead_id: params.lead_id,
old_score: params.old_score,
new_score: params.new_score,
reason: params.reason,
changed_at: NOW()
}
END ON
```
## See Also
- [SEND TEMPLATE](./keywords.md) - Nurture campaign emails
- [SET SCHEDULE](./keyword-set-schedule.md) - Automated scoring jobs
- [ON Keyword](./keyword-on.md) - Event-driven score updates
- [GET / POST](./keywords-http.md) - CRM integration

View file

@ -0,0 +1,259 @@
# Social Media Keywords
General Bots provides native social media integration through BASIC keywords for posting content, scheduling, retrieving metrics, and managing posts across multiple platforms.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Platform Support
Supported platforms include Instagram, Facebook, LinkedIn, and Twitter/X. Each platform requires appropriate API credentials configured in your bot's `config.csv`.
## POST TO
Publish content to one or more social media platforms.
### Single Platform
```basic
POST TO INSTAGRAM image, "Check out our new feature! #AI #Automation"
POST TO FACEBOOK image, caption
POST TO LINKEDIN image, caption
POST TO TWITTER image, caption
```
### Multiple Platforms
Post to several platforms simultaneously:
```basic
POST TO "instagram,facebook,linkedin" image, caption
```
The keyword returns a post ID that can be used for metrics retrieval or deletion.
### Example: Product Announcement
```basic
image = "/products/new-release.jpg"
caption = "Introducing our latest innovation! Available now. #NewProduct #Innovation"
post_id = POST TO "instagram,facebook" image, caption
SET BOT MEMORY "latest_post_id", post_id
TALK "Posted to Instagram and Facebook"
```
## POST TO ... AT (Scheduled)
Schedule posts for future publishing at a specific date and time.
```basic
POST TO INSTAGRAM AT "2025-02-01 10:00" image, caption
POST TO FACEBOOK AT "2025-02-15 09:00" image, "Coming soon!"
```
### Campaign Scheduling
```basic
' Schedule a week of posts
images = LIST "/campaign/week1/"
dates = ["2025-02-03 09:00", "2025-02-04 09:00", "2025-02-05 09:00"]
FOR i = 0 TO LEN(images) - 1
POST TO "instagram,facebook" AT dates[i] images[i].path, captions[i]
NEXT i
TALK "Campaign scheduled: " + LEN(images) + " posts"
```
## GET METRICS
Retrieve engagement metrics for published posts.
### Platform-Specific Metrics
```basic
' Instagram metrics
metrics = GET INSTAGRAM METRICS "post-id"
TALK "Likes: " + metrics.likes + ", Comments: " + metrics.comments
' Facebook metrics
fb_metrics = GET FACEBOOK METRICS "post-id"
TALK "Shares: " + fb_metrics.shares + ", Reactions: " + fb_metrics.reactions
' LinkedIn metrics
li_metrics = GET LINKEDIN METRICS "post-id"
TALK "Impressions: " + li_metrics.impressions
' Twitter metrics
tw_metrics = GET TWITTER METRICS "post-id"
TALK "Retweets: " + tw_metrics.retweets + ", Likes: " + tw_metrics.likes
```
### Metrics Report
```basic
SET SCHEDULE "every monday at 9am"
post_id = GET BOT MEMORY "latest_post_id"
metrics = GET INSTAGRAM METRICS post_id
WITH report
.post_id = post_id
.likes = metrics.likes
.comments = metrics.comments
.reach = metrics.reach
.engagement_rate = ROUND((metrics.likes + metrics.comments) / metrics.reach * 100, 2)
.report_date = NOW()
END WITH
SEND MAIL TO "marketing@company.com" SUBJECT "Weekly Social Report" BODY report
```
## GET POSTS
List posts from a platform.
```basic
' Get all Instagram posts
posts = GET INSTAGRAM POSTS
FOR EACH post IN posts
TALK post.id + ": " + post.caption
NEXT post
' Get Facebook posts
fb_posts = GET FACEBOOK POSTS
```
## DELETE POST
Remove a scheduled or published post.
```basic
DELETE POST "post-id"
TALK "Post removed"
```
### Conditional Deletion
```basic
' Delete posts with low engagement
posts = GET INSTAGRAM POSTS
FOR EACH post IN posts
metrics = GET INSTAGRAM METRICS post.id
IF metrics.likes < 10 AND DATEDIFF("day", post.created_at, NOW()) > 30 THEN
DELETE POST post.id
TALK "Deleted low-engagement post: " + post.id
END IF
NEXT post
```
## Campaign Examples
### Welcome Campaign
```basic
ON FORM SUBMIT "signup"
name = fields.name
email = fields.email
' Welcome email immediately
SEND TEMPLATE "welcome", "email", email, #{name: name}
' Schedule social proof post
IF fields.share_permission = "yes" THEN
caption = "Welcome to our community, " + name + "! 🎉 #NewMember #Community"
POST TO INSTAGRAM AT DATEADD(NOW(), 1, "hour") "/templates/welcome-card.png", caption
END IF
END ON
```
### Social Media Campaign
```basic
' social-campaign.bas
SET SCHEDULE "every day at 10am"
' Rotate through content library
content_index = GET BOT MEMORY "content_index"
IF content_index = "" THEN content_index = 0
content_library = [
#{image: "/content/tip1.png", caption: "Pro tip: Automate your workflows! #Productivity"},
#{image: "/content/tip2.png", caption: "Save hours every week with automation #Efficiency"},
#{image: "/content/tip3.png", caption: "Let AI handle the repetitive tasks #AI #Automation"}
]
current = content_library[content_index MOD LEN(content_library)]
post_id = POST TO "instagram,linkedin" current.image, current.caption
SET BOT MEMORY "content_index", content_index + 1
SET BOT MEMORY "last_post_id", post_id
TALK "Posted content #" + (content_index + 1)
```
### Engagement Monitoring
```basic
SET SCHEDULE "every 6 hours"
posts = GET INSTAGRAM POSTS
total_engagement = 0
post_count = 0
FOR EACH post IN posts
IF DATEDIFF("day", post.created_at, NOW()) <= 7 THEN
metrics = GET INSTAGRAM METRICS post.id
total_engagement = total_engagement + metrics.likes + metrics.comments
post_count = post_count + 1
END IF
NEXT post
avg_engagement = IIF(post_count > 0, ROUND(total_engagement / post_count, 0), 0)
IF avg_engagement < 50 THEN
SEND MAIL TO "marketing@company.com" SUBJECT "Low Engagement Alert" BODY "Average engagement this week: " + avg_engagement
END IF
```
## Configuration
Add social media credentials to your bot's `config.csv`:
```csv
key,value
instagram-access-token,your-instagram-token
instagram-account-id,your-account-id
facebook-access-token,your-facebook-token
facebook-page-id,your-page-id
linkedin-access-token,your-linkedin-token
linkedin-organization-id,your-org-id
twitter-api-key,your-api-key
twitter-api-secret,your-api-secret
twitter-access-token,your-access-token
twitter-access-secret,your-access-secret
```
## Best Practices
**Schedule posts strategically.** Analyze your audience engagement patterns and post when your followers are most active.
**Use hashtags effectively.** Include relevant hashtags but avoid overloading—3 to 5 well-chosen tags typically perform better than 30 generic ones.
**Monitor metrics regularly.** Set up scheduled reports to track engagement trends and adjust your content strategy.
**Handle rate limits gracefully.** Social platforms enforce API rate limits. Space out bulk operations and implement retry logic.
**Store post IDs.** Save post identifiers in BOT MEMORY for later metrics retrieval or deletion.
```basic
post_id = POST TO INSTAGRAM image, caption
SET BOT MEMORY "post_" + FORMAT(NOW(), "yyyyMMdd"), post_id
```
## See Also
- [SET SCHEDULE](./keyword-set-schedule.md) - Automate posting schedules
- [Template Variables](./template-variables.md) - Dynamic content in captions
- [SEND TEMPLATE](./keywords.md) - Multi-channel messaging
- [GET BOT MEMORY](./keyword-get-bot-memory.md) - Store post tracking data

View file

@ -1,28 +1,26 @@
# Template Variables Reference # Template Variables
> Documentation for SEND TEMPLATE variables and built-in placeholders
## Overview
Templates support variable substitution using double curly braces `{{variable_name}}`. Variables are replaced at send time with values from the provided data object. Templates support variable substitution using double curly braces `{{variable_name}}`. Variables are replaced at send time with values from the provided data object.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Built-in Variables ## Built-in Variables
These variables are automatically available in all templates: These variables are automatically available in all templates without explicit declaration:
| Variable | Description | Example Output | | Variable | Description | Example |
|----------|-------------|----------------| |----------|-------------|---------|
| `{{recipient}}` | Recipient email/phone | `john@example.com` | | `{{recipient}}` | Recipient email or phone | `john@example.com` |
| `{{to}}` | Alias for recipient | `john@example.com` | | `{{to}}` | Alias for recipient | `john@example.com` |
| `{{date}}` | Current date (YYYY-MM-DD) | `2025-01-22` | | `{{date}}` | Current date (YYYY-MM-DD) | `2025-01-22` |
| `{{time}}` | Current time (HH:MM) | `14:30` | | `{{time}}` | Current time (HH:MM) | `14:30` |
| `{{datetime}}` | Date and time | `2025-01-22 14:30` | | `{{datetime}}` | Combined date and time | `2025-01-22 14:30` |
| `{{year}}` | Current year | `2025` | | `{{year}}` | Current year | `2025` |
| `{{month}}` | Current month name | `January` | | `{{month}}` | Current month name | `January` |
## Custom Variables ## Custom Variables
Pass custom variables via the variables parameter: Pass custom variables via the variables parameter in `SEND TEMPLATE`:
```basic ```basic
WITH vars WITH vars
@ -35,7 +33,8 @@ END WITH
SEND TEMPLATE "welcome", "email", "john@example.com", vars SEND TEMPLATE "welcome", "email", "john@example.com", vars
``` ```
Template content: The template content would reference these variables:
``` ```
Hello {{name}}, Hello {{name}},
@ -51,7 +50,7 @@ The Team
### Email Templates ### Email Templates
Email templates support `Subject:` line extraction: Email templates support automatic `Subject:` line extraction. Place the subject on the first line:
``` ```
Subject: Welcome to {{company}}, {{name}}! Subject: Welcome to {{company}}, {{name}}!
@ -61,15 +60,18 @@ Hello {{name}},
Thank you for joining us... Thank you for joining us...
``` ```
The system extracts the subject line and uses the remainder as the body.
### WhatsApp Templates ### WhatsApp Templates
WhatsApp templates must be pre-approved by Meta. Use numbered placeholders: WhatsApp templates must be pre-approved by Meta. Use numbered placeholders as required by the WhatsApp Business API:
``` ```
Hello {{1}}, your order {{2}} has shipped. Track at {{3}} Hello {{1}}, your order {{2}} has shipped. Track at {{3}}
``` ```
Map variables: Map variables using numeric keys:
```basic ```basic
WITH vars WITH vars
.1 = customer_name .1 = customer_name
@ -82,7 +84,7 @@ SEND TEMPLATE "order-shipped", "whatsapp", phone, vars
### SMS Templates ### SMS Templates
Keep SMS templates under 160 characters for single segment: Keep SMS templates under 160 characters for single-segment delivery:
``` ```
Hi {{name}}, your code is {{code}}. Valid for 10 minutes. Hi {{name}}, your code is {{code}}. Valid for 10 minutes.
@ -131,25 +133,6 @@ Shipping to:
Track your order: {{tracking_url}} Track your order: {{tracking_url}}
``` ```
### Lead Nurture
```
Subject: {{name}}, here's your exclusive resource
Hi {{name}},
As a {{company}} professional, we thought you'd find this helpful:
{{resource_title}}
{{resource_description}}
Download now: {{resource_url}}
Best,
{{sender_name}}
```
### Appointment Reminder ### Appointment Reminder
``` ```
@ -176,46 +159,33 @@ See you soon!
CREATE TEMPLATE "welcome", "email", "Welcome {{name}}!", "Hello {{name}}, thank you for joining {{company}}!" CREATE TEMPLATE "welcome", "email", "Welcome {{name}}!", "Hello {{name}}, thank you for joining {{company}}!"
``` ```
### Via Database ### Retrieving Templates
Templates are stored in `message_templates` table: ```basic
template = GET TEMPLATE "welcome"
| Column | Type | Description | TALK "Template body: " + template.body
|--------|------|-------------| ```
| `id` | UUID | Template ID |
| `bot_id` | UUID | Bot owner |
| `name` | TEXT | Template name |
| `channel` | TEXT | email/whatsapp/sms/telegram/push |
| `subject` | TEXT | Email subject (nullable) |
| `body` | TEXT | Template body |
| `variables` | JSONB | List of variable names |
| `is_active` | BOOL | Active status |
## Variable Extraction ## Variable Extraction
Variables are automatically extracted from template body: Variables are automatically extracted from template content when the template is created. The system identifies all `{{variable}}` patterns and stores them for validation. Built-in variables (recipient, date, time, etc.) are excluded from the extraction.
```basic
body = "Hello {{name}}, your order {{order_id}} is {{status}}."
' Extracted variables: ["name", "order_id", "status"]
```
Built-in variables (recipient, date, time, etc.) are excluded from extraction.
## Fallback Values ## Fallback Values
Use NVL for fallback values in your code: Handle missing variables using `NVL` in your code:
```basic ```basic
WITH vars WITH vars
.name = NVL(user_name, "Friend") .name = NVL(user_name, "Friend")
.company = NVL(user_company, "your organization") .company = NVL(user_company, "your organization")
END WITH END WITH
SEND TEMPLATE "greeting", "email", email, vars
``` ```
## Multi-Channel Example ## Multi-Channel Delivery
Send same template to multiple channels: Send the same template to multiple channels in one call:
```basic ```basic
WITH vars WITH vars
@ -223,19 +193,57 @@ WITH vars
.message = "Your appointment is confirmed" .message = "Your appointment is confirmed"
END WITH END WITH
' Send to all channels
SEND TEMPLATE "appointment-confirm", "email,sms,whatsapp", recipient, vars SEND TEMPLATE "appointment-confirm", "email,sms,whatsapp", recipient, vars
```
' Or send separately with channel-specific content Or send channel-specific versions:
```basic
SEND TEMPLATE "appointment-email", "email", email, vars SEND TEMPLATE "appointment-email", "email", email, vars
SEND TEMPLATE "appointment-sms", "sms", phone, vars SEND TEMPLATE "appointment-sms", "sms", phone, vars
``` ```
## Bulk Sending
Send templates to multiple recipients:
```basic
recipients = ["a@example.com", "b@example.com", "c@example.com"]
count = SEND TEMPLATE "newsletter" TO "email" recipients, #{month: "January"}
TALK "Sent to " + count + " recipients"
```
## Best Practices ## Best Practices
1. **Keep variable names simple**: Use `name` not `customer_first_name` **Keep variable names simple.** Use `name` rather than `customer_first_name_from_database`. Shorter names are easier to maintain.
2. **Provide fallbacks**: Always handle missing variables
3. **Test templates**: Verify all variables are populated **Provide fallbacks.** Always handle the case where a variable might be missing or empty.
4. **Channel limits**: SMS 160 chars, WhatsApp requires approval
5. **Personalization**: Use `{{name}}` for better engagement **Test templates.** Verify all variables populate correctly before deploying to production.
6. **Unsubscribe**: Include unsubscribe link in marketing emails
**Respect channel limits.** SMS has a 160-character single-segment limit. WhatsApp templates require Meta approval.
**Personalize thoughtfully.** Using `{{name}}` improves engagement, but avoid over-personalization that feels intrusive.
**Include unsubscribe options.** Marketing emails should always provide an unsubscribe mechanism.
## Database Storage
Templates are stored in the `message_templates` table:
| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Template identifier |
| `bot_id` | UUID | Owning bot |
| `name` | TEXT | Template name |
| `channel` | TEXT | email/whatsapp/sms/telegram/push |
| `subject` | TEXT | Email subject (nullable) |
| `body` | TEXT | Template body |
| `variables` | JSONB | List of variable names |
| `is_active` | BOOL | Active status |
## See Also
- [SEND TEMPLATE Keyword](./keywords.md) - Full keyword reference
- [SET SCHEDULE](./keyword-set-schedule.md) - Scheduled template delivery
- [Universal Messaging](./universal-messaging.md) - Multi-channel patterns

View file

@ -0,0 +1,247 @@
# Multimodal Configuration
General Bots integrates with botmodels—a Python service for multimodal AI tasks—to enable image generation, video creation, audio synthesis, and vision capabilities directly from BASIC scripts.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Architecture
```
┌─────────────┐ HTTPS ┌─────────────┐
│ botserver │ ────────────▶ │ botmodels │
│ (Rust) │ │ (Python) │
└─────────────┘ └─────────────┘
│ │
│ BASIC Keywords │ AI Models
│ - IMAGE │ - Stable Diffusion
│ - VIDEO │ - Zeroscope
│ - AUDIO │ - TTS/Whisper
│ - SEE │ - BLIP2
```
When a BASIC script calls a multimodal keyword, botserver forwards the request to botmodels, which runs the appropriate AI model and returns the generated content.
## Configuration
Add these settings to your bot's `config.csv` file to enable multimodal capabilities.
### BotModels Service
| Key | Default | Description |
|-----|---------|-------------|
| `botmodels-enabled` | `false` | Enable botmodels integration |
| `botmodels-host` | `0.0.0.0` | Host address for botmodels service |
| `botmodels-port` | `8085` | Port for botmodels service |
| `botmodels-api-key` | — | API key for authentication |
| `botmodels-https` | `false` | Use HTTPS for connection |
### Image Generation
| Key | Default | Description |
|-----|---------|-------------|
| `image-generator-model` | — | Path to image generation model |
| `image-generator-steps` | `4` | Inference steps (more = higher quality, slower) |
| `image-generator-width` | `512` | Output image width in pixels |
| `image-generator-height` | `512` | Output image height in pixels |
| `image-generator-gpu-layers` | `20` | Layers to offload to GPU |
| `image-generator-batch-size` | `1` | Batch size for generation |
### Video Generation
| Key | Default | Description |
|-----|---------|-------------|
| `video-generator-model` | — | Path to video generation model |
| `video-generator-frames` | `24` | Number of frames to generate |
| `video-generator-fps` | `8` | Output frames per second |
| `video-generator-width` | `320` | Output video width in pixels |
| `video-generator-height` | `576` | Output video height in pixels |
| `video-generator-gpu-layers` | `15` | Layers to offload to GPU |
| `video-generator-batch-size` | `1` | Batch size for generation |
## Example Configuration
```csv
key,value
botmodels-enabled,true
botmodels-host,0.0.0.0
botmodels-port,8085
botmodels-api-key,your-secret-key
botmodels-https,false
image-generator-model,../../../../data/diffusion/sd_turbo_f16.gguf
image-generator-steps,4
image-generator-width,512
image-generator-height,512
image-generator-gpu-layers,20
video-generator-model,../../../../data/diffusion/zeroscope_v2_576w
video-generator-frames,24
video-generator-fps,8
```
## BASIC Keywords
Once configured, these keywords become available in your scripts.
### IMAGE
Generate an image from a text prompt:
```basic
file = IMAGE "a sunset over mountains with purple clouds"
SEND FILE TO user, file
```
The keyword returns a path to the generated image file.
### VIDEO
Generate a video from a text prompt:
```basic
file = VIDEO "a rocket launching into space"
SEND FILE TO user, file
```
Video generation is more resource-intensive than image generation. Expect longer processing times.
### AUDIO
Generate speech audio from text:
```basic
file = AUDIO "Hello, welcome to our service!"
SEND FILE TO user, file
```
### SEE
Analyze an image or video and get a description:
```basic
' Describe an image
caption = SEE "/path/to/image.jpg"
TALK caption
' Describe a video
description = SEE "/path/to/video.mp4"
TALK description
```
The SEE keyword uses vision models to understand visual content and return natural language descriptions.
## Starting BotModels
Before using multimodal features, start the botmodels service:
```bash
cd botmodels
python -m uvicorn src.main:app --host 0.0.0.0 --port 8085
```
For production with HTTPS:
```bash
python -m uvicorn src.main:app \
--host 0.0.0.0 \
--port 8085 \
--ssl-keyfile key.pem \
--ssl-certfile cert.pem
```
## BotModels API Endpoints
The botmodels service exposes these REST endpoints:
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/image/generate` | POST | Generate image from prompt |
| `/api/video/generate` | POST | Generate video from prompt |
| `/api/speech/generate` | POST | Generate speech from text |
| `/api/speech/totext` | POST | Transcribe audio to text |
| `/api/vision/describe` | POST | Describe an image |
| `/api/vision/describe_video` | POST | Describe a video |
| `/api/vision/vqa` | POST | Visual question answering |
| `/api/health` | GET | Health check |
All endpoints except `/api/health` require the `X-API-Key` header for authentication.
## Model Paths
Configure model paths relative to the botmodels service directory. Typical layout:
```
data/
├── diffusion/
│ ├── sd_turbo_f16.gguf # Stable Diffusion
│ └── zeroscope_v2_576w/ # Zeroscope video
├── tts/
│ └── model.onnx # Text-to-speech
├── whisper/
│ └── model.bin # Speech-to-text
└── vision/
└── blip2/ # Vision model
```
## GPU Acceleration
Both image and video generation benefit significantly from GPU acceleration. Configure GPU layers based on your hardware:
| GPU VRAM | Recommended GPU Layers |
|----------|----------------------|
| 4GB | 8-12 |
| 8GB | 15-20 |
| 12GB+ | 25-35 |
Lower GPU layers if you experience out-of-memory errors.
## Troubleshooting
**"BotModels is not enabled"**
Set `botmodels-enabled=true` in your config.csv.
**Connection refused**
Verify botmodels service is running and check host/port configuration. Test connectivity:
```bash
curl http://localhost:8085/api/health
```
**Authentication failed**
Ensure `botmodels-api-key` in config.csv matches the `API_KEY` environment variable in botmodels.
**Model not found**
Verify model paths are correct and models are downloaded to the expected locations.
**Out of memory**
Reduce `gpu-layers` or `batch-size`. Video generation is particularly memory-intensive.
## Security Considerations
**Use HTTPS in production.** Set `botmodels-https=true` and configure SSL certificates on the botmodels service.
**Use strong API keys.** Generate cryptographically random keys for the `botmodels-api-key` setting.
**Restrict network access.** Limit botmodels service access to trusted hosts only.
**Consider GPU isolation.** Run botmodels on a dedicated GPU server if sharing resources with other services.
## Performance Tips
**Image generation** runs fastest with SD Turbo models and 4-8 inference steps. More steps improve quality but increase generation time linearly.
**Video generation** is the most resource-intensive operation. Keep frame counts low (24-48) for reasonable response times.
**Batch processing** improves throughput when generating multiple items. Increase `batch-size` if you have sufficient GPU memory.
**Caching** generated content when appropriate. If multiple users request similar content, consider storing results.
## See Also
- [LLM Configuration](./llm-config.md) - Language model settings
- [Bot Parameters](./parameters.md) - All configuration options
- [IMAGE Keyword](../chapter-06-gbdialog/keywords.md) - Image generation reference
- [SEE Keyword](../chapter-06-gbdialog/keywords.md) - Vision capabilities

View file

@ -0,0 +1,294 @@
# Enterprise Platform Migration
<img src="../assets/feature-parity-flow.svg" alt="Feature Parity Flow" style="max-height: 400px; width: 100%; object-fit: contain;">
General Bots provides complete feature parity with enterprise cloud productivity suites while offering significant advantages: self-hosting, open source licensing, no per-user fees, and native AI integration.
## Migration Overview
<img src="../assets/api-comparison-matrix.svg" alt="API Comparison Matrix" style="max-height: 500px; width: 100%; object-fit: contain;">
Organizations evaluating self-hosted alternatives find General Bots delivers equivalent functionality with full data sovereignty. The sections below map common enterprise APIs to their General Bots equivalents.
## API Endpoint Mapping
### Mail and Communication
Enterprise mail APIs handle sending, receiving, and managing email. General Bots provides the same capabilities through Stalwart Mail Server and BASIC keywords.
| Enterprise API | General Bots Equivalent | Implementation |
|----------------|------------------------|----------------|
| Messages endpoint | Stalwart IMAP/JMAP | Full mailbox access |
| Send mail endpoint | `SEND MAIL` keyword | `SEND MAIL TO email SUBJECT s BODY b` |
| Mail folders | Stalwart folders | Standard IMAP folders |
| Attachments | File keywords | `READ`, `WRITE` with attachments |
The BASIC syntax is straightforward:
```basic
SEND MAIL TO "client@company.com" SUBJECT "Report Ready" BODY report_content
```
For receiving mail, configure webhooks or use scheduled scripts to process incoming messages through the Stalwart API.
### Calendar and Scheduling
Calendar APIs manage events, appointments, and scheduling. General Bots integrates CalDAV with the `BOOK` keyword.
| Enterprise API | General Bots Equivalent | Implementation |
|----------------|------------------------|----------------|
| Calendar events | Calendar API | `/api/calendar/events` |
| Create event | `BOOK` keyword | `BOOK "Meeting" AT datetime` |
| Calendar view | Calendar range query | Date-filtered event retrieval |
| Free/busy lookup | Availability API | Schedule availability |
Schedule appointments conversationally:
```basic
TALK "When would you like to schedule your appointment?"
HEAR appointment_time AS DATE
BOOK "Consultation" AT appointment_time
TALK "Your appointment is confirmed for " + FORMAT(appointment_time, "MMMM d 'at' h:mm a")
```
### Files and Storage
Cloud storage APIs handle file operations, versioning, and sharing. SeaweedFS provides S3-compatible storage with full versioning support.
| Enterprise API | General Bots Equivalent | Implementation |
|----------------|------------------------|----------------|
| List files | `LIST` keyword | `LIST "/documents/"` |
| File listing | Drive API | `/api/files/list` |
| File content | `READ` keyword | `content = READ "file.pdf"` |
| File versions | Versions API | `/api/files/versions` |
| Permissions | Sharing API | Permission management |
File operations in BASIC:
```basic
files = LIST "/reports/"
FOR EACH file IN files
content = READ file.path
processed = LLM "Summarize this document: " + content
WRITE "/summaries/" + file.name + ".summary.txt", processed
NEXT file
```
### Tasks and Planning
Task management APIs create, update, and track work items. General Bots implements a complete task system with project organization.
| Enterprise API | General Bots Equivalent | Implementation |
|----------------|------------------------|----------------|
| Tasks endpoint | Tasks API | `/api/tasks` |
| Task lists | Task lists | Board-based organization |
| Create task | `CREATE TASK` keyword | Task creation |
| Task details | Task CRUD | Full task lifecycle |
Create tasks from conversations:
```basic
TALK "What task should I create?"
HEAR task_title
TALK "When is it due?"
HEAR due_date AS DATE
CREATE TASK task_title DUE due_date
TALK "Task created: " + task_title
```
### Users and Directory
User management APIs handle identity, groups, and permissions. Zitadel provides enterprise-grade IAM with OIDC/OAuth2.
| Enterprise API | General Bots Equivalent | Implementation |
|----------------|------------------------|----------------|
| Users endpoint | Users API | `/api/users` |
| Current user | Current user | Session context |
| Groups | Groups API | `/api/groups` |
| Directory | Directory API | Zitadel directory |
| Memberships | Membership API | Group memberships |
### Automation and Workflows
Cloud automation platforms provide flow-based workflow design. General Bots offers BASIC scripting with more power and flexibility.
| Cloud Automation | General Bots Equivalent | Advantage |
|------------------|------------------------|-----------|
| Scheduled flows | `SET SCHEDULE` | Cron syntax, unlimited |
| HTTP triggers | `WEBHOOK` | Instant API creation |
| Connectors | `GET`, `POST`, GraphQL | Any REST/GraphQL API |
| Conditions | `IF/THEN/ELSE` | Full programming logic |
| Loops | `FOR EACH` | Native iteration |
| Data operations | `TABLE`, `INSERT`, `UPDATE` | Direct database access |
A workflow that would require a visual designer elsewhere becomes simple BASIC:
```basic
SET SCHEDULE "0 9 * * 1-5"
' Daily sales report - runs weekdays at 9 AM
sales = AGGREGATE "orders", "SUM", "total", "date = TODAY()"
count = AGGREGATE "orders", "COUNT", "id", "date = TODAY()"
SET CONTEXT "You are a business analyst. Create a brief executive summary."
summary = LLM "Sales: $" + sales + ", Orders: " + count
SEND MAIL TO "executives@company.com" SUBJECT "Daily Sales Report" BODY summary
```
### AI and Intelligence
Cloud AI assistants typically require additional per-user licensing. General Bots includes AI capabilities at no extra cost.
| Cloud AI Feature | General Bots Equivalent | Advantage |
|------------------|------------------------|-----------|
| AI Assistant | `LLM` keyword | Free (bring your API key) |
| Document analysis | `USE KB` + `LLM` | Built-in RAG |
| Image generation | `IMAGE` keyword | Local generation available |
| Speech-to-text | `HEAR AS AUDIO` | Whisper integration |
| Text-to-speech | `AUDIO` keyword | TTS models |
| Vision/OCR | `SEE` keyword | Vision models |
AI integration is native:
```basic
USE KB "product-docs"
SET CONTEXT "You are a helpful product specialist."
TALK "How can I help you today?"
HEAR question
response = LLM question
TALK response
```
## Feature Parity Matrix
### Core Services
| Service Category | Enterprise Cloud | General Bots | Status |
|------------------|------------------|--------------|--------|
| Email | Cloud mail service | Stalwart Mail | ✅ Complete |
| Calendar | Cloud calendar | CalDAV + Calendar API | ✅ Complete |
| Files | Cloud storage | SeaweedFS | ✅ Complete |
| Video | Cloud meetings | LiveKit | ✅ Complete |
| Chat | Cloud messaging | Multi-channel | ✅ Complete |
| Tasks | Cloud tasks | Tasks Module | ✅ Complete |
| Identity | Cloud identity | Zitadel | ✅ Complete |
| Search | Cloud search | Qdrant Vectors | ✅ Semantic |
### Automation
| Capability | Cloud Platform | General Bots | Status |
|------------|----------------|--------------|--------|
| Scheduled tasks | Scheduled flows | `SET SCHEDULE` | ✅ Complete |
| Webhooks | HTTP triggers | `WEBHOOK` | ✅ Complete |
| API calls | Connectors | HTTP keywords | ✅ Flexible |
| Custom logic | Expressions | Full BASIC | ✅ Powerful |
| Database | Cloud datastore | Direct SQL | ✅ Direct |
| Pricing | Per-user fees | Included | ✅ Free |
### AI Capabilities
| Feature | Cloud AI (extra cost) | General Bots | Status |
|---------|----------------------|--------------|--------|
| Chat assistance | ✅ | `LLM` keyword | ✅ Included |
| Document Q&A | ✅ | `USE KB` + RAG | ✅ Included |
| Code generation | ✅ | `LLM` with context | ✅ Included |
| Image generation | Limited | `IMAGE` keyword | ✅ Full |
| Video generation | ❌ | `VIDEO` keyword | ✅ Available |
| Custom models | ❌ | Any provider | ✅ Flexible |
## Cost Comparison
### Typical Per-User Cloud Licensing
| License Tier | Monthly Cost | 100 Users/Year |
|--------------|--------------|----------------|
| Basic | $6/user | $7,200 |
| Standard | $12.50/user | $15,000 |
| Premium | $22/user | $26,400 |
| + AI features | $30/user | $36,000 |
| **Total Premium + AI** | **$52/user** | **$62,400** |
### General Bots Self-Hosted
| Component | Monthly Cost | Notes |
|-----------|--------------|-------|
| Software | $0 | AGPL licensed |
| Infrastructure | $50-200 | Your servers |
| LLM API (optional) | $50-500 | Pay per use |
| **Total** | **$100-700** | **Unlimited users** |
For 100 users, General Bots costs roughly 1-2% of typical cloud licensing while providing equivalent or better functionality.
## Migration Approach
### Phase 1: Assessment
Inventory current service usage and map to General Bots equivalents. Most organizations find complete feature coverage for core productivity scenarios.
### Phase 2: Parallel Deployment
Run General Bots alongside existing services during transition. Configure identity federation between Zitadel and existing directory services.
### Phase 3: Data Migration
Use provided migration tools and APIs:
```basic
' Example: Migrate files from external storage
files = GET "https://api.storage.example/files"
FOR EACH file IN files
content = DOWNLOAD file.url
WRITE "/" + file.name, content
NEXT file
```
### Phase 4: Cutover
Redirect DNS, update client configurations, and deprecate cloud subscriptions.
## What You Gain
**Data Sovereignty** - Your data stays on your infrastructure. No third-party access, no cross-border data concerns.
**Cost Control** - Predictable infrastructure costs instead of per-user licensing that scales with your organization.
**Customization** - Full source code access. Modify, extend, and integrate as needed.
**AI Integration** - Native LLM support without additional licensing. Use any provider or run models locally.
**Automation Power** - BASIC scripting provides more flexibility than visual flow builders with no per-automation limits.
**No Vendor Lock-in** - Open standards (IMAP, CalDAV, S3, OIDC) mean your data is always portable.
## Migration Resources
General Bots provides tools and documentation for smooth migration:
- **Import utilities** for common data formats
- **API compatibility layers** for gradual transition
- **Identity federation** for single sign-on during migration
- **Data validation tools** to verify migration completeness
## Summary
General Bots delivers enterprise productivity features without enterprise pricing:
- 100% API coverage for core productivity services
- Self-hosted deployment with full data sovereignty
- No per-user licensing fees
- Native AI integration without additional cost
- More powerful automation with BASIC scripting
- Open source with full code access
The choice between cloud and self-hosted depends on organizational priorities. For those valuing control, cost efficiency, and customization, General Bots delivers enterprise-grade productivity without enterprise-grade pricing.
## See Also
- [Quick Start](../chapter-01/quick-start.md) - Deploy in minutes
- [Keywords Reference](../chapter-06-gbdialog/keywords.md) - Full BASIC reference
- [REST API Reference](../chapter-10-api/README.md) - Complete API documentation
- [Migration Guide](../chapter-14-migration/README.md) - Detailed migration steps

View file

@ -1,40 +1,35 @@
# Platform Comparison: General Bots vs Notion AI vs Perplexity # Platform Capabilities
This document compares General Bots with popular AI-powered platforms to highlight unique capabilities and help users understand when to choose each solution. General Bots provides a unique combination of capabilities that differentiate it from other AI platforms. This document outlines what makes General Bots suitable for organizations seeking customizable, self-hosted AI automation.
## Executive Summary <img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
| Capability | General Bots | Notion AI | Perplexity | ## Core Differentiators
|------------|-------------|-----------|------------|
| **Primary Focus** | Customizable AI automation platform | Document collaboration with AI | AI-powered search engine |
| **Self-hosted** | ✅ Yes | ❌ No | ❌ No |
| **Open Source** | ✅ AGPL | ❌ Proprietary | ❌ Proprietary |
| **Custom APIs/Webhooks** | ✅ Full control | ❌ No | ❌ No |
| **Database Integration** | ✅ Full SQL | ⚠️ Limited (Notion DBs) | ❌ No |
| **Custom LLM Backend** | ✅ Any provider | ❌ OpenAI only | ❌ Proprietary |
| **BASIC Programming** | ✅ Native | ❌ No | ❌ No |
| **Multi-channel** | ✅ WhatsApp, Teams, Web, etc. | ❌ Web only | ❌ Web only |
| **File Storage** | ✅ .gbdrive | ⚠️ Notion pages | ❌ No |
| **Email Integration** | ✅ Send/receive | ❌ No | ❌ No |
| **Pricing** | Free (self-hosted) | $10/user/month | $20/month |
## Detailed Comparison ### Self-Hosted & Open Source
### 1. Customization & Extensibility General Bots runs entirely on your infrastructure. Your data never leaves your servers, and you have full access to the source code under AGPL licensing.
#### General Bots | Capability | General Bots |
|------------|-------------|
| Self-hosted deployment | ✅ Full control |
| Open source | ✅ AGPL licensed |
| Data sovereignty | ✅ Your infrastructure |
| Custom modifications | ✅ Full source access |
| Per-user licensing | ✅ None required |
General Bots is designed for maximum customization: ### Customization & Extensibility
Build exactly what you need with BASIC scripting and instant API creation:
```basic ```basic
' Create a custom API endpoint in one line ' Create a custom API endpoint
WEBHOOK "customer-lookup" WEBHOOK "customer-lookup"
customer_id = params.id customer_id = params.id
USE KB "customer-data" USE KB "customer-data"
' AI-powered response response = LLM "Get information about customer " + customer_id
response = LLM "Get all information about customer " + customer_id
WITH result = NEW OBJECT WITH result = NEW OBJECT
.customer_id = customer_id .customer_id = customer_id
@ -43,37 +38,19 @@ WITH result = NEW OBJECT
END WITH END WITH
``` ```
**Capabilities:** This creates a working API endpoint in seconds—no separate deployment, no infrastructure configuration.
- Create unlimited custom webhooks/APIs
- Write automation in BASIC syntax
- Integrate with any external system
- Self-host with full control
- Modify source code (AGPL license)
#### Notion AI **What you can build:**
- Custom webhooks and APIs
- Automated workflows with BASIC scripts
- Integrations with any external system
- Multi-channel chatbots
- Document processing pipelines
- Scheduled automation tasks
Limited to built-in features: ### Knowledge Base & RAG
- Summarize pages
- Generate content
- Translate text
- Brainstorm ideas
- No custom API creation
- No webhook support
- No programmatic automation
#### Perplexity Full control over your knowledge base with built-in retrieval-augmented generation:
Search-focused only:
- Ask questions, get answers
- No customization
- No API creation
- No automation capabilities
### 2. Knowledge Base & RAG
#### General Bots
Full control over your knowledge base:
```basic ```basic
' Load multiple knowledge sources ' Load multiple knowledge sources
@ -81,20 +58,16 @@ USE KB "company-policies"
USE KB "product-catalog" USE KB "product-catalog"
USE KB "customer-faq" USE KB "customer-faq"
' Set custom context SET CONTEXT "You are a helpful customer service agent."
SET CONTEXT "You are a helpful customer service agent for Acme Corp."
' Query with RAG
answer = LLM user_question answer = LLM user_question
' Save conversation for training ' Save for training and analysis
WITH conversation = NEW OBJECT INSERT "conversations", #{
.question = user_question question: user_question,
.answer = answer answer: answer,
.timestamp = NOW() timestamp: NOW()
.user_id = user.id }
END WITH
INSERT "conversations", conversation
``` ```
**Features:** **Features:**
@ -105,401 +78,138 @@ INSERT "conversations", conversation
- Semantic caching - Semantic caching
- Full document indexing - Full document indexing
#### Notion AI ### Multi-Channel Deployment
- Only searches within Notion workspace Deploy once, reach users everywhere:
- No external document upload for AI
- Limited to Notion page structure
- No custom embeddings
#### Perplexity
- Searches the web in real-time
- No custom document upload (free tier)
- Pro tier allows file upload
- No persistent knowledge base
### 3. Automation & Workflows
#### General Bots
Complete automation platform:
```basic ```basic
' Scheduled automation ' Same code works across all channels
SET SCHEDULE "daily-report", "0 9 * * *" TALK "How can I help you today?"
' Fetch data from multiple sources
sales = GET "https://api.crm.com/sales/today"
inventory = FIND "inventory", "stock < 10"
support_tickets = GET "https://api.zendesk.com/tickets/open"
' AI-generated summary
SET CONTEXT "You are a business analyst. Create an executive summary."
summary = LLM "Summarize: Sales: " + sales + ", Low stock: " + inventory + ", Open tickets: " + support_tickets
' Send report
SEND MAIL "executives@company.com", "Daily Business Report", summary
' Post to Slack
WITH slack_msg = NEW OBJECT
.text = summary
.channel = "#daily-reports"
END WITH
POST "https://hooks.slack.com/services/xxx", slack_msg
```
**Automation types:**
- Scheduled tasks (cron)
- Webhooks (event-driven)
- Database triggers (ON keyword)
- Multi-channel messaging
- Email workflows
- File processing pipelines
#### Notion AI
- No automation capabilities
- Manual AI invocation only
- No scheduled tasks
- No webhooks
- No external integrations
#### Perplexity
- No automation
- Interactive queries only
- No scheduling
- No integrations
### 4. Multi-Channel Communication
#### General Bots
Deploy to any channel:
```basic
' Same BASIC code works on all channels
TALK "Hello! How can I help you today?"
HEAR question HEAR question
response = LLM question
USE KB "support-docs" TALK response
answer = LLM question
TALK answer
' Channel-specific features
IF channel = "whatsapp" THEN
' Send WhatsApp-specific media
TALK IMAGE "product-photo.jpg"
ELSE IF channel = "teams" THEN
' Teams adaptive card
TALK CARD "product-details"
END IF
``` ```
**Supported channels:** **Supported channels:**
- Web chat
- WhatsApp Business - WhatsApp Business
- Microsoft Teams - Teams
- Slack - Slack
- Telegram - Telegram
- Web chat
- SMS - SMS
- Email - Email
- Voice (coming soon) - Voice (LiveKit)
#### Notion AI ### Database & Integration
- Web interface only Direct database access and unlimited API integrations:
- No mobile app AI
- No chat deployments
- No messaging integrations
#### Perplexity
- Web interface
- Mobile apps
- No third-party deployments
- No messaging integrations
### 5. Data Privacy & Control
#### General Bots
**Full data sovereignty:**
- Self-hosted on your infrastructure
- Data never leaves your servers
- Choose your own LLM provider
- Audit logs and compliance
- GDPR/HIPAA ready
```basic ```basic
' All data stays on your servers ' Direct SQL access
SAVE "customer_data", customer_id, sensitive_info customers = FIND "customers", "region = 'EMEA'"
' Use local LLM if needed
SET CONTEXT "Use local Llama model"
response = LLM query
```
#### Notion AI
- Data stored on Notion servers (US/EU)
- Uses OpenAI (data sent to OpenAI)
- Limited compliance features
- SOC 2 Type 2 certified
#### Perplexity
- Data stored on Perplexity servers
- Search queries may be logged
- Limited privacy controls
- No self-hosting option
### 6. Integration Capabilities
#### General Bots
Native HTTP/API support:
```basic
' REST APIs ' REST APIs
customers = GET "https://api.salesforce.com/customers" data = GET "https://api.example.com/data"
POST "https://api.hubspot.com/contacts", contact_data POST "https://api.crm.com/leads", lead_data
PUT "https://api.stripe.com/customers/123", update_data
DELETE "https://api.service.com/items/456"
' GraphQL ' GraphQL
query = "query { user(id: 123) { name email } }"
result = GRAPHQL "https://api.github.com/graphql", query, vars result = GRAPHQL "https://api.github.com/graphql", query, vars
' SOAP (legacy systems)
result = SOAP "https://legacy.corp.com/service.wsdl", "GetCustomer", params
' Database
data = FIND "products", "category='electronics'"
INSERT "orders", order_data
UPDATE "inventory", "sku=ABC123", stock_update
``` ```
**Integrations:** No connector marketplace, no per-integration fees—connect to anything with HTTP.
- Any REST API
- GraphQL endpoints
- SOAP services
- SQL databases
- S3-compatible storage
- Email (SMTP/IMAP)
- Calendar (CalDAV)
- Any webhook-capable service
#### Notion AI ### AI Capabilities
- Notion API only Native AI integration without additional licensing:
- Limited integrations via Notion
- No direct external API calls
- No database connections
#### Perplexity | Feature | Implementation |
|---------|---------------|
| Chat assistance | `LLM` keyword |
| Document Q&A | `USE KB` + RAG |
| Image generation | `IMAGE` keyword |
| Video generation | `VIDEO` keyword |
| Speech-to-text | `HEAR AS AUDIO` |
| Text-to-speech | `AUDIO` keyword |
| Vision/OCR | `SEE` keyword |
- No API integrations Use any LLM provider (OpenAI, Anthropic, local models) or run entirely offline with local inference.
- Search only
- No external data sources
### 7. Document Processing ## Automation Power
#### General Bots BASIC scripting provides full programming capabilities:
Full document pipeline:
```basic ```basic
' Upload and process documents SET SCHEDULE "every day at 9am"
HEAR document AS FILE
url = UPLOAD document, "uploads/"
' Extract text from various formats ' Daily report automation
content = GET "documents/report.pdf" sales = AGGREGATE "orders", "SUM", "total", "date = TODAY()"
count = AGGREGATE "orders", "COUNT", "id", "date = TODAY()"
' AI processing SET CONTEXT "You are a business analyst."
SET CONTEXT "Extract key metrics from this report" summary = LLM "Sales: $" + sales + ", Orders: " + count
metrics = LLM content
' Generate new documents SEND MAIL TO "team@company.com" SUBJECT "Daily Report" BODY summary
WITH invoice_data = NEW OBJECT
.customer = customer_name
.items = order_items
.total = order_total
END WITH
pdf = GENERATE PDF "templates/invoice.html", invoice_data, "invoices/inv-001.pdf"
' Merge multiple PDFs
merged = MERGE PDF ["cover.pdf", "report.pdf", "appendix.pdf"], "final-report.pdf"
' Compress and send
archive = COMPRESS ["report.pdf", "data.xlsx"], "delivery.zip"
SEND MAIL customer_email, "Your Report", "Please find attached.", archive
``` ```
**Supported formats:** **Automation features:**
- PDF (read, generate, merge) - Scheduled tasks (cron syntax)
- Office documents (Word, Excel, PowerPoint) - Event-driven webhooks
- Images (OCR support) - Database triggers
- CSV/JSON data - Conditional logic
- Archives (ZIP, TAR) - Loops and iterations
- Error handling
- Multi-step workflows
#### Notion AI ## When General Bots Excels
- Notion pages only General Bots is the right choice when you need:
- Export to PDF/Markdown
- No document generation
- No PDF processing
#### Perplexity **Custom chatbots** for customer service, internal support, or specialized domains where you control the knowledge base and conversation flow.
- Can read uploaded PDFs (Pro) **Workflow automation** that goes beyond simple triggers—full programming logic with database access, API calls, and AI integration.
- No document generation
- No processing capabilities
### 8. Cost Comparison **Multi-channel deployment** where the same bot serves users on web, mobile messaging, and enterprise platforms.
#### General Bots (Self-hosted) **Data sovereignty** with self-hosted deployment keeping all data on your infrastructure.
| Component | Cost | **Cost control** without per-user licensing that scales with your organization.
|-----------|------|
| Software | Free (AGPL) |
| Infrastructure | $20-100/month (your servers) |
| LLM API | Pay per use (OpenAI, etc.) |
| **Total** | **$20-200/month** (unlimited users) |
#### Notion AI **Integration flexibility** connecting to any system without marketplace limitations.
| Plan | Cost | ## Deployment Options
|------|------|
| Free | Limited AI features |
| Plus | $10/user/month |
| Business | $18/user/month |
| **10 users** | **$100-180/month** |
#### Perplexity ### Self-Hosted
| Plan | Cost | Run General Bots on your own infrastructure:
|------|------| - Single binary deployment
| Free | Limited queries | - Container support (LXC, Docker)
| Pro | $20/month | - Scales horizontally
| Team | $20/user/month | - Full observability
| **10 users** | **$200/month** |
### 9. Use Case Recommendations ### Quick Start
#### Choose General Bots when you need: ```bash
./botserver
- ✅ Custom chatbots for customer service
- ✅ Internal automation workflows
- ✅ Multi-channel deployment (WhatsApp, Teams, etc.)
- ✅ Integration with existing systems
- ✅ Custom APIs without traditional development
- ✅ Data privacy and self-hosting
- ✅ Complex business logic in simple BASIC
- ✅ Document processing pipelines
- ✅ Scheduled tasks and webhooks
#### Choose Notion AI when you need:
- ✅ Document collaboration with AI assist
- ✅ Team knowledge management
- ✅ Content writing assistance
- ✅ Simple Q&A within documents
- ✅ Project management with AI
#### Choose Perplexity when you need:
- ✅ Research and fact-checking
- ✅ Real-time web search with AI
- ✅ Quick answers with citations
- ✅ Exploring topics
## Feature Matrix
| Feature | General Bots | Notion AI | Perplexity |
|---------|-------------|-----------|------------|
| **AI Chat** | ✅ | ✅ | ✅ |
| **Custom Knowledge Base** | ✅ | ⚠️ | ⚠️ |
| **API Creation** | ✅ | ❌ | ❌ |
| **Webhooks** | ✅ | ❌ | ❌ |
| **Scheduled Tasks** | ✅ | ❌ | ❌ |
| **Database** | ✅ | ⚠️ | ❌ |
| **File Storage** | ✅ | ⚠️ | ❌ |
| **Email** | ✅ | ❌ | ❌ |
| **WhatsApp** | ✅ | ❌ | ❌ |
| **Teams** | ✅ | ❌ | ❌ |
| **Slack** | ✅ | ⚠️ | ❌ |
| **PDF Generation** | ✅ | ❌ | ❌ |
| **Custom LLM** | ✅ | ❌ | ❌ |
| **Self-hosted** | ✅ | ❌ | ❌ |
| **Open Source** | ✅ | ❌ | ❌ |
| **Real-time Web Search** | ⚠️ | ❌ | ✅ |
| **Document Collaboration** | ⚠️ | ✅ | ❌ |
## Migration Path
### From Notion AI to General Bots
1. Export Notion pages as Markdown
2. Upload to General Bots knowledge base
3. Create BASIC scripts for automation
4. Deploy to additional channels
```basic
' Import Notion export
files = LIST "notion-export/"
FOR EACH file IN files
content = GET file
USE KB "imported-docs"
' Documents automatically indexed
NEXT file
TALK "Notion content imported and ready for AI queries!"
``` ```
### From Perplexity to General Bots Access at `http://localhost:8080` and start building.
1. Identify common queries ## Summary
2. Build knowledge base from trusted sources
3. Create custom Q&A endpoint
```basic General Bots combines:
' Replace Perplexity with custom research endpoint
WEBHOOK "research"
query = body.query - **Self-hosting** for complete data control
USE KB "trusted-sources" - **BASIC scripting** for powerful automation
USE WEBSITE "https://docs.company.com" - **Multi-channel** for broad reach
- **Native AI** without extra licensing
- **Open source** for transparency and customization
- **No per-user fees** for predictable costs
SET CONTEXT "Provide accurate, cited answers based on the knowledge base." For organizations that need more than a simple chatbot—those requiring custom integrations, complex workflows, and full control over their AI deployment—General Bots provides the foundation to build exactly what you need.
answer = LLM query
WITH result = NEW OBJECT
.query = query
.answer = answer
.sources = "Internal knowledge base"
END WITH
```
## Conclusion
**General Bots** stands apart as the only platform that combines:
1. **Full customization** - Write BASIC code for any automation
2. **Self-hosting** - Complete data control
3. **Multi-channel** - Deploy anywhere
4. **Open source** - Modify and extend freely
5. **Cost-effective** - No per-user pricing
While Notion AI excels at document collaboration and Perplexity at web search, General Bots is the choice for organizations that need **customizable, self-hosted AI automation** with **enterprise-grade capabilities**.
## See Also ## See Also
- [Quick Start](../chapter-01/quick-start.md) - Get started in 5 minutes - [Quick Start](../chapter-01/quick-start.md) - Get running in minutes
- [WEBHOOK](../chapter-06-gbdialog/keyword-webhook.md) - Create instant APIs
- [Keywords Reference](../chapter-06-gbdialog/keywords.md) - Full BASIC reference - [Keywords Reference](../chapter-06-gbdialog/keywords.md) - Full BASIC reference
- [Architecture](../chapter-07-gbapp/architecture.md) - Technical deep dive - [REST API](../chapter-10-api/README.md) - API documentation
- [Projects](./projects.md) - Team collaboration features

View file

@ -0,0 +1,348 @@
# Projects
Projects organize work and enable team collaboration within General Bots. A project groups related tasks, conversations, documents, and team members into a shared workspace where everyone stays aligned.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Every bot starts with a default project. Users can create additional projects to organize different initiatives, clients, or departments. When chatting with the bot, selecting a project scopes the conversation to that context—the AI understands what you're working on and who else is involved.
Projects connect three core capabilities:
- **Tasks** belong to projects, making it easy to track work across teams
- **Conversations** can be project-scoped, so the AI has relevant context
- **Team members** are assigned to projects, enabling collaboration
## Creating Projects
### Via Chat
```
User: Create a new project called Website Redesign
Bot: Project "Website Redesign" created. Would you like to add team members?
User: Yes, add maria@company.com and john@company.com
Bot: Added Maria and John to the project. You can now assign tasks and chat within this project context.
```
### Via BASIC
```basic
' create-project.bas
PARAM name AS string
PARAM description AS string
DESCRIPTION "Create a new project workspace"
project_id = CREATE PROJECT name WITH DESCRIPTION description
TALK "Project created: " + name
' Add current user as owner
ADD USER TO PROJECT project_id, user.id, "owner"
```
### Via API
```
POST /api/projects
{
"name": "Website Redesign",
"description": "Q2 website refresh initiative",
"members": ["user-id-1", "user-id-2"]
}
```
## Project Structure
Each project contains:
```
Project
├── Settings
│ ├── Name and description
│ ├── Visibility (private/team/public)
│ └── Default assignee
├── Members
│ ├── Owners (full control)
│ ├── Members (can edit)
│ └── Viewers (read only)
├── Tasks
│ ├── Boards and columns
│ ├── Task items
│ └── Dependencies
├── Conversations
│ ├── Project chat history
│ └── AI context from project docs
└── Files
└── Project-specific documents
```
## Working with Projects
### Switching Project Context
In the chat interface, select a project from the project dropdown. All subsequent conversations use that project's context:
```
[Project: Website Redesign ▼]
User: What tasks are due this week?
Bot: In the Website Redesign project, you have 3 tasks due this week:
1. Finalize homepage mockups (Friday)
2. Review navigation structure (Wednesday)
3. Content inventory spreadsheet (Thursday)
```
### Project-Scoped AI
When a project is selected, the AI automatically:
- References project documents in responses
- Knows about team members and their roles
- Understands project-specific terminology from past conversations
- Suggests relevant tasks and next steps
```
User: Who's working on the design?
Bot: Maria is assigned to the design tasks. She completed the color palette
yesterday and is currently working on the homepage mockups. John is
handling the technical implementation once designs are approved.
```
### Team Collaboration
Project members can chat together with AI assistance:
```
Maria: @bot summarize what we discussed about the navigation
Bot: Based on your project conversations, the team decided on:
- Simplified top nav with 5 main sections
- Mega menu for product categories
- Mobile-first hamburger menu
John raised concerns about dropdown accessibility that still need addressing.
```
## BASIC Keywords for Projects
### CREATE PROJECT
```basic
project_id = CREATE PROJECT "Marketing Campaign" WITH DESCRIPTION "Q3 launch"
```
### GET PROJECT
```basic
project = GET PROJECT project_id
TALK "Project: " + project.name
TALK "Members: " + LEN(project.members)
TALK "Open tasks: " + project.task_count
```
### LIST PROJECTS
```basic
' List user's projects
projects = LIST PROJECTS
FOR EACH p IN projects
TALK p.name + " (" + p.role + ")"
NEXT p
' List projects with filter
active = LIST PROJECTS WHERE "status = 'active'"
```
### ADD USER TO PROJECT
```basic
ADD USER TO PROJECT project_id, user_id, "member"
ADD USER TO PROJECT project_id, email, "owner"
```
### REMOVE USER FROM PROJECT
```basic
REMOVE USER FROM PROJECT project_id, user_id
```
### SET PROJECT
Set the current conversation's project context:
```basic
SET PROJECT project_id
' Subsequent operations use this project context
CREATE TASK "Review designs" ' Task created in the selected project
```
### DELETE PROJECT
```basic
DELETE PROJECT project_id
' Or via dynamic path
DELETE "/projects/" + project_id
```
## API Reference
### List Projects
```
GET /api/projects
```
Returns projects the authenticated user can access.
### Get Project
```
GET /api/projects/{id}
```
Returns project details including members and task summary.
### Create Project
```
POST /api/projects
{
"name": "Project Name",
"description": "Optional description",
"visibility": "team",
"members": [
{"user_id": "...", "role": "owner"},
{"user_id": "...", "role": "member"}
]
}
```
### Update Project
```
PUT /api/projects/{id}
{
"name": "Updated Name",
"description": "Updated description"
}
```
### Delete Project
```
DELETE /api/projects/{id}
```
### Project Members
```
GET /api/projects/{id}/members
POST /api/projects/{id}/members
DELETE /api/projects/{id}/members/{user_id}
```
### Project Tasks
```
GET /api/projects/{id}/tasks
POST /api/projects/{id}/tasks
```
### Project Conversations
```
GET /api/projects/{id}/conversations
```
## Database Schema
Projects are stored in the `projects` table:
| Column | Type | Description |
|--------|------|-------------|
| `id` | UUID | Project identifier |
| `bot_id` | UUID | Owning bot |
| `name` | TEXT | Project name |
| `description` | TEXT | Optional description |
| `visibility` | TEXT | private, team, or public |
| `settings` | JSONB | Project configuration |
| `created_by` | UUID | Creator user ID |
| `created_at` | TIMESTAMP | Creation time |
| `updated_at` | TIMESTAMP | Last update |
Project membership in `project_members`:
| Column | Type | Description |
|--------|------|-------------|
| `project_id` | UUID | Project reference |
| `user_id` | UUID | User reference |
| `role` | TEXT | owner, member, or viewer |
| `joined_at` | TIMESTAMP | When user joined |
## Default Project
Every bot has a default project that cannot be deleted. Tasks created without specifying a project go here. Users can:
- Rename the default project
- Move tasks from default to specific projects
- Use the default for personal/unorganized work
```basic
' Get the default project
default = GET DEFAULT PROJECT
TALK "Default project: " + default.name
```
## Project Templates
Create projects from templates for common scenarios:
```basic
' Create from template
project_id = CREATE PROJECT FROM TEMPLATE "client-onboarding", "Acme Corp Onboarding"
' Available templates
templates = LIST PROJECT TEMPLATES
```
Built-in templates include:
- **Client Onboarding** - Tasks for new client setup
- **Product Launch** - Launch checklist and milestones
- **Sprint** - Two-week sprint with standard ceremonies
- **Content Calendar** - Monthly content planning
## Best Practices
**Keep projects focused.** A project should represent a distinct initiative with clear boundaries. If a project grows too large, consider splitting it.
**Assign clear ownership.** Every project needs at least one owner responsible for keeping it organized and moving forward.
**Use project context in chat.** When discussing project-specific topics, select the project first so the AI has full context.
**Archive completed projects.** Rather than deleting, archive finished projects to preserve history:
```basic
UPDATE PROJECT project_id SET status = "archived"
```
**Review project membership regularly.** Remove users who are no longer involved to keep conversations relevant.
## Integration with Tasks
Tasks belong to exactly one project. The task view shows the default project by default, with options to filter by project or view all tasks across projects.
```basic
' Create task in specific project
SET PROJECT project_id
CREATE TASK "Design review" DUE DATEADD(NOW(), 7, "day")
' Or specify project directly
CREATE TASK "Design review" IN PROJECT project_id
```
## See Also
- [Tasks API](../chapter-10-api/tasks-api.md) - Task management endpoints
- [Conversations API](../chapter-10-api/conversations-api.md) - Chat history
- [Groups API](../chapter-10-api/groups-api.md) - User group management
- [SET CONTEXT](../chapter-06-gbdialog/keyword-set-context.md) - AI context configuration

View file

@ -0,0 +1,461 @@
# Botpress Migration Guide
Migrating chatbots from Botpress to General Bots.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Botpress is an open-source chatbot platform with visual flow builder and NLU. General Bots provides a simpler approach using LLM-based understanding and BASIC scripting, with integrated productivity features and native multi-channel support.
## Why Migrate
| Aspect | Botpress | General Bots |
|--------|----------|--------------|
| NLU Approach | Intent training required | LLM-based (no training) |
| Flow Building | Visual + code | BASIC scripts |
| Self-hosting | Available | Available |
| AI Integration | Via hooks | Native LLM keywords |
| Knowledge Base | Limited | Full RAG system |
| Productivity Suite | Not included | Email, calendar, files, tasks |
| Multi-channel | Via connectors | Native support |
| Learning Curve | Moderate | Simple BASIC |
## Concept Mapping
| Botpress Concept | General Bots Equivalent |
|------------------|------------------------|
| Flows | BASIC scripts |
| Nodes | BASIC statements |
| Intents | LLM understanding |
| Entities | `HEAR AS <type>` |
| Slots | Variables |
| Actions | BASIC keywords |
| Hooks | `ON` triggers |
| Content Types | TALK variations |
| Knowledge Base | `.gbkb` folders |
| Channels | Native multi-channel |
## Flow Migration
### Botpress Flow Structure
```yaml
# Botpress flow (simplified)
nodes:
- id: entry
type: standard
next: ask_name
- id: ask_name
type: say_something
content: "What's your name?"
next: capture_name
- id: capture_name
type: listen
slot: name
next: greet
- id: greet
type: say_something
content: "Hello {{name}}!"
```
### General Bots Equivalent
```basic
' Simple and readable
TALK "What's your name?"
HEAR name AS NAME
TALK "Hello " + name + "!"
```
## Migration Examples
### Simple Welcome Flow
**Botpress:**
- Entry node → Say "Welcome" → Listen for intent → Route to sub-flow
**General Bots:**
```basic
USE KB "help-docs"
SET CONTEXT "You are a friendly assistant for Acme Corp."
TALK "Welcome! How can I help you today?"
HEAR question
answer = LLM question
TALK answer
```
### Lead Capture Flow
**Botpress:**
```
Entry → Ask Name → Capture Slot → Ask Email → Capture Slot →
Ask Company → Capture Slot → Save to CRM → Thank You
```
**General Bots:**
```basic
' lead-capture.bas
TALK "I'd love to learn more about you!"
TALK "What's your name?"
HEAR name AS NAME
TALK "And your work email?"
HEAR email AS EMAIL
TALK "What company are you with?"
HEAR company
' Save directly - no external action needed
INSERT "leads", #{
name: name,
email: email,
company: company,
source: "chatbot",
created_at: NOW()
}
' Score the lead
score = SCORE LEAD #{name: name, email: email, company: company}
IF score.status = "hot" THEN
SEND MAIL TO "sales@company.com" SUBJECT "Hot Lead" BODY "New lead: " + name + " from " + company
END IF
TALK "Thanks, " + name + "! Someone from our team will be in touch soon."
```
### FAQ Bot with Fallback
**Botpress:**
- NLU intent matching
- Knowledge base query
- Fallback to human
**General Bots:**
```basic
USE KB "faq"
USE KB "product-docs"
SET CONTEXT "Answer customer questions helpfully. If you cannot answer confidently, offer to connect with a human."
TALK "What can I help you with?"
HEAR question
answer = LLM question
' Check if confident answer
IF CONTAINS(LOWER(answer), "i don't") OR CONTAINS(LOWER(answer), "not sure") THEN
TALK "I'm not certain about that. Would you like to speak with someone?"
HEAR wants_human AS BOOLEAN
IF wants_human THEN
CREATE TASK "Customer inquiry: " + question
SEND MAIL TO "support@company.com" SUBJECT "Chat Handoff" BODY question
TALK "I've notified our team. Someone will reach out shortly."
END IF
ELSE
TALK answer
END IF
```
### Multi-Step Booking Flow
**Botpress:**
```
Select Service → Choose Date → Choose Time → Confirm → Book
(Multiple nodes with slot filling)
```
**General Bots:**
```basic
TALK "Let's book your appointment."
TALK "What service do you need?"
HEAR service AS "Consultation", "Checkup", "Follow-up", "Emergency"
TALK "What date works for you?"
HEAR appt_date AS DATE
TALK "What time?"
HEAR appt_time AS HOUR
' Check availability
available = GET "https://calendar.api/available?date=" + appt_date + "&time=" + appt_time
IF available THEN
BOOK service AT appt_date + " " + appt_time
TALK "Your " + service + " is confirmed for " + FORMAT(appt_date, "MMMM d") + " at " + appt_time
ELSE
TALK "That slot isn't available. Would " + available.next + " work instead?"
END IF
```
## NLU Migration
### Botpress Intents
```yaml
# Botpress intent definition
intents:
- name: order_status
utterances:
- where is my order
- track my order
- order status
- what happened to my order
```
### General Bots Approach
No intent definition needed. The LLM understands naturally:
```basic
USE KB "order-help"
SET CONTEXT "Help customers with their orders."
TALK "How can I help with your order?"
HEAR question
' LLM understands "where is my order", "track order", etc.
' without explicit training
answer = LLM question
```
### Entity Extraction
**Botpress:**
```yaml
entities:
- name: order_number
type: pattern
pattern: "ORD-[0-9]{6}"
```
**General Bots:**
```basic
TALK "What's your order number?"
HEAR order_number
' Or with validation pattern
IF NOT MATCH(order_number, "ORD-[0-9]{6}") THEN
TALK "Please enter a valid order number (e.g., ORD-123456)"
HEAR order_number
END IF
```
## Actions Migration
### Botpress Custom Actions
```javascript
// Botpress action
const checkOrderStatus = async (orderId) => {
const response = await axios.get(`/api/orders/${orderId}`);
return response.data.status;
};
```
### General Bots
```basic
' Direct API call - no separate action file
order = GET "https://api.company.com/orders/" + order_id
TALK "Your order status is: " + order.status
```
## Hooks Migration
### Botpress Hooks
```javascript
// before_incoming_middleware hook
bp.events.on('before_incoming_middleware', async (event) => {
// Custom logic
});
```
### General Bots Triggers
```basic
' Event-driven triggers
ON "message:received"
' Log all messages
INSERT "message_log", #{
content: params.content,
user: params.user_id,
timestamp: NOW()
}
END ON
ON "session:started"
' Track new sessions
INSERT "sessions", #{
id: params.session_id,
started: NOW()
}
END ON
```
## Content Types
### Botpress Content
```javascript
// Botpress content types
{
type: 'builtin_card',
title: 'Product',
image: 'product.jpg',
actions: [{ title: 'Buy', action: 'buy' }]
}
```
### General Bots
```basic
' Text
TALK "Hello!"
' Image
TALK IMAGE "/products/featured.jpg"
' File
TALK FILE "/docs/brochure.pdf"
' Suggestions
ADD SUGGESTION "View Products"
ADD SUGGESTION "Contact Sales"
ADD SUGGESTION "Get Help"
TALK "What would you like to do?"
```
## Knowledge Base Migration
### Botpress Q&A
Limited to question-answer pairs.
### General Bots RAG
Full document support:
```
my-bot.gbkb/
├── products/
│ ├── catalog.pdf
│ ├── specs.xlsx
│ └── pricing.md
├── support/
│ ├── faq.md
│ └── troubleshooting.md
└── company/
├── about.md
└── policies.pdf
```
```basic
USE KB "products"
USE KB "support"
USE KB "company"
answer = LLM customer_question
```
## Channel Migration
### Botpress Channels
Requires separate connector configuration for each channel.
### General Bots
Native multi-channel with same code:
```basic
' Works everywhere: Web, WhatsApp, Teams, Slack, Telegram, SMS
TALK "How can I help?"
HEAR question
answer = LLM question
TALK answer
```
## Database and State
### Botpress State
```javascript
// Botpress user state
event.state.user.name = 'John';
event.state.session.orderId = '12345';
```
### General Bots
```basic
' Session/conversation memory
SET BOT MEMORY "customer_name", name
SET BOT MEMORY "current_order", order_id
' Retrieve
name = GET BOT MEMORY "customer_name"
' Persistent storage
INSERT "customers", #{name: name, email: email}
customer = FIND "customers", "email = '" + email + "'"
```
## What You Gain
**Simpler Development:** BASIC scripts are more readable than visual flows with scattered code.
**No NLU Training:** LLM understands variations without explicit intent training.
**Native AI:** Full LLM integration without plugins.
**Productivity Suite:** Built-in email, calendar, files, and tasks.
**Unified Platform:** Chat, automation, and productivity in one system.
**True Multi-Channel:** Same code works everywhere without channel-specific configuration.
## Migration Checklist
### Pre-Migration
- [ ] Export Botpress flows and content
- [ ] Document intents and entities
- [ ] List custom actions
- [ ] Export Q&A/knowledge base
- [ ] Note channel configurations
### Migration
- [ ] Set up General Bots environment
- [ ] Create BASIC scripts for main flows
- [ ] Build knowledge base structure
- [ ] Implement entity validation
- [ ] Configure channels
- [ ] Test all flows
### Post-Migration
- [ ] Compare conversation quality
- [ ] Verify integrations
- [ ] Train team
- [ ] Redirect channel endpoints
- [ ] Decommission Botpress
## See Also
- [Dialog Basics](../chapter-06-gbdialog/basics.md) - Script fundamentals
- [HEAR Keyword](../chapter-06-gbdialog/keyword-hear.md) - Input validation
- [Knowledge Base](../chapter-03/README.md) - RAG configuration
- [Platform Comparison](./comparison-matrix.md) - Full comparison

View file

@ -0,0 +1,200 @@
# Platform Comparison Matrix
This comprehensive comparison helps organizations evaluate General Bots against major productivity, automation, and AI platforms.
<img src="../assets/platform-comparison-summary.svg" alt="Platform Comparison Summary" style="max-height: 450px; width: 100%; object-fit: contain;">
## Executive Summary
General Bots uniquely combines self-hosted deployment, open source licensing, native AI integration, and powerful BASIC scripting—capabilities that typically require multiple expensive subscriptions across competing platforms.
## Complete Platform Comparison
### Deployment & Licensing
| Capability | General Bots | Microsoft 365 | Google Workspace | n8n | Notion | Perplexity | Claude | Make/Zapier |
|------------|-------------|---------------|------------------|-----|--------|------------|--------|-------------|
| Self-hosted | ✅ Full | ❌ Cloud only | ❌ Cloud only | ✅ Available | ❌ Cloud only | ❌ Cloud only | ❌ Cloud only | ❌ Cloud only |
| Open source | ✅ AGPL | ❌ Proprietary | ❌ Proprietary | ✅ Fair-code | ❌ Proprietary | ❌ Proprietary | ❌ Proprietary | ❌ Proprietary |
| Data sovereignty | ✅ Your servers | ❌ Microsoft servers | ❌ Google servers | ✅ Self-host option | ❌ AWS/GCP | ❌ Their servers | ❌ Anthropic servers | ❌ Their servers |
| Per-user licensing | ✅ None | ❌ $12-57/user/mo | ❌ $6-18/user/mo | ⚠️ Cloud version | ❌ $10-15/user/mo | ❌ $20/mo | ❌ $20/mo | ❌ Per-task pricing |
| Source code access | ✅ Full | ❌ None | ❌ None | ✅ Available | ❌ None | ❌ None | ❌ None | ❌ None |
| Modify & extend | ✅ Unlimited | ❌ API only | ❌ API only | ✅ Possible | ❌ API only | ❌ None | ❌ None | ❌ None |
### Productivity Suite
| Capability | General Bots | Microsoft 365 | Google Workspace | n8n | Notion | Perplexity | Claude | Make/Zapier |
|------------|-------------|---------------|------------------|-----|--------|------------|--------|-------------|
| Email | ✅ Stalwart | ✅ Exchange | ✅ Gmail | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None |
| Calendar | ✅ CalDAV | ✅ Outlook | ✅ Calendar | ❌ None | ❌ Basic | ❌ None | ❌ None | ❌ None |
| File storage | ✅ SeaweedFS | ✅ OneDrive | ✅ Drive | ❌ None | ⚠️ Limited | ❌ None | ❌ None | ❌ None |
| Tasks/Projects | ✅ Full | ✅ Planner | ✅ Tasks | ❌ None | ✅ Strong | ❌ None | ❌ None | ❌ None |
| Video meetings | ✅ LiveKit | ✅ Teams | ✅ Meet | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None |
| Team chat | ✅ Multi-channel | ✅ Teams | ✅ Chat | ❌ None | ⚠️ Comments | ❌ None | ❌ None | ❌ None |
| Document editing | ✅ Available | ✅ Office apps | ✅ Docs/Sheets | ❌ None | ✅ Pages | ❌ None | ❌ None | ❌ None |
| Identity/SSO | ✅ Zitadel | ✅ Entra ID | ✅ Identity | ❌ None | ⚠️ Basic | ❌ None | ❌ None | ❌ None |
### AI & Intelligence
| Capability | General Bots | Microsoft 365 | Google Workspace | n8n | Notion | Perplexity | Claude | Make/Zapier |
|------------|-------------|---------------|------------------|-----|--------|------------|--------|-------------|
| LLM integration | ✅ Any provider | ⚠️ Copilot ($30/user) | ⚠️ Gemini (extra) | ⚠️ Via nodes | ⚠️ Limited | ✅ Built-in | ✅ Built-in | ⚠️ Via connectors |
| Custom prompts | ✅ Full control | ⚠️ Limited | ⚠️ Limited | ✅ Available | ⚠️ Basic | ⚠️ Limited | ✅ Available | ⚠️ Limited |
| RAG/Knowledge base | ✅ Built-in | ⚠️ Extra cost | ⚠️ Extra cost | ⚠️ Custom build | ⚠️ Page search | ⚠️ Pro only | ⚠️ Projects | ❌ None |
| Image generation | ✅ Local SD | ⚠️ Designer | ⚠️ Limited | ⚠️ Via API | ❌ None | ⚠️ Limited | ✅ Available | ⚠️ Via API |
| Video generation | ✅ Zeroscope | ❌ None | ❌ None | ⚠️ Via API | ❌ None | ❌ None | ❌ None | ⚠️ Via API |
| Speech-to-text | ✅ Whisper | ⚠️ Extra | ⚠️ Extra | ⚠️ Via API | ❌ None | ❌ None | ❌ None | ⚠️ Via API |
| Vision/OCR | ✅ BLIP2 | ⚠️ Extra | ⚠️ Extra | ⚠️ Via API | ❌ None | ❌ None | ✅ Available | ⚠️ Via API |
| Local/offline AI | ✅ Full support | ❌ None | ❌ None | ⚠️ Possible | ❌ None | ❌ None | ❌ None | ❌ None |
| AI cost | ✅ Bring your key | ❌ $30/user/mo | ❌ $20/user/mo | ⚠️ API costs | ❌ $10/user/mo | ❌ $20/mo | ❌ $20/mo | ⚠️ Per operation |
### Automation & Integration
| Capability | General Bots | Microsoft 365 | Google Workspace | n8n | Notion | Perplexity | Claude | Make/Zapier |
|------------|-------------|---------------|------------------|-----|--------|------------|--------|-------------|
| Workflow automation | ✅ BASIC scripts | ⚠️ Power Automate ($) | ⚠️ AppSheet ($) | ✅ Visual builder | ⚠️ Basic | ❌ None | ❌ None | ✅ Visual builder |
| Scheduled tasks | ✅ Cron + natural | ⚠️ Extra license | ⚠️ Limited | ✅ Available | ❌ None | ❌ None | ❌ None | ✅ Available |
| Webhooks | ✅ Instant creation | ⚠️ Complex setup | ⚠️ Limited | ✅ Available | ⚠️ Limited | ❌ None | ❌ None | ✅ Available |
| Custom APIs | ✅ One line | ❌ Azure required | ❌ GCP required | ✅ Possible | ❌ None | ❌ None | ✅ API available | ❌ None |
| Database access | ✅ Direct SQL | ⚠️ Dataverse ($) | ⚠️ BigQuery ($) | ✅ Multiple DBs | ⚠️ Notion DBs | ❌ None | ❌ None | ⚠️ Limited |
| REST API calls | ✅ GET/POST/etc | ⚠️ Premium connectors | ⚠️ Limited | ✅ HTTP nodes | ❌ None | ❌ None | ❌ None | ✅ HTTP module |
| GraphQL | ✅ Native | ❌ None | ❌ None | ✅ Available | ❌ None | ❌ None | ❌ None | ⚠️ Limited |
| SOAP/Legacy | ✅ Supported | ⚠️ Limited | ❌ None | ✅ Available | ❌ None | ❌ None | ❌ None | ⚠️ Limited |
| Automation pricing | ✅ Unlimited | ❌ Per-flow fees | ❌ Per-run fees | ⚠️ Execution limits | ❌ None | ❌ None | ❌ None | ❌ Per-task fees |
### Multi-Channel Communication
| Capability | General Bots | Microsoft 365 | Google Workspace | n8n | Notion | Perplexity | Claude | Make/Zapier |
|------------|-------------|---------------|------------------|-----|--------|------------|--------|-------------|
| Web chat | ✅ Built-in | ⚠️ Bot Framework | ❌ None | ❌ None | ❌ None | ✅ Web only | ✅ Web only | ❌ None |
| WhatsApp | ✅ Native | ⚠️ Extra setup | ❌ None | ⚠️ Via nodes | ❌ None | ❌ None | ❌ None | ⚠️ Connector |
| Teams | ✅ Native | ✅ Native | ❌ None | ⚠️ Via nodes | ❌ None | ❌ None | ❌ None | ⚠️ Connector |
| Slack | ✅ Native | ⚠️ Connector | ⚠️ Limited | ⚠️ Via nodes | ⚠️ Integration | ❌ None | ⚠️ Integration | ⚠️ Connector |
| Telegram | ✅ Native | ❌ None | ❌ None | ⚠️ Via nodes | ❌ None | ❌ None | ❌ None | ⚠️ Connector |
| SMS | ✅ Native | ⚠️ Extra | ❌ None | ⚠️ Via nodes | ❌ None | ❌ None | ❌ None | ⚠️ Connector |
| Email bot | ✅ Native | ⚠️ Complex | ⚠️ Limited | ⚠️ Via nodes | ❌ None | ❌ None | ❌ None | ⚠️ Connector |
| Voice | ✅ LiveKit | ⚠️ Extra | ⚠️ Extra | ❌ None | ❌ None | ❌ None | ❌ None | ❌ None |
### Developer Experience
| Capability | General Bots | Microsoft 365 | Google Workspace | n8n | Notion | Perplexity | Claude | Make/Zapier |
|------------|-------------|---------------|------------------|-----|--------|------------|--------|-------------|
| Scripting language | ✅ BASIC (simple) | ⚠️ Power Fx | ⚠️ Apps Script | ✅ JavaScript | ❌ None | ❌ None | ❌ None | ❌ Visual only |
| No-code option | ✅ Conversational | ⚠️ Power Apps | ⚠️ AppSheet | ✅ Visual builder | ✅ Pages | ✅ Chat | ✅ Chat | ✅ Visual builder |
| Custom keywords | ✅ Rust extensible | ❌ None | ❌ None | ✅ Custom nodes | ❌ None | ❌ None | ❌ None | ❌ None |
| API-first | ✅ Full REST | ✅ Graph API | ✅ Workspace API | ✅ REST API | ⚠️ Limited | ⚠️ Limited | ✅ Full API | ⚠️ Limited |
| Debugging | ✅ Console + logs | ⚠️ Complex | ⚠️ Complex | ✅ Execution logs | ❌ None | ❌ None | ❌ None | ⚠️ Limited |
| Version control | ✅ File-based | ⚠️ Limited | ⚠️ Limited | ✅ Git support | ⚠️ Page history | ❌ None | ❌ None | ⚠️ Limited |
### Security & Compliance
| Capability | General Bots | Microsoft 365 | Google Workspace | n8n | Notion | Perplexity | Claude | Make/Zapier |
|------------|-------------|---------------|------------------|-----|--------|------------|--------|-------------|
| Data residency control | ✅ Your choice | ⚠️ Limited regions | ⚠️ Limited regions | ✅ Self-host | ❌ US/EU only | ❌ No control | ❌ No control | ❌ No control |
| GDPR compliance | ✅ Self-managed | ✅ Available | ✅ Available | ✅ Self-host | ⚠️ Depends | ⚠️ Limited | ⚠️ Limited | ⚠️ Limited |
| HIPAA capable | ✅ Self-managed | ⚠️ Extra cost | ⚠️ Extra cost | ✅ Self-host | ❌ No | ❌ No | ❌ No | ❌ No |
| Audit logs | ✅ Full control | ✅ Available | ✅ Available | ✅ Available | ⚠️ Limited | ❌ Limited | ❌ Limited | ⚠️ Limited |
| Encryption at rest | ✅ Configurable | ✅ Standard | ✅ Standard | ✅ Configurable | ✅ Standard | ✅ Standard | ✅ Standard | ✅ Standard |
| SSO/OIDC | ✅ Zitadel | ✅ Entra | ✅ Identity | ⚠️ Enterprise | ⚠️ Business | ❌ Basic | ⚠️ Enterprise | ⚠️ Enterprise |
| MFA | ✅ Built-in | ✅ Built-in | ✅ Built-in | ⚠️ Configure | ⚠️ Basic | ⚠️ Basic | ⚠️ Basic | ⚠️ Basic |
## Cost Analysis (100 Users, Annual)
| Platform | Base License | AI Features | Automation | Storage | Total Annual |
|----------|-------------|-------------|------------|---------|--------------|
| **General Bots** | $0 | $0 (bring key) | $0 | Included | **$3,000-12,000*** |
| Microsoft 365 E3 + Copilot | $43,200 | $36,000 | $12,000+ | Included | **$91,200+** |
| Google Workspace Business + Gemini | $21,600 | $24,000 | $6,000+ | Included | **$51,600+** |
| n8n Cloud + separate tools | $0-6,000 | API costs | Included | None | **$20,000+** |
| Notion Team + AI | $12,000 | $12,000 | None | Limited | **$24,000** |
| Multiple point solutions | Varies | Varies | Varies | Varies | **$50,000+** |
*General Bots cost = infrastructure + optional LLM API usage
## Feature Availability by Use Case
### Customer Service Bot
| Requirement | General Bots | Microsoft | Google | n8n | Notion | AI Assistants |
|-------------|-------------|-----------|--------|-----|--------|---------------|
| Knowledge base | ✅ | ⚠️ Extra | ⚠️ Extra | ⚠️ Build | ⚠️ Limited | ⚠️ Limited |
| WhatsApp channel | ✅ | ⚠️ Complex | ❌ | ⚠️ Build | ❌ | ❌ |
| Web widget | ✅ | ⚠️ Complex | ❌ | ❌ | ❌ | ❌ |
| Ticket creation | ✅ | ⚠️ Extra | ⚠️ Extra | ✅ | ⚠️ Manual | ❌ |
| Human handoff | ✅ | ⚠️ Extra | ❌ | ⚠️ Build | ❌ | ❌ |
| Analytics | ✅ | ⚠️ Extra | ⚠️ Extra | ⚠️ Build | ❌ | ❌ |
### Internal Automation
| Requirement | General Bots | Microsoft | Google | n8n | Notion | AI Assistants |
|-------------|-------------|-----------|--------|-----|--------|---------------|
| Scheduled reports | ✅ | ⚠️ Extra | ⚠️ Extra | ✅ | ❌ | ❌ |
| Database sync | ✅ | ⚠️ Extra | ⚠️ Extra | ✅ | ❌ | ❌ |
| API orchestration | ✅ | ⚠️ Premium | ⚠️ Limited | ✅ | ❌ | ❌ |
| Document processing | ✅ | ⚠️ Extra | ⚠️ Extra | ⚠️ Build | ❌ | ⚠️ Limited |
| Email automation | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| Custom logic | ✅ | ⚠️ Limited | ⚠️ Limited | ✅ | ❌ | ❌ |
### Team Collaboration
| Requirement | General Bots | Microsoft | Google | n8n | Notion | AI Assistants |
|-------------|-------------|-----------|--------|-----|--------|---------------|
| Project management | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| Team chat | ✅ | ✅ | ✅ | ❌ | ⚠️ | ❌ |
| File sharing | ✅ | ✅ | ✅ | ❌ | ⚠️ | ❌ |
| Video meetings | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| AI assistant | ✅ | ⚠️ Extra | ⚠️ Extra | ⚠️ Build | ⚠️ Extra | ✅ |
| Self-hosted | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ |
## Migration Complexity
| From Platform | To General Bots | Effort | Data Portability | Tool Support |
|---------------|-----------------|--------|------------------|--------------|
| Microsoft 365 | Full migration | Medium | Good (APIs) | Scripts provided |
| Google Workspace | Full migration | Medium | Good (APIs) | Scripts provided |
| n8n | Automation only | Low | Easy (JSON) | Direct import |
| Notion | Content migration | Low | Good (Export) | Scripts provided |
| Zapier/Make | Workflow rebuild | Medium | Manual | Templates available |
| Custom solution | Varies | Varies | Depends | API compatible |
## Decision Matrix
### Choose General Bots when you need:
- ✅ Complete data sovereignty and self-hosting
- ✅ No per-user licensing costs at scale
- ✅ Native AI without additional subscriptions
- ✅ Full productivity suite in one platform
- ✅ Multi-channel chatbot deployment
- ✅ Powerful automation without limits
- ✅ Open source transparency and extensibility
- ✅ Custom integrations and modifications
### Consider alternatives when:
- You require specific certifications only available from large vendors
- Your organization mandates a particular cloud provider
- You have no infrastructure or IT capacity for self-hosting
- You need only a single narrow feature (e.g., just document editing)
## Summary
General Bots provides the most comprehensive feature set for organizations seeking:
| Advantage | Impact |
|-----------|--------|
| **75-95% cost reduction** | Eliminate per-user fees, AI add-ons, automation limits |
| **Complete data control** | Self-hosted, your infrastructure, your rules |
| **Unified platform** | Email, files, chat, automation, AI in one system |
| **No artificial limits** | Unlimited users, workflows, API calls, storage |
| **Full transparency** | Open source code, audit everything |
| **Future-proof** | No vendor lock-in, standard formats, portable data |
The combination of enterprise productivity features, native AI, powerful automation, and self-hosted deployment makes General Bots unique in the market—delivering capabilities that would otherwise require subscriptions to multiple expensive platforms.
## See Also
- [Migration Overview](./overview.md) - Getting started
- [Migration Resources](./resources.md) - Tools and templates
- [Enterprise Platform Migration](./microsoft-365.md) - Detailed migration guide
- [Quick Start](../chapter-01/quick-start.md) - Deploy in minutes

View file

@ -0,0 +1,476 @@
# Dialogflow Migration Guide
Migrating chatbots and conversational agents from Dialogflow to General Bots.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Dialogflow is Google's conversational AI platform for building chatbots with intent-based NLU. General Bots provides a simpler, more powerful approach using LLM-based understanding and BASIC scripting—without cloud lock-in or complex intent management.
## Why Migrate
| Aspect | Dialogflow | General Bots |
|--------|------------|--------------|
| Hosting | Google Cloud only | Self-hosted |
| Pricing | Per-request fees | No per-request costs |
| NLU Approach | Intent + entity training | LLM-based (zero training) |
| Fulfillment | Cloud Functions/webhooks | Native BASIC scripts |
| Knowledge Base | Limited connector | Full RAG system |
| Channels | Via integrations | Native multi-channel |
| Customization | Limited | Full source access |
| Maintenance | Intent training required | LLM handles variations |
## Cost Comparison
### Dialogflow Pricing
| Edition | Cost |
|---------|------|
| ES (Standard) | Free tier + $0.002/request |
| CX | $0.007/request |
| Mega Agent | $0.06/request |
**10,000 requests/month:** $20-600/month
### General Bots
| Component | Cost |
|-----------|------|
| Software | $0 |
| Infrastructure | $50-200/month |
| LLM API | Usage-based (typically lower) |
## Architecture Comparison
### Dialogflow Architecture
```
User → Dialogflow Agent → Intent Matching → Fulfillment Webhook → Response
Entity Extraction
Context Management
```
### General Bots Architecture
```
User → BASIC Script → LLM Processing → Response
Knowledge Base (RAG)
Direct Actions (DB, API, etc.)
```
## Concept Mapping
### Intents to BASIC
| Dialogflow Concept | General Bots Equivalent |
|--------------------|------------------------|
| Intent | LLM understanding + conditions |
| Training Phrases | Not needed (LLM handles) |
| Entity | `HEAR AS <type>` |
| Context | `SET CONTEXT` / `SET BOT MEMORY` |
| Fulfillment | Direct BASIC code |
| Follow-up Intent | Conversation flow |
| Event | `ON` triggers |
| Knowledge Connector | `USE KB` |
### Entity Types
| Dialogflow Entity | General Bots HEAR AS |
|-------------------|---------------------|
| @sys.date | `HEAR AS DATE` |
| @sys.time | `HEAR AS HOUR` |
| @sys.number | `HEAR AS INTEGER` / `FLOAT` |
| @sys.email | `HEAR AS EMAIL` |
| @sys.phone-number | `HEAR AS MOBILE` |
| @sys.currency-name | `HEAR AS MONEY` |
| @sys.person | `HEAR AS NAME` |
| Custom entity | Menu options or LLM extraction |
## Migration Examples
### Simple FAQ Bot
**Dialogflow:**
- Intent: "hours" with training phrases
- Response: "We're open 9 AM to 5 PM"
**General Bots:**
```basic
USE KB "company-info"
SET CONTEXT "You are a helpful assistant for Acme Corp. Answer questions about our business."
TALK "Hi! How can I help you today?"
HEAR question
answer = LLM question
TALK answer
```
The LLM understands "hours", "when are you open", "opening times", etc. without explicit training.
### Order Status Bot
**Dialogflow:**
```
Intent: order.status
Training phrases: "where is my order", "track order", "order status"
Entity: @order_number
Fulfillment: Webhook to order API
```
**General Bots:**
```basic
' order-status.bas
SET CONTEXT "You help customers check their order status."
TALK "I can help you track your order. What's your order number?"
HEAR order_number
' Direct API call - no webhook needed
SET HEADER "Authorization", "Bearer " + GET CONFIG "orders-api-key"
order = GET "https://api.company.com/orders/" + order_number
IF order.error THEN
TALK "I couldn't find that order. Please check the number and try again."
ELSE
TALK "Your order #" + order_number + " is " + order.status + "."
IF order.status = "shipped" THEN
TALK "Tracking number: " + order.tracking
TALK "Expected delivery: " + FORMAT(order.delivery_date, "MMMM d")
END IF
END IF
TALK "Is there anything else I can help with?"
```
### Appointment Booking
**Dialogflow:**
```
Intent: book.appointment
Entities: @sys.date, @sys.time, @service_type
Slot filling for required parameters
Fulfillment: Calendar API webhook
```
**General Bots:**
```basic
' appointment-booking.bas
SET CONTEXT "You help customers book appointments."
TALK "I'd be happy to help you book an appointment."
TALK "What type of service do you need?"
HEAR service AS "Consultation", "Follow-up", "New Patient", "Urgent Care"
TALK "What date works for you?"
HEAR appointment_date AS DATE
TALK "And what time?"
HEAR appointment_time AS HOUR
' Check availability
available = GET "https://api.calendar.com/check?date=" + appointment_date + "&time=" + appointment_time
IF available.open THEN
' Book directly
BOOK service + " Appointment" AT appointment_date + " " + appointment_time
TALK "Perfect! Your " + service + " appointment is confirmed for " + FORMAT(appointment_date, "MMMM d") + " at " + appointment_time
' Send confirmation
TALK "What email should I send the confirmation to?"
HEAR email AS EMAIL
SEND MAIL TO email SUBJECT "Appointment Confirmation" BODY "Your " + service + " is scheduled for " + appointment_date
ELSE
TALK "That time isn't available. How about " + available.next_slot + "?"
HEAR confirm AS BOOLEAN
' ... continue flow
END IF
```
### Multi-Turn Conversation
**Dialogflow:**
- Follow-up intents
- Context management
- Lifespan settings
**General Bots:**
```basic
' pizza-order.bas
SET CONTEXT "You help customers order pizza."
TALK "Welcome to Pizza Bot! What would you like to order?"
' Size
TALK "What size pizza?"
HEAR size AS "Small", "Medium", "Large", "Extra Large"
' Type
TALK "What type would you like?"
HEAR pizza_type AS "Pepperoni", "Margherita", "Supreme", "Hawaiian", "Custom"
IF pizza_type = "Custom" THEN
TALK "What toppings would you like? (comma separated)"
HEAR toppings
END IF
' Confirm
TALK "So that's a " + size + " " + pizza_type + " pizza. Is that correct?"
HEAR confirmed AS BOOLEAN
IF confirmed THEN
' Store order
order_id = INSERT "orders", #{
size: size,
type: pizza_type,
toppings: toppings,
status: "pending",
created_at: NOW()
}
TALK "Great! Your order #" + order_id + " has been placed."
TALK "Would you like to add anything else?"
HEAR add_more AS BOOLEAN
IF add_more THEN
' Continue ordering
ELSE
TALK "What's your delivery address?"
HEAR address
' ... complete order
END IF
ELSE
TALK "No problem, let's start over."
END IF
```
## Migrating Fulfillment Code
### Dialogflow Webhook
```javascript
// Dialogflow fulfillment
exports.webhook = (req, res) => {
const intent = req.body.queryResult.intent.displayName;
const params = req.body.queryResult.parameters;
if (intent === 'order.status') {
const orderId = params.order_number;
// Call API
fetch(`https://api.example.com/orders/${orderId}`)
.then(response => response.json())
.then(order => {
res.json({
fulfillmentText: `Your order is ${order.status}`
});
});
}
};
```
### General Bots Equivalent
```basic
' The logic is inline - no separate webhook needed
order = GET "https://api.example.com/orders/" + order_id
TALK "Your order is " + order.status
```
## Knowledge Base Migration
### Dialogflow Knowledge Connector
Limited to FAQ format, requires Google Cloud.
### General Bots Knowledge Base
Full document support with RAG:
```
my-bot.gbkb/
├── products/
│ ├── catalog.pdf
│ └── specifications.xlsx
├── support/
│ ├── faq.md
│ └── troubleshooting.md
└── policies/
├── returns.pdf
└── warranty.md
```
```basic
USE KB "products"
USE KB "support"
USE KB "policies"
answer = LLM customer_question
```
## Context Migration
### Dialogflow Contexts
```javascript
// Setting context in fulfillment
outputContexts: [{
name: `projects/.../contexts/order-context`,
lifespanCount: 5,
parameters: { orderId: '12345' }
}]
```
### General Bots Memory
```basic
' Store context
SET BOT MEMORY "current_order_id", order_id
SET BOT MEMORY "customer_name", customer_name
' Retrieve context
order_id = GET BOT MEMORY "current_order_id"
```
## Multi-Channel Deployment
### Dialogflow Integrations
Requires separate configuration for each channel:
- Web: Dialogflow Messenger
- Telephony: CCAI
- Other: Custom integrations
### General Bots
Same code works everywhere:
```basic
' Works on Web, WhatsApp, Teams, Slack, Telegram, SMS
TALK "How can I help?"
HEAR question
USE KB "support"
answer = LLM question
TALK answer
```
## Advanced Features
### Small Talk
**Dialogflow:** Enable small talk prebuilt agent
**General Bots:** LLM handles naturally
```basic
SET CONTEXT "You are a friendly assistant. Engage in casual conversation when appropriate while staying helpful."
' LLM naturally handles:
' - "Hello"
' - "How are you?"
' - "Thanks"
' - "Goodbye"
```
### Sentiment Analysis
**Dialogflow:** Enable sentiment in settings
**General Bots:**
```basic
HEAR customer_message
sentiment = LLM "Analyze the sentiment of this message and respond with: positive, neutral, or negative. Message: " + customer_message
IF sentiment = "negative" THEN
SET CONTEXT "The customer seems frustrated. Be extra helpful and empathetic."
' Or escalate
CREATE TASK "Review negative sentiment conversation"
END IF
answer = LLM customer_message
TALK answer
```
### Rich Responses
**Dialogflow:** Card, suggestion chips, etc.
**General Bots:**
```basic
' Suggestions
ADD SUGGESTION "Check Order"
ADD SUGGESTION "Track Shipment"
ADD SUGGESTION "Contact Support"
TALK "What would you like to do?"
' Images
TALK IMAGE "/products/featured.jpg"
' Files
TALK FILE "/documents/brochure.pdf"
```
## Migration Checklist
### Pre-Migration
- [ ] Export Dialogflow agent (JSON)
- [ ] Document all intents and training phrases
- [ ] List entities and their values
- [ ] Map fulfillment webhooks
- [ ] Identify knowledge connectors
- [ ] Note channel integrations
### Migration
- [ ] Set up General Bots environment
- [ ] Create knowledge base from FAQs/docs
- [ ] Build BASIC scripts for main flows
- [ ] Implement entity validation with HEAR AS
- [ ] Convert fulfillment logic to BASIC
- [ ] Configure channels
### Post-Migration
- [ ] Test all conversation flows
- [ ] Compare response quality
- [ ] Verify API integrations
- [ ] Train team on new system
- [ ] Redirect channel integrations
- [ ] Decommission Dialogflow agent
## What You Gain
**No Intent Training:** LLM understands variations without explicit training phrases.
**Simpler Architecture:** Logic lives in BASIC scripts, not spread across intents and webhooks.
**Self-Hosted:** No Google Cloud dependency or per-request fees.
**Native Integrations:** Direct API calls and database access without webhook complexity.
**Full RAG:** Rich knowledge base support beyond simple FAQ.
**Multi-Channel Native:** Deploy everywhere with one codebase.
## See Also
- [HEAR Keyword](../chapter-06-gbdialog/keyword-hear.md) - Input validation (replaces entities)
- [SET CONTEXT](../chapter-06-gbdialog/keyword-set-context.md) - AI behavior configuration
- [Knowledge Base](../chapter-03/README.md) - RAG setup
- [Platform Comparison](./comparison-matrix.md) - Full feature comparison

View file

@ -0,0 +1,471 @@
# Intercom Migration Guide
Migrating customer messaging and support from Intercom to General Bots.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Intercom is a customer messaging platform with live chat, chatbots, and help desk features. General Bots provides equivalent capabilities with self-hosting, no per-seat pricing, and native AI integration.
## Why Migrate
| Aspect | Intercom | General Bots |
|--------|----------|--------------|
| Pricing | $39-139/seat/month | No per-seat fees |
| Hosting | Cloud only | Self-hosted |
| AI Features | Fin AI ($0.99/resolution) | Native LLM (any provider) |
| Channels | Web, email, mobile | Web, WhatsApp, Teams, Slack, SMS, more |
| Automation | Limited workflows | Full BASIC scripting |
| Knowledge Base | Included | Built-in RAG |
| Data Ownership | Their servers | Your infrastructure |
| Customization | Limited | Full source access |
## Cost Comparison
### Intercom Pricing (per seat/month)
| Plan | Cost | Features |
|------|------|----------|
| Essential | $39 | Basic chat, inbox |
| Advanced | $99 | Automation, reporting |
| Expert | $139 | Full platform |
| Fin AI | $0.99/resolution | AI answers |
**10 support agents:** $990-1,390/month + AI costs
### General Bots
| Component | Cost |
|-----------|------|
| Software | $0 |
| Infrastructure | $50-200/month |
| LLM API (optional) | Usage-based |
**10 agents:** ~$100-300/month total
## Feature Mapping
### Core Features
| Intercom Feature | General Bots Equivalent |
|------------------|------------------------|
| Messenger | Web chat widget |
| Inbox | Conversation management |
| Help Center | Knowledge base (.gbkb) |
| Bots | BASIC dialog scripts |
| Product Tours | Guided conversations |
| Outbound Messages | Automated messaging |
### Bot Capabilities
| Intercom Bots | General Bots Equivalent |
|---------------|------------------------|
| Custom Bots | BASIC scripts |
| Resolution Bot | LLM + USE KB |
| Task Bots | Automated workflows |
| Qualification Bots | HEAR AS + lead scoring |
| Article Suggestions | RAG responses |
## Migration Process
### Step 1: Export Intercom Data
1. Go to Settings → Data Management
2. Export conversations, contacts, and articles
3. Download Help Center articles
4. Export custom attributes and tags
### Step 2: Migrate Knowledge Base
Convert Help Center articles to General Bots knowledge base:
```
my-bot.gbkb/
├── getting-started/
│ ├── quick-start.md
│ └── setup-guide.md
├── features/
│ ├── feature-overview.md
│ └── tutorials.md
├── troubleshooting/
│ ├── common-issues.md
│ └── faq.md
└── billing/
├── plans.md
└── payments.md
```
### Step 3: Create Support Bot
```basic
' support-bot.bas
' Main customer support entry point
USE KB "getting-started"
USE KB "features"
USE KB "troubleshooting"
USE KB "billing"
SET CONTEXT "You are a friendly customer support assistant.
- Be helpful and concise
- If you cannot answer, offer to connect with a human
- Always maintain a professional, positive tone"
TALK "Hi! I'm here to help. What can I assist you with today?"
LOOP
HEAR question
' Check for handoff request
IF CONTAINS(LOWER(question), "human") OR CONTAINS(LOWER(question), "agent") OR CONTAINS(LOWER(question), "person") THEN
CALL REQUEST_HUMAN_HANDOFF()
EXIT LOOP
END IF
answer = LLM question
TALK answer
TALK "Is there anything else I can help you with?"
LOOP
```
### Step 4: Implement Human Handoff
```basic
SUB REQUEST_HUMAN_HANDOFF()
TALK "I'll connect you with a support agent. Let me gather some information first."
TALK "What's your email address?"
HEAR email AS EMAIL
TALK "Please briefly describe your issue:"
HEAR issue_summary
' Create support ticket
ticket_id = INSERT "support_tickets", #{
customer_email: email,
summary: issue_summary,
conversation_id: session.id,
status: "pending",
created_at: NOW()
}
' Notify support team
SEND MAIL TO "support@company.com" SUBJECT "New Support Request #" + ticket_id BODY "Customer: " + email + "\n\nIssue: " + issue_summary
POST GET CONFIG "slack-support", #{
text: "New support request from " + email + ": " + issue_summary
}
TALK "Thanks! A support agent will reach out to you at " + email + " shortly. Your ticket number is #" + ticket_id
END SUB
```
## Recreating Intercom Features
### Messenger Widget
General Bots provides embeddable chat widgets:
```html
<!-- Embed in your website -->
<script src="https://your-bot-server/widget.js"></script>
<script>
GeneralBots.init({
botId: 'your-bot-id',
position: 'bottom-right',
greeting: 'Hi! How can we help?'
});
</script>
```
### Qualification Bot
**Intercom:** Qualification workflow
**General Bots:**
```basic
' lead-qualification.bas
PARAM source AS string
DESCRIPTION "Qualify incoming leads"
TALK "Welcome! I'd love to learn more about you."
TALK "What's your name?"
HEAR name AS NAME
TALK "And your work email?"
HEAR email AS EMAIL
TALK "What company are you with?"
HEAR company
TALK "What's your role?"
HEAR role AS "Executive", "Manager", "Individual Contributor", "Student", "Other"
TALK "What brings you here today?"
HEAR interest AS "Product Demo", "Pricing", "Support", "Partnership", "Just Exploring"
' Score the lead
WITH lead_data
.name = name
.email = email
.company = company
.role = role
.interest = interest
.source = source
END WITH
score = SCORE LEAD lead_data
' Route based on qualification
IF score.status = "hot" OR interest = "Product Demo" THEN
TALK "Great! Let me schedule a demo for you."
TALK "When works best?"
HEAR preferred_time
SEND MAIL TO "sales@company.com" SUBJECT "Hot Lead - Demo Request" BODY lead_data
CREATE TASK "Demo call with " + name DUE DATEADD(NOW(), 1, "day")
TALK "Our team will reach out within 24 hours to confirm your demo!"
ELSEIF interest = "Pricing" THEN
USE KB "pricing"
pricing_info = LLM "Provide a brief pricing overview"
TALK pricing_info
TALK "Would you like to speak with someone about your specific needs?"
ELSE
USE KB "getting-started"
TALK "Here's what you can do to get started..."
answer = LLM "Give a brief getting started guide"
TALK answer
END IF
INSERT "leads", lead_data
```
### Proactive Messages
**Intercom:** Outbound messages
**General Bots:**
```basic
' proactive-engagement.bas
SET SCHEDULE "every hour"
' Find users who might need help
inactive_sessions = FIND "sessions", "last_activity < DATEADD(NOW(), -5, 'minute') AND page_views > 3 AND not contacted"
FOR EACH session IN inactive_sessions
' Send proactive message
SEND TO session.id MESSAGE "Need any help? I'm here if you have questions!"
UPDATE "sessions", "id = '" + session.id + "'", #{contacted: true}
NEXT session
```
### Resolution Bot (AI Answers)
**Intercom Fin:** $0.99 per resolution
**General Bots:**
```basic
' ai-resolution.bas
USE KB "help-center"
USE KB "product-docs"
USE KB "faq"
SET CONTEXT "You are a helpful support assistant. Answer questions accurately based on the knowledge base. If you're not confident in the answer, say so and offer to connect with a human."
TALK "How can I help you today?"
HEAR question
answer = LLM question
' Check confidence (you can implement confidence scoring)
IF CONTAINS(answer, "I'm not sure") OR CONTAINS(answer, "I don't have") THEN
TALK answer
TALK "Would you like me to connect you with a support agent?"
HEAR wants_human AS BOOLEAN
IF wants_human THEN
CALL REQUEST_HUMAN_HANDOFF()
END IF
ELSE
TALK answer
' Track resolution
INSERT "resolutions", #{
question: question,
answer: answer,
resolved: true,
timestamp: NOW()
}
END IF
```
### Customer Segments
**Intercom:** User segments
**General Bots:**
```basic
' segment-customers.bas
SET SCHEDULE "every day at 6am"
customers = FIND "customers", "1=1"
FOR EACH customer IN customers
segment = "standard"
IF customer.total_spent > 10000 THEN
segment = "enterprise"
ELSEIF customer.total_spent > 1000 THEN
segment = "premium"
ELSEIF customer.signup_date > DATEADD(NOW(), -30, "day") THEN
segment = "new"
ELSEIF customer.last_activity < DATEADD(NOW(), -90, "day") THEN
segment = "at-risk"
END IF
UPDATE "customers", "id = '" + customer.id + "'", #{segment: segment}
NEXT customer
```
### Targeted Campaigns
```basic
' win-back-campaign.bas
SET SCHEDULE "every monday at 10am"
' Find at-risk customers
at_risk = FIND "customers", "segment = 'at-risk' AND not win_back_sent"
FOR EACH customer IN at_risk
USE KB "product-updates"
personalized_message = LLM "Write a brief, friendly win-back message for " + customer.name + " who hasn't used our product in 3 months. Mention recent improvements."
SEND MAIL TO customer.email SUBJECT "We miss you, " + customer.name + "!" BODY personalized_message
UPDATE "customers", "id = '" + customer.id + "'", #{win_back_sent: true, win_back_date: NOW()}
NEXT customer
```
## Multi-Channel Support
### Intercom Channels
- Web Messenger
- Mobile SDK
- Email
- SMS (add-on)
### General Bots Channels
All channels use the same BASIC scripts:
```basic
' Same bot works everywhere
USE KB "support"
TALK "How can I help?"
HEAR question
answer = LLM question
TALK answer
' Channel-specific handling if needed
IF channel = "whatsapp" THEN
' WhatsApp-specific features
ELSEIF channel = "email" THEN
' Email formatting
END IF
```
Supported channels:
- Web chat
- WhatsApp Business
- Teams
- Slack
- Telegram
- SMS
- Email
- Voice (LiveKit)
## Reporting and Analytics
### Conversation Metrics
```basic
' daily-metrics.bas
SET SCHEDULE "every day at 11pm"
today = FORMAT(NOW(), "yyyy-MM-dd")
conversations = AGGREGATE "conversations", "COUNT", "id", "DATE(created_at) = '" + today + "'"
resolutions = AGGREGATE "resolutions", "COUNT", "id", "DATE(timestamp) = '" + today + "' AND resolved = true"
avg_response_time = AGGREGATE "conversations", "AVG", "first_response_seconds", "DATE(created_at) = '" + today + "'"
WITH daily_report
.date = today
.total_conversations = conversations
.ai_resolutions = resolutions
.resolution_rate = ROUND(resolutions / conversations * 100, 1)
.avg_response_time = ROUND(avg_response_time / 60, 1)
END WITH
INSERT "daily_metrics", daily_report
SEND MAIL TO "support-lead@company.com" SUBJECT "Daily Support Metrics - " + today BODY daily_report
```
## Migration Checklist
### Pre-Migration
- [ ] Export all Intercom data (conversations, contacts, articles)
- [ ] Document custom bot workflows
- [ ] List all integrations
- [ ] Note custom attributes and tags
- [ ] Set up General Bots environment
### Migration
- [ ] Convert Help Center to .gbkb structure
- [ ] Create support bot scripts
- [ ] Implement human handoff flow
- [ ] Set up notification channels
- [ ] Configure chat widget
- [ ] Import customer data
### Post-Migration
- [ ] Test all conversation flows
- [ ] Verify knowledge base accuracy
- [ ] Train support team
- [ ] Run parallel support briefly
- [ ] Redirect widget embed code
- [ ] Cancel Intercom subscription
## What You Gain
**No Per-Seat Pricing:** Add unlimited agents without cost increase.
**Native AI:** Use any LLM without per-resolution fees.
**Full Customization:** Modify every aspect of the support experience.
**Data Ownership:** All conversations stay on your infrastructure.
**Automation Power:** Go beyond simple workflows with full BASIC scripting.
**Multi-Channel Native:** Same bot works across all channels without add-ons.
## See Also
- [Projects](../chapter-11-features/projects.md) - Organizing support queues
- [HEAR Validation](../chapter-06-gbdialog/keyword-hear.md) - Input validation
- [Lead Scoring](../chapter-06-gbdialog/keywords-lead-scoring.md) - Qualification
- [Platform Comparison](./comparison-matrix.md) - Full feature comparison

View file

@ -0,0 +1,361 @@
# n8n Migration Guide
Migrating workflows and automations from n8n to General Bots.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
n8n is a workflow automation platform with a visual node-based editor. General Bots provides equivalent automation capabilities through BASIC scripting, offering more flexibility and integrated features without execution limits.
## Why Migrate
| Aspect | n8n | General Bots |
|--------|-----|--------------|
| Automation | Visual workflows | BASIC scripts (more powerful) |
| Pricing | Per-execution limits | Unlimited executions |
| AI Integration | Via API nodes | Native LLM keywords |
| Chat/Bot | Not included | Full multi-channel |
| Productivity Suite | Not included | Email, calendar, files, tasks |
| Knowledge Base | Not included | Built-in RAG |
| Self-hosting | Available | Available |
## Workflow Mapping
### Triggers
| n8n Trigger | General Bots Equivalent |
|-------------|------------------------|
| Schedule Trigger | `SET SCHEDULE` |
| Webhook | `WEBHOOK` |
| Email Trigger (IMAP) | `ON "email:received"` |
| Database Trigger | `ON "table:tablename:insert"` |
| Manual Trigger | Direct script execution |
| Cron | `SET SCHEDULE "cron expression"` |
### Common Nodes
| n8n Node | General Bots Equivalent |
|----------|------------------------|
| HTTP Request | `GET`, `POST`, `PUT`, `DELETE` |
| Set | Variable assignment |
| IF | `IF/THEN/ELSE/END IF` |
| Switch | `SWITCH/CASE/END SWITCH` |
| Code (JavaScript) | BASIC script |
| Function | BASIC subroutines |
| Merge | Array operations |
| Split In Batches | `FOR EACH` |
| Wait | `WAIT` |
| Send Email | `SEND MAIL` |
| Slack | `POST` to Slack webhook |
| Discord | `POST` to Discord webhook |
| Google Sheets | `GET`/`POST` to Sheets API |
| Airtable | `GET`/`POST` to Airtable API |
| MySQL/PostgreSQL | `FIND`, `INSERT`, `UPDATE`, `DELETE` |
| MongoDB | `GET`/`POST` to MongoDB API |
## Migration Examples
### Scheduled Data Sync
**n8n workflow:**
```
Schedule Trigger → HTTP Request → IF → Google Sheets
```
**General Bots equivalent:**
```basic
SET SCHEDULE "every hour"
data = GET "https://api.example.com/data"
IF data.status = "active" THEN
FOR EACH item IN data.items
INSERT "synced_data", #{
id: item.id,
name: item.name,
value: item.value,
synced_at: NOW()
}
NEXT item
END IF
TALK "Synced " + LEN(data.items) + " items"
```
### Webhook Processing
**n8n workflow:**
```
Webhook → Set → IF → Send Email + Slack
```
**General Bots equivalent:**
```basic
WEBHOOK "order-received"
order = body
customer_name = order.customer.name
order_total = order.total
IF order_total > 1000 THEN
SEND MAIL TO "sales@company.com" SUBJECT "Large Order" BODY "Order from " + customer_name + ": $" + order_total
POST "https://hooks.slack.com/services/xxx", #{
text: "Large order received: $" + order_total
}
END IF
```
### Multi-Step API Orchestration
**n8n workflow:**
```
Webhook → HTTP Request (API 1) → Code → HTTP Request (API 2) → IF → Multiple outputs
```
**General Bots equivalent:**
```basic
WEBHOOK "process-lead"
lead = body
' Step 1: Enrich lead data
enriched = POST "https://api.clearbit.com/enrich", #{email: lead.email}
' Step 2: Score the lead
WITH lead_data
.email = lead.email
.company = enriched.company.name
.industry = enriched.company.industry
.size = enriched.company.employees
END WITH
score = SCORE LEAD lead_data
' Step 3: Route based on score
IF score.status = "hot" THEN
POST "https://api.salesforce.com/leads", lead_data
SEND MAIL TO "sales@company.com" SUBJECT "Hot Lead" BODY lead_data
ELSEIF score.status = "warm" THEN
POST "https://api.hubspot.com/contacts", lead_data
ELSE
INSERT "cold_leads", lead_data
END IF
```
### Error Handling
**n8n approach:** Error Trigger node
**General Bots equivalent:**
```basic
SET SCHEDULE "every 5 minutes"
TRY
result = GET "https://api.example.com/health"
IF result.status <> "healthy" THEN
THROW "Service unhealthy: " + result.message
END IF
CATCH
SEND MAIL TO "ops@company.com" SUBJECT "Alert: Service Down" BODY ERROR_MESSAGE
POST "https://hooks.slack.com/services/xxx", #{text: "Service alert: " + ERROR_MESSAGE}
END TRY
```
## Exporting n8n Workflows
### Export Process
1. In n8n, select the workflow
2. Click the three-dot menu → Download
3. Save the JSON file
4. Analyze nodes and connections
5. Translate to BASIC script
### JSON Structure Analysis
n8n exports workflows as JSON:
```json
{
"nodes": [
{"type": "n8n-nodes-base.httpRequest", "parameters": {...}},
{"type": "n8n-nodes-base.if", "parameters": {...}}
],
"connections": {...}
}
```
Map each node type to the equivalent BASIC keyword.
## Feature Comparison
### What You Gain
**Native AI integration:**
```basic
USE KB "company-docs"
response = LLM "Analyze this data and provide insights: " + data
```
**Multi-channel chat:**
```basic
TALK "How can I help you?"
HEAR question
answer = LLM question
TALK answer
```
**Built-in productivity:**
```basic
CREATE TASK "Follow up with " + customer_name DUE DATEADD(NOW(), 3, "day")
BOOK "Meeting with " + customer_name AT meeting_time
SEND MAIL TO customer_email SUBJECT "Confirmation" BODY message
```
**Knowledge base:**
```basic
USE KB "product-docs"
USE KB "pricing-info"
answer = LLM customer_question
```
### What Changes
| n8n Approach | General Bots Approach |
|--------------|----------------------|
| Visual drag-and-drop | Text-based BASIC scripts |
| Node connections | Sequential code flow |
| Credentials UI | config.csv settings |
| Execution history UI | Log files + monitoring |
| Community nodes | HTTP keywords + custom code |
## Credentials Migration
### n8n Credentials
n8n stores credentials separately. Export and configure in General Bots:
**config.csv:**
```csv
key,value
slack-webhook-url,https://hooks.slack.com/services/xxx
api-key-clearbit,your-api-key
salesforce-token,your-token
```
**Usage in BASIC:**
```basic
slack_url = GET CONFIG "slack-webhook-url"
POST slack_url, #{text: "Message"}
```
## Migration Checklist
### Pre-Migration
- [ ] Export all n8n workflows as JSON
- [ ] Document active schedules and triggers
- [ ] List all credentials and API keys
- [ ] Identify critical workflows for priority migration
- [ ] Set up General Bots environment
### Migration
- [ ] Translate workflows to BASIC scripts
- [ ] Configure credentials in config.csv
- [ ] Set up webhooks with same endpoints
- [ ] Configure schedules
- [ ] Test each workflow individually
### Post-Migration
- [ ] Run parallel execution for verification
- [ ] Compare outputs between systems
- [ ] Monitor for errors
- [ ] Decommission n8n workflows
- [ ] Document new BASIC scripts
## Common Patterns
### Batch Processing
**n8n:** Split In Batches node
**General Bots:**
```basic
items = GET "https://api.example.com/items"
batch_size = 10
total = LEN(items)
FOR i = 0 TO total - 1 STEP batch_size
batch = SLICE(items, i, i + batch_size)
FOR EACH item IN batch
PROCESS_ITEM(item)
NEXT item
WAIT 1000 ' Rate limiting
NEXT i
```
### Conditional Branching
**n8n:** IF node with multiple branches
**General Bots:**
```basic
SWITCH status
CASE "new"
HANDLE_NEW()
CASE "pending"
HANDLE_PENDING()
CASE "complete"
HANDLE_COMPLETE()
DEFAULT
HANDLE_UNKNOWN()
END SWITCH
```
### Data Transformation
**n8n:** Set node or Code node
**General Bots:**
```basic
' Transform data
WITH transformed
.full_name = data.first_name + " " + data.last_name
.email = LOWER(data.email)
.created = NOW()
.source = "api"
END WITH
```
## Best Practices
**Start with simple workflows.** Migrate straightforward automations first to build familiarity with BASIC syntax.
**Use descriptive variable names.** BASIC scripts are more readable than node graphs when well-written.
**Add comments.** Document your scripts for future maintenance:
```basic
' Daily sales report - sends summary to management
' Runs at 6 PM on weekdays
SET SCHEDULE "0 18 * * 1-5"
```
**Leverage native features.** Don't just replicate n8n workflows—take advantage of General Bots' integrated AI, chat, and productivity features.
**Test incrementally.** Verify each migrated workflow before moving to the next.
## See Also
- [SET SCHEDULE](../chapter-06-gbdialog/keyword-set-schedule.md) - Scheduling reference
- [WEBHOOK](../chapter-06-gbdialog/keyword-webhook.md) - Webhook creation
- [HTTP Keywords](../chapter-06-gbdialog/keywords-http.md) - API integration
- [Platform Comparison](./comparison-matrix.md) - Full feature comparison

View file

@ -0,0 +1,443 @@
# Notion Migration Guide
Migrating content and workflows from Notion to General Bots.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Notion is a collaborative workspace combining notes, databases, and project management. General Bots provides equivalent functionality through its knowledge base, task management, and AI-powered conversation features—with the added benefit of self-hosting and native automation.
## Why Migrate
| Aspect | Notion | General Bots |
|--------|--------|--------------|
| Hosting | Cloud only | Self-hosted |
| Pricing | $10-15/user/month | No per-user fees |
| AI Features | $10/user/month add-on | Native (any LLM) |
| Automation | Limited | Full BASIC scripting |
| Chat/Bot | Not included | Multi-channel |
| API Creation | Not available | Instant webhooks |
| Data Sovereignty | Their servers | Your infrastructure |
## Content Mapping
### Notion to General Bots
| Notion Feature | General Bots Equivalent |
|----------------|------------------------|
| Pages | Knowledge base documents (.gbkb) |
| Databases | Tables (CSV/database) |
| Kanban boards | Task boards |
| Calendar | Calendar API |
| Comments | Conversation history |
| Templates | Bot templates |
| Integrations | BASIC scripts + webhooks |
| Notion AI | LLM keyword |
## Migration Process
### Step 1: Export Notion Content
1. Go to Settings & Members → Settings
2. Scroll to Export content
3. Choose Export format: Markdown & CSV
4. Download the ZIP file
The export includes:
- Pages as Markdown files
- Databases as CSV files
- Attachments in folders
### Step 2: Prepare Knowledge Base
Organize exported content for General Bots:
```
my-bot.gbkb/
├── company-info/
│ ├── about.md
│ ├── policies.md
│ └── procedures.md
├── products/
│ ├── catalog.md
│ └── pricing.md
└── support/
├── faq.md
└── troubleshooting.md
```
### Step 3: Import Documents
Place Markdown files in your `.gbkb` folder. General Bots automatically indexes them for RAG:
```basic
USE KB "company-info"
USE KB "products"
USE KB "support"
TALK "How can I help you?"
HEAR question
answer = LLM question
TALK answer
```
### Step 4: Convert Databases
Transform Notion CSV exports to General Bots tables:
```basic
' Import Notion database export
data = READ "notion-export/Projects.csv"
FOR EACH row IN data
INSERT "projects", #{
name: row["Name"],
status: row["Status"],
due_date: row["Due Date"],
assignee: row["Assignee"],
imported_at: NOW()
}
NEXT row
TALK "Imported " + LEN(data) + " projects"
```
### Step 5: Recreate Task Boards
Convert Notion Kanban boards to General Bots task boards:
```basic
' Create project for Notion board
project_id = CREATE PROJECT "Product Roadmap" WITH DESCRIPTION "Migrated from Notion"
' Import tasks
tasks = READ "notion-export/Roadmap.csv"
FOR EACH task IN tasks
status = SWITCH task["Status"]
CASE "Not Started" : "todo"
CASE "In Progress" : "in_progress"
CASE "Done" : "done"
DEFAULT : "todo"
END SWITCH
CREATE TASK task["Name"] IN PROJECT project_id WITH STATUS status
NEXT task
```
## Notion AI to General Bots
### Document Summarization
**Notion AI:**
- Highlight text → "Summarize"
- Limited to Notion content
**General Bots:**
```basic
USE KB "documents"
summary = LLM "Summarize the key points from our Q3 report"
TALK summary
```
### Content Generation
**Notion AI:**
- Type `/ai` → Generate content
- Basic prompting
**General Bots:**
```basic
SET CONTEXT "You are a technical writer. Write clear, concise documentation."
TALK "What would you like me to write?"
HEAR topic
content = LLM "Write comprehensive documentation about: " + topic
WRITE "/docs/" + SLUGIFY(topic) + ".md", content
TALK "Documentation created!"
```
### Q&A on Documents
**Notion AI:**
- Ask questions about page content
- Single page context
**General Bots:**
```basic
' Load entire knowledge base
USE KB "all-docs"
USE KB "wiki"
USE KB "procedures"
' Answer questions across all content
TALK "Ask me anything about our documentation"
HEAR question
answer = LLM question
TALK answer
```
## Automation Migration
### Notion Automations (Limited)
Notion has basic automations for:
- Status changes
- Due date reminders
- Slack notifications
### General Bots Equivalent
**Status change automation:**
```basic
ON "table:projects:update"
IF params.old_status <> params.new_status THEN
IF params.new_status = "complete" THEN
SEND MAIL TO params.owner_email SUBJECT "Project Completed" BODY "Your project " + params.name + " is now complete!"
END IF
END IF
END ON
```
**Due date reminders:**
```basic
SET SCHEDULE "every day at 9am"
upcoming = FIND "tasks", "due_date = DATEADD(NOW(), 1, 'day') AND status <> 'done'"
FOR EACH task IN upcoming
SEND MAIL TO task.assignee_email SUBJECT "Task Due Tomorrow" BODY "Reminder: " + task.name + " is due tomorrow"
NEXT task
```
**Slack notifications:**
```basic
ON "table:tasks:insert"
POST "https://hooks.slack.com/services/xxx", #{
text: "New task created: " + params.name,
channel: "#tasks"
}
END ON
```
## Database Migration
### Notion Database Properties
| Notion Property | General Bots Equivalent |
|-----------------|------------------------|
| Title | TEXT column |
| Text | TEXT column |
| Number | NUMERIC column |
| Select | TEXT with validation |
| Multi-select | JSONB array |
| Date | DATE/TIMESTAMP column |
| Person | User reference |
| Files | File path references |
| Checkbox | BOOLEAN column |
| URL | TEXT column |
| Email | TEXT column |
| Phone | TEXT column |
| Formula | Computed in BASIC |
| Relation | Foreign key |
| Rollup | AGGREGATE queries |
### Formula Migration
**Notion formula:**
```
prop("Price") * prop("Quantity")
```
**General Bots:**
```basic
' Calculate on insert/update
total = price * quantity
INSERT "orders", #{item: item, price: price, quantity: quantity, total: total}
' Or query with calculation
SELECT "*, price * quantity as total FROM orders"
```
### Relation Migration
**Notion relations** link databases together.
**General Bots:**
```basic
' Create related tables
CREATE TABLE "projects" (id, name, status)
CREATE TABLE "tasks" (id, project_id, name, assignee)
' Query with join
tasks = FIND "tasks", "project_id = '" + project_id + "'"
' Or use JOIN keyword
result = JOIN "projects", "tasks", "projects.id = tasks.project_id"
```
## Template Migration
### Notion Templates
Notion templates are pre-filled pages. Convert to General Bots templates:
**Meeting notes template → BASIC script:**
```basic
' meeting-notes.bas
PARAM meeting_title AS string
PARAM attendees AS string
PARAM date AS date
DESCRIPTION "Create meeting notes document"
template = "# " + meeting_title + "
**Date:** " + FORMAT(date, "MMMM d, yyyy") + "
**Attendees:** " + attendees + "
## Agenda
1.
2.
3.
## Discussion Notes
## Action Items
- [ ]
- [ ]
## Next Meeting
"
WRITE "/meetings/" + FORMAT(date, "yyyy-MM-dd") + "-" + SLUGIFY(meeting_title) + ".md", template
TALK "Meeting notes created: " + meeting_title
```
### Project Template
```basic
' new-project.bas
PARAM project_name AS string
PARAM owner AS string
DESCRIPTION "Create new project with standard structure"
project_id = CREATE PROJECT project_name WITH DESCRIPTION "Created by template"
ADD USER TO PROJECT project_id, owner, "owner"
' Create standard tasks
CREATE TASK "Define requirements" IN PROJECT project_id
CREATE TASK "Create timeline" IN PROJECT project_id
CREATE TASK "Assign resources" IN PROJECT project_id
CREATE TASK "Kickoff meeting" IN PROJECT project_id
CREATE TASK "First milestone review" IN PROJECT project_id
TALK "Project '" + project_name + "' created with 5 starter tasks"
```
## What You Gain
### Self-Hosting
Your data stays on your infrastructure. No concerns about Notion's data practices or service availability.
### Native AI Without Extra Cost
Notion charges $10/user/month for AI features. General Bots includes AI at no additional cost—use any LLM provider.
### Full Automation
Go beyond Notion's limited automations with complete BASIC scripting:
```basic
SET SCHEDULE "every monday at 9am"
' Generate weekly report
projects = FIND "projects", "status = 'active'"
tasks_completed = AGGREGATE "tasks", "COUNT", "id", "completed_at > DATEADD(NOW(), -7, 'day')"
SET CONTEXT "You are a project manager. Create a concise weekly summary."
report = LLM "Summarize: " + LEN(projects) + " active projects, " + tasks_completed + " tasks completed this week"
SEND MAIL TO "team@company.com" SUBJECT "Weekly Project Summary" BODY report
```
### Multi-Channel Access
Access your knowledge base through any channel:
```basic
' Same bot works on web, WhatsApp, Teams, Slack
TALK "How can I help you today?"
HEAR question
USE KB "company-wiki"
answer = LLM question
TALK answer
```
### Custom APIs
Create APIs instantly—something not possible in Notion:
```basic
WEBHOOK "project-status"
project = FIND "projects", "id = '" + params.id + "'"
tasks = FIND "tasks", "project_id = '" + params.id + "'"
WITH response
.project = project
.task_count = LEN(tasks)
.completed = LEN(FILTER(tasks, "status = 'done'"))
END WITH
```
## Migration Checklist
### Pre-Migration
- [ ] Export all Notion content (Markdown & CSV)
- [ ] Inventory databases and their properties
- [ ] Document active integrations
- [ ] Identify critical templates
- [ ] Set up General Bots environment
### Migration
- [ ] Organize Markdown files into .gbkb structure
- [ ] Import database CSVs to tables
- [ ] Convert formulas to BASIC calculations
- [ ] Recreate task boards as projects
- [ ] Migrate templates to BASIC scripts
- [ ] Set up automations
### Post-Migration
- [ ] Verify all content is searchable
- [ ] Test database queries
- [ ] Confirm automations work
- [ ] Train team on new interface
- [ ] Redirect any Notion integrations
## Best Practices
**Organize knowledge base thoughtfully.** Group related documents in collections for better RAG results.
**Simplify database structures.** Notion encourages complex relations; General Bots works best with cleaner schemas.
**Leverage AI for migration.** Use General Bots' LLM to help transform and summarize Notion content:
```basic
content = READ "notion-export/long-document.md"
summary = LLM "Create a concise summary of this document: " + content
WRITE "/summaries/document-summary.md", summary
```
**Keep templates as scripts.** BASIC templates are more powerful than Notion's static templates.
## See Also
- [Knowledge Base](../chapter-03/README.md) - KB configuration
- [Projects](../chapter-11-features/projects.md) - Project management
- [Template Variables](../chapter-06-gbdialog/template-variables.md) - Dynamic content
- [Platform Comparison](./comparison-matrix.md) - Full feature comparison

View file

@ -0,0 +1,406 @@
# Perplexity Migration Guide
Migrating from Perplexity to General Bots for AI-powered search and knowledge retrieval.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Perplexity is an AI-powered search assistant that answers questions with web citations. General Bots provides equivalent and expanded capabilities through its knowledge base, RAG system, and LLM integration—with the advantage of using your own documents, self-hosting, and full customization.
## Why Migrate
| Aspect | Perplexity | General Bots |
|--------|------------|--------------|
| Hosting | Cloud only | Self-hosted |
| Pricing | $20/month Pro | No subscription |
| Knowledge Source | Web search | Your documents + optional web |
| Customization | None | Full BASIC scripting |
| Data Privacy | Queries logged | Complete privacy |
| API Access | Limited | Full REST API |
| Multi-channel | Web only | Web, WhatsApp, Teams, etc. |
| Automation | None | Full workflow automation |
| Integration | None | Any system via API |
## Feature Comparison
### Search and Q&A
| Perplexity Feature | General Bots Equivalent |
|--------------------|------------------------|
| Web search | `USE WEBSITE` + `LLM` |
| Document Q&A (Pro) | `USE KB` + `LLM` |
| Citation generation | RAG with sources |
| Focus modes | `SET CONTEXT` |
| Collections (Pro) | Multiple `.gbkb` folders |
| File upload | Knowledge base indexing |
### What Perplexity Does
1. Searches the web for relevant information
2. Synthesizes answers from multiple sources
3. Provides citations and links
4. Allows follow-up questions
### What General Bots Does
1. Searches your private knowledge base
2. Optionally fetches web content
3. Synthesizes answers with full context
4. Provides source references
5. Allows conversation and follow-ups
6. Automates actions based on answers
7. Deploys to any channel
## Migration Approach
### Step 1: Build Your Knowledge Base
Instead of relying on web search, create a curated knowledge base:
```
my-bot.gbkb/
├── company/
│ ├── policies.pdf
│ ├── procedures.md
│ └── org-chart.pdf
├── products/
│ ├── catalog.pdf
│ ├── specifications.xlsx
│ └── pricing.csv
├── support/
│ ├── faq.md
│ ├── troubleshooting.md
│ └── known-issues.md
└── industry/
├── regulations.pdf
└── best-practices.md
```
### Step 2: Configure RAG
Enable retrieval-augmented generation:
```basic
' Load knowledge collections
USE KB "company"
USE KB "products"
USE KB "support"
' Set assistant behavior
SET CONTEXT "You are a knowledgeable assistant. Answer questions based on the provided documents. Always cite your sources."
' Handle questions
TALK "What would you like to know?"
HEAR question
answer = LLM question
TALK answer
```
### Step 3: Add Web Search (Optional)
For real-time information, add website sources:
```basic
USE KB "internal-docs"
USE WEBSITE "https://docs.example.com"
USE WEBSITE "https://industry-news.com"
answer = LLM "What are the latest updates on " + topic
```
## Recreating Perplexity Features
### Focus Modes
**Perplexity Focus: Academic**
```basic
SET CONTEXT "You are an academic research assistant. Provide scholarly, well-cited responses based on peer-reviewed sources and academic literature. Be precise and thorough."
USE KB "research-papers"
USE KB "academic-journals"
answer = LLM question
```
**Perplexity Focus: Writing**
```basic
SET CONTEXT "You are a professional writing assistant. Help with content creation, editing, and improving text. Focus on clarity, style, and engagement."
answer = LLM "Help me write: " + topic
```
**Perplexity Focus: Code**
```basic
SET CONTEXT "You are an expert programmer. Provide accurate, well-documented code examples. Explain your reasoning and suggest best practices."
USE KB "code-documentation"
USE KB "api-references"
answer = LLM question
```
### Collections
**Perplexity Collections** organize related searches.
**General Bots equivalent:**
```basic
' Create specialized search contexts
WEBHOOK "search-products"
USE KB "products"
SET CONTEXT "You are a product specialist."
answer = LLM body.query
END WEBHOOK
WEBHOOK "search-support"
USE KB "support"
SET CONTEXT "You are a support technician."
answer = LLM body.query
END WEBHOOK
WEBHOOK "search-legal"
USE KB "legal"
SET CONTEXT "You are a legal advisor. Always include disclaimers."
answer = LLM body.query
END WEBHOOK
```
### Pro Search (Deep Research)
**Perplexity Pro Search** performs multi-step research.
**General Bots equivalent:**
```basic
' Deep research workflow
PARAM topic AS string
DESCRIPTION "Perform comprehensive research on a topic"
SET CONTEXT "You are a research analyst. Conduct thorough analysis with multiple perspectives."
USE KB "all-documents"
' Step 1: Initial analysis
initial = LLM "Provide an overview of: " + topic
' Step 2: Deep dive
details = LLM "Now provide detailed analysis with specific examples for: " + topic
' Step 3: Alternative perspectives
alternatives = LLM "What are alternative viewpoints or counterarguments regarding: " + topic
' Step 4: Synthesis
WITH research_prompt
.instruction = "Synthesize a comprehensive report"
.overview = initial
.details = details
.alternatives = alternatives
END WITH
final_report = LLM "Create a comprehensive report combining: " + research_prompt
TALK final_report
```
### Citation and Sources
**Perplexity** shows numbered citations with links.
**General Bots** provides source references through RAG:
```basic
USE KB "documents"
SET CONTEXT "When answering, always cite which document your information comes from. Format citations as [Source: document name]."
answer = LLM question
TALK answer
```
## What You Gain
### Private Knowledge Base
Your proprietary documents stay private:
```basic
USE KB "confidential-data"
USE KB "internal-reports"
' All queries against your own data
' Nothing sent to external search engines
answer = LLM sensitive_question
```
### Custom AI Behavior
Fine-tune responses for your specific needs:
```basic
SET CONTEXT "You are the customer service assistant for Acme Corp.
- Always be friendly and professional
- If you don't know something, offer to connect with a human
- Never discuss competitor products
- Emphasize our satisfaction guarantee"
answer = LLM customer_question
```
### Multi-Channel Deployment
Access your AI assistant anywhere:
```basic
' Same knowledge base, any channel
' Web chat, WhatsApp, Teams, Slack, SMS, Email
TALK "How can I help you?"
HEAR question
USE KB "company-knowledge"
answer = LLM question
TALK answer
```
### Automation Beyond Q&A
Take action based on queries:
```basic
USE KB "products"
TALK "What are you looking for?"
HEAR query
answer = LLM query
' If user wants to order, take action
IF CONTAINS(LOWER(query), "order") OR CONTAINS(LOWER(query), "buy") THEN
TALK "Would you like me to start an order?"
HEAR confirm AS BOOLEAN
IF confirm THEN
CREATE TASK "Follow up on order inquiry" DUE DATEADD(NOW(), 1, "day")
SEND MAIL TO "sales@company.com" SUBJECT "Order Inquiry" BODY "Customer asked: " + query
END IF
END IF
TALK answer
```
### API for Integration
Create search APIs for your applications:
```basic
WEBHOOK "search"
USE KB params.collection
SET CONTEXT params.context
answer = LLM params.query
WITH response
.answer = answer
.query = params.query
.timestamp = NOW()
END WITH
```
Call from any application:
```
POST /api/search
{
"collection": "products",
"context": "You are a product expert",
"query": "What's the best option for enterprise?"
}
```
## Migration Checklist
### Pre-Migration
- [ ] Identify information sources you frequently search
- [ ] Gather documents to build knowledge base
- [ ] Determine required focus modes/contexts
- [ ] Plan deployment channels
- [ ] Set up General Bots environment
### Migration
- [ ] Organize documents into .gbkb collections
- [ ] Create context configurations
- [ ] Build specialized search endpoints
- [ ] Test with common queries
- [ ] Configure multi-channel access
### Post-Migration
- [ ] Compare answer quality
- [ ] Train team on new interface
- [ ] Monitor and refine contexts
- [ ] Add automation workflows
- [ ] Expand knowledge base as needed
## Example: Complete Search Assistant
```basic
' search-assistant.bas
' A Perplexity-like search experience with General Bots
' Load knowledge bases
USE KB "company-docs"
USE KB "product-info"
USE KB "industry-knowledge"
' Configure AI behavior
SET CONTEXT "You are an intelligent search assistant.
Provide accurate, well-sourced answers.
When citing information, mention the source document.
If you're uncertain, acknowledge the limitations.
Be concise but comprehensive."
' Main conversation loop
TALK "Hello! I can search our knowledge base and help answer your questions. What would you like to know?"
LOOP
HEAR query
IF LOWER(query) = "exit" OR LOWER(query) = "quit" THEN
TALK "Goodbye!"
EXIT LOOP
END IF
' Generate response with sources
answer = LLM query
TALK answer
' Offer follow-up
TALK "Would you like to know more about any aspect of this?"
LOOP
```
## Best Practices
**Curate your knowledge base.** Quality documents produce better answers than random web search.
**Use specific contexts.** Tailor the AI's behavior for different use cases rather than using generic settings.
**Iterate on prompts.** Refine your `SET CONTEXT` instructions based on the quality of responses.
**Combine sources strategically.** Mix internal documents with curated external sources for comprehensive coverage.
**Add automation.** Go beyond Q&A—let your assistant take actions, create tasks, and integrate with workflows.
## See Also
- [Knowledge Base](../chapter-03/README.md) - Building effective KBs
- [USE KB](../chapter-06-gbdialog/keyword-use-kb.md) - Knowledge base keyword
- [SET CONTEXT](../chapter-06-gbdialog/keyword-set-context.md) - AI configuration
- [Platform Comparison](./comparison-matrix.md) - Full feature comparison

View file

@ -0,0 +1,290 @@
# Migration Resources
General Bots provides comprehensive tools and resources for organizations transitioning from cloud-based productivity platforms to self-hosted infrastructure.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Migration Toolkit
### Data Import Utilities
General Bots includes import tools for common enterprise data formats:
**Email Migration**
- IMAP sync for mailbox migration
- PST file import support
- Calendar (ICS) import
- Contact (VCF/CardDAV) import
**File Migration**
- Bulk file upload via S3 API
- Folder structure preservation
- Metadata retention
- Version history import where available
**User Migration**
- SCIM provisioning support
- LDAP directory sync
- CSV user import
- Bulk credential generation
### BASIC Migration Scripts
Template scripts for common migration tasks:
```basic
' migrate-files.bas
PARAM source_api AS string
PARAM auth_token AS string
DESCRIPTION "Migrate files from external storage"
SET HEADER "Authorization", "Bearer " + auth_token
files = GET source_api + "/files"
FOR EACH file IN files
content = DOWNLOAD file.download_url
WRITE "/" + file.path, content
TALK "Migrated: " + file.name
NEXT file
TALK "Migration complete: " + LEN(files) + " files"
```
```basic
' migrate-users.bas
PARAM csv_path AS string
DESCRIPTION "Import users from CSV export"
users = READ csv_path
FOR EACH row IN users
CREATE USER row.email WITH NAME row.name
NEXT row
```
## API Compatibility
### REST API Mapping
General Bots REST APIs follow familiar patterns:
| Common Operation | General Bots Endpoint |
|-----------------|----------------------|
| List files | `GET /api/files/list` |
| Upload file | `POST /api/files/write` |
| Download file | `GET /api/files/{path}` |
| List users | `GET /api/users` |
| Create user | `POST /api/users` |
| Send email | `POST /api/email/send` |
| List calendar events | `GET /api/calendar/events` |
| Create task | `POST /api/tasks` |
### Identity Federation
Support SSO during migration with identity federation:
- OIDC provider integration
- SAML support via Zitadel
- Hybrid authentication during transition
- Gradual user migration
Configure in `config.csv`:
```csv
key,value
oidc-provider-url,https://identity.example.com
oidc-client-id,general-bots-client
oidc-client-secret,your-secret
```
## Industry Templates
Pre-built configurations for common industries:
### Healthcare
- HIPAA-compliant configuration
- Patient communication templates
- Appointment scheduling workflows
- Secure document handling
### Financial Services
- SOC 2 aligned settings
- Secure data handling
- Audit logging enabled
- Compliance reporting
### Education
- Student enrollment flows
- Course management
- Parent communication channels
- Assignment tracking
### Professional Services
- Client onboarding templates
- Project management workflows
- Time tracking integration
- Invoice generation
## Deployment Guides
### Infrastructure Sizing
| Organization Size | CPU | RAM | Storage | Users |
|------------------|-----|-----|---------|-------|
| Small | 2 cores | 4 GB | 100 GB | 1-50 |
| Medium | 4 cores | 8 GB | 500 GB | 50-500 |
| Large | 8 cores | 16 GB | 2 TB | 500-5000 |
| Enterprise | 16+ cores | 32+ GB | 10+ TB | 5000+ |
### High Availability
For production deployments:
- PostgreSQL replication
- Load-balanced botserver instances
- Distributed SeaweedFS storage
- Redis/Valkey clustering
### Backup Strategy
Automated backup configuration:
```basic
SET SCHEDULE "every day at 2am"
' Database backup
result = POST "https://backup.internal/postgres", #{database: "botserver"}
' File storage backup
result = POST "https://backup.internal/seaweedfs", #{bucket: "all"}
' Notify on completion
SEND MAIL TO "ops@company.com" SUBJECT "Backup Complete" BODY result
```
## Training Resources
### Administrator Training
- Initial setup and configuration
- User management
- Security settings
- Monitoring and maintenance
### Developer Training
- BASIC scripting fundamentals
- API integration patterns
- Custom keyword development
- Package creation
### End User Training
- Chat interface usage
- File management
- Calendar and tasks
- Mobile access
## ROI Calculator
Estimate savings with self-hosted deployment:
| Factor | Cloud (100 users) | General Bots |
|--------|------------------|--------------|
| Annual licensing | $15,000-60,000 | $0 |
| AI assistant add-on | $36,000 | $0 |
| Infrastructure | Included | $2,400-6,000 |
| LLM API costs | Included | $600-6,000 |
| **Total Annual** | **$51,000-96,000** | **$3,000-12,000** |
Typical savings: 75-95% reduction in annual costs.
## Support Resources
### Documentation
- Complete keyword reference
- API documentation
- Configuration guides
- Troubleshooting guides
### Community
- GitHub discussions
- Issue tracking
- Feature requests
- Community contributions
### Professional Services
For enterprise deployments:
- Migration planning
- Custom development
- Training programs
- Support contracts
Contact: partners@pragmatismo.com.br
## Migration Checklist
### Pre-Migration
- [ ] Inventory current services and usage
- [ ] Identify data to migrate
- [ ] Plan user communication
- [ ] Set up test environment
- [ ] Configure identity federation
### Migration
- [ ] Deploy General Bots infrastructure
- [ ] Import users and groups
- [ ] Migrate files and documents
- [ ] Transfer email (if applicable)
- [ ] Set up integrations
### Post-Migration
- [ ] Verify data integrity
- [ ] Test all workflows
- [ ] Train users
- [ ] Update DNS/routing
- [ ] Decommission old services
- [ ] Monitor and optimize
## Case Study Template
Document your migration for internal reference:
**Organization Profile**
- Size and industry
- Previous platform
- Key requirements
**Migration Scope**
- Services migrated
- Data volume
- Timeline
**Results**
- Cost savings achieved
- Performance improvements
- User feedback
**Lessons Learned**
- Challenges encountered
- Solutions implemented
- Recommendations
## See Also
- [Migration Overview](./overview.md) - Getting started with migration
- [Validation and Testing](./validation.md) - Verify migration success
- [Enterprise Platform Migration](../chapter-11-features/m365-comparison.md) - Feature mapping
- [Quick Start](../chapter-01/quick-start.md) - Initial deployment

View file

@ -0,0 +1,489 @@
# Zapier and Make Migration Guide
Migrating workflows from Zapier or Make (formerly Integromat) to General Bots.
<img src="../assets/gb-decorative-header.svg" alt="General Bots" style="max-height: 100px; width: 100%; object-fit: contain;">
## Overview
Zapier and Make are visual automation platforms connecting apps through triggers and actions. General Bots provides equivalent automation through BASIC scripting, offering more power and flexibility without per-task pricing.
## Why Migrate
| Aspect | Zapier/Make | General Bots |
|--------|-------------|--------------|
| Pricing | Per-task/operation | Unlimited executions |
| Automation | Visual workflows | BASIC scripts |
| AI Integration | Via paid apps | Native LLM keywords |
| Chat/Bot | Not included | Multi-channel |
| Productivity Suite | Not included | Email, calendar, files |
| Custom Logic | Limited | Full programming |
| Self-hosting | Not available | Full control |
| API Creation | Not available | Instant webhooks |
## Cost Comparison
### Zapier Pricing
| Plan | Tasks/Month | Cost |
|------|-------------|------|
| Free | 100 | $0 |
| Starter | 750 | $19.99 |
| Professional | 2,000 | $49 |
| Team | 50,000 | $69/user |
| Company | 100,000+ | Custom |
### Make Pricing
| Plan | Operations/Month | Cost |
|------|------------------|------|
| Free | 1,000 | $0 |
| Core | 10,000 | $9 |
| Pro | 10,000 | $16 |
| Teams | 10,000 | $29/user |
| Enterprise | Custom | Custom |
### General Bots
| Plan | Operations | Cost |
|------|------------|------|
| Self-hosted | Unlimited | Infrastructure only |
## Trigger Mapping
| Zapier/Make Trigger | General Bots Equivalent |
|---------------------|------------------------|
| Schedule | `SET SCHEDULE` |
| Webhook | `WEBHOOK` |
| New Email | `ON "email:received"` |
| New Row (Sheets) | `ON "table:name:insert"` |
| Form Submission | `ON FORM SUBMIT` |
| New File | `ON "file:created"` |
| RSS Feed | Scheduled `GET` |
| App-specific | API polling or webhooks |
## Action Mapping
| Zapier/Make Action | General Bots Equivalent |
|--------------------|------------------------|
| Send Email | `SEND MAIL` |
| HTTP Request | `GET`, `POST`, `PUT`, `DELETE` |
| Create Row | `INSERT` |
| Update Row | `UPDATE` |
| Filter | `IF/THEN/ELSE` |
| Formatter | String/date functions |
| Delay | `WAIT` |
| Paths | `IF` branches |
| Loop | `FOR EACH` |
| Code (JS/Python) | BASIC script |
| Slack Message | `POST` to Slack webhook |
| Create Task | `CREATE TASK` |
| Send SMS | SMS integration |
## Migration Examples
### Simple Zap: Form to Email
**Zapier:**
```
Typeform → Gmail (Send Email)
```
**General Bots:**
```basic
ON FORM SUBMIT "contact-form"
name = fields.name
email = fields.email
message = fields.message
SEND MAIL TO "support@company.com" SUBJECT "New Contact: " + name BODY "From: " + email + "\n\nMessage:\n" + message
END ON
```
### Multi-Step Zap: Lead Processing
**Zapier:**
```
Webhook → Filter → Clearbit Enrich → Salesforce (Create Lead) → Slack (Send Message)
```
**General Bots:**
```basic
WEBHOOK "new-lead"
lead = body
' Filter
IF lead.email = "" OR NOT CONTAINS(lead.email, "@") THEN
RETURN #{status: "invalid", reason: "Invalid email"}
END IF
' Enrich
SET HEADER "Authorization", "Bearer " + GET CONFIG "clearbit-key"
enriched = GET "https://person.clearbit.com/v2/people/find?email=" + lead.email
' Create in CRM
WITH salesforce_lead
.Email = lead.email
.FirstName = enriched.name.givenName
.LastName = enriched.name.familyName
.Company = enriched.employment.name
.Title = enriched.employment.title
END WITH
SET HEADER "Authorization", "Bearer " + GET CONFIG "salesforce-token"
result = POST "https://yourinstance.salesforce.com/services/data/v52.0/sobjects/Lead", salesforce_lead
' Notify Slack
POST GET CONFIG "slack-webhook", #{
text: "New lead: " + lead.email + " from " + enriched.employment.name
}
RETURN #{status: "success", salesforce_id: result.id}
```
### Scheduled Sync
**Make Scenario:**
```
Schedule → HTTP Request → Iterator → Google Sheets (Add Row)
```
**General Bots:**
```basic
SET SCHEDULE "every hour"
data = GET "https://api.example.com/new-orders"
FOR EACH order IN data.orders
INSERT "orders", #{
order_id: order.id,
customer: order.customer_name,
total: order.total,
status: order.status,
synced_at: NOW()
}
NEXT order
TALK "Synced " + LEN(data.orders) + " orders"
```
### Error Handling
**Zapier:** Error handling path or retry
**General Bots:**
```basic
SET SCHEDULE "every 5 minutes"
TRY
result = POST "https://api.example.com/sync", data
IF result.status <> 200 THEN
THROW "API returned " + result.status
END IF
CATCH
' Log error
INSERT "error_log", #{
error: ERROR_MESSAGE,
timestamp: NOW(),
data: data
}
' Alert
SEND MAIL TO "ops@company.com" SUBJECT "Sync Error" BODY ERROR_MESSAGE
POST GET CONFIG "slack-alerts", #{text: "Sync failed: " + ERROR_MESSAGE}
END TRY
```
### Conditional Paths
**Zapier Paths:**
```
Trigger → Path A (if condition) → Actions
→ Path B (else) → Actions
```
**General Bots:**
```basic
WEBHOOK "order-status"
order = body
IF order.total > 1000 THEN
' High-value order path
SEND MAIL TO "vip-team@company.com" SUBJECT "High-Value Order" BODY order
POST GET CONFIG "slack-vip", #{text: "VIP Order: $" + order.total}
priority = "high"
ELSEIF order.is_rush = true THEN
' Rush order path
SEND MAIL TO "fulfillment@company.com" SUBJECT "RUSH Order" BODY order
priority = "rush"
ELSE
' Standard order path
priority = "normal"
END IF
INSERT "orders", #{
id: order.id,
total: order.total,
priority: priority,
created: NOW()
}
```
### Data Transformation
**Make/Zapier Formatter:**
- Split text
- Format dates
- Math operations
- Lookup tables
**General Bots:**
```basic
' String operations
full_name = first_name + " " + last_name
email_domain = SPLIT(email, "@")[1]
slug = LOWER(REPLACE(title, " ", "-"))
' Date formatting
formatted_date = FORMAT(created_at, "MMMM d, yyyy")
due_date = DATEADD(NOW(), 7, "day")
days_ago = DATEDIFF("day", created_at, NOW())
' Math
subtotal = price * quantity
tax = subtotal * 0.08
total = subtotal + tax
discount = IIF(total > 100, total * 0.1, 0)
' Lookup
status_label = SWITCH status
CASE "new" : "New Order"
CASE "processing" : "In Progress"
CASE "shipped" : "On the Way"
CASE "delivered" : "Completed"
DEFAULT : "Unknown"
END SWITCH
```
## App-Specific Migrations
### Gmail/Email
**Zapier:** Gmail trigger/action
**General Bots:**
```basic
' Send email
SEND MAIL TO recipient SUBJECT subject BODY body
' With attachments
SEND MAIL TO recipient SUBJECT subject BODY body ATTACH "/files/report.pdf"
' Process incoming (via Stalwart webhook)
ON "email:received"
IF CONTAINS(params.subject, "Order") THEN
PROCESS_ORDER(params)
END IF
END ON
```
### Slack
**Zapier:** Slack app
**General Bots:**
```basic
' Simple message
POST "https://hooks.slack.com/services/xxx", #{text: "Hello!"}
' Rich message
WITH slack_message
.channel = "#general"
.blocks = [
#{type: "header", text: #{type: "plain_text", text: "New Order"}},
#{type: "section", text: #{type: "mrkdwn", text: "*Customer:* " + customer_name}},
#{type: "section", text: #{type: "mrkdwn", text: "*Total:* $" + total}}
]
END WITH
POST GET CONFIG "slack-webhook", slack_message
```
### Google Sheets
**Zapier:** Google Sheets app
**General Bots:**
```basic
' Read from sheet
SET HEADER "Authorization", "Bearer " + GET CONFIG "google-token"
data = GET "https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}/values/Sheet1!A1:D100"
' Append row
POST "https://sheets.googleapis.com/v4/spreadsheets/{spreadsheetId}/values/Sheet1!A1:append?valueInputOption=USER_ENTERED", #{
values: [[name, email, phone, NOW()]]
}
' Or use General Bots tables directly
INSERT "contacts", #{name: name, email: email, phone: phone}
```
### Airtable
**Zapier:** Airtable app
**General Bots:**
```basic
SET HEADER "Authorization", "Bearer " + GET CONFIG "airtable-key"
' Read records
records = GET "https://api.airtable.com/v0/{baseId}/{tableName}"
' Create record
POST "https://api.airtable.com/v0/{baseId}/{tableName}", #{
fields: #{
Name: name,
Email: email,
Status: "New"
}
}
```
### HubSpot
**Zapier:** HubSpot app
**General Bots:**
```basic
SET HEADER "Authorization", "Bearer " + GET CONFIG "hubspot-token"
' Create contact
POST "https://api.hubapi.com/crm/v3/objects/contacts", #{
properties: #{
email: email,
firstname: first_name,
lastname: last_name,
company: company
}
}
' Create deal
POST "https://api.hubapi.com/crm/v3/objects/deals", #{
properties: #{
dealname: deal_name,
amount: amount,
pipeline: "default",
dealstage: "appointmentscheduled"
}
}
```
## What You Gain
### No Operation Limits
```basic
' Process thousands of records without worrying about limits
SET SCHEDULE "every hour"
records = GET "https://api.example.com/all-records"
FOR EACH record IN records
PROCESS_RECORD(record) ' No per-operation cost
NEXT record
```
### Native AI Integration
```basic
' AI-powered automation
USE KB "company-docs"
incoming_email = params.body
category = LLM "Categorize this email as: support, sales, billing, or other: " + incoming_email
IF category = "support" THEN
response = LLM "Draft a helpful support response to: " + incoming_email
SEND MAIL TO params.from SUBJECT "Re: " + params.subject BODY response
END IF
```
### Multi-Channel Chat
```basic
' Same automation works across channels
TALK "How can I help you?"
HEAR request
USE KB "help-docs"
answer = LLM request
TALK answer
' Available on Web, WhatsApp, Teams, Slack, Telegram, SMS
```
### Built-in Productivity
```basic
' No need for separate calendar, task, email apps
CREATE TASK "Follow up with " + customer_name DUE DATEADD(NOW(), 3, "day")
BOOK "Call with " + customer_name AT meeting_time
SEND MAIL TO customer_email SUBJECT "Confirmation" BODY message
```
## Migration Checklist
### Pre-Migration
- [ ] Export Zap/Scenario descriptions
- [ ] Document all triggers and schedules
- [ ] List all connected apps and credentials
- [ ] Identify critical automations
- [ ] Set up General Bots environment
### Migration
- [ ] Create BASIC scripts for each workflow
- [ ] Configure credentials in config.csv
- [ ] Set up webhooks with same URLs
- [ ] Configure schedules
- [ ] Test each automation
### Post-Migration
- [ ] Run parallel for verification
- [ ] Compare execution results
- [ ] Monitor for errors
- [ ] Disable Zapier/Make automations
- [ ] Cancel subscriptions
## Best Practices
**Start with simple Zaps.** Migrate basic workflows first to learn BASIC syntax.
**Combine multiple Zaps.** Often several Zaps can become one General Bots script.
**Use native features.** Don't replicate Zapier patterns—leverage AI, chat, and productivity features.
**Add error handling.** BASIC provides better error handling than visual builders.
**Document your scripts.** Add comments explaining what each script does.
```basic
' Daily sales report
' Runs at 6 PM on weekdays
' Aggregates daily orders and sends summary to management
SET SCHEDULE "0 18 * * 1-5"
' ... implementation
```
## See Also
- [SET SCHEDULE](../chapter-06-gbdialog/keyword-set-schedule.md) - Scheduling
- [WEBHOOK](../chapter-06-gbdialog/keyword-webhook.md) - Webhooks
- [HTTP Keywords](../chapter-06-gbdialog/keywords-http.md) - API calls
- [Platform Comparison](./comparison-matrix.md) - Full comparison