Compare commits

..

2 commits

Author SHA1 Message Date
aaba2976b4
Update .gitmodules 2026-02-06 17:11:32 -03:00
116f11cb42 Update all submodules to latest commits
Includes botui fix for 404 errors with bot name prefixes:
- Removed root-level static routes that conflicted with bot prefixes
- All static assets now properly served under /suite/ path
- Fixes /edu/suite/js/api-client.js and related assets
2026-02-06 16:30:42 -03:00
29 changed files with 620 additions and 1717 deletions

12
.gitignore vendored
View file

@ -30,17 +30,7 @@ botserver-installers/*
!botserver-installers/.gitkeep
botserver-stack
TODO*
work
# Lock file (regenerated from Cargo.toml)
Cargo.lock
.kiro
config
# Playwright
node_modules/
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/

22
.gitmodules vendored
View file

@ -1,42 +1,42 @@
[submodule "botapp"]
path = botapp
url = https://alm.pragmatismo.com.br/GeneralBots/botapp.git
url = https://github.com/GeneralBots/botapp.git
[submodule "botserver"]
path = botserver
url = https://alm.pragmatismo.com.br/GeneralBots/botserver.git
url = https://github.com/GeneralBots/botserver.git
[submodule "botlib"]
path = botlib
url = https://alm.pragmatismo.com.br/GeneralBots/botlib.git
url = https://github.com/GeneralBots/botlib.git
[submodule "botui"]
path = botui
url = https://alm.pragmatismo.com.br/GeneralBots/botui.git
url = https://github.com/GeneralBots/botui.git
[submodule "botbook"]
path = botbook
url = https://alm.pragmatismo.com.br/GeneralBots/botbook.git
url = https://github.com/GeneralBots/botbook.git
[submodule "bottest"]
path = bottest
url = https://alm.pragmatismo.com.br/GeneralBots/bottest.git
url = https://github.com/GeneralBots/bottest.git
[submodule "botdevice"]
path = botdevice
url = https://alm.pragmatismo.com.br/GeneralBots/botdevice.git
url = https://github.com/GeneralBots/botdevice.git
[submodule "botmodels"]
path = botmodels
url = https://alm.pragmatismo.com.br/GeneralBots/botmodels.git
url = https://github.com/GeneralBots/botmodels.git
[submodule "botplugin"]
path = botplugin
url = https://alm.pragmatismo.com.br/GeneralBots/botplugin.git
url = https://github.com/GeneralBots/botplugin.git
[submodule "bottemplates"]
path = bottemplates
url = https://alm.pragmatismo.com.br/GeneralBots/bottemplates.git
url = https://github.com/GeneralBots/bottemplates.git
[submodule ".github"]
path = .github
url = https://alm.pragmatismo.com.br/GeneralBots/.github.git
url = https://github.com/GeneralBots/.github.git

9
.idea/gb.iml generated
View file

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="botserver-installers">
<CLASSES>
<root url="jar://$PROJECT_DIR$/botserver/botserver-installers/llama-b7345-bin-ubuntu-x64.zip!/" />
<root url="jar://$PROJECT_DIR$/botserver/botserver-installers/vault_1.15.4_linux_amd64.zip!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

6
.idea/misc.xml generated
View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated
View file

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/gb.iml" filepath="$PROJECT_DIR$/.idea/gb.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated
View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

52
.idea/workspace.xml generated
View file

@ -1,52 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="32fd08b0-7933-467d-9a46-1a53fd2da15c" name="Changes" comment="">
<change beforePath="$PROJECT_DIR$/botserver" beforeDir="false" afterPath="$PROJECT_DIR$/botserver" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"associatedIndex": 1
}]]></component>
<component name="ProjectId" id="38qdWTFkX8Nem4LzgigXpAycSN7" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"ModuleVcsDetector.initialDetectionPerformed": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"RunOnceActivity.git.unshallow": "true",
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
"git-widget-placeholder": "main",
"last_opened_file_path": "/home/rodriguez/src/gb",
"vue.rearranger.settings.migration": "true"
}
}]]></component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-jdk-30f59d01ecdd-2fc7cc6b9a17-intellij.indexing.shared.core-IU-253.30387.90" />
</set>
</attachedChunks>
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="32fd08b0-7933-467d-9a46-1a53fd2da15c" name="Changes" comment="" />
<created>1769531070022</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1769531070022</updated>
<workItem from="1769531115917" duration="176000" />
</task>
<servers />
</component>
</project>

View file

@ -1,198 +0,0 @@
{
"languages": {
"typescript": {
"name": "typescript-language-server",
"command": "typescript-language-server",
"args": [
"--stdio"
],
"file_extensions": [
"ts",
"js",
"tsx",
"jsx"
],
"project_patterns": [
"package.json",
"tsconfig.json"
],
"exclude_patterns": [
"**/node_modules/**",
"**/dist/**"
],
"multi_workspace": false,
"initialization_options": {
"preferences": {
"disableSuggestions": false
}
},
"request_timeout_secs": 60
},
"python": {
"name": "pyright",
"command": "pyright-langserver",
"args": [
"--stdio"
],
"file_extensions": [
"py"
],
"project_patterns": [
"pyproject.toml",
"setup.py",
"requirements.txt",
"pyrightconfig.json"
],
"exclude_patterns": [
"**/__pycache__/**",
"**/venv/**",
"**/.venv/**",
"**/.pytest_cache/**"
],
"multi_workspace": false,
"initialization_options": {},
"request_timeout_secs": 60
},
"rust": {
"name": "rust-analyzer",
"command": "rust-analyzer",
"args": [],
"file_extensions": [
"rs"
],
"project_patterns": [
"Cargo.toml"
],
"exclude_patterns": [
"**/target/**"
],
"multi_workspace": false,
"initialization_options": {
"cargo": {
"buildScripts": {
"enable": true
}
},
"diagnostics": {
"enable": true,
"enableExperimental": true
},
"workspace": {
"symbol": {
"search": {
"scope": "workspace"
}
}
}
},
"request_timeout_secs": 60
},
"java": {
"name": "jdtls",
"command": "jdtls",
"args": [],
"file_extensions": [
"java"
],
"project_patterns": [
"pom.xml",
"build.gradle",
"build.gradle.kts",
".project"
],
"exclude_patterns": [
"**/target/**",
"**/build/**",
"**/.gradle/**"
],
"multi_workspace": false,
"initialization_options": {
"settings": {
"java": {
"compile": {
"nullAnalysis": {
"mode": "automatic"
}
},
"configuration": {
"annotationProcessing": {
"enabled": true
}
}
}
}
},
"request_timeout_secs": 60
},
"ruby": {
"name": "solargraph",
"command": "solargraph",
"args": [
"stdio"
],
"file_extensions": [
"rb"
],
"project_patterns": [
"Gemfile",
"Rakefile"
],
"exclude_patterns": [
"**/vendor/**",
"**/tmp/**"
],
"multi_workspace": false,
"initialization_options": {},
"request_timeout_secs": 60
},
"go": {
"name": "gopls",
"command": "gopls",
"args": [],
"file_extensions": [
"go"
],
"project_patterns": [
"go.mod",
"go.sum"
],
"exclude_patterns": [
"**/vendor/**"
],
"multi_workspace": false,
"initialization_options": {
"usePlaceholders": true,
"completeUnimported": true
},
"request_timeout_secs": 60
},
"cpp": {
"name": "clangd",
"command": "clangd",
"args": [
"--background-index"
],
"file_extensions": [
"cpp",
"cc",
"cxx",
"c",
"h",
"hpp",
"hxx"
],
"project_patterns": [
"CMakeLists.txt",
"compile_commands.json",
"Makefile"
],
"exclude_patterns": [
"**/build/**",
"**/cmake-build-**/**"
],
"multi_workspace": false,
"initialization_options": {},
"request_timeout_secs": 60
}
}
}

View file

@ -1,7 +0,0 @@
{
"languages": {
"Rust": {
"enable_language_server": false,
},
},
}

View file

@ -1,133 +1,140 @@
#!/bin/bash
#
# DEPENDENCIES.sh - Runtime Dependencies for General Bots
#
# This script installs all system packages required to RUN botserver binary.
# These are the minimal dependencies needed for production deployment.
#
# Usage: sudo ./DEPENDENCIES.sh
#
#!/bin/bash
#
# DEPENDENCIES.sh - Runtime Dependencies for General Bots
#
# This script installs all system packages required to RUN botserver binary.
# These are the minimal dependencies needed for production deployment.
#
# Usage: sudo ./DEPENDENCIES.sh
#
set -e
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} General Bots Runtime Dependencies${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} General Bots Runtime Dependencies${NC}"
echo -e "${GREEN}========================================${NC}"
# Check root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Error: Run as root (use sudo)${NC}"
exit 1
fi
# Check root
if [ "$EUID" -ne 0 ]; then
echo -e "${RED}Error: Run as root (use sudo)${NC}"
exit 1
fi
# Detect OS
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
else
echo -e "${RED}Error: Cannot detect OS${NC}"
exit 1
fi
# Detect OS
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$ID
else
echo -e "${RED}Error: Cannot detect OS${NC}"
exit 1
fi
echo -e "${YELLOW}OS: $OS${NC}"
echo -e "${YELLOW}OS: $OS${NC}"
install_debian_ubuntu() {
apt-get install -y \
libpq5 \
libssl3 \
liblzma5 \
zlib1g \
ca-certificates \
curl \
wget \
libclang1 \
pkg-config \
snapd
install_debian_ubuntu() {
apt-get update
apt-get install -y \
libpq5 \
libssl3 \
liblzma5 \
zlib1g \
ca-certificates \
curl \
wget \
libabseil20210324 \
libclang1 \
pkg-config \
snapd
# LXC for containers
snap install lxd || apt-get install -y lxd || true
# Initialize LXD
if command -v lxd &> /dev/null && ! lxc list &> /dev/null 2>&1; then
lxd init --auto || true
fi
}
install_fedora_rhel() {
dnf install -y \
libpq \
openssl-libs \
xz-libs \
zlib \
ca-certificates \
curl \
wget \
abseil-cpp \
clang-libs \
pkgconf-pkg-config \
lxc \
lxc-templates
}
}
install_arch() {
pacman -Sy --noconfirm \
postgresql-libs \
openssl \
xz \
zlib \
ca-certificates \
curl \
wget \
abseil-cpp \
clang \
pkgconf \
lxc
}
install_fedora_rhel() {
dnf install -y \
libpq \
openssl-libs \
xz-libs \
zlib \
ca-certificates \
curl \
wget \
abseil-cpp \
clang-libs \
pkgconf-pkg-config \
lxc \
lxc-templates
}
install_alpine() {
apk add --no-cache \
libpq \
openssl \
xz-libs \
zlib \
ca-certificates \
curl \
wget \
abseil-cpp \
clang \
pkgconf \
lxc
}
install_arch() {
pacman -Sy --noconfirm \
postgresql-libs \
openssl \
xz \
zlib \
ca-certificates \
curl \
wget \
abseil-cpp \
clang \
pkgconf \
lxc
}
case $OS in
ubuntu|debian|linuxmint|pop)
install_debian_ubuntu
;;
fedora|rhel|centos|rocky|almalinux)
install_fedora_rhel
;;
arch|manjaro)
install_arch
;;
alpine)
install_alpine
;;
*)
echo -e "${RED}Unsupported OS: $OS${NC}"
echo "Required libraries:"
echo " - libpq (PostgreSQL client)"
echo " - libssl (OpenSSL)"
echo " - liblzma (XZ compression)"
echo " - zlib (compression)"
echo " - abseil-cpp (Google Abseil)"
echo " - clang (LLVM runtime)"
echo " - LXC (containers)"
exit 1
;;
esac
install_alpine() {
apk add --no-cache \
libpq \
openssl \
xz-libs \
zlib \
ca-certificates \
curl \
wget \
abseil-cpp \
clang \
pkgconf \
lxc
}
case $OS in
ubuntu|debian|linuxmint|pop)
install_debian_ubuntu
;;
fedora|rhel|centos|rocky|almalinux)
install_fedora_rhel
;;
arch|manjaro)
install_arch
;;
alpine)
install_alpine
;;
*)
echo -e "${RED}Unsupported OS: $OS${NC}"
echo "Required libraries:"
echo " - libpq (PostgreSQL client)"
echo " - libssl (OpenSSL)"
echo " - liblzma (XZ compression)"
echo " - zlib (compression)"
echo " - abseil-cpp (Google Abseil)"
echo " - clang (LLVM runtime)"
echo " - LXC (containers)"
exit 1
;;
esac
echo -e "${GREEN}Runtime dependencies installed!${NC}"
echo ""
echo "You can now run:"
echo " ./botserver"
echo -e "${GREEN}Runtime dependencies installed!${NC}"
echo ""
echo "You can now run:"
echo " ./botserver"

383
PROMPT.md Normal file
View file

@ -0,0 +1,383 @@
# General Bots Workspace - Master Development Guide
**Version:** 6.2.0 - DO NOT CHANGE
**Project:** General Bots Workspace (Rust Monorepo)
---
## 📁 WORKSPACE STRUCTURE
| Crate | Purpose | Port | Tech Stack |
|-------|---------|------|------------|
| **botserver** | Main API server, business logic | 8088 | Axum, Diesel, Rhai BASIC |
| **botui** | Web UI server (dev) + proxy | 3000 | Axum, HTML/HTMX/CSS |
| **botapp** | Desktop app wrapper | - | Tauri 2 |
| **botlib** | Shared library | - | Core types, errors |
| **botbook** | Documentation | - | mdBook |
| **bottest** | Integration tests | - | tokio-test |
| **botdevice** | IoT/Device support | - | Rust |
| **botmodels** | Data models visualization | - | - |
| **botplugin** | Browser extension | - | JS |
### Key Paths
- **Binary:** `target/debug/botserver`
- **Run from:** `botserver/` directory
- **Env file:** `botserver/.env`
- **Stack:** `botserver/botserver-stack/`
- **UI Files:** `botui/ui/suite/`
---
## 🔥 ERROR FIXING WORKFLOW
### Mode 1: OFFLINE Batch Fix (PREFERRED)
When given error output:
```
1. Read ENTIRE error list first
2. Group errors by file
3. For EACH file with errors:
a. View file → understand context
b. Fix ALL errors in that file
c. Write once with all fixes
4. Move to next file
5. REPEAT until ALL errors addressed
6. ONLY THEN → verify with build/diagnostics
```
**NEVER run cargo build/check/clippy DURING fixing**
**Fix ALL errors OFFLINE first, verify ONCE at the end**
### Mode 2: Interactive Loop
```
LOOP UNTIL (0 warnings AND 0 errors):
1. Run diagnostics → pick file with issues
2. Read entire file
3. Fix ALL issues in that file
4. Write file once with all fixes
5. Verify with diagnostics
6. CONTINUE LOOP
END LOOP
```
### Common Error Patterns
| Error | Fix |
|-------|-----|
| `expected i64, found u64` | `value as i64` |
| `expected Option<T>, found T` | `Some(value)` |
| `expected T, found Option<T>` | `value.unwrap_or(default)` |
| `cannot multiply f32 by f64` | `f64::from(f32_val) * f64_val` |
| `no field X on type Y` | Check struct definition |
| `no variant X found` | Check enum definition |
| `function takes N arguments` | Match function signature |
| `cannot find function` | Add missing function or fix import |
| `unused variable` | Delete or use with `..` in patterns |
| `unused import` | Delete the import line |
| `cannot move out of X because borrowed` | Use scoping `{ }` to limit borrow |
---
## 🧠 MEMORY MANAGEMENT
When compilation fails due to memory issues (process "Killed"):
```bash
pkill -9 cargo; pkill -9 rustc; pkill -9 botserver
CARGO_BUILD_JOBS=1 cargo check -p botserver 2>&1 | tail -200
```
---
## 📏 FILE SIZE LIMITS - MANDATORY
### Maximum 1000 Lines Per File
When a file grows beyond this limit:
1. **Identify logical groups** - Find related functions
2. **Create subdirectory module** - e.g., `handlers/`
3. **Split by responsibility:**
- `crud.rs` - Create, Read, Update, Delete
- `ai.rs` - AI/ML handlers
- `export.rs` - Export/import
- `validation.rs` - Validation
- `mod.rs` - Re-exports
4. **Keep files focused** - Single responsibility
5. **Update mod.rs** - Re-export all public items
**NEVER let a single file exceed 1000 lines - split proactively at 800 lines**
---
## 🚀 PERFORMANCE & SIZE STANDARDS
### Binary Size Optimization
- **Release Profile**: Always maintain `opt-level = "z"`, `lto = true`, `codegen-units = 1`, `strip = true`, `panic = "abort"`.
- **Dependencies**:
- Run `cargo tree --duplicates` weekly to find and resolve duplicate versions.
- Run `cargo machete` to remove unused dependencies.
- Use `default-features = false` and explicitly opt-in to needed features.
### Memory Optimization
- **Strings**: Prefer `&str` over `String` where possible. Use `Cow<str>` for conditional ownership.
- **Collections**: Use `Vec::with_capacity` when size is known. Consider `SmallVec` for hot paths.
- **Allocations**: Minimize heap allocations in hot paths.
### Linting & Code Quality
- **Clippy**: Code MUST pass `cargo clippy --all-targets --all-features` with **0 warnings**.
- **No Allow**: Do not use `#[allow(clippy::...)]` unless absolutely necessary and documented. Fix the underlying issue.
---
## 🔐 SECURITY DIRECTIVES - MANDATORY
### Error Handling - NO PANICS IN PRODUCTION
```rust
// ❌ FORBIDDEN
value.unwrap()
value.expect("message")
panic!("error")
todo!()
unimplemented!()
// ✅ REQUIRED
value?
value.ok_or_else(|| Error::NotFound)?
value.unwrap_or_default()
value.unwrap_or_else(|e| { log::error!("{}", e); default })
if let Some(v) = value { ... }
match value { Ok(v) => v, Err(e) => return Err(e.into()) }
```
### Command Execution - USE SafeCommand
```rust
// ❌ FORBIDDEN
Command::new("some_command").arg(user_input).output()
// ✅ REQUIRED
use crate::security::command_guard::SafeCommand;
SafeCommand::new("allowed_command")?
.arg("safe_arg")?
.execute()
```
### Error Responses - USE ErrorSanitizer
```rust
// ❌ FORBIDDEN
Json(json!({ "error": e.to_string() }))
format!("Database error: {}", e)
// ✅ REQUIRED
use crate::security::error_sanitizer::log_and_sanitize;
let sanitized = log_and_sanitize(&e, "context", None);
(StatusCode::INTERNAL_SERVER_ERROR, sanitized)
```
### SQL - USE sql_guard
```rust
// ❌ FORBIDDEN
format!("SELECT * FROM {}", user_table)
// ✅ REQUIRED
use crate::security::sql_guard::{sanitize_identifier, validate_table_name};
let safe_table = sanitize_identifier(&user_table);
validate_table_name(&safe_table)?;
```
---
## ❌ ABSOLUTE PROHIBITIONS
```
❌ NEVER use .unwrap() or .expect() in production code (tests OK)
❌ NEVER use panic!(), todo!(), unimplemented!()
❌ NEVER use Command::new() directly - use SafeCommand
❌ NEVER return raw error strings to HTTP clients
❌ NEVER use #[allow()] in source code - FIX the code instead
❌ NEVER add lint exceptions to Cargo.toml - FIX the code instead
❌ NEVER use _ prefix for unused variables - DELETE or USE them
❌ NEVER leave unused imports or dead code
❌ NEVER add comments - code must be self-documenting
❌ NEVER modify Cargo.toml lints section!
❌ NEVER use CDN links - all assets must be local
```
---
## ✅ MANDATORY CODE PATTERNS
### Use Self in Impl Blocks
```rust
impl MyStruct {
fn new() -> Self { Self { } } // ✅ Not MyStruct
}
```
### Derive Eq with PartialEq
```rust
#[derive(PartialEq, Eq)] // ✅ Always both
struct MyStruct { }
```
### Inline Format Args
```rust
format!("Hello {name}") // ✅ Not format!("{}", name)
```
### Combine Match Arms
```rust
match x {
A | B => do_thing(), // ✅ Combine identical arms
C => other(),
}
```
---
## 🖥️ UI Architecture (botui + botserver)
### Two Servers During Development
| Server | Port | Purpose |
|--------|------|---------|
| **botui** | 3000 | Serves UI files + proxies API to botserver |
| **botserver** | 8088 | Backend API + embedded UI fallback |
### How It Works
```
Browser → localhost:3000 → botui (serves HTML/CSS/JS)
→ /api/* proxied to botserver:8088
→ /suite/* served from botui/ui/suite/
```
### Adding New Suite Apps
1. Create folder: `botui/ui/suite/<appname>/`
2. Add to `SUITE_DIRS` in `botui/src/ui_server/mod.rs`
3. Rebuild botui: `cargo build -p botui`
4. Add menu entry in `botui/ui/suite/index.html`
### Hot Reload
- **UI files (HTML/CSS/JS)**: Edit & refresh browser (no restart)
- **botui Rust code**: Rebuild + restart botui
- **botserver Rust code**: Rebuild + restart botserver
### Production (Single Binary)
When `botui/ui/suite/` folder not found, botserver uses **embedded UI** compiled into binary via `rust-embed`.
---
## 🎨 FRONTEND STANDARDS
### HTMX-First Approach
- Use HTMX to minimize JavaScript
- Server returns HTML fragments, not JSON
- Use `hx-get`, `hx-post`, `hx-target`, `hx-swap`
- WebSocket via htmx-ws extension
### Local Assets Only - NO CDN
```html
<!-- ✅ CORRECT -->
<script src="js/vendor/htmx.min.js"></script>
<!-- ❌ WRONG -->
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
```
### Vendor Libraries Location
```
ui/suite/js/vendor/
├── htmx.min.js
├── htmx-ws.js
├── marked.min.js
└── gsap.min.js
```
---
## 📋 PROJECT-SPECIFIC PROMPTS
Each crate has its own PROMPT.md with specific guidelines:
| Crate | PROMPT.md Location | Focus |
|-------|-------------------|-------|
| botserver | `botserver/PROMPT.md` | API, security, Rhai BASIC |
| botui | `botui/PROMPT.md` | UI, HTMX, CSS design system |
| botapp | `botapp/PROMPT.md` | Tauri, desktop features |
| botlib | `botlib/PROMPT.md` | Shared types, errors |
| botbook | `botbook/PROMPT.md` | Documentation, mdBook |
| bottest | `bottest/PROMPT.md` | Test infrastructure |
### Special Prompts
| File | Purpose |
|------|---------|
| `botserver/src/tasks/PROMPT.md` | AutoTask LLM executor |
| `botserver/src/auto_task/APP_GENERATOR_PROMPT.md` | App generation |
---
## 🚀 STARTING DEVELOPMENT
### Start Both Servers
```bash
# Terminal 1: botserver
cd botserver && cargo run -- --noconsole
# Terminal 2: botui
cd botui && BOTSERVER_URL="http://localhost:8088" cargo run
```
### Build Commands
```bash
# Check single crate
cargo check -p botserver
# Build workspace
cargo build
# Run tests
cargo test -p bottest
```
---
## 📋 CONTINUATION PROMPT
When starting a new session or continuing work:
```
Continue on gb/ workspace. Follow PROMPT.md strictly:
1. Check current state with build/diagnostics
2. Fix ALL warnings and errors - NO #[allow()] attributes
3. Delete unused code, don't suppress warnings
4. Remove unused parameters, don't prefix with _
5. Verify after each fix batch
6. Loop until 0 warnings, 0 errors
```
---
## 🔑 REMEMBER
- **OFFLINE FIRST** - Fix all errors from list before compiling
- **ZERO WARNINGS, ZERO ERRORS** - The only acceptable state
- **FIX, DON'T SUPPRESS** - No #[allow()], no Cargo.toml lint exceptions
- **SECURITY FIRST** - No unwrap, no raw errors, no direct commands
- **READ BEFORE FIX** - Always understand context first
- **BATCH BY FILE** - Fix ALL errors in a file at once
- **WRITE ONCE** - Single edit per file with all fixes
- **VERIFY LAST** - Only compile/diagnostics after ALL fixes
- **DELETE DEAD CODE** - Don't keep unused code around
- **Version 6.2.0** - Do not change without approval
- **GIT WORKFLOW** - ALWAYS push to ALL repositories (github, pragmatismo)

1130
README.md

File diff suppressed because it is too large Load diff

2
botapp

@ -1 +1 @@
Subproject commit b5ee6e061acf1388aef777ddcd9a2bf84bd6ed57
Subproject commit 1a1e17fa1012e4db10a0f716c9b63a03b4863c9f

@ -1 +1 @@
Subproject commit 85696bb9070738f6bb865202f8c7de733f7c731a
Subproject commit 827e011ac05084396aaf2c3098409bf5e02b5cf9

2
botlib

@ -1 +1 @@
Subproject commit 2765fa2ebadc91435e8d90f068b4c96dbb77329b
Subproject commit bfaa68dc35e96ced2915d43ffe6fca8267a9a598

@ -1 +1 @@
Subproject commit 22a1954fac2f87a0a13b5e599771273172afc73a
Subproject commit 462a6dfa51b12f22e87712e613a559f66f9013cb

@ -1 +1 @@
Subproject commit 30345c66e2738ebe73d896841e54f655999e3630
Subproject commit 84458b2a6905af7db72b15f5e833bb7942ccdaa9

@ -1 +1 @@
Subproject commit 74e761de0dd5105885acf00183223a702a8436df
Subproject commit 706391b272e0fb7c5b2646cc4cc72180195e07f4

2
botui

@ -1 +1 @@
Subproject commit 414d277ae1757834d2ddbd6225063b451e919788
Subproject commit 661edc09fa1063673e84b63d2dcb5cfbe0f91232

View file

@ -1,20 +0,0 @@
{
"base_url": "http://localhost:8300",
"default_org": {
"id": "358572039839154190",
"name": "default",
"domain": "default.localhost"
},
"default_user": {
"id": "admin",
"username": "admin",
"email": "admin@localhost",
"password": "",
"first_name": "Admin",
"last_name": "User"
},
"admin_token": "eW0mGnOlKjpYHsrZZNAh1o3_8qeyF1iKKgEj-Y63GBdjQbQmxKxEjsNmVLZ_DWRDK6I3_yI",
"project_id": "",
"client_id": "358572040510308366",
"client_secret": "WyZRbj5iMkOkbvvtJWivXVaaydhWX1TodavhnAhsivl8IDZ44v2QoqT5upfgmOfz"
}

View file

@ -1,12 +0,0 @@
{
"name": "gb",
"version": "1.0.0",
"main": "index.js",
"author": "Rodrigo Rodriguez (Pragmatismo) <me@rodrigorodriguez.com>",
"license": "MIT",
"devDependencies": {
"@playwright/test": "^1.58.1",
"@types/node": "^25.2.0"
},
"scripts": {}
}

View file

@ -1,79 +0,0 @@
import { defineConfig, devices } from '@playwright/test';
/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('')`. */
// baseURL: 'http://localhost:3000',
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},
/* Configure projects for major browsers */
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
/* Test against mobile viewports. */
// {
// name: 'Mobile Chrome',
// use: { ...devices['Pixel 5'] },
// },
// {
// name: 'Mobile Safari',
// use: { ...devices['iPhone 12'] },
// },
/* Test against branded browsers. */
// {
// name: 'Microsoft Edge',
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
// },
// {
// name: 'Google Chrome',
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
// },
],
/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://localhost:3000',
// reuseExistingServer: !process.env.CI,
// },
});

View file

@ -1 +0,0 @@
rm -rf botserver-stack/ ./work/ .env

View file

@ -1,28 +0,0 @@
#!/bin/bash
set -e
echo "🛑 Stopping existing processes..."
pkill -f botserver || true
pkill -f botui || true
pkill -f rustc || true
echo "🧹 Cleaning logs..."
rm -f botserver.log botui.log
echo "🔨 Building botserver..."
cargo build -p botserver
echo "🔨 Building botui..."
cargo build -p botui
echo "🚀 Starting botserver..."
RUST_LOG=info ./target/debug/botserver --noconsole > botserver.log 2>&1 &
BOTSERVER_PID=$!
echo "🚀 Starting botui..."
BOTSERVER_URL="https://localhost:8088" ./target/debug/botui > botui.log 2>&1 &
BOTUI_PID=$!
echo "✅ Started botserver (PID: $BOTSERVER_PID) and botui (PID: $BOTUI_PID)"
echo "📊 Monitor with: tail -f botserver.log botui.log"
echo "🌐 Access at: http://localhost:3000"

View file

@ -1,28 +0,0 @@
REM Knowledge Base Website Crawler Bot - Start Template
REM Sets up bot context and crawled websites, then exits
REM Load bot introduction
intro = GET BOT MEMORY "introduction"
IF intro = "" THEN
intro = "I'm your documentation assistant with access to crawled websites."
END IF
REM Register websites for crawling (preprocessing mode)
USE WEBSITE "https://docs.python.org"
USE WEBSITE "https://developer.mozilla.org"
USE WEBSITE "https://stackoverflow.com"
REM Set context for LLM
SET CONTEXT "role" AS intro
SET CONTEXT "capabilities" AS "I can search Python docs, MDN web docs, and Stack Overflow."
REM Configure suggestion buttons
CLEAR SUGGESTIONS
ADD SUGGESTION "python" AS "How do I use Python dictionaries?"
ADD SUGGESTION "javascript" AS "Explain JavaScript async/await"
ADD SUGGESTION "web" AS "What is the DOM in web development?"
REM Initial greeting
TALK intro
TALK "I have access to Python documentation, MDN web docs, and Stack Overflow."
TALK "Ask me any programming question!"

View file

@ -1,4 +0,0 @@
pkill botui
pkill botserver -9

View file

@ -1,18 +0,0 @@
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});
test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
// Click the get started link.
await page.getByRole('link', { name: 'Get started' }).click();
// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
});

View file

@ -1,41 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@playwright/test@^1.58.1":
version "1.58.1"
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.58.1.tgz#891dcd1da815cb1042490531f6d8778988509d22"
integrity sha512-6LdVIUERWxQMmUSSQi0I53GgCBYgM2RpGngCPY7hSeju+VrKjq3lvs7HpJoPbDiY5QM5EYRtRX5fvrinnMAz3w==
dependencies:
playwright "1.58.1"
"@types/node@^25.2.0":
version "25.2.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-25.2.0.tgz#015b7d228470c1dcbfc17fe9c63039d216b4d782"
integrity sha512-DZ8VwRFUNzuqJ5khrvwMXHmvPe+zGayJhr2CDNiKB1WBE1ST8Djl00D0IC4vvNmHMdj6DlbYRIaFE7WHjlDl5w==
dependencies:
undici-types "~7.16.0"
fsevents@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
playwright-core@1.58.1:
version "1.58.1"
resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.58.1.tgz#d63be2c9b7dcbdb035beddd4b42437bd3ca89107"
integrity sha512-bcWzOaTxcW+VOOGBCQgnaKToLJ65d6AqfLVKEWvexyS3AS6rbXl+xdpYRMGSRBClPvyj44njOWoxjNdL/H9UNg==
playwright@1.58.1:
version "1.58.1"
resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.58.1.tgz#63300e77a604c77264e1b499c0d94b54ed96d6ba"
integrity sha512-+2uTZHxSCcxjvGc5C891LrS1/NlxglGxzrC4seZiVjcYVQfUa87wBL6rTDqzGjuoWNjnBzRqKmF6zRYGMvQUaQ==
dependencies:
playwright-core "1.58.1"
optionalDependencies:
fsevents "2.3.2"
undici-types@~7.16.0:
version "7.16.0"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46"
integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==