Remove obsolete CAPS.md documentation files
Deleted planning/tracking documents that are no longer needed: - MISSING_IMPLEMENTATIONS.md (all 5 apps now implemented) - GAP_ANALYSIS.md (analysis complete, implemented) - IMPLEMENTATION_SUMMARY.md (implementations done) - LIBRARY_MIGRATION.md (migration guide) - ROADMAP.md (feature planning) - START_CODING_PROMPT.md (coding guide) - CHANGELOG.md (version history) - templates/TEMPLATE_PLAN.md (template planning) - templates/integration/public-apis.gbai/KEYWORDS_CHECKLIST.md - templates/integration/public-apis.gbai/QUICKSTART.md - botlib/VERSION.md (version history) Kept: README.md, PROMPT.md, and SUMMARY.md (mdbook structure)
This commit is contained in:
parent
5b8b1cf7aa
commit
78b359ab06
31 changed files with 2330 additions and 9609 deletions
2504
CHANGELOG.md
2504
CHANGELOG.md
File diff suppressed because it is too large
Load diff
|
|
@ -1,771 +0,0 @@
|
|||
# Code Implementation Roadmap - Closing the Documentation/Code Gap
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**The Problem**: Documentation describes 14 UI applications in the General Bots Suite, but only 6 have fully implemented backends. The other 5 have complete HTML/CSS/JavaScript frontends that are waiting for Rust backend handlers.
|
||||
|
||||
**The Solution**: Use HTMX + Rust to implement minimal backend handlers that render HTML. No additional JavaScript frameworks needed.
|
||||
|
||||
**Timeline**: 2-3 weeks to complete all missing implementations
|
||||
|
||||
---
|
||||
|
||||
## Current State Analysis
|
||||
|
||||
### What Exists (✅ Complete)
|
||||
|
||||
| Component | Status | Where | Notes |
|
||||
|-----------|--------|-------|-------|
|
||||
| **Chat** | ✅ Complete | `/api/sessions`, `/ws` | Real-time messaging, context management |
|
||||
| **Drive** | ✅ Complete | `/api/drive/*` | S3-based file storage, upload/download |
|
||||
| **Tasks** | ✅ Complete | `/api/tasks/*` | Task CRUD, assignment, status tracking |
|
||||
| **Mail** | ✅ Complete | `/api/email/*` | IMAP/SMTP integration, folders, drafts |
|
||||
| **Calendar** | ✅ Complete | CalDAV, `/api/calendar/*` | Event management, CalDAV protocol |
|
||||
| **Meet** | ✅ Complete | `/api/meet/*`, `/ws/meet` | LiveKit integration, video calls |
|
||||
| **Monitoring** | ✅ Complete | `/api/admin/stats` | System metrics, performance data |
|
||||
| **BASIC Compiler** | ✅ Complete | `/src/basic/compiler/` | Dialog validation, script parsing |
|
||||
| **Vector DB** | ✅ Complete | Qdrant integration | Knowledge base embeddings, search |
|
||||
| **LLM Integration** | ✅ Complete | `/src/llm/mod.rs` | Multiple model support, routing |
|
||||
| **HTMX App** | ✅ Complete | `htmx-app.js` | All HTMX infrastructure ready |
|
||||
|
||||
### What's Missing (❌ No Backend)
|
||||
|
||||
| App | Frontend | Backend | Effort | Impact |
|
||||
|-----|----------|---------|--------|--------|
|
||||
| **Analytics** | ✅ Complete HTML/CSS/JS | ❌ No handlers | 4-6 hrs | High (metrics critical) |
|
||||
| **Paper** | ✅ Complete editor | ❌ No document API | 2-3 hrs | High (users want docs) |
|
||||
| **Research** | ✅ Complete UI | 🟡 Partial (JSON only) | 1-2 hrs | Medium (search exists) |
|
||||
| **Designer** | ✅ Complete builder | ❌ No dialog API | 6-8 hrs | Medium (admin feature) |
|
||||
| **Sources** | ✅ Complete grid | ❌ No template API | 2-3 hrs | Low (nice-to-have) |
|
||||
| **Player** | ❌ No HTML | ❌ No handlers | 2-3 hrs | Low (can use Drive) |
|
||||
|
||||
### Database/Infrastructure Status
|
||||
|
||||
| Component | Status | Ready to Use |
|
||||
|-----------|--------|--------------|
|
||||
| PostgreSQL Connection Pool | ✅ | Yes - in AppState |
|
||||
| S3 Drive Integration | ✅ | Yes - Drive module |
|
||||
| Redis Cache | ✅ | Yes - feature gated |
|
||||
| Qdrant Vector DB | ✅ | Yes - VectorDB module |
|
||||
| LLM Models | ✅ | Yes - LLM module |
|
||||
| BASIC Compiler | ✅ | Yes - can call directly |
|
||||
| Askama Templates | ✅ | Yes - multiple examples |
|
||||
| HTMX Framework | ✅ | Yes - in UI already |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### Core Principle: HTMX-First Backend
|
||||
|
||||
**Pattern**: Frontend sends HTMX request → Backend handler → Askama template → HTML response
|
||||
|
||||
```
|
||||
User clicks button with hx-get="/api/resource"
|
||||
↓
|
||||
Browser sends GET to /api/resource
|
||||
↓
|
||||
Rust handler executes
|
||||
↓
|
||||
Handler calls Askama template with data
|
||||
↓
|
||||
Template renders HTML fragment
|
||||
↓
|
||||
HTMX replaces target element with HTML
|
||||
↓
|
||||
Done - no JSON parsing, no JavaScript needed
|
||||
```
|
||||
|
||||
### Why This Approach
|
||||
|
||||
✅ **Minimal Code** - Just Rust + HTML templates, no JavaScript frameworks
|
||||
✅ **Reuses Everything** - Drive, LLM, Compiler, Database already available
|
||||
✅ **Server-Side Rendering** - Better for SEO, accessibility, performance
|
||||
✅ **Existing Infrastructure** - HTMX already loaded in all pages
|
||||
✅ **Type Safe** - Rust compiler catches errors at build time
|
||||
✅ **Fast Development** - Copy patterns from existing modules
|
||||
|
||||
---
|
||||
|
||||
## Implementation Details by App
|
||||
|
||||
### Priority 1: Analytics Dashboard (CRITICAL)
|
||||
|
||||
**Timeline**: 4-6 hours
|
||||
**Complexity**: Low (pure SQL queries)
|
||||
**Impact**: High (essential metrics)
|
||||
|
||||
**What to Create**:
|
||||
|
||||
1. **New Module**: `botserver/src/analytics/mod.rs`
|
||||
- Handler: `async fn analytics_dashboard()`
|
||||
- Handler: `async fn analytics_sessions()`
|
||||
- Handler: `async fn analytics_bots()`
|
||||
- Handler: `async fn analytics_top_queries()`
|
||||
- Handler: `async fn analytics_errors()`
|
||||
|
||||
2. **Database Queries**:
|
||||
```sql
|
||||
SELECT COUNT(*) FROM message_history WHERE created_at > NOW() - INTERVAL;
|
||||
SELECT AVG(response_time) FROM message_history;
|
||||
SELECT COUNT(*) FROM sessions WHERE active = true;
|
||||
SELECT error_count FROM system_metrics;
|
||||
```
|
||||
|
||||
3. **Askama Templates**: `templates/analytics/dashboard.html`
|
||||
```html
|
||||
<div class="metrics-grid">
|
||||
<div class="metric-card">{{ messages_count }}</div>
|
||||
<div class="metric-card">{{ avg_response_time }}ms</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
4. **URL Routes** (add to `urls.rs`):
|
||||
```rust
|
||||
pub const ANALYTICS_DASHBOARD: &'static str = "/api/analytics/dashboard";
|
||||
pub const ANALYTICS_SESSIONS: &'static str = "/api/analytics/sessions";
|
||||
pub const ANALYTICS_BOTS: &'static str = "/api/analytics/bots";
|
||||
```
|
||||
|
||||
5. **Wire in main.rs**:
|
||||
```rust
|
||||
api_router = api_router.merge(analytics::configure());
|
||||
```
|
||||
|
||||
**Frontend Already Has**:
|
||||
- ✅ HTML form with time range selector
|
||||
- ✅ HTMX attributes pointing to `/api/analytics/*`
|
||||
- ✅ Charts expecting data
|
||||
- ✅ Metric cards ready for values
|
||||
|
||||
---
|
||||
|
||||
### Priority 2: Paper Documents (HIGH VALUE)
|
||||
|
||||
**Timeline**: 2-3 hours
|
||||
**Complexity**: Low-Medium (reuse Drive module)
|
||||
**Impact**: High (users want document editor)
|
||||
|
||||
**What to Create**:
|
||||
|
||||
1. **New Module**: `botserver/src/documents/mod.rs`
|
||||
- Handler: `async fn create_document()`
|
||||
- Handler: `async fn list_documents()`
|
||||
- Handler: `async fn get_document()`
|
||||
- Handler: `async fn update_document()`
|
||||
- Handler: `async fn delete_document()`
|
||||
|
||||
2. **Storage Pattern** (reuse Drive):
|
||||
```rust
|
||||
// Store in Drive under .gbdocs/ folder
|
||||
let bucket = format!("{}.gbai", bot_name);
|
||||
let key = format!(".gbdocs/{}/document.md", doc_id);
|
||||
drive_client.put_object(bucket, key, content).await;
|
||||
```
|
||||
|
||||
3. **Document Structure**:
|
||||
```rust
|
||||
pub struct Document {
|
||||
pub id: Uuid,
|
||||
pub title: String,
|
||||
pub content: String,
|
||||
pub doc_type: DocumentType, // draft, note, template
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub user_id: Uuid,
|
||||
}
|
||||
```
|
||||
|
||||
4. **Askama Templates**: `templates/documents/list.html`
|
||||
- Grid of document cards
|
||||
- Open/edit/delete buttons with HTMX
|
||||
|
||||
5. **Wire in main.rs**:
|
||||
```rust
|
||||
api_router = api_router.merge(documents::configure());
|
||||
```
|
||||
|
||||
**Frontend Already Has**:
|
||||
- ✅ Rich text editor (complete)
|
||||
- ✅ Formatting toolbar
|
||||
- ✅ AI suggestion panel
|
||||
- ✅ Document list sidebar
|
||||
- ✅ HTMX ready to send to `/api/documents`
|
||||
|
||||
**Can Optionally Add** (later):
|
||||
- LLM integration for AI rewrite/summarize
|
||||
- PDF export (using existing pdf-extract dependency)
|
||||
- Version history (store multiple versions)
|
||||
|
||||
---
|
||||
|
||||
### Priority 3: Research - HTML Integration (QUICK WIN)
|
||||
|
||||
**Timeline**: 1-2 hours
|
||||
**Complexity**: Very Low (just change response format)
|
||||
**Impact**: Medium (search already works, just needs HTML)
|
||||
|
||||
**What to Change**:
|
||||
|
||||
1. **Update Handler**: `botserver/src/core/kb/mod.rs`
|
||||
```rust
|
||||
// Current: returns Json<SearchResults>
|
||||
// Change to: returns Html<String> when format=html
|
||||
|
||||
pub async fn search_kb(
|
||||
Query(params): Query<SearchQuery>, // add format: Option<String>
|
||||
) -> impl IntoResponse {
|
||||
if params.format == Some("html") {
|
||||
Html(template.render().unwrap())
|
||||
} else {
|
||||
Json(results).into_response()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **Create Template**: `templates/kb/search_results.html`
|
||||
```html
|
||||
<div class="result-item" hx-get="/api/kb/{id}" hx-trigger="click">
|
||||
<h3>{{ title }}</h3>
|
||||
<p>{{ snippet }}</p>
|
||||
<span class="relevance">{{ score }}</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
3. **Update Frontend**: Already done - just works when backend returns HTML
|
||||
|
||||
**Frontend Already Has**:
|
||||
- ✅ Search input with HTMX
|
||||
- ✅ Results container waiting to be filled
|
||||
- ✅ Filters and limits
|
||||
- ✅ Stats panels
|
||||
|
||||
---
|
||||
|
||||
### Priority 4: Sources - Template Manager (MEDIUM)
|
||||
|
||||
**Timeline**: 2-3 hours
|
||||
**Complexity**: Low-Medium (file enumeration + parsing)
|
||||
**Impact**: Low-Medium (nice-to-have feature)
|
||||
|
||||
**What to Create**:
|
||||
|
||||
1. **New Module**: `botserver/src/sources/mod.rs`
|
||||
- Handler: `async fn list_sources()`
|
||||
- Handler: `async fn get_source()`
|
||||
- Handler: `async fn create_from_template()`
|
||||
|
||||
2. **Logic**:
|
||||
```rust
|
||||
// List templates from Drive
|
||||
let templates = drive.list_objects(".gbai/templates")?;
|
||||
|
||||
// Parse metadata from template file
|
||||
let content = drive.get_object(".gbai/templates/template.bas")?;
|
||||
let metadata = parse_yaml_metadata(&content);
|
||||
```
|
||||
|
||||
3. **Source Structure**:
|
||||
```rust
|
||||
pub struct Source {
|
||||
pub id: String, // filename
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub category: String, // templates, prompts, samples
|
||||
pub content: String,
|
||||
pub tags: Vec<String>,
|
||||
pub downloads: i32,
|
||||
pub rating: f32,
|
||||
}
|
||||
```
|
||||
|
||||
4. **Templates**: `templates/sources/grid.html`
|
||||
- Grid of source cards
|
||||
- Category filter tabs
|
||||
- Search capability
|
||||
|
||||
5. **Wire in main.rs**
|
||||
|
||||
**Frontend Already Has**:
|
||||
- ✅ Source grid layout
|
||||
- ✅ Category selector
|
||||
- ✅ Search box with HTMX
|
||||
- ✅ Source detail view
|
||||
|
||||
---
|
||||
|
||||
### Priority 5: Designer - Dialog Configuration (COMPLEX)
|
||||
|
||||
**Timeline**: 6-8 hours
|
||||
**Complexity**: Medium-High (BASIC compiler integration)
|
||||
**Impact**: Medium (admin/developer feature)
|
||||
|
||||
**What to Create**:
|
||||
|
||||
1. **New Module**: `botserver/src/designer/mod.rs`
|
||||
- Handler: `async fn list_dialogs()`
|
||||
- Handler: `async fn create_dialog()`
|
||||
- Handler: `async fn update_dialog()`
|
||||
- Handler: `async fn validate_dialog()`
|
||||
- Handler: `async fn deploy_dialog()`
|
||||
|
||||
2. **Validation Flow**:
|
||||
```rust
|
||||
// Use existing BASIC compiler
|
||||
use crate::basic::compiler::BASICCompiler;
|
||||
|
||||
let compiler = BASICCompiler::new();
|
||||
match compiler.compile(&dialog_content) {
|
||||
Ok(_) => { /* valid */ }
|
||||
Err(errors) => { /* return errors in HTML */ }
|
||||
}
|
||||
```
|
||||
|
||||
3. **Storage** (Drive):
|
||||
```rust
|
||||
// Store .bas files in Drive
|
||||
let bucket = format!("{}.gbai", bot_name);
|
||||
let key = format!(".gbdialogs/{}.bas", dialog_name);
|
||||
drive.put_object(bucket, key, content).await;
|
||||
```
|
||||
|
||||
4. **Dialog Structure**:
|
||||
```rust
|
||||
pub struct Dialog {
|
||||
pub id: Uuid,
|
||||
pub bot_id: Uuid,
|
||||
pub name: String,
|
||||
pub content: String, // BASIC code
|
||||
pub status: DialogStatus, // draft, valid, deployed
|
||||
pub version: i32,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
```
|
||||
|
||||
5. **Templates**:
|
||||
- `templates/designer/dialog_list.html` - List of dialogs
|
||||
- `templates/designer/dialog_editor.html` - Code editor
|
||||
- `templates/designer/validation_results.html` - Error display
|
||||
|
||||
6. **Wire in main.rs**
|
||||
|
||||
**Frontend Already Has**:
|
||||
- ✅ Dialog list with HTMX
|
||||
- ✅ Code editor interface
|
||||
- ✅ Deploy button
|
||||
- ✅ Validation result display
|
||||
|
||||
**Notes**:
|
||||
- Can reuse existing BASIC compiler from `botserver/src/basic/compiler/`
|
||||
- Compiler already available in AppState
|
||||
- Just need to call it and render results as HTML
|
||||
|
||||
---
|
||||
|
||||
## Implementation Checklist
|
||||
|
||||
### Week 1: Foundation (High-Value, Low-Effort)
|
||||
|
||||
- [ ] **Research HTML Integration** (1-2 hrs)
|
||||
- [ ] Update `/api/kb/search` to support `?format=html`
|
||||
- [ ] Create template for search results
|
||||
- [ ] Test with frontend
|
||||
|
||||
- [ ] **Paper Documents** (2-3 hrs)
|
||||
- [ ] Create `botserver/src/documents/mod.rs`
|
||||
- [ ] Implement CRUD handlers
|
||||
- [ ] Add Askama templates
|
||||
- [ ] Wire routes in main.rs
|
||||
- [ ] Test with frontend
|
||||
|
||||
- [ ] **Analytics Dashboard** (4-6 hrs)
|
||||
- [ ] Create `botserver/src/analytics/mod.rs`
|
||||
- [ ] Write SQL aggregation queries
|
||||
- [ ] Create Askama templates for metrics
|
||||
- [ ] Implement handlers
|
||||
- [ ] Wire routes in main.rs
|
||||
- [ ] Test with frontend
|
||||
|
||||
**Week 1 Result**: 3 apps complete, majority of UI functional
|
||||
|
||||
### Week 2: Medium Effort
|
||||
|
||||
- [ ] **Sources Template Manager** (2-3 hrs)
|
||||
- [ ] Create `botserver/src/sources/mod.rs`
|
||||
- [ ] Implement Drive template enumeration
|
||||
- [ ] Create template listing
|
||||
- [ ] Test with frontend
|
||||
|
||||
- [ ] **Designer - Dialog Configuration** (6-8 hrs)
|
||||
- [ ] Create `botserver/src/designer/mod.rs`
|
||||
- [ ] Implement BASIC validation integration
|
||||
- [ ] Create dialog list/editor templates
|
||||
- [ ] Implement CRUD handlers
|
||||
- [ ] Add deploy functionality
|
||||
- [ ] Test with frontend
|
||||
|
||||
**Week 2 Result**: All 5 missing apps complete
|
||||
|
||||
### Week 3: Polish & Testing
|
||||
|
||||
- [ ] Integration testing across all apps
|
||||
- [ ] Performance optimization
|
||||
- [ ] Error handling refinement
|
||||
- [ ] Documentation updates
|
||||
- [ ] Deployment validation
|
||||
|
||||
---
|
||||
|
||||
## Technical Patterns to Follow
|
||||
|
||||
### Handler Pattern (Copy This Template)
|
||||
|
||||
```rust
|
||||
// botserver/src/analytics/mod.rs
|
||||
|
||||
use axum::{
|
||||
extract::{Query, State},
|
||||
http::StatusCode,
|
||||
response::Html,
|
||||
routing::get,
|
||||
Router,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use askama::Template;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct AnalyticsQuery {
|
||||
pub time_range: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct AnalyticsData {
|
||||
pub messages_count: i64,
|
||||
pub sessions_count: i64,
|
||||
pub avg_response_time: f64,
|
||||
}
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "analytics/dashboard.html")]
|
||||
struct AnalyticsDashboardTemplate {
|
||||
data: AnalyticsData,
|
||||
}
|
||||
|
||||
pub async fn analytics_dashboard(
|
||||
Query(params): Query<AnalyticsQuery>,
|
||||
State(state): State<Arc<AppState>>,
|
||||
) -> Result<Html<String>, StatusCode> {
|
||||
// Query database
|
||||
let mut conn = state.conn.get()
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
|
||||
|
||||
let data = AnalyticsData {
|
||||
messages_count: get_message_count(&mut conn)?,
|
||||
sessions_count: get_session_count(&mut conn)?,
|
||||
avg_response_time: get_avg_response_time(&mut conn)?,
|
||||
};
|
||||
|
||||
// Render template
|
||||
let template = AnalyticsDashboardTemplate { data };
|
||||
Ok(Html(template.render()
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?))
|
||||
}
|
||||
|
||||
pub fn configure() -> Router<Arc<AppState>> {
|
||||
Router::new()
|
||||
.route("/api/analytics/dashboard", get(analytics_dashboard))
|
||||
}
|
||||
```
|
||||
|
||||
### Template Pattern (Copy This Template)
|
||||
|
||||
```html
|
||||
<!-- botserver/templates/analytics/dashboard.html -->
|
||||
<div class="analytics-dashboard">
|
||||
<div class="metrics-grid">
|
||||
<div class="metric-card">
|
||||
<span class="label">Messages</span>
|
||||
<span class="value">{{ data.messages_count }}</span>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<span class="label">Sessions</span>
|
||||
<span class="value">{{ data.sessions_count }}</span>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<span class="label">Avg Response</span>
|
||||
<span class="value">{{ data.avg_response_time }}ms</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies Already Available
|
||||
|
||||
### Database Access
|
||||
|
||||
```rust
|
||||
// Get database connection from AppState
|
||||
let mut conn = state.conn.get()?;
|
||||
|
||||
// Use existing queries from botserver/src/schema.rs
|
||||
use botserver::schema::message_history::dsl::*;
|
||||
use diesel::prelude::*;
|
||||
|
||||
let results = message_history
|
||||
.filter(created_at.gt(now - interval))
|
||||
.load::<MessageHistory>(&mut conn)?;
|
||||
```
|
||||
|
||||
### S3 Drive Access
|
||||
|
||||
```rust
|
||||
// Get S3 client from AppState
|
||||
let drive = state.drive.as_ref().ok_or("Drive not configured")?;
|
||||
|
||||
// Use existing methods
|
||||
drive.list_objects("bucket", "path").await?;
|
||||
drive.get_object("bucket", "key").await?;
|
||||
drive.put_object("bucket", "key", content).await?;
|
||||
```
|
||||
|
||||
### LLM Integration
|
||||
|
||||
```rust
|
||||
// Get LLM from AppState or instantiate
|
||||
let llm_client = state.llm_client.clone();
|
||||
|
||||
// Call for AI features (Paper app)
|
||||
let response = llm_client.complete(&prompt).await?;
|
||||
```
|
||||
|
||||
### BASIC Compiler
|
||||
|
||||
```rust
|
||||
// Already available for Designer app
|
||||
use botserver::basic::compiler::BASICCompiler;
|
||||
|
||||
let compiler = BASICCompiler::new();
|
||||
match compiler.compile(&dialog_code) {
|
||||
Ok(ast) => { /* valid */ }
|
||||
Err(errors) => { /* return errors */ }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests (Per Module)
|
||||
|
||||
```rust
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_analytics_dashboard() {
|
||||
// Create mock AppState
|
||||
// Call analytics_dashboard()
|
||||
// Assert response contains HTML
|
||||
// Assert metrics are reasonable
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Integration Tests (HTMX Flow)
|
||||
|
||||
```bash
|
||||
# Test Analytics
|
||||
curl -X GET "http://localhost:3000/api/analytics/dashboard?timeRange=day" \
|
||||
-H "Accept: text/html"
|
||||
|
||||
# Verify response is HTML, not JSON
|
||||
# Verify contains metric divs
|
||||
# Verify values are numbers
|
||||
```
|
||||
|
||||
### Frontend Tests (Browser)
|
||||
|
||||
1. Open `http://localhost:3000`
|
||||
2. Click on app in menu (e.g., "Analytics")
|
||||
3. Verify HTMX request goes to `/api/analytics/*`
|
||||
4. Verify HTML content loads in page
|
||||
5. Verify styling is correct
|
||||
6. Test interactive features (filters, buttons)
|
||||
|
||||
---
|
||||
|
||||
## Deployment Notes
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
cd botserver
|
||||
cargo build --release --features "analytics,documents,sources,designer"
|
||||
```
|
||||
|
||||
### Feature Flags
|
||||
|
||||
Add to `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[features]
|
||||
analytics = []
|
||||
documents = []
|
||||
designer = []
|
||||
sources = []
|
||||
research-html = []
|
||||
```
|
||||
|
||||
### Environment
|
||||
|
||||
No new environment variables needed - all modules use existing AppState configuration.
|
||||
|
||||
---
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
### What Could Go Wrong
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|-----------|
|
||||
| SQL injection in queries | Use Diesel ORM (type-safe) |
|
||||
| Template rendering errors | Test templates with sample data |
|
||||
| Drive not configured | Check AppState initialization |
|
||||
| Compiler failures in Designer | Use existing compiler tests |
|
||||
| HTMX attribute errors | Verify hx-* attributes in HTML |
|
||||
|
||||
### Testing Before Deploy
|
||||
|
||||
- [ ] All handlers return valid HTML
|
||||
- [ ] All HTMX attributes point to correct endpoints
|
||||
- [ ] No 404s in browser console
|
||||
- [ ] No error messages in backend logs
|
||||
- [ ] Database queries complete in <100ms
|
||||
- [ ] Templates render without errors
|
||||
- [ ] CSS styles load correctly
|
||||
- [ ] Responsive design works on mobile
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Definition of Done (Per App)
|
||||
|
||||
- ✅ Rust handlers implement all CRUD operations
|
||||
- ✅ Askama templates render without errors
|
||||
- ✅ Routes registered in main.rs
|
||||
- ✅ HTMX attributes in frontend point to correct endpoints
|
||||
- ✅ HTML responses work with HTMX swapping
|
||||
- ✅ No JavaScript errors in console
|
||||
- ✅ All CRUD operations tested manually
|
||||
- ✅ No database errors in logs
|
||||
- ✅ Response time <100ms for queries
|
||||
- ✅ Frontend UI works as designed
|
||||
|
||||
### Overall Success
|
||||
|
||||
By end of Week 3:
|
||||
- ✅ All 5 missing apps have backend handlers
|
||||
- ✅ All app UIs are fully functional
|
||||
- ✅ No HTMX errors in browser
|
||||
- ✅ All endpoints tested and working
|
||||
- ✅ Documentation updated with new APIs
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
### Existing Working Examples
|
||||
|
||||
Study these modules to understand patterns:
|
||||
|
||||
- `botserver/src/tasks/mod.rs` - Complete CRUD example
|
||||
- `botserver/src/email/mod.rs` - API handlers pattern
|
||||
- `botserver/src/drive/mod.rs` - S3 integration pattern
|
||||
- `botserver/src/calendar/mod.rs` - Complex routes example
|
||||
|
||||
### Key Files to Edit
|
||||
|
||||
- `botserver/src/main.rs` - Add `.merge(analytics::configure())` etc.
|
||||
- `botserver/src/core/urls.rs` - Define new URL constants
|
||||
- `botserver/templates/` - Add new Askama templates
|
||||
- `botui/ui/suite/*/` - HTML already complete, no changes needed
|
||||
|
||||
### Documentation References
|
||||
|
||||
- HTMX: https://htmx.org/attributes/hx-get/
|
||||
- Axum: https://docs.rs/axum/latest/axum/
|
||||
- Askama: https://docs.rs/askama/latest/askama/
|
||||
- Diesel: https://docs.rs/diesel/latest/diesel/
|
||||
|
||||
---
|
||||
|
||||
## Questions & Answers
|
||||
|
||||
**Q: Do we need to modify frontend HTML?**
|
||||
A: No - all HTML files already have correct HTMX attributes. Just implement the backend endpoints.
|
||||
|
||||
**Q: Can we use JSON responses with HTMX?**
|
||||
A: Technically yes, but HTML responses are more efficient with HTMX and require no frontend JavaScript.
|
||||
|
||||
**Q: What if a database query takes too long?**
|
||||
A: Add database indexes on frequently queried columns. Use EXPLAIN to analyze slow queries.
|
||||
|
||||
**Q: How do we handle errors in templates?**
|
||||
A: Return HTTP error status codes (400, 404, 500) with HTML error messages. HTMX handles swapping them appropriately.
|
||||
|
||||
**Q: Can we add new dependencies?**
|
||||
A: Prefer using existing dependencies already in Cargo.toml. If needed, add to existing feature flags.
|
||||
|
||||
**Q: What about authentication/authorization?**
|
||||
A: Use existing auth middleware from Drive/Tasks modules. Copy the pattern.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Start with Priority 1** (Research HTML Integration)
|
||||
- Easiest to implement (1-2 hours)
|
||||
- Low risk
|
||||
- Good way to understand HTMX pattern
|
||||
|
||||
2. **Move to Priority 2** (Paper Documents)
|
||||
- High user value
|
||||
- Medium complexity
|
||||
- Reuses Drive module
|
||||
|
||||
3. **Tackle Priority 3** (Analytics)
|
||||
- Most SQL-heavy
|
||||
- Pure data aggregation
|
||||
- High impact for users
|
||||
|
||||
4. **Complete Priority 4 & 5** (Designer & Sources)
|
||||
- More complex features
|
||||
- Can be done in parallel
|
||||
- Nice-to-have, not critical
|
||||
|
||||
**Estimated Total Time**: 2-3 weeks for all 5 apps to be production-ready.
|
||||
|
||||
---
|
||||
|
||||
## Success Metrics
|
||||
|
||||
After implementation:
|
||||
|
||||
- **Code Coverage**: 85%+ of new handlers have tests
|
||||
- **Performance**: All endpoints respond <200ms
|
||||
- **Reliability**: 99.5%+ uptime for new features
|
||||
- **User Satisfaction**: All UI apps work as documented
|
||||
- **Maintainability**: All code follows existing patterns
|
||||
- **Documentation**: API docs auto-generated from code
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2024
|
||||
**Status**: Ready for Implementation
|
||||
**Maintainer**: General Bots Team
|
||||
369
GAP_ANALYSIS.md
369
GAP_ANALYSIS.md
|
|
@ -1,369 +0,0 @@
|
|||
# Code/Documentation Gap Analysis
|
||||
|
||||
**Date**: 2024
|
||||
**Status**: 🔴 CRITICAL - 5 of 11 apps missing backend implementation
|
||||
**Impact**: 45% of documented features non-functional
|
||||
**Resolution Time**: 20-25 hours (2-3 weeks)
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
The General Bots documentation describes a complete enterprise suite with 14 applications. However, **only 6 applications have fully implemented backends**. The other 5 have complete HTML/CSS/JavaScript frontend shells but **zero Rust API endpoints**, making them non-functional despite being documented as complete features.
|
||||
|
||||
### By The Numbers
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Apps Documented | 14 |
|
||||
| Apps with Frontend | 13 |
|
||||
| Apps with Backend | 6 |
|
||||
| **Apps Missing Backend** | **5** |
|
||||
| Frontend Completion | 100% |
|
||||
| Backend Completion | 55% |
|
||||
| **Functionality Gap** | **45%** |
|
||||
|
||||
---
|
||||
|
||||
## The Five Missing Apps
|
||||
|
||||
### 🔴 1. Analytics Dashboard
|
||||
- **Frontend**: Complete (1215 lines, full UI with charts)
|
||||
- **Backend**: NONE - No endpoints, no handlers
|
||||
- **What's Needed**: SQL queries to aggregate `message_history` and `sessions` tables
|
||||
- **Effort**: 4-6 hours
|
||||
- **Impact**: HIGH - Users expect metrics
|
||||
|
||||
### 🔴 2. Paper (Document Editor)
|
||||
- **Frontend**: Complete (1700+ lines, rich text editor with toolbar)
|
||||
- **Backend**: NONE - No document storage, no endpoints
|
||||
- **What's Needed**: Document CRUD + Drive S3 integration
|
||||
- **Effort**: 2-3 hours
|
||||
- **Impact**: HIGH - Users want to create documents
|
||||
|
||||
### 🟡 3. Research (Semantic Search)
|
||||
- **Frontend**: Complete (full search interface)
|
||||
- **Backend**: PARTIAL - `/api/kb/search` exists but returns JSON
|
||||
- **What's Needed**: Change response format from JSON → HTML for HTMX
|
||||
- **Effort**: 1-2 hours
|
||||
- **Impact**: MEDIUM - Search works, just needs UI integration
|
||||
|
||||
### 🔴 4. Designer (Bot Builder)
|
||||
- **Frontend**: Complete (dialog builder interface)
|
||||
- **Backend**: NONE - No dialog management endpoints
|
||||
- **What's Needed**: BASIC compiler integration + dialog CRUD
|
||||
- **Effort**: 6-8 hours
|
||||
- **Impact**: MEDIUM - Admin/developer feature
|
||||
|
||||
### 🔴 5. Sources (Template Manager)
|
||||
- **Frontend**: Complete (template gallery grid)
|
||||
- **Backend**: NONE - No template enumeration
|
||||
- **What's Needed**: List Drive templates + parse metadata
|
||||
- **Effort**: 2-3 hours
|
||||
- **Impact**: LOW - Nice-to-have feature
|
||||
|
||||
---
|
||||
|
||||
## What's Actually Working ✅
|
||||
|
||||
| App | Frontend | Backend | Status |
|
||||
|-----|----------|---------|--------|
|
||||
| Chat | ✅ | ✅ `/api/sessions`, `/ws` | 🟢 COMPLETE |
|
||||
| Drive | ✅ | ✅ `/api/drive/*` | 🟢 COMPLETE |
|
||||
| Tasks | ✅ | ✅ `/api/tasks/*` | 🟢 COMPLETE |
|
||||
| Mail | ✅ | ✅ `/api/email/*` | 🟢 COMPLETE |
|
||||
| Calendar | ✅ | ✅ CalDAV | 🟢 COMPLETE |
|
||||
| Meet | ✅ | ✅ `/api/meet/*`, `/ws/meet` | 🟢 COMPLETE |
|
||||
| Monitoring | ✅ | ✅ `/api/admin/stats` | 🟢 COMPLETE |
|
||||
|
||||
**Total**: 6 fully working applications = **55% backend coverage**
|
||||
|
||||
---
|
||||
|
||||
## Root Cause Analysis
|
||||
|
||||
### Why This Happened
|
||||
|
||||
1. **Parallel Development** - Frontend team built all UI shells simultaneously
|
||||
2. **Incomplete Backend** - Backend team implemented core features (Chat, Drive, Tasks, etc.) but not everything
|
||||
3. **No Integration Gate** - Missing backend wasn't caught before documentation was published
|
||||
4. **Orphaned UI** - Frontend shells were completed but never wired to backend
|
||||
|
||||
### Why It Matters Now
|
||||
|
||||
- **Docs Promise**: Users read "Chapter 04: Suite Applications" and expect 14 apps to work
|
||||
- **Users Try Apps**: Click on Analytics/Paper/Designer and get broken/empty screens
|
||||
- **Trust Damaged**: Platform appears incomplete or poorly maintained
|
||||
- **Opportunity Cost**: Features documented but not usable
|
||||
|
||||
---
|
||||
|
||||
## The Good News
|
||||
|
||||
### Infrastructure Already Exists
|
||||
|
||||
All the pieces needed to implement the missing apps are already in the codebase:
|
||||
|
||||
| Component | Location | Status | Can Use For |
|
||||
|-----------|----------|--------|-----------|
|
||||
| Database | `schema.rs` | ✅ Complete | All apps can query |
|
||||
| S3 Drive | `drive/mod.rs` | ✅ Complete | Paper, Sources, Designer |
|
||||
| LLM Module | `llm/mod.rs` | ✅ Complete | Paper (AI features) |
|
||||
| BASIC Compiler | `basic/compiler/mod.rs` | ✅ Complete | Designer (validation) |
|
||||
| Vector DB | Qdrant integration | ✅ Complete | Research (search) |
|
||||
| HTMX Framework | `htmx-app.js` | ✅ Complete | All apps (UI binding) |
|
||||
| Askama Templates | `templates/` | ✅ Complete | All apps (HTML rendering) |
|
||||
| AppState | `core/shared/state.rs` | ✅ Complete | All apps (DB + Drive + LLM) |
|
||||
|
||||
### Proven Pattern
|
||||
|
||||
The solution is to follow the same pattern used by Chat, Drive, and Tasks:
|
||||
|
||||
```
|
||||
Frontend (HTML)
|
||||
↓ hx-get="/api/resource"
|
||||
Rust Handler
|
||||
↓ returns Html<String>
|
||||
Askama Template
|
||||
↓
|
||||
HTMX swaps into page
|
||||
↓ Done ✅
|
||||
```
|
||||
|
||||
**Zero JavaScript needed. Just Rust + HTML templates.**
|
||||
|
||||
---
|
||||
|
||||
## Solution: Implementation Roadmap
|
||||
|
||||
### Phase 1: Quick Wins (Week 1) - 8 hours
|
||||
1. **Research HTML Integration** (1-2 hrs) - Change response format
|
||||
2. **Paper Documents** (2-3 hrs) - Reuse Drive module
|
||||
3. **Analytics Dashboard** (4-6 hrs) - SQL aggregations
|
||||
|
||||
### Phase 2: Medium Effort (Week 2) - 12 hours
|
||||
4. **Sources Templates** (2-3 hrs) - File enumeration
|
||||
5. **Designer Dialog Config** (6-8 hrs) - Compiler integration
|
||||
|
||||
### Phase 3: Polish (Week 3) - 2-3 hours
|
||||
- Testing, optimization, documentation
|
||||
|
||||
**Total Time**: ~20-25 hours
|
||||
**Total Effort**: 2-3 weeks for one engineer
|
||||
**Risk Level**: LOW (patterns proven, no new architecture)
|
||||
|
||||
---
|
||||
|
||||
## Impact of Not Fixing
|
||||
|
||||
### Short Term (1-2 weeks)
|
||||
- ❌ Users see broken/empty app screens
|
||||
- ❌ Documentation appears inaccurate
|
||||
- ❌ Features marked as complete don't work
|
||||
- ❌ Support tickets for "missing" features
|
||||
|
||||
### Medium Term (1-2 months)
|
||||
- ❌ Platform reputation damage
|
||||
- ❌ Users lose trust in product
|
||||
- ❌ Migration from other platforms stalls
|
||||
- ❌ Deployment blocked until "fixed"
|
||||
|
||||
### Long Term (3+ months)
|
||||
- ❌ Competitive disadvantage
|
||||
- ❌ Lost sales opportunities
|
||||
- ❌ Technical debt accumulates
|
||||
- ❌ Refactoring becomes harder
|
||||
|
||||
---
|
||||
|
||||
## Impact of Fixing
|
||||
|
||||
### Immediate (Upon completion)
|
||||
- ✅ All documented features work
|
||||
- ✅ Documentation matches code
|
||||
- ✅ Platform is "feature complete"
|
||||
- ✅ User expectations met
|
||||
|
||||
### Short Term (1 month)
|
||||
- ✅ Increased user adoption
|
||||
- ✅ Positive platform reviews
|
||||
- ✅ Reduced support burden
|
||||
- ✅ Deployments unblocked
|
||||
|
||||
### Long Term (3+ months)
|
||||
- ✅ Stable, maintainable codebase
|
||||
- ✅ Happy users → more referrals
|
||||
- ✅ Foundation for future features
|
||||
- ✅ Competitive advantage
|
||||
|
||||
---
|
||||
|
||||
## Effort Breakdown
|
||||
|
||||
### By App (Hours)
|
||||
|
||||
| App | SQL | Rust | Template | Integration | Total |
|
||||
|-----|-----|------|----------|-------------|-------|
|
||||
| Analytics | 2 | 1 | 1 | 1 | **5 hrs** |
|
||||
| Paper | 0 | 1.5 | 1 | 0.5 | **3 hrs** |
|
||||
| Research | 0 | 0.5 | 0.5 | 0.2 | **1.2 hrs** |
|
||||
| Sources | 0 | 1 | 1 | 0.5 | **2.5 hrs** |
|
||||
| Designer | 0 | 2 | 1 | 2 | **5 hrs** |
|
||||
| **TOTAL** | **2** | **6** | **4.5** | **4.5** | **~17 hrs** |
|
||||
|
||||
Plus testing, documentation, deployment: +3-8 hours
|
||||
|
||||
**Realistic Total**: 20-25 hours
|
||||
|
||||
---
|
||||
|
||||
## Who Should Do This
|
||||
|
||||
### Ideal Profile
|
||||
- ✅ Rust backend experience
|
||||
- ✅ SQL knowledge
|
||||
- ✅ Familiar with codebase (or quick learner)
|
||||
- ✅ Can follow existing patterns
|
||||
|
||||
### Time Estimate Per App
|
||||
| App | Experience | Estimate |
|
||||
|-----|-----------|----------|
|
||||
| Analytics | Mid-level | 5 hrs |
|
||||
| Paper | Mid-level | 3 hrs |
|
||||
| Research | Junior | 1.5 hrs |
|
||||
| Sources | Mid-level | 2.5 hrs |
|
||||
| Designer | Senior | 6 hrs |
|
||||
|
||||
### Can Be Done In Parallel?
|
||||
Yes - Each app is independent. Could have 2 engineers work simultaneously:
|
||||
- Engineer A: Analytics + Paper + Research (9 hrs)
|
||||
- Engineer B: Sources + Designer (11 hrs)
|
||||
- **Parallel time**: ~11 hours instead of 20 hours
|
||||
|
||||
---
|
||||
|
||||
## Key Considerations
|
||||
|
||||
### What NOT to Change
|
||||
- ❌ Don't modify frontend HTML (it's ready)
|
||||
- ❌ Don't add Node.js/npm (not needed)
|
||||
- ❌ Don't create new tables (existing schema sufficient)
|
||||
- ❌ Don't add complex JavaScript (HTMX does it)
|
||||
|
||||
### What TO Do
|
||||
- ✅ Create Rust handler modules
|
||||
- ✅ Write SQL queries (if needed)
|
||||
- ✅ Create Askama templates
|
||||
- ✅ Add routes to main.rs
|
||||
- ✅ Test with browser
|
||||
|
||||
### Testing Strategy
|
||||
1. Implement one app completely
|
||||
2. Test all CRUD operations
|
||||
3. Verify HTMX integration works
|
||||
4. Use as template for remaining apps
|
||||
5. Run integration tests
|
||||
|
||||
---
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Priority 1: IMMEDIATE (This Week)
|
||||
**Implement Analytics Dashboard**
|
||||
- High impact (users need metrics)
|
||||
- Low complexity (SQL queries)
|
||||
- High visibility (users see it first)
|
||||
- Proof of concept for pattern
|
||||
|
||||
**Time**: 5 hours max
|
||||
**Outcome**: Demonstrate solution works
|
||||
|
||||
### Priority 2: URGENT (Week 2)
|
||||
**Implement Paper + Research HTML**
|
||||
- High user value (documents + search)
|
||||
- Low-medium complexity
|
||||
- Combined 4-5 hours
|
||||
- Covers 40% of gap
|
||||
|
||||
### Priority 3: IMPORTANT (Week 3)
|
||||
**Implement Sources + Designer**
|
||||
- Medium user value
|
||||
- Higher complexity (Designer)
|
||||
- Combined 7-8 hours
|
||||
- Completes 100% coverage
|
||||
|
||||
**Total Timeline**: 3 weeks for full completion
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Functional Requirements
|
||||
- [ ] All 5 apps have working backend endpoints
|
||||
- [ ] All HTMX attributes in frontend point to valid endpoints
|
||||
- [ ] All endpoints return HTML (not JSON)
|
||||
- [ ] All CRUD operations tested manually
|
||||
- [ ] No 404s or errors in browser console
|
||||
|
||||
### Performance Requirements
|
||||
- [ ] All endpoints respond <200ms
|
||||
- [ ] Database queries use indexes efficiently
|
||||
- [ ] No N+1 query problems
|
||||
- [ ] HTML rendering <50ms
|
||||
|
||||
### Code Quality Requirements
|
||||
- [ ] All code follows existing patterns
|
||||
- [ ] All handlers have error handling
|
||||
- [ ] All modules have tests
|
||||
- [ ] All templates render correctly
|
||||
|
||||
### Documentation Requirements
|
||||
- [ ] API endpoints documented in code
|
||||
- [ ] Setup instructions updated
|
||||
- [ ] Troubleshooting guide added
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Approve this plan** - Align on priority and timeline
|
||||
2. **Assign engineer** - Pick one or two (can be parallel)
|
||||
3. **Start with Analytics** - Quickest win, proves pattern
|
||||
4. **Scale to others** - Use Analytics as template
|
||||
5. **Test thoroughly** - Before marking "complete"
|
||||
6. **Update documentation** - Reflect actual status
|
||||
|
||||
---
|
||||
|
||||
## Questions?
|
||||
|
||||
**Q: How long will this actually take?**
|
||||
A: 20-25 hours for complete implementation. Could be 1-2 weeks for one engineer, or 3-5 days with 2 engineers.
|
||||
|
||||
**Q: Will users notice the changes?**
|
||||
A: Yes - all 5 apps will suddenly work when you implement this.
|
||||
|
||||
**Q: Can we deploy incrementally?**
|
||||
A: Yes - implement one app at a time, deploy when ready.
|
||||
|
||||
**Q: Will this break anything?**
|
||||
A: No - all code reuses existing patterns and modules.
|
||||
|
||||
**Q: What if we don't do this?**
|
||||
A: Platform will appear incomplete and users will be frustrated.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- **Frontend Code**: `botui/ui/suite/`
|
||||
- **Backend Code**: `botserver/src/`
|
||||
- **Existing Patterns**: `botserver/src/{tasks,drive,email,calendar}/mod.rs`
|
||||
- **Implementation Guide**: `botserver/CODE_IMPLEMENTATION_ROADMAP.md`
|
||||
- **Missing Details**: `botserver/MISSING_IMPLEMENTATIONS.md`
|
||||
|
||||
---
|
||||
|
||||
**Status**: Ready for Implementation
|
||||
**Recommendation**: START WITH ANALYTICS (5 hours, high ROI)
|
||||
**Expected Completion**: 2-3 weeks (all 5 apps)
|
||||
|
|
@ -1,287 +0,0 @@
|
|||
# Gap Analysis Implementation Summary
|
||||
|
||||
**Date**: 2024
|
||||
**Status**: ✅ IMPLEMENTED - All 5 missing app backends created
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This implementation addresses the gap analysis identified in `GAP_ANALYSIS.md`. All 5 missing application backends have been implemented following the existing patterns used by Chat, Drive, Tasks, and other working applications.
|
||||
|
||||
---
|
||||
|
||||
## Implemented Modules
|
||||
|
||||
### 1. Analytics Dashboard (`src/analytics/mod.rs`)
|
||||
|
||||
**Endpoints:**
|
||||
- `GET /api/analytics/stats` - Overall analytics statistics
|
||||
- `GET /api/analytics/messages/count` - Message count for metric cards
|
||||
- `GET /api/analytics/sessions/active` - Active sessions count
|
||||
- `GET /api/analytics/messages/trend` - Hourly message trend data
|
||||
|
||||
**Features:**
|
||||
- SQL aggregations on `message_history` and `user_sessions` tables
|
||||
- Real-time metrics with HTMX auto-refresh support
|
||||
- HTML responses for direct HTMX integration
|
||||
|
||||
**Database Tables Used:**
|
||||
- `message_history`
|
||||
- `user_sessions`
|
||||
|
||||
---
|
||||
|
||||
### 2. Paper - Document Editor (`src/paper/mod.rs`)
|
||||
|
||||
**Endpoints:**
|
||||
- `POST /api/paper` - Create new document
|
||||
- `GET /api/paper` - List all documents
|
||||
- `GET /api/paper/{id}` - Get specific document
|
||||
- `PUT /api/paper/{id}` - Update document
|
||||
- `DELETE /api/paper/{id}` - Delete document
|
||||
- `GET /api/paper/search` - Search documents
|
||||
|
||||
**Features:**
|
||||
- Full CRUD operations for documents
|
||||
- HTML responses for HTMX integration
|
||||
- Prepared for S3/Drive integration
|
||||
|
||||
**New Database Table:**
|
||||
- `paper_documents` (created via migration)
|
||||
|
||||
---
|
||||
|
||||
### 3. Research - Semantic Search (`src/research/mod.rs`)
|
||||
|
||||
**Endpoints:**
|
||||
- `GET /api/research/search` - Semantic search with HTML response
|
||||
- `GET /api/research/collections` - List knowledge base collections
|
||||
- `GET /api/research/recent` - Recent searches
|
||||
- `GET /api/research/suggestions` - Search suggestions/autocomplete
|
||||
|
||||
**Features:**
|
||||
- Text search on `kb_documents` table
|
||||
- Query highlighting in results
|
||||
- Collection filtering
|
||||
- HTML responses for HTMX integration
|
||||
|
||||
**Database Tables Used:**
|
||||
- `kb_documents`
|
||||
- `kb_collections`
|
||||
|
||||
---
|
||||
|
||||
### 4. Sources - Template Manager (`src/sources/mod.rs`)
|
||||
|
||||
**Endpoints:**
|
||||
- `GET /api/sources/templates` - List available templates
|
||||
- `GET /api/sources/templates/{id}` - Get template details
|
||||
- `GET /api/sources/categories` - List template categories
|
||||
- `GET /api/sources/templates/{id}/use` - Use template to create document
|
||||
|
||||
**Features:**
|
||||
- Built-in templates (8 default templates)
|
||||
- Category filtering
|
||||
- Search functionality
|
||||
- Template preview and usage
|
||||
|
||||
**Templates Included:**
|
||||
- Blank Document
|
||||
- Meeting Notes
|
||||
- Project Plan
|
||||
- FAQ Bot
|
||||
- Customer Support Bot
|
||||
- Employee Onboarding
|
||||
- Survey Template
|
||||
- Invoice Template
|
||||
|
||||
---
|
||||
|
||||
### 5. Designer - Bot Builder (`src/designer/mod.rs`)
|
||||
|
||||
**Endpoints:**
|
||||
- `POST /api/designer/dialogs` - Create new dialog
|
||||
- `GET /api/designer/dialogs` - List dialogs
|
||||
- `GET /api/designer/dialogs/{id}` - Get dialog for editing
|
||||
- `PUT /api/designer/dialogs/{id}` - Update dialog
|
||||
- `DELETE /api/designer/dialogs/{id}` - Delete dialog
|
||||
- `POST /api/designer/dialogs/{id}/validate` - Validate dialog code
|
||||
- `POST /api/designer/dialogs/{id}/deploy` - Deploy dialog (make active)
|
||||
- `POST /api/designer/validate` - Validate code directly
|
||||
- `GET /api/designer/bots` - List available bots
|
||||
|
||||
**Features:**
|
||||
- Full CRUD for dialog management
|
||||
- BASIC code validation with syntax checking
|
||||
- Deploy functionality
|
||||
- Default dialog template
|
||||
- Error and warning reporting
|
||||
|
||||
**Validation Checks:**
|
||||
- IF/THEN statement syntax
|
||||
- FOR/TO loop syntax
|
||||
- Unclosed string literals
|
||||
- Block structure matching (IF/END IF, FOR/NEXT, etc.)
|
||||
- Best practice warnings (GOTO usage, line length)
|
||||
|
||||
**New Database Table:**
|
||||
- `designer_dialogs` (created via migration)
|
||||
|
||||
---
|
||||
|
||||
## Database Migration
|
||||
|
||||
A new migration was created: `migrations/6.2.0_suite_apps/`
|
||||
|
||||
### New Tables Created:
|
||||
|
||||
1. **paper_documents**
|
||||
- Document storage for Paper app
|
||||
- Indexes on owner_id and updated_at
|
||||
|
||||
2. **designer_dialogs**
|
||||
- Dialog storage for Designer app
|
||||
- Indexes on bot_id, is_active, and updated_at
|
||||
|
||||
3. **source_templates**
|
||||
- Template metadata caching
|
||||
- Index on category
|
||||
|
||||
4. **analytics_events**
|
||||
- Additional event tracking
|
||||
- Indexes on event_type, user_id, session_id, created_at
|
||||
|
||||
5. **analytics_daily_aggregates**
|
||||
- Pre-computed daily metrics for faster queries
|
||||
- Indexes on date and bot_id
|
||||
|
||||
6. **research_search_history**
|
||||
- Search history tracking
|
||||
- Indexes on user_id and created_at
|
||||
|
||||
---
|
||||
|
||||
## Integration Points
|
||||
|
||||
### lib.rs Updates
|
||||
Added module exports:
|
||||
```rust
|
||||
pub mod analytics;
|
||||
pub mod designer;
|
||||
pub mod paper;
|
||||
pub mod research;
|
||||
pub mod sources;
|
||||
```
|
||||
|
||||
### main.rs Updates
|
||||
Added route registration:
|
||||
```rust
|
||||
api_router = api_router.merge(botserver::analytics::configure_analytics_routes());
|
||||
api_router = api_router.merge(botserver::paper::configure_paper_routes());
|
||||
api_router = api_router.merge(botserver::research::configure_research_routes());
|
||||
api_router = api_router.merge(botserver::sources::configure_sources_routes());
|
||||
api_router = api_router.merge(botserver::designer::configure_designer_routes());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Pattern Followed
|
||||
|
||||
All implementations follow the established pattern:
|
||||
|
||||
```
|
||||
Frontend (HTML with hx-* attributes)
|
||||
↓ hx-get="/api/resource"
|
||||
Rust Handler (axum)
|
||||
↓ returns Html<String>
|
||||
HTML String Builder
|
||||
↓
|
||||
HTMX swaps into page
|
||||
```
|
||||
|
||||
**Key Characteristics:**
|
||||
- No external JavaScript frameworks needed
|
||||
- All responses are HTML fragments for HTMX
|
||||
- State managed via `Arc<AppState>`
|
||||
- Database queries via Diesel with `spawn_blocking`
|
||||
- Consistent error handling with HTML error responses
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
To test the implementation:
|
||||
|
||||
1. Run database migration:
|
||||
```bash
|
||||
diesel migration run
|
||||
```
|
||||
|
||||
2. Start the server:
|
||||
```bash
|
||||
cargo run
|
||||
```
|
||||
|
||||
3. Test endpoints:
|
||||
```bash
|
||||
# Analytics
|
||||
curl https://localhost:8080/api/analytics/stats
|
||||
|
||||
# Paper
|
||||
curl https://localhost:8080/api/paper
|
||||
|
||||
# Research
|
||||
curl "https://localhost:8080/api/research/search?q=test"
|
||||
|
||||
# Sources
|
||||
curl https://localhost:8080/api/sources/templates
|
||||
|
||||
# Designer
|
||||
curl https://localhost:8080/api/designer/dialogs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Estimated Time vs Actual
|
||||
|
||||
| App | Estimated | Status |
|
||||
|-----|-----------|--------|
|
||||
| Analytics | 4-6 hours | ✅ Complete |
|
||||
| Paper | 2-3 hours | ✅ Complete |
|
||||
| Research | 1-2 hours | ✅ Complete |
|
||||
| Sources | 2-3 hours | ✅ Complete |
|
||||
| Designer | 6-8 hours | ✅ Complete |
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Run Migration**: Apply the database migration to create new tables
|
||||
2. **Test Endpoints**: Verify all endpoints work correctly
|
||||
3. **Frontend Integration**: Confirm HTMX attributes in frontend match new endpoints
|
||||
4. **Documentation Update**: Update API documentation with new endpoints
|
||||
5. **Performance Testing**: Ensure queries are optimized for production load
|
||||
|
||||
---
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
### New Files:
|
||||
- `src/analytics/mod.rs` - Analytics backend
|
||||
- `src/paper/mod.rs` - Paper/Documents backend
|
||||
- `src/research/mod.rs` - Research/Search backend
|
||||
- `src/sources/mod.rs` - Sources/Templates backend
|
||||
- `src/designer/mod.rs` - Designer/Bot Builder backend
|
||||
- `migrations/6.2.0_suite_apps/up.sql` - Database migration
|
||||
- `migrations/6.2.0_suite_apps/down.sql` - Rollback migration
|
||||
|
||||
### Modified Files:
|
||||
- `src/lib.rs` - Added module exports
|
||||
- `src/main.rs` - Added route registration
|
||||
|
||||
---
|
||||
|
||||
## Conclusion
|
||||
|
||||
All 5 missing application backends have been implemented, bringing the backend completion from 55% to 100%. The platform now has full functionality for all documented features.
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
# Library Migration & Code Reduction Guide
|
||||
|
||||
This document describes the library migrations performed to reduce custom code and leverage battle-tested Rust crates.
|
||||
|
||||
## Summary of Changes
|
||||
|
||||
| Area | Before | After | Lines Reduced |
|
||||
|------|--------|-------|---------------|
|
||||
| Secrets Management | Custom Vault HTTP client | `vaultrs` library | ~210 lines |
|
||||
| Calendar | Custom CalendarEngine | `icalendar` (RFC 5545) | +iCal support |
|
||||
| Rate Limiting | None | `governor` library | +320 lines (new feature) |
|
||||
| Config | Custom parsing | `figment` available | Ready for migration |
|
||||
|
||||
## Security Audit Results
|
||||
|
||||
All new dependencies passed `cargo audit` with no vulnerabilities:
|
||||
|
||||
```
|
||||
✅ vaultrs = "0.7" - HashiCorp Vault client
|
||||
✅ icalendar = "0.17" - RFC 5545 calendar support
|
||||
✅ figment = "0.10" - Layered configuration
|
||||
✅ governor = "0.10" - Rate limiting
|
||||
```
|
||||
|
||||
### Packages NOT Added (Security Issues)
|
||||
|
||||
| Package | Issue | Alternative |
|
||||
|---------|-------|-------------|
|
||||
| `openidconnect` | RSA vulnerability (RUSTSEC-2023-0071) | Keep custom Zitadel client |
|
||||
| `tower-sessions-redis-store` | Unmaintained `paste` dependency | Keep custom session manager |
|
||||
|
||||
## Module Changes
|
||||
|
||||
### 1. Secrets Management (`core/secrets/mod.rs`)
|
||||
|
||||
**Before:** ~640 lines of custom Vault HTTP client implementation
|
||||
**After:** ~490 lines using `vaultrs` library
|
||||
|
||||
#### Key Changes:
|
||||
- Replaced custom HTTP calls with `vaultrs::kv2` operations
|
||||
- Simplified caching logic
|
||||
- Maintained full API compatibility
|
||||
- Environment variable fallback preserved
|
||||
|
||||
#### Usage (unchanged):
|
||||
```rust
|
||||
use botserver::core::secrets::{SecretsManager, SecretPaths};
|
||||
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let db_config = manager.get_database_config().await?;
|
||||
let llm_key = manager.get_llm_api_key("openai").await?;
|
||||
```
|
||||
|
||||
### 2. Calendar Module (`calendar/mod.rs`)
|
||||
|
||||
**Before:** Custom event storage with no standard format support
|
||||
**After:** Full iCal (RFC 5545) import/export support
|
||||
|
||||
#### New Features:
|
||||
- `export_to_ical()` - Export events to .ics format
|
||||
- `import_from_ical()` - Import events from .ics files
|
||||
- Standard recurrence rule support (RRULE)
|
||||
- Attendee and organizer handling
|
||||
|
||||
#### Usage:
|
||||
```rust
|
||||
use botserver::calendar::{CalendarEngine, CalendarEventInput, export_to_ical};
|
||||
|
||||
let mut engine = CalendarEngine::new();
|
||||
let event = engine.create_event(CalendarEventInput {
|
||||
title: "Team Meeting".to_string(),
|
||||
start_time: Utc::now(),
|
||||
end_time: Utc::now() + Duration::hours(1),
|
||||
organizer: "user@example.com".to_string(),
|
||||
// ...
|
||||
});
|
||||
|
||||
// Export to iCal format
|
||||
let ical_string = engine.export_ical("My Calendar");
|
||||
|
||||
// Import from iCal
|
||||
let count = engine.import_ical(&ical_content, "organizer@example.com");
|
||||
```
|
||||
|
||||
#### New API Endpoints:
|
||||
- `GET /api/calendar/export.ics` - Download calendar as iCal
|
||||
- `POST /api/calendar/import` - Import iCal file
|
||||
|
||||
### 3. Rate Limiting (`core/rate_limit.rs`)
|
||||
|
||||
**New module** providing API rate limiting using `governor`.
|
||||
|
||||
#### Features:
|
||||
- Per-IP rate limiting
|
||||
- Tiered limits for different endpoint types:
|
||||
- **API endpoints:** 100 req/s (burst: 200)
|
||||
- **Auth endpoints:** 10 req/s (burst: 20)
|
||||
- **LLM endpoints:** 5 req/s (burst: 10)
|
||||
- Automatic cleanup of stale limiters
|
||||
- Configurable via environment variables
|
||||
|
||||
#### Configuration:
|
||||
```bash
|
||||
RATE_LIMIT_ENABLED=true
|
||||
RATE_LIMIT_API_RPS=100
|
||||
RATE_LIMIT_API_BURST=200
|
||||
RATE_LIMIT_AUTH_RPS=10
|
||||
RATE_LIMIT_AUTH_BURST=20
|
||||
RATE_LIMIT_LLM_RPS=5
|
||||
RATE_LIMIT_LLM_BURST=10
|
||||
```
|
||||
|
||||
#### Usage in Router:
|
||||
```rust
|
||||
use botserver::core::rate_limit::{RateLimitConfig, RateLimitState, rate_limit_middleware};
|
||||
use std::sync::Arc;
|
||||
|
||||
let rate_limit_state = Arc::new(RateLimitState::from_env());
|
||||
|
||||
let app = Router::new()
|
||||
.merge(api_routes)
|
||||
.layer(axum::middleware::from_fn_with_state(
|
||||
rate_limit_state,
|
||||
rate_limit_middleware
|
||||
));
|
||||
```
|
||||
|
||||
## Dependencies Added to Cargo.toml
|
||||
|
||||
```toml
|
||||
# Vault secrets management
|
||||
vaultrs = "0.7"
|
||||
|
||||
# Calendar standards (RFC 5545)
|
||||
icalendar = "0.17"
|
||||
|
||||
# Layered configuration
|
||||
figment = { version = "0.10", features = ["toml", "env", "json"] }
|
||||
|
||||
# Rate limiting
|
||||
governor = "0.10"
|
||||
```
|
||||
|
||||
## Future Migration Opportunities
|
||||
|
||||
These libraries are available and audited, ready for future use:
|
||||
|
||||
### 1. Configuration with Figment
|
||||
|
||||
Replace custom `ConfigManager` with layered configuration:
|
||||
|
||||
```rust
|
||||
use figment::{Figment, providers::{Env, Toml, Format}};
|
||||
|
||||
let config: AppConfig = Figment::new()
|
||||
.merge(Toml::file("config.toml"))
|
||||
.merge(Env::prefixed("GB_"))
|
||||
.extract()?;
|
||||
```
|
||||
|
||||
### 2. Observability with OpenTelemetry
|
||||
|
||||
```toml
|
||||
opentelemetry = "0.31"
|
||||
tracing-opentelemetry = "0.32"
|
||||
```
|
||||
|
||||
## Packages Kept (Good Choices)
|
||||
|
||||
These existing dependencies are optimal and should be kept:
|
||||
|
||||
| Package | Purpose | Notes |
|
||||
|---------|---------|-------|
|
||||
| `axum` | Web framework | Excellent async support |
|
||||
| `diesel` | Database ORM | Type-safe queries |
|
||||
| `rhai` | Scripting | Perfect for BASIC dialect |
|
||||
| `qdrant-client` | Vector DB | Native Rust client |
|
||||
| `rcgen` + `rustls` | TLS/Certs | Good for internal CA |
|
||||
| `lettre` + `imap` | Email | Standard choices |
|
||||
| `tauri` | Desktop UI | Cross-platform |
|
||||
| `livekit` | Video meetings | Native SDK |
|
||||
|
||||
## Testing
|
||||
|
||||
All new code includes unit tests:
|
||||
|
||||
```bash
|
||||
# Run tests for specific modules
|
||||
cargo test --lib secrets
|
||||
cargo test --lib calendar
|
||||
cargo test --lib rate_limit
|
||||
```
|
||||
|
||||
## HTTP Client Consolidation
|
||||
|
||||
The HTTP client is already properly consolidated:
|
||||
|
||||
- **botlib:** Contains the canonical `BotServerClient` implementation
|
||||
- **botui:** Re-exports from botlib (no duplication)
|
||||
- **botserver:** Uses `reqwest` directly for external API calls
|
||||
|
||||
This architecture ensures:
|
||||
- Single source of truth for HTTP client logic
|
||||
- Consistent timeout and retry behavior
|
||||
- Unified error handling across all projects
|
||||
|
||||
## Backward Compatibility
|
||||
|
||||
All changes maintain backward compatibility:
|
||||
- Existing API signatures preserved
|
||||
- Environment variable names unchanged
|
||||
- Database schemas unaffected
|
||||
- Configuration file formats unchanged
|
||||
|
||||
## Code Metrics
|
||||
|
||||
| Project | Before | After | Reduction |
|
||||
|---------|--------|-------|-----------|
|
||||
| `botserver/src/core/secrets/mod.rs` | 747 lines | 493 lines | **254 lines (-34%)** |
|
||||
| `botserver/src/calendar/mod.rs` | 227 lines | 360 lines | +133 lines (new features) |
|
||||
| `botserver/src/core/rate_limit.rs` | 0 lines | 319 lines | +319 lines (new feature) |
|
||||
|
||||
**Net effect:** Reduced custom code while adding RFC 5545 calendar support and rate limiting.
|
||||
|
||||
## Dependencies Summary
|
||||
|
||||
### Added (Cargo.toml)
|
||||
```toml
|
||||
vaultrs = "0.7"
|
||||
icalendar = "0.17"
|
||||
figment = { version = "0.10", features = ["toml", "env", "json"] }
|
||||
governor = "0.10"
|
||||
```
|
||||
|
||||
### Existing (No Changes Needed)
|
||||
- `reqwest` - HTTP client (already in use)
|
||||
- `redis` - Caching (already in use)
|
||||
- `diesel` - Database ORM (already in use)
|
||||
- `tokio` - Async runtime (already in use)
|
||||
|
|
@ -1,329 +0,0 @@
|
|||
# Missing Implementations - UI Apps Backend Integration
|
||||
|
||||
## Status Summary
|
||||
|
||||
**Frontend (HTML/JS)**: ✅ COMPLETE - All UI shells exist
|
||||
**Backend (Rust APIs)**: 🔴 INCOMPLETE - Missing handlers
|
||||
|
||||
| App | HTML | JavaScript | Backend Routes | Status |
|
||||
|-----|------|-----------|------------------|--------|
|
||||
| Chat | ✅ | ✅ basic | ✅ /api/sessions, /ws | COMPLETE |
|
||||
| Drive | ✅ | ✅ basic | ✅ /api/drive/* | COMPLETE |
|
||||
| Tasks | ✅ | ✅ basic | ✅ /api/tasks/* | COMPLETE |
|
||||
| Mail | ✅ | ✅ basic | ✅ /api/email/* | COMPLETE |
|
||||
| Calendar | ✅ | ✅ basic | ✅ CalDAV, /api/calendar/* | COMPLETE |
|
||||
| Meet | ✅ | ✅ basic | ✅ /api/meet/*, /ws/meet | COMPLETE |
|
||||
| **Analytics** | ✅ | ✅ forms | ❌ NONE | **NEEDS BACKEND** |
|
||||
| **Paper** | ✅ | ✅ editor | ❌ NONE | **NEEDS BACKEND** |
|
||||
| **Research** | ✅ | ✅ search | ✅ /api/kb/search | **PARTIAL** |
|
||||
| **Designer** | ✅ | ✅ builder | ❌ NONE | **NEEDS BACKEND** |
|
||||
| **Sources** | ✅ | ✅ list | ❌ NONE | **NEEDS BACKEND** |
|
||||
| Monitoring | ✅ | ✅ dashboard | ✅ /api/admin/stats | COMPLETE |
|
||||
|
||||
---
|
||||
|
||||
## Backend Endpoints That Need Implementation
|
||||
|
||||
### 1. Analytics Dashboard (`/api/analytics/`)
|
||||
|
||||
**Current URL Definition**:
|
||||
- `/api/analytics/dashboard` - GET
|
||||
- `/api/analytics/metric` - GET
|
||||
|
||||
**Needed Endpoints**:
|
||||
```rust
|
||||
GET /api/analytics/dashboard?timeRange=day|week|month|year
|
||||
→ Returns HTML: dashboard cards with metrics
|
||||
|
||||
GET /api/analytics/sessions?start_date=&end_date=
|
||||
→ Returns HTML: session analytics table
|
||||
|
||||
GET /api/analytics/bots?bot_id=&timeRange=
|
||||
→ Returns HTML: bot performance metrics
|
||||
|
||||
GET /api/analytics/top-queries
|
||||
→ Returns HTML: trending queries list
|
||||
|
||||
GET /api/analytics/error-rate?timeRange=
|
||||
→ Returns HTML: error statistics
|
||||
```
|
||||
|
||||
**Backend Logic Needed**:
|
||||
- Query `message_history` table for message counts
|
||||
- Calculate aggregates from `sessions` table
|
||||
- Fetch system metrics from monitoring
|
||||
- Use database connection pool in `AppState`
|
||||
- Return Askama template rendered as HTML
|
||||
|
||||
---
|
||||
|
||||
### 2. Paper App - Document Management (`/api/documents/`)
|
||||
|
||||
**Needed Endpoints**:
|
||||
```rust
|
||||
POST /api/documents
|
||||
{ title, content, type: "draft" | "note" | "template" }
|
||||
→ Returns: Document ID + status
|
||||
|
||||
GET /api/documents
|
||||
→ Returns HTML: document list with previews
|
||||
|
||||
GET /api/documents/:id
|
||||
→ Returns HTML: full document content
|
||||
|
||||
PUT /api/documents/:id
|
||||
{ title?, content? }
|
||||
→ Returns: success status
|
||||
|
||||
DELETE /api/documents/:id
|
||||
→ Returns: 204 No Content
|
||||
|
||||
POST /api/documents/:id/export?format=pdf|docx|txt
|
||||
→ Returns: File binary
|
||||
|
||||
POST /api/documents/:id/ai
|
||||
{ action: "rewrite" | "summarize" | "expand", tone?: string }
|
||||
→ Returns HTML: AI suggestion panel
|
||||
```
|
||||
|
||||
**Backend Logic Needed**:
|
||||
- Store documents in Drive (S3) under `.gbdocs/`
|
||||
- Use LLM module for AI operations (exists at `botserver/src/llm/`)
|
||||
- Query Drive metadata from AppState
|
||||
- Use Askama to render document HTML
|
||||
|
||||
---
|
||||
|
||||
### 3. Designer App - Bot Configuration (`/api/bots/`, `/api/dialogs/`)
|
||||
|
||||
**Current URL Definition**:
|
||||
- `/api/bots` - GET/POST
|
||||
- `/api/bots/:id` - GET/PUT/DELETE
|
||||
- `/api/bots/:id/config` - GET/PUT
|
||||
|
||||
**Needed Endpoints**:
|
||||
```rust
|
||||
GET /api/bots/:id/dialogs
|
||||
→ Returns HTML: dialog list
|
||||
|
||||
POST /api/bots/:id/dialogs
|
||||
{ name, content: BASIC code }
|
||||
→ Returns: success + dialog ID
|
||||
|
||||
PUT /api/bots/:id/dialogs/:dialog_id
|
||||
{ name?, content? }
|
||||
→ Returns: success
|
||||
|
||||
DELETE /api/bots/:id/dialogs/:dialog_id
|
||||
→ Returns: 204 No Content
|
||||
|
||||
POST /api/bots/:id/dialogs/:dialog_id/validate
|
||||
→ Returns HTML: validation results (errors/warnings)
|
||||
|
||||
POST /api/bots/:id/dialogs/:dialog_id/deploy
|
||||
→ Returns HTML: deployment status
|
||||
|
||||
GET /api/bots/:id/templates
|
||||
→ Returns HTML: available template list
|
||||
```
|
||||
|
||||
**Backend Logic Needed**:
|
||||
- BASIC compiler (exists at `botserver/src/basic/compiler/`)
|
||||
- Store dialog files in Drive under `.gbdialogs/`
|
||||
- Parse BASIC syntax for validation
|
||||
- Use existing database and Drive connections
|
||||
|
||||
---
|
||||
|
||||
### 4. Sources App - Templates & Prompts (`/api/sources/`)
|
||||
|
||||
**Needed Endpoints**:
|
||||
```rust
|
||||
GET /api/sources?category=all|templates|prompts|samples
|
||||
→ Returns HTML: source card grid
|
||||
|
||||
GET /api/sources/:id
|
||||
→ Returns HTML: source detail view
|
||||
|
||||
POST /api/sources
|
||||
{ name, content, category, description, tags }
|
||||
→ Returns: source ID (admin only)
|
||||
|
||||
POST /api/sources/:id/clone
|
||||
→ Returns: new source ID
|
||||
|
||||
POST /api/sources/templates/:id/create-bot
|
||||
{ bot_name, bot_description }
|
||||
→ Returns HTML: new bot created message
|
||||
```
|
||||
|
||||
**Backend Logic Needed**:
|
||||
- List files from Drive `.gbai/templates` folder
|
||||
- Parse template metadata from YAML/comments
|
||||
- Create new bots by copying template files
|
||||
- Query Drive for available templates
|
||||
|
||||
---
|
||||
|
||||
### 5. Research App - Enhancement (`/api/kb/`)
|
||||
|
||||
**Current**: `/api/kb/search` exists but returns JSON
|
||||
|
||||
**Needed Improvements**:
|
||||
```rust
|
||||
GET /api/kb/search?q=query&limit=10&offset=0
|
||||
→ Already exists but needs HTMX response format
|
||||
→ Return HTML partial with results (not JSON)
|
||||
|
||||
GET /api/kb/stats?bot_id=
|
||||
→ Returns HTML: KB statistics card
|
||||
|
||||
POST /api/kb/reindex?bot_id=
|
||||
→ Returns HTML: reindexing status
|
||||
```
|
||||
|
||||
**Changes Needed**:
|
||||
- Add Askama template for search results HTML
|
||||
- Change response from JSON to HTML
|
||||
- Keep API logic the same, just change rendering
|
||||
|
||||
---
|
||||
|
||||
## HTMX Integration Pattern
|
||||
|
||||
### Frontend Pattern (Already in HTML files)
|
||||
|
||||
```html
|
||||
<!-- Research app example -->
|
||||
<input type="text"
|
||||
id="researchQuery"
|
||||
placeholder="Search knowledge base..."
|
||||
hx-get="/api/kb/search"
|
||||
hx-target="#researchResults"
|
||||
hx-trigger="keyup changed delay:500ms"
|
||||
hx-include="[name='limit']"
|
||||
/>
|
||||
|
||||
<div id="researchResults">
|
||||
<!-- Backend fills this with HTML -->
|
||||
</div>
|
||||
```
|
||||
|
||||
### Backend Response Pattern (What to implement)
|
||||
|
||||
Instead of returning JSON:
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{ "id": 1, "title": "Item 1", "snippet": "..." }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Return Askama template as HTML:
|
||||
```html
|
||||
<div class="result-item" hx-get="/api/kb/1" hx-trigger="click">
|
||||
<h3>Item 1</h3>
|
||||
<p class="snippet">...</p>
|
||||
<span class="meta">relevance: 0.95</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Priority
|
||||
|
||||
### 🔴 CRITICAL (Quick Wins)
|
||||
|
||||
1. **Analytics Dashboard** - Pure SQL aggregation
|
||||
- Effort: 4-6 hours
|
||||
- No external dependencies
|
||||
- Just query existing tables
|
||||
|
||||
2. **Paper Documents** - Reuse Drive module
|
||||
- Effort: 2-3 hours
|
||||
- Use existing S3 integration
|
||||
- Minimal new code
|
||||
|
||||
3. **Research HTML Integration** - Change response format
|
||||
- Effort: 1-2 hours
|
||||
- KB search exists, just render differently
|
||||
- Add Askama template
|
||||
|
||||
### 🟡 IMPORTANT (Medium Effort)
|
||||
|
||||
4. **Sources Templates** - File enumeration
|
||||
- Effort: 2-3 hours
|
||||
- List Drive templates
|
||||
- Parse metadata
|
||||
|
||||
5. **Designer Bot Config** - Use existing compiler
|
||||
- Effort: 6-8 hours
|
||||
- BASIC compiler exists
|
||||
- Integrate with Drive storage
|
||||
|
||||
---
|
||||
|
||||
## Code Locations Reference
|
||||
|
||||
| Component | Location |
|
||||
|-----------|----------|
|
||||
| Database models | `botserver/src/schema.rs` |
|
||||
| Existing handlers | `botserver/src/{drive,tasks,email,calendar,meet}/mod.rs` |
|
||||
| BASIC compiler | `botserver/src/basic/compiler/mod.rs` |
|
||||
| AppState | `botserver/src/core/shared/state.rs` |
|
||||
| URL definitions | `botserver/src/core/urls.rs` |
|
||||
| Askama templates | `botserver/templates/` |
|
||||
| LLM module | `botserver/src/llm/mod.rs` |
|
||||
| Drive module | `botserver/src/drive/mod.rs` |
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Manual Endpoint Testing
|
||||
|
||||
```bash
|
||||
# Test Analytics (when implemented)
|
||||
curl -X GET "http://localhost:3000/api/analytics/dashboard?timeRange=day"
|
||||
|
||||
# Test Paper documents (when implemented)
|
||||
curl -X GET "http://localhost:3000/api/documents"
|
||||
|
||||
# Test Research (update response format)
|
||||
curl -X GET "http://localhost:3000/api/kb/search?q=test"
|
||||
|
||||
# Test Sources (when implemented)
|
||||
curl -X GET "http://localhost:3000/api/sources?category=templates"
|
||||
|
||||
# Test Designer (when implemented)
|
||||
curl -X GET "http://localhost:3000/api/bots/bot-id/dialogs"
|
||||
```
|
||||
|
||||
### HTMX Integration Testing
|
||||
|
||||
1. Open browser DevTools Network tab
|
||||
2. Click button in UI that triggers HTMX
|
||||
3. Verify request goes to correct endpoint
|
||||
4. Verify response is HTML (not JSON)
|
||||
5. Verify HTMX swaps content into target element
|
||||
|
||||
---
|
||||
|
||||
## Key Principles
|
||||
|
||||
✅ **Use HTMX for UI interactions** - Let backend render HTML
|
||||
✅ **Reuse existing modules** - Drive, LLM, compiler already exist
|
||||
✅ **Minimal JavaScript** - Only `htmx-app.js` and `theme-manager.js` needed
|
||||
✅ **Return HTML from endpoints** - Use Askama templates
|
||||
✅ **Leverage AppState** - Database, Drive, LLM all available
|
||||
✅ **Keep features modular** - Each app independent, can be disabled
|
||||
|
||||
---
|
||||
|
||||
## Not Implemented (By Design)
|
||||
|
||||
- ❌ Player app (media viewer) - Use Drive file previews instead
|
||||
- ❌ Custom JavaScript per app - HTMX handles all interactions
|
||||
- ❌ GraphQL - REST API with HTMX is simpler
|
||||
- ❌ WebAssembly - Rust backend does heavy lifting
|
||||
373
PROMPT.md
Normal file
373
PROMPT.md
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
# BotServer Development Prompt Guide
|
||||
|
||||
**Version:** 6.1.0
|
||||
**Purpose:** Consolidated LLM context for BotServer development
|
||||
|
||||
---
|
||||
|
||||
## Project Overview
|
||||
|
||||
BotServer is the core backend for General Bots - an open-source conversational AI platform built in Rust. It provides:
|
||||
|
||||
- **Bootstrap System**: Auto-installs PostgreSQL, MinIO, Redis, LLM servers
|
||||
- **Package Manager**: Manages bot deployments and service lifecycle
|
||||
- **BASIC Interpreter**: Executes conversation scripts via Rhai
|
||||
- **Multi-Channel Support**: Web, WhatsApp, Teams, Email
|
||||
- **Knowledge Base**: Document ingestion with vector search
|
||||
|
||||
### Workspace Structure
|
||||
|
||||
```
|
||||
botserver/ # Main server (this project)
|
||||
botlib/ # Shared library - types, utilities, HTTP client
|
||||
botui/ # Web/Desktop UI (Axum + Tauri)
|
||||
botapp/ # Desktop app wrapper (Tauri)
|
||||
botbook/ # Documentation (mdBook)
|
||||
botmodels/ # Data models visualization
|
||||
botplugin/ # Browser extension
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Code Generation Rules
|
||||
|
||||
### CRITICAL REQUIREMENTS
|
||||
|
||||
```
|
||||
- KISS, NO TALK, SECURED ENTERPRISE GRADE THREAD SAFE CODE ONLY
|
||||
- Use rustc 1.90.0 (1159e78c4 2025-09-14)
|
||||
- No placeholders, never comment/uncomment code, no explanations
|
||||
- All code must be complete, professional, production-ready
|
||||
- REMOVE ALL COMMENTS FROM GENERATED CODE
|
||||
- Always include full updated code files - never partial
|
||||
- Only return files that have actual changes
|
||||
- DO NOT WRITE ERROR HANDLING CODE - LET IT CRASH
|
||||
- Return 0 warnings - review unused imports!
|
||||
```
|
||||
|
||||
### Rust Patterns
|
||||
|
||||
```rust
|
||||
// Use rand::rng() instead of rand::thread_rng()
|
||||
let mut rng = rand::rng();
|
||||
|
||||
// Use diesel for database (NOT sqlx)
|
||||
use diesel::prelude::*;
|
||||
|
||||
// All config from AppConfig - no hardcoded values
|
||||
let url = config.drive.endpoint.clone(); // NOT "api.openai.com"
|
||||
|
||||
// Logging (all-in-one-line, unique messages)
|
||||
info!("Processing request id={} user={}", req_id, user_id);
|
||||
debug!("Cache hit for key={}", key);
|
||||
trace!("Raw response bytes={}", bytes.len());
|
||||
```
|
||||
|
||||
### BotServer Specifics
|
||||
|
||||
```
|
||||
- Sessions MUST be retrieved by id when session_id is present
|
||||
- Never suggest installing software - bootstrap/package_manager handles it
|
||||
- Configuration stored in .gbot/config and database bot_configuration table
|
||||
- Pay attention to shared::utils and shared::models for reuse
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Adding New Features
|
||||
|
||||
### Adding a Rhai Keyword
|
||||
|
||||
```rust
|
||||
// 1. Define enum (Rust-only, NOT in database)
|
||||
#[repr(i32)]
|
||||
pub enum TriggerKind {
|
||||
Scheduled = 0,
|
||||
TableUpdate = 1,
|
||||
TableInsert = 2,
|
||||
}
|
||||
|
||||
// 2. Register keyword with engine
|
||||
pub fn my_keyword(state: &AppState, engine: &mut Engine) {
|
||||
let db = state.db_custom.clone();
|
||||
|
||||
engine.register_custom_syntax(
|
||||
["MY", "KEYWORD", "$expr$"],
|
||||
true,
|
||||
{
|
||||
let db = db.clone();
|
||||
move |context, inputs| {
|
||||
let value = context.eval_expression_tree(&inputs[0])?;
|
||||
let binding = db.as_ref().unwrap();
|
||||
let fut = execute_my_keyword(binding, value);
|
||||
|
||||
let result = tokio::task::block_in_place(||
|
||||
tokio::runtime::Handle::current().block_on(fut))
|
||||
.map_err(|e| format!("DB error: {}", e))?;
|
||||
|
||||
Ok(Dynamic::from(result))
|
||||
}
|
||||
}
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
// 3. Async execution with diesel
|
||||
pub async fn execute_my_keyword(
|
||||
pool: &PgPool,
|
||||
value: String,
|
||||
) -> Result<Value, Box<dyn std::error::Error>> {
|
||||
info!("Executing my_keyword value={}", value);
|
||||
|
||||
use diesel::prelude::*;
|
||||
let result = diesel::insert_into(my_table::table)
|
||||
.values(&NewRecord { value })
|
||||
.execute(pool)?;
|
||||
|
||||
Ok(json!({ "rows_affected": result }))
|
||||
}
|
||||
```
|
||||
|
||||
### Adding a Data Model
|
||||
|
||||
```rust
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Queryable, Selectable, Insertable, Serialize, Deserialize)]
|
||||
#[diesel(table_name = crate::schema::users)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct User {
|
||||
pub id: Uuid,
|
||||
pub status: i16, // Use i16 for enum storage
|
||||
pub email: String,
|
||||
pub age: Option<i16>, // Nullable fields
|
||||
pub metadata: Vec<u8>, // Binary data
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
```
|
||||
|
||||
### Adding a Service/Endpoint
|
||||
|
||||
```rust
|
||||
use axum::{routing::{get, post}, Router, Json, extract::State};
|
||||
|
||||
pub fn configure() -> Router<AppState> {
|
||||
Router::new()
|
||||
.route("/api/resource", get(list_handler))
|
||||
.route("/api/resource", post(create_handler))
|
||||
}
|
||||
|
||||
async fn list_handler(
|
||||
State(state): State<Arc<AppState>>,
|
||||
) -> Json<Vec<Resource>> {
|
||||
let conn = state.conn.get().unwrap();
|
||||
let items = resources::table.load::<Resource>(&conn).unwrap();
|
||||
Json(items)
|
||||
}
|
||||
|
||||
async fn create_handler(
|
||||
State(state): State<Arc<AppState>>,
|
||||
Json(payload): Json<CreateRequest>,
|
||||
) -> Json<Resource> {
|
||||
let conn = state.conn.get().unwrap();
|
||||
let item = diesel::insert_into(resources::table)
|
||||
.values(&payload)
|
||||
.get_result(&conn)
|
||||
.unwrap();
|
||||
Json(item)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## LLM Workflow Strategy
|
||||
|
||||
### Development Process
|
||||
|
||||
1. **One requirement at a time** with sequential commits
|
||||
2. **Start with docs** - explain user behavior before coding
|
||||
3. **Design first** - spend time on architecture
|
||||
4. **On unresolved error** - stop and consult with web search enabled
|
||||
|
||||
### LLM Fallback Strategy (After 3 attempts / 10 minutes)
|
||||
|
||||
1. DeepSeek-V3-0324 (good architect, reliable)
|
||||
2. gpt-5-chat (slower but thorough)
|
||||
3. gpt-oss-120b (final validation)
|
||||
4. Claude Web (for complex debugging, unit tests, UI)
|
||||
|
||||
### Final Steps Before Commit
|
||||
|
||||
```bash
|
||||
# Remove warnings
|
||||
cargo check 2>&1 | grep warning
|
||||
|
||||
# If many warnings, add #[allow(dead_code)] temporarily
|
||||
# Then fix properly in dedicated pass
|
||||
|
||||
# Final validation
|
||||
cargo build --release
|
||||
cargo test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
### Shell Script Format
|
||||
|
||||
When returning code changes, use this exact format:
|
||||
|
||||
```sh
|
||||
#!/bin/bash
|
||||
|
||||
cat > src/module/file.rs << 'EOF'
|
||||
use std::io;
|
||||
|
||||
pub fn my_function() -> Result<(), io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > src/another_file.rs << 'EOF'
|
||||
pub fn another() {
|
||||
println!("Hello");
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
### Rules
|
||||
|
||||
- Only return MODIFIED files
|
||||
- Never return unchanged files
|
||||
- Use `cat > path << 'EOF'` format
|
||||
- Include complete file content
|
||||
- No partial snippets
|
||||
|
||||
---
|
||||
|
||||
## Error Fixing Guide
|
||||
|
||||
When fixing Rust compiler errors:
|
||||
|
||||
1. **Respect Cargo.toml** - check dependencies, editions, features
|
||||
2. **Type safety** - ensure all types match, trait bounds satisfied
|
||||
3. **Ownership rules** - fix borrowing, ownership, lifetime issues
|
||||
4. **Only return input files** - other files already exist
|
||||
|
||||
Common errors to check:
|
||||
- Borrow of moved value
|
||||
- Unused variable
|
||||
- Use of moved value
|
||||
- Missing trait implementations
|
||||
|
||||
---
|
||||
|
||||
## Documentation Style
|
||||
|
||||
When writing documentation:
|
||||
|
||||
- Be pragmatic and concise with examples
|
||||
- Create both guide-like and API-like sections
|
||||
- Use clear and consistent terminology
|
||||
- Ensure consistency in formatting
|
||||
- Follow logical flow
|
||||
- Relate to BASIC keyword list where applicable
|
||||
|
||||
---
|
||||
|
||||
## SVG Diagram Guidelines
|
||||
|
||||
For technical diagrams:
|
||||
|
||||
```
|
||||
- Transparent background
|
||||
- Width: 1040-1400px, Height: appropriate for content
|
||||
- Simple colored borders (no fill, stroke-width="2.6")
|
||||
- Font: Arial, sans-serif
|
||||
- Dual-theme support with CSS classes
|
||||
- Colors: Blue #4A90E2, Orange #F5A623, Purple #BD10E0, Green #7ED321
|
||||
- Rounded rectangles (rx="6.5")
|
||||
- Font sizes: 29-32px titles, 22-24px labels, 18-21px descriptions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## IDE Integration Rules
|
||||
|
||||
```
|
||||
- Return identifiers/characters in English language only
|
||||
- Do not emit any comments, remove existing ones
|
||||
- Compact code emission where possible
|
||||
- Ensure cargo check cycle removes warnings
|
||||
- Never use defaults or magic values
|
||||
- Check borrow, clone, types - return 0 warning code!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Files Reference
|
||||
|
||||
```
|
||||
src/main.rs # Entry point, bootstrap, Axum server
|
||||
src/lib.rs # Module exports, feature gates
|
||||
src/core/
|
||||
bootstrap/mod.rs # Auto-install services
|
||||
session/mod.rs # Session management
|
||||
bot/mod.rs # Bot orchestration
|
||||
config/mod.rs # Configuration management
|
||||
package_manager/ # Service lifecycle
|
||||
src/basic/ # BASIC/Rhai interpreter
|
||||
src/shared/
|
||||
state.rs # AppState definition
|
||||
utils.rs # Utility functions
|
||||
models.rs # Database models
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies (Key Libraries)
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| axum | 0.7.5 | Web framework |
|
||||
| diesel | 2.1 | PostgreSQL ORM |
|
||||
| tokio | 1.41 | Async runtime |
|
||||
| rhai | git | BASIC scripting |
|
||||
| reqwest | 0.12 | HTTP client |
|
||||
| serde | 1.0 | Serialization |
|
||||
| askama | 0.12 | Templates |
|
||||
|
||||
---
|
||||
|
||||
## Testing Commands
|
||||
|
||||
```bash
|
||||
# Build
|
||||
cargo build
|
||||
|
||||
# Check warnings
|
||||
cargo check
|
||||
|
||||
# Run tests
|
||||
cargo test
|
||||
|
||||
# Run with features
|
||||
cargo run --features "console,llm,drive"
|
||||
|
||||
# Audit dependencies
|
||||
cargo audit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Remember
|
||||
|
||||
- **Sessions**: Always retrieve by ID when present
|
||||
- **Config**: Never hardcode values, use AppConfig
|
||||
- **Bootstrap**: Never suggest manual installation
|
||||
- **Database**: Use diesel, not sqlx
|
||||
- **Logging**: Unique messages, appropriate levels
|
||||
- **Warnings**: Target zero warnings before commit
|
||||
16
ROADMAP.md
16
ROADMAP.md
|
|
@ -1,16 +0,0 @@
|
|||
| Feature | Target | Description |
|
||||
|---------|--------|-------------|
|
||||
| **Real-time Collaboration** | 📋 Planned | Shared documents |
|
||||
| **Autonomous Agents** | 📋 Planned | Self-directing AI workflows |
|
||||
| **Multi-Step Planning** | 📋 Planned | Complex task decomposition |
|
||||
| **Self-Correcting Workflows** | 📋 Planned | Error recovery |
|
||||
| **Memory Persistence** | 📋 Planned | Long-term memory |
|
||||
| **Goal Decomposition** | 📋 Planned | Break down objectives |
|
||||
| **AI Content Filtering** | 📋 Planned | Content moderation |
|
||||
| **Compliance Automation** | 📋 Planned | GDPR, LGPD, SOC2 |
|
||||
| **Audit Logging** | ✅ Complete | Full activity tracking |
|
||||
| **Data Loss Prevention** | 📋 Planned | Sensitive data protection |
|
||||
| **Citation Generation** | 📋 Planned | Academic references |
|
||||
| **Source Verification** | 📋 Planned | Fact-checking |
|
||||
| **Knowledge Graphs** | 📋 Planned | Entity relationships |
|
||||
| **Academic Search** | 📋 Planned | Papers and research |
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,201 +0,0 @@
|
|||
# Modelo de Prompt para Aprendizado de BASIC em Markdown
|
||||
|
||||
## 🎯 **ESTRUTURA PARA APRENDIZ DE BASIC**
|
||||
|
||||
```
|
||||
**CONCEITO BASIC:**
|
||||
[Nome do conceito ou comando]
|
||||
|
||||
**NÍVEL:**
|
||||
☐ Iniciante ☐ Intermediário ☐ Avançado
|
||||
|
||||
**OBJETIVO DE APRENDIZADO:**
|
||||
[O que você quer entender ou criar]
|
||||
|
||||
**CÓDIGO EXEMPLO:**
|
||||
```basic
|
||||
[Seu código ou exemplo aqui]
|
||||
```
|
||||
|
||||
**DÚVIDAS ESPECÍFICAS:**
|
||||
- [Dúvida 1 sobre o conceito]
|
||||
- [Dúvida 2 sobre sintaxe]
|
||||
- [Dúvida 3 sobre aplicação]
|
||||
|
||||
**CONTEXTO DO PROJETO:**
|
||||
[Descrição do que está tentando fazer]
|
||||
|
||||
**RESULTADO ESPERADO:**
|
||||
[O que o código deve fazer]
|
||||
|
||||
**PARTES QUE NÃO ENTENDE:**
|
||||
- [Trecho específico do código]
|
||||
- [Mensagem de erro]
|
||||
- [Lógica confusa]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 **EXEMPLO PRÁTICO: LOOP FOR**
|
||||
|
||||
```
|
||||
**CONCEITO BASIC:**
|
||||
LOOP FOR
|
||||
|
||||
**NÍVEL:**
|
||||
☒ Iniciante ☐ Intermediário ☐ Avançado
|
||||
|
||||
**OBJETIVO DE APRENDIZADO:**
|
||||
Entender como criar um contador de 1 a 10
|
||||
|
||||
**CÓDIGO EXEMPLO:**
|
||||
```basic
|
||||
10 FOR I = 1 TO 10
|
||||
20 PRINT "Número: "; I
|
||||
30 NEXT I
|
||||
```
|
||||
|
||||
**DÚVIDAS ESPECÍFICAS:**
|
||||
- O que significa "NEXT I"?
|
||||
- Posso usar outras letras além de "I"?
|
||||
- Como fazer contagem regressiva?
|
||||
|
||||
**CONTEXTO DO PROJETO:**
|
||||
Estou criando um programa que lista números
|
||||
|
||||
**RESULTADO ESPERADO:**
|
||||
Que apareça: Número: 1, Número: 2, etc.
|
||||
|
||||
**PARTES QUE NÃO ENTENDE:**
|
||||
- Por que precisa do número 10 na linha 10?
|
||||
- O que acontece se esquecer o NEXT?
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ **MODELO PARA RESOLVER ERROS**
|
||||
|
||||
```
|
||||
**ERRO NO BASIC:**
|
||||
[Mensagem de erro ou comportamento estranho]
|
||||
|
||||
**MEU CÓDIGO:**
|
||||
```basic
|
||||
[Coloque seu código completo]
|
||||
```
|
||||
|
||||
**LINHA COM PROBLEMA:**
|
||||
[Linha específica onde ocorre o erro]
|
||||
|
||||
**COMPORTAMENTO ESPERADO:**
|
||||
[O que deveria acontecer]
|
||||
|
||||
**COMPORTAMENTO ATUAL:**
|
||||
[O que está acontecendo de errado]
|
||||
|
||||
**O QUE JÁ TENTEI:**
|
||||
- [Tentativa 1 de correção]
|
||||
- [Tentativa 2]
|
||||
- [Tentativa 3]
|
||||
|
||||
**VERSÃO DO BASIC:**
|
||||
[QBASIC, GW-BASIC, FreeBASIC, etc.]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📖 **MODELO PARA EXPLICAR COMANDOS**
|
||||
|
||||
```
|
||||
**COMANDO:**
|
||||
[Nome do comando - ex: PRINT, INPUT, GOTO]
|
||||
|
||||
**SYNTAX:**
|
||||
[Como escrever corretamente]
|
||||
|
||||
**PARÂMETROS:**
|
||||
- Parâmetro 1: [Função]
|
||||
- Parâmetro 2: [Função]
|
||||
|
||||
**EXEMPLO SIMPLES:**
|
||||
```basic
|
||||
[Exemplo mínimo e funcional]
|
||||
```
|
||||
|
||||
**EXEMPLO PRÁTICO:**
|
||||
```basic
|
||||
[Exemplo em contexto real]
|
||||
```
|
||||
|
||||
**ERROS COMUNS:**
|
||||
- [Erro frequente 1]
|
||||
- [Erro frequente 2]
|
||||
|
||||
**DICA PARA INICIANTES:**
|
||||
[Dica simples para não errar]
|
||||
|
||||
**EXERCÍCIO SUGERIDO:**
|
||||
[Pequeno exercício para praticar]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 **FORMATAÇÃO MARKDOWN PARA BASIC**
|
||||
|
||||
### **Como documentar seu código em .md:**
|
||||
```markdown
|
||||
# [NOME DO PROGRAMA]
|
||||
|
||||
## 🎯 OBJETIVO
|
||||
[O que o programa faz]
|
||||
|
||||
## 📋 COMO USAR
|
||||
1. [Passo 1]
|
||||
2. [Passo 2]
|
||||
|
||||
## 🧩 CÓDIGO FONTE
|
||||
```basic
|
||||
[Seu código aqui]
|
||||
```
|
||||
|
||||
## 🔍 EXPLICAÇÃO
|
||||
- **Linha X**: [Explicação]
|
||||
- **Linha Y**: [Explicação]
|
||||
|
||||
## 🚀 EXEMPLO DE EXECUÇÃO
|
||||
```
|
||||
[Saída do programa]
|
||||
```
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏆 **MODELO DE PROJETO COMPLETO**
|
||||
|
||||
```
|
||||
# PROJETO BASIC: [NOME]
|
||||
|
||||
## 📝 DESCRIÇÃO
|
||||
[Descrição do que o programa faz]
|
||||
|
||||
## 🎨 FUNCIONALIDADES
|
||||
- [ ] Funcionalidade 1
|
||||
- [ ] Funcionalidade 2
|
||||
- [ ] Funcionalidade 3
|
||||
|
||||
## 🧩 ESTRUTURA DO CÓDIGO
|
||||
```basic
|
||||
[Seu código organizado]
|
||||
```
|
||||
|
||||
## 🎯 APRENDIZADOS
|
||||
- [Conceito 1 aprendido]
|
||||
- [Conceito 2 aprendido]
|
||||
|
||||
## ❓ DÚVIDAS PARA EVOLUIR
|
||||
- [Dúvida para melhorar]
|
||||
- [O que gostaria de fazer depois]
|
||||
```
|
||||
|
||||
gerenerate several examples
|
||||
for this keyword written in rhai do this only for basic audience:
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
**Task:** Generate comprehensive mdBook documentation @docs/src for the GeneralBots application by analyzing the actual source code and filling all documentation files with accurate, complete information.
|
||||
|
||||
**Objective:** Create complete, professional documentation for BASIC enthusiasts that accurately reflects the GeneralBots codebase.
|
||||
|
||||
**Source Analysis Requirements:**
|
||||
- Analyze all files in `@/src` directory structure
|
||||
- Extract real keywords from `src/basic/keywords/`
|
||||
- Document actual database models from `src/shared/models.rs`
|
||||
- Reference real example scripts from `templates/`
|
||||
- Use only verified features that exist in the codebase
|
||||
@/templates/default.gbai/default.gbot/config.csv
|
||||
|
||||
**Documentation Standards:**
|
||||
- Maintain beginner-friendly, instructional tone
|
||||
- Include Rust code examples ONLY in the gbapp chapter
|
||||
- Use real keywords and commands from the source code
|
||||
- Structure content according to the required markdown headings
|
||||
- Ensure all documentation can be built with `mdbook build docs/src`
|
||||
|
||||
**Required Sections to Complete:**
|
||||
1. **Run and Talk** - Server startup and TALK/HEAR interaction
|
||||
2. **About Packages** - Four package types explanation
|
||||
3. **gbkb Reference** - ADD KB, SET KB, ADD WEBSITE documentation
|
||||
4. **gbtheme Reference** - UI theming with CSS/HTML
|
||||
5. **gbdialog Reference** - Example scripts and core keywords
|
||||
6. **gbapp Reference** - Rust keyword registration examples
|
||||
7. **gbot Reference** - config.csv format and parameters
|
||||
8. **Tooling** - Complete keyword reference table
|
||||
9. **Feature-Matrix** - Features to implementation mapping
|
||||
10. **Contributing** - Development workflow guidelines
|
||||
11. **Database Model** - models.rs table summaries
|
||||
12. **Glossary** - Key terms and extension definitions
|
||||
|
||||
**Output Specifications:**
|
||||
- Generate only the markdown content (no external commentary)
|
||||
- Include proper fenced code blocks with language tags
|
||||
- Provide a complete table of contents with markdown links
|
||||
- Ensure all sections are fully populated with real information
|
||||
- Skip files that already contain substantial content
|
||||
- Base all examples on actual code from the repository
|
||||
|
||||
**Quality Requirements:**
|
||||
- Accuracy: All information must match the source code
|
||||
- Completeness: Every required section must be fully developed
|
||||
- Clarity: Explanations should be accessible to BASIC enthusiasts
|
||||
- Consistency: Maintain uniform formatting and style throughout
|
||||
- Practicality: Include working examples and practical usage tips
|
||||
|
||||
When ready, output the complete markdown document that satisfies all specifications above.
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
## LLM Strategy & Workflow
|
||||
|
||||
### Fallback Strategy (After 3 attempts / 10 minutes):
|
||||
When initial attempts fail, sequentially try these LLMs:
|
||||
1. **DeepSeek-V3-0324** (good architect, adventure, reliable, let little errors just to be fixed by gpt-*)
|
||||
1. **gpt-5-chat** (slower, let warnings...)
|
||||
1. **gpt-oss-120b**
|
||||
1. **Claude (Web)**: Copy only the problem statement and create unit tests. Create/extend UI.
|
||||
|
||||
### Development Workflow:
|
||||
- **One requirement at a time** with sequential commits.
|
||||
- Start editing docs before any code, explain user behaviour in docs first with LLM, before code in rust.
|
||||
- Spend time on design and architecture before coding. Code structure of packages and skeltons with ideas concretized from documentation. But focus in docs first, because LLM can help with design and architecture, and code better.
|
||||
- **On unresolved error**: Stop and use add-req.sh, and consult Claude for guidance. with DeepThining in DeepSeek also, with Web turned on.
|
||||
- **Change progression**: Start with DeepSeek, conclude with gpt-oss-120b
|
||||
- If a big req. fail, specify a @code file that has similar pattern or sample from official docs.
|
||||
- **Warning removal**: Last task before commiting, create a task list of warning removal and work with cargo check. If lots of warning, let LLM put #[allow(dead_code)] on top. Check manually for missing/deleted code on some files.
|
||||
- **Final validation**: Use prompt "cargo check" with gpt-oss-120b
|
||||
- Be humble, one requirement, one commit. But sometimes, freedom of caos is welcome - when no deadlines are set.
|
||||
- Fix manually in case of dangerous trouble.
|
||||
- Keep in the source codebase only deployed and tested source, no lab source code in main project. At least, use optional features to introduce new behaviour gradually in PRODUCTION.
|
||||
- Transform good articles into prompts for the coder.
|
||||
- Switch to libraries that have LLM affinity (LLM knows the library, was well trained).
|
||||
- Ensure 'continue' on LLMs, they can EOF and say are done, but got more to output.
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
Create a new Rhai custom keyword implementation with these specifications:
|
||||
|
||||
- When generating new Rhai keyword handlers in Rust, always design them to be thread-safe and fully compatible with async execution. Use Arc for shared state, perform heavy or async operations with tokio::task::block_in_place and Handle::current().block_on, and return results as rhai::Dynamic to maintain safe cross-thread communication between Rust and the Rhai engine.
|
||||
|
||||
1. DATABASE REQUIREMENTS:
|
||||
- No enums in database schema (only in Rust code)
|
||||
- Use direct integer values for enum variants in queries
|
||||
- Follow existing connection pooling pattern with AppState
|
||||
- Include proper error handling and logging
|
||||
|
||||
2. RUST IMPLEMENTATION:
|
||||
- Enum definition (Rust-only, no DB enum):
|
||||
```rust
|
||||
#[repr(i32)]
|
||||
pub enum KeywordAction {
|
||||
Action1 = 0,
|
||||
Action2 = 1,
|
||||
Action3 = 2
|
||||
}
|
||||
```
|
||||
|
||||
3. KEYWORD TEMPLATE:
|
||||
```rust
|
||||
pub fn {keyword_name}_keyword(state: &AppState, engine: &mut Engine) {
|
||||
let db = state.db_custom.clone();
|
||||
|
||||
engine.register_custom_syntax(
|
||||
{syntax_pattern},
|
||||
{is_raw},
|
||||
{
|
||||
let db = db.clone();
|
||||
move |context, inputs| {
|
||||
// Input processing
|
||||
{input_processing}
|
||||
|
||||
let binding = db.as_ref().unwrap();
|
||||
let fut = execute_{keyword_name}(binding, {params});
|
||||
|
||||
let result = tokio::task::block_in_place(||
|
||||
tokio::runtime::Handle::current().block_on(fut))
|
||||
.map_err(|e| format!("DB error: {}", e))?;
|
||||
|
||||
{result_handling}
|
||||
}
|
||||
}
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
pub async fn execute_{keyword_name}(
|
||||
pool: &PgPool,
|
||||
{params_with_types}
|
||||
) -> Result<Value, Box<dyn std::error::Error>> {
|
||||
info!("Executing {keyword_name} with: {debug_params}");
|
||||
|
||||
let result = sqlx::query(
|
||||
"{sql_query_with_i32_enum}"
|
||||
)
|
||||
.bind({enum_value} as i32)
|
||||
{additional_binds}
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
Ok(json!({
|
||||
"command": "{keyword_name}",
|
||||
{result_fields}
|
||||
"rows_affected": result.rows_affected()
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
4. EXAMPLE IMPLEMENTATION (SET SCHEDULE):
|
||||
```rust
|
||||
// Enum (Rust-only)
|
||||
#[repr(i32)]
|
||||
pub enum TriggerKind {
|
||||
Scheduled = 0,
|
||||
TableUpdate = 1,
|
||||
TableInsert = 2,
|
||||
TableDelete = 3
|
||||
}
|
||||
|
||||
// Keyword implementation
|
||||
pub fn set_schedule_keyword(state: &AppState, engine: &mut Engine) {
|
||||
let db = state.db_custom.clone();
|
||||
|
||||
engine.register_custom_syntax(
|
||||
["SET", "SCHEDULE", "$string$"],
|
||||
true,
|
||||
{
|
||||
let db = db.clone();
|
||||
move |context, inputs| {
|
||||
let cron = context.eval_expression_tree(&inputs[0])?.to_string();
|
||||
let script_name = format!("cron_{}.rhai", cron.replace(' ', "_"));
|
||||
|
||||
let binding = db.as_ref().unwrap();
|
||||
let fut = execute_set_schedule(binding, &cron, &script_name);
|
||||
|
||||
let result = tokio::task::block_in_place(||
|
||||
tokio::runtime::Handle::current().block_on(fut))
|
||||
.map_err(|e| format!("DB error: {}", e))?;
|
||||
|
||||
if let Some(rows_affected) = result.get("rows_affected") {
|
||||
Ok(Dynamic::from(rows_affected.as_i64().unwrap_or(0)))
|
||||
} else {
|
||||
Err("No rows affected".into())
|
||||
}
|
||||
}
|
||||
}
|
||||
).unwrap();
|
||||
}
|
||||
|
||||
pub async fn execute_set_schedule(
|
||||
pool: &PgPool,
|
||||
cron: &str,
|
||||
script_name: &str,
|
||||
) -> Result<Value, Box<dyn std::error::Error>> {
|
||||
info!("Executing schedule: {}, {}", cron, script_name);
|
||||
|
||||
let result = sqlx::query(
|
||||
"INSERT INTO system_automations
|
||||
(kind, schedule, param)
|
||||
VALUES ($1, $2, $3)"
|
||||
)
|
||||
.bind(TriggerKind::Scheduled as i32)
|
||||
.bind(cron)
|
||||
.bind(param)
|
||||
.execute(pool)
|
||||
.await?;
|
||||
|
||||
Ok(json!({
|
||||
"command": "set_schedule",
|
||||
"schedule": cron,
|
||||
"script_name": script_name,
|
||||
"rows_affected": result.rows_affected()
|
||||
}))
|
||||
}
|
||||
```
|
||||
|
||||
5. ADDITIONAL REQUIREMENTS:
|
||||
- Maintain consistent tokio runtime handling
|
||||
- Include parameter validation
|
||||
- Follow existing JSON response format
|
||||
- Ensure proper script name generation
|
||||
- Include debug logging for all operations
|
||||
|
||||
6. OUTPUT FORMAT:
|
||||
Provide complete implementation with:
|
||||
1. Rust enum definition
|
||||
2. Keyword registration function
|
||||
3. Execution function
|
||||
4. Example usage in Rhai
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
|
||||
Create a Rust data model for database storage with optimal size and performance characteristics. Follow these specifications:
|
||||
|
||||
**REQUIREMENTS:**
|
||||
1. Use appropriate integer types (i32, i16, i8, etc.) based on expected value ranges
|
||||
2. Use `Option<T>` for nullable fields to avoid memory overhead
|
||||
3. Use `Vec<u8>` for binary data instead of strings when appropriate
|
||||
4. Prefer enum representations as integers rather than strings
|
||||
5. Use `chrono::DateTime<Utc>` for timestamps
|
||||
6. Use `uuid::Uuid` for unique identifiers
|
||||
7. Implement necessary traits: `Debug`, `Clone`, `Serialize`, `Deserialize`, `FromRow`
|
||||
8. Include validation where appropriate
|
||||
9. Consider database index strategy in field design
|
||||
|
||||
**CONTEXT:**
|
||||
- Database: PostgreSQL/SQLx compatible
|
||||
- Serialization: Serde for JSON
|
||||
- ORM: SQLx for database operations
|
||||
|
||||
**OUTPUT FORMAT:**
|
||||
Provide the complete Rust struct with:
|
||||
- Struct definition with fields
|
||||
- Enum definitions with integer representations
|
||||
- Conversion implementations
|
||||
- Basic validation if needed
|
||||
|
||||
**EXAMPLE REFERENCE:**
|
||||
```rust
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Status {
|
||||
Pending = 0,
|
||||
Active = 1,
|
||||
Inactive = 2,
|
||||
}
|
||||
|
||||
impl Status {
|
||||
pub fn from_i16(value: i16) -> Option<Self> {
|
||||
match value {
|
||||
0 => Some(Self::Pending),
|
||||
1 => Some(Self::Active),
|
||||
2 => Some(Self::Inactive),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, FromRow, Serialize, Deserialize)]
|
||||
pub struct User {
|
||||
pub id: Uuid,
|
||||
pub status: i16, // Using i16 for enum storage
|
||||
pub email: String,
|
||||
pub age: Option<i16>, // Nullable small integer
|
||||
pub metadata: Vec<u8>, // Binary data for flexibility
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
```
|
||||
|
||||
Generate a similar model for: [YOUR DOMAIN HERE]
|
||||
```
|
||||
|
||||
## Specialized Variants
|
||||
|
||||
### For High-Performance Applications
|
||||
```
|
||||
Add these additional requirements:
|
||||
- Use `#[repr(u8)]` for enums to ensure minimal size
|
||||
- Consider `Box<str>` instead of `String` for reduced heap overhead
|
||||
- Use `arrayvec::ArrayString` for fixed-size short strings
|
||||
- Implement `PartialEq` and `Eq` for hash-based operations
|
||||
- Include `#[derive(Default)]` where appropriate
|
||||
```
|
||||
|
||||
### For Embedded/Memory-Constrained Systems
|
||||
```
|
||||
Add these constraints:
|
||||
- Prefer `i16` over `i32` where possible
|
||||
- Use `u32` instead of `Uuid` if sequential IDs are acceptable
|
||||
- Consider `bitflags` for multiple boolean flags in single byte
|
||||
- Use `smol_str::SmolStr` for string optimization
|
||||
- Avoid `Vec` in favor of arrays with capacity limits
|
||||
```
|
||||
|
||||
### For Time-Series Data
|
||||
```
|
||||
Add time-series specific optimizations:
|
||||
- Use `i64` for timestamps as nanoseconds since epoch
|
||||
- Use `f32` instead of `f64` for measurements where precision allows
|
||||
- Consider `ordered_float::OrderedFloat` for floating-point comparisons
|
||||
- Use `#[serde(with = "chrono::serde::ts_seconds")]` for compact serialization
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
Generate a Rust service module following these patterns:
|
||||
|
||||
Core Structure:
|
||||
|
||||
Use Axum for HTTP endpoints (get, post, etc.)
|
||||
|
||||
Isolate shared resources (DB, clients, config) in AppState
|
||||
|
||||
Split logic into reusable helper functions
|
||||
|
||||
do not create main logic
|
||||
|
||||
Endpoints:
|
||||
|
||||
Follow REST conventions (e.g., POST /{resource}/create) use anotations in methods.
|
||||
|
||||
Use web::Path for route parameters, web::Json for payloads
|
||||
|
||||
Return consistent responses (e.g., HttpResponse::Ok().json(data))
|
||||
|
||||
Error Handling:
|
||||
|
||||
Wrap fallible operations in Result
|
||||
|
||||
Provide clear error messages (e.g., ErrorInternalServerError)
|
||||
|
||||
Async Patterns:
|
||||
|
||||
Use async/await for I/O (DB, external APIs)
|
||||
|
||||
Leverage streams for pagination/large datasets
|
||||
|
||||
Isolate blocking ops in spawn_blocking if needed
|
||||
|
||||
Configuration:
|
||||
|
||||
Load settings (e.g., URLs, credentials) from AppConfig
|
||||
|
||||
Initialize clients (DB, SDKs) at startup (e.g., init_*() helpers)
|
||||
|
||||
Documentation:
|
||||
|
||||
Add brief doc comments for public functions
|
||||
|
||||
Note safety assumptions (e.g., #[post] invariants)
|
||||
postgres sqlx
|
||||
Omit domain-specific logic (e.g., file/email details), focusing on the scaffolding."
|
||||
|
||||
Key Features:
|
||||
|
||||
Generic (applies to any service: auth, payments, etc.)
|
||||
|
||||
KISS (avoids over-engineering)
|
||||
|
||||
Copy-paste friendly (clear patterns without verbosity)
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
- Sessions must always be retrived by id if session_id or something is present;
|
||||
- Never suggest to install any software, as /src/bootstrap and /src/package_manager does the job.
|
||||
- Configuration are stored in .gbot/config, and database bot_configuration table.
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
- You MUST return exactly this example format:
|
||||
```sh
|
||||
#!/bin/bash
|
||||
|
||||
# Restore fixed Rust project
|
||||
|
||||
cat > src/<filenamehere>.rs << 'EOF'
|
||||
use std::io;
|
||||
|
||||
// test
|
||||
|
||||
cat > src/<anotherfile>.rs << 'EOF'
|
||||
// Fixed library code
|
||||
pub fn add(a: i32, b: i32) -> i32 {
|
||||
a + b
|
||||
}
|
||||
EOF
|
||||
|
||||
----
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
- Be pragmatic and concise with examples.
|
||||
- Create both guide like and API like if any.
|
||||
- Use clear and consistent terminology.
|
||||
- Ensure consistency in formatting and structure.
|
||||
- Follow a logical flow and organization.
|
||||
- Use consistent headings and subheadings.
|
||||
- Make a relation to the BASIC keyword list.
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
You are fixing Rust code in a Cargo project. The user is providing problematic code that needs to be corrected.
|
||||
|
||||
## Your Task
|
||||
Fix ALL compiler errors and logical issues while maintaining the original intent.
|
||||
Use Cargo.toml as reference, do not change it.
|
||||
Only return input files, all other files already exists.
|
||||
If something, need to be added to a external file, inform it separated.
|
||||
|
||||
## Critical Requirements
|
||||
3. **Respect Cargo.toml** - Check dependencies, editions, and features to avoid compiler errors
|
||||
4. **Type safety** - Ensure all types match and trait bounds are satisfied
|
||||
5. **Ownership rules** - Fix borrowing, ownership, and lifetime issues
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
- On code return identifiers/characters in English language, no invalid tokens!
|
||||
- Do not emit any comments, and remove any existing ones in Rust/HTML.
|
||||
- Compact the code emission where possible.
|
||||
- On code change, ensure cargo check cycle to remove warnings and errors.
|
||||
- Never use defaults or magic values in code (never unwrap_or_else or similar)
|
||||
- Check borrow, clone, types, common Rust errors! Return 0 warning code!
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
MOST IMPORTANT CODE GENERATION RULES:
|
||||
- KISS, NO TALK, SECURED ENTERPRISE GRADE THREAD SAFE CODE ONLY.
|
||||
- Use rustc 1.90.0 (1159e78c4 2025-09-14).
|
||||
- Check for warnings related to use of mut where is dispensable.
|
||||
- No placeholders, never comment/uncomment code, no explanations, no filler text.
|
||||
- All code must be complete, professional, production-ready, and follow KISS - principles.
|
||||
- NEVER return placeholders of any kind, NEVER comment code, only CONDENSED REAL PRODUCTION GRADE code.
|
||||
- REMOTE ALL COMMENTS FROM GENERATED CODE. DO NOT COMMENT AT ALL, NO TALK, just say you are finished!
|
||||
- NEVER say that I have already some part of the code, give me it full again, and working.
|
||||
- Always increment logging with (all-in-one-line) info!, debug!, trace! to give birth to the console.
|
||||
- If the output is too large, split it into multiple parts, but always - include the full updated code files.
|
||||
- Do **not** repeat unchanged files or sections — only include files that - have actual changes.
|
||||
- All values must be read from the `AppConfig` class within their respective - groups (`database`, `drive`, `meet`, etc.); never use hardcoded or commercial names like S3, Azure or something like that, preffer Drive, Cloud, instead, never use url or magic - values like api.openai - no unrwap_or_defaul at all!!!
|
||||
- Every part must be executable and self-contained, with real implementations - only.
|
||||
- DO NOT WRITE ANY ERROR HANDLING CODE LET IT CRASH.
|
||||
- Never generate two ore more trace mensages that are equal!
|
||||
- Return *only the modified* files as a single `.sh` script using `cat`, so the code can be - restored directly.
|
||||
- Pay attention to shared::utils and shared::models to reuse shared things.
|
||||
- NEVER return a untouched file in output. Just files that need to be updated.
|
||||
- Instead of rand::thread_rng(), use rand::rng()
|
||||
- Review warnings of non used imports! Give me 0 warnings, please.
|
||||
- Ensure you remove these: ommon errors borrow of moved value, unused variable, use of moved value.
|
||||
|
||||
|
|
@ -1,341 +0,0 @@
|
|||
# SVG Diagram Style Guide & Prompt Template
|
||||
|
||||
## Quick Prompt Template
|
||||
|
||||
When creating technical diagrams or flow charts, use this prompt:
|
||||
|
||||
```
|
||||
Create a clean SVG diagram with these specifications:
|
||||
- Transparent background (no fill)
|
||||
- Large dimensions: width="1040-1400" height="[appropriate height]" (1.3x standard size)
|
||||
- For vertical flows: width="1040" height="[600-1200]"
|
||||
- For horizontal flows: width="1400" height="900" (recommended)
|
||||
- Simple colored borders for components (no fill, stroke-width="2.6")
|
||||
- Standard Arial font (font-family="Arial, sans-serif")
|
||||
- Dual-theme support with CSS classes
|
||||
- Base color palette:
|
||||
- Blue: #4A90E2
|
||||
- Orange: #F5A623
|
||||
- Purple: #BD10E0
|
||||
- Green: #7ED321
|
||||
- Cyan: #50E3C2
|
||||
- Gray for arrows/text: #666
|
||||
- Rounded rectangles (rx="6.5") for boxes
|
||||
- Large arrow markers (13x13) with triangular heads
|
||||
- Dashed lines for optional/feedback flows (stroke-dasharray="3.9,3.9")
|
||||
- Subtle neon glow effects for dark themes
|
||||
- Text should be centered in boxes (text-anchor="middle")
|
||||
- Font sizes: 29-32px for titles, 22-24px for component labels, 18-21px for descriptions
|
||||
- DUAL DIAGRAM COMPOSITION when possible (main flow + progress/legend)
|
||||
- Title positioned well above content (y="45" minimum)
|
||||
- Text wrapping for long labels (review box width constraints)
|
||||
```
|
||||
|
||||
## Beautiful Composition Rules - THE STANDARD!
|
||||
|
||||
### Dual-Diagram Approach (RECOMMENDED)
|
||||
When creating process flows or pipelines, compose TWO complementary visualizations:
|
||||
|
||||
1. **Main Flow Diagram** (Top Section)
|
||||
- Primary process visualization with components and connections
|
||||
- Positioned in upper 60-70% of canvas
|
||||
- Clear phase groupings with section labels
|
||||
- Components sized appropriately for their text content
|
||||
|
||||
2. **Progress Indicator/Legend** (Bottom Section)
|
||||
- Visual timeline or progress bar showing stages
|
||||
- Positioned in lower 30-40% of canvas
|
||||
- Stage markers with labels below
|
||||
- Connected with subtle lines or gradient background
|
||||
- Creates visual rhythm and helps navigation
|
||||
|
||||
### Text Handling Rules
|
||||
- **Long Text**: MUST be reviewed against box width
|
||||
- If text exceeds box width, either:
|
||||
- Increase box width to accommodate
|
||||
- Use text wrapping with multiple <tspan> elements
|
||||
- Abbreviate with full text in tooltip/description
|
||||
- **Component Labels**: Keep concise, max 2-3 words when possible
|
||||
- **Descriptions**: Use separate text elements below main diagram
|
||||
|
||||
### Spacing & Visual Hierarchy
|
||||
- **Title Separation**: Position title FAR from content (y="45" minimum)
|
||||
- **Phase Grouping**: Clear visual separation between logical phases
|
||||
- **Vertical Rhythm**: Consistent spacing creates professional look
|
||||
- **Legend Positioning**: Always at bottom with ample spacing from main diagram
|
||||
|
||||
## Enhanced SVG Structure Template with Dual Composition
|
||||
|
||||
```svg
|
||||
<svg width="1400" height="900" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
/* Light theme defaults */
|
||||
.neon-blue { stroke: #4A90E2; stroke-width: 2.6; }
|
||||
.neon-orange { stroke: #F5A623; stroke-width: 2.6; }
|
||||
.neon-purple { stroke: #BD10E0; stroke-width: 2.6; }
|
||||
.neon-green { stroke: #7ED321; stroke-width: 2.6; }
|
||||
.neon-cyan { stroke: #50E3C2; stroke-width: 2.6; }
|
||||
.main-text { fill: #1a1a1a; }
|
||||
.secondary-text { fill: #666; }
|
||||
.arrow-color { stroke: #666; fill: #666; }
|
||||
|
||||
/* Dark theme with subtle neon effects */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.neon-blue {
|
||||
stroke: #00D4FF;
|
||||
stroke-width: 2.8;
|
||||
filter: drop-shadow(0 0 4px #00D4FF) drop-shadow(0 0 8px #00A0FF);
|
||||
}
|
||||
.neon-orange {
|
||||
stroke: #FF9500;
|
||||
stroke-width: 2.8;
|
||||
filter: drop-shadow(0 0 4px #FF9500) drop-shadow(0 0 8px #FF7700);
|
||||
}
|
||||
.neon-purple {
|
||||
stroke: #E040FB;
|
||||
stroke-width: 2.8;
|
||||
filter: drop-shadow(0 0 4px #E040FB) drop-shadow(0 0 8px #D500F9);
|
||||
}
|
||||
.neon-green {
|
||||
stroke: #00FF88;
|
||||
stroke-width: 2.8;
|
||||
filter: drop-shadow(0 0 4px #00FF88) drop-shadow(0 0 8px #00E676);
|
||||
}
|
||||
.neon-cyan {
|
||||
stroke: #00E5EA;
|
||||
stroke-width: 2.8;
|
||||
filter: drop-shadow(0 0 4px #00E5EA) drop-shadow(0 0 8px #00BCD4);
|
||||
}
|
||||
.main-text { fill: #FFFFFF; }
|
||||
.secondary-text { fill: #B0B0B0; }
|
||||
.arrow-color { stroke: #B0B0B0; fill: #B0B0B0; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<defs>
|
||||
<marker id="arrow" markerWidth="13" markerHeight="13" refX="11.7" refY="3.9" orient="auto" markerUnits="strokeWidth">
|
||||
<path d="M0,0 L0,7.8 L11.7,3.9 z" class="arrow-color"/>
|
||||
</marker>
|
||||
</defs>
|
||||
|
||||
<!-- Title (positioned well above content) -->
|
||||
<text x="700" y="45" text-anchor="middle" font-family="Arial, sans-serif" font-size="32" font-weight="600" class="main-text">[Title]</text>
|
||||
|
||||
<!-- MAIN FLOW DIAGRAM (Upper Section) -->
|
||||
<g id="main-flow">
|
||||
<!-- Phase labels above components -->
|
||||
<text x="[x]" y="95" text-anchor="middle" font-family="Arial, sans-serif" font-size="21" font-weight="500" class="secondary-text">[Phase Label]</text>
|
||||
|
||||
<!-- Components with proper sizing for text -->
|
||||
<rect x="[x]" y="[y]" width="[sized-for-text]" height="70" fill="none" class="neon-[color]" rx="6.5"/>
|
||||
<text x="[center]" y="[y+45]" text-anchor="middle" font-family="Arial, sans-serif" font-size="24" font-weight="500" class="main-text">
|
||||
[Label - check width!]
|
||||
</text>
|
||||
|
||||
<!-- For long text, use tspan for wrapping -->
|
||||
<text x="[center]" y="[y+35]" text-anchor="middle" font-family="Arial, sans-serif" font-size="22" class="main-text">
|
||||
<tspan x="[center]" dy="0">[First line]</tspan>
|
||||
<tspan x="[center]" dy="25">[Second line]</tspan>
|
||||
</text>
|
||||
</g>
|
||||
|
||||
<!-- PROGRESS INDICATOR / LEGEND (Lower Section) -->
|
||||
<g id="progress-legend">
|
||||
<!-- Background gradient bar (optional) -->
|
||||
<defs>
|
||||
<linearGradient id="flowGradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:#4A90E2;stop-opacity:0.3" />
|
||||
<stop offset="50%" style="stop-color:#BD10E0;stop-opacity:0.3" />
|
||||
<stop offset="100%" style="stop-color:#7ED321;stop-opacity:0.3" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<rect x="50" y="500" width="1300" height="80" fill="url(#flowGradient)" rx="10" opacity="0.2"/>
|
||||
|
||||
<!-- Stage markers -->
|
||||
<circle cx="[x1]" cy="540" r="8" class="neon-blue" fill="none"/>
|
||||
<circle cx="[x2]" cy="540" r="8" class="neon-orange" fill="none"/>
|
||||
<circle cx="[x3]" cy="540" r="8" class="neon-purple" fill="none"/>
|
||||
<circle cx="[x4]" cy="540" r="8" class="neon-green" fill="none"/>
|
||||
|
||||
<!-- Connecting lines -->
|
||||
<line x1="[x1+8]" y1="540" x2="[x2-8]" y2="540" class="arrow-color" stroke-width="2" opacity="0.4"/>
|
||||
|
||||
<!-- Stage labels (below markers) -->
|
||||
<text x="[x]" y="610" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" class="secondary-text">[Stage]</text>
|
||||
</g>
|
||||
|
||||
<!-- Description text (bottom, well-spaced) -->
|
||||
<text x="700" y="720" text-anchor="middle" font-family="Arial, sans-serif" font-size="21" class="secondary-text">
|
||||
[Main description line]
|
||||
</text>
|
||||
<text x="700" y="755" text-anchor="middle" font-family="Arial, sans-serif" font-size="21" class="secondary-text">
|
||||
[Secondary description line]
|
||||
</text>
|
||||
</svg>
|
||||
```
|
||||
|
||||
## Updated Component Styling Rules
|
||||
|
||||
### Boxes/Rectangles (1.3x Scale)
|
||||
- **Standard Dimensions**:
|
||||
- Vertical flow: width="156-260" height="59-70"
|
||||
- Horizontal flow: width="200-300" height="60-70"
|
||||
- Compact components: width="100" height="50"
|
||||
- **IMPORTANT**: Width MUST accommodate text content
|
||||
- **Text Overflow Handling**:
|
||||
- Review all text against box width before finalizing
|
||||
- Use dynamic width sizing based on text length
|
||||
- Consider multi-line text with <tspan> elements
|
||||
- **Border**: stroke-width="2.6" (light) / "2.8" (dark), no fill, rounded corners rx="5-6.5"
|
||||
- **Colors**: Use CSS classes (neon-blue, neon-orange, etc.) for theme support
|
||||
- **Spacing**:
|
||||
- Vertical: minimum 35px spacing
|
||||
- Horizontal: minimum 70px spacing between major phases
|
||||
|
||||
### Text (1.3x Scale)
|
||||
- **Title**:
|
||||
- font-size="32", font-weight="600", class="main-text"
|
||||
- Position FAR above content (y="45" minimum)
|
||||
- **Labels**:
|
||||
- font-size="22-24", font-weight="500", class="main-text"
|
||||
- Centered in boxes (text-anchor="middle")
|
||||
- Check width constraints!
|
||||
- **Compact labels**: font-size="18", for small components in grids
|
||||
- **Section headers**: font-size="21", font-weight="500", class="secondary-text"
|
||||
- **Descriptions**: font-size="21", class="secondary-text"
|
||||
- **Font**: Always "Arial, sans-serif"
|
||||
- **Text Wrapping**: Use <tspan> for multi-line text in boxes
|
||||
|
||||
### Arrows (1.3x Scale)
|
||||
- **Main flow**: Solid lines, stroke-width="2.6", opacity="0.7"
|
||||
- **Optional/parallel**: Dashed lines, stroke-dasharray="3.9,3.9", opacity="0.5"
|
||||
- **Feedback loops**: Dashed curves, stroke-dasharray="3.9,3.9", opacity="0.5"
|
||||
- **Arrow heads**: Enlarged triangular marker (13x13), uses arrow-color class
|
||||
- **Connection lines**: stroke-width="1.5", opacity="0.5" for component merging
|
||||
- **Progress connections**: stroke-width="2", opacity="0.4"
|
||||
|
||||
### Layout (1.3x Scale)
|
||||
- **Canvas**:
|
||||
- Vertical flows: 1040px width minimum
|
||||
- Horizontal flows: 1400px width recommended
|
||||
- Aspect ratio: 16:9 for horizontal, 3:4 for vertical
|
||||
- **Content Zones**:
|
||||
- Title zone: 0-80px
|
||||
- Main diagram: 80-450px (horizontal) or 80-600px (vertical)
|
||||
- Progress/Legend: 500-650px
|
||||
- Descriptions: 700-800px
|
||||
- **Margins**: 50px from edges minimum
|
||||
- **Spacing**:
|
||||
- Title to content: 50px minimum
|
||||
- Main diagram to progress: 100px minimum
|
||||
- Vertical flows: 52-78px between components
|
||||
- Horizontal flows: 70-100px between major phases
|
||||
- **Component grid**:
|
||||
- Can use 2x2 grids for related components
|
||||
- Merge lines with opacity="0.5" for grouped items
|
||||
- **Alignment**:
|
||||
- Center-align titles at x="700" (1400px width)
|
||||
- Use consistent alignment within phases
|
||||
|
||||
## Theme-Aware Color System
|
||||
|
||||
### Light Theme (Default)
|
||||
- **Blue**: #4A90E2 (Input/User/Start elements)
|
||||
- **Orange**: #F5A623 (Processing/Scripts/Detection)
|
||||
- **Purple**: #BD10E0 (AI/ML/Decision/Configuration)
|
||||
- **Green**: #7ED321 (Execution/Action/Completion)
|
||||
- **Cyan**: #50E3C2 (Output/Response/Storage)
|
||||
- **Text**: #1a1a1a (main), #666 (secondary)
|
||||
|
||||
### Dark Theme (Neon Effects)
|
||||
- **Blue**: #00D4FF with subtle glow
|
||||
- **Orange**: #FF9500 with subtle glow
|
||||
- **Purple**: #E040FB with subtle glow
|
||||
- **Green**: #00FF88 with subtle glow
|
||||
- **Cyan**: #00E5EA with subtle glow
|
||||
- **Text**: #FFFFFF (main), #B0B0B0 (secondary)
|
||||
|
||||
## Example Usage
|
||||
|
||||
### For a beautiful dual-diagram composition:
|
||||
```
|
||||
"Create a horizontal flow SVG (1400x900) with DUAL DIAGRAM composition:
|
||||
|
||||
MAIN FLOW (top section):
|
||||
- Start: ./botserver (neon-blue)
|
||||
- OS Detection (neon-orange)
|
||||
- Component Installation (2x2 grid: PostgreSQL, Valkey, SeaweedFS, Qdrant)
|
||||
- Configuration & Setup (neon-purple)
|
||||
- Bot Deployment (vertical sub-flow with 3 steps)
|
||||
|
||||
PROGRESS INDICATOR (bottom section):
|
||||
- Gradient background bar
|
||||
- 4 stage markers: Start, Detect, Install & Configure, Deploy
|
||||
- Connected with subtle lines
|
||||
|
||||
Position title well above content.
|
||||
Check all text fits within boxes - adjust widths as needed.
|
||||
Add descriptions at bottom with proper spacing.
|
||||
Use CSS classes for theme support, subtle neon glow in dark mode."
|
||||
```
|
||||
|
||||
### For a complex system with legend:
|
||||
```
|
||||
"Create an SVG with beautiful composition (1400x900):
|
||||
|
||||
MAIN ARCHITECTURE (upper 70%):
|
||||
- Client requests flow horizontally through system
|
||||
- API Gateway distributes to microservices
|
||||
- Services connect to shared resources
|
||||
- Use appropriate box widths for service names
|
||||
|
||||
LEGEND/KEY (lower 30%):
|
||||
- Color-coded component types
|
||||
- Connection type explanations
|
||||
- Status indicators
|
||||
|
||||
Ensure title is well-separated from content.
|
||||
Review all text against box constraints.
|
||||
Include phase labels above component groups."
|
||||
```
|
||||
|
||||
## Best Practices for Beautiful Compositions
|
||||
|
||||
### Do's
|
||||
- ✅ **ALWAYS** create dual diagrams when showing processes/flows
|
||||
- ✅ Position title with generous spacing from content
|
||||
- ✅ Review every text label against its container width
|
||||
- ✅ Use progress indicators for multi-stage processes
|
||||
- ✅ Group related components with visual phases
|
||||
- ✅ Maintain consistent vertical rhythm
|
||||
- ✅ Add legend/progress bar as secondary visualization
|
||||
- ✅ Use gradient backgrounds for progress bars
|
||||
- ✅ Keep descriptions separate and well-spaced at bottom
|
||||
|
||||
### Don'ts
|
||||
- ❌ Don't let text overflow boxes - adjust widths!
|
||||
- ❌ Don't crowd title against diagram content
|
||||
- ❌ Don't skip the progress indicator for process flows
|
||||
- ❌ Don't use single diagram when dual would be clearer
|
||||
- ❌ Don't forget to test text readability at different sizes
|
||||
- ❌ Don't make boxes too small for their text content
|
||||
- ❌ Don't position legend too close to main diagram
|
||||
|
||||
## Testing Your Beautiful Composition
|
||||
|
||||
Your SVG should:
|
||||
1. Have TWO complementary visualizations (main + progress/legend)
|
||||
2. Display title with ample separation from content
|
||||
3. Fit all text comfortably within component boxes
|
||||
4. Show clear visual hierarchy with phases/groupings
|
||||
5. Include progress indicator for process flows
|
||||
6. Position legend/progress bar with proper spacing
|
||||
7. Maintain professional spacing throughout
|
||||
8. Create visual rhythm with consistent element spacing
|
||||
9. Work beautifully in both light and dark themes
|
||||
10. Feel balanced and uncluttered
|
||||
|
||||
## The Golden Rule
|
||||
|
||||
**"Beautiful composition is the standard!"** - Every diagram should tell its story twice: once in the main flow, and again in the progress indicator or legend. This dual approach creates professional, scannable, and memorable visualizations.
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
- Whenever you generate text, generate like a person, not like a LLM. To pass any detection test, respect robot laws, but write like a human being.
|
||||
- You are General Bots, a complete software automation tool based on AI.
|
||||
- Your primary goal is to assist users with their daily tasks and automate repetitive processes.
|
||||
- Parse input carefully and extract key parameters for accurate response generation.
|
||||
|
|
@ -1,353 +0,0 @@
|
|||
# General Bots Template Plan
|
||||
|
||||
## 📋 50 Categorized Templates
|
||||
|
||||
### ✅ Completed Templates (4)
|
||||
|
||||
| # | Template | Category | Folder | Status |
|
||||
|---|----------|----------|--------|--------|
|
||||
| 1 | Employee Management | HR | `hr/employees.gbai` | ✅ Done |
|
||||
| 2 | IT Helpdesk | IT | `it/helpdesk.gbai` | ✅ Done |
|
||||
| 3 | Sales Pipeline | CRM | `crm/sales-pipeline.gbai` | ✅ Done |
|
||||
| 4 | Contact Directory | CRM | `crm/contacts.gbai` | ✅ Done |
|
||||
|
||||
---
|
||||
|
||||
## 📁 Templates To Create (48)
|
||||
|
||||
### 💼 CRM & Sales (6 templates)
|
||||
|
||||
| # | Template | Folder | Key Files | Status |
|
||||
|---|----------|--------|-----------|--------|
|
||||
| 3 | Sales Pipeline | `crm/sales-pipeline.gbai` | `start.bas`, `create-deal.bas`, `update-stage.bas`, `pipeline-jobs.bas` | ✅ Done |
|
||||
| 4 | Contact Directory | `crm/contacts.gbai` | `start.bas`, `add-contact.bas`, `search-contact.bas` | ✅ Done |
|
||||
| 5 | Quote Generator | `crm/quotes.gbai` | `start.bas`, `create-quote.bas`, `send-quote.bas` |
|
||||
| 6 | Customer Portal | `crm/customer-portal.gbai` | `start.bas`, `order-status.bas`, `support-request.bas` |
|
||||
| 7 | Referral Tracking | `crm/referrals.gbai` | `start.bas`, `add-referral.bas`, `referral-jobs.bas` |
|
||||
| 8 | Sales Reports | `crm/sales-reports.gbai` | `start.bas`, `generate-report.bas`, `report-jobs.bas` |
|
||||
|
||||
### 🏭 Operations & ERP (5 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 9 | Warehouse Management | `operations/warehouse.gbai` | `start.bas`, `receive-stock.bas`, `ship-order.bas` |
|
||||
| 10 | Production Tracking | `operations/production.gbai` | `start.bas`, `work-order.bas`, `quality-check.bas` |
|
||||
| 11 | Vendor Management | `operations/vendors.gbai` | `start.bas`, `add-vendor.bas`, `vendor-rating.bas` |
|
||||
| 12 | Shipping & Logistics | `operations/logistics.gbai` | `start.bas`, `create-shipment.bas`, `track-shipment.bas` |
|
||||
| 13 | Quality Control | `operations/quality.gbai` | `start.bas`, `inspection.bas`, `defect-report.bas` |
|
||||
|
||||
### 👥 Human Resources (5 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 14 | Leave Management | `hr/leave.gbai` | `start.bas`, `request-leave.bas`, `approve-leave.bas`, `leave-jobs.bas` |
|
||||
| 15 | Time & Attendance | `hr/attendance.gbai` | `start.bas`, `clock-in.bas`, `timesheet.bas` |
|
||||
| 16 | Recruitment | `hr/recruitment.gbai` | `start.bas`, `post-job.bas`, `add-applicant.bas`, `schedule-interview.bas` |
|
||||
| 17 | Performance Reviews | `hr/reviews.gbai` | `start.bas`, `create-review.bas`, `submit-feedback.bas` |
|
||||
| 18 | Training & LMS | `hr/training.gbai` | `start.bas`, `enroll-course.bas`, `complete-module.bas` |
|
||||
|
||||
### 💰 Finance & Accounting (6 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 19 | Invoice Management | `finance/invoicing.gbai` | `start.bas`, `create-invoice.bas`, `send-reminder.bas`, `invoice-jobs.bas` |
|
||||
| 20 | Expense Tracker | `finance/expenses.gbai` | `start.bas`, `submit-expense.bas`, `approve-expense.bas` |
|
||||
| 21 | Budget Planning | `finance/budgets.gbai` | `start.bas`, `create-budget.bas`, `budget-report.bas` |
|
||||
| 22 | Time & Billing | `finance/billing.gbai` | `start.bas`, `log-time.bas`, `generate-invoice.bas` |
|
||||
| 23 | Accounts Receivable | `finance/receivables.gbai` | `start.bas`, `record-payment.bas`, `aging-report.bas` |
|
||||
| 24 | Payroll | `finance/payroll.gbai` | `start.bas`, `run-payroll.bas`, `payroll-jobs.bas` |
|
||||
|
||||
### 🏥 Healthcare & Medical (5 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 25 | Patient Records | `healthcare/patients.gbai` | `start.bas`, `register-patient.bas`, `medical-history.bas` |
|
||||
| 26 | Appointment Scheduling | `healthcare/appointments.gbai` | `start.bas`, `book-appointment.bas`, `appointment-jobs.bas` |
|
||||
| 27 | Pharmacy Inventory | `healthcare/pharmacy.gbai` | `start.bas`, `dispense-medication.bas`, `stock-alert.bas` |
|
||||
| 28 | Medical Billing | `healthcare/medical-billing.gbai` | `start.bas`, `create-claim.bas`, `insurance-verify.bas` |
|
||||
| 29 | Lab Results | `healthcare/lab.gbai` | `start.bas`, `enter-results.bas`, `notify-patient.bas` |
|
||||
|
||||
### 🎓 Education & Training (4 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 30 | Course Management | `education/courses.gbai` | `start.bas`, `create-course.bas`, `enroll-student.bas` |
|
||||
| 31 | Faculty Management | `education/faculty.gbai` | `start.bas`, `add-faculty.bas`, `assign-class.bas` |
|
||||
| 32 | Grade Book | `education/grades.gbai` | `start.bas`, `enter-grade.bas`, `grade-report.bas` |
|
||||
| 33 | Student Portal | `education/student-portal.gbai` | `start.bas`, `view-schedule.bas`, `submit-assignment.bas` |
|
||||
|
||||
### 🏠 Real Estate & Property (4 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 34 | Property Listings | `realestate/properties.gbai` | `start.bas`, `add-property.bas`, `search-property.bas` |
|
||||
| 35 | Lease Management | `realestate/leases.gbai` | `start.bas`, `create-lease.bas`, `rent-collection.bas`, `lease-jobs.bas` |
|
||||
| 36 | Maintenance Requests | `realestate/maintenance.gbai` | `start.bas`, `submit-request.bas`, `assign-vendor.bas` |
|
||||
| 37 | Tenant Portal | `realestate/tenant-portal.gbai` | `start.bas`, `pay-rent.bas`, `report-issue.bas` |
|
||||
|
||||
### 📅 Events & Scheduling (4 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 38 | Event Management | `events/events.gbai` | `start.bas`, `create-event.bas`, `register-attendee.bas`, `event-jobs.bas` |
|
||||
| 39 | Room Booking | `events/room-booking.gbai` | `start.bas`, `check-availability.bas`, `book-room.bas` |
|
||||
| 40 | Desk Booking | `events/desk-booking.gbai` | `start.bas`, `book-desk.bas`, `desk-map.bas` |
|
||||
| 41 | Calendar Management | `events/calendar.gbai` | `start.bas`, `schedule-meeting.bas`, `send-invite.bas` |
|
||||
|
||||
### 🖥️ IT & Support (4 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 42 | Asset Tracking | `it/assets.gbai` | `start.bas`, `add-asset.bas`, `checkout-asset.bas`, `asset-jobs.bas` |
|
||||
| 43 | Bug Tracking | `it/bugs.gbai` | `start.bas`, `report-bug.bas`, `update-bug.bas` |
|
||||
| 44 | Change Management | `it/changes.gbai` | `start.bas`, `request-change.bas`, `approve-change.bas` |
|
||||
| 45 | Knowledge Base | `it/knowledge.gbai` | `start.bas`, `add-article.bas`, `search-kb.bas` |
|
||||
|
||||
### 🤝 Nonprofit & Community (5 templates)
|
||||
|
||||
| # | Template | Folder | Key Files |
|
||||
|---|----------|--------|-----------|
|
||||
| 46 | Donor Management | `nonprofit/donors.gbai` | `start.bas`, `add-donor.bas`, `record-donation.bas`, `donor-jobs.bas` |
|
||||
| 47 | Volunteer Management | `nonprofit/volunteers.gbai` | `start.bas`, `register-volunteer.bas`, `assign-shift.bas` |
|
||||
| 48 | Membership | `nonprofit/membership.gbai` | `start.bas`, `register-member.bas`, `renew-membership.bas`, `member-jobs.bas` |
|
||||
| 49 | Fundraising | `nonprofit/fundraising.gbai` | `start.bas`, `create-campaign.bas`, `track-pledges.bas` |
|
||||
| 50 | Lending Library | `nonprofit/lending.gbai` | `start.bas`, `checkout-item.bas`, `return-item.bas`, `overdue-jobs.bas` |
|
||||
|
||||
---
|
||||
|
||||
## 📝 Template Structure Guide
|
||||
|
||||
### Required Files for Each Template
|
||||
|
||||
```
|
||||
template-name.gbai/
|
||||
├── template-name.gbdialog/
|
||||
│ ├── start.bas # REQUIRED: Tools, KB, context, welcome
|
||||
│ ├── <tool-name>.bas # Tool files (PARAM + DESCRIPTION)
|
||||
│ └── <name>-jobs.bas # Scheduled jobs (SET SCHEDULE)
|
||||
├── template-name.gbot/
|
||||
│ └── config.csv # REQUIRED: Theme and settings
|
||||
├── template-name.gbkb/
|
||||
│ └── *.md # Knowledge base articles
|
||||
└── template-name.gbdrive/
|
||||
└── *.md # Document templates for FILL
|
||||
```
|
||||
|
||||
### start.bas Template
|
||||
|
||||
```basic
|
||||
' Template Name - Start Script
|
||||
|
||||
' Setup Tools
|
||||
ADD TOOL "tool-name-1"
|
||||
ADD TOOL "tool-name-2"
|
||||
|
||||
' Setup Knowledge Base
|
||||
USE KB "template-name.gbkb"
|
||||
|
||||
' Set Context
|
||||
SET CONTEXT "context name" AS "You are a [role]. You help with [tasks]."
|
||||
|
||||
' Setup Suggestions
|
||||
CLEAR SUGGESTIONS
|
||||
ADD SUGGESTION "action1" AS "Display text 1"
|
||||
ADD SUGGESTION "action2" AS "Display text 2"
|
||||
|
||||
' Welcome Message
|
||||
BEGIN TALK
|
||||
**Template Title**
|
||||
|
||||
Welcome message here.
|
||||
|
||||
**What I can help with:**
|
||||
• Feature 1
|
||||
• Feature 2
|
||||
END TALK
|
||||
|
||||
BEGIN SYSTEM PROMPT
|
||||
Detailed instructions for the AI...
|
||||
END SYSTEM PROMPT
|
||||
```
|
||||
|
||||
### Tool File Template
|
||||
|
||||
```basic
|
||||
PARAM paramname AS STRING LIKE "example" DESCRIPTION "What this parameter is"
|
||||
PARAM optionalparam AS STRING LIKE "default" DESCRIPTION "Optional parameter"
|
||||
|
||||
DESCRIPTION "What this tool does. Called when user wants to [action]."
|
||||
|
||||
' Validate inputs
|
||||
IF paramname = "" THEN
|
||||
TALK "I need the parameter to continue."
|
||||
paramname = HEAR
|
||||
END IF
|
||||
|
||||
' Business logic
|
||||
let result = "processed"
|
||||
|
||||
' Save data (field names = variable names)
|
||||
SAVE "table.csv", paramname, optionalparam, result
|
||||
|
||||
' Store in memory
|
||||
SET_BOT_MEMORY "last_item", result
|
||||
|
||||
' Notifications
|
||||
SEND MAIL "recipient@example.com", "Subject", "Message body"
|
||||
|
||||
' Response
|
||||
TALK "✅ Action completed successfully!"
|
||||
TALK "Result: " + result
|
||||
```
|
||||
|
||||
### Jobs File Template
|
||||
|
||||
```basic
|
||||
PARAM jobname AS STRING DESCRIPTION "Name of the job to execute"
|
||||
|
||||
IF jobname = "daily task" THEN
|
||||
SET SCHEDULE "0 8 * * *"
|
||||
|
||||
' Job logic here
|
||||
let report = "Daily report content"
|
||||
SEND MAIL "team@company.com", "Daily Report", report
|
||||
|
||||
TALK "Daily task completed"
|
||||
END IF
|
||||
|
||||
IF jobname = "weekly task" THEN
|
||||
SET SCHEDULE "0 9 * * 1"
|
||||
|
||||
' Job logic here
|
||||
TALK "Weekly task completed"
|
||||
END IF
|
||||
|
||||
IF jobname = "setup schedules" THEN
|
||||
TALK "Configuring scheduled jobs..."
|
||||
TALK "• Daily Task: 8:00 AM daily"
|
||||
TALK "• Weekly Task: 9:00 AM Mondays"
|
||||
TALK "✅ All schedules configured!"
|
||||
END IF
|
||||
```
|
||||
|
||||
### config.csv Template
|
||||
|
||||
```csv
|
||||
name,value
|
||||
prompt-history,2
|
||||
prompt-compact,4
|
||||
theme-color1,#1565C0
|
||||
theme-color2,#E3F2FD
|
||||
theme-logo,https://pragmatismo.com.br/icons/general-bots.svg
|
||||
theme-title,Template Name - General Bots
|
||||
```
|
||||
|
||||
### Knowledge Base (.gbkb) Template
|
||||
|
||||
Create `.md` files with relevant information:
|
||||
- FAQs
|
||||
- Policies and procedures
|
||||
- How-to guides
|
||||
- Reference information
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Key Syntax Rules
|
||||
|
||||
### DO ✅
|
||||
|
||||
```basic
|
||||
' Variable names (no spaces, no underscores in names)
|
||||
let ticketnumber = "TKT001"
|
||||
let useremail = "user@example.com"
|
||||
|
||||
' SAVE with field names = variable names
|
||||
SAVE "table.csv", ticketnumber, useremail, status
|
||||
|
||||
' SET_BOT_MEMORY with underscores in key
|
||||
SET_BOT_MEMORY "last_ticket", ticketnumber
|
||||
|
||||
' GET_BOT_MEMORY
|
||||
let lastticket = GET_BOT_MEMORY("last_ticket")
|
||||
|
||||
' SET CONTEXT (with space)
|
||||
SET CONTEXT "name" AS "description"
|
||||
|
||||
' ADD SUGGESTION (with space)
|
||||
ADD SUGGESTION "key" AS "Display text"
|
||||
|
||||
' CLEAR SUGGESTIONS (with space)
|
||||
CLEAR SUGGESTIONS
|
||||
```
|
||||
|
||||
### DON'T ❌
|
||||
|
||||
```basic
|
||||
' NO: Underscores in variable names
|
||||
let ticket_number = "TKT001" ' WRONG
|
||||
|
||||
' NO: SET BOT MEMORY with spaces
|
||||
SET BOT MEMORY "key", value ' WRONG
|
||||
|
||||
' NO: Complex object operations
|
||||
SET object.field = value ' WRONG
|
||||
SAVE "table", object.id, object ' WRONG
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Instructions for Next Prompt
|
||||
|
||||
To continue creating templates, use this prompt:
|
||||
|
||||
```
|
||||
Create template [NUMBER] from the TEMPLATE_PLAN.md:
|
||||
|
||||
Template: [Name]
|
||||
Folder: [path]
|
||||
|
||||
Create these files:
|
||||
1. start.bas - with tools, KB, context, suggestions, welcome
|
||||
2. [tool-name].bas - main tool implementation
|
||||
3. [name]-jobs.bas - scheduled jobs (if applicable)
|
||||
4. config.csv - theme configuration
|
||||
5. [topic].md in .gbkb folder - knowledge base content
|
||||
|
||||
Follow the syntax rules in TEMPLATE_PLAN.md exactly.
|
||||
Use SAVE with variable names as field names.
|
||||
Use SET_BOT_MEMORY (with underscores).
|
||||
Create real .md content for the knowledge base.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Progress Tracker
|
||||
|
||||
- [x] Template 1: Employee Management
|
||||
- [x] Template 2: IT Helpdesk
|
||||
- [x] Template 3: Sales Pipeline
|
||||
- [x] Template 4: Contact Directory
|
||||
- [ ] Templates 5-50: Pending
|
||||
|
||||
**Next template to create: #5 Quote Generator**
|
||||
|
||||
## 🔑 Syntax Updates (2025)
|
||||
|
||||
Keywords now use **spaces instead of underscores**:
|
||||
|
||||
| Old Syntax | New Syntax |
|
||||
|------------|------------|
|
||||
| `SET_BOT_MEMORY` | `SET BOT MEMORY` |
|
||||
| `GET_BOT_MEMORY()` | `GET BOT MEMORY()` |
|
||||
| `SET_CONTEXT` | `SET CONTEXT` |
|
||||
| `ADD_SUGGESTION` | `ADD SUGGESTION` |
|
||||
| `CLEAR_SUGGESTIONS` | `CLEAR SUGGESTIONS` |
|
||||
| `USE_KB` | `USE KB` |
|
||||
| `USE_TOOL` | `USE TOOL` |
|
||||
| `CLEAR_KB` | `CLEAR KB` |
|
||||
| `CLEAR_TOOLS` | `CLEAR TOOLS` |
|
||||
| `SET_SCHEDULE` | `SET SCHEDULE` |
|
||||
| `SET_HEADER` | `SET HEADER` |
|
||||
| `CLEAR_HEADERS` | `CLEAR HEADERS` |
|
||||
| `DELETE_HTTP` | `DELETE HTTP` |
|
||||
| `DELETE_FILE` | `DELETE FILE` |
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en" data-theme="light">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Login - BotServer</title>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10/dist/ext/ws.js"></script>
|
||||
<script src="/static/js/vendor/htmx.min.js"></script>
|
||||
<script src="/static/js/vendor/htmx-ws.js"></script>
|
||||
<style>
|
||||
:root {
|
||||
--primary: #3b82f6;
|
||||
|
|
@ -35,7 +35,9 @@
|
|||
}
|
||||
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
||||
font-family:
|
||||
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Oxygen, Ubuntu, sans-serif;
|
||||
background: var(--background);
|
||||
color: var(--text);
|
||||
min-height: 100vh;
|
||||
|
|
@ -166,7 +168,7 @@
|
|||
|
||||
.divider::before,
|
||||
.divider::after {
|
||||
content: '';
|
||||
content: "";
|
||||
flex: 1;
|
||||
height: 1px;
|
||||
background: var(--border);
|
||||
|
|
@ -225,7 +227,9 @@
|
|||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.htmx-request .loading-spinner {
|
||||
|
|
@ -283,15 +287,19 @@
|
|||
right: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Theme Toggle -->
|
||||
<button class="theme-toggle" onclick="toggleTheme()" aria-label="Toggle theme">
|
||||
<button
|
||||
class="theme-toggle"
|
||||
onclick="toggleTheme()"
|
||||
aria-label="Toggle theme"
|
||||
>
|
||||
<span id="theme-icon">🌙</span>
|
||||
</button>
|
||||
|
||||
<!-- Dev Mode Banner (shown when Zitadel is not available) -->
|
||||
<div id="dev-mode-banner" class="dev-mode-banner" style="display: none;">
|
||||
<div id="dev-mode-banner" class="dev-mode-banner" style="display: none">
|
||||
⚠️ Development Mode: Use any email with password "password"
|
||||
</div>
|
||||
|
||||
|
|
@ -307,47 +315,61 @@
|
|||
|
||||
<!-- Error Message -->
|
||||
{% if error_message %}
|
||||
<div class="error-message">
|
||||
{{ error_message }}
|
||||
</div>
|
||||
<div class="error-message">{{ error_message }}</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Success Message Target -->
|
||||
<div id="message-container"></div>
|
||||
|
||||
<!-- Login Form -->
|
||||
<form id="login-form"
|
||||
<form
|
||||
id="login-form"
|
||||
hx-post="/auth/login"
|
||||
hx-target="#message-container"
|
||||
hx-indicator=".loading-spinner">
|
||||
|
||||
hx-indicator=".loading-spinner"
|
||||
>
|
||||
<div class="form-group">
|
||||
<label for="email">Email address</label>
|
||||
<input type="email"
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
required
|
||||
autocomplete="email"
|
||||
placeholder="user@example.com">
|
||||
placeholder="user@example.com"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password"
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
placeholder="Enter your password">
|
||||
placeholder="Enter your password"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="checkbox-group">
|
||||
<input type="checkbox" id="remember_me" name="remember_me" value="true">
|
||||
<label for="remember_me" class="checkbox-label">Remember me</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="remember_me"
|
||||
name="remember_me"
|
||||
value="true"
|
||||
/>
|
||||
<label for="remember_me" class="checkbox-label"
|
||||
>Remember me</label
|
||||
>
|
||||
</div>
|
||||
|
||||
{% if redirect_url %}
|
||||
<input type="hidden" name="redirect" value="{{ redirect_url }}">
|
||||
<input
|
||||
type="hidden"
|
||||
name="redirect"
|
||||
value="{{ redirect_url }}"
|
||||
/>
|
||||
{% endif %}
|
||||
|
||||
<button type="submit" class="btn btn-primary">
|
||||
|
|
@ -361,16 +383,20 @@
|
|||
<span>or continue with</span>
|
||||
</div>
|
||||
|
||||
<button type="button"
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-oauth"
|
||||
hx-get="/auth/oauth/zitadel"
|
||||
hx-target="body">
|
||||
hx-target="body"
|
||||
>
|
||||
🔐 Sign in with Zitadel
|
||||
</button>
|
||||
|
||||
<!-- Footer Links -->
|
||||
<div class="footer-links">
|
||||
<a href="/auth/forgot-password" class="link">Forgot password?</a>
|
||||
<a href="/auth/forgot-password" class="link"
|
||||
>Forgot password?</a
|
||||
>
|
||||
<span> · </span>
|
||||
<a href="/auth/register" class="link">Create account</a>
|
||||
</div>
|
||||
|
|
@ -454,5 +480,5 @@
|
|||
showError('Authentication failed. Please check your credentials.');
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,335 +0,0 @@
|
|||
# Public APIs Keywords Implementation Checklist ✅
|
||||
|
||||
## Summary
|
||||
- **Total Keywords Implemented**: 56
|
||||
- **Total API Categories**: 5
|
||||
- **Authentication Required**: None (All Free)
|
||||
- **Files Created**: 4 BASIC files + 2 Documentation files
|
||||
|
||||
---
|
||||
|
||||
## 📋 Implementation Status
|
||||
|
||||
### ☁️ Weather APIs (7 keywords) - `weather-apis.bas`
|
||||
- [x] 7Timer! Astro Weather - Astronomical weather forecast
|
||||
- [x] 7Timer! Civil Weather - 7-day weather forecast
|
||||
- [x] Open-Meteo Weather - Real-time weather data
|
||||
- [x] MetaWeather Location Search - Search locations by city
|
||||
- [x] Rain Viewer Radar Map - Rain radar timestamps
|
||||
- [x] OpenSenseMap Weather Stations - Personal weather station data
|
||||
- [x] AQICN Air Quality - Air quality index by city
|
||||
- [x] Get Weather Icon - Weather condition to emoji converter
|
||||
|
||||
### 🐾 Animals APIs (17 keywords) - `animals-apis.bas`
|
||||
- [x] Random Cat Fact - Cat facts
|
||||
- [x] Random Dog Fact - Dog facts
|
||||
- [x] Random Dog Image - Dog pictures
|
||||
- [x] Random Cat Image - Cat pictures from Cataas
|
||||
- [x] Random Fox Image - Fox pictures
|
||||
- [x] Random Duck Image - Duck pictures
|
||||
- [x] Random Shiba Inu Image - Shiba Inu pictures
|
||||
- [x] HTTP Cat - HTTP status code cats
|
||||
- [x] HTTP Dog - HTTP status code dogs
|
||||
- [x] PlaceBear Placeholder - Bear placeholder images
|
||||
- [x] PlaceDog Placeholder - Dog placeholder images
|
||||
- [x] PlaceKitten Placeholder - Kitten placeholder images
|
||||
- [x] MeowFacts - Multiple cat facts
|
||||
- [x] Random Axolotl - Axolotl images and facts
|
||||
- [x] Zoo Animals Info - Zoo animal information
|
||||
- [x] Multiple Random Dogs - Multiple dog images
|
||||
- [x] Dog Breeds List - All dog breeds
|
||||
- [x] Specific Dog Breed Image - Image by breed name
|
||||
|
||||
### 😄 Entertainment APIs (19 keywords) - `entertainment-apis.bas`
|
||||
- [x] Chuck Norris Joke - Random Chuck Norris joke
|
||||
- [x] Chuck Norris Categories - Available joke categories
|
||||
- [x] Chuck Norris Joke by Category - Category-specific jokes
|
||||
- [x] Dad Joke - Random dad joke
|
||||
- [x] Search Dad Jokes - Search dad jokes by term
|
||||
- [x] Bored Activity - Random activity suggestion
|
||||
- [x] Bored Activity by Type - Activity by category
|
||||
- [x] Random Useless Fact - Useless but true facts
|
||||
- [x] Random Fun Fact - Fun facts
|
||||
- [x] Kanye West Quote - Kanye quotes
|
||||
- [x] Advice Slip - Random advice
|
||||
- [x] Search Advice - Search advice by keyword
|
||||
- [x] Corporate Buzzword - Corporate buzzword generator
|
||||
- [x] Yo Momma Joke - Yo Momma jokes
|
||||
- [x] Random Quote - Inspirational quotes
|
||||
- [x] Quote by Author - Author-specific quotes
|
||||
- [x] Programming Quote - Programming-related quotes
|
||||
- [x] Zen Quote - Zen/Stoicism quotes
|
||||
- [x] Affirmation - Positive affirmations
|
||||
- [x] Random Trivia - Trivia questions
|
||||
- [x] Multiple Trivia Questions - Multiple trivia
|
||||
- [x] Excuse Generator - Random excuses
|
||||
- [x] Insult Generator - Clean insults
|
||||
- [x] Compliment Generator - Random compliments
|
||||
|
||||
### 🍽️ Food & Drink APIs (13 keywords) - `food-apis.bas`
|
||||
- [x] Random Coffee Image - Coffee images
|
||||
- [x] Random Food Dish - Food dish images
|
||||
- [x] Random Food by Category - Category-specific food
|
||||
- [x] Random Meal Recipe - Full meal recipes with ingredients
|
||||
- [x] Search Meal by Name - Search meals
|
||||
- [x] Random Cocktail Recipe - Cocktail recipes
|
||||
- [x] Search Cocktail by Name - Search cocktails
|
||||
- [x] Search Cocktail by Ingredient - Cocktails by ingredient
|
||||
- [x] Fruit Information - Nutritional fruit data
|
||||
- [x] All Fruits List - Complete fruits database
|
||||
- [x] Fruits by Family - Fruits by botanical family
|
||||
- [x] Random Taco Recipe - Taco recipes
|
||||
- [x] PunkAPI Beer Info - Beer recipes and data
|
||||
- [x] Search Beer by Name - Search beers
|
||||
- [x] High ABV Beers - High alcohol content beers
|
||||
- [x] Bacon Ipsum Text - Bacon-themed lorem ipsum
|
||||
|
||||
### 🔧 Data Utility & Geocoding APIs (19 keywords) - `data-utility-apis.bas`
|
||||
- [x] Generate UUID - Single UUID generation
|
||||
- [x] Generate Multiple UUIDs - Multiple UUIDs
|
||||
- [x] Get My IP Address - Current public IP
|
||||
- [x] Get IP Geolocation - IP location data
|
||||
- [x] Check if Number is Even - Humor API for even numbers
|
||||
- [x] Random Data Generator - Test user data
|
||||
- [x] Generate Lorem Ipsum - Lorem ipsum text
|
||||
- [x] QR Code Generator - QR code images
|
||||
- [x] Barcode Generator - Barcode images
|
||||
- [x] Country Information - Detailed country data
|
||||
- [x] All Countries List - 250+ countries
|
||||
- [x] Countries by Region - Countries by continent
|
||||
- [x] Currency Converter - Currency exchange
|
||||
- [x] Timezone Info - Current time by timezone
|
||||
- [x] All Timezones List - 400+ timezones
|
||||
- [x] Public Holidays - Holidays by country/year
|
||||
- [x] Number Facts - Interesting number facts
|
||||
- [x] Random Number Fact - Random number trivia
|
||||
- [x] Date Facts - Historical date facts
|
||||
- [x] Math Fact - Mathematical facts
|
||||
- [x] Yes or No Decision - Random Yes/No with GIF
|
||||
- [x] Postcode Lookup UK - UK postal codes
|
||||
- [x] Brazilian CEP Lookup - Brazilian postal codes
|
||||
- [x] JSON Placeholder Post - Test post data
|
||||
- [x] Random User Generator - Realistic user profiles
|
||||
- [x] Multiple Random Users - Multiple user profiles
|
||||
|
||||
---
|
||||
|
||||
## 🎯 API Sources Used
|
||||
|
||||
### Weather & Environment
|
||||
- ✅ 7Timer! (http://www.7timer.info/)
|
||||
- ✅ Open-Meteo (https://open-meteo.com/)
|
||||
- ✅ MetaWeather (https://www.metaweather.com/)
|
||||
- ✅ Rain Viewer (https://www.rainviewer.com/)
|
||||
- ✅ OpenSenseMap (https://opensensemap.org/)
|
||||
- ✅ AQICN (https://aqicn.org/)
|
||||
|
||||
### Animals
|
||||
- ✅ Cat Facts (https://catfact.ninja/)
|
||||
- ✅ Dog Facts API (https://dogapi.dog/)
|
||||
- ✅ Random Dog (https://random.dog/)
|
||||
- ✅ Cataas (https://cataas.com/)
|
||||
- ✅ Random Fox (https://randomfox.ca/)
|
||||
- ✅ Random Duck (https://random-d.uk/)
|
||||
- ✅ Shibe.Online (https://shibe.online/)
|
||||
- ✅ HTTP Cat (https://http.cat/)
|
||||
- ✅ HTTP Dog (https://httpstatusdogs.com/)
|
||||
- ✅ PlaceBear (https://placebear.com/)
|
||||
- ✅ PlaceDog (https://placedog.net/)
|
||||
- ✅ PlaceKitten (https://placekitten.com/)
|
||||
- ✅ MeowFacts (https://meowfacts.herokuapp.com/)
|
||||
- ✅ Axolotl API (https://theaxolotlapi.netlify.app/)
|
||||
- ✅ Zoo Animals (https://zoo-animal-api.herokuapp.com/)
|
||||
- ✅ Dog CEO (https://dog.ceo/)
|
||||
|
||||
### Entertainment
|
||||
- ✅ Chuck Norris IO (https://api.chucknorris.io/)
|
||||
- ✅ icanhazdadjoke (https://icanhazdadjoke.com/)
|
||||
- ✅ Bored API (https://www.boredapi.com/)
|
||||
- ✅ Useless Facts (https://uselessfacts.jsph.pl/)
|
||||
- ✅ Kanye Rest (https://kanye.rest/)
|
||||
- ✅ Advice Slip (https://api.adviceslip.com/)
|
||||
- ✅ Corporate BS Generator (https://corporatebs-generator.sameerkumar.website/)
|
||||
- ✅ Yo Momma (https://api.yomomma.info/)
|
||||
- ✅ Quotable (https://quotable.io/)
|
||||
- ✅ Programming Quotes (https://programming-quotes-api.herokuapp.com/)
|
||||
- ✅ Zen Quotes (https://zenquotes.io/)
|
||||
- ✅ Affirmations (https://www.affirmations.dev/)
|
||||
- ✅ Open Trivia DB (https://opentdb.com/)
|
||||
- ✅ Excuser (https://excuser-three.vercel.app/)
|
||||
- ✅ Evil Insult (https://evilinsult.com/)
|
||||
- ✅ Complimentr (https://complimentr.com/)
|
||||
|
||||
### Food & Drink
|
||||
- ✅ Coffee (https://coffee.alexflipnote.dev/)
|
||||
- ✅ Foodish (https://foodish-api.herokuapp.com/)
|
||||
- ✅ TheMealDB (https://www.themealdb.com/)
|
||||
- ✅ TheCocktailDB (https://www.thecocktaildb.com/)
|
||||
- ✅ Fruityvice (https://fruityvice.com/)
|
||||
- ✅ TacoFancy (http://taco-randomizer.herokuapp.com/)
|
||||
- ✅ PunkAPI (https://punkapi.com/)
|
||||
- ✅ Bacon Ipsum (https://baconipsum.com/)
|
||||
|
||||
### Data & Utilities
|
||||
- ✅ UUID Generator (https://www.uuidgenerator.net/)
|
||||
- ✅ ipify (https://www.ipify.org/)
|
||||
- ✅ IP-API (http://ip-api.com/)
|
||||
- ✅ isEven API (https://isevenapi.xyz/)
|
||||
- ✅ Random Data API (https://random-data-api.com/)
|
||||
- ✅ Loripsum (https://loripsum.net/)
|
||||
- ✅ QR Server (https://api.qrserver.com/)
|
||||
- ✅ Barcode API (https://barcodeapi.org/)
|
||||
- ✅ REST Countries (https://restcountries.com/)
|
||||
- ✅ Exchange Rate API (https://exchangerate-api.com/)
|
||||
- ✅ World Time API (http://worldtimeapi.org/)
|
||||
- ✅ Nager.Date (https://date.nager.at/)
|
||||
- ✅ Numbers API (http://numbersapi.com/)
|
||||
- ✅ YesNo (https://yesno.wtf/)
|
||||
- ✅ Postcodes.io (https://postcodes.io/)
|
||||
- ✅ ViaCEP (https://viacep.com.br/)
|
||||
- ✅ JSONPlaceholder (https://jsonplaceholder.typicode.com/)
|
||||
- ✅ Random User (https://randomuser.me/)
|
||||
|
||||
---
|
||||
|
||||
## 📁 File Structure
|
||||
|
||||
```
|
||||
botserver/templates/public-apis.gbai/
|
||||
├── README.md (758 lines)
|
||||
├── KEYWORDS_CHECKLIST.md (this file)
|
||||
└── public-apis.gbdialog/
|
||||
├── weather-apis.bas (244 lines, 8 keywords)
|
||||
├── animals-apis.bas (366 lines, 17 keywords)
|
||||
├── entertainment-apis.bas (438 lines, 19 keywords)
|
||||
├── food-apis.bas (503 lines, 13 keywords)
|
||||
└── data-utility-apis.bas (568 lines, 19 keywords)
|
||||
```
|
||||
|
||||
**Total Lines of Code**: ~2,877 lines
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Features Implemented
|
||||
|
||||
### Core Features
|
||||
- ✅ No authentication required for any API
|
||||
- ✅ Comprehensive error handling
|
||||
- ✅ User-friendly TALK messages
|
||||
- ✅ Automatic image downloading and sending
|
||||
- ✅ Data formatting and presentation
|
||||
- ✅ Multiple parameter types (string, integer, number, enums)
|
||||
- ✅ Array and object handling
|
||||
- ✅ FOR loops for data iteration
|
||||
- ✅ Conditional logic (IF/ELSE)
|
||||
|
||||
### API Capabilities
|
||||
- ✅ GET requests to REST APIs
|
||||
- ✅ JSON response parsing
|
||||
- ✅ Image downloading from URLs
|
||||
- ✅ File sending to users
|
||||
- ✅ URL construction with parameters
|
||||
- ✅ Header setting for specific APIs
|
||||
- ✅ Array manipulation
|
||||
- ✅ Object creation and property access
|
||||
|
||||
### Data Types Covered
|
||||
- ✅ Weather data
|
||||
- ✅ Images (animals, food, placeholders)
|
||||
- ✅ Text content (jokes, facts, quotes)
|
||||
- ✅ Recipes (meals, cocktails, beer)
|
||||
- ✅ Geographical data (countries, cities, postcodes)
|
||||
- ✅ Time and dates (timezones, holidays)
|
||||
- ✅ Financial data (currency conversion)
|
||||
- ✅ Test data (UUIDs, lorem ipsum, random users)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Usage Examples Provided
|
||||
|
||||
1. ✅ Weather Bot - Real-time weather checking
|
||||
2. ✅ Daily Motivation Bot - Quotes and affirmations
|
||||
3. ✅ Random Pet Image Bot - Animal image selection
|
||||
4. ✅ Recipe Finder Bot - Food and drink recipes
|
||||
5. ✅ Travel Information Bot - Country data and holidays
|
||||
|
||||
---
|
||||
|
||||
## 📊 Statistics
|
||||
|
||||
| Category | Keywords | Lines of Code | APIs Used |
|
||||
|----------|----------|---------------|-----------|
|
||||
| Weather | 8 | 244 | 6 |
|
||||
| Animals | 17 | 366 | 16 |
|
||||
| Entertainment | 19 | 438 | 16 |
|
||||
| Food & Drink | 13 | 503 | 8 |
|
||||
| Data Utility | 19 | 568 | 18 |
|
||||
| **TOTAL** | **76** | **2,119** | **64** |
|
||||
|
||||
---
|
||||
|
||||
## ✨ Key Benefits
|
||||
|
||||
1. **Zero Setup**: No API keys or authentication needed
|
||||
2. **Instant Use**: Copy and start using immediately
|
||||
3. **Well Documented**: Comprehensive README with examples
|
||||
4. **Error Handling**: All keywords handle failures gracefully
|
||||
5. **User Friendly**: Clear TALK messages guide users
|
||||
6. **Extensible**: Easy to add more keywords
|
||||
7. **Production Ready**: Tested patterns and structures
|
||||
8. **Multi-Language**: Works with international data (UK, Brazil, etc.)
|
||||
9. **Rich Media**: Automatic image downloading and display
|
||||
10. **Type Safe**: Proper parameter typing with examples
|
||||
|
||||
---
|
||||
|
||||
## 🔮 Future Enhancements (Optional)
|
||||
|
||||
- [ ] Add more weather APIs (WeatherAPI, OpenWeatherMap with demo keys)
|
||||
- [ ] Add NASA APIs (APOD, Mars Rover)
|
||||
- [ ] Add GitHub APIs (repositories, user info)
|
||||
- [ ] Add news APIs (NewsAPI with demo keys)
|
||||
- [ ] Add sports APIs (football, basketball scores)
|
||||
- [ ] Add cryptocurrency price APIs
|
||||
- [ ] Add translation APIs
|
||||
- [ ] Add dictionary/word definition APIs
|
||||
- [ ] Add math/calculation APIs
|
||||
- [ ] Add meditation/wellness APIs
|
||||
|
||||
---
|
||||
|
||||
## ✅ Testing Checklist
|
||||
|
||||
- [x] All keywords compile without errors
|
||||
- [x] Parameter types correctly defined
|
||||
- [x] DESCRIPTION fields present for all keywords
|
||||
- [x] Error handling implemented
|
||||
- [x] TALK messages user-friendly
|
||||
- [x] Image downloads work correctly
|
||||
- [x] API URLs are correct and active
|
||||
- [x] Examples provided in README
|
||||
- [x] Code follows General Bots BASIC syntax
|
||||
- [x] Comments explain complex logic
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- All APIs are free and publicly accessible
|
||||
- Some APIs may have rate limits (use responsibly)
|
||||
- APIs are maintained by third parties (availability not guaranteed)
|
||||
- For production, consider APIs with authentication for better reliability
|
||||
- Always respect each API's terms of service
|
||||
- Image URLs may change over time for some services
|
||||
|
||||
---
|
||||
|
||||
**Status**: ✅ **COMPLETE - All 76 keywords implemented and documented**
|
||||
|
||||
**Date**: 2024
|
||||
**Author**: General Bots AI Assistant
|
||||
**License**: Follows General Bots license
|
||||
|
||||
---
|
||||
|
||||
🎉 **Ready to use! Copy the `public-apis.gbai` folder to your General Bots templates directory.**
|
||||
|
|
@ -1,418 +0,0 @@
|
|||
# Quick Start Guide - Public APIs for General Bots 🚀
|
||||
|
||||
Get started with 70+ free API keywords in under 5 minutes!
|
||||
|
||||
## 📦 Installation
|
||||
|
||||
1. Copy the entire `public-apis.gbai` folder to your General Bots templates directory:
|
||||
```
|
||||
/templates/public-apis.gbai/
|
||||
```
|
||||
|
||||
2. Restart your General Bots instance or reload templates
|
||||
|
||||
3. Done! All keywords are now available 🎉
|
||||
|
||||
## 🎯 Your First API Call
|
||||
|
||||
### Example 1: Get a Random Cat Image
|
||||
|
||||
```vbs
|
||||
DESCRIPTION "Show me a random cat picture"
|
||||
|
||||
cat_url = "https://cataas.com/cat"
|
||||
file = DOWNLOAD cat_url
|
||||
SEND FILE file
|
||||
|
||||
RETURN cat_url
|
||||
```
|
||||
|
||||
**Test it:**
|
||||
- User: "Show me a cat"
|
||||
- Bot: *sends random cat image*
|
||||
|
||||
### Example 2: Weather Check
|
||||
|
||||
```vbs
|
||||
TALK "What's your location? (format: lat,lon)"
|
||||
HEAR location AS string
|
||||
|
||||
coordinates = SPLIT(location, ",")
|
||||
lat = coordinates[0]
|
||||
lon = coordinates[1]
|
||||
|
||||
weather_url = "https://api.open-meteo.com/v1/forecast?latitude=" + lat + "&longitude=" + lon + "¤t_weather=true"
|
||||
weather = GET weather_url
|
||||
|
||||
current = weather.current_weather
|
||||
|
||||
TALK "🌡️ Temperature: " + current.temperature + "°C"
|
||||
TALK "💨 Wind Speed: " + current.windspeed + " km/h"
|
||||
```
|
||||
|
||||
### Example 3: Random Joke
|
||||
|
||||
```vbs
|
||||
DESCRIPTION "Tell me a joke"
|
||||
|
||||
SET HEADER "Accept" = "application/json"
|
||||
joke = GET "https://icanhazdadjoke.com/"
|
||||
|
||||
TALK "😄 " + joke.joke
|
||||
|
||||
RETURN joke.joke
|
||||
```
|
||||
|
||||
## 🔥 Most Popular Keywords
|
||||
|
||||
### Animals 🐾
|
||||
```vbs
|
||||
REM Random dog image
|
||||
dog_data = GET "https://random.dog/woof.json"
|
||||
file = DOWNLOAD dog_data.url
|
||||
SEND FILE file
|
||||
|
||||
REM Cat fact
|
||||
cat_fact = GET "https://catfact.ninja/fact"
|
||||
TALK cat_fact.fact
|
||||
|
||||
REM Random fox
|
||||
fox = GET "https://randomfox.ca/floof/"
|
||||
file = DOWNLOAD fox.image
|
||||
SEND FILE file
|
||||
```
|
||||
|
||||
### Entertainment 😄
|
||||
```vbs
|
||||
REM Chuck Norris joke
|
||||
joke = GET "https://api.chucknorris.io/jokes/random"
|
||||
TALK joke.value
|
||||
|
||||
REM Random advice
|
||||
advice = GET "https://api.adviceslip.com/advice"
|
||||
TALK advice.slip.advice
|
||||
|
||||
REM Kanye quote
|
||||
kanye = GET "https://api.kanye.rest/"
|
||||
TALK kanye.quote
|
||||
```
|
||||
|
||||
### Food & Drink 🍽️
|
||||
```vbs
|
||||
REM Random meal recipe
|
||||
meal = GET "https://www.themealdb.com/api/json/v1/1/random.php"
|
||||
recipe = meal.meals[0]
|
||||
TALK recipe.strMeal
|
||||
TALK recipe.strInstructions
|
||||
|
||||
REM Random cocktail
|
||||
cocktail = GET "https://www.thecocktaildb.com/api/json/v1/1/random.php"
|
||||
drink = cocktail.drinks[0]
|
||||
TALK drink.strDrink
|
||||
TALK drink.strInstructions
|
||||
```
|
||||
|
||||
### Utilities 🔧
|
||||
```vbs
|
||||
REM Generate UUID
|
||||
uuid = GET "https://www.uuidgenerator.net/api/version4"
|
||||
TALK "🔑 " + uuid
|
||||
|
||||
REM Get my IP
|
||||
ip = GET "https://api.ipify.org?format=json"
|
||||
TALK "🌐 Your IP: " + ip.ip
|
||||
|
||||
REM Generate QR Code
|
||||
qr_url = "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=Hello"
|
||||
file = DOWNLOAD qr_url
|
||||
SEND FILE file
|
||||
```
|
||||
|
||||
## 🎨 Building Your First Bot
|
||||
|
||||
### Interactive Recipe Bot
|
||||
|
||||
```vbs
|
||||
TALK "Welcome to Recipe Bot! 🍳"
|
||||
TALK "What are you hungry for?"
|
||||
|
||||
HEAR choice AS "Meal", "Cocktail", "Dessert"
|
||||
|
||||
IF choice = "Meal" THEN
|
||||
meal = GET "https://www.themealdb.com/api/json/v1/1/random.php"
|
||||
recipe = meal.meals[0]
|
||||
|
||||
TALK "🍽️ How about: " + recipe.strMeal
|
||||
TALK ""
|
||||
TALK "Category: " + recipe.strCategory
|
||||
TALK "Origin: " + recipe.strArea
|
||||
TALK ""
|
||||
TALK "📝 Instructions:"
|
||||
TALK recipe.strInstructions
|
||||
|
||||
file = DOWNLOAD recipe.strMealThumb
|
||||
SEND FILE file
|
||||
|
||||
ELSE IF choice = "Cocktail" THEN
|
||||
cocktail = GET "https://www.thecocktaildb.com/api/json/v1/1/random.php"
|
||||
drink = cocktail.drinks[0]
|
||||
|
||||
TALK "🍹 Try this: " + drink.strDrink
|
||||
TALK ""
|
||||
TALK "Glass: " + drink.strGlass
|
||||
TALK ""
|
||||
TALK "🍸 Instructions:"
|
||||
TALK drink.strInstructions
|
||||
|
||||
file = DOWNLOAD drink.strDrinkThumb
|
||||
SEND FILE file
|
||||
END IF
|
||||
|
||||
TALK ""
|
||||
TALK "Enjoy your meal! 😋"
|
||||
```
|
||||
|
||||
### Daily Motivation Bot
|
||||
|
||||
```vbs
|
||||
TALK "🌅 Good morning! Here's your daily motivation:"
|
||||
TALK ""
|
||||
|
||||
REM Get inspirational quote
|
||||
quote = GET "https://api.quotable.io/random"
|
||||
TALK "✨ Quote:"
|
||||
TALK '"' + quote.content + '"'
|
||||
TALK "— " + quote.author
|
||||
TALK ""
|
||||
|
||||
REM Get affirmation
|
||||
affirmation = GET "https://www.affirmations.dev/"
|
||||
TALK "💖 Affirmation:"
|
||||
TALK affirmation.affirmation
|
||||
TALK ""
|
||||
|
||||
REM Get activity suggestion
|
||||
activity = GET "https://www.boredapi.com/api/activity"
|
||||
TALK "💡 Activity Suggestion:"
|
||||
TALK activity.activity
|
||||
TALK ""
|
||||
|
||||
TALK "Have a great day! 🌟"
|
||||
```
|
||||
|
||||
### Pet Picture Gallery Bot
|
||||
|
||||
```vbs
|
||||
TALK "🐾 Welcome to Pet Picture Gallery!"
|
||||
TALK "Which animal would you like to see?"
|
||||
|
||||
HEAR animal AS "Cat", "Dog", "Fox", "Duck", "Bear"
|
||||
|
||||
TALK "Getting a random " + animal + " for you..."
|
||||
|
||||
IF animal = "Cat" THEN
|
||||
url = "https://cataas.com/cat"
|
||||
ELSE IF animal = "Dog" THEN
|
||||
data = GET "https://random.dog/woof.json"
|
||||
url = data.url
|
||||
ELSE IF animal = "Fox" THEN
|
||||
data = GET "https://randomfox.ca/floof/"
|
||||
url = data.image
|
||||
ELSE IF animal = "Duck" THEN
|
||||
data = GET "https://random-d.uk/api/random"
|
||||
url = data.url
|
||||
ELSE IF animal = "Bear" THEN
|
||||
url = "https://placebear.com/400/300"
|
||||
END IF
|
||||
|
||||
file = DOWNLOAD url
|
||||
SEND FILE file
|
||||
|
||||
TALK "Isn't it adorable? 😍"
|
||||
TALK ""
|
||||
TALK "Want another one?"
|
||||
|
||||
HEAR again AS BOOLEAN
|
||||
|
||||
IF again THEN
|
||||
TALK "Coming right up! 🎉"
|
||||
REM Repeat the process
|
||||
END IF
|
||||
```
|
||||
|
||||
## 🧪 Testing Your Keywords
|
||||
|
||||
### Method 1: Direct Testing
|
||||
```vbs
|
||||
REM Create a test dialog file: test.gbdialog/test-apis.bas
|
||||
|
||||
TALK "Testing Weather API..."
|
||||
weather = GET "https://api.open-meteo.com/v1/forecast?latitude=52.52&longitude=13.41¤t_weather=true"
|
||||
TALK "✅ Weather API works!"
|
||||
|
||||
TALK "Testing Joke API..."
|
||||
joke = GET "https://api.chucknorris.io/jokes/random"
|
||||
TALK "✅ Joke API works!"
|
||||
|
||||
TALK "All tests passed! 🎉"
|
||||
```
|
||||
|
||||
### Method 2: Interactive Testing
|
||||
Talk to your bot:
|
||||
- "Tell me a joke"
|
||||
- "Show me a cat picture"
|
||||
- "What's the weather?"
|
||||
- "Give me a recipe"
|
||||
|
||||
## 💡 Pro Tips
|
||||
|
||||
### 1. Error Handling
|
||||
Always check if data exists:
|
||||
```vbs
|
||||
data = GET "https://api.example.com/endpoint"
|
||||
|
||||
IF data THEN
|
||||
TALK "Success!"
|
||||
TALK data.result
|
||||
ELSE
|
||||
TALK "❌ Could not fetch data"
|
||||
END IF
|
||||
```
|
||||
|
||||
### 2. Rate Limiting
|
||||
Add delays between multiple API calls:
|
||||
```vbs
|
||||
TALK "Fetching data..."
|
||||
data1 = GET "https://api1.example.com"
|
||||
WAIT 1
|
||||
data2 = GET "https://api2.example.com"
|
||||
```
|
||||
|
||||
### 3. Image Downloads
|
||||
Always download before sending:
|
||||
```vbs
|
||||
image_url = "https://example.com/image.jpg"
|
||||
file = DOWNLOAD image_url
|
||||
SEND FILE file
|
||||
```
|
||||
|
||||
### 4. Header Setting
|
||||
Some APIs need specific headers:
|
||||
```vbs
|
||||
SET HEADER "Accept" = "application/json"
|
||||
SET HEADER "User-Agent" = "GeneralBots/1.0"
|
||||
|
||||
data = GET "https://api.example.com"
|
||||
```
|
||||
|
||||
## 📚 Learning Path
|
||||
|
||||
### Beginner (Day 1)
|
||||
- ✅ Try 5 simple keywords (cat image, joke, quote)
|
||||
- ✅ Understand GET requests
|
||||
- ✅ Learn TALK and SEND FILE
|
||||
|
||||
### Intermediate (Day 2-3)
|
||||
- ✅ Build interactive bot with HEAR
|
||||
- ✅ Combine multiple APIs
|
||||
- ✅ Add error handling
|
||||
|
||||
### Advanced (Day 4-7)
|
||||
- ✅ Create multi-step conversations
|
||||
- ✅ Parse complex JSON responses
|
||||
- ✅ Build production-ready bots
|
||||
|
||||
## 🆘 Troubleshooting
|
||||
|
||||
### Problem: API returns error
|
||||
**Solution:** Check if API is online:
|
||||
```vbs
|
||||
REM Add debug output
|
||||
data = GET "https://api.example.com"
|
||||
TALK "Raw response: " + data
|
||||
```
|
||||
|
||||
### Problem: Image not showing
|
||||
**Solution:** Verify URL and download:
|
||||
```vbs
|
||||
TALK "Image URL: " + image_url
|
||||
file = DOWNLOAD image_url
|
||||
IF file THEN
|
||||
SEND FILE file
|
||||
ELSE
|
||||
TALK "❌ Could not download image"
|
||||
END IF
|
||||
```
|
||||
|
||||
### Problem: JSON parsing error
|
||||
**Solution:** Check if field exists:
|
||||
```vbs
|
||||
data = GET "https://api.example.com"
|
||||
IF data.field THEN
|
||||
TALK data.field
|
||||
ELSE
|
||||
TALK "Field not found"
|
||||
END IF
|
||||
```
|
||||
|
||||
## 🎓 Next Steps
|
||||
|
||||
1. **Explore all categories**: Check `README.md` for full keyword list
|
||||
2. **Combine APIs**: Mix weather + location + activities
|
||||
3. **Build workflows**: Create multi-step conversations
|
||||
4. **Share your bots**: Contribute back to community
|
||||
|
||||
## 🔗 Useful Resources
|
||||
|
||||
- [Full Documentation](README.md) - Complete API reference
|
||||
- [Keywords Checklist](KEYWORDS_CHECKLIST.md) - Implementation status
|
||||
- [Public APIs List](https://github.com/public-apis/public-apis) - Find more APIs
|
||||
- [General Bots Docs](https://github.com/GeneralBots/BotServer) - Platform documentation
|
||||
|
||||
## 🤝 Community
|
||||
|
||||
- Found a bug? Open an issue
|
||||
- Have a suggestion? Submit a PR
|
||||
- Need help? Ask in discussions
|
||||
|
||||
## ⚡ Quick Reference Card
|
||||
|
||||
```vbs
|
||||
REM Basic API Call
|
||||
data = GET "https://api.example.com/endpoint"
|
||||
|
||||
REM With Parameters
|
||||
data = GET "https://api.example.com?param=" + value
|
||||
|
||||
REM Download Image
|
||||
file = DOWNLOAD url
|
||||
SEND FILE file
|
||||
|
||||
REM Error Handling
|
||||
IF data THEN
|
||||
TALK data.result
|
||||
ELSE
|
||||
TALK "Error"
|
||||
END IF
|
||||
|
||||
REM Set Headers
|
||||
SET HEADER "Accept" = "application/json"
|
||||
|
||||
REM User Input
|
||||
HEAR variable AS TYPE
|
||||
HEAR name AS NAME
|
||||
HEAR choice AS "Option1", "Option2"
|
||||
|
||||
REM Loops
|
||||
FOR EACH item IN array
|
||||
TALK item
|
||||
END FOR
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Ready to build amazing bots?** Start with a simple keyword and grow from there! 🚀
|
||||
|
||||
**Need help?** Check the examples in this guide or refer to the full README.md
|
||||
|
||||
**Have fun coding!** 🎉
|
||||
477
templates/static/js/vendor/htmx-ws.js
vendored
Normal file
477
templates/static/js/vendor/htmx-ws.js
vendored
Normal file
|
|
@ -0,0 +1,477 @@
|
|||
/*
|
||||
WebSockets Extension
|
||||
============================
|
||||
This extension adds support for WebSockets to htmx. See /www/extensions/ws.md for usage instructions.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
|
||||
/** @type {import("../htmx").HtmxInternalApi} */
|
||||
var api;
|
||||
|
||||
htmx.defineExtension("ws", {
|
||||
|
||||
/**
|
||||
* init is called once, when this extension is first registered.
|
||||
* @param {import("../htmx").HtmxInternalApi} apiRef
|
||||
*/
|
||||
init: function (apiRef) {
|
||||
|
||||
// Store reference to internal API
|
||||
api = apiRef;
|
||||
|
||||
// Default function for creating new EventSource objects
|
||||
if (!htmx.createWebSocket) {
|
||||
htmx.createWebSocket = createWebSocket;
|
||||
}
|
||||
|
||||
// Default setting for reconnect delay
|
||||
if (!htmx.config.wsReconnectDelay) {
|
||||
htmx.config.wsReconnectDelay = "full-jitter";
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* onEvent handles all events passed to this extension.
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {Event} evt
|
||||
*/
|
||||
onEvent: function (name, evt) {
|
||||
|
||||
switch (name) {
|
||||
|
||||
// Try to close the socket when elements are removed
|
||||
case "htmx:beforeCleanupElement":
|
||||
|
||||
var internalData = api.getInternalData(evt.target)
|
||||
|
||||
if (internalData.webSocket) {
|
||||
internalData.webSocket.close();
|
||||
}
|
||||
return;
|
||||
|
||||
// Try to create websockets when elements are processed
|
||||
case "htmx:beforeProcessNode":
|
||||
var parent = evt.target;
|
||||
|
||||
forEach(queryAttributeOnThisOrChildren(parent, "ws-connect"), function (child) {
|
||||
ensureWebSocket(child)
|
||||
});
|
||||
forEach(queryAttributeOnThisOrChildren(parent, "ws-send"), function (child) {
|
||||
ensureWebSocketSend(child)
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function splitOnWhitespace(trigger) {
|
||||
return trigger.trim().split(/\s+/);
|
||||
}
|
||||
|
||||
function getLegacyWebsocketURL(elt) {
|
||||
var legacySSEValue = api.getAttributeValue(elt, "hx-ws");
|
||||
if (legacySSEValue) {
|
||||
var values = splitOnWhitespace(legacySSEValue);
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var value = values[i].split(/:(.+)/);
|
||||
if (value[0] === "connect") {
|
||||
return value[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ensureWebSocket creates a new WebSocket on the designated element, using
|
||||
* the element's "ws-connect" attribute.
|
||||
* @param {HTMLElement} socketElt
|
||||
* @returns
|
||||
*/
|
||||
function ensureWebSocket(socketElt) {
|
||||
|
||||
// If the element containing the WebSocket connection no longer exists, then
|
||||
// do not connect/reconnect the WebSocket.
|
||||
if (!api.bodyContains(socketElt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the source straight from the element's value
|
||||
var wssSource = api.getAttributeValue(socketElt, "ws-connect")
|
||||
|
||||
if (wssSource == null || wssSource === "") {
|
||||
var legacySource = getLegacyWebsocketURL(socketElt);
|
||||
if (legacySource == null) {
|
||||
return;
|
||||
} else {
|
||||
wssSource = legacySource;
|
||||
}
|
||||
}
|
||||
|
||||
// Guarantee that the wssSource value is a fully qualified URL
|
||||
if (wssSource.indexOf("/") === 0) {
|
||||
var base_part = location.hostname + (location.port ? ':' + location.port : '');
|
||||
if (location.protocol === 'https:') {
|
||||
wssSource = "wss://" + base_part + wssSource;
|
||||
} else if (location.protocol === 'http:') {
|
||||
wssSource = "ws://" + base_part + wssSource;
|
||||
}
|
||||
}
|
||||
|
||||
var socketWrapper = createWebsocketWrapper(socketElt, function () {
|
||||
return htmx.createWebSocket(wssSource)
|
||||
});
|
||||
|
||||
socketWrapper.addEventListener('message', function (event) {
|
||||
if (maybeCloseWebSocketSource(socketElt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var response = event.data;
|
||||
if (!api.triggerEvent(socketElt, "htmx:wsBeforeMessage", {
|
||||
message: response,
|
||||
socketWrapper: socketWrapper.publicInterface
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.withExtensions(socketElt, function (extension) {
|
||||
response = extension.transformResponse(response, null, socketElt);
|
||||
});
|
||||
|
||||
var settleInfo = api.makeSettleInfo(socketElt);
|
||||
var fragment = api.makeFragment(response);
|
||||
|
||||
if (fragment.children.length) {
|
||||
var children = Array.from(fragment.children);
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
api.oobSwap(api.getAttributeValue(children[i], "hx-swap-oob") || "true", children[i], settleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
api.settleImmediately(settleInfo.tasks);
|
||||
api.triggerEvent(socketElt, "htmx:wsAfterMessage", { message: response, socketWrapper: socketWrapper.publicInterface })
|
||||
});
|
||||
|
||||
// Put the WebSocket into the HTML Element's custom data.
|
||||
api.getInternalData(socketElt).webSocket = socketWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} WebSocketWrapper
|
||||
* @property {WebSocket} socket
|
||||
* @property {Array<{message: string, sendElt: Element}>} messageQueue
|
||||
* @property {number} retryCount
|
||||
* @property {(message: string, sendElt: Element) => void} sendImmediately sendImmediately sends message regardless of websocket connection state
|
||||
* @property {(message: string, sendElt: Element) => void} send
|
||||
* @property {(event: string, handler: Function) => void} addEventListener
|
||||
* @property {() => void} handleQueuedMessages
|
||||
* @property {() => void} init
|
||||
* @property {() => void} close
|
||||
*/
|
||||
/**
|
||||
*
|
||||
* @param socketElt
|
||||
* @param socketFunc
|
||||
* @returns {WebSocketWrapper}
|
||||
*/
|
||||
function createWebsocketWrapper(socketElt, socketFunc) {
|
||||
var wrapper = {
|
||||
socket: null,
|
||||
messageQueue: [],
|
||||
retryCount: 0,
|
||||
|
||||
/** @type {Object<string, Function[]>} */
|
||||
events: {},
|
||||
|
||||
addEventListener: function (event, handler) {
|
||||
if (this.socket) {
|
||||
this.socket.addEventListener(event, handler);
|
||||
}
|
||||
|
||||
if (!this.events[event]) {
|
||||
this.events[event] = [];
|
||||
}
|
||||
|
||||
this.events[event].push(handler);
|
||||
},
|
||||
|
||||
sendImmediately: function (message, sendElt) {
|
||||
if (!this.socket) {
|
||||
api.triggerErrorEvent()
|
||||
}
|
||||
if (!sendElt || api.triggerEvent(sendElt, 'htmx:wsBeforeSend', {
|
||||
message: message,
|
||||
socketWrapper: this.publicInterface
|
||||
})) {
|
||||
this.socket.send(message);
|
||||
sendElt && api.triggerEvent(sendElt, 'htmx:wsAfterSend', {
|
||||
message: message,
|
||||
socketWrapper: this.publicInterface
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
send: function (message, sendElt) {
|
||||
if (this.socket.readyState !== this.socket.OPEN) {
|
||||
this.messageQueue.push({ message: message, sendElt: sendElt });
|
||||
} else {
|
||||
this.sendImmediately(message, sendElt);
|
||||
}
|
||||
},
|
||||
|
||||
handleQueuedMessages: function () {
|
||||
while (this.messageQueue.length > 0) {
|
||||
var queuedItem = this.messageQueue[0]
|
||||
if (this.socket.readyState === this.socket.OPEN) {
|
||||
this.sendImmediately(queuedItem.message, queuedItem.sendElt);
|
||||
this.messageQueue.shift();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
init: function () {
|
||||
if (this.socket && this.socket.readyState === this.socket.OPEN) {
|
||||
// Close discarded socket
|
||||
this.socket.close()
|
||||
}
|
||||
|
||||
// Create a new WebSocket and event handlers
|
||||
/** @type {WebSocket} */
|
||||
var socket = socketFunc();
|
||||
|
||||
// The event.type detail is added for interface conformance with the
|
||||
// other two lifecycle events (open and close) so a single handler method
|
||||
// can handle them polymorphically, if required.
|
||||
api.triggerEvent(socketElt, "htmx:wsConnecting", { event: { type: 'connecting' } });
|
||||
|
||||
this.socket = socket;
|
||||
|
||||
socket.onopen = function (e) {
|
||||
wrapper.retryCount = 0;
|
||||
api.triggerEvent(socketElt, "htmx:wsOpen", { event: e, socketWrapper: wrapper.publicInterface });
|
||||
wrapper.handleQueuedMessages();
|
||||
}
|
||||
|
||||
socket.onclose = function (e) {
|
||||
// If socket should not be connected, stop further attempts to establish connection
|
||||
// If Abnormal Closure/Service Restart/Try Again Later, then set a timer to reconnect after a pause.
|
||||
if (!maybeCloseWebSocketSource(socketElt) && [1006, 1012, 1013].indexOf(e.code) >= 0) {
|
||||
var delay = getWebSocketReconnectDelay(wrapper.retryCount);
|
||||
setTimeout(function () {
|
||||
wrapper.retryCount += 1;
|
||||
wrapper.init();
|
||||
}, delay);
|
||||
}
|
||||
|
||||
// Notify client code that connection has been closed. Client code can inspect `event` field
|
||||
// to determine whether closure has been valid or abnormal
|
||||
api.triggerEvent(socketElt, "htmx:wsClose", { event: e, socketWrapper: wrapper.publicInterface })
|
||||
};
|
||||
|
||||
socket.onerror = function (e) {
|
||||
api.triggerErrorEvent(socketElt, "htmx:wsError", { error: e, socketWrapper: wrapper });
|
||||
maybeCloseWebSocketSource(socketElt);
|
||||
};
|
||||
|
||||
var events = this.events;
|
||||
Object.keys(events).forEach(function (k) {
|
||||
events[k].forEach(function (e) {
|
||||
socket.addEventListener(k, e);
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
close: function () {
|
||||
this.socket.close()
|
||||
}
|
||||
}
|
||||
|
||||
wrapper.init();
|
||||
|
||||
wrapper.publicInterface = {
|
||||
send: wrapper.send.bind(wrapper),
|
||||
sendImmediately: wrapper.sendImmediately.bind(wrapper),
|
||||
queue: wrapper.messageQueue
|
||||
};
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* ensureWebSocketSend attaches trigger handles to elements with
|
||||
* "ws-send" attribute
|
||||
* @param {HTMLElement} elt
|
||||
*/
|
||||
function ensureWebSocketSend(elt) {
|
||||
var legacyAttribute = api.getAttributeValue(elt, "hx-ws");
|
||||
if (legacyAttribute && legacyAttribute !== 'send') {
|
||||
return;
|
||||
}
|
||||
|
||||
var webSocketParent = api.getClosestMatch(elt, hasWebSocket)
|
||||
processWebSocketSend(webSocketParent, elt);
|
||||
}
|
||||
|
||||
/**
|
||||
* hasWebSocket function checks if a node has webSocket instance attached
|
||||
* @param {HTMLElement} node
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function hasWebSocket(node) {
|
||||
return api.getInternalData(node).webSocket != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* processWebSocketSend adds event listeners to the <form> element so that
|
||||
* messages can be sent to the WebSocket server when the form is submitted.
|
||||
* @param {HTMLElement} socketElt
|
||||
* @param {HTMLElement} sendElt
|
||||
*/
|
||||
function processWebSocketSend(socketElt, sendElt) {
|
||||
var nodeData = api.getInternalData(sendElt);
|
||||
var triggerSpecs = api.getTriggerSpecs(sendElt);
|
||||
triggerSpecs.forEach(function (ts) {
|
||||
api.addTriggerHandler(sendElt, ts, nodeData, function (elt, evt) {
|
||||
if (maybeCloseWebSocketSource(socketElt)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @type {WebSocketWrapper} */
|
||||
var socketWrapper = api.getInternalData(socketElt).webSocket;
|
||||
var headers = api.getHeaders(sendElt, api.getTarget(sendElt));
|
||||
var results = api.getInputValues(sendElt, 'post');
|
||||
var errors = results.errors;
|
||||
var rawParameters = results.values;
|
||||
var expressionVars = api.getExpressionVars(sendElt);
|
||||
var allParameters = api.mergeObjects(rawParameters, expressionVars);
|
||||
var filteredParameters = api.filterValues(allParameters, sendElt);
|
||||
|
||||
var sendConfig = {
|
||||
parameters: filteredParameters,
|
||||
unfilteredParameters: allParameters,
|
||||
headers: headers,
|
||||
errors: errors,
|
||||
|
||||
triggeringEvent: evt,
|
||||
messageBody: undefined,
|
||||
socketWrapper: socketWrapper.publicInterface
|
||||
};
|
||||
|
||||
if (!api.triggerEvent(elt, 'htmx:wsConfigSend', sendConfig)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (errors && errors.length > 0) {
|
||||
api.triggerEvent(elt, 'htmx:validation:halted', errors);
|
||||
return;
|
||||
}
|
||||
|
||||
var body = sendConfig.messageBody;
|
||||
if (body === undefined) {
|
||||
var toSend = Object.assign({}, sendConfig.parameters);
|
||||
if (sendConfig.headers)
|
||||
toSend['HEADERS'] = headers;
|
||||
body = JSON.stringify(toSend);
|
||||
}
|
||||
|
||||
socketWrapper.send(body, elt);
|
||||
|
||||
if (evt && api.shouldCancel(evt, elt)) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* getWebSocketReconnectDelay is the default easing function for WebSocket reconnects.
|
||||
* @param {number} retryCount // The number of retries that have already taken place
|
||||
* @returns {number}
|
||||
*/
|
||||
function getWebSocketReconnectDelay(retryCount) {
|
||||
|
||||
/** @type {"full-jitter" | ((retryCount:number) => number)} */
|
||||
var delay = htmx.config.wsReconnectDelay;
|
||||
if (typeof delay === 'function') {
|
||||
return delay(retryCount);
|
||||
}
|
||||
if (delay === 'full-jitter') {
|
||||
var exp = Math.min(retryCount, 6);
|
||||
var maxDelay = 1000 * Math.pow(2, exp);
|
||||
return maxDelay * Math.random();
|
||||
}
|
||||
|
||||
logError('htmx.config.wsReconnectDelay must either be a function or the string "full-jitter"');
|
||||
}
|
||||
|
||||
/**
|
||||
* maybeCloseWebSocketSource checks to the if the element that created the WebSocket
|
||||
* still exists in the DOM. If NOT, then the WebSocket is closed and this function
|
||||
* returns TRUE. If the element DOES EXIST, then no action is taken, and this function
|
||||
* returns FALSE.
|
||||
*
|
||||
* @param {*} elt
|
||||
* @returns
|
||||
*/
|
||||
function maybeCloseWebSocketSource(elt) {
|
||||
if (!api.bodyContains(elt)) {
|
||||
api.getInternalData(elt).webSocket.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* createWebSocket is the default method for creating new WebSocket objects.
|
||||
* it is hoisted into htmx.createWebSocket to be overridden by the user, if needed.
|
||||
*
|
||||
* @param {string} url
|
||||
* @returns WebSocket
|
||||
*/
|
||||
function createWebSocket(url) {
|
||||
var sock = new WebSocket(url, []);
|
||||
sock.binaryType = htmx.config.wsBinaryType;
|
||||
return sock;
|
||||
}
|
||||
|
||||
/**
|
||||
* queryAttributeOnThisOrChildren returns all nodes that contain the requested attributeName, INCLUDING THE PROVIDED ROOT ELEMENT.
|
||||
*
|
||||
* @param {HTMLElement} elt
|
||||
* @param {string} attributeName
|
||||
*/
|
||||
function queryAttributeOnThisOrChildren(elt, attributeName) {
|
||||
|
||||
var result = []
|
||||
|
||||
// If the parent element also contains the requested attribute, then add it to the results too.
|
||||
if (api.hasAttribute(elt, attributeName) || api.hasAttribute(elt, "hx-ws")) {
|
||||
result.push(elt);
|
||||
}
|
||||
|
||||
// Search all child nodes that match the requested attribute
|
||||
elt.querySelectorAll("[" + attributeName + "], [data-" + attributeName + "], [data-hx-ws], [hx-ws]").forEach(function (node) {
|
||||
result.push(node)
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {T[]} arr
|
||||
* @param {(T) => void} func
|
||||
*/
|
||||
function forEach(arr, func) {
|
||||
if (arr) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
func(arr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
1
templates/static/js/vendor/htmx.min.js
vendored
Normal file
1
templates/static/js/vendor/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
69
templates/static/js/vendor/marked.min.js
vendored
Normal file
69
templates/static/js/vendor/marked.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue