Update: README and template files

This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2026-02-04 13:54:26 -03:00
parent 6df9f7dce5
commit 85696bb907
10 changed files with 448 additions and 150 deletions

273
README.md
View file

@ -1,10 +1,17 @@
# General Bots
# General Bots Documentation (BotBook)
**Version:** 6.2.0
**Purpose:** Comprehensive documentation for General Bots (mdBook format)
![General Bots Logo](https://github.com/GeneralBots/botserver/blob/main/logo.png?raw=true)
**Enterprise-Grade LLM Orchestrator & AI Automation Platform**
---
A strongly-typed, self-hosted conversational platform focused on convention over configuration and code-less approaches.
## Overview
BotBook is the official documentation repository for General Bots, built using [mdBook](https://rust-lang.github.io/mdBook/). It provides comprehensive guides, API references, tutorials, and architectural documentation for the entire General Bots platform - an enterprise-grade LLM orchestrator and AI automation platform.
For the latest live documentation, visit **[docs.pragmatismo.com.br](https://docs.pragmatismo.com.br)**.
---
@ -14,7 +21,7 @@ A strongly-typed, self-hosted conversational platform focused on convention over
---
## 📦 Repositories
## 📦 General Bots Repositories
| Repository | Description | Status |
|------------|-------------|--------|
@ -33,6 +40,7 @@ A strongly-typed, self-hosted conversational platform focused on convention over
- **Rust** (latest stable) - [Install from rustup.rs](https://rustup.rs/)
- **Git** - [Download from git-scm.com](https://git-scm.com/downloads)
- **mdBook** - `cargo install mdbook`
### Run the Server
@ -63,6 +71,20 @@ cd botapp
cargo tauri dev
```
### Build Documentation
```bash
# Clone botbook
git clone https://github.com/GeneralBots/botbook
cd botbook
# Build documentation
mdbook build
# Serve locally with hot reload
mdbook serve --open
```
---
## ✨ Key Features
@ -100,6 +122,182 @@ CLEAR TOOLS ' Remove all tools from session
---
## 📁 Documentation Structure
```
botbook/
├── book.toml # mdBook configuration
├── src/
│ ├── SUMMARY.md # Table of contents
│ ├── README.md # Introduction
│ ├── 01-introduction/ # Quick Start
│ ├── 02-templates/ # Package System
│ ├── 03-knowledge-base/ # Knowledge Base
│ ├── 04-gbui/ # UI Interface
│ ├── 06-gbdialog/ # BASIC Dialogs
│ ├── 08-config/ # Configuration
│ ├── 10-rest/ # REST API
│ ├── 12-auth/ # Authentication
│ └── assets/ # Images, diagrams
├── i18n/ # Translations
└── book/ # Generated output
```
---
## 📚 Documentation Writing Guidelines
### ✅ Keyword Naming Rules - MANDATORY
**Keywords NEVER use underscores. Always use spaces.**
| Write This | NOT This |
|------------|----------|
| `SEND MAIL` | `SEND_MAIL` |
| `GENERATE PDF` | `GENERATE_PDF` |
| `MERGE PDF` | `MERGE_PDF` |
| `DELETE` | `DELETE_HTTP` |
| `SET HEADER` | `SET_HEADER` |
| `FOR EACH` | `FOR_EACH` |
#### Correct Syntax Examples
```basic
SEND MAIL to, subject, body, attachments
GENERATE PDF template, data, output
MERGE PDF files, output
DELETE "url"
ON ERROR RESUME NEXT
SET BOT MEMORY key, value
KB STATISTICS
```
#### ❌ NEVER Use Underscores
```basic
SEND_MAIL ' WRONG!
GENERATE_PDF ' WRONG!
DELETE_HTTP ' WRONG!
```
---
### 🎨 Official Icons - MANDATORY
**NEVER generate icons with LLM. Use official SVG icons from `botui/ui/suite/assets/icons/`**
#### Usage in Documentation
```markdown
<!-- Reference icons in docs -->
![Chat](../assets/icons/gb-chat.svg)
<!-- With HTML for sizing -->
<img src="../assets/icons/gb-analytics.svg" alt="Analytics" width="24">
```
#### Required Icons
```
ui/suite/assets/icons/
├── gb-logo.svg # Main GB logo
├── gb-bot.svg # Bot/assistant
├── gb-analytics.svg # Analytics
├── gb-calendar.svg # Calendar
├── gb-chat.svg # Chat
├── gb-drive.svg # File storage
├── gb-mail.svg # Email
├── gb-meet.svg # Video meetings
├── gb-tasks.svg # Task management
└── ...
```
All icons use `stroke="currentColor"` for CSS theming.
---
### 🚫 NO ASCII Diagramrams - MANDATORY
**NEVER use ASCII art diagrams. ALL diagrams must be SVG.**
#### ❌ Prohibited ASCII Patterns
```
┌─────────┐ ╔═══════╗ +-------+
│ Box │ ║ Box ║ | Box |
└─────────┘ ╚═══════╝ +-------+
```
#### ✅ What to Use Instead
| Instead of... | Use... |
|---------------|--------|
| ASCII box diagrams | SVG diagrams in `assets/` |
| ASCII flow charts | SVG with arrows and boxes |
| ASCII directory trees | Markdown tables |
---
### 🎨 SVG Diagram Guidelines
All SVGs must support light/dark modes:
```xml
<style>
.title-text { fill: #1E1B4B; }
.main-text { fill: #334155; }
@media (prefers-color-scheme: dark) {
.title-text { fill: #F1F5F9; }
.main-text { fill: #E2E8F0; }
}
</style>
```
---
### 💬 Conversation Examples
Use WhatsApp-style HTML format for bot interactions:
```html
<div class="wa-chat">
<div class="wa-message bot">
<div class="wa-bubble">
<p>Hello! How can I help?</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>I want to enroll</p>
<div class="wa-time">10:31</div>
</div>
</div>
</div>
```
---
### 📋 Source Code References
| Topic | Source Location |
|-------|-----------------|
| BASIC Keywords | `botserver/src/basic/keywords/` |
| Database Models | `botserver/src/shared/models.rs` |
| API Routes | `botserver/src/core/urls.rs` |
| Configuration | `botserver/src/core/config/` |
| Templates | `botserver/templates/` |
---
### 📖 Documentation Accuracy Rules
```
- All documentation MUST match actual source code
- Extract real keywords from botserver/src/basic/keywords/
- Use actual examples from botserver/templates/
- Version numbers must be 6.2.0
- No placeholder content - only verified features
```
---
## 🏛️ Architecture Details
### botserver (Core)
@ -133,31 +331,14 @@ Common Rust code shared across projects:
---
## 🔧 Development Setup
## 🛡️ Security
```bash
# Clone all repositories
git clone https://github.com/GeneralBots/botserver botserver
git clone https://github.com/GeneralBots/botui
git clone https://github.com/GeneralBots/botapp
git clone https://github.com/GeneralBots/botlib
git clone https://github.com/GeneralBots/botbook botbook
- **AGPL-3.0 License** - True open source with contribution requirements
- **Self-hosted** - Your data stays on your infrastructure
- **Enterprise-grade** - 5+ years of stability
- **No vendor lock-in** - Open protocols and standards
# Build all (from each directory)
cd botlib && cargo build
cd ../botserver && cargo build
cd ../botui && cargo build
cd ../botapp && cargo build
```
---
## 📖 Documentation
- **[Complete Documentation](https://github.com/GeneralBots/botbook)** - Full mdBook documentation
- **[Quick Start Guide](https://github.com/GeneralBots/botserver/blob/main/docs/QUICK_START.md)** - Get started in minutes
- **[API Reference](https://github.com/GeneralBots/botserver/blob/main/docs/src/chapter-10-api/README.md)** - REST API documentation
- **[Architecture Guide](https://github.com/GeneralBots/botserver/blob/main/docs/src/chapter-07-gbapp/README.md)** - System architecture
Report security issues to: **security@pragmatismo.com.br**
---
@ -172,14 +353,16 @@ cd ../botapp && cargo build
---
## 🛡️ Security
## 🔗 Links
- **AGPL-3.0 License** - True open source with contribution requirements
- **Self-hosted** - Your data stays on your infrastructure
- **Enterprise-grade** - 5+ years of stability
- **No vendor lock-in** - Open protocols and standards
Report security issues to: **security@pragmatismo.com.br**
- **Website:** [pragmatismo.com.br](https://pragmatismo.com.br)
- **Documentation:** [docs.pragmatismo.com.br](https://docs.pragmatismo.com.br)
- **BotBook:** [Complete Documentation](https://github.com/GeneralBots/botbook)
- **Quick Start:** [Get Started in Minutes](https://github.com/GeneralBots/botserver/blob/main/docs/QUICK_START.md)
- **API Reference:** [REST API Documentation](https://github.com/GeneralBots/botserver/blob/main/docs/src/chapter-10-api/README.md)
- **Architecture:** [System Architecture Guide](https://github.com/GeneralBots/botserver/blob/main/docs/src/chapter-07-gbapp/README.md)
- **Stack Overflow:** Tag questions with `generalbots`
- **Video Tutorial:** [7 AI General Bots LLM Templates](https://www.youtube.com/watch?v=KJgvUPXi3Fw)
---
@ -195,6 +378,19 @@ We welcome contributions! See our [Contributing Guidelines](https://github.com/G
---
## 🔑 Remember
- **Accuracy** - Must match botserver source code
- **Completeness** - No placeholder sections
- **Clarity** - Accessible to BASIC enthusiasts
- **Keywords** - NEVER use underscores - always spaces
- **NO ASCII art** - Use SVG diagrams only
- **Official icons** - Use icons from botui/ui/suite/assets/icons/
- **Version 6.2.0** - Always reference 6.2.0
- **GIT WORKFLOW** - ALWAYS push to ALL repositories (github, pragmatismo)
---
## 📄 License
General Bots is licensed under **AGPL-3.0**.
@ -205,15 +401,6 @@ Copyright (c) pragmatismo.com.br. All rights reserved.
---
## 🔗 Links
- **Website:** [pragmatismo.com.br](https://pragmatismo.com.br)
- **Documentation:** [docs.pragmatismo.com.br](https://docs.pragmatismo.com.br)
- **Stack Overflow:** Tag questions with `generalbots`
- **Video Tutorial:** [7 AI General Bots LLM Templates](https://www.youtube.com/watch?v=KJgvUPXi3Fw)
---
> **Code Name:** [Guaribas](https://en.wikipedia.org/wiki/Guaribas) (a city in Brazil, state of Piauí)
>
> *"No one should have to do work that can be done by a machine."* - Roberto Mangabeira Unger

View file

@ -107,7 +107,7 @@ Attendants can be identified by **any channel**: WhatsApp phone, email, Microsof
```csv
id,name,channel,preferences,department,aliases,phone,email,teams,google
att-001,João Silva,all,sales,commercial,joao;js;silva,+5511999990001,joao.silva@company.com,joao.silva@company.onmicrosoft.com,joao.silva@company.com
att-002,Maria Santos,whatsapp,support,customer-service,maria;ms,+5511999990002,maria.santos@company.com,maria.santos@company.onmicrosoft.com,maria.santos@gmail.com
att-002,Maria Santos,whatsapp,support,customer-service,maria;ms,+5511999990002,santos@company.com,santos@company.onmicrosoft.com,santos@gmail.com
att-003,Pedro Costa,web,technical,engineering,pedro;pc;tech,+5511999990003,pedro.costa@company.com,pedro.costa@company.onmicrosoft.com,pedro.costa@company.com
att-004,Ana Oliveira,all,collections,finance,ana;ao;cobranca,+5511999990004,ana.oliveira@company.com,ana.oliveira@company.onmicrosoft.com,ana.oliveira@company.com
att-005,Carlos Souza,whatsapp,sales,commercial,carlos;cs,+5511999990005,carlos.souza@company.com,carlos.souza@company.onmicrosoft.com,carlos.souza@gmail.com

View file

@ -62,7 +62,7 @@ Add these settings to your `config.csv`:
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>maria.santos@company.com</p>
<p>santos@company.com</p>
<div class="wa-time">10:33</div>
</div>
</div>
@ -97,7 +97,7 @@ Add these settings to your `config.csv`:
<p>📋 <strong>Contact Details</strong></p>
<p>━━━━━━━━━━━━━━━━━</p>
<p>👤 <strong>Name:</strong> Maria Santos</p>
<p>📧 <strong>Email:</strong> maria.santos@company.com</p>
<p>📧 <strong>Email:</strong> santos@company.com</p>
<p>📱 <strong>Phone:</strong> +55 11 98765-4321</p>
<p>🏢 <strong>Company:</strong> Tech Solutions Ltd</p>
<p>🏷️ <strong>Tags:</strong> lead</p>
@ -139,7 +139,7 @@ Add these settings to your `config.csv`:
<div class="wa-bubble">
<p>🔍 Found 3 contacts at "Tech Solutions":</p>
<p></p>
<p>1. <strong>Maria Santos</strong> - maria.santos@company.com</p>
<p>1. <strong>Maria Santos</strong> - santos@company.com</p>
<p> 📱 +55 11 98765-4321 | 🏷️ lead</p>
<p></p>
<p>2. <strong>João Silva</strong> - joao.silva@techsolutions.com</p>

View file

@ -51,12 +51,12 @@ pageVariable = "pagina"
limitVariable = "limite"
SEND EMAIL admin, "Syncing categories..."
SYNCHRONIZE /categorias/receitas-despesas, maria.CategoriaReceita, Id, pageVariable, limitVariable
SYNCHRONIZE /categorias/receitas-despesas, CategoriaReceita, Id, pageVariable, limitVariable
SEND EMAIL admin, REPORT
RESET REPORT
' Sync payment methods
SYNCHRONIZE /formas-pagamentos, maria.FormaDePagamento, Id, pageVariable, limitVariable
SYNCHRONIZE /formas-pagamentos, FormaDePagamento, Id, pageVariable, limitVariable
SEND EMAIL admin, REPORT
RESET REPORT
```
@ -69,7 +69,7 @@ Until `SYNCHRONIZE` is implemented, use this pattern:
' Manual sync equivalent
pageVariable = "pagina"
limitVariable = "limite"
tableName = "maria.CategoriaReceita"
tableName = "CategoriaReceita"
endpoint = "/categorias/receitas-despesas"
page = 1
@ -112,7 +112,7 @@ TALK "Synced " + totalSynced + " records to " + tableName
When implemented, `SYNCHRONIZE` should:
1. Use the global `host`, `limit`, `pages` variables from config
2. Support connection prefixes (e.g., `maria.TableName`)
2. Support connection prefixes (e.g., `TableName`)
3. Handle API errors gracefully with retry logic
4. Update the `REPORT` variable with sync statistics
5. Support both REST JSON responses and paginated arrays

View file

@ -5,7 +5,7 @@ The `TABLE` keyword defines database tables directly in your `.bas` files. Table
## Syntax
```basic
TABLE TableName ON connection
TABLE TableName
FieldName dataType[(length[,precision])] [key] [references OtherTable]
...
END TABLE
@ -70,7 +70,7 @@ conn-maria-Driver,mariadb
### Basic Table Definition
```basic
TABLE Contacts ON maria
TABLE Contacts
Id number key
Nome string(150)
Email string(255)
@ -82,7 +82,7 @@ END TABLE
### Table with Multiple Field Types
```basic
TABLE Produtos ON maria
TABLE Produtos
Id number key
Nome string(150)
Sku string(20)
@ -98,7 +98,7 @@ END TABLE
### Table with Foreign Key References
```basic
TABLE Pedidos ON maria
TABLE Pedidos
Id number key
Numero integer
Data date
@ -108,7 +108,7 @@ TABLE Pedidos ON maria
Vendedor_id number
END TABLE
TABLE PedidosItem ON maria
TABLE PedidosItem
Id number key
Pedido_id number
Produto_id number
@ -122,7 +122,7 @@ END TABLE
```basic
' Contact management tables
TABLE Contatos ON maria
TABLE Contatos
Id number key
Nome string(150)
Codigo string(50)
@ -142,7 +142,7 @@ TABLE Contatos ON maria
END TABLE
' Payment methods
TABLE FormaDePagamento ON maria
TABLE FormaDePagamento
Id number key
Descricao string(255)
TipoPagamento integer
@ -153,7 +153,7 @@ TABLE FormaDePagamento ON maria
END TABLE
' Accounts receivable
TABLE ContasAReceber ON maria
TABLE ContasAReceber
Id number key
Situacao integer
Vencimento date

View file

@ -2,60 +2,96 @@
**Syntax**
```
```basic
USE WEBSITE "https://example.com"
USE WEBSITE "https://example.com" REFRESH "1d"
```
**Parameters**
- `"url"` A valid HTTP or HTTPS URL pointing to a website that should be made available in the conversation context.
- `"refresh"` (Optional) How often to recrawl the website. Supports: `"1d"` (1 day), `"1w"` (1 week), `"1m"` (1 month), `"1y"` (1 year). Defaults to `"1m"`.
**Description**
`USE WEBSITE` operates in two distinct modes:
1. **Preprocessing Mode** (Script Compilation): When found in a BASIC script during compilation, it registers the website for background crawling. The crawler service will fetch, extract, and index the website's content into a vector database collection. This ensures the website content is ready before any conversation starts.
1. **Preprocessing Mode** (Script Compilation): When found in a BASIC script during compilation, it registers the website for background crawling. The crawler service will fetch, extract, and index the website's content into a vector database collection. The crawl happens immediately on first compile, then recurs based on the REFRESH interval.
2. **Runtime Mode** (Conversation Execution): During a conversation, `USE WEBSITE` associates an already-crawled website collection with the current session, making it available for queries via `FIND` or `LLM` calls. This behaves similarly to `USE KB` - it's a session-scoped association.
If a website hasn't been registered during preprocessing, the runtime execution will fail with an appropriate error message.
If a website hasn't been registered during preprocessing, the runtime execution will auto-register it for crawling.
**Example**
**Refresh Interval Behavior**
- **Smart Interval Selection**: If the same URL is registered multiple times with different REFRESH intervals, the **shortest interval** is always used
- **Default**: If no REFRESH is specified, defaults to `"1m"` (1 month)
- **Formats Supported**:
- `"1d"` = 1 day
- `"1w"` = 1 week
- `"1m"` = 1 month (default)
- `"1y"` = 1 year
- Custom: `"3d"`, `"2w"`, `"6m"`, etc.
**Examples**
Basic usage with default 1-month refresh:
```basic
USE WEBSITE "https://docs.example.com"
```
High-frequency website (daily refresh):
```basic
USE WEBSITE "https://news.example.com" REFRESH "1d"
```
Stable documentation (monthly refresh):
```basic
USE WEBSITE "https://api.example.com/docs" REFRESH "1m"
```
Multiple registrations - shortest interval wins:
```basic
USE WEBSITE "https://example.com" REFRESH "1w"
USE WEBSITE "https://example.com" REFRESH "1d"
' Final refresh interval: 1d (shortest)
```
**Runtime Example**
```basic
' In script preprocessing, this registers the website for crawling
USE WEBSITE "https://docs.example.com"
' During conversation, this makes the crawled content available
USE WEBSITE "https://docs.example.com"
FIND "deployment procedures"
TALK "I found information about deployment procedures in the documentation."
USE WEBSITE "https://company.com/policies" REFRESH "1w"
question = HEAR "What would you like to know about our policies?"
FIND question
answer = LLM "Based on the search results, provide a clear answer"
TALK answer
```
**Preprocessing Behavior**
When the script is compiled:
- The URL is validated
- The website is registered in the `website_crawls` table
- The crawler service picks it up and indexes the content
- The website is registered in the `website_crawls` table with the specified refresh policy
- The crawler service immediately starts crawling the website
- Subsequent crawls are scheduled based on the REFRESH interval
- Status can be: pending (0), crawled (1), or failed (2)
**Runtime Behavior**
When executed in a conversation:
- Checks if the website has been crawled
- Checks if the website has been registered and crawled
- If not registered, auto-registers with default 1-month refresh
- Associates the website collection with the current session
- Makes the content searchable via `FIND` and available to `LLM`
**With LLM Integration**
**Database Schema**
```basic
USE WEBSITE "https://company.com/policies"
question = HEAR "What would you like to know about our policies?"
FIND question
answer = LLM "Based on the search results, provide a clear answer"
TALK answer
```
The `website_crawls` table stores:
- `refresh_policy` - User-configured refresh interval (e.g., "1d", "1w", "1m")
- `expires_policy` - Internal representation in days
- `next_crawl` - Timestamp for next scheduled crawl
- `crawl_status` - 0=pending, 1=success, 2=processing, 3=error
**Related Keywords**

View file

@ -105,7 +105,7 @@ These conversations show how the authentication template works in real-world sce
<div class="wa-message user">
<div class="wa-bubble">
<p>maria.santos</p>
<p>santos</p>
<div class="wa-time">09:00 <span class="wa-status read"></span></div>
</div>
</div>

View file

@ -237,7 +237,7 @@ These conversations show how the HR Employees template works in real-world scena
<p><strong>Employee Added Successfully!</strong></p>
<p></p>
<p>🆔 Employee ID: EMP-2025-0147</p>
<p>📧 Email: maria.santos@company.com</p>
<p>📧 Email: santos@company.com</p>
<p>📞 Extension: 4587</p>
<p></p>
<p>📧 Welcome email sent to Maria</p>

View file

@ -139,7 +139,7 @@ These conversations show how the enrollment template works in real-world scenari
<div class="wa-message user">
<div class="wa-bubble">
<p>maria.santos@email.com</p>
<p>santos@email.com</p>
<div class="wa-time">10:32 <span class="wa-status read"></span></div>
</div>
</div>
@ -177,7 +177,7 @@ These conversations show how the enrollment template works in real-world scenari
<p>Please confirm your details:</p>
<p><strong>Name:</strong> Maria Santos Silva</p>
<p><strong>Birth Date:</strong> 15/03/1990</p>
<p><strong>Email:</strong> maria.santos@email.com</p>
<p><strong>Email:</strong> santos@email.com</p>
<p><strong>Personal ID:</strong> 12345678901</p>
<p><strong>Address:</strong> Rua das Palmeiras, 456 - São Paulo, SP</p>
<div class="wa-time">10:33</div>

View file

@ -1,103 +1,178 @@
<svg width="800" height="600" viewBox="0 0 800 600" xmlns="http://www.w3.org/2000/svg" style="max-width: 100%; height: auto;">
<svg width="800" height="720" viewBox="0 0 800 720" xmlns="http://www.w3.org/2000/svg" style="max-width: 100%; height: auto;">
<style>
/* Light Mode Colors */
.title-text { fill: #1E1B4B; }
.main-text { fill: #334155; }
.box-stroke { stroke: #4B5563; }
.arrow-stroke { stroke: #6B7280; }
.arrow-fill { fill: #4B5563; }
.arrow-double-fill { fill: #6B7280; }
/* Box-specific colors */
.user-input-stroke { stroke: #3B82F6; }
.user-input-text { fill: #1E40AF; }
.bot-response-stroke { stroke: #10B981; }
.bot-response-text { fill: #047857; }
.websocket-stroke { stroke: #F97316; }
.websocket-text { fill: #C2410C; }
.websocket-subtext { fill: #FDBA74; }
.session-manager-stroke { stroke: #8B5CF6; }
.session-manager-text { fill: #7C3AED; }
.session-manager-steps { fill: #6D28D9; }
.valkey-stroke { stroke: #DC2626; }
.valkey-text { fill: #B91C1C; }
.valkey-subtext { fill: #EF4444; }
.postgres-stroke { stroke: #2563EB; }
.postgres-text { fill: #1D4ED8; }
.postgres-subtext { fill: #3B82F6; }
.features-stroke { stroke: #4B5563; }
.features-text { fill: #1F2937; }
.circle-stroke { stroke: #64748B; }
/* Dark Mode Colors */
@media (prefers-color-scheme: dark) {
.title-text { fill: #F1F5F9; }
.main-text { fill: #E2E8F0; }
.box-stroke { stroke: #9CA3AF; }
.arrow-stroke { stroke: #9CA3AF; }
.arrow-fill { fill: #9CA3AF; }
.arrow-double-fill { fill: #A1A1AA; }
.user-input-stroke { stroke: #60A5FA; }
.user-input-text { fill: #93C5FD; }
.bot-response-stroke { stroke: #34D399; }
.bot-response-text { fill: #6EE7B7; }
.websocket-stroke { stroke: #FB923C; }
.websocket-text { fill: #FDBA74; }
.websocket-subtext { fill: #FED7AA; }
.session-manager-stroke { stroke: #A78BFA; }
.session-manager-text { fill: #C4B5FD; }
.session-manager-steps { fill: #DDD6FE; }
.valkey-stroke { stroke: #F87171; }
.valkey-text { fill: #FCA5A5; }
.valkey-subtext { fill: #FECACA; }
.postgres-stroke { stroke: #60A5FA; }
.postgres-text { fill: #93C5FD; }
.postgres-subtext { fill: #BFDBFE; }
.features-stroke { stroke: #6B7280; }
.features-text { fill: #F9FAFB; }
.circle-stroke { stroke: #94A3B8; }
}
</style>
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#4B5563"/>
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L12,6 L0,12 z" class="arrow-fill"/>
</marker>
<marker id="arrow-double" markerWidth="10" markerHeight="10" refX="5" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L5,3 z" fill="#999"/>
<path d="M5,0 L5,6 L10,3 z" fill="#999"/>
<marker id="arrow-double" markerWidth="16" markerHeight="12" refX="8" refY="6" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L8,6 L0,12 z" class="arrow-double-fill"/>
<path d="M16,0 L8,6 L16,12 z" class="arrow-double-fill"/>
</marker>
</defs>
<!-- Title -->
<text x="400" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="22" font-weight="bold" fill="#1F2937">Session Manager Architecture</text>
<text x="400" y="30" text-anchor="middle" font-family="Arial, sans-serif" font-size="22" font-weight="bold" class="title-text">Session Manager Architecture</text>
<!-- User Input -->
<rect x="50" y="60" width="150" height="50" fill="none" stroke="#63B3ED" stroke-width="2" rx="8"/>
<text x="125" y="85" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#1E40AF">User Input</text>
<rect x="50" y="60" width="150" height="50" fill="none" class="user-input-stroke" stroke-width="2" rx="8"/>
<text x="125" y="85" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" class="user-input-text">User Input</text>
<!-- Bot Response -->
<rect x="600" y="60" width="150" height="50" fill="none" stroke="#68D391" stroke-width="2" rx="8"/>
<text x="675" y="85" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#10B981">Bot Response</text>
<rect x="600" y="60" width="150" height="50" fill="none" class="bot-response-stroke" stroke-width="2" rx="8"/>
<text x="675" y="85" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" class="bot-response-text">Bot Response</text>
<!-- Arrows down from User Input and up to Bot Response -->
<line x1="125" y1="110" x2="125" y2="150" stroke="#888" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="675" y1="150" x2="675" y2="110" stroke="#888" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="125" y1="120" x2="125" y2="180" class="arrow-stroke" stroke-width="1.5" marker-end="url(#arrow)"/>
<line x1="675" y1="180" x2="675" y2="120" class="arrow-stroke" stroke-width="1.5" marker-end="url(#arrow)"/>
<!-- WebSocket/HTTP boxes -->
<rect x="50" y="150" width="150" height="60" fill="none" stroke="#F6AD55" stroke-width="2" rx="6"/>
<text x="125" y="175" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#EA580C">WebSocket</text>
<text x="125" y="195" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" fill="#FED7AA">/HTTP</text>
<rect x="50" y="180" width="150" height="60" fill="none" class="websocket-stroke" stroke-width="2" rx="6"/>
<text x="125" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" class="websocket-text">WebSocket</text>
<text x="125" y="225" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" class="websocket-subtext">/HTTP</text>
<rect x="600" y="150" width="150" height="60" fill="none" stroke="#F6AD55" stroke-width="2" rx="6"/>
<text x="675" y="175" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#EA580C">WebSocket</text>
<text x="675" y="195" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" fill="#FED7AA">/HTTP</text>
<rect x="600" y="180" width="150" height="60" fill="none" class="websocket-stroke" stroke-width="2" rx="6"/>
<text x="675" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" class="websocket-text">WebSocket</text>
<text x="675" y="225" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" class="websocket-subtext">/HTTP</text>
<!-- Arrows to/from Session Manager -->
<line x1="125" y1="210" x2="125" y2="250" stroke="#888" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="675" y1="250" x2="675" y2="210" stroke="#888" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="125" y1="250" x2="125" y2="310" class="arrow-stroke" stroke-width="1.5" marker-end="url(#arrow)"/>
<line x1="675" y1="310" x2="675" y2="250" class="arrow-stroke" stroke-width="1.5" marker-end="url(#arrow)"/>
<!-- Session Manager Box -->
<rect x="100" y="250" width="600" height="130" fill="none" stroke="#B794F4" stroke-width="3" rx="10"/>
<text x="400" y="280" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#9333EA">Session Manager</text>
<rect x="100" y="310" width="600" height="130" fill="none" class="session-manager-stroke" stroke-width="3" rx="10"/>
<text x="400" y="340" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" class="session-manager-text">Session Manager</text>
<!-- Session Manager Steps -->
<g font-family="Arial, sans-serif" font-size="18" fill="#7C3AED">
<text x="150" y="310">1. Validate Token</text>
<text x="150" y="330">2. Load Session</text>
<text x="150" y="350">3. Update State</text>
<g font-family="Arial, sans-serif" font-size="18" class="session-manager-steps">
<text x="150" y="370">1. Validate Token</text>
<text x="150" y="390">2. Load Session</text>
<text x="150" y="410">3. Update State</text>
<text x="450" y="310">4. Execute BASIC</text>
<text x="450" y="330">5. Generate Response</text>
<text x="450" y="350">6. Save History</text>
<text x="450" y="370">4. Execute BASIC</text>
<text x="450" y="390">5. Generate Response</text>
<text x="450" y="410">6. Save History</text>
</g>
<!-- Arrows down to databases -->
<line x1="250" y1="380" x2="250" y2="420" stroke="#888" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="550" y1="380" x2="550" y2="420" stroke="#888" stroke-width="2" marker-end="url(#arrow)"/>
<line x1="250" y1="450" x2="250" y2="490" class="arrow-stroke" stroke-width="1.5" marker-end="url(#arrow)"/>
<line x1="550" y1="450" x2="550" y2="490" class="arrow-stroke" stroke-width="1.5" marker-end="url(#arrow)"/>
<!-- Database boxes -->
<rect x="150" y="420" width="200" height="80" fill="none" stroke="#E53E3E" stroke-width="2" rx="8"/>
<text x="250" y="450" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#EF4444">Valkey</text>
<text x="250" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" fill="#DC2626">(Cache)</text>
<rect x="150" y="490" width="200" height="80" fill="none" class="valkey-stroke" stroke-width="2" rx="8"/>
<text x="250" y="520" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" class="valkey-text">Valkey</text>
<text x="250" y="540" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" class="valkey-subtext">(Cache)</text>
<rect x="450" y="420" width="200" height="80" fill="none" stroke="#4A90E2" stroke-width="2" rx="8"/>
<text x="550" y="450" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" fill="#2563EB">PostgreSQL</text>
<text x="550" y="470" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" fill="#1E40AF">(Persist)</text>
<rect x="450" y="490" width="200" height="80" fill="none" class="postgres-stroke" stroke-width="2" rx="8"/>
<text x="550" y="520" text-anchor="middle" font-family="Arial, sans-serif" font-size="20" font-weight="bold" class="postgres-text">PostgreSQL</text>
<text x="550" y="540" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" class="postgres-subtext">(Persist)</text>
<!-- Sync arrow between databases -->
<path d="M 350 460 L 450 460" stroke="#888" stroke-width="2" marker-end="url(#arrow-double)" stroke-dasharray="5,5" opacity="0.7"/>
<text x="400" y="455" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#374151">Sync Every</text>
<text x="400" y="475" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="#374151">Message</text>
<path d="M 350 530 L 450 530" class="arrow-stroke" stroke-width="1.5" marker-end="url(#arrow-double)" stroke-dasharray="5,5" opacity="0.7"/>
<text x="400" y="525" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" class="main-text">Sync Every</text>
<text x="400" y="545" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" class="main-text">Message</text>
<!-- Process Flow Numbers -->
<g font-family="Arial, sans-serif" font-size="16" fill="#374151">
<circle cx="125" cy="130" r="12" fill="none" stroke="#718096" stroke-width="1"/>
<text x="125" y="134" text-anchor="middle">1</text>
<g font-family="Arial, sans-serif" font-size="16" class="main-text">
<circle cx="95" cy="140" r="12" fill="none" class="circle-stroke" stroke-width="1"/>
<text x="95" y="144" text-anchor="middle">1</text>
<circle cx="125" cy="230" r="12" fill="none" stroke="#718096" stroke-width="1"/>
<text x="125" y="234" text-anchor="middle">2</text>
<circle cx="95" cy="270" r="12" fill="none" class="circle-stroke" stroke-width="1"/>
<text x="95" y="274" text-anchor="middle">2</text>
<circle cx="400" cy="315" r="12" fill="none" stroke="#718096" stroke-width="1"/>
<text x="400" y="319" text-anchor="middle">3</text>
<circle cx="400" cy="375" r="12" fill="none" class="circle-stroke" stroke-width="1"/>
<text x="400" y="379" text-anchor="middle">3</text>
<circle cx="675" cy="230" r="12" fill="none" stroke="#718096" stroke-width="1"/>
<text x="675" y="234" text-anchor="middle">4</text>
<circle cx="705" cy="270" r="12" fill="none" class="circle-stroke" stroke-width="1"/>
<text x="705" y="274" text-anchor="middle">4</text>
<circle cx="675" cy="130" r="12" fill="none" stroke="#718096" stroke-width="1"/>
<text x="675" y="134" text-anchor="middle">5</text>
<circle cx="705" cy="140" r="12" fill="none" class="circle-stroke" stroke-width="1"/>
<text x="705" y="144" text-anchor="middle">5</text>
</g>
<!-- Features box -->
<g id="features" transform="translate(50, 520)">
<rect x="0" y="0" width="700" height="60" fill="none" stroke="#4A5568" stroke-width="1" rx="5" stroke-dasharray="2,2" opacity="0.5"/>
<text x="350" y="20" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#1F2937">Key Features</text>
<g id="features" transform="translate(50, 600)">
<rect x="0" y="0" width="700" height="100" fill="none" class="features-stroke" stroke-width="1" rx="5" stroke-dasharray="2,2" opacity="0.5"/>
<text x="350" y="20" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" class="features-text">Key Features</text>
<g font-family="Arial, sans-serif" font-size="16" fill="#374151">
<g font-family="Arial, sans-serif" font-size="14" class="main-text">
<text x="50" y="45">• Real-time WebSocket support</text>
<text x="250" y="45">• Automatic session persistence</text>
<text x="450" y="45">• Redis-compatible caching</text>
<text x="600" y="45">• ACID compliance</text>
<text x="400" y="45">• Automatic session persistence</text>
<text x="50" y="75">• Redis-compatible caching</text>
<text x="400" y="75">• ACID compliance</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB