fix(server): update security modules and TODOs
This commit is contained in:
parent
0a24cd4b50
commit
fdf74903ad
6 changed files with 665 additions and 779 deletions
33
Cargo.toml
33
Cargo.toml
|
|
@ -23,8 +23,8 @@ directory = []
|
||||||
# Communication
|
# Communication
|
||||||
chat = ["automation", "drive", "cache"]
|
chat = ["automation", "drive", "cache"]
|
||||||
people = ["automation", "drive", "cache"]
|
people = ["automation", "drive", "cache"]
|
||||||
mail = ["automation", "drive", "cache", "dep:lettre", "dep:mailparse", "dep:imap", "dep:native-tls"]
|
mail = ["automation", "drive", "cache", "dep:lettre", "dep:mailparse", "dep:imap"]
|
||||||
meet = ["automation", "drive", "cache", "dep:livekit"]
|
meet = ["automation", "drive", "cache"]
|
||||||
social = ["automation", "drive", "cache"]
|
social = ["automation", "drive", "cache"]
|
||||||
|
|
||||||
# Productivity
|
# Productivity
|
||||||
|
|
@ -38,7 +38,7 @@ billing = ["automation", "drive", "cache"]
|
||||||
|
|
||||||
# Documents
|
# Documents
|
||||||
docs = ["automation", "drive", "cache", "docx-rs", "ooxmlsdk"]
|
docs = ["automation", "drive", "cache", "docx-rs", "ooxmlsdk"]
|
||||||
sheet = ["automation", "drive", "cache", "calamine", "spreadsheet-ods", "dep:rust_xlsxwriter", "dep:umya-spreadsheet"]
|
sheet = ["automation", "drive", "cache", "calamine", "dep:rust_xlsxwriter", "dep:umya-spreadsheet"]
|
||||||
slides = ["automation", "drive", "cache", "ooxmlsdk"]
|
slides = ["automation", "drive", "cache", "ooxmlsdk"]
|
||||||
paper = ["automation", "drive", "cache"]
|
paper = ["automation", "drive", "cache"]
|
||||||
|
|
||||||
|
|
@ -95,26 +95,19 @@ bigdecimal = { workspace = true }
|
||||||
aes-gcm = { workspace = true }
|
aes-gcm = { workspace = true }
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
argon2 = { workspace = true }
|
argon2 = { workspace = true }
|
||||||
async-lock = { workspace = true }
|
|
||||||
async-stream = { workspace = true }
|
|
||||||
async-trait = { workspace = true }
|
async-trait = { workspace = true }
|
||||||
axum = { workspace = true }
|
axum = { workspace = true }
|
||||||
axum-server = { workspace = true }
|
axum-server = { workspace = true }
|
||||||
base64 = { workspace = true }
|
base64 = { workspace = true }
|
||||||
bytes = { workspace = true }
|
|
||||||
chrono = { workspace = true, features = ["clock", "std"] }
|
chrono = { workspace = true, features = ["clock", "std"] }
|
||||||
color-eyre = { workspace = true }
|
color-eyre = { workspace = true }
|
||||||
diesel = { workspace = true, features = ["postgres", "uuid", "chrono", "serde_json", "r2d2", "numeric", "32-column-tables"] }
|
diesel = { workspace = true, features = ["postgres", "uuid", "chrono", "serde_json", "r2d2", "numeric", "32-column-tables"] }
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
dotenvy = { workspace = true }
|
dotenvy = { workspace = true }
|
||||||
env_logger = { workspace = true }
|
|
||||||
futures = { workspace = true }
|
futures = { workspace = true }
|
||||||
futures-util = { workspace = true }
|
futures-util = { workspace = true }
|
||||||
tokio-util = { workspace = true, features = ["codec"] }
|
|
||||||
hex = { workspace = true }
|
hex = { workspace = true }
|
||||||
hmac = { workspace = true }
|
hmac = { workspace = true }
|
||||||
hyper = { workspace = true, features = ["client", "server", "http1", "http2"] }
|
|
||||||
hyper-rustls = { workspace = true, features = ["http2"] }
|
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
num-format = { workspace = true }
|
num-format = { workspace = true }
|
||||||
once_cell = { workspace = true }
|
once_cell = { workspace = true }
|
||||||
|
|
@ -127,11 +120,8 @@ toml = { workspace = true }
|
||||||
sha2 = { workspace = true }
|
sha2 = { workspace = true }
|
||||||
sha1 = { workspace = true }
|
sha1 = { workspace = true }
|
||||||
tokio = { workspace = true, features = ["full", "process"] }
|
tokio = { workspace = true, features = ["full", "process"] }
|
||||||
tokio-stream = { workspace = true }
|
|
||||||
tower = { workspace = true }
|
|
||||||
tower-http = { workspace = true, features = ["cors", "fs", "trace"] }
|
tower-http = { workspace = true, features = ["cors", "fs", "trace"] }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-subscriber = { workspace = true }
|
|
||||||
urlencoding = { workspace = true }
|
urlencoding = { workspace = true }
|
||||||
uuid = { workspace = true, features = ["v4", "v5"] }
|
uuid = { workspace = true, features = ["v4", "v5"] }
|
||||||
|
|
||||||
|
|
@ -140,13 +130,10 @@ rustls = { workspace = true, features = ["ring", "std", "tls12"] }
|
||||||
tokio-rustls = { workspace = true }
|
tokio-rustls = { workspace = true }
|
||||||
rcgen = { workspace = true, features = ["crypto", "ring", "pem"] }
|
rcgen = { workspace = true, features = ["crypto", "ring", "pem"] }
|
||||||
x509-parser = { workspace = true }
|
x509-parser = { workspace = true }
|
||||||
rustls-native-certs = { workspace = true }
|
|
||||||
webpki-roots = { workspace = true }
|
|
||||||
ring = { workspace = true }
|
ring = { workspace = true }
|
||||||
ciborium = { workspace = true }
|
ciborium = { workspace = true }
|
||||||
time = { workspace = true, features = ["formatting"] }
|
time = { workspace = true, features = ["formatting"] }
|
||||||
jsonwebtoken = { workspace = true }
|
jsonwebtoken = { workspace = true }
|
||||||
tower-cookies = { workspace = true }
|
|
||||||
|
|
||||||
# === APP-SPECIFIC DEPENDENCIES ===
|
# === APP-SPECIFIC DEPENDENCIES ===
|
||||||
|
|
||||||
|
|
@ -154,10 +141,6 @@ tower-cookies = { workspace = true }
|
||||||
imap = { workspace = true, optional = true }
|
imap = { workspace = true, optional = true }
|
||||||
lettre = { workspace = true, optional = true }
|
lettre = { workspace = true, optional = true }
|
||||||
mailparse = { workspace = true, optional = true }
|
mailparse = { workspace = true, optional = true }
|
||||||
native-tls = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
# Video Meetings (meet feature)
|
|
||||||
livekit = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
# Vector Database (vectordb feature)
|
# Vector Database (vectordb feature)
|
||||||
qdrant-client = { workspace = true, optional = true }
|
qdrant-client = { workspace = true, optional = true }
|
||||||
|
|
@ -166,7 +149,6 @@ qdrant-client = { workspace = true, optional = true }
|
||||||
docx-rs = { workspace = true, optional = true }
|
docx-rs = { workspace = true, optional = true }
|
||||||
ooxmlsdk = { workspace = true, optional = true, features = ["parts"] }
|
ooxmlsdk = { workspace = true, optional = true, features = ["parts"] }
|
||||||
calamine = { workspace = true, optional = true }
|
calamine = { workspace = true, optional = true }
|
||||||
spreadsheet-ods = { workspace = true, optional = true }
|
|
||||||
rust_xlsxwriter = { workspace = true, optional = true }
|
rust_xlsxwriter = { workspace = true, optional = true }
|
||||||
umya-spreadsheet = { workspace = true, optional = true }
|
umya-spreadsheet = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
|
@ -206,9 +188,6 @@ redis = { workspace = true, features = ["tokio-comp"], optional = true }
|
||||||
# System Monitoring (monitoring feature)
|
# System Monitoring (monitoring feature)
|
||||||
sysinfo = { workspace = true, optional = true }
|
sysinfo = { workspace = true, optional = true }
|
||||||
|
|
||||||
# Networking/gRPC (grpc feature)
|
|
||||||
tonic = { workspace = true, features = ["transport"], optional = true }
|
|
||||||
|
|
||||||
# UI Enhancement (progress-bars feature)
|
# UI Enhancement (progress-bars feature)
|
||||||
indicatif = { workspace = true, optional = true }
|
indicatif = { workspace = true, optional = true }
|
||||||
smartstring = { workspace = true }
|
smartstring = { workspace = true }
|
||||||
|
|
@ -224,9 +203,6 @@ vaultrs = { workspace = true }
|
||||||
# Calendar standards (RFC 5545)
|
# Calendar standards (RFC 5545)
|
||||||
icalendar = { workspace = true }
|
icalendar = { workspace = true }
|
||||||
|
|
||||||
# Layered configuration
|
|
||||||
figment = { workspace = true, features = ["toml"] }
|
|
||||||
|
|
||||||
# Rate limiting
|
# Rate limiting
|
||||||
governor = { workspace = true }
|
governor = { workspace = true }
|
||||||
|
|
||||||
|
|
@ -239,9 +215,6 @@ walkdir = { workspace = true }
|
||||||
|
|
||||||
# Embedded static files
|
# Embedded static files
|
||||||
rust-embed = { workspace = true }
|
rust-embed = { workspace = true }
|
||||||
mime_guess = { workspace = true }
|
|
||||||
hyper-util = { workspace = true, features = ["client-legacy"] }
|
|
||||||
http-body-util = { workspace = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
mockito = { workspace = true }
|
mockito = { workspace = true }
|
||||||
|
|
|
||||||
358
TODO.md
358
TODO.md
|
|
@ -1,79 +1,309 @@
|
||||||
# Plano de Compilação Individual de Features
|
# General Bots 7.0 - Enhanced Multi-Agent Orchestration
|
||||||
|
|
||||||
## Objetivo
|
**Target Release:** Q3 2026
|
||||||
Compilar cada feature individualmente do botserver com `cargo check --no-default-features --features <feature>` para identificar todos os erros de dependência e compilação, consolidando os logs para análise sistemática.
|
**Current Version:** 6.1.0
|
||||||
|
**Priority:** Critical for enterprise adoption
|
||||||
|
|
||||||
## Features a Testar
|
---
|
||||||
|
|
||||||
### Grupo 1: Comunicação
|
## Phase 1: Enhanced Orchestration (Months 1-2) 🚀
|
||||||
- [x] `chat`
|
|
||||||
- [x] `people`
|
|
||||||
- [x] `mail`
|
|
||||||
- [ ] `meet` (Failed: webrtc-sys C++ build error: missing absl/container/inlined_vector.h)
|
|
||||||
- [x] `social`
|
|
||||||
|
|
||||||
### Grupo 2: Produtividade
|
### 1.1 ORCHESTRATE WORKFLOW Keyword
|
||||||
- [x] `calendar`
|
- [ ] **File:** `src/basic/keywords/orchestration.rs`
|
||||||
- [x] `tasks`
|
- [ ] Add `ORCHESTRATE WORKFLOW` keyword to BASIC interpreter
|
||||||
- [x] `project`
|
- [ ] Support STEP definitions with BOT calls
|
||||||
- [x] `goals`
|
- [ ] Support PARALLEL branches execution
|
||||||
- [x] `workspaces`
|
- [ ] Support conditional IF/THEN logic in workflows
|
||||||
- [x] `tickets`
|
- [ ] Variable passing between steps
|
||||||
- [x] `billing`
|
- [ ] **Database:** Add `workflow_executions` table
|
||||||
- crm
|
- [ ] **Test:** Create workflow execution tests
|
||||||
### Grupo 3: Documentos
|
|
||||||
- [x] `docs`
|
|
||||||
- [x] `sheet`
|
|
||||||
- [x] `slides`
|
|
||||||
- [x] `paper`
|
|
||||||
|
|
||||||
### Grupo 4: Mídia
|
### 1.2 Event Bus System
|
||||||
- [x] `video`
|
- [ ] **File:** `src/basic/keywords/events.rs`
|
||||||
- [x] `player`
|
- [ ] Add `ON EVENT` keyword for event handlers
|
||||||
- [x] `canvas`
|
- [ ] Add `PUBLISH EVENT` keyword for event emission
|
||||||
|
- [ ] Add `WAIT FOR EVENT` with timeout support
|
||||||
|
- [ ] **Integration:** Use existing Redis pub/sub
|
||||||
|
- [ ] **Database:** Add `workflow_events` table
|
||||||
|
- [ ] **Test:** Event-driven workflow tests
|
||||||
|
|
||||||
### Grupo 5: Aprendizado
|
### 1.3 Bot Learning Enhancement
|
||||||
- [x] `learn`
|
- [ ] **File:** `src/basic/keywords/bot_learning.rs`
|
||||||
- [x] `research` (Fixed: gated email dependencies, added missing imports)
|
- [ ] Add `BOT LEARN` keyword for pattern storage (extends existing `SET BOT MEMORY`)
|
||||||
- [x] `sources`
|
- [ ] Add `BOT RECALL` keyword for pattern retrieval (extends existing bot memory)
|
||||||
|
- [ ] Add `BOT SHARE KNOWLEDGE` for cross-bot learning
|
||||||
|
- [ ] **Integration:** Use existing VectorDB (Qdrant) + existing bot_memories table
|
||||||
|
- [ ] **Write-back:** Store learned patterns in `.gbkb` folders for persistence
|
||||||
|
- [ ] **Test:** Bot learning and recall tests
|
||||||
|
|
||||||
### Grupo 6: Analytics
|
**Note:** Difference between `SET BOT MEMORY` vs `BOT LEARN`:
|
||||||
- [x] `analytics`
|
- `SET BOT MEMORY`: Manual key-value storage (existing)
|
||||||
- [x] `dashboards`
|
- `BOT LEARN`: Automatic pattern recognition from conversations
|
||||||
- [x] `monitoring` (Fixed: E0308 type mismatch in SVG generation)
|
|
||||||
|
|
||||||
### Grupo 7: Desenvolvimento
|
### 1.4 Database Schema
|
||||||
- [x] `designer`
|
```sql
|
||||||
- [x] `editor`
|
-- Add to migrations/
|
||||||
|
CREATE TABLE workflow_executions (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
bot_id UUID REFERENCES bots(id),
|
||||||
|
workflow_name TEXT,
|
||||||
|
current_step INTEGER,
|
||||||
|
state JSONB,
|
||||||
|
status TEXT DEFAULT 'running',
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
### Grupo 8: Admin
|
CREATE TABLE workflow_events (
|
||||||
- [x] `attendant`
|
id UUID PRIMARY KEY,
|
||||||
- [x] `security`
|
workflow_id UUID REFERENCES workflow_executions(id),
|
||||||
- [x] `settings`
|
event_name TEXT,
|
||||||
|
event_data JSONB,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
## Erros e Avisos Identificados
|
CREATE TABLE bot_knowledge (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
bot_id UUID REFERENCES bots(id),
|
||||||
|
pattern TEXT,
|
||||||
|
confidence FLOAT,
|
||||||
|
learned_from UUID REFERENCES conversations(id),
|
||||||
|
kb_file_path TEXT, -- Path to .gbkb file for persistence
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
### Erros de Compilação (Bloqueios)
|
---
|
||||||
- [ ] **meet**: Falha no build C++ da dependência `webrtc-sys` (header `absl/container/inlined_vector.h` não encontrado).
|
|
||||||
- Requer instalação de dependências de sistema (não resolvido neste ambiente).
|
|
||||||
|
|
||||||
### Avisos Comuns (Shared)
|
## Phase 2: Visual Workflow Designer (Months 3-4) 🎨
|
||||||
- [x] Fixed all shared warnings (unused variables/mut/imports in compiler, state, drive_monitor).
|
|
||||||
|
|
||||||
### Avisos Específicos de Feature
|
### 2.1 Drag-and-Drop Canvas
|
||||||
- [x] **mail**: Fixed unused imports.
|
- [ ] **File:** `src/designer/workflow_canvas.rs`
|
||||||
- [x] **tasks**: Fixed unused imports.
|
- [ ] Extend existing designer with workflow nodes
|
||||||
- [x] **project**: Fixed unused imports.
|
- [ ] Add node types: BotAgent, HumanApproval, Condition, Loop, Parallel
|
||||||
- [x] **tickets**: Fixed unused imports.
|
- [ ] Drag-and-drop interface using existing HTMX
|
||||||
- [x] **learn**: Fixed unused imports.
|
- [ ] **Frontend:** Add workflow canvas to existing designer UI
|
||||||
- [x] **analytics**: Fixed unused imports.
|
- [ ] **Output:** Generate BASIC code from visual design
|
||||||
- [x] **designer**: Fixed unused variable `messages`.
|
|
||||||
|
|
||||||
|
### 2.2 Bot Templates
|
||||||
|
- [ ] **Directory:** `bottemplates/` (not templates/)
|
||||||
|
- [ ] Create pre-built workflow `.gbai` packages
|
||||||
|
- [ ] Customer support escalation template
|
||||||
|
- [ ] E-commerce order processing template
|
||||||
|
- [ ] Content moderation template
|
||||||
|
- [ ] **Integration:** Auto-discovery via existing package system
|
||||||
|
|
||||||
## Remaining Warnings Plan (From TODO.tmp)
|
### 2.3 Visual Designer Enhancement
|
||||||
1. **Automated Fixes**: Run `cargo clippy --fix --workspace` to resolve simple warnings (unused imports/variables/mut).
|
- [ ] **File:** `src/designer/mod.rs`
|
||||||
- [ ] Execution in progress.
|
- [ ] Add workflow mode to existing designer
|
||||||
2. **Manual Fixes**: Address warnings not resolvable by auto-fix.
|
- [ ] Real-time BASIC code preview
|
||||||
- [ ] Complex logic changes.
|
- [ ] Workflow validation and error checking
|
||||||
- [ ] Feature gating adjustments.
|
- [ ] **Test:** Visual designer workflow tests
|
||||||
3. **Verification**: Run `cargo check --workspace` to ensure zero warnings.
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3: Intelligence & Learning (Months 5-6) 🧠
|
||||||
|
|
||||||
|
### 3.1 Smart LLM Routing
|
||||||
|
- [ ] **File:** `src/llm/smart_router.rs`
|
||||||
|
- [ ] Extend existing `llm/observability.rs`
|
||||||
|
- [ ] Add cost/latency tracking per model
|
||||||
|
- [ ] Automatic model selection based on task type
|
||||||
|
- [ ] **BASIC:** Enhance LLM keyword with OPTIMIZE FOR parameter
|
||||||
|
- [ ] **Database:** Add `model_performance` table
|
||||||
|
- [ ] **Test:** LLM routing optimization tests
|
||||||
|
|
||||||
|
### 3.2 Bot Learning System
|
||||||
|
- [ ] **File:** `src/bots/learning.rs`
|
||||||
|
- [ ] Pattern recognition from conversation history
|
||||||
|
- [ ] Cross-bot knowledge sharing mechanisms
|
||||||
|
- [ ] Confidence scoring for learned patterns
|
||||||
|
- [ ] **Write-back to .gbkb:** Store learned patterns as knowledge base files
|
||||||
|
- [ ] **Integration:** Use existing conversation storage + VectorDB
|
||||||
|
- [ ] **Test:** Bot learning behavior tests
|
||||||
|
|
||||||
|
### 3.3 Enhanced BASIC Keywords
|
||||||
|
```basic
|
||||||
|
' New keywords to implement
|
||||||
|
result = LLM "Analyze data" WITH OPTIMIZE FOR "speed"
|
||||||
|
BOT LEARN PATTERN "customer prefers email" WITH CONFIDENCE 0.8
|
||||||
|
preferences = BOT RECALL "customer communication patterns"
|
||||||
|
BOT SHARE KNOWLEDGE WITH "support-bot-2"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4: Plugin Ecosystem (Months 7-8) 🔌
|
||||||
|
|
||||||
|
### 4.1 Plugin Registry
|
||||||
|
- [ ] **File:** `src/plugins/registry.rs`
|
||||||
|
- [ ] **Database:** Add `plugins` table with metadata
|
||||||
|
- [ ] Plugin security scanning system
|
||||||
|
- [ ] Version management and updates
|
||||||
|
- [ ] **Integration:** Extend existing MCP support
|
||||||
|
|
||||||
|
### 4.2 Plugin Discovery Keywords
|
||||||
|
- [ ] **File:** `src/basic/keywords/plugins.rs`
|
||||||
|
- [ ] Add `SEARCH PLUGINS` keyword
|
||||||
|
- [ ] Add `INSTALL PLUGIN` keyword
|
||||||
|
- [ ] Add `LIST PLUGINS` keyword
|
||||||
|
- [ ] **Integration:** Auto-update `mcp.csv` on install
|
||||||
|
- [ ] **Test:** Plugin installation and discovery tests
|
||||||
|
|
||||||
|
### 4.3 Plugin Marketplace
|
||||||
|
- [ ] **Database Schema:**
|
||||||
|
```sql
|
||||||
|
CREATE TABLE plugins (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
name TEXT UNIQUE,
|
||||||
|
description TEXT,
|
||||||
|
mcp_server_url TEXT,
|
||||||
|
permissions TEXT[],
|
||||||
|
security_scan_result JSONB,
|
||||||
|
downloads INTEGER DEFAULT 0,
|
||||||
|
rating FLOAT,
|
||||||
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Guidelines
|
||||||
|
|
||||||
|
### Code Standards
|
||||||
|
- [ ] **No breaking changes** - all existing `.gbai` packages must work
|
||||||
|
- [ ] **Extend existing systems** - don't rebuild what works
|
||||||
|
- [ ] **BASIC-first design** - everything accessible via BASIC keywords
|
||||||
|
- [ ] **Use existing infrastructure** - PostgreSQL, Redis, Qdrant, LXC
|
||||||
|
- [ ] **Proper error handling** - no unwrap(), use SafeCommand wrapper
|
||||||
|
|
||||||
|
### Testing Requirements
|
||||||
|
- [ ] **Unit tests** for all new BASIC keywords
|
||||||
|
- [ ] **Integration tests** for workflow execution
|
||||||
|
- [ ] **Performance tests** for multi-agent coordination
|
||||||
|
- [ ] **Backward compatibility tests** for existing `.gbai` packages
|
||||||
|
|
||||||
|
### Documentation Updates
|
||||||
|
- [ ] **File:** `docs/reference/basic-language.md` - Add new keywords
|
||||||
|
- [ ] **File:** `docs/guides/workflows.md` - Workflow creation guide
|
||||||
|
- [ ] **File:** `docs/guides/multi-agent.md` - Multi-agent patterns
|
||||||
|
- [ ] **File:** `docs/api/workflow-api.md` - Workflow REST endpoints
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Structure Changes
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── basic/keywords/
|
||||||
|
│ ├── orchestration.rs # NEW: ORCHESTRATE WORKFLOW
|
||||||
|
│ ├── events.rs # NEW: ON EVENT, PUBLISH EVENT
|
||||||
|
│ ├── agent_learning.rs # NEW: AGENT LEARN/RECALL
|
||||||
|
│ └── plugins.rs # NEW: SEARCH/INSTALL PLUGINS
|
||||||
|
├── designer/
|
||||||
|
│ ├── workflow_canvas.rs # NEW: Visual workflow editor
|
||||||
|
│ └── mod.rs # EXTEND: Add workflow mode
|
||||||
|
├── llm/
|
||||||
|
│ └── smart_router.rs # NEW: Intelligent model routing
|
||||||
|
├── agents/
|
||||||
|
│ └── learning.rs # NEW: Agent learning system
|
||||||
|
└── plugins/
|
||||||
|
└── registry.rs # NEW: Plugin management
|
||||||
|
|
||||||
|
templates/
|
||||||
|
└── workflow-templates/ # NEW: Pre-built workflows
|
||||||
|
├── customer-support.gbai/
|
||||||
|
├── order-processing.gbai/
|
||||||
|
└── content-moderation.gbai/
|
||||||
|
|
||||||
|
docs/
|
||||||
|
├── guides/
|
||||||
|
│ ├── tools-vs-bots.md # DONE: Tool vs Bot explanation
|
||||||
|
│ ├── workflows.md # NEW: Workflow creation
|
||||||
|
│ └── multi-agent.md # NEW: Multi-agent patterns
|
||||||
|
└── reference/
|
||||||
|
└── basic-language.md # UPDATE: New keywords
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
|
||||||
|
### Technical Metrics
|
||||||
|
- [ ] **Backward compatibility:** 100% existing `.gbai` packages work
|
||||||
|
- [ ] **Performance:** Workflow execution <2s overhead
|
||||||
|
- [ ] **Reliability:** 99.9% workflow completion rate
|
||||||
|
- [ ] **Memory usage:** <10% increase from current baseline
|
||||||
|
|
||||||
|
### Business Metrics
|
||||||
|
- [ ] **Workflow creation time:** 50% reduction vs manual coordination
|
||||||
|
- [ ] **Training time:** 80% reduction for non-programmers
|
||||||
|
- [ ] **Enterprise adoption:** 10x faster implementation
|
||||||
|
- [ ] **Community plugins:** 100+ plugins in first 6 months
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Risk Mitigation
|
||||||
|
|
||||||
|
### Technical Risks
|
||||||
|
- [ ] **Context overflow:** Implement workflow state persistence
|
||||||
|
- [ ] **Bot coordination failures:** Add timeout and retry mechanisms
|
||||||
|
- [ ] **Performance degradation:** Implement workflow step caching
|
||||||
|
- [ ] **Memory leaks:** Proper cleanup of workflow sessions
|
||||||
|
|
||||||
|
### Business Risks
|
||||||
|
- [ ] **Breaking changes:** Comprehensive backward compatibility testing
|
||||||
|
- [ ] **Complexity creep:** Keep BASIC-first design principle
|
||||||
|
- [ ] **Performance impact:** Benchmark all new features
|
||||||
|
- [ ] **Security vulnerabilities:** Security review for all plugin systems
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
### External Dependencies (No New Ones)
|
||||||
|
- ✅ **Rust 1.75+** - Already required
|
||||||
|
- ✅ **PostgreSQL** - Already in LXC container
|
||||||
|
- ✅ **Redis** - Already in LXC container
|
||||||
|
- ✅ **Qdrant** - Already in LXC container
|
||||||
|
- ✅ **Rhai** - Already used for BASIC interpreter
|
||||||
|
|
||||||
|
### Internal Dependencies
|
||||||
|
- ✅ **Existing BASIC interpreter** - Extend with new keywords
|
||||||
|
- ✅ **Existing bot management** - Use for multi-agent coordination
|
||||||
|
- ✅ **Existing session system** - Store workflow state
|
||||||
|
- ✅ **Existing MCP support** - Extend for plugin system
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Delivery Timeline
|
||||||
|
|
||||||
|
| Phase | Duration | Deliverable | Dependencies |
|
||||||
|
|-------|----------|-------------|--------------|
|
||||||
|
| **Phase 1** | 2 months | Enhanced orchestration | None |
|
||||||
|
| **Phase 2** | 2 months | Visual designer | Phase 1 |
|
||||||
|
| **Phase 3** | 2 months | Intelligence & learning | Phase 1 |
|
||||||
|
| **Phase 4** | 2 months | Plugin ecosystem | Phase 1 |
|
||||||
|
|
||||||
|
**Total Duration:** 8 months
|
||||||
|
**Target Release:** General Bots 7.0 - Q3 2026
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Immediate Next Steps
|
||||||
|
1. [ ] **Create feature branch:** `git checkout -b feature/orchestration-7.0`
|
||||||
|
2. [ ] **Set up development environment:** Ensure Rust 1.75+, PostgreSQL, Redis
|
||||||
|
3. [ ] **Start with Phase 1.1:** Implement `ORCHESTRATE WORKFLOW` keyword
|
||||||
|
4. [ ] **Create basic test:** Simple 2-step workflow execution
|
||||||
|
5. [ ] **Document progress:** Update this TODO.md as tasks complete
|
||||||
|
|
||||||
|
### Development Order
|
||||||
|
1. **Start with BASIC keywords** - Core functionality first
|
||||||
|
2. **Add database schema** - Persistence layer
|
||||||
|
3. **Implement workflow engine** - Execution logic
|
||||||
|
4. **Add visual designer** - User interface
|
||||||
|
5. **Enhance with intelligence** - AI improvements
|
||||||
|
6. **Build plugin system** - Extensibility
|
||||||
|
|
||||||
|
**Remember:** Build on existing systems, don't rebuild. Every new feature should extend what already works in General Bots.
|
||||||
|
|
|
||||||
663
TODO.tmp
663
TODO.tmp
|
|
@ -1,663 +0,0 @@
|
||||||
Checking bottest v6.1.0 (/home/rodriguez/src/gb/bottest)
|
|
||||||
Compiling botapp v6.1.0 (/home/rodriguez/src/gb/botapp)
|
|
||||||
Checking botserver v6.1.0 (/home/rodriguez/src/gb/botserver)
|
|
||||||
warning: this function has too many arguments (8/7)
|
|
||||||
--> botserver/src/auto_task/app_logs.rs:117:5
|
|
||||||
|
|
|
||||||
117 | / pub fn log(
|
|
||||||
118 | | &self,
|
|
||||||
119 | | app_name: &str,
|
|
||||||
120 | | level: LogLevel,
|
|
||||||
... |
|
|
||||||
125 | | user_id: Option<Uuid>,
|
|
||||||
126 | | ) {
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
= note: `#[warn(clippy::too_many_arguments)]` on by default
|
|
||||||
|
|
||||||
warning: this function has too many arguments (8/7)
|
|
||||||
--> botserver/src/auto_task/app_logs.rs:154:5
|
|
||||||
|
|
|
||||||
154 | / pub fn log_error(
|
|
||||||
155 | | &self,
|
|
||||||
156 | | app_name: &str,
|
|
||||||
157 | | source: LogSource,
|
|
||||||
... |
|
|
||||||
162 | | stack_trace: Option<&str>,
|
|
||||||
163 | | ) {
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
|
|
||||||
warning: this function has too many arguments (8/7)
|
|
||||||
--> botserver/src/auto_task/task_manifest.rs:938:1
|
|
||||||
|
|
|
||||||
938 | / pub fn create_manifest_from_llm_response(
|
|
||||||
939 | | app_name: &str,
|
|
||||||
940 | | description: &str,
|
|
||||||
941 | | tables: Vec<TableDefinition>,
|
|
||||||
... |
|
|
||||||
946 | | monitors: Vec<MonitorDefinition>,
|
|
||||||
947 | | ) -> TaskManifest {
|
|
||||||
| |_________________^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
|
|
||||||
warning: this function has too many arguments (11/7)
|
|
||||||
--> botserver/src/basic/keywords/human_approval.rs:256:5
|
|
||||||
|
|
|
||||||
256 | / pub fn create_request(
|
|
||||||
257 | | &self,
|
|
||||||
258 | | bot_id: Uuid,
|
|
||||||
259 | | session_id: Uuid,
|
|
||||||
... |
|
|
||||||
267 | | default_action: Option<ApprovalDecision>,
|
|
||||||
268 | | ) -> ApprovalRequest {
|
|
||||||
| |________________________^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
|
|
||||||
warning: this function has too many arguments (8/7)
|
|
||||||
--> botserver/src/basic/keywords/create_site.rs:111:1
|
|
||||||
|
|
|
||||||
111 | / async fn create_site(
|
|
||||||
112 | | config: crate::core::config::AppConfig,
|
|
||||||
113 | | s3: Option<std::sync::Arc<aws_sdk_s3::Client>>,
|
|
||||||
114 | | bucket: String,
|
|
||||||
... |
|
|
||||||
119 | | prompt: Dynamic,
|
|
||||||
120 | | ) -> Result<String, Box<dyn Error + Send + Sync>> {
|
|
||||||
| |_________________________________________________^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
|
|
||||||
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
|
|
||||||
--> botserver/src/channels/media_upload.rs:44:5
|
|
||||||
|
|
|
||||||
44 | / pub fn from_str(s: &str) -> Option<Self> {
|
|
||||||
45 | | match s.to_lowercase().as_str() {
|
|
||||||
46 | | "twitter" | "x" => Some(Self::Twitter),
|
|
||||||
47 | | "facebook" | "fb" => Some(Self::Facebook),
|
|
||||||
... |
|
|
||||||
61 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#should_implement_trait
|
|
||||||
= note: `#[warn(clippy::should_implement_trait)]` on by default
|
|
||||||
|
|
||||||
warning: match expression looks like `matches!` macro
|
|
||||||
--> botserver/src/channels/oauth.rs:52:9
|
|
||||||
|
|
|
||||||
52 | / match self {
|
|
||||||
53 | | Self::Bluesky | Self::Telegram | Self::Twilio => false,
|
|
||||||
54 | | _ => true,
|
|
||||||
55 | | }
|
|
||||||
| |_________^ help: try: `!matches!(self, Self::Bluesky | Self::Telegram | Self::Twilio)`
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#match_like_matches_macro
|
|
||||||
= note: `#[warn(clippy::match_like_matches_macro)]` on by default
|
|
||||||
|
|
||||||
warning: very complex type used. Consider factoring parts into `type` definitions
|
|
||||||
--> botserver/src/core/middleware.rs:501:6
|
|
||||||
|
|
|
||||||
501 | ) -> impl Fn(Request<Body>, Next) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Response, Response>> + Send>>
|
|
||||||
| ______^
|
|
||||||
502 | | + Clone
|
|
||||||
503 | | + Send {
|
|
||||||
| |_____________^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#type_complexity
|
|
||||||
= note: `#[warn(clippy::type_complexity)]` on by default
|
|
||||||
|
|
||||||
warning: stripping a prefix manually
|
|
||||||
--> botserver/src/core/middleware.rs:691:9
|
|
||||||
|
|
|
||||||
691 | &auth_header[7..]
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: the prefix was tested here
|
|
||||||
--> botserver/src/core/middleware.rs:690:17
|
|
||||||
|
|
|
||||||
690 | let token = if auth_header.starts_with("Bearer ") {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#manual_strip
|
|
||||||
= note: `#[warn(clippy::manual_strip)]` on by default
|
|
||||||
help: try using the `strip_prefix` method
|
|
||||||
|
|
|
||||||
690 ~ let token = if let Some(<stripped>) = auth_header.strip_prefix("Bearer ") {
|
|
||||||
691 ~ <stripped>
|
|
||||||
|
|
|
||||||
|
|
||||||
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
|
|
||||||
--> botserver/src/core/organization_invitations.rs:37:5
|
|
||||||
|
|
|
||||||
37 | / pub fn from_str(s: &str) -> Option<Self> {
|
|
||||||
38 | | match s.to_lowercase().as_str() {
|
|
||||||
39 | | "owner" => Some(Self::Owner),
|
|
||||||
40 | | "admin" => Some(Self::Admin),
|
|
||||||
... |
|
|
||||||
47 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#should_implement_trait
|
|
||||||
|
|
||||||
warning: this function has too many arguments (10/7)
|
|
||||||
--> botserver/src/core/organization_invitations.rs:184:5
|
|
||||||
|
|
|
||||||
184 | / pub async fn create_invitation(
|
|
||||||
185 | | &self,
|
|
||||||
186 | | organization_id: Uuid,
|
|
||||||
187 | | organization_name: &str,
|
|
||||||
... |
|
|
||||||
194 | | expires_in_days: i64,
|
|
||||||
195 | | ) -> Result<OrganizationInvitation, String> {
|
|
||||||
| |_______________________________________________^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
|
|
||||||
warning: this function has too many arguments (9/7)
|
|
||||||
--> botserver/src/core/organization_invitations.rs:249:5
|
|
||||||
|
|
|
||||||
249 | / pub async fn bulk_invite(
|
|
||||||
250 | | &self,
|
|
||||||
251 | | organization_id: Uuid,
|
|
||||||
252 | | organization_name: &str,
|
|
||||||
... |
|
|
||||||
258 | | message: Option<String>,
|
|
||||||
259 | | ) -> BulkInviteResponse {
|
|
||||||
| |___________________________^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
|
|
||||||
warning: clamp-like pattern without using clamp function
|
|
||||||
--> botserver/src/core/organization_invitations.rs:651:27
|
|
||||||
|
|
|
||||||
651 | let expires_in_days = req.expires_in_days.unwrap_or(7).max(1).min(30);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with clamp: `req.expires_in_days.unwrap_or(7).clamp(1, 30)`
|
|
||||||
|
|
|
||||||
= note: clamp will panic if max < min
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#manual_clamp
|
|
||||||
= note: `#[warn(clippy::manual_clamp)]` on by default
|
|
||||||
|
|
||||||
warning: very complex type used. Consider factoring parts into `type` definitions
|
|
||||||
--> botserver/src/core/organization_rbac.rs:246:17
|
|
||||||
|
|
|
||||||
246 | user_roles: Arc<RwLock<HashMap<(Uuid, Uuid), Vec<Uuid>>>>,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#type_complexity
|
|
||||||
|
|
||||||
warning: this function has too many arguments (8/7)
|
|
||||||
--> botserver/src/core/package_manager/setup/directory_setup.rs:221:5
|
|
||||||
|
|
|
||||||
221 | / pub async fn create_user(
|
|
||||||
222 | | &mut self,
|
|
||||||
223 | | org_id: &str,
|
|
||||||
224 | | username: &str,
|
|
||||||
... |
|
|
||||||
229 | | is_admin: bool,
|
|
||||||
230 | | ) -> Result<DefaultUser> {
|
|
||||||
| |____________________________^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#too_many_arguments
|
|
||||||
|
|
||||||
warning: very complex type used. Consider factoring parts into `type` definitions
|
|
||||||
--> botserver/src/core/performance.rs:740:16
|
|
||||||
|
|
|
||||||
740 | processor: Arc<dyn Fn(Vec<T>) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>> + Send + Sync>,
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#type_complexity
|
|
||||||
|
|
||||||
warning: very complex type used. Consider factoring parts into `type` definitions
|
|
||||||
--> botserver/src/core/performance.rs:749:28
|
|
||||||
|
|
|
||||||
749 | let processor_arc: Arc<dyn Fn(Vec<T>) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>> + Send + Sync> =
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#type_complexity
|
|
||||||
|
|
||||||
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
|
|
||||||
--> botserver/src/security/api_keys.rs:65:5
|
|
||||||
|
|
|
||||||
65 | / pub fn from_str(s: &str) -> Option<Self> {
|
|
||||||
66 | | match s {
|
|
||||||
67 | | "read" => Some(Self::Read),
|
|
||||||
68 | | "write" => Some(Self::Write),
|
|
||||||
... |
|
|
||||||
85 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#should_implement_trait
|
|
||||||
|
|
||||||
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
|
|
||||||
--> botserver/src/security/auth.rs:150:5
|
|
||||||
|
|
|
||||||
150 | / pub fn from_str(s: &str) -> Self {
|
|
||||||
151 | | match s.to_lowercase().as_str() {
|
|
||||||
152 | | "anonymous" => Self::Anonymous,
|
|
||||||
153 | | "user" => Self::User,
|
|
||||||
... |
|
|
||||||
164 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#should_implement_trait
|
|
||||||
|
|
||||||
warning: very complex type used. Consider factoring parts into `type` definitions
|
|
||||||
--> botserver/src/security/passkey.rs:898:10
|
|
||||||
|
|
|
||||||
898 | ) -> Result<(Vec<u8>, Vec<u8>, Option<Vec<u8>>), PasskeyError> {
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#type_complexity
|
|
||||||
|
|
||||||
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
|
|
||||||
--> botserver/src/security/protection/manager.rs:36:5
|
|
||||||
|
|
|
||||||
36 | / pub fn from_str(s: &str) -> Option<Self> {
|
|
||||||
37 | | match s.to_lowercase().as_str() {
|
|
||||||
38 | | "lynis" => Some(Self::Lynis),
|
|
||||||
39 | | "rkhunter" => Some(Self::RKHunter),
|
|
||||||
... |
|
|
||||||
46 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#should_implement_trait
|
|
||||||
|
|
||||||
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
|
|
||||||
--> botserver/src/security/secrets.rs:13:5
|
|
||||||
|
|
|
||||||
13 | / pub fn from_str(secret: &str) -> Self {
|
|
||||||
14 | | Self {
|
|
||||||
15 | | inner: secret.to_string(),
|
|
||||||
16 | | }
|
|
||||||
17 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#should_implement_trait
|
|
||||||
|
|
||||||
warning: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
|
|
||||||
--> botserver/src/botmodels/python_bridge.rs:124:5
|
|
||||||
|
|
|
||||||
124 | / pub fn from_str(s: &str) -> Option<Self> {
|
|
||||||
125 | | match s.to_lowercase().as_str() {
|
|
||||||
126 | | "mediapipe" => Some(Self::MediaPipe),
|
|
||||||
127 | | "deepface" => Some(Self::DeepFace),
|
|
||||||
... |
|
|
||||||
134 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#should_implement_trait
|
|
||||||
|
|
||||||
warning: `botserver` (bin "botserver") generated 23 warnings
|
|
||||||
warning: variable does not need to be mutable
|
|
||||||
--> botserver/src/botmodels/opencv.rs:613:13
|
|
||||||
|
|
|
||||||
613 | let mut detector = OpenCvFaceDetector::new(config);
|
|
||||||
| ----^^^^^^^^
|
|
||||||
| |
|
|
||||||
| help: remove this `mut`
|
|
||||||
|
|
|
||||||
= note: `#[warn(unused_mut)]` (part of `#[warn(unused)]`) on by default
|
|
||||||
|
|
||||||
warning: this `impl` can be derived
|
|
||||||
--> botserver/src/core/session/mod.rs:551:5
|
|
||||||
|
|
|
||||||
551 | / impl Default for Role {
|
|
||||||
552 | | fn default() -> Self {
|
|
||||||
553 | | Self::User
|
|
||||||
554 | | }
|
|
||||||
555 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#derivable_impls
|
|
||||||
= note: `#[warn(clippy::derivable_impls)]` on by default
|
|
||||||
help: replace the manual implementation with a derive attribute and mark the default variant
|
|
||||||
|
|
|
||||||
544 ~ #[derive(Default)]
|
|
||||||
545 ~ pub enum Role {
|
|
||||||
546 | Admin,
|
|
||||||
547 | Attendant,
|
|
||||||
548 ~ #[default]
|
|
||||||
549 ~ User,
|
|
||||||
550 | Guest,
|
|
||||||
551 | }
|
|
||||||
552 |
|
|
||||||
553 ~
|
|
||||||
|
|
|
||||||
|
|
||||||
warning: this `impl` can be derived
|
|
||||||
--> botserver/src/core/session/mod.rs:593:5
|
|
||||||
|
|
|
||||||
593 | / impl Default for Channel {
|
|
||||||
594 | | fn default() -> Self {
|
|
||||||
595 | | Self::WhatsApp
|
|
||||||
596 | | }
|
|
||||||
597 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#derivable_impls
|
|
||||||
help: replace the manual implementation with a derive attribute and mark the default variant
|
|
||||||
|
|
|
||||||
584 ~ #[derive(Default)]
|
|
||||||
585 ~ pub enum Channel {
|
|
||||||
586 ~ #[default]
|
|
||||||
587 ~ WhatsApp,
|
|
||||||
588 | Teams,
|
|
||||||
...
|
|
||||||
594 |
|
|
||||||
595 ~
|
|
||||||
|
|
|
||||||
|
|
||||||
warning: this `impl` can be derived
|
|
||||||
--> botserver/src/core/session/mod.rs:668:5
|
|
||||||
|
|
|
||||||
668 | / impl Default for SessionState {
|
|
||||||
669 | | fn default() -> Self {
|
|
||||||
670 | | Self::Active
|
|
||||||
671 | | }
|
|
||||||
672 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#derivable_impls
|
|
||||||
help: replace the manual implementation with a derive attribute and mark the default variant
|
|
||||||
|
|
|
||||||
661 ~ #[derive(Default)]
|
|
||||||
662 ~ pub enum SessionState {
|
|
||||||
663 ~ #[default]
|
|
||||||
664 ~ Active,
|
|
||||||
665 | Waiting,
|
|
||||||
...
|
|
||||||
669 |
|
|
||||||
670 ~
|
|
||||||
|
|
|
||||||
|
|
||||||
warning: this `impl` can be derived
|
|
||||||
--> botserver/src/core/session/mod.rs:723:5
|
|
||||||
|
|
|
||||||
723 | / impl Default for ContentType {
|
|
||||||
724 | | fn default() -> Self {
|
|
||||||
725 | | Self::Text
|
|
||||||
726 | | }
|
|
||||||
727 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#derivable_impls
|
|
||||||
help: replace the manual implementation with a derive attribute and mark the default variant
|
|
||||||
|
|
|
||||||
712 ~ #[derive(Default)]
|
|
||||||
713 ~ pub enum ContentType {
|
|
||||||
714 ~ #[default]
|
|
||||||
715 ~ Text,
|
|
||||||
716 | Image,
|
|
||||||
...
|
|
||||||
724 |
|
|
||||||
725 ~
|
|
||||||
|
|
|
||||||
|
|
||||||
warning: this `impl` can be derived
|
|
||||||
--> botserver/src/core/session/mod.rs:763:5
|
|
||||||
|
|
|
||||||
763 | / impl Default for Priority {
|
|
||||||
764 | | fn default() -> Self {
|
|
||||||
765 | | Self::Normal
|
|
||||||
766 | | }
|
|
||||||
767 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#derivable_impls
|
|
||||||
help: replace the manual implementation with a derive attribute and mark the default variant
|
|
||||||
|
|
|
||||||
756 ~ #[derive(Default)]
|
|
||||||
757 ~ pub enum Priority {
|
|
||||||
758 | Low = 0,
|
|
||||||
759 ~ #[default]
|
|
||||||
760 ~ Normal = 1,
|
|
||||||
761 | High = 2,
|
|
||||||
...
|
|
||||||
764 |
|
|
||||||
765 ~
|
|
||||||
|
|
|
||||||
|
|
||||||
warning: this `impl` can be derived
|
|
||||||
--> botserver/src/core/session/mod.rs:779:5
|
|
||||||
|
|
|
||||||
779 | / impl Default for QueueStatus {
|
|
||||||
780 | | fn default() -> Self {
|
|
||||||
781 | | Self::Waiting
|
|
||||||
782 | | }
|
|
||||||
783 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#derivable_impls
|
|
||||||
help: replace the manual implementation with a derive attribute and mark the default variant
|
|
||||||
|
|
|
||||||
771 ~ #[derive(Default)]
|
|
||||||
772 ~ pub enum QueueStatus {
|
|
||||||
773 ~ #[default]
|
|
||||||
774 ~ Waiting,
|
|
||||||
775 | Assigned,
|
|
||||||
...
|
|
||||||
780 |
|
|
||||||
781 ~
|
|
||||||
|
|
|
||||||
|
|
||||||
warning: this `impl` can be derived
|
|
||||||
--> botserver/src/core/session/mod.rs:824:5
|
|
||||||
|
|
|
||||||
824 | / impl Default for ConversationState {
|
|
||||||
825 | | fn default() -> Self {
|
|
||||||
826 | | Self::Initial
|
|
||||||
827 | | }
|
|
||||||
828 | | }
|
|
||||||
| |_____^
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#derivable_impls
|
|
||||||
help: replace the manual implementation with a derive attribute and mark the default variant
|
|
||||||
|
|
|
||||||
815 ~ #[derive(Default)]
|
|
||||||
816 ~ pub enum ConversationState {
|
|
||||||
817 ~ #[default]
|
|
||||||
818 ~ Initial,
|
|
||||||
819 | WaitingForUser,
|
|
||||||
...
|
|
||||||
825 |
|
|
||||||
826 ~
|
|
||||||
|
|
|
||||||
|
|
||||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
|
||||||
--> botserver/src/core/shared/memory_monitor.rs:500:36
|
|
||||||
|
|
|
||||||
500 | assert!(stats.rss_bytes > 0 || stats.virtual_bytes >= 0);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: because `0` is the minimum value for this type, this comparison is always true
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#absurd_extreme_comparisons
|
|
||||||
= note: `#[deny(clippy::absurd_extreme_comparisons)]` on by default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/csrf.rs:606:9
|
|
||||||
|
|
|
||||||
606 | config.token_expiry_minutes = 0;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::csrf::CsrfConfig { token_expiry_minutes: 0, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/csrf.rs:605:9
|
|
||||||
|
|
|
||||||
605 | let mut config = CsrfConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
= note: `#[warn(clippy::field_reassign_with_default)]` on by default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/dlp.rs:1079:9
|
|
||||||
|
|
|
||||||
1079 | config.scan_inbound = false;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::dlp::DlpConfig { scan_inbound: false, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/dlp.rs:1078:9
|
|
||||||
|
|
|
||||||
1078 | let mut config = DlpConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/encryption.rs:622:9
|
|
||||||
|
|
|
||||||
622 | config.envelope_encryption = true;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::encryption::EncryptionConfig { envelope_encryption: true, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/encryption.rs:621:9
|
|
||||||
|
|
|
||||||
621 | let mut config = EncryptionConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false
|
|
||||||
--> botserver/src/security/password.rs:720:17
|
|
||||||
|
|
|
||||||
720 | assert!(result.strength.score() >= 0);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: because `0` is the minimum value for this type, this comparison is always true
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#absurd_extreme_comparisons
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/security_monitoring.rs:1011:9
|
|
||||||
|
|
|
||||||
1011 | config.brute_force_threshold = 3;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::security_monitoring::SecurityMonitoringConfig { brute_force_threshold: 3, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/security_monitoring.rs:1010:9
|
|
||||||
|
|
|
||||||
1010 | let mut config = SecurityMonitoringConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/security_monitoring.rs:1033:9
|
|
||||||
|
|
|
||||||
1033 | config.brute_force_threshold = 2;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::security_monitoring::SecurityMonitoringConfig { brute_force_threshold: 2, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/security_monitoring.rs:1032:9
|
|
||||||
|
|
|
||||||
1032 | let mut config = SecurityMonitoringConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/security_monitoring.rs:1183:9
|
|
||||||
|
|
|
||||||
1183 | config.retention_hours = 0;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::security_monitoring::SecurityMonitoringConfig { retention_hours: 0, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/security_monitoring.rs:1182:9
|
|
||||||
|
|
|
||||||
1182 | let mut config = SecurityMonitoringConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/session.rs:715:9
|
|
||||||
|
|
|
||||||
715 | config.max_concurrent_sessions = 2;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::session::SessionConfig { max_concurrent_sessions: 2, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/session.rs:714:9
|
|
||||||
|
|
|
||||||
714 | let mut config = SessionConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/webhook.rs:701:9
|
|
||||||
|
|
|
||||||
701 | config.timestamp_tolerance_seconds = 60;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::webhook::WebhookConfig { timestamp_tolerance_seconds: 60, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/webhook.rs:700:9
|
|
||||||
|
|
|
||||||
700 | let mut config = WebhookConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/webhook.rs:732:9
|
|
||||||
|
|
|
||||||
732 | config.require_https = false;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::webhook::WebhookConfig { require_https: false, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/webhook.rs:731:9
|
|
||||||
|
|
|
||||||
731 | let mut config = WebhookConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/webhook.rs:742:9
|
|
||||||
|
|
|
||||||
742 | config.max_payload_size = 100;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::webhook::WebhookConfig { max_payload_size: 100, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/webhook.rs:741:9
|
|
||||||
|
|
|
||||||
741 | let mut config = WebhookConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: field assignment outside of initializer for an instance created with Default::default()
|
|
||||||
--> botserver/src/security/webhook.rs:871:9
|
|
||||||
|
|
|
||||||
871 | config.replay_window_seconds = 0;
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
note: consider initializing the variable with `security::webhook::WebhookConfig { replay_window_seconds: 0, ..Default::default() }` and removing relevant reassignments
|
|
||||||
--> botserver/src/security/webhook.rs:870:9
|
|
||||||
|
|
|
||||||
870 | let mut config = WebhookConfig::default();
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#field_reassign_with_default
|
|
||||||
|
|
||||||
warning: useless use of `vec!`
|
|
||||||
--> botserver/src/security/command_guard.rs:597:24
|
|
||||||
|
|
|
||||||
597 | let _allowed = vec![PathBuf::from("/tmp")];
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can use an array directly: `[PathBuf::from("/tmp")]`
|
|
||||||
|
|
|
||||||
= help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.92.0/index.html#useless_vec
|
|
||||||
= note: `#[warn(clippy::useless_vec)]` on by default
|
|
||||||
|
|
||||||
warning: comparison is useless due to type limits
|
|
||||||
--> botserver/src/core/shared/memory_monitor.rs:500:36
|
|
||||||
|
|
|
||||||
500 | assert!(stats.rss_bytes > 0 || stats.virtual_bytes >= 0);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: `#[warn(unused_comparisons)]` on by default
|
|
||||||
|
|
||||||
warning: comparison is useless due to type limits
|
|
||||||
--> botserver/src/security/password.rs:720:17
|
|
||||||
|
|
|
||||||
720 | assert!(result.strength.score() >= 0);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
warning: `botserver` (bin "botserver" test) generated 45 warnings (23 duplicates)
|
|
||||||
error: could not compile `botserver` (bin "botserver" test) due to 2 previous errors; 45 warnings emitted
|
|
||||||
308
docs/guides/tools-vs-bots.md
Normal file
308
docs/guides/tools-vs-bots.md
Normal file
|
|
@ -0,0 +1,308 @@
|
||||||
|
# Tools vs Bots: When to Use Each
|
||||||
|
|
||||||
|
**Chapter 4: Understanding the Difference Between Function Calls and AI Agents**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
General Bots provides two ways to extend your bot's capabilities:
|
||||||
|
- **TOOLs** - Simple functions with input/output
|
||||||
|
- **BOTs** - Intelligent AI agents that can reason and remember
|
||||||
|
|
||||||
|
Understanding when to use each is crucial for building efficient, cost-effective automation.
|
||||||
|
|
||||||
|
## Quick Comparison
|
||||||
|
|
||||||
|
| Feature | TOOL | BOT |
|
||||||
|
|---------|------|-----|
|
||||||
|
| **Purpose** | Data operations | Decision making |
|
||||||
|
| **Intelligence** | None (function) | Full LLM reasoning |
|
||||||
|
| **Speed** | Fast (10-100ms) | Slower (1-5 seconds) |
|
||||||
|
| **Cost** | Free | LLM tokens ($0.001-0.01) |
|
||||||
|
| **Input** | Structured data | Natural language |
|
||||||
|
| **Output** | Structured data | Conversational response |
|
||||||
|
| **Memory** | Stateless | Remembers context |
|
||||||
|
|
||||||
|
## Tools: The Function Approach
|
||||||
|
|
||||||
|
### What Are Tools?
|
||||||
|
|
||||||
|
Tools are **stateless functions** that perform specific operations:
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' Tool usage - direct function call
|
||||||
|
USE TOOL "check-order"
|
||||||
|
result = CALL TOOL "check-order" WITH order_id="12345"
|
||||||
|
' Returns: {"status": "delivered", "amount": 899}
|
||||||
|
```
|
||||||
|
|
||||||
|
### When to Use Tools
|
||||||
|
|
||||||
|
✅ **Perfect for:**
|
||||||
|
- Database queries
|
||||||
|
- API calls
|
||||||
|
- Calculations
|
||||||
|
- Data transformations
|
||||||
|
- Real-time operations
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' Examples of good tool usage
|
||||||
|
USE TOOL "get-weather"
|
||||||
|
weather = CALL TOOL "get-weather" WITH city="São Paulo"
|
||||||
|
|
||||||
|
USE TOOL "calculate-tax"
|
||||||
|
tax = CALL TOOL "calculate-tax" WITH amount=100, region="BR"
|
||||||
|
|
||||||
|
USE TOOL "send-email"
|
||||||
|
CALL TOOL "send-email" WITH to="user@example.com", subject="Order Confirmed"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tool Limitations
|
||||||
|
|
||||||
|
❌ **Cannot:**
|
||||||
|
- Make decisions
|
||||||
|
- Understand context
|
||||||
|
- Remember previous calls
|
||||||
|
- Handle ambiguous input
|
||||||
|
- Provide explanations
|
||||||
|
|
||||||
|
## Bots: The AI Agent Approach
|
||||||
|
|
||||||
|
### What Are Bots?
|
||||||
|
|
||||||
|
Bots are **intelligent agents** that can reason, remember, and make decisions:
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' Bot usage - conversational interaction
|
||||||
|
ADD BOT "order-specialist"
|
||||||
|
response = ASK BOT "order-specialist" ABOUT "Customer says order 12345 arrived damaged. What should we do?"
|
||||||
|
' Returns: Detailed analysis with reasoning and recommendation
|
||||||
|
```
|
||||||
|
|
||||||
|
### When to Use Bots
|
||||||
|
|
||||||
|
✅ **Perfect for:**
|
||||||
|
- Complex decision making
|
||||||
|
- Natural language understanding
|
||||||
|
- Multi-step reasoning
|
||||||
|
- Context-aware responses
|
||||||
|
- Customer service scenarios
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' Examples of good bot usage
|
||||||
|
ADD BOT "financial-advisor"
|
||||||
|
advice = ASK BOT "financial-advisor" ABOUT "Customer wants refund after 60 days but threatens legal action"
|
||||||
|
|
||||||
|
ADD BOT "technical-support"
|
||||||
|
solution = ASK BOT "technical-support" ABOUT "User can't login, tried password reset twice"
|
||||||
|
|
||||||
|
ADD BOT "content-moderator"
|
||||||
|
decision = ASK BOT "content-moderator" ABOUT "Review this user comment for policy violations"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bot Capabilities
|
||||||
|
|
||||||
|
✅ **Can:**
|
||||||
|
- Analyze complex situations
|
||||||
|
- Remember conversation history
|
||||||
|
- Use multiple tools internally
|
||||||
|
- Provide detailed explanations
|
||||||
|
- Handle edge cases
|
||||||
|
|
||||||
|
## Real-World Example: Order Processing
|
||||||
|
|
||||||
|
### Scenario
|
||||||
|
Customer contacts support: *"My laptop order #12345 arrived broken. I need this fixed immediately as I have a presentation tomorrow."*
|
||||||
|
|
||||||
|
### Tool-Only Approach (Limited)
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' Simple but inflexible
|
||||||
|
USE TOOL "check-order"
|
||||||
|
order = CALL TOOL "check-order" WITH order_id="12345"
|
||||||
|
|
||||||
|
USE TOOL "check-warranty"
|
||||||
|
warranty = CALL TOOL "check-warranty" WITH order_id="12345"
|
||||||
|
|
||||||
|
IF order.status = "delivered" AND warranty.valid = true THEN
|
||||||
|
TALK "You're eligible for replacement"
|
||||||
|
ELSE
|
||||||
|
TALK "Please contact manager"
|
||||||
|
END IF
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problems:**
|
||||||
|
- No understanding of urgency ("presentation tomorrow")
|
||||||
|
- No consideration of customer history
|
||||||
|
- Rigid, rule-based responses
|
||||||
|
- Cannot handle edge cases
|
||||||
|
|
||||||
|
### Bot Approach (Intelligent)
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' Intelligent and flexible
|
||||||
|
ADD BOT "support-specialist"
|
||||||
|
response = ASK BOT "support-specialist" ABOUT "Customer says laptop order #12345 arrived broken. They have presentation tomorrow and need immediate help."
|
||||||
|
```
|
||||||
|
|
||||||
|
**Bot's internal reasoning:**
|
||||||
|
1. Uses `check-order` tool → Order delivered 2 days ago, $1,299 laptop
|
||||||
|
2. Uses `check-warranty` tool → Premium warranty valid
|
||||||
|
3. Uses `customer-history` tool → VIP customer, 8 previous orders
|
||||||
|
4. **Analyzes urgency** → Presentation tomorrow = time-sensitive
|
||||||
|
5. **Considers options** → Replacement (2-day shipping) vs immediate refund for local purchase
|
||||||
|
6. **Makes recommendation** → "Given urgency and VIP status, authorize immediate refund so customer can buy locally, plus expedited replacement as backup"
|
||||||
|
|
||||||
|
## Hybrid Approach: Best of Both Worlds
|
||||||
|
|
||||||
|
**Recommended pattern: Bots use Tools internally**
|
||||||
|
|
||||||
|
```basic
|
||||||
|
' support-specialist.bas - Bot implementation
|
||||||
|
USE TOOL "check-order"
|
||||||
|
USE TOOL "check-warranty"
|
||||||
|
USE TOOL "customer-history"
|
||||||
|
USE TOOL "inventory-check"
|
||||||
|
USE KB "support-policies"
|
||||||
|
|
||||||
|
WHEN ASKED ABOUT order_issue DO
|
||||||
|
' Gather data using tools (fast, cheap)
|
||||||
|
order = CALL TOOL "check-order" WITH order_id
|
||||||
|
warranty = CALL TOOL "check-warranty" WITH order_id
|
||||||
|
customer = CALL TOOL "customer-history" WITH customer_id
|
||||||
|
|
||||||
|
' Apply AI reasoning (intelligent, contextual)
|
||||||
|
urgency = ANALYZE urgency FROM user_message
|
||||||
|
customer_value = CALCULATE value FROM customer.total_orders
|
||||||
|
|
||||||
|
IF urgency = "high" AND customer_value = "vip" THEN
|
||||||
|
recommendation = "Expedited resolution with manager approval"
|
||||||
|
ELSE IF warranty.type = "premium" THEN
|
||||||
|
recommendation = "Standard replacement process"
|
||||||
|
ELSE
|
||||||
|
recommendation = "Store credit or repair option"
|
||||||
|
END IF
|
||||||
|
|
||||||
|
RETURN detailed_response WITH reasoning AND next_steps
|
||||||
|
END WHEN
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Guidelines
|
||||||
|
|
||||||
|
### Tool Performance
|
||||||
|
- **Latency:** 10-100ms
|
||||||
|
- **Cost:** $0 (no LLM calls)
|
||||||
|
- **Throughput:** 1000+ operations/second
|
||||||
|
- **Use for:** High-frequency, simple operations
|
||||||
|
|
||||||
|
### Bot Performance
|
||||||
|
- **Latency:** 1-5 seconds
|
||||||
|
- **Cost:** $0.001-0.01 per interaction
|
||||||
|
- **Throughput:** 10-100 interactions/second
|
||||||
|
- **Use for:** Complex, high-value decisions
|
||||||
|
|
||||||
|
## Decision Framework
|
||||||
|
|
||||||
|
### Use TOOL when:
|
||||||
|
1. **Operation is deterministic** - Same input always produces same output
|
||||||
|
2. **Speed is critical** - Real-time responses needed
|
||||||
|
3. **Cost matters** - High-frequency operations
|
||||||
|
4. **Data is structured** - Clear input/output format
|
||||||
|
|
||||||
|
### Use BOT when:
|
||||||
|
1. **Context matters** - Previous conversation affects response
|
||||||
|
2. **Reasoning required** - Multiple factors to consider
|
||||||
|
3. **Natural language input** - Ambiguous or conversational requests
|
||||||
|
4. **Edge cases exist** - Situations requiring judgment
|
||||||
|
|
||||||
|
### Use HYBRID when:
|
||||||
|
1. **Complex workflows** - Multiple steps with decision points
|
||||||
|
2. **Data + Intelligence** - Need both fast data access and smart reasoning
|
||||||
|
3. **Scalability important** - Balance cost and capability
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Pattern 1: Data Retrieval
|
||||||
|
```basic
|
||||||
|
' TOOL: Simple lookup
|
||||||
|
price = CALL TOOL "get-price" WITH product_id="laptop-123"
|
||||||
|
|
||||||
|
' BOT: Contextual pricing
|
||||||
|
ADD BOT "pricing-advisor"
|
||||||
|
quote = ASK BOT "pricing-advisor" ABOUT "Customer wants bulk discount for 50 laptops, they're a returning enterprise client"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 2: Validation
|
||||||
|
```basic
|
||||||
|
' TOOL: Rule-based validation
|
||||||
|
valid = CALL TOOL "validate-email" WITH email="user@domain.com"
|
||||||
|
|
||||||
|
' BOT: Contextual validation
|
||||||
|
ADD BOT "content-reviewer"
|
||||||
|
assessment = ASK BOT "content-reviewer" ABOUT "Is this product review appropriate for our family-friendly site?"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pattern 3: Workflow Orchestration
|
||||||
|
```basic
|
||||||
|
' Hybrid: Bot coordinates, tools execute
|
||||||
|
ORCHESTRATE WORKFLOW "order-processing"
|
||||||
|
STEP 1: CALL TOOL "validate-payment" WITH payment_info
|
||||||
|
STEP 2: BOT "fraud-detector" ANALYZES transaction_pattern
|
||||||
|
STEP 3: CALL TOOL "reserve-inventory" WITH product_id
|
||||||
|
STEP 4: BOT "shipping-optimizer" SELECTS best_carrier
|
||||||
|
STEP 5: CALL TOOL "send-confirmation" WITH order_details
|
||||||
|
END WORKFLOW
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### 1. Start Simple, Add Intelligence
|
||||||
|
```basic
|
||||||
|
' Phase 1: Tool-based (fast to implement)
|
||||||
|
result = CALL TOOL "process-refund" WITH order_id, amount
|
||||||
|
|
||||||
|
' Phase 2: Add bot intelligence (when complexity grows)
|
||||||
|
ADD BOT "refund-specialist"
|
||||||
|
decision = ASK BOT "refund-specialist" ABOUT "Customer wants refund but policy expired, they're threatening bad review"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Cache Bot Responses
|
||||||
|
```basic
|
||||||
|
' Expensive bot call
|
||||||
|
ADD BOT "product-recommender"
|
||||||
|
recommendations = ASK BOT "product-recommender" ABOUT "Best laptop for gaming under $1000"
|
||||||
|
|
||||||
|
' Cache result for similar queries
|
||||||
|
REMEMBER "gaming-laptop-under-1000" AS recommendations
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Fallback Patterns
|
||||||
|
```basic
|
||||||
|
' Try bot first, fallback to tool
|
||||||
|
TRY
|
||||||
|
response = ASK BOT "smart-assistant" ABOUT user_query
|
||||||
|
CATCH bot_error
|
||||||
|
' Fallback to simple tool
|
||||||
|
response = CALL TOOL "keyword-search" WITH query=user_query
|
||||||
|
END TRY
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
**Tools** are your **workhorses** - fast, reliable, cost-effective for data operations.
|
||||||
|
|
||||||
|
**Bots** are your **brain trust** - intelligent, contextual, perfect for complex decisions.
|
||||||
|
|
||||||
|
**Hybrid approach** gives you the best of both: use tools for speed and bots for intelligence.
|
||||||
|
|
||||||
|
Choose based on your specific needs:
|
||||||
|
- Need speed? → Tool
|
||||||
|
- Need intelligence? → Bot
|
||||||
|
- Need both? → Bot that uses tools
|
||||||
|
|
||||||
|
The key is understanding that **tools and bots complement each other** - they're not competing solutions, but different tools for different jobs in your AI automation toolkit.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Next:** [Chapter 5: Building Multi-Agent Workflows](workflows.md)
|
||||||
|
|
@ -49,7 +49,7 @@ impl LocalJwtAuthProvider {
|
||||||
let roles: Vec<Role> = claims
|
let roles: Vec<Role> = claims
|
||||||
.roles
|
.roles
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|r| r.iter().map(|s| Role::from_str(s)).collect())
|
.map(|r| r.iter().filter_map(|s| Role::from_str(s).ok()).collect())
|
||||||
.unwrap_or_else(|| vec![Role::User]);
|
.unwrap_or_else(|| vec![Role::User]);
|
||||||
|
|
||||||
let mut user = AuthenticatedUser::new(user_id, username).with_roles(roles);
|
let mut user = AuthenticatedUser::new(user_id, username).with_roles(roles);
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ use axum::{
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::OnceLock;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::OnceLock;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
|
|
@ -18,7 +18,9 @@ static PROTECTION_MANAGER: OnceLock<Arc<RwLock<ProtectionManager>>> = OnceLock::
|
||||||
|
|
||||||
fn get_manager() -> &'static Arc<RwLock<ProtectionManager>> {
|
fn get_manager() -> &'static Arc<RwLock<ProtectionManager>> {
|
||||||
PROTECTION_MANAGER.get_or_init(|| {
|
PROTECTION_MANAGER.get_or_init(|| {
|
||||||
Arc::new(RwLock::new(ProtectionManager::new(ProtectionConfig::default())))
|
Arc::new(RwLock::new(ProtectionManager::new(
|
||||||
|
ProtectionConfig::default(),
|
||||||
|
)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,10 +75,7 @@ pub fn configure_protection_routes() -> Router<Arc<AppState>> {
|
||||||
"/api/security/protection/:tool/status",
|
"/api/security/protection/:tool/status",
|
||||||
get(get_tool_status),
|
get(get_tool_status),
|
||||||
)
|
)
|
||||||
.route(
|
.route("/api/security/protection/:tool/install", post(install_tool))
|
||||||
"/api/security/protection/:tool/install",
|
|
||||||
post(install_tool),
|
|
||||||
)
|
|
||||||
.route(
|
.route(
|
||||||
"/api/security/protection/:tool/uninstall",
|
"/api/security/protection/:tool/uninstall",
|
||||||
post(uninstall_tool),
|
post(uninstall_tool),
|
||||||
|
|
@ -109,7 +108,7 @@ pub fn configure_protection_routes() -> Router<Arc<AppState>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_tool(tool_name: &str) -> Result<ProtectionTool, (StatusCode, Json<ApiResponse<()>>)> {
|
fn parse_tool(tool_name: &str) -> Result<ProtectionTool, (StatusCode, Json<ApiResponse<()>>)> {
|
||||||
ProtectionTool::from_str(tool_name).ok_or_else(|| {
|
ProtectionTool::from_str(tool_name).map_err(|_| {
|
||||||
(
|
(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Json(ApiResponse::error(format!("Unknown tool: {tool_name}"))),
|
Json(ApiResponse::error(format!("Unknown tool: {tool_name}"))),
|
||||||
|
|
@ -117,7 +116,8 @@ fn parse_tool(tool_name: &str) -> Result<ProtectionTool, (StatusCode, Json<ApiRe
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_all_status() -> Result<Json<ApiResponse<AllStatusResponse>>, (StatusCode, Json<ApiResponse<()>>)> {
|
async fn get_all_status(
|
||||||
|
) -> Result<Json<ApiResponse<AllStatusResponse>>, (StatusCode, Json<ApiResponse<()>>)> {
|
||||||
let manager = get_manager().read().await;
|
let manager = get_manager().read().await;
|
||||||
let status_map = manager.get_all_status().await;
|
let status_map = manager.get_all_status().await;
|
||||||
let tools: Vec<ToolStatus> = status_map.into_values().collect();
|
let tools: Vec<ToolStatus> = status_map.into_values().collect();
|
||||||
|
|
@ -135,7 +135,10 @@ async fn get_tool_status(
|
||||||
Ok(status) => Ok(Json(ApiResponse::success(status))),
|
Ok(status) => Ok(Json(ApiResponse::success(status))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to get tool status");
|
warn!(error = %e, "Failed to get tool status");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to get tool status"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to get tool status")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -153,7 +156,10 @@ async fn install_tool(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to install tool");
|
warn!(error = %e, "Failed to install tool");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to install tool"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to install tool")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +190,10 @@ async fn start_service(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to start service");
|
warn!(error = %e, "Failed to start service");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to start service"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to start service")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -202,7 +211,10 @@ async fn stop_service(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to stop service");
|
warn!(error = %e, "Failed to stop service");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to stop service"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to stop service")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +232,10 @@ async fn enable_service(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to enable service");
|
warn!(error = %e, "Failed to enable service");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to enable service"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to enable service")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +253,10 @@ async fn disable_service(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to disable service");
|
warn!(error = %e, "Failed to disable service");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to disable service"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to disable service")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +271,10 @@ async fn run_scan(
|
||||||
Ok(result) => Ok(Json(ApiResponse::success(result))),
|
Ok(result) => Ok(Json(ApiResponse::success(result))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to run scan");
|
warn!(error = %e, "Failed to run scan");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to run scan"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to run scan")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -268,7 +289,10 @@ async fn get_report(
|
||||||
Ok(report) => Ok(Json(ApiResponse::success(report))),
|
Ok(report) => Ok(Json(ApiResponse::success(report))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to get report");
|
warn!(error = %e, "Failed to get report");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to get report"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to get report")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +310,10 @@ async fn update_definitions(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to update definitions");
|
warn!(error = %e, "Failed to update definitions");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to update definitions"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to update definitions")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -313,17 +340,25 @@ async fn toggle_auto(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to toggle auto setting");
|
warn!(error = %e, "Failed to toggle auto setting");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to toggle auto setting"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to toggle auto setting")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_quarantine() -> Result<Json<ApiResponse<Vec<super::lmd::QuarantinedFile>>>, (StatusCode, Json<ApiResponse<()>>)> {
|
async fn get_quarantine(
|
||||||
|
) -> Result<Json<ApiResponse<Vec<super::lmd::QuarantinedFile>>>, (StatusCode, Json<ApiResponse<()>>)>
|
||||||
|
{
|
||||||
match super::lmd::list_quarantined().await {
|
match super::lmd::list_quarantined().await {
|
||||||
Ok(files) => Ok(Json(ApiResponse::success(files))),
|
Ok(files) => Ok(Json(ApiResponse::success(files))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to get quarantine list");
|
warn!(error = %e, "Failed to get quarantine list");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to get quarantine list"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to get quarantine list")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -338,7 +373,10 @@ async fn remove_from_quarantine(
|
||||||
}))),
|
}))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(error = %e, "Failed to restore file from quarantine");
|
warn!(error = %e, "Failed to restore file from quarantine");
|
||||||
Err((StatusCode::INTERNAL_SERVER_ERROR, Json(ApiResponse::error("Failed to restore file from quarantine"))))
|
Err((
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
Json(ApiResponse::error("Failed to restore file from quarantine")),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue