Chapter 17: Rewrite Autonomous Tasks with wa-chat format and SVG diagrams

- Add autotask-architecture.svg showing intent classification flow
- Convert all designer-panel format to wa-chat (WhatsApp style)
- Remove emojis and icons per PROMPT.md standards
- Convert ASCII diagrams to tables
- Delete CODER-PROMPT.md and implementation.md
- Rename chapter from 21 to 17
- Add 6 SVG diagrams for chapter 17
- Fix book.toml: devchat-panel.css to designer-panel.css
- Update SUMMARY.md with correct paths
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-12-27 17:10:57 -03:00
parent a6cf79c9ae
commit 9d25ecbb12
30 changed files with 3375 additions and 1882 deletions

View file

@ -12,7 +12,7 @@ build-dir = "book"
default-theme = "light"
preferred-dark-theme = "navy"
smart-punctuation = true
additional-css = ["src/custom.css", "src/whatsapp-chat.css"]
additional-css = ["src/custom.css", "src/whatsapp-chat.css", "src/designer-panel.css"]
additional-js = ["src/theme-sync.js"]
[output.html.favicon]

View file

@ -224,6 +224,6 @@ with status: received, diagnosing, repairing, ready, delivered"
## See Also
- [Autonomous Tasks](../../21-autonomous-tasks/README.md) - Complete guide
- [Autonomous Tasks](../../17-autonomous-tasks/README.md) - Complete guide
- [Dev Chat Widget](../dev-chat.md) - Test while developing
- [HTMX Architecture](../htmx-architecture.md) - How the UI works

View file

@ -238,6 +238,6 @@ The dev chat widget:
## See Also
- [Autonomous Tasks](../21-autonomous-tasks/README.md) - How apps are generated
- [Autonomous Tasks](../17-autonomous-tasks/README.md) - How apps are generated
- [HTMX Architecture](./htmx-architecture.md) - Frontend patterns
- [REST API](../10-rest/README.md) - API reference

View file

@ -309,7 +309,7 @@ The dev chat uses the same `user_data` system for history storage.
## See Also
- [Autonomous Tasks Chapter](../21-autonomous-tasks/README.md) - Complete guide
- [Autonomous Tasks Chapter](../17-autonomous-tasks/README.md) - Complete guide
- [CREATE SITE](../06-gbdialog/keyword-create-site.md) - The keyword behind it
- [REST API](../10-rest/README.md) - API reference
- [HTMX Architecture](../04-gbui/htmx-architecture.md) - Frontend patterns

View file

@ -0,0 +1,166 @@
# Autonomous Tasks
Build complete applications through natural conversation. Describe what you want, and the system creates it automatically.
The AutoTask system uses an LLM-powered intent classifier to understand your request and route it to the appropriate handler. Whether you need a full web application, a simple reminder, or automated monitoring, you describe it in plain language.
![AutoTask Architecture](../assets/chapter-17/autotask-architecture.svg)
---
## Intent Types
| Type | Example | What Gets Created |
|------|---------|-------------------|
| `APP_CREATE` | "create app for clinic" | HTMX pages, tools, schedulers |
| `TODO` | "call John tomorrow" | Task saved to tasks table |
| `MONITOR` | "alert when IBM changes" | ON CHANGE event handler |
| `ACTION` | "email all customers" | Executes immediately |
| `SCHEDULE` | "daily 9am summary" | SET SCHEDULE automation |
| `GOAL` | "increase sales 20%" | Autonomous LLM loop with metrics |
| `TOOL` | "when I say X, do Y" | Voice/chat command |
---
## Quick Start
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Create an app for my clinic</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Done:</strong></p>
<p>patients table created</p>
<p>appointments table created</p>
<p>App available at /apps/clinic</p>
<div class="wa-time">10:31</div>
</div>
</div>
</div>
---
## Architecture Overview
![Bot Database Architecture](../assets/chapter-17/bot-database-architecture.svg)
One bot equals one database. All applications within a bot share the same data tables, tools, and schedulers.
---
## File Structure
| Path | Description |
|------|-------------|
| `.gbdrive/apps/{name}/` | Generated web application |
| `.gbdrive/apps/{name}/index.html` | Main HTMX page |
| `.gbdrive/apps/{name}/assets/` | CSS, images |
| `.gbdialog/tables.bas` | Database schema definitions |
| `.gbdialog/tools/` | Voice and chat commands |
| `.gbdialog/schedulers/` | Timed automations |
| `.gbdialog/events/` | Event triggers (ON CHANGE, ON EMAIL) |
---
## Creating an Application
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>I need an app to track customers and orders</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Done:</strong></p>
<p>customers table created</p>
<p>orders table created</p>
<p>App available at /apps/store</p>
<div class="wa-time">10:31</div>
</div>
</div>
</div>
---
## Modifying Your Application
Use Designer to change anything about your app through conversation.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Add a phone field to customers</p>
<div class="wa-time">14:20</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Phone field added to customers table.</p>
<div class="wa-time">14:20</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>Change the submit button to blue</p>
<div class="wa-time">14:21</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Button color updated to blue.</p>
<div class="wa-time">14:21</div>
</div>
</div>
</div>
---
## Adding Automation
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Every day at 9am, send me new orders by email</p>
<div class="wa-time">09:15</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Scheduler created: daily-orders-summary.bas</p>
<p>Schedule: Every day at 9:00 AM</p>
<div class="wa-time">09:15</div>
</div>
</div>
</div>
---
## Keywords Reference
| Keyword | Purpose |
|---------|---------|
| `TABLE` | Define data structure |
| `FIND` | Search records |
| `SAVE` | Create record |
| `UPDATE` | Modify record |
| `DELETE` | Remove record |
| `TALK` | Send message |
| `HEAR` | Wait for input |
| `SET SCHEDULE` | Create automation |
| `ON CHANGE` | Monitor for changes |
| `ON EMAIL` | Trigger on email received |
---
## Next Steps
- [Designer Guide](./designer.md) — Edit apps through conversation
- [Data Model](./data-model.md) — Understanding tables
- [Task Workflow](./workflow.md) — How tasks execute
- [Examples](./examples.md) — Real-world applications

View file

@ -0,0 +1,117 @@
# App Generation
From natural language to complete application, the generation process handles database design, UI creation, and automation setup.
![App Generation Flow](../assets/chapter-17/app-generation-flow.svg)
---
## How It Works
You describe what you need. The system analyzes your request, identifies the domain, extracts entities, and generates everything automatically.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Create an inventory app for my store</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Done:</strong></p>
<p>products table created</p>
<p>categories table created</p>
<p>suppliers table created</p>
<p>App available at /apps/inventory</p>
<div class="wa-time">10:31</div>
</div>
</div>
</div>
---
## What Gets Created
| Component | Location | Description |
|-----------|----------|-------------|
| Database tables | `tables.bas` | Data schema with fields and types |
| Web pages | `/apps/{name}/` | HTMX-based user interface |
| Voice commands | `.gbdialog/tools/` | Activated by trigger phrases |
| Automations | `.gbdialog/schedulers/` | Timed tasks and reports |
---
## Modifying Your App
Use conversation to change any aspect of your application.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Add a supplier field to products</p>
<div class="wa-time">14:20</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Supplier field added to products table.</p>
<p>Form updated in products.html.</p>
<div class="wa-time">14:20</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>Change the header color to red</p>
<div class="wa-time">14:21</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Header color updated to red in styles.css.</p>
<div class="wa-time">14:21</div>
</div>
</div>
</div>
---
## Multiple Apps, Shared Data
Create different applications that share the same database tables.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Create a reports app using the same inventory data</p>
<div class="wa-time">15:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Done:</strong></p>
<p>App created at /apps/inventory-reports</p>
<p>Uses existing tables: products, categories, suppliers</p>
<div class="wa-time">15:01</div>
</div>
</div>
</div>
---
## Generation Process
| Phase | Description |
|-------|-------------|
| **Intent Analysis** | LLM identifies domain and required entities |
| **Schema Design** | Tables and relationships defined |
| **UI Generation** | HTMX pages created for each entity |
| **Tool Creation** | Voice commands for common actions |
| **Scheduler Setup** | Automations for reports and alerts |
---
## Next Steps
- [Designer Guide](./designer.md) — All modification commands
- [Data Model](./data-model.md) — Understanding table definitions

View file

@ -0,0 +1,166 @@
# Data Model
Tables store your application data. When you describe what you need, the system creates table definitions automatically in `tables.bas`.
![Data Model Flow](../assets/chapter-17/data-model-flow.svg)
---
## What Is a Table?
A table organizes related data into rows and columns, similar to a spreadsheet.
| id | name | phone | email |
|----|------|-------|-------|
| 1 | John Smith | 555-1234 | john@email.com |
| 2 | Maria Garcia | 555-5678 | maria@email.com |
---
## Creating Tables
Describe what data you need to store.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>I need a customers table with name, phone, and email</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>customers table created with fields:</p>
<p>name (STRING)</p>
<p>phone (STRING)</p>
<p>email (STRING)</p>
<div class="wa-time">10:30</div>
</div>
</div>
</div>
---
## Adding Fields
Add new fields to existing tables through conversation.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Add address to customers</p>
<div class="wa-time">14:15</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Address field added to customers table.</p>
<div class="wa-time">14:15</div>
</div>
</div>
</div>
---
## Field Types
| Type | Use For | Example |
|------|---------|---------|
| `STRING` | Short text | Names, phones |
| `TEXT` | Long text | Notes, descriptions |
| `INTEGER` | Whole numbers | Age, quantity |
| `DECIMAL` | Numbers with decimals | Price, weight |
| `BOOLEAN` | Yes/No values | Active, completed |
| `DATE` | Dates only | Birth date |
| `DATETIME` | Date and time | Appointment time |
---
## Searching Data
Use natural language to find records.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Find customers named Smith</p>
<div class="wa-time">11:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Found 2 customers:</strong></p>
<p>John Smith - 555-1234</p>
<p>Jane Smith - 555-9876</p>
<div class="wa-time">11:00</div>
</div>
</div>
</div>
---
## Linking Tables
Create relationships between tables.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Create orders table linked to customers</p>
<div class="wa-time">11:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>orders table created with:</p>
<p>customer_id (links to customers)</p>
<p>date (DATETIME)</p>
<p>total (DECIMAL)</p>
<p>status (STRING)</p>
<div class="wa-time">11:30</div>
</div>
</div>
</div>
---
## Shared Data
All applications within a bot share the same tables. Change data in one app, and it updates everywhere.
| Concept | Description |
|---------|-------------|
| One bot = one database | All apps share tables |
| Schema in tables.bas | Single source of truth |
| Auto-sync | Changes deploy automatically |
---
## TABLE Keyword
Tables are defined in `.gbdialog/tables.bas` using the TABLE keyword:
| Syntax | Description |
|--------|-------------|
| `TABLE name` | Start table definition |
| `field AS TYPE` | Define a field |
| `END TABLE` | End table definition |
---
## FIND Keyword
Query data using the FIND keyword:
| Syntax | Description |
|--------|-------------|
| `FIND * IN table` | Get all records |
| `FIND * IN table WHERE condition` | Filter records |
| `FIND field1, field2 IN table` | Select specific fields |
---
## Next Steps
- [Designer Guide](./designer.md) — Modify tables through conversation
- [Examples](./examples.md) — Real-world data models

View file

@ -0,0 +1,377 @@
# Designer
Designer is an AI assistant that appears alongside your application. Use natural conversation to modify any aspect of your app without writing code.
![Designer Workflow](../assets/chapter-17/designer-workflow.svg)
---
## How It Works
Designer understands the context of your application. When you make a request, it knows which app you are viewing, which page is active, and what tables exist.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Change the schedule button to blue</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Updating schedule.html:</p>
<p>.btn-schedule { background-color: #3498db; }</p>
<p>Button color changed to blue.</p>
<div class="wa-time">10:30</div>
</div>
</div>
</div>
---
## What Designer Can Modify
| Category | Examples |
|----------|----------|
| **Styles** | Colors, layout, fonts, spacing |
| **HTML Pages** | Forms, lists, buttons, elements |
| **Database** | Add fields, create tables |
| **Tools** | Voice commands, chat triggers |
| **Schedulers** | Automated tasks, reports |
---
## Editing Styles
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Make the colors more modern, blue tones</p>
<div class="wa-time">14:20</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Updating styles.css:</p>
<p>Primary color: #2563eb</p>
<p>Secondary color: #3b82f6</p>
<p>Background: #f8fafc</p>
<p>Visual style updated.</p>
<div class="wa-time">14:20</div>
</div>
</div>
</div>
---
## Adding Form Fields
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Add an insurance field to the patient form</p>
<div class="wa-time">11:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Making two changes:</p>
<p><strong>1. tables.bas</strong> - new field:</p>
<p>insurance AS STRING</p>
<p><strong>2. patients.html</strong> - new input added</p>
<p>Insurance field added to form.</p>
<div class="wa-time">11:00</div>
</div>
</div>
</div>
---
## Creating Voice Commands
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Create a command to see today's appointments</p>
<div class="wa-time">09:15</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Creating .gbdialog/tools/todays-appointments.bas</p>
<p>Triggers: "today's appointments", "daily schedule"</p>
<p>Command created. Say "today's appointments" to use it.</p>
<div class="wa-time">09:15</div>
</div>
</div>
</div>
---
## Creating Schedulers
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Every day at 9am send reminders to today's patients</p>
<div class="wa-time">16:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Creating .gbdialog/schedulers/daily-reminder.bas</p>
<p>Schedule: Every day at 9:00 AM</p>
<p>Action: Send reminder to patients with appointments today</p>
<p>Scheduler configured.</p>
<div class="wa-time">16:00</div>
</div>
</div>
</div>
---
## Adding Database Fields
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Add SSN field to the patients table</p>
<div class="wa-time">10:45</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Updating tables.bas:</p>
<p>Adding: ssn AS STRING UNIQUE INDEX</p>
<p>Database synchronized.</p>
<p>Field available in all apps.</p>
<div class="wa-time">10:45</div>
</div>
</div>
</div>
---
## Context Awareness
Designer tracks your current location and correlates follow-up requests.
| Context | How It Is Used |
|---------|----------------|
| **Current app** | Edits apply to that app's files |
| **Current page** | Defaults edits to that file |
| **Recent changes** | Correlates follow-up requests |
| **Available tables** | Knows your data structure |
| **Existing tools** | Knows voice commands already created |
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Change the button to green</p>
<div class="wa-time">14:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Changing button in schedule.html to green.</p>
<p>Button updated.</p>
<div class="wa-time">14:30</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>And add a notes field</p>
<div class="wa-time">14:31</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Adding notes field to the same form.</p>
<p>Field added.</p>
<div class="wa-time">14:31</div>
</div>
</div>
</div>
---
## Handling Sensitive Information
When Designer needs API keys or credentials:
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Integrate with Stripe for payments</p>
<div class="wa-time">15:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>To integrate with Stripe, I need the API Key.</p>
<p>Do you want to provide it now or later?</p>
<div class="wa-time">15:00</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>Later</p>
<div class="wa-time">15:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Saved as pending item.</p>
<p>Pending: Stripe API Key</p>
<p>You can provide it in Settings, Pending Items.</p>
<p>Payment structure created. When you provide the key, it will work automatically.</p>
<div class="wa-time">15:01</div>
</div>
</div>
</div>
---
## Preview Before Changes
Designer shows what will change before applying destructive operations.
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Remove the email field from the form</p>
<div class="wa-time">11:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>I will remove the email field from patients.html.</p>
<p><strong>Note:</strong> The field will remain in the database. Existing data will not be lost.</p>
<p>Confirm?</p>
<div class="wa-time">11:30</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>Yes</p>
<div class="wa-time">11:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Field removed from form.</p>
<div class="wa-time">11:30</div>
</div>
</div>
</div>
---
## Safety Features
| Feature | Description |
|---------|-------------|
| Preview changes | Shows what will change before applying |
| Confirm destructive actions | Asks before deleting |
| Change history | All changes are logged |
| Undo support | Can undo recent changes |
---
## Limitations
| Limitation | Reason |
|------------|--------|
| Cannot delete entire app | Safety protection |
| Cannot access external systems without credentials | Security |
| Cannot modify system files | Isolation |
| Cannot execute arbitrary code | Security |
---
## Available Keywords
Designer uses GB BASIC keywords to implement changes:
| Category | Keywords |
|----------|----------|
| **Communication** | TALK, HEAR, SEND MAIL, SEND TEMPLATE |
| **Data** | FIND, SAVE, UPDATE, DELETE |
| **Automation** | SET SCHEDULE, ON CHANGE, ON EMAIL |
| **AI** | LLM, USE KB |
| **Web** | SCRAPE, GET, POST, RSS |
| **Memory** | SET BOT MEMORY, GET BOT MEMORY |
| **Control** | IF/THEN/ELSE, FOR EACH/NEXT, WHILE/WEND |
---
## Undoing Changes
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Undo the last change</p>
<div class="wa-time">12:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Last change: Removed email field from patients.html</p>
<p>Do you want to undo?</p>
<div class="wa-time">12:00</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>Yes</p>
<div class="wa-time">12:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Email field restored.</p>
<div class="wa-time">12:00</div>
</div>
</div>
</div>
---
## Tips for Better Results
### Be Specific
| Less Effective | More Effective |
|----------------|----------------|
| "improve the form" | "add email validation to the form" |
| "change the colors" | "change the main button to green" |
| "fix this" | "increase the font size in the table" |
### Combine Requests
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Add SSN field to patient form with mask and validation, and show it in the list too</p>
<div class="wa-time">10:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Making 3 changes:</p>
<p>1. tables.bas - new SSN field</p>
<p>2. patients.html - input with mask XXX-XX-XXXX</p>
<p>3. patients.html - SSN column in the table</p>
<p>All changes applied.</p>
<div class="wa-time">10:00</div>
</div>
</div>
</div>
---
## Next Steps
- [App Generation](./app-generation.md) — How apps are created
- [Task Workflow](./workflow.md) — How tasks are processed
- [Data Model](./data-model.md) — TABLE keyword reference

View file

@ -0,0 +1 @@
# DevChat

View file

@ -0,0 +1,248 @@
# Examples
Real-world applications built through natural conversation.
---
## Example 1: Cellphone Store CRM
**Request:** "Create a CRM for my cellphone store with customer tracking, inventory, sales, and repair status"
**Generated URL:** `/apps/cellphone-crm`
### Tables Created
| Table | Fields |
|-------|--------|
| `customers` | id, name, phone, email, address, notes |
| `products` | id, name, brand, model, price, cost, stock |
| `sales` | id, customer_id, product_id, quantity, total, date |
| `repairs` | id, customer_id, device, problem, status, price |
### Features
| Feature | Description |
|---------|-------------|
| Customer search | Find by name or phone |
| Inventory alerts | Low stock notifications |
| Sales tracking | Linked to customer and product |
| Repair board | Status workflow tracking |
| Daily summary | Sales report automation |
### Execution Steps
| Step | Task | Time |
|------|------|------|
| 1 | Create database tables | 15s |
| 2 | Generate customer management UI | 45s |
| 3 | Generate product inventory UI | 30s |
| 4 | Generate sales tracking UI | 40s |
| 5 | Generate repair status board | 50s |
| 6 | Add search and filters | 25s |
| **Total** | | **3m 25s** |
---
## Example 2: Restaurant Reservations
**Request:** "Build a reservation system for my restaurant with table management and waitlist"
**Generated URL:** `/apps/restaurant-reservations`
### Tables Created
| Table | Fields |
|-------|--------|
| `tables` | id, number, capacity, location, status |
| `reservations` | id, guest_name, phone, party_size, date, time, table_id, status |
| `waitlist` | id, guest_name, phone, party_size, added_at, estimated_wait |
### Features
| Feature | Description |
|---------|-------------|
| Table layout | Visual availability display |
| Calendar view | Reservation scheduling |
| Waitlist | Real-time queue management |
| SMS notifications | Guest alerts (if configured) |
| Daily bookings | Summary report |
---
## Example 3: Property Management
**Request:** "Create a system to manage rental properties with tenants, leases, and maintenance requests"
**Generated URL:** `/apps/property-manager`
### Tables Created
| Table | Fields |
|-------|--------|
| `properties` | id, address, type, bedrooms, bathrooms, rent, status |
| `tenants` | id, name, phone, email, emergency_contact |
| `leases` | id, property_id, tenant_id, start_date, end_date, rent, deposit |
| `maintenance` | id, property_id, tenant_id, issue, priority, status, assigned_to |
| `payments` | id, lease_id, amount, date, method, status |
### Features
| Feature | Description |
|---------|-------------|
| Property listing | Filters by type, status, rent |
| Tenant directory | With lease history |
| Maintenance tracking | Priority and status workflow |
| Payment tracking | Due date alerts |
| Lease reminders | Expiration notifications |
---
## Example 4: Gym Membership
**Request:** "Build a gym membership system with class scheduling and attendance tracking"
**Generated URL:** `/apps/gym-manager`
### Tables Created
| Table | Fields |
|-------|--------|
| `members` | id, name, phone, email, plan, start_date, expiry_date |
| `classes` | id, name, instructor, day, time, capacity, room |
| `enrollments` | id, member_id, class_id, enrolled_at |
| `attendance` | id, member_id, check_in, check_out |
| `payments` | id, member_id, amount, date, plan |
### Features
| Feature | Description |
|---------|-------------|
| Check-in/out | Member attendance tracking |
| Class schedule | With enrollment management |
| Attendance reports | Usage analytics |
| Expiry alerts | Membership renewal reminders |
| Revenue tracking | Payment summaries |
---
## Example 5: Event Planning
**Request:** "Create an event planning tool with guest lists, vendors, and budget tracking"
**Generated URL:** `/apps/event-planner`
### Tables Created
| Table | Fields |
|-------|--------|
| `events` | id, name, date, venue, budget, status |
| `guests` | id, event_id, name, email, rsvp_status, dietary_needs, table |
| `vendors` | id, event_id, name, service, contact, cost, status |
| `tasks` | id, event_id, task, assignee, due_date, status |
| `expenses` | id, event_id, category, description, amount, paid |
### Features
| Feature | Description |
|---------|-------------|
| Event dashboard | Countdown and overview |
| Guest list | RSVP tracking |
| Vendor management | Contracts and payments |
| Task checklist | Assignment and due dates |
| Budget tracking | Budget vs actual spending |
---
## Example 6: Medical Clinic
**Request:** "Build a patient management system for a small clinic with appointments and medical records"
**Generated URL:** `/apps/clinic-manager`
### Tables Created
| Table | Fields |
|-------|--------|
| `patients` | id, name, dob, phone, email, address, insurance |
| `appointments` | id, patient_id, doctor, date, time, reason, status |
| `records` | id, patient_id, date, diagnosis, treatment, notes, doctor |
| `prescriptions` | id, record_id, medication, dosage, duration |
### Features
| Feature | Description |
|---------|-------------|
| Patient search | With full history |
| Appointment calendar | Per doctor view |
| Medical records | Timeline per patient |
| Prescriptions | Medication tracking |
| Daily list | Appointments per doctor |
---
## Example 7: Inventory System
**Request:** "Simple inventory tracking with suppliers, purchase orders, and stock alerts"
**Generated URL:** `/apps/inventory`
### Tables Created
| Table | Fields |
|-------|--------|
| `products` | id, sku, name, category, quantity, min_stock, location |
| `suppliers` | id, name, contact, email, phone, address |
| `purchase_orders` | id, supplier_id, status, total, created_at |
| `order_items` | id, order_id, product_id, quantity, unit_price |
| `stock_movements` | id, product_id, type, quantity, reason, date |
### Features
| Feature | Description |
|---------|-------------|
| Product list | With stock levels |
| Low stock alerts | Dashboard notifications |
| Supplier directory | Contact management |
| Purchase orders | Creation and tracking |
| Stock history | Movement audit trail |
---
## Complexity Guide
| Complexity | Tables | Time | Example |
|------------|--------|------|---------|
| Simple | 1-2 | 1-2 min | Contact list, tracker |
| Medium | 3-5 | 3-5 min | CRM, basic inventory |
| Complex | 6-10 | 5-10 min | Full business management |
| Large | 10+ | 10+ min | ERP-style systems |
---
## Tips for Better Results
### Be Specific
| Less Effective | More Effective |
|----------------|----------------|
| "Business app" | "CRM for cellphone store with customers, products, sales, and repair tracking" |
| "Inventory system" | "Inventory system with low stock alerts when below 10 units" |
| "Track repairs" | "Repair tracking with statuses: received, diagnosing, repairing, ready, delivered" |
### Include Key Details
| Detail | Example |
|--------|---------|
| Entities | "customers, products, orders" |
| Relationships | "orders linked to customers" |
| Workflows | "status: pending, approved, shipped" |
| Automations | "daily report at 9am" |
| Alerts | "notify when stock below 10" |
---
## Next Steps
- [Task Workflow](./workflow.md) — How tasks execute
- [App Generation](./app-generation.md) — Technical details
- [Data Model](./data-model.md) — Table structure

View file

@ -0,0 +1,124 @@
# Task Workflow
From request to working application, the task workflow handles every step automatically.
![Task Workflow](../assets/chapter-17/task-workflow.svg)
---
## The Three Steps
| Step | What Happens |
|------|--------------|
| 1. **Describe** | You tell the bot what you want in plain language |
| 2. **Plan** | System analyzes and creates an execution plan |
| 3. **Execute** | Steps run automatically, app is delivered |
---
## Example Workflow
<div class="wa-chat">
<div class="wa-message user">
<div class="wa-bubble">
<p>Create a CRM for my store with customers, products, and sales</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Planning:</strong></p>
<p>Step 1: Create database tables</p>
<p>Step 2: Generate customer management UI</p>
<p>Step 3: Generate product inventory UI</p>
<p>Step 4: Generate sales tracking UI</p>
<p>Step 5: Create voice commands</p>
<div class="wa-time">10:30</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Done:</strong></p>
<p>customers table created</p>
<p>products table created</p>
<p>sales table created</p>
<p>App available at /apps/crm</p>
<div class="wa-time">10:31</div>
</div>
</div>
</div>
---
## Error Handling
When something goes wrong, the system asks what to do.
<div class="wa-chat">
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Error:</strong> Could not create chart component</p>
<p>Options: Retry, Skip, Cancel</p>
<div class="wa-time">10:32</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>Skip</p>
<div class="wa-time">10:32</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>Skipped chart component. Continuing with remaining steps.</p>
<div class="wa-time">10:32</div>
</div>
</div>
</div>
---
## Approval Requests
Some actions require confirmation before executing.
<div class="wa-chat">
<div class="wa-message bot">
<div class="wa-bubble">
<p><strong>Approval required:</strong></p>
<p>This action will send 50 emails to customers.</p>
<p>Confirm?</p>
<div class="wa-time">11:00</div>
</div>
</div>
<div class="wa-message user">
<div class="wa-bubble">
<p>Yes</p>
<div class="wa-time">11:00</div>
</div>
</div>
<div class="wa-message bot">
<div class="wa-bubble">
<p>50 emails sent successfully.</p>
<div class="wa-time">11:01</div>
</div>
</div>
</div>
---
## Actions Requiring Approval
| Action | Reason |
|--------|--------|
| Bulk email sends | Prevents accidental spam |
| Data deletion | Prevents data loss |
| External API calls | Cost and security |
| Schema changes | Database integrity |
---
## Next Steps
- [Designer Guide](./designer.md) — Edit apps through conversation
- [Examples](./examples.md) — Real-world applications

View file

@ -1,221 +0,0 @@
# Autonomous Tasks
> **From Intent to Application**
---
## What Are Autonomous Tasks?
Autonomous Tasks transform how applications are built. Instead of writing code manually, you describe what you want, and the system generates a complete working application.
**Example:**
> "I want to create a CRM for my cellphone store"
**Result:**
- A fully functional HTMX web application at `/apps/cellphone-crm`
- Database tables for `customers`, `products`, `sales`, `repairs`
- Forms, lists, filters, and reports - all working
- Connected to your bot for AI-assisted operations
---
## How It Works
```
┌─────────────────────────────────────────────────────────────────┐
│ 1. DESCRIBE │
│ "Create a CRM for my cellphone store with customer │
│ tracking, sales, and repair status" │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 2. PLAN │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Step 1 │ │ Step 2 │ │ Step 3 │ │
│ │ Create │→│ Generate │→│ Setup │ │
│ │ Tables │ │ UI │ │ Workflows │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 3. EXECUTE │
│ [████████████████░░░░░░░░░░] 60% - Generating UI... │
│ Step 2 of 3 • ETA: 2 minutes │
└─────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────┐
│ 4. DONE │
│ ✅ Application ready at /apps/cellphone-crm │
│ ✅ Tables created: customers, products, sales, repairs │
│ ✅ AI assistant connected │
└─────────────────────────────────────────────────────────────────┘
```
---
## The Stack
| Layer | Technology | What It Does |
|-------|------------|--------------|
| **Frontend** | HTMX | Dynamic UI without writing JavaScript |
| **Backend** | botserver | API, authentication, business logic |
| **Database** | PostgreSQL | Stores your application data |
| **Storage** | MinIO/S3 | Files, documents, uploads |
| **AI** | LLM | Generates the app, powers the assistant |
### No Middleware Needed
Generated apps talk directly to botserver:
```
┌─────────────────────┐ ┌─────────────────────┐
│ HTMX Frontend │──────│ botserver │
│ │ HTTP │ │
│ - Forms │◄────►│ - /api/db/table │
│ - Lists │ │ - /api/drive/... │
│ - Actions │ │ - /api/llm/... │
└─────────────────────┘ └─────────────────────┘
```
---
## Where Apps Live
Generated applications are stored in `.gbdrive/apps`:
```
mybot.gbai/
└── mybot.gbdrive/
└── apps/
└── cellphone-crm/
├── index.html # Main application
├── _assets/
│ ├── htmx.min.js
│ ├── app.js
│ └── styles.css
└── data/
└── schema.json # Table definitions
```
Access your app at: `https://your-bot.com/apps/cellphone-crm`
---
## Data Storage
### The `user_data` Virtual Table
Every app has access to a flexible data store through the `user_data` virtual table system. When your app needs a table like `customers`, botserver maps it to the underlying storage:
```
App request: POST /api/db/customers
botserver routes to: user_data table with namespace "cellphone-crm.customers"
PostgreSQL storage with proper indexing and relationships
```
### Your Tables Are Real
When you create an app that needs `customers`, `products`, and `sales` tables, they're created as proper database entities:
| Table | Fields | Purpose |
|-------|--------|---------|
| `customers` | id, name, phone, email, notes | Customer records |
| `products` | id, name, brand, model, price, stock | Inventory |
| `sales` | id, customer_id, product_id, date, amount | Transactions |
| `repairs` | id, customer_id, device, status, notes | Service tracking |
---
## Task Steps
Every task is broken into steps that are stored for:
1. **Continuation** - Resume later if interrupted
2. **Progress tracking** - See exactly where you are
3. **Debugging** - Understand what happened
4. **Learning** - Improve future generations
### Step Structure
```json
{
"task_id": "abc123",
"steps": [
{
"order": 1,
"name": "Create database tables",
"status": "completed",
"started_at": "2024-01-15T10:00:00Z",
"completed_at": "2024-01-15T10:00:15Z"
},
{
"order": 2,
"name": "Generate application UI",
"status": "running",
"started_at": "2024-01-15T10:00:16Z",
"progress": 60
},
{
"order": 3,
"name": "Configure workflows",
"status": "pending"
}
]
}
```
---
## Chapter Contents
- [Task Workflow](./workflow.md) - From intent to completion
- [App Generation](./app-generation.md) - How apps are created
- [Data Model](./data-model.md) - Tables and storage
- [Progress Tracking](./progress.md) - Monitoring and continuation
- [Examples](./examples.md) - Real-world autonomous tasks
---
## Quick Example
**You say:**
> "Create a CRM for my cellphone store with customers, sales tracking, and repair status"
**The system:**
1. **Analyzes your intent:**
- Type: CRM application
- Domain: Cellphone retail
- Entities: customers, products, sales, repairs
2. **Creates the plan:**
- Step 1: Create `customers`, `products`, `sales`, `repairs` tables
- Step 2: Generate HTMX application with forms and lists
- Step 3: Add search, filters, and status workflows
3. **Executes and reports:**
```
✅ Step 1: Tables created
⏳ Step 2: Generating UI... (60%)
⏸ Step 3: Waiting
```
4. **Delivers the app:**
- URL: `/apps/cellphone-crm`
- Features: Customer list, add customer form, sales tracking, repair status board
---
## See Also
- [CREATE SITE](../06-gbdialog/keyword-create-site.md) - The keyword behind app generation
- [.gbdrive Storage](../02-templates/gbdrive.md) - Where apps live
- [REST API](../10-rest/README.md) - The API your apps use
- [HTMX Architecture](../04-gbui/htmx-architecture.md) - Frontend patterns

View file

@ -1,373 +0,0 @@
# App Generation
> **HTMX Applications Connected to botserver**
---
## Overview
When you request an application, the system generates a complete HTMX frontend that communicates directly with botserver's API. No middleware, no separate backend - just HTML that talks to the API.
---
## The Generated Stack
```
┌─────────────────────────────────────────────────────────────────┐
│ Generated Application │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ index.html │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Lists │ │ Forms │ │ Actions │ │ Filters │ │ │
│ │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │
│ │ └───────────┬┴───────────┴┬───────────┘ │ │
│ │ │ HTMX │ │ │
│ └───────────────────┼─────────────┼──────────────────────┘ │
└──────────────────────┼─────────────┼──────────────────────────┘
│ │
▼ ▼
┌─────────────────────────────────────────────────────────────────┐
│ botserver API │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ /api/db/* │ │/api/drive/*│ │ /api/llm/* │ │
│ │ CRUD │ │ Files │ │ AI │ │
│ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘ │
│ └───────────────┼───────────────┘ │
│ ▼ │
│ PostgreSQL + MinIO │
└─────────────────────────────────────────────────────────────────┘
```
---
## Generated File Structure
When you create an app called "cellphone-crm", this is created:
```
.gbdrive/apps/cellphone-crm/
├── index.html # Main application
├── _assets/
│ ├── htmx.min.js # HTMX library
│ ├── app.js # App-specific JavaScript
│ └── styles.css # Styling
└── schema.json # Table definitions
```
---
## HTMX Patterns Used
### List View with Auto-Refresh
```html
<div id="customers"
hx-get="/api/db/customers"
hx-trigger="load, every 30s"
hx-swap="innerHTML">
Loading customers...
</div>
```
### Create Form
```html
<form hx-post="/api/db/customers"
hx-target="#customers"
hx-swap="afterbegin"
hx-indicator=".loading">
<input name="name" placeholder="Customer name" required>
<input name="phone" type="tel" placeholder="Phone">
<input name="email" type="email" placeholder="Email">
<button type="submit">
Add Customer
<span class="loading htmx-indicator">...</span>
</button>
</form>
```
### Edit in Place
```html
<tr hx-get="/api/db/customers/${id}/edit"
hx-trigger="dblclick"
hx-swap="outerHTML">
<td>${name}</td>
<td>${phone}</td>
<td>${email}</td>
</tr>
```
### Delete with Confirmation
```html
<button hx-delete="/api/db/customers/${id}"
hx-target="closest tr"
hx-swap="outerHTML swap:0.5s"
hx-confirm="Delete this customer?">
🗑️
</button>
```
### Search
```html
<input type="search"
name="q"
placeholder="Search customers..."
hx-get="/api/db/customers"
hx-trigger="keyup changed delay:300ms"
hx-target="#customers">
```
### Filter Dropdown
```html
<select name="status"
hx-get="/api/db/repairs"
hx-trigger="change"
hx-target="#repairs">
<option value="">All Status</option>
<option value="received">Received</option>
<option value="repairing">Repairing</option>
<option value="ready">Ready</option>
</select>
```
---
## API Endpoints Your App Uses
### App Context is Automatic
Your app runs inside botui (Suite). The botui proxy automatically:
1. Detects your app from the URL (`/apps/cellphone-crm/`)
2. Injects `X-App-Context: cellphone-crm` header
3. Forwards to botserver
**You don't need to do anything special** - just use normal HTMX:
```html
<!-- botui handles the app context automatically -->
<form hx-post="/api/db/customers">
<input name="name">
<button>Add</button>
</form>
```
### Endpoints
| HTMX Call | Endpoint | What It Does |
|-----------|----------|--------------|
| `hx-get="/api/db/customers"` | GET | List all customers |
| `hx-get="/api/db/customers?q=john"` | GET | Search customers |
| `hx-post="/api/db/customers"` | POST | Create customer |
| `hx-put="/api/db/customers/123"` | PUT | Update customer |
| `hx-delete="/api/db/customers/123"` | DELETE | Delete customer |
### Query Parameters
| Parameter | Example | Purpose |
|-----------|---------|---------|
| `q` | `?q=john` | Full-text search |
| `sort` | `?sort=created_at` | Sort field |
| `order` | `?order=desc` | Sort direction |
| `limit` | `?limit=20` | Results per page |
| `offset` | `?offset=40` | Pagination |
| `{field}` | `?status=active` | Filter by field |
---
## Example: Cellphone CRM
For a cellphone store CRM, the generated app includes:
### Customer List
```html
<section id="customers-section">
<header>
<h2>Customers</h2>
<input type="search"
hx-get="/api/db/customers"
hx-trigger="keyup changed delay:300ms"
hx-target="#customer-list"
placeholder="Search by name or phone...">
<button onclick="openModal('add-customer')">+ Add Customer</button>
</header>
<table>
<thead>
<tr>
<th>Name</th>
<th>Phone</th>
<th>Email</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="customer-list"
hx-get="/api/db/customers"
hx-trigger="load">
</tbody>
</table>
</section>
```
### Sales Form
```html
<form id="new-sale"
hx-post="/api/db/sales"
hx-target="#recent-sales"
hx-swap="afterbegin">
<select name="customer_id" required
hx-get="/api/db/customers"
hx-trigger="load"
hx-target="this"
hx-swap="innerHTML">
<option>Loading customers...</option>
</select>
<select name="product_id" required
hx-get="/api/db/products?stock_gt=0"
hx-trigger="load"
hx-target="this"
hx-swap="innerHTML">
<option>Loading products...</option>
</select>
<input name="quantity" type="number" min="1" value="1">
<button type="submit">Complete Sale</button>
</form>
```
### Repair Status Board
```html
<div class="kanban-board">
<div class="column" data-status="received">
<h3>Received</h3>
<div hx-get="/api/db/repairs?status=received"
hx-trigger="load, every 60s">
</div>
</div>
<div class="column" data-status="diagnosing">
<h3>Diagnosing</h3>
<div hx-get="/api/db/repairs?status=diagnosing"
hx-trigger="load, every 60s">
</div>
</div>
<div class="column" data-status="repairing">
<h3>Repairing</h3>
<div hx-get="/api/db/repairs?status=repairing"
hx-trigger="load, every 60s">
</div>
</div>
<div class="column" data-status="ready">
<h3>Ready for Pickup</h3>
<div hx-get="/api/db/repairs?status=ready"
hx-trigger="load, every 60s">
</div>
</div>
</div>
```
---
## Styling
Generated apps use CSS custom properties for easy theming:
```css
:root {
--primary: #0ea5e9;
--success: #22c55e;
--warning: #f59e0b;
--danger: #ef4444;
--bg: #ffffff;
--text: #1e293b;
--border: #e2e8f0;
--radius: 8px;
}
/* Dark mode automatic */
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f172a;
--text: #f1f5f9;
--border: #334155;
}
}
```
---
## JavaScript Helpers
`app.js` includes utilities for common operations:
```javascript
// Toast notifications
function toast(message, type = 'info') {
// Shows a temporary notification
}
// Modal management
function openModal(id) { ... }
function closeModal(id) { ... }
// HTMX event handling
document.body.addEventListener('htmx:afterSwap', (e) => {
// Update UI after data changes
});
document.body.addEventListener('htmx:responseError', (e) => {
toast('Error: ' + e.detail.error, 'error');
});
```
---
## Bot Integration
Your generated app can talk to the bot for AI features:
```html
<!-- AI-assisted customer lookup -->
<form hx-post="/api/llm/complete"
hx-target="#ai-result">
<input name="prompt"
placeholder="Find customers who bought iPhones last month">
<button type="submit">🤖 Ask AI</button>
</form>
<!-- AI generates the query, executes it, returns results -->
<div id="ai-result"></div>
```
---
## Customization After Generation
Generated apps can be modified:
1. **Edit directly** - Modify `index.html` in `.gbdrive/apps/`
2. **Use Designer** - Visual editor in Suite
3. **Regenerate** - Ask for changes, system updates the app
---
## See Also
- [Data Model](./data-model.md) - How tables are created
- [Progress Tracking](./progress.md) - Monitor generation
- [HTMX Architecture](../04-gbui/htmx-architecture.md) - Frontend patterns
- [REST API](../10-rest/README.md) - API reference

View file

@ -1,398 +0,0 @@
# Data Model
> **Tables Created for Your Application**
---
## Overview
When you create an autonomous task that generates an application, the system automatically creates the database tables needed to store your data. These tables are real PostgreSQL tables with proper types, indexes, and relationships.
---
## The user_data System
Under the hood, all application data is managed through the `user_data` virtual table system. This provides:
- **Namespacing** - Each app's tables are isolated
- **Multi-tenancy** - Your data is separate from other users
- **Flexibility** - Tables can be created dynamically
- **Security** - Access control per table
### How It Works
Apps run inside botui (Suite), which proxies all API calls to botserver. The app context flows automatically:
```
┌─────────────────────────────────────────────────────────────┐
│ botui (Suite) │
│ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Your App: /apps/cellphone-crm/ │ │
│ │ │ │
│ │ <form hx-post="/api/db/customers"> │ │
│ │ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ botui proxy │ │
│ │ - Adds X-App-Context: cellphone-crm │ │
│ │ - Forwards to botserver │ │
│ └───────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ botserver │
│ │
│ POST /api/db/customers │
│ X-App-Context: cellphone-crm │
│ │ │
│ ▼ │
│ Routes to: user_data WHERE app='cellphone-crm' │
│ AND table='customers' │
└─────────────────────────────────────────────────────────────┘
```
### App Context Detection
botui proxy determines the app from the request URL and injects the `X-App-Context` header:
| Request From | App Context |
|--------------|-------------|
| `/apps/cellphone-crm/*` | `cellphone-crm` |
| `/apps/inventory/*` | `inventory` |
| Suite main (no app) | `default` |
### Generated HTMX (No Special Headers Needed)
```html
<!-- Your app just uses normal HTMX -->
<form hx-post="/api/db/customers">
<input name="name">
<button>Add</button>
</form>
<!-- botui proxy automatically adds X-App-Context -->
```
### For External API Clients
```bash
# Must include X-App-Context header
curl -X POST https://bot.example.com/api/db/customers \
-H "X-App-Context: cellphone-crm" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name": "John"}'
```
---
## Table Creation
When you describe your app, the system infers the tables needed:
**Your description:**
> "CRM for cellphone store with customer tracking, sales, and repairs"
**Tables created:**
| Table | Purpose |
|-------|---------|
| `customers` | Customer records |
| `products` | Inventory items |
| `sales` | Transaction records |
| `repairs` | Service tickets |
---
## Generated Schema
### customers
```sql
CREATE TABLE customers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
phone TEXT,
email TEXT,
address TEXT,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_customers_name ON customers USING gin(name gin_trgm_ops);
CREATE INDEX idx_customers_phone ON customers(phone);
```
### products
```sql
CREATE TABLE products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
brand TEXT,
model TEXT,
price DECIMAL(10,2),
cost DECIMAL(10,2),
stock INTEGER DEFAULT 0,
min_stock INTEGER DEFAULT 5,
category TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_products_brand ON products(brand);
CREATE INDEX idx_products_category ON products(category);
```
### sales
```sql
CREATE TABLE sales (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID REFERENCES customers(id),
product_id UUID REFERENCES products(id),
quantity INTEGER NOT NULL DEFAULT 1,
unit_price DECIMAL(10,2),
total DECIMAL(10,2),
payment TEXT,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_sales_customer ON sales(customer_id);
CREATE INDEX idx_sales_date ON sales(created_at);
```
### repairs
```sql
CREATE TABLE repairs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
customer_id UUID REFERENCES customers(id),
device TEXT NOT NULL,
brand TEXT,
model TEXT,
problem TEXT,
diagnosis TEXT,
solution TEXT,
status TEXT DEFAULT 'received',
price DECIMAL(10,2),
received_at TIMESTAMPTZ DEFAULT NOW(),
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_repairs_customer ON repairs(customer_id);
CREATE INDEX idx_repairs_status ON repairs(status);
```
---
## Data Types
The system automatically selects appropriate types:
| Field Pattern | SQL Type | Example |
|---------------|----------|---------|
| `name`, `title`, `description` | TEXT | Customer name |
| `email` | TEXT (validated) | john@example.com |
| `phone` | TEXT | +1-555-0123 |
| `price`, `cost`, `amount`, `total` | DECIMAL(10,2) | 299.99 |
| `quantity`, `stock`, `count` | INTEGER | 10 |
| `date`, `_at` suffix | TIMESTAMPTZ | 2024-01-15T10:30:00Z |
| `is_`, `has_` prefix | BOOLEAN | true |
| `id` | UUID | a1b2c3d4-... |
| `_id` suffix | UUID (FK) | References another table |
---
## Relationships
Foreign keys are created automatically when fields end with `_id`:
```
customers
├──< sales (customer_id customers.id)
└──< repairs (customer_id customers.id)
products
└──< sales (product_id products.id)
```
---
## Accessing Data
### From Your App (HTMX)
```html
<!-- List all customers -->
<div hx-get="/api/db/customers" hx-trigger="load">
<!-- Get one customer -->
<div hx-get="/api/db/customers/abc123">
<!-- Create customer -->
<form hx-post="/api/db/customers">
<!-- Update customer -->
<form hx-put="/api/db/customers/abc123">
<!-- Delete customer -->
<button hx-delete="/api/db/customers/abc123">
```
### From Chat
> "Show me all customers who bought an iPhone"
The bot queries the database and responds with results.
### API Response Format
```json
{
"data": [
{
"id": "abc123",
"name": "John Smith",
"phone": "+1-555-0123",
"email": "john@example.com",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total": 150,
"limit": 20,
"offset": 0
}
```
---
## Filtering and Querying
### Simple Filters
```
GET /api/db/repairs?status=ready
GET /api/db/products?brand=Apple
GET /api/db/sales?customer_id=abc123
```
### Search
```
GET /api/db/customers?q=john
```
Searches across all text fields.
### Sorting
```
GET /api/db/sales?sort=created_at&order=desc
```
### Pagination
```
GET /api/db/customers?limit=20&offset=40
```
### Comparison Operators
```
GET /api/db/products?price_gt=100 # Greater than
GET /api/db/products?stock_lt=5 # Less than
GET /api/db/products?stock_gte=10 # Greater or equal
GET /api/db/repairs?status_ne=completed # Not equal
```
---
## Schema Storage
Table definitions are stored in `schema.json`:
```json
{
"app": "cellphone-crm",
"tables": {
"customers": {
"columns": {
"id": {"type": "uuid", "primary": true},
"name": {"type": "text", "required": true},
"phone": {"type": "text"},
"email": {"type": "text"}
},
"indexes": ["name", "phone"]
},
"products": {
"columns": {
"id": {"type": "uuid", "primary": true},
"name": {"type": "text", "required": true},
"price": {"type": "decimal"},
"stock": {"type": "integer", "default": 0}
}
}
},
"relationships": [
{"from": "sales.customer_id", "to": "customers.id"},
{"from": "sales.product_id", "to": "products.id"},
{"from": "repairs.customer_id", "to": "customers.id"}
]
}
```
---
## Adding Tables Later
You can ask to add tables to an existing app:
> "Add a suppliers table to my cellphone CRM"
The system will:
1. Create the `suppliers` table
2. Update `schema.json`
3. Add UI elements if requested
---
## Data Import
Import existing data via:
### CSV Upload
```
Upload suppliers.csv to /apps/cellphone-crm/import
```
### API
```bash
curl -X POST /api/db/customers/import \
-H "Content-Type: text/csv" \
--data-binary @customers.csv
```
### Chat
> "Import customers from the Excel file I uploaded"
---
## See Also
- [App Generation](./app-generation.md) - How apps are created
- [REST API](../10-rest/README.md) - Full API reference
- [Storage API](../10-rest/storage-api.md) - File storage

View file

@ -1,269 +0,0 @@
# Examples
> **Real-World Autonomous Tasks**
---
## Example 1: Cellphone Store CRM
### The Request
> "Create a CRM for my cellphone store with customer tracking, inventory, sales, and repair status"
### Generated Application
**URL:** `/apps/cellphone-crm`
**Tables Created:**
| Table | Fields |
|-------|--------|
| `customers` | id, name, phone, email, address, notes |
| `products` | id, name, brand, model, price, cost, stock |
| `sales` | id, customer_id, product_id, quantity, total, date |
| `repairs` | id, customer_id, device, problem, status, price |
**Features:**
- Customer list with search by name or phone
- Product inventory with low stock alerts
- Sales entry linked to customer and product
- Repair status board (Kanban style)
- Daily sales summary
### Execution
```
Step 1: Create database tables .................. ✓ (15s)
Step 2: Generate customer management UI ........ ✓ (45s)
Step 3: Generate product inventory UI .......... ✓ (30s)
Step 4: Generate sales tracking UI ............. ✓ (40s)
Step 5: Generate repair status board ........... ✓ (50s)
Step 6: Add search and filters ................. ✓ (25s)
Total time: 3 minutes 25 seconds
```
---
## Example 2: Restaurant Reservations
### The Request
> "Build a reservation system for my restaurant with table management and waitlist"
### Generated Application
**URL:** `/apps/restaurant-reservations`
**Tables Created:**
| Table | Fields |
|-------|--------|
| `tables` | id, number, capacity, location, status |
| `reservations` | id, guest_name, phone, party_size, date, time, table_id, status |
| `waitlist` | id, guest_name, phone, party_size, added_at, estimated_wait |
**Features:**
- Visual table layout with availability
- Reservation calendar view
- Real-time waitlist management
- SMS notification integration (if configured)
- Daily booking summary
---
## Example 3: Property Management
### The Request
> "Create a system to manage rental properties with tenants, leases, and maintenance requests"
### Generated Application
**URL:** `/apps/property-manager`
**Tables Created:**
| Table | Fields |
|-------|--------|
| `properties` | id, address, type, bedrooms, bathrooms, rent, status |
| `tenants` | id, name, phone, email, emergency_contact |
| `leases` | id, property_id, tenant_id, start_date, end_date, rent, deposit |
| `maintenance` | id, property_id, tenant_id, issue, priority, status, assigned_to |
| `payments` | id, lease_id, amount, date, method, status |
**Features:**
- Property listing with filters
- Tenant directory with lease history
- Maintenance request tracking (priority + status)
- Payment tracking with due date alerts
- Lease expiration reminders
---
## Example 4: Gym Membership
### The Request
> "Build a gym membership system with class scheduling and attendance tracking"
### Generated Application
**URL:** `/apps/gym-manager`
**Tables Created:**
| Table | Fields |
|-------|--------|
| `members` | id, name, phone, email, plan, start_date, expiry_date |
| `classes` | id, name, instructor, day, time, capacity, room |
| `enrollments` | id, member_id, class_id, enrolled_at |
| `attendance` | id, member_id, check_in, check_out |
| `payments` | id, member_id, amount, date, plan |
**Features:**
- Member check-in/check-out
- Class schedule with enrollment
- Attendance reports
- Membership expiry alerts
- Revenue tracking
---
## Example 5: Event Planning
### The Request
> "Create an event planning tool with guest lists, vendors, and budget tracking"
### Generated Application
**URL:** `/apps/event-planner`
**Tables Created:**
| Table | Fields |
|-------|--------|
| `events` | id, name, date, venue, budget, status |
| `guests` | id, event_id, name, email, rsvp_status, dietary_needs, table |
| `vendors` | id, event_id, name, service, contact, cost, status |
| `tasks` | id, event_id, task, assignee, due_date, status |
| `expenses` | id, event_id, category, description, amount, paid |
**Features:**
- Event dashboard with countdown
- Guest list with RSVP tracking
- Vendor management
- Task checklist
- Budget vs actual spending
---
## Example 6: Medical Clinic
### The Request
> "Build a patient management system for a small clinic with appointments and medical records"
### Generated Application
**URL:** `/apps/clinic-manager`
**Tables Created:**
| Table | Fields |
|-------|--------|
| `patients` | id, name, dob, phone, email, address, insurance |
| `appointments` | id, patient_id, doctor, date, time, reason, status |
| `records` | id, patient_id, date, diagnosis, treatment, notes, doctor |
| `prescriptions` | id, record_id, medication, dosage, duration |
**Features:**
- Patient search and history
- Appointment calendar
- Medical record timeline per patient
- Prescription tracking
- Daily appointment list per doctor
---
## Example 7: Inventory for Small Business
### The Request
> "Simple inventory tracking with suppliers, purchase orders, and stock alerts"
### Generated Application
**URL:** `/apps/inventory`
**Tables Created:**
| Table | Fields |
|-------|--------|
| `products` | id, sku, name, category, quantity, min_stock, location |
| `suppliers` | id, name, contact, email, phone, address |
| `purchase_orders` | id, supplier_id, status, total, created_at |
| `order_items` | id, order_id, product_id, quantity, unit_price |
| `stock_movements` | id, product_id, type, quantity, reason, date |
**Features:**
- Product list with stock levels
- Low stock alerts dashboard
- Supplier directory
- Purchase order creation
- Stock movement history
---
## Task Complexity Guide
| Complexity | Tables | Time | Example |
|------------|--------|------|---------|
| **Simple** | 1-2 | 1-2 min | Contact list, simple tracker |
| **Medium** | 3-5 | 3-5 min | CRM, basic inventory |
| **Complex** | 6-10 | 5-10 min | Full business management |
| **Large** | 10+ | 10+ min | ERP-style systems |
---
## Tips for Good Results
### Be Specific
✅ **Good:**
> "CRM for cellphone store with customers, products, sales, and repair tracking with status workflow"
❌ **Vague:**
> "Business app"
### Mention Key Features
✅ **Good:**
> "Inventory system with low stock alerts when below 10 units"
❌ **Missing detail:**
> "Inventory system"
### Include Workflows
✅ **Good:**
> "Repair tracking with statuses: received, diagnosing, repairing, ready, delivered"
❌ **No workflow:**
> "Track repairs"
---
## See Also
- [Task Workflow](./workflow.md) - How tasks are processed
- [App Generation](./app-generation.md) - Technical details
- [Data Model](./data-model.md) - Table structure

View file

@ -1,328 +0,0 @@
# Progress Tracking
> **Know Where Your Task Is**
---
## Overview
Every autonomous task shows real-time progress so you always know:
- What step is running
- How far along it is
- How much time remains
- If anything needs your attention
---
## The Progress View
```
┌────────────────────────────────────────────────────────────────┐
│ Cellphone Store CRM │
│ │
│ [████████████████████░░░░░░░░░░] 65% │
│ │
│ Step 2 of 4: Generate application UI │
│ ├─ Customer list view ✓ │
│ ├─ Product list view ✓ │
│ ├─ Sales form ◐ (in progress) │
│ └─ Repair board ○ (pending) │
│ │
│ Started: 2 min ago │
│ ETA: 3 min remaining │
│ │
│ [Pause] [Cancel] │
└────────────────────────────────────────────────────────────────┘
```
---
## Progress Indicators
| Symbol | Meaning |
|--------|---------|
| ✓ | Completed |
| ◐ | In progress |
| ○ | Pending |
| ⚠ | Needs attention |
| ✕ | Failed |
| ⏸ | Paused |
---
## Step States
Each step goes through these states:
```
pending → running → completed
↘ failed
↘ skipped
```
### State Details
| State | Description | Action |
|-------|-------------|--------|
| `pending` | Waiting to start | None needed |
| `running` | Currently executing | Monitor progress |
| `completed` | Successfully finished | None needed |
| `failed` | Encountered error | Review and retry/skip |
| `skipped` | Intentionally bypassed | None needed |
| `paused` | Waiting for resume | Click Resume |
| `approval` | Needs your approval | Approve or reject |
---
## Real-Time Updates
Progress updates via WebSocket:
```javascript
// Connect to task updates
const ws = new WebSocket('/ws/tasks');
ws.onmessage = (event) => {
const update = JSON.parse(event.data);
switch (update.type) {
case 'progress':
// Update progress bar
updateProgress(update.percent);
break;
case 'step_complete':
// Mark step as done
markStepComplete(update.step);
break;
case 'approval_needed':
// Show approval dialog
showApproval(update.approval);
break;
case 'task_complete':
// Show completion
showComplete(update.result);
break;
}
};
```
---
## Stored Progress
Progress is persisted to the database so you can:
### Resume After Interruption
If you close your browser or lose connection:
1. Task continues running on the server
2. When you return, progress is restored
3. You see exactly where it is
### Continue Later
If you pause a task:
1. Current state is saved
2. Come back anytime
3. Click Resume to continue from the exact point
### Review History
```sql
-- task_progress table
task_id | step | percent | status | updated_at
----------|---------|---------|-----------|--------------------
abc123 | 1 | 100 | completed | 2024-01-15 10:00:15
abc123 | 2 | 65 | running | 2024-01-15 10:02:30
abc123 | 3 | 0 | pending | NULL
abc123 | 4 | 0 | pending | NULL
```
---
## Progress API
### Get Task Progress
```http
GET /api/tasks/{task_id}/progress
```
**Response:**
```json
{
"task_id": "abc123",
"title": "Cellphone Store CRM",
"status": "running",
"progress": 65,
"current_step": 2,
"total_steps": 4,
"started_at": "2024-01-15T10:00:00Z",
"eta_seconds": 180,
"steps": [
{
"order": 1,
"name": "Create database tables",
"status": "completed",
"progress": 100,
"duration_ms": 15000
},
{
"order": 2,
"name": "Generate application UI",
"status": "running",
"progress": 65,
"substeps": [
{"name": "Customer list", "done": true},
{"name": "Product list", "done": true},
{"name": "Sales form", "done": false},
{"name": "Repair board", "done": false}
]
},
{
"order": 3,
"name": "Add search and filters",
"status": "pending",
"progress": 0
},
{
"order": 4,
"name": "Configure workflows",
"status": "pending",
"progress": 0
}
]
}
```
### Subscribe to Updates
```http
WS /ws/tasks/{task_id}
```
Receives real-time progress updates.
---
## Progress in Chat
Ask your bot about task progress:
> "How's my CRM task going?"
**Bot response:**
```
📊 Your Cellphone Store CRM task is 65% complete.
Currently: Generating application UI
- ✓ Customer list view
- ✓ Product list view
- ⏳ Sales form (in progress)
- ⏳ Repair board
ETA: About 3 minutes remaining.
```
---
## Notifications
Get notified when:
| Event | Notification |
|-------|--------------|
| Task starts | "Your CRM task has started" |
| Step completes | "Step 1 complete: Database created" |
| Approval needed | "⚠️ Approval required for Step 3" |
| Task completes | "✅ Your CRM is ready!" |
| Task fails | "❌ Task failed at Step 2" |
### Notification Channels
- **Browser** - Desktop notifications
- **Email** - For long-running tasks
- **Chat** - Bot sends you updates
- **Mobile** - Push notifications (if app installed)
---
## Time Estimates
The system estimates remaining time based on:
1. **Historical data** - How long similar steps took before
2. **Current progress** - How fast the current step is moving
3. **Complexity** - More complex apps take longer
### Estimate Accuracy
| Task Complexity | Estimate Accuracy |
|-----------------|-------------------|
| Simple (1-2 tables) | ±20% |
| Medium (3-5 tables) | ±30% |
| Complex (6+ tables) | ±50% |
---
## Handling Slow Tasks
If a task is taking longer than expected:
### Check Progress
```
"Status of my CRM task"
```
### See Detailed Logs
```
"Show logs for my CRM task"
```
### Cancel and Retry
```
"Cancel my CRM task and start over"
```
---
## Progress Best Practices
### Monitor Long Tasks
For tasks over 10 minutes:
- Enable email notifications
- Check in periodically
- Have fallback plans
### Pause Before Leaving
If you need to leave:
- Pause the task
- It saves state
- Resume when ready
### Review Failed Steps
When a step fails:
1. Check the error message
2. Understand what went wrong
3. Retry, skip, or modify
---
## See Also
- [Task Workflow](./workflow.md) - The complete task flow
- [App Generation](./app-generation.md) - What gets generated
- [Examples](./examples.md) - Real task examples

View file

@ -1,283 +0,0 @@
# Task Workflow
> **From Intent to Working Application**
---
## The Four Phases
Every autonomous task goes through four phases:
```
DESCRIBE → PLAN → EXECUTE → DELIVER
```
---
## Phase 1: Describe
You describe what you want in plain language:
> "Create a CRM for my cellphone store"
The system extracts:
| Element | Extracted Value |
|---------|-----------------|
| **Action** | Create application |
| **Type** | CRM |
| **Domain** | Cellphone retail |
| **Implied entities** | customers, products, sales |
### Good Descriptions
| ✅ Good | ❌ Too Vague |
|---------|--------------|
| "CRM for cellphone store with customer tracking and repair status" | "Make an app" |
| "Sales dashboard showing daily revenue and top products" | "Dashboard" |
| "Inventory system with stock alerts when below 10 units" | "Track stuff" |
### Adding Context
Be specific about your needs:
```
"Create a CRM for my cellphone store with:
- Customer list with name, phone, email
- Product inventory with brand, model, price, stock
- Sales tracking linked to customers and products
- Repair status board (received, diagnosing, repairing, ready, delivered)
- Search by customer name or phone number"
```
---
## Phase 2: Plan
The system creates an execution plan:
```
┌────────────────────────────────────────────────────────────────┐
│ TASK: Cellphone Store CRM │
│ Confidence: 92% | Risk: Low | ETA: 5 minutes │
├────────────────────────────────────────────────────────────────┤
│ │
│ Step 1: Create database tables [CRITICAL] │
│ → customers, products, sales, repairs │
│ │
│ Step 2: Generate application UI [HIGH] │
│ → List views, forms, navigation │
│ │
│ Step 3: Add search and filters [MEDIUM] │
│ → Name search, status filters │
│ │
│ Step 4: Configure repair workflow [MEDIUM] │
│ → Status transitions, notifications │
│ │
└────────────────────────────────────────────────────────────────┘
```
### Plan Review
Before execution, you can:
- **Accept** - Proceed with the plan
- **Modify** - Adjust steps or requirements
- **Cancel** - Discard and start over
### Step Priorities
| Priority | Meaning |
|----------|---------|
| **CRITICAL** | Must succeed for app to work |
| **HIGH** | Core functionality |
| **MEDIUM** | Important features |
| **LOW** | Nice to have |
---
## Phase 3: Execute
The system executes each step:
```
[████████████████████░░░░░░░░░░] 65%
Step 2 of 4: Generate application UI
├─ Creating customer list view... ✓
├─ Creating product list view... ✓
├─ Creating sales form...
└─ Remaining: repair board, navigation
ETA: 2 minutes
```
### Execution Modes
| Mode | Behavior | Best For |
|------|----------|----------|
| **Automatic** | Runs all steps without stopping | Trusted, simple tasks |
| **Supervised** | Pauses before each step | Learning, complex tasks |
| **Dry Run** | Shows what would happen | Testing, verification |
### Pause and Resume
Tasks can be paused at any time:
```
[PAUSED] Step 2 of 4: Generate application UI
Progress saved. Resume anytime with:
→ Click "Resume" in Tasks
→ Say "continue my CRM task"
```
When you resume, execution continues from exactly where it stopped.
---
## Phase 4: Deliver
When complete, you receive:
```
┌────────────────────────────────────────────────────────────────┐
│ ✅ TASK COMPLETE │
├────────────────────────────────────────────────────────────────┤
│ │
│ Application: Cellphone Store CRM │
│ URL: /apps/cellphone-crm │
│ │
│ Created: │
│ 📋 4 database tables (customers, products, sales, repairs) │
│ 📱 5 views (lists + forms) │
│ 🔍 Search by name, phone, status │
│ 📊 Repair status workflow │
│ │
│ [Open App] [View Details] [Create Another] │
│ │
└────────────────────────────────────────────────────────────────┘
```
---
## Stored Steps
Every step is stored in the database:
```sql
-- task_steps table
task_id | step_order | name | status | progress
------------|------------|-------------------------|-----------|----------
abc123 | 1 | Create database tables | completed | 100
abc123 | 2 | Generate application UI | completed | 100
abc123 | 3 | Add search and filters | completed | 100
abc123 | 4 | Configure repair flow | completed | 100
```
### Why Store Steps?
1. **Resume interrupted tasks** - Power outage? Network issue? Just continue.
2. **Track progress** - Know exactly where a task is
3. **Debug failures** - See which step failed and why
4. **Audit trail** - Record of what was done
---
## Error Handling
When a step fails:
```
[ERROR] Step 3: Add search and filters
Error: Could not create full-text index on 'customers' table
Reason: Column 'notes' exceeds maximum indexable length
Options:
[Retry] - Try the step again
[Skip] - Continue without this feature
[Modify] - Change the approach
[Cancel] - Stop the task
```
### Automatic Recovery
For transient errors (network timeouts, temporary unavailability), the system automatically retries up to 3 times with exponential backoff.
---
## Approvals
High-impact steps may require approval:
```
┌────────────────────────────────────────────────────────────────┐
│ ⚠️ APPROVAL REQUIRED │
├────────────────────────────────────────────────────────────────┤
│ │
│ Step: Create database tables │
│ │
│ This will create 4 new tables: │
│ • customers (6 columns) │
│ • products (7 columns) │
│ • sales (5 columns) │
│ • repairs (8 columns) │
│ │
│ Impact: Database storage increase ~1MB │
│ │
│ [Approve] [Modify] [Reject] │
│ │
└────────────────────────────────────────────────────────────────┘
```
### What Requires Approval?
| Action | Default |
|--------|---------|
| Create tables | Auto-approve |
| Delete data | Requires approval |
| External API calls | Configurable |
| Email sending | Requires approval |
| File deletion | Requires approval |
---
## Task States
```
┌─────────────┐
│ DRAFT │ Task created, not started
└──────┬──────┘
┌──────▼──────┐
│ PLANNING │ Generating execution plan
└──────┬──────┘
┌──────▼──────┐
│ READY │ Plan complete, awaiting start
└──────┬──────┘
┌────────────┼────────────┐
│ │ │
┌──────▼──────┐ ┌───▼───┐ ┌─────▼─────┐
│ RUNNING │ │PAUSED │ │ APPROVAL │
└──────┬──────┘ └───┬───┘ │ PENDING │
│ │ └─────┬─────┘
│ │ │
└────────────┼───────────┘
┌────────────┼────────────┐
│ │ │
┌──────▼──────┐ ┌───▼───┐ ┌─────▼─────┐
│ COMPLETED │ │FAILED │ │ CANCELLED │
└─────────────┘ └───────┘ └───────────┘
```
---
## See Also
- [App Generation](./app-generation.md) - How apps are built
- [Progress Tracking](./progress.md) - Monitoring your tasks
- [Examples](./examples.md) - Real-world workflows

View file

@ -380,12 +380,12 @@
# Part XVI - Autonomous Tasks
- [Chapter 17: Autonomous Tasks](./21-autonomous-tasks/README.md)
- [Task Workflow](./21-autonomous-tasks/workflow.md)
- [App Generation](./21-autonomous-tasks/app-generation.md)
- [Data Model](./21-autonomous-tasks/data-model.md)
- [Progress Tracking](./21-autonomous-tasks/progress.md)
- [Examples](./21-autonomous-tasks/examples.md)
- [Chapter 17: Autonomous Tasks](./17-autonomous-tasks/README.md)
- [Task Workflow](./17-autonomous-tasks/workflow.md)
- [App Generation](./17-autonomous-tasks/app-generation.md)
- [Data Model](./17-autonomous-tasks/data-model.md)
- [Examples](./17-autonomous-tasks/examples.md)
- [Designer](./17-autonomous-tasks/designer.md)
# Appendices

View file

@ -0,0 +1,199 @@
<svg width="900" height="520" xmlns="http://www.w3.org/2000/svg">
<defs>
<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="pinkGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#EC4899;stop-opacity:1" />
<stop offset="100%" style="stop-color:#F472B6;stop-opacity:1" />
</linearGradient>
<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>
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
<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>
<marker id="arrowDown" markerWidth="10" markerHeight="10" refX="3" refY="9" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L6,0 L3,9 z" fill="#8B5CF6"/>
</marker>
</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="900" height="520" fill="#FAFBFC"/>
<rect width="900" height="520" fill="url(#dots)"/>
<!-- Title -->
<text x="450" y="35" text-anchor="middle" font-size="20" font-weight="600" class="title-text">App Generation Flow</text>
<text x="450" y="55" text-anchor="middle" font-size="12" class="secondary-text">From Natural Language Request to Complete Application</text>
<!-- Step 1: User Request -->
<g transform="translate(40, 80)">
<rect width="250" height="120" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="250" height="40" rx="12" fill="url(#primaryGrad)"/>
<rect y="28" width="250" height="12" fill="url(#primaryGrad)"/>
<text x="125" y="28" text-anchor="middle" font-size="13" font-weight="600" class="white-text">1. User Describes App</text>
<!-- Chat bubble -->
<rect x="15" y="52" width="220" height="55" rx="8" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="125" y="72" text-anchor="middle" font-size="9" class="main-text">"cria um CRM para minha loja</text>
<text x="125" y="85" text-anchor="middle" font-size="9" class="main-text">com clientes, produtos e vendas"</text>
<text x="205" y="100" text-anchor="end" font-size="8" class="secondary-text">10:30</text>
</g>
<!-- Arrow 1 -->
<line x1="295" y1="140" x2="335" y2="140" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<!-- Step 2: Analysis -->
<g transform="translate(340, 80)">
<rect width="220" height="120" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="220" height="40" rx="12" fill="url(#cyanGrad)"/>
<rect y="28" width="220" height="12" fill="url(#cyanGrad)"/>
<text x="110" y="28" text-anchor="middle" font-size="13" font-weight="600" class="white-text">2. Intent Analysis</text>
<text x="15" y="65" font-size="9" class="secondary-text">Extracted:</text>
<text x="15" y="82" font-size="9" class="main-text">• Domain: retail/CRM</text>
<text x="15" y="97" font-size="9" class="main-text">• Entities: customers, products, sales</text>
<text x="15" y="112" font-size="9" class="main-text">• Features: CRUD, relationships</text>
</g>
<!-- Arrow 2 -->
<line x1="565" y1="140" x2="605" y2="140" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<!-- Step 3: Plan -->
<g transform="translate(610, 80)">
<rect width="250" height="120" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="250" height="40" rx="12" fill="url(#orangeGrad)"/>
<rect y="28" width="250" height="12" fill="url(#orangeGrad)"/>
<text x="125" y="28" text-anchor="middle" font-size="13" font-weight="600" class="white-text">3. Execution Plan</text>
<text x="15" y="65" font-size="9" class="main-text">Step 1: Create database tables</text>
<text x="15" y="80" font-size="9" class="main-text">Step 2: Generate web pages</text>
<text x="15" y="95" font-size="9" class="main-text">Step 3: Create voice tools</text>
<text x="15" y="110" font-size="9" class="main-text">Step 4: Setup schedulers</text>
</g>
<!-- Central arrow down -->
<line x1="450" y1="205" x2="450" y2="240" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<!-- Generated Outputs Section -->
<g transform="translate(40, 250)">
<rect width="820" height="250" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="820" height="40" rx="12" fill="url(#greenGrad)"/>
<rect y="28" width="820" height="12" fill="url(#greenGrad)"/>
<text x="410" y="28" text-anchor="middle" font-size="14" font-weight="600" class="white-text">4. Generated Output</text>
<!-- Tables output -->
<g transform="translate(20, 55)">
<rect width="185" height="180" rx="8" fill="#F8FAFC" stroke="#E2E8F0"/>
<rect width="185" height="30" rx="8" fill="#EEF2FF" stroke="#C7D2FE"/>
<rect y="22" width="185" height="8" fill="#EEF2FF"/>
<text x="92" y="22" text-anchor="middle" font-size="11" font-weight="500" class="main-text">📊 tables.bas</text>
<rect x="10" y="40" width="165" height="130" rx="4" fill="#1E1B4B"/>
<text x="20" y="58" font-size="8" fill="#A5B4FC" font-family="monospace">TABLE customers</text>
<text x="20" y="72" font-size="8" fill="#94A3B8" font-family="monospace"> name AS STRING</text>
<text x="20" y="86" font-size="8" fill="#94A3B8" font-family="monospace"> phone AS STRING</text>
<text x="20" y="100" font-size="8" fill="#A5B4FC" font-family="monospace">END TABLE</text>
<text x="20" y="118" font-size="8" fill="#A5B4FC" font-family="monospace">TABLE products</text>
<text x="20" y="132" font-size="8" fill="#94A3B8" font-family="monospace"> name AS STRING</text>
<text x="20" y="146" font-size="8" fill="#94A3B8" font-family="monospace"> price AS DECIMAL</text>
<text x="20" y="160" font-size="8" fill="#A5B4FC" font-family="monospace">END TABLE</text>
</g>
<!-- Web App output -->
<g transform="translate(220, 55)">
<rect width="185" height="180" rx="8" fill="#F8FAFC" stroke="#E2E8F0"/>
<rect width="185" height="30" rx="8" fill="#ECFDF5" stroke="#A7F3D0"/>
<rect y="22" width="185" height="8" fill="#ECFDF5"/>
<text x="92" y="22" text-anchor="middle" font-size="11" font-weight="500" class="main-text">📱 Web App</text>
<text x="15" y="55" font-size="9" class="secondary-text">/apps/crm-loja/</text>
<rect x="10" y="65" width="165" height="22" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="92" y="80" text-anchor="middle" font-size="9" class="mono-text">index.html</text>
<rect x="10" y="92" width="165" height="22" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="92" y="107" text-anchor="middle" font-size="9" class="mono-text">customers.html</text>
<rect x="10" y="119" width="165" height="22" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="92" y="134" text-anchor="middle" font-size="9" class="mono-text">products.html</text>
<rect x="10" y="146" width="165" height="22" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="92" y="161" text-anchor="middle" font-size="9" class="mono-text">sales.html</text>
</g>
<!-- Tools output -->
<g transform="translate(420, 55)">
<rect width="185" height="180" rx="8" fill="#F8FAFC" stroke="#E2E8F0"/>
<rect width="185" height="30" rx="8" fill="#FEF3C7" stroke="#FCD34D"/>
<rect y="22" width="185" height="8" fill="#FEF3C7"/>
<text x="92" y="22" text-anchor="middle" font-size="11" font-weight="500" class="main-text">🔧 Voice Tools</text>
<text x="15" y="55" font-size="9" class="secondary-text">tools/</text>
<rect x="10" y="65" width="165" height="35" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="92" y="80" text-anchor="middle" font-size="9" class="mono-text">buscar-cliente.bas</text>
<text x="92" y="93" text-anchor="middle" font-size="7" class="secondary-text">"buscar cliente, encontrar..."</text>
<rect x="10" y="105" width="165" height="35" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="92" y="120" text-anchor="middle" font-size="9" class="mono-text">nova-venda.bas</text>
<text x="92" y="133" text-anchor="middle" font-size="7" class="secondary-text">"nova venda, registrar..."</text>
<rect x="10" y="145" width="165" height="27" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="92" y="162" text-anchor="middle" font-size="9" class="mono-text">+ more tools...</text>
</g>
<!-- Schedulers output -->
<g transform="translate(620, 55)">
<rect width="185" height="180" rx="8" fill="#F8FAFC" stroke="#E2E8F0"/>
<rect width="185" height="30" rx="8" fill="#FCE7F3" stroke="#F9A8D4"/>
<rect y="22" width="185" height="8" fill="#FCE7F3"/>
<text x="92" y="22" text-anchor="middle" font-size="11" font-weight="500" class="main-text">⏰ Schedulers</text>
<text x="15" y="55" font-size="9" class="secondary-text">schedulers/</text>
<rect x="10" y="65" width="165" height="50" rx="4" fill="#FCE7F3" stroke="#F9A8D4"/>
<text x="92" y="82" text-anchor="middle" font-size="9" class="mono-text">alerta-estoque.bas</text>
<text x="92" y="97" text-anchor="middle" font-size="7" class="secondary-text">SET SCHEDULE "0 9 * * *"</text>
<text x="92" y="108" text-anchor="middle" font-size="7" class="secondary-text">Daily stock check at 9am</text>
<rect x="10" y="120" width="165" height="50" rx="4" fill="#FCE7F3" stroke="#F9A8D4"/>
<text x="92" y="137" text-anchor="middle" font-size="9" class="mono-text">relatorio-diario.bas</text>
<text x="92" y="152" text-anchor="middle" font-size="7" class="secondary-text">SET SCHEDULE "0 18 * * *"</text>
<text x="92" y="163" text-anchor="middle" font-size="7" class="secondary-text">Daily report at 6pm</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,204 @@
<svg width="900" height="580" xmlns="http://www.w3.org/2000/svg">
<defs>
<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="pinkGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#EC4899;stop-opacity:1" />
<stop offset="100%" style="stop-color:#F472B6;stop-opacity:1" />
</linearGradient>
<linearGradient id="redGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#EF4444;stop-opacity:1" />
<stop offset="100%" style="stop-color:#F87171;stop-opacity:1" />
</linearGradient>
<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>
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
<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>
<marker id="arrowDown" markerWidth="10" markerHeight="10" refX="3" refY="9" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L6,0 L3,9 z" fill="#8B5CF6"/>
</marker>
</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="900" height="580" fill="#FAFBFC"/>
<rect width="900" height="580" fill="url(#dots)"/>
<!-- Title -->
<text x="450" y="35" text-anchor="middle" font-size="20" font-weight="600" class="title-text">GB AutoTask Architecture</text>
<text x="450" y="55" text-anchor="middle" font-size="12" class="secondary-text">Intent Classification and Autonomous Execution</text>
<!-- User Input -->
<g transform="translate(350, 75)">
<rect width="200" height="50" rx="25" fill="url(#primaryGrad)" filter="url(#cardShadow)"/>
<text x="100" y="30" text-anchor="middle" font-size="14" font-weight="600" class="white-text">USER</text>
</g>
<!-- Arrow down from User -->
<line x1="450" y1="130" x2="450" y2="160" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<!-- Intent Classifier -->
<g transform="translate(250, 165)">
<rect width="400" height="60" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="400" height="35" rx="10" fill="url(#cyanGrad)"/>
<rect y="25" width="400" height="10" fill="url(#cyanGrad)"/>
<text x="200" y="25" text-anchor="middle" font-size="13" font-weight="600" class="white-text">INTENT CLASSIFIER</text>
<text x="200" y="50" text-anchor="middle" font-size="10" class="secondary-text">LLM classifies user request into intent type</text>
</g>
<!-- Branching arrows -->
<line x1="450" y1="230" x2="450" y2="260" stroke="#8B5CF6" stroke-width="2"/>
<line x1="100" y1="260" x2="800" y2="260" stroke="#8B5CF6" stroke-width="2"/>
<!-- Vertical drops to intent types -->
<line x1="100" y1="260" x2="100" y2="290" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<line x1="240" y1="260" x2="240" y2="290" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<line x1="380" y1="260" x2="380" y2="290" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<line x1="520" y1="260" x2="520" y2="290" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<line x1="660" y1="260" x2="660" y2="290" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<line x1="800" y1="260" x2="800" y2="290" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowDown)"/>
<!-- Intent Type 1: APP CREATE -->
<g transform="translate(40, 295)">
<rect width="120" height="80" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="120" height="28" rx="8" fill="url(#primaryGrad)"/>
<rect y="20" width="120" height="8" fill="url(#primaryGrad)"/>
<text x="60" y="20" text-anchor="middle" font-size="10" font-weight="600" class="white-text">APP CREATE</text>
<text x="60" y="48" text-anchor="middle" font-size="8" class="secondary-text">"create clinic app"</text>
<text x="60" y="65" text-anchor="middle" font-size="8" class="mono-text">HTMX + tools</text>
</g>
<!-- Intent Type 2: TODO -->
<g transform="translate(180, 295)">
<rect width="120" height="80" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="120" height="28" rx="8" fill="url(#greenGrad)"/>
<rect y="20" width="120" height="8" fill="url(#greenGrad)"/>
<text x="60" y="20" text-anchor="middle" font-size="10" font-weight="600" class="white-text">TODO</text>
<text x="60" y="48" text-anchor="middle" font-size="8" class="secondary-text">"call John tomorrow"</text>
<text x="60" y="65" text-anchor="middle" font-size="8" class="mono-text">SAVE TO tasks</text>
</g>
<!-- Intent Type 3: MONITOR -->
<g transform="translate(320, 295)">
<rect width="120" height="80" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="120" height="28" rx="8" fill="url(#cyanGrad)"/>
<rect y="20" width="120" height="8" fill="url(#cyanGrad)"/>
<text x="60" y="20" text-anchor="middle" font-size="10" font-weight="600" class="white-text">MONITOR</text>
<text x="60" y="48" text-anchor="middle" font-size="8" class="secondary-text">"alert if IBM changes"</text>
<text x="60" y="65" text-anchor="middle" font-size="8" class="mono-text">ON CHANGE</text>
</g>
<!-- Intent Type 4: ACTION -->
<g transform="translate(460, 295)">
<rect width="120" height="80" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="120" height="28" rx="8" fill="url(#orangeGrad)"/>
<rect y="20" width="120" height="8" fill="url(#orangeGrad)"/>
<text x="60" y="20" text-anchor="middle" font-size="10" font-weight="600" class="white-text">ACTION</text>
<text x="60" y="48" text-anchor="middle" font-size="8" class="secondary-text">"email customers"</text>
<text x="60" y="65" text-anchor="middle" font-size="8" class="mono-text">Execute .bas</text>
</g>
<!-- Intent Type 5: SCHEDULE -->
<g transform="translate(600, 295)">
<rect width="120" height="80" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="120" height="28" rx="8" fill="url(#pinkGrad)"/>
<rect y="20" width="120" height="8" fill="url(#pinkGrad)"/>
<text x="60" y="20" text-anchor="middle" font-size="10" font-weight="600" class="white-text">SCHEDULE</text>
<text x="60" y="48" text-anchor="middle" font-size="8" class="secondary-text">"daily 9am summary"</text>
<text x="60" y="65" text-anchor="middle" font-size="8" class="mono-text">SET SCHEDULE</text>
</g>
<!-- Intent Type 6: GOAL -->
<g transform="translate(740, 295)">
<rect width="120" height="80" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="120" height="28" rx="8" fill="url(#redGrad)"/>
<rect y="20" width="120" height="8" fill="url(#redGrad)"/>
<text x="60" y="20" text-anchor="middle" font-size="10" font-weight="600" class="white-text">GOAL</text>
<text x="60" y="48" text-anchor="middle" font-size="8" class="secondary-text">"increase sales 20%"</text>
<text x="60" y="65" text-anchor="middle" font-size="8" class="mono-text">LLM loop</text>
</g>
<!-- File Structure Section -->
<g transform="translate(40, 400)">
<rect width="820" height="165" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<text x="410" y="25" text-anchor="middle" font-size="13" font-weight="600" class="main-text">Generated File Structure</text>
<!-- .gbdrive column -->
<g transform="translate(20, 40)">
<rect width="250" height="110" rx="6" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="125" y="22" text-anchor="middle" font-size="11" font-weight="600" class="main-text">.gbdrive/apps/</text>
<text x="15" y="45" font-size="9" class="mono-text">index.html</text>
<text x="165" y="45" font-size="8" class="secondary-text">Main HTMX page</text>
<text x="15" y="62" font-size="9" class="mono-text">*.html</text>
<text x="165" y="62" font-size="8" class="secondary-text">Additional pages</text>
<text x="15" y="79" font-size="9" class="mono-text">assets/</text>
<text x="165" y="79" font-size="8" class="secondary-text">CSS, images</text>
<text x="15" y="96" font-size="9" class="mono-text">tables.bas</text>
<text x="165" y="96" font-size="8" class="secondary-text">Data schema</text>
</g>
<!-- .gbdialog/tools column -->
<g transform="translate(290, 40)">
<rect width="250" height="110" rx="6" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="125" y="22" text-anchor="middle" font-size="11" font-weight="600" class="main-text">.gbdialog/tools/</text>
<text x="15" y="45" font-size="9" class="mono-text">{tool-name}.bas</text>
<text x="15" y="62" font-size="8" class="secondary-text">Voice/chat commands</text>
<text x="15" y="82" font-size="9" class="mono-text">DESCRIPTION "trigger"</text>
<text x="15" y="99" font-size="8" class="secondary-text">Activated by phrase</text>
</g>
<!-- .gbdialog/schedulers + events column -->
<g transform="translate(560, 40)">
<rect width="240" height="110" rx="6" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="120" y="22" text-anchor="middle" font-size="11" font-weight="600" class="main-text">.gbdialog/schedulers/</text>
<text x="15" y="45" font-size="9" class="mono-text">{name}.bas</text>
<text x="140" y="45" font-size="8" class="secondary-text">SET SCHEDULE</text>
<line x1="15" y1="58" x2="225" y2="58" stroke="#FCD34D" stroke-width="1"/>
<text x="120" y="75" text-anchor="middle" font-size="11" font-weight="600" class="main-text">.gbdialog/events/</text>
<text x="15" y="95" font-size="9" class="mono-text">{name}.bas</text>
<text x="140" y="95" font-size="8" class="secondary-text">ON CHANGE, ON EMAIL</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,162 @@
<svg width="900" height="500" xmlns="http://www.w3.org/2000/svg">
<defs>
<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>
<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>
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
<marker id="arrowGray" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#94A3B8"/>
</marker>
</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="900" height="500" fill="#FAFBFC"/>
<rect width="900" height="500" fill="url(#dots)"/>
<!-- Title -->
<text x="450" y="35" text-anchor="middle" font-size="20" font-weight="600" class="title-text">Bot Database Architecture</text>
<text x="450" y="55" text-anchor="middle" font-size="12" class="secondary-text">One Bot = One Database • Multiple Apps Share Data</text>
<!-- Organization Box -->
<rect x="30" y="75" width="840" height="410" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<text x="50" y="100" font-size="14" font-weight="600" class="main-text">ORGANIZATION</text>
<!-- Organization Default Database -->
<rect x="50" y="115" width="180" height="100" rx="8" fill="url(#orangeGrad)"/>
<text x="140" y="140" text-anchor="middle" font-size="12" font-weight="600" class="white-text">organization_default</text>
<text x="140" y="158" text-anchor="middle" font-size="10" class="white-text" opacity="0.9">System Database</text>
<text x="60" y="180" font-size="9" class="white-text" opacity="0.8">• users</text>
<text x="60" y="193" font-size="9" class="white-text" opacity="0.8">• bots</text>
<text x="60" y="206" font-size="9" class="white-text" opacity="0.8">• subscriptions</text>
<!-- Bot 1: Clinica -->
<rect x="260" y="115" width="270" height="355" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5"/>
<!-- Bot 1 Header -->
<rect x="260" y="115" width="270" height="40" rx="8" fill="url(#primaryGrad)"/>
<rect x="260" y="140" width="270" height="15" fill="url(#primaryGrad)"/>
<text x="395" y="140" text-anchor="middle" font-size="13" font-weight="600" class="white-text">bot_clinica</text>
<!-- Bot 1 Database Tables -->
<text x="275" y="175" font-size="11" font-weight="600" class="main-text">Database Tables</text>
<rect x="275" y="185" width="110" height="24" rx="4" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="330" y="201" text-anchor="middle" font-size="10" class="mono-text">patients</text>
<rect x="275" y="213" width="110" height="24" rx="4" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="330" y="229" text-anchor="middle" font-size="10" class="mono-text">appointments</text>
<rect x="275" y="241" width="110" height="24" rx="4" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="330" y="257" text-anchor="middle" font-size="10" class="mono-text">doctors</text>
<!-- Bot 1 Shared Resources -->
<text x="400" y="175" font-size="11" font-weight="600" class="main-text">Shared Resources</text>
<rect x="400" y="185" width="115" height="24" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="457" y="201" text-anchor="middle" font-size="10" class="mono-text">tools/</text>
<rect x="400" y="213" width="115" height="24" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="457" y="229" text-anchor="middle" font-size="10" class="mono-text">schedulers/</text>
<rect x="400" y="241" width="115" height="24" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="457" y="257" text-anchor="middle" font-size="10" class="mono-text">events/</text>
<!-- Bot 1 Apps -->
<text x="275" y="290" font-size="11" font-weight="600" class="main-text">Apps (share same data)</text>
<rect x="275" y="300" width="235" height="30" rx="4" fill="url(#cyanGrad)"/>
<text x="392" y="320" text-anchor="middle" font-size="10" class="white-text">/apps/reception</text>
<rect x="275" y="335" width="235" height="30" rx="4" fill="url(#cyanGrad)"/>
<text x="392" y="355" text-anchor="middle" font-size="10" class="white-text">/apps/scheduling</text>
<rect x="275" y="370" width="235" height="30" rx="4" fill="url(#cyanGrad)"/>
<text x="392" y="390" text-anchor="middle" font-size="10" class="white-text">/apps/reports</text>
<!-- tables.bas indicator -->
<rect x="275" y="410" width="235" height="50" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="392" y="432" text-anchor="middle" font-size="10" font-weight="600" class="main-text">tables.bas</text>
<text x="392" y="448" text-anchor="middle" font-size="9" class="secondary-text">TABLE definitions → auto-sync to DB</text>
<!-- Bot 2: Loja -->
<rect x="560" y="115" width="270" height="355" rx="8" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5"/>
<!-- Bot 2 Header -->
<rect x="560" y="115" width="270" height="40" rx="8" fill="url(#greenGrad)"/>
<rect x="560" y="140" width="270" height="15" fill="url(#greenGrad)"/>
<text x="695" y="140" text-anchor="middle" font-size="13" font-weight="600" class="white-text">bot_loja</text>
<!-- Bot 2 Database Tables -->
<text x="575" y="175" font-size="11" font-weight="600" class="main-text">Database Tables</text>
<rect x="575" y="185" width="110" height="24" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="630" y="201" text-anchor="middle" font-size="10" class="mono-text">customers</text>
<rect x="575" y="213" width="110" height="24" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="630" y="229" text-anchor="middle" font-size="10" class="mono-text">products</text>
<rect x="575" y="241" width="110" height="24" rx="4" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="630" y="257" text-anchor="middle" font-size="10" class="mono-text">sales</text>
<!-- Bot 2 Shared Resources -->
<text x="700" y="175" font-size="11" font-weight="600" class="main-text">Shared Resources</text>
<rect x="700" y="185" width="115" height="24" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="757" y="201" text-anchor="middle" font-size="10" class="mono-text">tools/</text>
<rect x="700" y="213" width="115" height="24" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="757" y="229" text-anchor="middle" font-size="10" class="mono-text">schedulers/</text>
<rect x="700" y="241" width="115" height="24" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="757" y="257" text-anchor="middle" font-size="10" class="mono-text">events/</text>
<!-- Bot 2 Apps -->
<text x="575" y="290" font-size="11" font-weight="600" class="main-text">Apps (share same data)</text>
<rect x="575" y="300" width="235" height="30" rx="4" fill="url(#greenGrad)"/>
<text x="692" y="320" text-anchor="middle" font-size="10" class="white-text">/apps/pos</text>
<rect x="575" y="335" width="235" height="30" rx="4" fill="url(#greenGrad)"/>
<text x="692" y="355" text-anchor="middle" font-size="10" class="white-text">/apps/inventory</text>
<rect x="575" y="370" width="235" height="30" rx="4" fill="url(#greenGrad)"/>
<text x="692" y="390" text-anchor="middle" font-size="10" class="white-text">/apps/service</text>
<!-- tables.bas indicator -->
<rect x="575" y="410" width="235" height="50" rx="4" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="692" y="432" text-anchor="middle" font-size="10" font-weight="600" class="main-text">tables.bas</text>
<text x="692" y="448" text-anchor="middle" font-size="9" class="secondary-text">TABLE definitions → auto-sync to DB</text>
<!-- Arrows from org_default to bots -->
<line x1="230" y1="165" x2="255" y2="165" stroke="#94A3B8" stroke-width="1.5" stroke-dasharray="4,3"/>
<!-- Legend -->
<rect x="50" y="235" width="180" height="115" rx="6" fill="#F8FAFC" stroke="#E2E8F0"/>
<text x="140" y="255" text-anchor="middle" font-size="10" font-weight="600" class="main-text">Key Concept</text>
<text x="60" y="275" font-size="9" class="secondary-text">• Each bot has own database</text>
<text x="60" y="292" font-size="9" class="secondary-text">• Apps share same tables</text>
<text x="60" y="309" font-size="9" class="secondary-text">• Tools/schedulers shared</text>
<text x="60" y="326" font-size="9" class="secondary-text">• tables.bas defines schema</text>
<text x="60" y="343" font-size="9" class="secondary-text">• Data isolated between bots</text>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

View file

@ -0,0 +1,174 @@
<svg width="900" height="420" xmlns="http://www.w3.org/2000/svg">
<defs>
<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>
<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>
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
<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>
<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>
.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="900" height="420" fill="#FAFBFC"/>
<rect width="900" height="420" fill="url(#dots)"/>
<!-- Title -->
<text x="450" y="35" text-anchor="middle" font-size="20" font-weight="600" class="title-text">TABLE Keyword → Database Flow</text>
<text x="450" y="55" text-anchor="middle" font-size="12" class="secondary-text">Define Once in BASIC, Sync Automatically to PostgreSQL</text>
<!-- Step 1: tables.bas file -->
<g transform="translate(40, 85)">
<rect width="220" height="200" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="220" height="40" rx="12" fill="url(#primaryGrad)"/>
<rect y="28" width="220" height="12" fill="url(#primaryGrad)"/>
<text x="110" y="28" text-anchor="middle" font-size="13" font-weight="600" class="white-text">1. Define in tables.bas</text>
<!-- Code preview -->
<rect x="15" y="55" width="190" height="130" rx="6" fill="#1E1B4B"/>
<text x="25" y="75" font-size="10" fill="#A5B4FC" font-family="monospace">TABLE patients</text>
<text x="25" y="92" font-size="10" fill="#94A3B8" font-family="monospace"> name AS STRING</text>
<text x="25" y="109" font-size="10" fill="#94A3B8" font-family="monospace"> phone AS STRING</text>
<text x="25" y="126" font-size="10" fill="#94A3B8" font-family="monospace"> email AS STRING</text>
<text x="25" y="143" font-size="10" fill="#A5B4FC" font-family="monospace">END TABLE</text>
<text x="25" y="170" font-size="9" fill="#64748B" font-family="monospace">.gbdialog/tables.bas</text>
</g>
<!-- Arrow 1 -->
<line x1="265" y1="185" x2="310" y2="185" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<text x="288" y="175" text-anchor="middle" font-size="9" class="secondary-text">parse</text>
<!-- Step 2: Schema Sync -->
<g transform="translate(315, 85)">
<rect width="200" height="200" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="200" height="40" rx="12" fill="url(#cyanGrad)"/>
<rect y="28" width="200" height="12" fill="url(#cyanGrad)"/>
<text x="100" y="28" text-anchor="middle" font-size="13" font-weight="600" class="white-text">2. Schema Sync</text>
<text x="100" y="70" text-anchor="middle" font-size="11" class="main-text">System compares</text>
<text x="100" y="88" text-anchor="middle" font-size="11" class="main-text">tables.bas ↔ database</text>
<rect x="20" y="105" width="160" height="70" rx="6" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="100" y="125" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Auto Operations:</text>
<text x="30" y="145" font-size="9" class="secondary-text">• CREATE new tables</text>
<text x="30" y="160" font-size="9" class="secondary-text">• ADD new columns</text>
</g>
<!-- Arrow 2 -->
<line x1="520" y1="185" x2="565" y2="185" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<text x="543" y="175" text-anchor="middle" font-size="9" class="secondary-text">migrate</text>
<!-- Step 3: PostgreSQL Database -->
<g transform="translate(570, 85)">
<rect width="290" height="200" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="290" height="40" rx="12" fill="url(#greenGrad)"/>
<rect y="28" width="290" height="12" fill="url(#greenGrad)"/>
<text x="145" y="28" text-anchor="middle" font-size="13" font-weight="600" class="white-text">3. PostgreSQL Database</text>
<!-- Table representation -->
<rect x="15" y="55" width="260" height="130" rx="6" fill="#F8FAFC" stroke="#E2E8F0"/>
<rect x="15" y="55" width="260" height="25" rx="6" fill="#ECFDF5" stroke="#A7F3D0"/>
<rect x="15" y="74" width="260" height="6" fill="#ECFDF5"/>
<text x="145" y="72" text-anchor="middle" font-size="11" font-weight="500" class="main-text">bot_clinica.patients</text>
<!-- Column headers -->
<text x="35" y="100" font-size="9" font-weight="500" class="secondary-text">id</text>
<text x="90" y="100" font-size="9" font-weight="500" class="secondary-text">name</text>
<text x="160" y="100" font-size="9" font-weight="500" class="secondary-text">phone</text>
<text x="230" y="100" font-size="9" font-weight="500" class="secondary-text">email</text>
<line x1="25" y1="108" x2="265" y2="108" stroke="#E2E8F0" stroke-width="1"/>
<!-- Sample data rows -->
<text x="35" y="125" font-size="9" class="mono-text">uuid1</text>
<text x="90" y="125" font-size="9" class="mono-text">João Silva</text>
<text x="160" y="125" font-size="9" class="mono-text">99999-1111</text>
<text x="230" y="125" font-size="9" class="mono-text">joao@...</text>
<text x="35" y="145" font-size="9" class="mono-text">uuid2</text>
<text x="90" y="145" font-size="9" class="mono-text">Maria Santos</text>
<text x="160" y="145" font-size="9" class="mono-text">99999-2222</text>
<text x="230" y="145" font-size="9" class="mono-text">maria@...</text>
<text x="35" y="165" font-size="9" class="mono-text">uuid3</text>
<text x="90" y="165" font-size="9" class="mono-text">Carlos Lima</text>
<text x="160" y="165" font-size="9" class="mono-text">99999-3333</text>
<text x="230" y="165" font-size="9" class="mono-text">carlos@...</text>
</g>
<!-- Bottom section: FIND keyword usage -->
<g transform="translate(40, 310)">
<rect width="820" height="95" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<text x="410" y="25" text-anchor="middle" font-size="13" font-weight="600" class="main-text">Access Data with FIND Keyword</text>
<!-- FIND example -->
<g transform="translate(20, 40)">
<rect width="250" height="45" rx="6" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="125" y="18" text-anchor="middle" font-size="10" font-weight="500" class="main-text">FIND Query</text>
<text x="125" y="35" text-anchor="middle" font-size="9" class="mono-text">FIND * IN patients WHERE name LIKE "%Silva%"</text>
</g>
<!-- Arrow -->
<line x1="280" y1="62" x2="320" y2="62" stroke="#10B981" stroke-width="2" marker-end="url(#arrowGreen)"/>
<!-- Result -->
<g transform="translate(330, 40)">
<rect width="200" height="45" rx="6" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="100" y="18" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Returns</text>
<text x="100" y="35" text-anchor="middle" font-size="9" class="mono-text">[ { name: "João Silva", ... } ]</text>
</g>
<!-- Arrow -->
<line x1="540" y1="62" x2="580" y2="62" stroke="#10B981" stroke-width="2" marker-end="url(#arrowGreen)"/>
<!-- All apps -->
<g transform="translate(590, 40)">
<rect width="210" height="45" rx="6" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="105" y="18" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Available Everywhere</text>
<text x="105" y="35" text-anchor="middle" font-size="9" class="secondary-text">All apps • Tools • Schedulers • API</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.5 KiB

View file

@ -0,0 +1,200 @@
<svg width="900" height="480" xmlns="http://www.w3.org/2000/svg">
<defs>
<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="pinkGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#EC4899;stop-opacity:1" />
<stop offset="100%" style="stop-color:#F472B6;stop-opacity:1" />
</linearGradient>
<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>
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
<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>
<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>
<marker id="arrowCyan" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#06B6D4"/>
</marker>
</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="900" height="480" fill="#FAFBFC"/>
<rect width="900" height="480" fill="url(#dots)"/>
<!-- Title -->
<text x="450" y="35" text-anchor="middle" font-size="20" font-weight="600" class="title-text">Designer — Meta-Programming Workflow</text>
<text x="450" y="55" text-anchor="middle" font-size="12" class="secondary-text">Edit Apps Through Natural Language Conversation</text>
<!-- User Request -->
<g transform="translate(40, 80)">
<rect width="200" height="130" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="200" height="40" rx="12" fill="url(#primaryGrad)"/>
<rect y="28" width="200" height="12" fill="url(#primaryGrad)"/>
<text x="100" y="28" text-anchor="middle" font-size="12" font-weight="600" class="white-text">1. User Request</text>
<!-- Chat bubble -->
<rect x="15" y="55" width="170" height="60" rx="8" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="100" y="75" text-anchor="middle" font-size="9" class="main-text">"muda o botão</text>
<text x="100" y="88" text-anchor="middle" font-size="9" class="main-text">de agendar pra azul"</text>
<text x="155" y="105" text-anchor="end" font-size="8" class="secondary-text">10:30</text>
</g>
<!-- Arrow 1 -->
<line x1="245" y1="145" x2="285" y2="145" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<!-- Context Analysis -->
<g transform="translate(290, 80)">
<rect width="200" height="130" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="200" height="40" rx="12" fill="url(#cyanGrad)"/>
<rect y="28" width="200" height="12" fill="url(#cyanGrad)"/>
<text x="100" y="28" text-anchor="middle" font-size="12" font-weight="600" class="white-text">2. Context Analysis</text>
<text x="15" y="65" font-size="9" class="secondary-text">Designer knows:</text>
<text x="15" y="82" font-size="9" class="main-text">• Current app: /apps/clinica</text>
<text x="15" y="97" font-size="9" class="main-text">• Current page: agendar.html</text>
<text x="15" y="112" font-size="9" class="main-text">• Available tables: patients...</text>
<text x="15" y="127" font-size="9" class="main-text">• Recent changes history</text>
</g>
<!-- Arrow 2 -->
<line x1="495" y1="145" x2="535" y2="145" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<!-- Code Generation -->
<g transform="translate(540, 80)">
<rect width="320" height="130" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="320" height="40" rx="12" fill="url(#orangeGrad)"/>
<rect y="28" width="320" height="12" fill="url(#orangeGrad)"/>
<text x="160" y="28" text-anchor="middle" font-size="12" font-weight="600" class="white-text">3. Generate Changes</text>
<!-- Code preview -->
<rect x="15" y="52" width="290" height="65" rx="6" fill="#1E1B4B"/>
<text x="25" y="70" font-size="9" fill="#94A3B8" font-family="monospace">/* agendar.html */</text>
<text x="25" y="85" font-size="9" fill="#A5B4FC" font-family="monospace">.btn-agendar {</text>
<text x="25" y="100" font-size="9" fill="#FCD34D" font-family="monospace"> background-color: #3498db;</text>
<text x="25" y="115" font-size="9" fill="#A5B4FC" font-family="monospace">}</text>
</g>
<!-- Middle section: What Can Be Modified -->
<g transform="translate(40, 230)">
<rect width="820" height="110" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<text x="410" y="25" text-anchor="middle" font-size="13" font-weight="600" class="main-text">What Designer Can Modify</text>
<!-- Modification types -->
<g transform="translate(20, 40)">
<rect width="150" height="55" rx="6" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="75" y="22" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Styles</text>
<text x="75" y="38" text-anchor="middle" font-size="9" class="mono-text">*.css, inline</text>
<text x="75" y="50" text-anchor="middle" font-size="8" class="secondary-text">colors, layout, fonts</text>
</g>
<g transform="translate(185, 40)">
<rect width="150" height="55" rx="6" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="75" y="22" text-anchor="middle" font-size="10" font-weight="500" class="main-text">HTML Pages</text>
<text x="75" y="38" text-anchor="middle" font-size="9" class="mono-text">*.html</text>
<text x="75" y="50" text-anchor="middle" font-size="8" class="secondary-text">forms, lists, elements</text>
</g>
<g transform="translate(350, 40)">
<rect width="150" height="55" rx="6" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="75" y="22" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Database</text>
<text x="75" y="38" text-anchor="middle" font-size="9" class="mono-text">tables.bas</text>
<text x="75" y="50" text-anchor="middle" font-size="8" class="secondary-text">add fields, tables</text>
</g>
<g transform="translate(515, 40)">
<rect width="150" height="55" rx="6" fill="#FCE7F3" stroke="#F9A8D4"/>
<text x="75" y="22" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Tools</text>
<text x="75" y="38" text-anchor="middle" font-size="9" class="mono-text">tools/*.bas</text>
<text x="75" y="50" text-anchor="middle" font-size="8" class="secondary-text">voice commands</text>
</g>
<g transform="translate(680, 40)">
<rect width="120" height="55" rx="6" fill="#E0E7FF" stroke="#A5B4FC"/>
<text x="60" y="22" text-anchor="middle" font-size="10" font-weight="500" class="main-text">Schedulers</text>
<text x="60" y="38" text-anchor="middle" font-size="9" class="mono-text">schedulers/</text>
<text x="60" y="50" text-anchor="middle" font-size="8" class="secondary-text">automation</text>
</g>
</g>
<!-- Bottom section: Preview and Apply -->
<g transform="translate(40, 360)">
<rect width="390" height="105" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="390" height="35" rx="10" fill="url(#greenGrad)"/>
<rect y="23" width="390" height="12" fill="url(#greenGrad)"/>
<text x="195" y="25" text-anchor="middle" font-size="12" font-weight="600" class="white-text">4. Preview Changes</text>
<!-- Preview content -->
<rect x="15" y="48" width="360" height="45" rx="6" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="25" y="66" font-size="9" class="main-text">Alterando em agendar.html:</text>
<text x="25" y="82" font-size="9" class="mono-text">button { background-color: #3498db; }</text>
</g>
<!-- Arrow to Apply -->
<line x1="435" y1="412" x2="475" y2="412" stroke="#10B981" stroke-width="2" marker-end="url(#arrowGreen)"/>
<!-- Apply section -->
<g transform="translate(480, 360)">
<rect width="380" height="105" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<rect width="380" height="35" rx="10" fill="url(#pinkGrad)"/>
<rect y="23" width="380" height="12" fill="url(#pinkGrad)"/>
<text x="190" y="25" text-anchor="middle" font-size="12" font-weight="600" class="white-text">5. Apply &amp; Confirm</text>
<!-- Response bubble -->
<rect x="15" y="48" width="350" height="45" rx="6" fill="#FCE7F3" stroke="#F9A8D4"/>
<text x="25" y="66" font-size="9" class="main-text">Pronto! Botão azul. ✅</text>
<text x="25" y="82" font-size="9" class="secondary-text">Mudanças salvas • Histórico atualizado • Undo disponível</text>
</g>
<!-- Key Features callout -->
<g transform="translate(700, 80)">
<rect x="0" y="55" width="150" height="75" rx="6" fill="#F8FAFC" stroke="#E2E8F0"/>
<text x="75" y="75" text-anchor="middle" font-size="10" font-weight="600" class="main-text">Safety Features</text>
<text x="10" y="93" font-size="8" class="secondary-text">• Preview before apply</text>
<text x="10" y="106" font-size="8" class="secondary-text">• Confirm destructive ops</text>
<text x="10" y="119" font-size="8" class="secondary-text">• Full undo support</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -0,0 +1,152 @@
<svg width="900" height="400" xmlns="http://www.w3.org/2000/svg">
<defs>
<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>
<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>
<pattern id="dots" patternUnits="userSpaceOnUse" width="20" height="20">
<circle cx="10" cy="10" r="1" fill="#6366F1" opacity="0.08"/>
</pattern>
<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>
</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="900" height="400" fill="#FAFBFC"/>
<rect width="900" height="400" fill="url(#dots)"/>
<!-- Title -->
<text x="450" y="35" text-anchor="middle" font-size="20" font-weight="600" class="title-text">Task Workflow</text>
<text x="450" y="55" text-anchor="middle" font-size="12" class="secondary-text">From Intent to Working Application</text>
<!-- Phase 1: Describe -->
<g transform="translate(50, 90)">
<rect width="180" height="140" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="180" height="45" rx="12" fill="url(#primaryGrad)"/>
<rect y="33" width="180" height="12" fill="url(#primaryGrad)"/>
<text x="90" y="30" text-anchor="middle" font-size="14" font-weight="600" class="white-text">1. DESCRIBE</text>
<text x="90" y="70" text-anchor="middle" font-size="11" class="main-text">You tell the bot</text>
<text x="90" y="85" text-anchor="middle" font-size="11" class="main-text">what you want</text>
<text x="15" y="110" font-size="10" class="secondary-text">• Natural language</text>
<text x="15" y="125" font-size="10" class="secondary-text">• "cria app de vendas"</text>
</g>
<!-- Arrow 1 -->
<line x1="235" y1="160" x2="270" y2="160" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<!-- Phase 2: Plan -->
<g transform="translate(275, 90)">
<rect width="180" height="140" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="180" height="45" rx="12" fill="url(#cyanGrad)"/>
<rect y="33" width="180" height="12" fill="url(#cyanGrad)"/>
<text x="90" y="30" text-anchor="middle" font-size="14" font-weight="600" class="white-text">2. PLAN</text>
<text x="90" y="70" text-anchor="middle" font-size="11" class="main-text">System creates</text>
<text x="90" y="85" text-anchor="middle" font-size="11" class="main-text">execution plan</text>
<text x="15" y="110" font-size="10" class="secondary-text">• Steps identified</text>
<text x="15" y="125" font-size="10" class="secondary-text">• You review &amp; confirm</text>
</g>
<!-- Arrow 2 -->
<line x1="460" y1="160" x2="495" y2="160" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<!-- Phase 3: Execute -->
<g transform="translate(500, 90)">
<rect width="180" height="140" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="180" height="45" rx="12" fill="url(#orangeGrad)"/>
<rect y="33" width="180" height="12" fill="url(#orangeGrad)"/>
<text x="90" y="30" text-anchor="middle" font-size="14" font-weight="600" class="white-text">3. EXECUTE</text>
<text x="90" y="70" text-anchor="middle" font-size="11" class="main-text">Steps run</text>
<text x="90" y="85" text-anchor="middle" font-size="11" class="main-text">automatically</text>
<text x="15" y="110" font-size="10" class="secondary-text">• Real-time progress</text>
<text x="15" y="125" font-size="10" class="secondary-text">• Pause/resume anytime</text>
</g>
<!-- Arrow 3 -->
<line x1="685" y1="160" x2="720" y2="160" stroke="#8B5CF6" stroke-width="2" marker-end="url(#arrowPurple)"/>
<!-- Phase 4: Deliver -->
<g transform="translate(725, 90)">
<rect width="150" height="140" rx="12" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="2" filter="url(#cardShadow)"/>
<rect width="150" height="45" rx="12" fill="url(#greenGrad)"/>
<rect y="33" width="150" height="12" fill="url(#greenGrad)"/>
<text x="75" y="30" text-anchor="middle" font-size="14" font-weight="600" class="white-text">4. DELIVER</text>
<text x="75" y="70" text-anchor="middle" font-size="11" class="main-text">App is ready</text>
<text x="75" y="85" text-anchor="middle" font-size="11" class="main-text">to use</text>
<text x="15" y="110" font-size="10" class="secondary-text">• Tables created</text>
<text x="15" y="125" font-size="10" class="secondary-text">• Tools ready</text>
</g>
<!-- Output Section -->
<g transform="translate(50, 260)">
<rect width="825" height="120" rx="10" fill="#FFFFFF" stroke="#E2E8F0" stroke-width="1.5" filter="url(#cardShadow)"/>
<text x="412" y="25" text-anchor="middle" font-size="13" font-weight="600" class="main-text">What Gets Created</text>
<!-- Output items -->
<g transform="translate(30, 45)">
<rect width="150" height="60" rx="6" fill="#EEF2FF" stroke="#C7D2FE"/>
<text x="75" y="25" text-anchor="middle" font-size="11" font-weight="500" class="main-text">Database Tables</text>
<text x="75" y="45" text-anchor="middle" font-size="10" class="mono-text">tables.bas</text>
</g>
<g transform="translate(200, 45)">
<rect width="150" height="60" rx="6" fill="#ECFDF5" stroke="#A7F3D0"/>
<text x="75" y="25" text-anchor="middle" font-size="11" font-weight="500" class="main-text">Web App</text>
<text x="75" y="45" text-anchor="middle" font-size="10" class="mono-text">/apps/name/</text>
</g>
<g transform="translate(370, 45)">
<rect width="150" height="60" rx="6" fill="#FEF3C7" stroke="#FCD34D"/>
<text x="75" y="25" text-anchor="middle" font-size="11" font-weight="500" class="main-text">Voice Tools</text>
<text x="75" y="45" text-anchor="middle" font-size="10" class="mono-text">tools/*.bas</text>
</g>
<g transform="translate(540, 45)">
<rect width="150" height="60" rx="6" fill="#FCE7F3" stroke="#F9A8D4"/>
<text x="75" y="25" text-anchor="middle" font-size="11" font-weight="500" class="main-text">Schedulers</text>
<text x="75" y="45" text-anchor="middle" font-size="10" class="mono-text">schedulers/*.bas</text>
</g>
<g transform="translate(710, 45)">
<rect width="95" height="60" rx="6" fill="#E0E7FF" stroke="#A5B4FC"/>
<text x="47" y="25" text-anchor="middle" font-size="11" font-weight="500" class="main-text">Monitors</text>
<text x="47" y="45" text-anchor="middle" font-size="10" class="mono-text">events/</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.3 KiB

View file

@ -0,0 +1,84 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400">
<defs>
<linearGradient id="bgGrad2017" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1" />
<stop offset="100%" style="stop-color:#16213e;stop-opacity:1" />
</linearGradient>
<linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#e94560;stop-opacity:1" />
<stop offset="100%" style="stop-color:#ff6b6b;stop-opacity:1" />
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="2" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect width="800" height="400" fill="url(#bgGrad2017)" rx="12"/>
<!-- Timeline line -->
<line x1="100" y1="200" x2="700" y2="200" stroke="#0f3460" stroke-width="4" stroke-linecap="round"/>
<!-- 2017 milestone -->
<circle cx="150" cy="200" r="16" fill="url(#accentGrad)" filter="url(#glow)"/>
<text x="150" y="160" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="14" font-weight="bold">2017</text>
<text x="150" y="250" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">No Forms</text>
<text x="150" y="265" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">Manifesto</text>
<!-- 2018-2020 milestone -->
<circle cx="300" cy="200" r="12" fill="#0f3460" stroke="#e94560" stroke-width="2"/>
<text x="300" y="160" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="14" font-weight="bold">2018-20</text>
<text x="300" y="250" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">Node.js</text>
<text x="300" y="265" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">Growth</text>
<!-- 2021-2023 milestone -->
<circle cx="450" cy="200" r="12" fill="#0f3460" stroke="#e94560" stroke-width="2"/>
<text x="450" y="160" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="14" font-weight="bold">2021-23</text>
<text x="450" y="250" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">Enterprise</text>
<text x="450" y="265" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">Adoption</text>
<!-- 2024 milestone -->
<circle cx="600" cy="200" r="12" fill="#0f3460" stroke="#e94560" stroke-width="2"/>
<text x="600" y="160" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="14" font-weight="bold">2024</text>
<text x="600" y="250" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">Rust</text>
<text x="600" y="265" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">Rewrite</text>
<!-- Form icon (crossed out) -->
<g transform="translate(80, 300)">
<rect x="0" y="0" width="50" height="60" rx="4" fill="none" stroke="#e94560" stroke-width="2"/>
<line x1="10" y1="15" x2="40" y2="15" stroke="#e94560" stroke-width="2"/>
<line x1="10" y1="30" x2="40" y2="30" stroke="#e94560" stroke-width="2"/>
<line x1="10" y1="45" x2="30" y2="45" stroke="#e94560" stroke-width="2"/>
<line x1="-5" y1="-5" x2="55" y2="65" stroke="#e94560" stroke-width="3"/>
</g>
<!-- Arrow -->
<path d="M160 330 L200 330" stroke="#4ade80" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#4ade80"/>
</marker>
</defs>
<!-- Chat icon -->
<g transform="translate(220, 300)">
<rect x="0" y="5" width="50" height="40" rx="8" fill="none" stroke="#4ade80" stroke-width="2"/>
<circle cx="15" cy="25" r="3" fill="#4ade80"/>
<circle cx="25" cy="25" r="3" fill="#4ade80"/>
<circle cx="35" cy="25" r="3" fill="#4ade80"/>
<path d="M10 45 L10 55 L20 45" fill="none" stroke="#4ade80" stroke-width="2" stroke-linejoin="round"/>
</g>
<!-- Title -->
<text x="400" y="50" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="24" font-weight="bold">The No Forms Movement</text>
<text x="400" y="75" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="14">People should converse, not fill forms</text>
<!-- Quote box -->
<rect x="350" y="290" width="380" height="70" rx="8" fill="#0f3460" opacity="0.6"/>
<text x="540" y="320" text-anchor="middle" fill="#e94560" font-family="system-ui, sans-serif" font-size="13" font-style="italic">"Replace forms with conversations"</text>
<text x="540" y="345" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="11">— Pragmatismo, 2017</text>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

160
src/assets/kb-access.svg Normal file
View file

@ -0,0 +1,160 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 600">
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1" />
<stop offset="100%" style="stop-color:#16213e;stop-opacity:1" />
</linearGradient>
<linearGradient id="userGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#667eea;stop-opacity:1" />
<stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" />
</linearGradient>
<linearGradient id="sessionGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#f093fb;stop-opacity:1" />
<stop offset="100%" style="stop-color:#f5576c;stop-opacity:1" />
</linearGradient>
<linearGradient id="kbGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#4facfe;stop-opacity:1" />
<stop offset="100%" style="stop-color:#00f2fe;stop-opacity:1" />
</linearGradient>
<linearGradient id="docGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#43e97b;stop-opacity:1" />
<stop offset="100%" style="stop-color:#38f9d7;stop-opacity:1" />
</linearGradient>
<linearGradient id="assocGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#fa709a;stop-opacity:1" />
<stop offset="100%" style="stop-color:#fee140;stop-opacity:1" />
</linearGradient>
<filter id="glow">
<feGaussianBlur stdDeviation="3" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#888"/>
</marker>
<marker id="arrowheadBlue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#4facfe"/>
</marker>
</defs>
<!-- Background -->
<rect width="900" height="600" fill="url(#bgGradient)"/>
<!-- Title -->
<text x="450" y="40" fill="#ffffff" font-family="Arial, sans-serif" font-size="24" font-weight="bold" text-anchor="middle">Knowledge Base Access Flow</text>
<text x="450" y="65" fill="#888888" font-family="Arial, sans-serif" font-size="14" text-anchor="middle">User permissions and document retrieval through associations</text>
<!-- Users Entity -->
<g transform="translate(60, 120)">
<rect x="0" y="0" width="160" height="140" rx="10" fill="url(#userGradient)" filter="url(#glow)"/>
<text x="80" y="30" fill="#ffffff" font-family="Arial, sans-serif" font-size="16" font-weight="bold" text-anchor="middle">👤 users</text>
<line x1="10" y1="45" x2="150" y2="45" stroke="#ffffff" stroke-opacity="0.3"/>
<text x="20" y="70" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">🔑 id (UUID)</text>
<text x="20" y="90" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">username</text>
<text x="20" y="110" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">email</text>
<text x="20" y="130" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">organization_id</text>
</g>
<!-- Session Entity -->
<g transform="translate(60, 320)">
<rect x="0" y="0" width="160" height="140" rx="10" fill="url(#sessionGradient)" filter="url(#glow)"/>
<text x="80" y="30" fill="#ffffff" font-family="Arial, sans-serif" font-size="16" font-weight="bold" text-anchor="middle">💬 sessions</text>
<line x1="10" y1="45" x2="150" y2="45" stroke="#ffffff" stroke-opacity="0.3"/>
<text x="20" y="70" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">🔑 id (UUID)</text>
<text x="20" y="90" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">🔗 user_id</text>
<text x="20" y="110" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">🔗 bot_id</text>
<text x="20" y="130" fill="#ffffff" font-family="Arial, sans-serif" font-size="12">context (JSONB)</text>
</g>
<!-- User KB Associations (Junction Table) -->
<g transform="translate(320, 200)">
<rect x="0" y="0" width="200" height="160" rx="10" fill="url(#assocGradient)" filter="url(#glow)"/>
<text x="100" y="30" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="14" font-weight="bold" text-anchor="middle">🔗 user_kb_associations</text>
<line x1="10" y1="45" x2="190" y2="45" stroke="#1a1a2e" stroke-opacity="0.3"/>
<text x="20" y="70" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">🔑 id (UUID)</text>
<text x="20" y="90" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">🔗 user_id</text>
<text x="20" y="110" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">🔗 collection_id</text>
<text x="20" y="130" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">permission_level</text>
<text x="20" y="150" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">granted_at</text>
</g>
<!-- KB Collections Entity -->
<g transform="translate(620, 120)">
<rect x="0" y="0" width="180" height="160" rx="10" fill="url(#kbGradient)" filter="url(#glow)"/>
<text x="90" y="30" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="16" font-weight="bold" text-anchor="middle">📚 kb_collections</text>
<line x1="10" y1="45" x2="170" y2="45" stroke="#1a1a2e" stroke-opacity="0.3"/>
<text x="20" y="70" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">🔑 id (UUID)</text>
<text x="20" y="90" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">🔗 bot_id</text>
<text x="20" y="110" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">name</text>
<text x="20" y="130" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">description</text>
<text x="20" y="150" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">visibility</text>
</g>
<!-- KB Documents Entity -->
<g transform="translate(620, 340)">
<rect x="0" y="0" width="180" height="160" rx="10" fill="url(#docGradient)" filter="url(#glow)"/>
<text x="90" y="30" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="16" font-weight="bold" text-anchor="middle">📄 kb_documents</text>
<line x1="10" y1="45" x2="170" y2="45" stroke="#1a1a2e" stroke-opacity="0.3"/>
<text x="20" y="70" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">🔑 id (UUID)</text>
<text x="20" y="90" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">🔗 collection_id</text>
<text x="20" y="110" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">title</text>
<text x="20" y="130" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">content</text>
<text x="20" y="150" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12">embeddings</text>
</g>
<!-- Connection Lines -->
<!-- User to Association -->
<path d="M220,190 L320,260" stroke="#888" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<text x="250" y="210" fill="#cccccc" font-family="Arial, sans-serif" font-size="11" transform="rotate(-25, 250, 210)">1:N</text>
<!-- Session to User -->
<path d="M140,320 L140,260" stroke="#888" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<text x="150" y="295" fill="#cccccc" font-family="Arial, sans-serif" font-size="11">N:1</text>
<!-- Association to Collection -->
<path d="M520,260 L620,200" stroke="#888" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<text x="555" y="215" fill="#cccccc" font-family="Arial, sans-serif" font-size="11" transform="rotate(25, 555, 215)">N:1</text>
<!-- Collection to Documents -->
<path d="M710,280 L710,340" stroke="#888" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<text x="720" y="315" fill="#cccccc" font-family="Arial, sans-serif" font-size="11">1:N</text>
<!-- Access Flow Indicators -->
<g transform="translate(50, 510)">
<rect x="0" y="0" width="800" height="80" rx="8" fill="#ffffff" fill-opacity="0.05" stroke="#4facfe" stroke-opacity="0.3"/>
<text x="400" y="25" fill="#4facfe" font-family="Arial, sans-serif" font-size="14" font-weight="bold" text-anchor="middle">Access Flow Steps</text>
<!-- Step 1 -->
<circle cx="80" cy="55" r="15" fill="url(#userGradient)"/>
<text x="80" y="60" fill="#ffffff" font-family="Arial, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">1</text>
<text x="135" y="60" fill="#cccccc" font-family="Arial, sans-serif" font-size="11" text-anchor="start">User authenticates</text>
<!-- Step 2 -->
<circle cx="280" cy="55" r="15" fill="url(#assocGradient)"/>
<text x="280" y="60" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">2</text>
<text x="335" y="60" fill="#cccccc" font-family="Arial, sans-serif" font-size="11" text-anchor="start">Check permissions</text>
<!-- Step 3 -->
<circle cx="480" cy="55" r="15" fill="url(#kbGradient)"/>
<text x="480" y="60" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">3</text>
<text x="535" y="60" fill="#cccccc" font-family="Arial, sans-serif" font-size="11" text-anchor="start">Access collection</text>
<!-- Step 4 -->
<circle cx="680" cy="55" r="15" fill="url(#docGradient)"/>
<text x="680" y="60" fill="#1a1a2e" font-family="Arial, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">4</text>
<text x="735" y="60" fill="#cccccc" font-family="Arial, sans-serif" font-size="11" text-anchor="start">Retrieve docs</text>
</g>
<!-- Permission Levels Legend -->
<g transform="translate(280, 420)">
<rect x="0" y="0" width="280" height="70" rx="6" fill="#ffffff" fill-opacity="0.05" stroke="#fa709a" stroke-opacity="0.3"/>
<text x="140" y="20" fill="#fa709a" font-family="Arial, sans-serif" font-size="12" font-weight="bold" text-anchor="middle">Permission Levels</text>
<text x="20" y="42" fill="#43e97b" font-family="Arial, sans-serif" font-size="11">● READ</text>
<text x="90" y="42" fill="#4facfe" font-family="Arial, sans-serif" font-size="11">● WRITE</text>
<text x="160" y="42" fill="#f5576c" font-family="Arial, sans-serif" font-size="11">● ADMIN</text>
<text x="230" y="42" fill="#fee140" font-family="Arial, sans-serif" font-size="11">● OWNER</text>
<text x="140" y="60" fill="#888888" font-family="Arial, sans-serif" font-size="10" text-anchor="middle">Stored in user_kb_associations.permission_level</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View file

@ -0,0 +1,257 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 700">
<defs>
<linearGradient id="bgGradDetail" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1" />
<stop offset="100%" style="stop-color:#16213e;stop-opacity:1" />
</linearGradient>
<linearGradient id="tableGradDetail" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#0f3460;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1a1a2e;stop-opacity:1" />
</linearGradient>
<filter id="shadowDetail">
<feDropShadow dx="2" dy="2" stdDeviation="3" flood-opacity="0.3"/>
</filter>
</defs>
<!-- Background -->
<rect width="1100" height="700" fill="url(#bgGradDetail)" rx="12"/>
<!-- Title -->
<text x="550" y="35" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="20" font-weight="bold">Detailed Database Schema</text>
<!-- Organizations Table -->
<g transform="translate(30, 60)" filter="url(#shadowDetail)">
<rect width="160" height="145" rx="6" fill="url(#tableGradDetail)" stroke="#e94560" stroke-width="2"/>
<rect width="160" height="26" rx="6" fill="#e94560"/>
<text x="80" y="18" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">organizations</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#a0a0a0" font-family="monospace" font-size="9">name VARCHAR(255)</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">slug VARCHAR(100)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">settings JSONB</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">updated_at TIMESTAMPTZ</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">deleted_at TIMESTAMPTZ</text>
<text x="10" y="140" fill="#60a5fa" font-family="monospace" font-size="8">IDX: slug (unique)</text>
</g>
<!-- Bots Table -->
<g transform="translate(220, 60)" filter="url(#shadowDetail)">
<rect width="170" height="175" rx="6" fill="url(#tableGradDetail)" stroke="#4ade80" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#4ade80"/>
<text x="85" y="18" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">bots</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 organization_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">name VARCHAR(255)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">description TEXT</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">config JSONB</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">status VARCHAR(50)</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">llm_provider VARCHAR</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">updated_at TIMESTAMPTZ</text>
<text x="10" y="168" fill="#60a5fa" font-family="monospace" font-size="8">IDX: org_id, name</text>
</g>
<!-- Users Table -->
<g transform="translate(30, 230)" filter="url(#shadowDetail)">
<rect width="170" height="205" rx="6" fill="url(#tableGradDetail)" stroke="#60a5fa" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#60a5fa"/>
<text x="85" y="18" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">users</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 organization_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">username VARCHAR(100)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">email VARCHAR(255)</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">password_hash TEXT</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">display_name VARCHAR</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">avatar_url TEXT</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">role VARCHAR(50)</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">preferences JSONB</text>
<text x="10" y="168" fill="#a0a0a0" font-family="monospace" font-size="9">last_login TIMESTAMPTZ</text>
<text x="10" y="182" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="196" fill="#60a5fa" font-family="monospace" font-size="8">IDX: email (unique)</text>
</g>
<!-- Sessions Table -->
<g transform="translate(220, 260)" filter="url(#shadowDetail)">
<rect width="175" height="190" rx="6" fill="url(#tableGradDetail)" stroke="#f472b6" stroke-width="2"/>
<rect width="175" height="26" rx="6" fill="#f472b6"/>
<text x="87" y="18" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">sessions</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 user_id UUID</text>
<text x="10" y="70" fill="#f472b6" font-family="monospace" font-size="9">🔗 bot_id UUID</text>
<text x="10" y="84" fill="#f472b6" font-family="monospace" font-size="9">🔗 kb_collection_id UUID</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">channel VARCHAR(50)</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">channel_user_id TEXT</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">context JSONB</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">started_at TIMESTAMPTZ</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">last_active TIMESTAMPTZ</text>
<text x="10" y="168" fill="#a0a0a0" font-family="monospace" font-size="9">expires_at TIMESTAMPTZ</text>
<text x="10" y="182" fill="#60a5fa" font-family="monospace" font-size="8">IDX: user_id, bot_id</text>
</g>
<!-- Messages Table -->
<g transform="translate(420, 260)" filter="url(#shadowDetail)">
<rect width="170" height="175" rx="6" fill="url(#tableGradDetail)" stroke="#fbbf24" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#fbbf24"/>
<text x="85" y="18" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">messages</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 session_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">role VARCHAR(20)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">content TEXT</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">metadata JSONB</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">tokens_used INTEGER</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">tool_calls JSONB</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">edited_at TIMESTAMPTZ</text>
<text x="10" y="168" fill="#60a5fa" font-family="monospace" font-size="8">IDX: session_id, created</text>
</g>
<!-- KB Collections Table -->
<g transform="translate(420, 60)" filter="url(#shadowDetail)">
<rect width="170" height="160" rx="6" fill="url(#tableGradDetail)" stroke="#a78bfa" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#a78bfa"/>
<text x="85" y="18" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">kb_collections</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 bot_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">name VARCHAR(255)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">description TEXT</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">embedding_model VARCHAR</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">chunk_size INTEGER</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">vector_config JSONB</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="154" fill="#60a5fa" font-family="monospace" font-size="8">IDX: bot_id, name</text>
</g>
<!-- KB Documents Table -->
<g transform="translate(620, 60)" filter="url(#shadowDetail)">
<rect width="170" height="190" rx="6" fill="url(#tableGradDetail)" stroke="#c084fc" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#c084fc"/>
<text x="85" y="18" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">kb_documents</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 collection_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">title VARCHAR(500)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">source_path TEXT</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">content_hash VARCHAR</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">chunk_count INTEGER</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">status VARCHAR(50)</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">metadata JSONB</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">indexed_at TIMESTAMPTZ</text>
<text x="10" y="168" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="182" fill="#60a5fa" font-family="monospace" font-size="8">IDX: collection_id</text>
</g>
<!-- Basic Tools Table -->
<g transform="translate(820, 60)" filter="url(#shadowDetail)">
<rect width="170" height="175" rx="6" fill="url(#tableGradDetail)" stroke="#22d3d1" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#22d3d1"/>
<text x="85" y="18" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">basic_tools</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 bot_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">name VARCHAR(100)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">description TEXT</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">source_code TEXT</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">parameters JSONB</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">is_active BOOLEAN</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">compiled_at TIMESTAMPTZ</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="168" fill="#60a5fa" font-family="monospace" font-size="8">IDX: bot_id, name</text>
</g>
<!-- Files Table -->
<g transform="translate(620, 280)" filter="url(#shadowDetail)">
<rect width="170" height="175" rx="6" fill="url(#tableGradDetail)" stroke="#fb923c" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#fb923c"/>
<text x="85" y="18" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">files</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 bot_id UUID</text>
<text x="10" y="70" fill="#f472b6" font-family="monospace" font-size="9">🔗 kb_doc_id UUID</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">path VARCHAR(1000)</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">filename VARCHAR(255)</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">mime_type VARCHAR(100)</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">size_bytes BIGINT</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">storage_key TEXT</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="168" fill="#60a5fa" font-family="monospace" font-size="8">IDX: bot_id, path</text>
</g>
<!-- Bot Memories Table -->
<g transform="translate(820, 280)" filter="url(#shadowDetail)">
<rect width="170" height="160" rx="6" fill="url(#tableGradDetail)" stroke="#34d399" stroke-width="2"/>
<rect width="170" height="26" rx="6" fill="#34d399"/>
<text x="85" y="18" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">bot_memories</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 bot_id UUID</text>
<text x="10" y="70" fill="#f472b6" font-family="monospace" font-size="9">🔗 user_id UUID</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">key VARCHAR(255)</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">value JSONB</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">scope VARCHAR(50)</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">expires_at TIMESTAMPTZ</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="154" fill="#60a5fa" font-family="monospace" font-size="8">IDX: bot_id, user, key</text>
</g>
<!-- System Automations Table -->
<g transform="translate(30, 460)" filter="url(#shadowDetail)">
<rect width="180" height="175" rx="6" fill="url(#tableGradDetail)" stroke="#f43f5e" stroke-width="2"/>
<rect width="180" height="26" rx="6" fill="#f43f5e"/>
<text x="90" y="18" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">system_automations</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 bot_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">name VARCHAR(255)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">trigger_type VARCHAR</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">schedule JSONB</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">action JSONB</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">is_active BOOLEAN</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">last_run TIMESTAMPTZ</text>
<text x="10" y="154" fill="#a0a0a0" font-family="monospace" font-size="9">next_run TIMESTAMPTZ</text>
<text x="10" y="168" fill="#60a5fa" font-family="monospace" font-size="8">IDX: bot_id, next_run</text>
</g>
<!-- User Email Accounts Table -->
<g transform="translate(240, 475)" filter="url(#shadowDetail)">
<rect width="175" height="160" rx="6" fill="url(#tableGradDetail)" stroke="#06b6d4" stroke-width="2"/>
<rect width="175" height="26" rx="6" fill="#06b6d4"/>
<text x="87" y="18" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">user_email_accounts</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 user_id UUID</text>
<text x="10" y="70" fill="#a0a0a0" font-family="monospace" font-size="9">email VARCHAR(255)</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">provider VARCHAR(50)</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">credentials_enc TEXT</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">is_primary BOOLEAN</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">sync_status VARCHAR</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">last_sync TIMESTAMPTZ</text>
<text x="10" y="154" fill="#60a5fa" font-family="monospace" font-size="8">IDX: user_id, email</text>
</g>
<!-- Clicks/Analytics Table -->
<g transform="translate(445, 475)" filter="url(#shadowDetail)">
<rect width="165" height="160" rx="6" fill="url(#tableGradDetail)" stroke="#8b5cf6" stroke-width="2"/>
<rect width="165" height="26" rx="6" fill="#8b5cf6"/>
<text x="82" y="18" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">clicks</text>
<text x="10" y="42" fill="#4ade80" font-family="monospace" font-size="9">🔑 id UUID</text>
<text x="10" y="56" fill="#f472b6" font-family="monospace" font-size="9">🔗 session_id UUID</text>
<text x="10" y="70" fill="#f472b6" font-family="monospace" font-size="9">🔗 message_id UUID</text>
<text x="10" y="84" fill="#a0a0a0" font-family="monospace" font-size="9">event_type VARCHAR</text>
<text x="10" y="98" fill="#a0a0a0" font-family="monospace" font-size="9">target VARCHAR(255)</text>
<text x="10" y="112" fill="#a0a0a0" font-family="monospace" font-size="9">metadata JSONB</text>
<text x="10" y="126" fill="#a0a0a0" font-family="monospace" font-size="9">created_at TIMESTAMPTZ</text>
<text x="10" y="140" fill="#a0a0a0" font-family="monospace" font-size="9">ip_address INET</text>
<text x="10" y="154" fill="#60a5fa" font-family="monospace" font-size="8">IDX: session_id, time</text>
</g>
<!-- Legend -->
<g transform="translate(640, 475)">
<rect width="350" height="145" rx="8" fill="#0f3460" opacity="0.5"/>
<text x="175" y="22" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">Legend</text>
<text x="20" y="45" fill="#4ade80" font-family="monospace" font-size="10">🔑</text>
<text x="40" y="45" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">Primary Key (UUID)</text>
<text x="20" y="65" fill="#f472b6" font-family="monospace" font-size="10">🔗</text>
<text x="40" y="65" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">Foreign Key Reference</text>
<text x="20" y="85" fill="#60a5fa" font-family="system-ui, sans-serif" font-size="10">IDX:</text>
<text x="50" y="85" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">Database Index</text>
<text x="180" y="45" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">JSONB = JSON Binary</text>
<text x="180" y="65" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">TIMESTAMPTZ = Timestamp w/ TZ</text>
<text x="180" y="85" fill="#a0a0a0" font

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -0,0 +1,155 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 500">
<defs>
<linearGradient id="bgGradSchema" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1" />
<stop offset="100%" style="stop-color:#16213e;stop-opacity:1" />
</linearGradient>
<linearGradient id="tableGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#0f3460;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1a1a2e;stop-opacity:1" />
</linearGradient>
<filter id="shadow">
<feDropShadow dx="2" dy="2" stdDeviation="3" flood-opacity="0.3"/>
</filter>
</defs>
<!-- Background -->
<rect width="900" height="500" fill="url(#bgGradSchema)" rx="12"/>
<!-- Title -->
<text x="450" y="40" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="22" font-weight="bold">Database Schema Overview</text>
<text x="450" y="62" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="12">PostgreSQL + Diesel ORM</text>
<!-- Organizations Table -->
<g transform="translate(50, 90)" filter="url(#shadow)">
<rect width="140" height="100" rx="6" fill="url(#tableGrad)" stroke="#e94560" stroke-width="2"/>
<rect width="140" height="28" rx="6" fill="#e94560"/>
<text x="70" y="19" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">organizations</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">name VARCHAR</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">created_at TIMESTAMP</text>
</g>
<!-- Bots Table -->
<g transform="translate(250, 90)" filter="url(#shadow)">
<rect width="140" height="120" rx="6" fill="url(#tableGrad)" stroke="#4ade80" stroke-width="2"/>
<rect width="140" height="28" rx="6" fill="#4ade80"/>
<text x="70" y="19" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">bots</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">org_id UUID FK</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">name VARCHAR</text>
<text x="12" y="93" fill="#a0a0a0" font-family="monospace" font-size="10">config JSONB</text>
</g>
<!-- Users Table -->
<g transform="translate(50, 280)" filter="url(#shadow)">
<rect width="140" height="130" rx="6" fill="url(#tableGrad)" stroke="#60a5fa" stroke-width="2"/>
<rect width="140" height="28" rx="6" fill="#60a5fa"/>
<text x="70" y="19" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">users</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">username VARCHAR</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">email VARCHAR</text>
<text x="12" y="93" fill="#a0a0a0" font-family="monospace" font-size="10">password_hash TEXT</text>
<text x="12" y="108" fill="#a0a0a0" font-family="monospace" font-size="10">created_at TIMESTAMP</text>
</g>
<!-- Sessions Table -->
<g transform="translate(250, 260)" filter="url(#shadow)">
<rect width="150" height="140" rx="6" fill="url(#tableGrad)" stroke="#f472b6" stroke-width="2"/>
<rect width="150" height="28" rx="6" fill="#f472b6"/>
<text x="75" y="19" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">sessions</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">user_id UUID FK</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">bot_id UUID FK</text>
<text x="12" y="93" fill="#a0a0a0" font-family="monospace" font-size="10">started_at TIMESTAMP</text>
<text x="12" y="108" fill="#a0a0a0" font-family="monospace" font-size="10">last_active TIMESTAMP</text>
<text x="12" y="123" fill="#a0a0a0" font-family="monospace" font-size="10">kb_id UUID FK</text>
</g>
<!-- Messages Table -->
<g transform="translate(460, 260)" filter="url(#shadow)">
<rect width="150" height="130" rx="6" fill="url(#tableGrad)" stroke="#fbbf24" stroke-width="2"/>
<rect width="150" height="28" rx="6" fill="#fbbf24"/>
<text x="75" y="19" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">messages</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">session_id UUID FK</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">role VARCHAR</text>
<text x="12" y="93" fill="#a0a0a0" font-family="monospace" font-size="10">content TEXT</text>
<text x="12" y="108" fill="#a0a0a0" font-family="monospace" font-size="10">timestamp TIMESTAMP</text>
</g>
<!-- Knowledge Base Table -->
<g transform="translate(460, 90)" filter="url(#shadow)">
<rect width="160" height="120" rx="6" fill="url(#tableGrad)" stroke="#a78bfa" stroke-width="2"/>
<rect width="160" height="28" rx="6" fill="#a78bfa"/>
<text x="80" y="19" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">kb_collections</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">bot_id UUID FK</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">name VARCHAR</text>
<text x="12" y="93" fill="#a0a0a0" font-family="monospace" font-size="10">vector_config JSONB</text>
</g>
<!-- Tools Table -->
<g transform="translate(680, 90)" filter="url(#shadow)">
<rect width="150" height="120" rx="6" fill="url(#tableGrad)" stroke="#22d3d1" stroke-width="2"/>
<rect width="150" height="28" rx="6" fill="#22d3d1"/>
<text x="75" y="19" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">basic_tools</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">bot_id UUID FK</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">name VARCHAR</text>
<text x="12" y="93" fill="#a0a0a0" font-family="monospace" font-size="10">definition JSONB</text>
</g>
<!-- Files Table -->
<g transform="translate(680, 280)" filter="url(#shadow)">
<rect width="150" height="130" rx="6" fill="url(#tableGrad)" stroke="#fb923c" stroke-width="2"/>
<rect width="150" height="28" rx="6" fill="#fb923c"/>
<text x="75" y="19" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">files</text>
<text x="12" y="48" fill="#a0a0a0" font-family="monospace" font-size="10">id UUID PK</text>
<text x="12" y="63" fill="#a0a0a0" font-family="monospace" font-size="10">kb_id UUID FK</text>
<text x="12" y="78" fill="#a0a0a0" font-family="monospace" font-size="10">path VARCHAR</text>
<text x="12" y="93" fill="#a0a0a0" font-family="monospace" font-size="10">mime_type VARCHAR</text>
<text x="12" y="108" fill="#a0a0a0" font-family="monospace" font-size="10">size INTEGER</text>
</g>
<!-- Relationship Lines -->
<!-- Org to Bots -->
<line x1="190" y1="140" x2="250" y2="140" stroke="#e94560" stroke-width="2" stroke-dasharray="5,3"/>
<circle cx="190" cy="140" r="4" fill="#e94560"/>
<text x="195" y="132" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">1:N</text>
<!-- Bots to KB -->
<line x1="390" y1="150" x2="460" y2="150" stroke="#4ade80" stroke-width="2" stroke-dasharray="5,3"/>
<circle cx="390" cy="150" r="4" fill="#4ade80"/>
<!-- Bots to Tools -->
<path d="M390 130 Q425 100 460 130" stroke="#4ade80" stroke-width="2" stroke-dasharray="5,3" fill="none"/>
<!-- Users to Sessions -->
<line x1="190" y1="345" x2="250" y2="330" stroke="#60a5fa" stroke-width="2" stroke-dasharray="5,3"/>
<circle cx="190" cy="345" r="4" fill="#60a5fa"/>
<text x="195" y="360" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">1:N</text>
<!-- Sessions to Messages -->
<line x1="400" y1="330" x2="460" y2="330" stroke="#f472b6" stroke-width="2" stroke-dasharray="5,3"/>
<circle cx="400" cy="330" r="4" fill="#f472b6"/>
<text x="415" y="322" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">1:N</text>
<!-- Bots to Sessions -->
<line x1="320" y1="210" x2="320" y2="260" stroke="#4ade80" stroke-width="2" stroke-dasharray="5,3"/>
<circle cx="320" cy="210" r="4" fill="#4ade80"/>
<!-- KB to Files -->
<line x1="620" y1="150" x2="680" y2="310" stroke="#a78bfa" stroke-width="2" stroke-dasharray="5,3"/>
<circle cx="620" cy="150" r="4" fill="#a78bfa"/>
<!-- Legend -->
<g transform="translate(50, 450)">
<text x="0" y="0" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">Legend:</text>
<circle cx="80" cy="-4" r="4" fill="#e94560"/>
<text x="90" y="0" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">One-to-Many</text>
<line x1="170" y1="-4" x2="200" y2="-4" stroke="#a0a0a0" stroke-width="2" stroke-dasharray="5,3"/>
<text x="210" y="0" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">Foreign Key</text>
<text x="300" y="0" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">PK = Primary Key | FK = Foreign Key</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

142
src/assets/session-flow.svg Normal file
View file

@ -0,0 +1,142 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 450">
<defs>
<linearGradient id="bgGradSession" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:1" />
<stop offset="100%" style="stop-color:#16213e;stop-opacity:1" />
</linearGradient>
<linearGradient id="nodeGrad" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#0f3460;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1a1a2e;stop-opacity:1" />
</linearGradient>
<marker id="arrowSession" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#4ade80"/>
</marker>
<marker id="arrowPink" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#f472b6"/>
</marker>
<marker id="arrowYellow" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#fbbf24"/>
</marker>
<filter id="glowSession">
<feGaussianBlur stdDeviation="2" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect width="800" height="450" fill="url(#bgGradSession)" rx="12"/>
<!-- Title -->
<text x="400" y="35" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="20" font-weight="bold">Session Flow Diagram</text>
<text x="400" y="55" text-anchor="middle" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="12">User → Session → Message Relationships</text>
<!-- User Node -->
<g transform="translate(80, 140)">
<rect width="120" height="100" rx="10" fill="url(#nodeGrad)" stroke="#60a5fa" stroke-width="3" filter="url(#glowSession)"/>
<rect width="120" height="30" rx="10" fill="#60a5fa"/>
<text x="60" y="20" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">User</text>
<circle cx="60" cy="60" r="20" fill="#1a1a2e" stroke="#60a5fa" stroke-width="2"/>
<circle cx="60" cy="55" r="8" fill="#60a5fa"/>
<path d="M45 75 Q60 85 75 75" fill="none" stroke="#60a5fa" stroke-width="2"/>
</g>
<!-- Bot Node -->
<g transform="translate(80, 290)">
<rect width="120" height="100" rx="10" fill="url(#nodeGrad)" stroke="#4ade80" stroke-width="3" filter="url(#glowSession)"/>
<rect width="120" height="30" rx="10" fill="#4ade80"/>
<text x="60" y="20" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">Bot</text>
<rect x="35" y="45" width="50" height="40" rx="6" fill="#1a1a2e" stroke="#4ade80" stroke-width="2"/>
<circle cx="50" cy="60" r="4" fill="#4ade80"/>
<circle cx="70" cy="60" r="4" fill="#4ade80"/>
<path d="M45 72 Q60 78 75 72" fill="none" stroke="#4ade80" stroke-width="2"/>
</g>
<!-- Session Node (Center) -->
<g transform="translate(300, 180)">
<rect width="140" height="130" rx="10" fill="url(#nodeGrad)" stroke="#f472b6" stroke-width="3" filter="url(#glowSession)"/>
<rect width="140" height="30" rx="10" fill="#f472b6"/>
<text x="70" y="20" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">Session</text>
<text x="15" y="50" fill="#a0a0a0" font-family="monospace" font-size="9">id: uuid</text>
<text x="15" y="65" fill="#a0a0a0" font-family="monospace" font-size="9">user_id: fk</text>
<text x="15" y="80" fill="#a0a0a0" font-family="monospace" font-size="9">bot_id: fk</text>
<text x="15" y="95" fill="#a0a0a0" font-family="monospace" font-size="9">started_at</text>
<text x="15" y="110" fill="#a0a0a0" font-family="monospace" font-size="9">last_active</text>
</g>
<!-- Messages Node -->
<g transform="translate(520, 130)">
<rect width="140" height="110" rx="10" fill="url(#nodeGrad)" stroke="#fbbf24" stroke-width="3" filter="url(#glowSession)"/>
<rect width="140" height="30" rx="10" fill="#fbbf24"/>
<text x="70" y="20" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">Messages</text>
<text x="15" y="50" fill="#a0a0a0" font-family="monospace" font-size="9">id: uuid</text>
<text x="15" y="65" fill="#a0a0a0" font-family="monospace" font-size="9">session_id: fk</text>
<text x="15" y="80" fill="#a0a0a0" font-family="monospace" font-size="9">role: user|bot</text>
<text x="15" y="95" fill="#a0a0a0" font-family="monospace" font-size="9">content: text</text>
</g>
<!-- Knowledge Base Node -->
<g transform="translate(520, 280)">
<rect width="140" height="100" rx="10" fill="url(#nodeGrad)" stroke="#a78bfa" stroke-width="3" filter="url(#glowSession)"/>
<rect width="140" height="30" rx="10" fill="#a78bfa"/>
<text x="70" y="20" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="12" font-weight="bold">KB Collection</text>
<text x="15" y="50" fill="#a0a0a0" font-family="monospace" font-size="9">id: uuid</text>
<text x="15" y="65" fill="#a0a0a0" font-family="monospace" font-size="9">name</text>
<text x="15" y="80" fill="#a0a0a0" font-family="monospace" font-size="9">documents[]</text>
</g>
<!-- Connection Lines -->
<!-- User to Session -->
<path d="M200 190 L300 220" stroke="#60a5fa" stroke-width="2" fill="none" marker-end="url(#arrowSession)"/>
<text x="235" y="195" fill="#60a5fa" font-family="system-ui, sans-serif" font-size="10">1:N</text>
<!-- Bot to Session -->
<path d="M200 340 L300 280" stroke="#4ade80" stroke-width="2" fill="none" marker-end="url(#arrowSession)"/>
<text x="235" y="325" fill="#4ade80" font-family="system-ui, sans-serif" font-size="10">1:N</text>
<!-- Session to Messages -->
<path d="M440 200 L520 185" stroke="#f472b6" stroke-width="2" fill="none" marker-end="url(#arrowPink)"/>
<text x="470" y="182" fill="#f472b6" font-family="system-ui, sans-serif" font-size="10">1:N</text>
<!-- Session to KB -->
<path d="M440 280 L520 310" stroke="#a78bfa" stroke-width="2" fill="none" stroke-dasharray="5,3"/>
<text x="470" y="305" fill="#a78bfa" font-family="system-ui, sans-serif" font-size="10">N:1</text>
<!-- Flow Description -->
<g transform="translate(700, 140)">
<rect x="-20" y="-10" width="100" height="220" rx="8" fill="#0f3460" opacity="0.5"/>
<text x="30" y="10" text-anchor="middle" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">Flow</text>
<circle cx="10" cy="40" r="8" fill="#60a5fa"/>
<text x="10" y="44" text-anchor="middle" fill="#fff" font-family="system-ui, sans-serif" font-size="9">1</text>
<text x="30" y="44" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">Connect</text>
<circle cx="10" cy="75" r="8" fill="#4ade80"/>
<text x="10" y="79" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="9">2</text>
<text x="30" y="79" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">Select Bot</text>
<circle cx="10" cy="110" r="8" fill="#f472b6"/>
<text x="10" y="114" text-anchor="middle" fill="#fff" font-family="system-ui, sans-serif" font-size="9">3</text>
<text x="30" y="114" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">Session</text>
<circle cx="10" cy="145" r="8" fill="#fbbf24"/>
<text x="10" y="149" text-anchor="middle" fill="#1a1a2e" font-family="system-ui, sans-serif" font-size="9">4</text>
<text x="30" y="149" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">Chat</text>
<circle cx="10" cy="180" r="8" fill="#a78bfa"/>
<text x="10" y="184" text-anchor="middle" fill="#fff" font-family="system-ui, sans-serif" font-size="9">5</text>
<text x="30" y="184" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="9">Query KB</text>
</g>
<!-- Legend -->
<g transform="translate(50, 410)">
<text x="0" y="0" fill="#ffffff" font-family="system-ui, sans-serif" font-size="11" font-weight="bold">Relationships:</text>
<line x1="100" y1="-5" x2="140" y2="-5" stroke="#60a5fa" stroke-width="2" marker-end="url(#arrowSession)"/>
<text x="150" y="0" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">One-to-Many (1:N)</text>
<line x1="280" y1="-5" x2="320" y2="-5" stroke="#a78bfa" stroke-width="2" stroke-dasharray="5,3"/>
<text x="330" y="0" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">Many-to-One (N:1)</text>
<text x="500" y="0" fill="#a0a0a0" font-family="system-ui, sans-serif" font-size="10">fk = Foreign Key</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

277
src/designer-panel.css Normal file
View file

@ -0,0 +1,277 @@
/**
* Designer Panel CSS
*
* Right-side panel styling for Designer conversation examples in documentation.
* This represents Designer as an accessory panel, not a WhatsApp-style chat.
*
* Usage:
* <div class="designer-panel">
* <div class="designer-header">
* <span class="designer-title">Designer</span>
* <span class="designer-status"> Online</span>
* </div>
* <div class="designer-messages">
* <div class="designer-msg user">User message</div>
* <div class="designer-msg assistant">Assistant response</div>
* </div>
* </div>
*/
/* ============================================
Panel Container
============================================ */
.designer-panel {
background-color: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
margin: 20px 0;
max-width: 420px;
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
sans-serif;
font-size: 14px;
overflow: hidden;
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
.designer-panel {
background-color: #1e293b;
border-color: #334155;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
}
/* ============================================
Panel Header
============================================ */
.designer-header {
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
padding: 12px 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.designer-title {
color: #ffffff;
font-weight: 600;
font-size: 14px;
letter-spacing: 0.3px;
}
.designer-status {
color: rgba(255, 255, 255, 0.9);
font-size: 12px;
}
.designer-file {
color: rgba(255, 255, 255, 0.85);
font-size: 11px;
font-family: "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
background: rgba(255, 255, 255, 0.15);
padding: 2px 8px;
border-radius: 4px;
}
/* ============================================
Messages Container
============================================ */
.designer-messages {
padding: 16px;
display: flex;
flex-direction: column;
gap: 12px;
}
/* ============================================
Individual Messages
============================================ */
.designer-msg {
padding: 10px 14px;
border-radius: 10px;
line-height: 1.5;
max-width: 95%;
}
/* User message - right aligned, purple tint */
.designer-msg.user {
background-color: #eef2ff;
color: #3730a3;
align-self: flex-end;
border-bottom-right-radius: 4px;
}
/* Assistant message - left aligned, gray */
.designer-msg.assistant {
background-color: #f8fafc;
color: #334155;
align-self: flex-start;
border-bottom-left-radius: 4px;
border: 1px solid #e2e8f0;
}
/* Dark mode messages */
@media (prefers-color-scheme: dark) {
.designer-msg.user {
background-color: #3730a3;
color: #e0e7ff;
}
.designer-msg.assistant {
background-color: #0f172a;
color: #e2e8f0;
border-color: #334155;
}
}
/* ============================================
Message Content
============================================ */
.designer-msg p {
margin: 0 0 6px 0;
}
.designer-msg p:last-child {
margin-bottom: 0;
}
.designer-msg strong {
font-weight: 600;
}
.designer-msg code {
background-color: rgba(0, 0, 0, 0.06);
padding: 2px 6px;
border-radius: 4px;
font-family: "SF Mono", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 12px;
}
@media (prefers-color-scheme: dark) {
.designer-msg code {
background-color: rgba(255, 255, 255, 0.1);
}
}
/* Success indicator */
.designer-msg .success {
color: #10b981;
}
/* Warning indicator */
.designer-msg .warning {
color: #f59e0b;
}
/* Error indicator */
.designer-msg .error {
color: #ef4444;
}
/* ============================================
Action Buttons in Messages
============================================ */
.designer-msg .designer-action {
display: inline-block;
background-color: #6366f1;
color: #ffffff;
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
margin: 6px 4px 0 0;
cursor: pointer;
transition: background-color 0.15s ease;
}
.designer-msg .designer-action:hover {
background-color: #4f46e5;
}
.designer-msg .designer-action.secondary {
background-color: #e2e8f0;
color: #475569;
}
.designer-msg .designer-action.secondary:hover {
background-color: #cbd5e1;
}
@media (prefers-color-scheme: dark) {
.designer-msg .designer-action.secondary {
background-color: #334155;
color: #e2e8f0;
}
.designer-msg .designer-action.secondary:hover {
background-color: #475569;
}
}
/* ============================================
Typing Indicator
============================================ */
.designer-typing {
display: flex;
gap: 4px;
padding: 10px 14px;
}
.designer-typing span {
width: 8px;
height: 8px;
background-color: #94a3b8;
border-radius: 50%;
animation: typing 1.4s infinite ease-in-out both;
}
.designer-typing span:nth-child(1) {
animation-delay: -0.32s;
}
.designer-typing span:nth-child(2) {
animation-delay: -0.16s;
}
@keyframes typing {
0%,
80%,
100% {
transform: scale(0.6);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
/* ============================================
Variants
============================================ */
/* Full width variant */
.designer-panel.full-width {
max-width: 100%;
}
/* Compact variant */
.designer-panel.compact {
max-width: 360px;
}
.designer-panel.compact .designer-header {
padding: 10px 14px;
}
.designer-panel.compact .designer-messages {
padding: 12px;
gap: 8px;
}
.designer-panel.compact .designer-msg {
padding: 8px 12px;
font-size: 13px;
}