Compare commits

..

No commits in common. "main" and "azure-arm-automation" have entirely different histories.

450 changed files with 36938 additions and 138928 deletions

2
.deployment Normal file
View file

@ -0,0 +1,2 @@
[config]
command = deploy.cmd

View file

@ -1,52 +0,0 @@
# BotServer Embedded Configuration
# For Orange Pi, Raspberry Pi, and other ARM SBCs
# Server
HOST=0.0.0.0
PORT=8088
RUST_LOG=info
# Database (SQLite for embedded, no PostgreSQL needed)
DATABASE_URL=sqlite:///opt/botserver/data/botserver.db
# LLM Configuration - Local llama.cpp
LLM_PROVIDER=llamacpp
LLM_API_URL=http://127.0.0.1:8080
LLM_MODEL=tinyllama
# Alternative: Use remote API
# LLM_PROVIDER=openai
# LLM_API_URL=https://api.openai.com/v1
# LLM_API_KEY=sk-...
# Alternative: Ollama (if installed)
# LLM_PROVIDER=ollama
# LLM_API_URL=http://127.0.0.1:11434
# LLM_MODEL=tinyllama
# Memory limits for embedded
MAX_CONTEXT_TOKENS=2048
MAX_RESPONSE_TOKENS=512
STREAMING_ENABLED=true
# Embedded UI
STATIC_FILES_PATH=/opt/botserver/ui
DEFAULT_UI=embedded
# WebSocket
WS_PING_INTERVAL=30
WS_TIMEOUT=300
# Security (change in production!)
JWT_SECRET=embedded-change-me-in-production
CORS_ORIGINS=*
# Logging
LOG_FILE=/opt/botserver/data/botserver.log
LOG_MAX_SIZE=10M
LOG_RETENTION=7
# Performance tuning for low-memory devices
# Uncomment for <2GB RAM devices
# RUST_BACKTRACE=0
# MALLOC_ARENA_MAX=2

View file

@ -1,36 +0,0 @@
# BotServer Environment Configuration
# =====================================
#
# ONLY VAULT VARIABLES ARE ALLOWED IN THIS FILE!
# All secrets (DATABASE_URL, API keys, etc.) MUST be stored in Vault.
# NO LEGACY FALLBACK - Vault is mandatory.
#
# Vault paths for secrets:
# - gbo/tables - PostgreSQL credentials (host, port, database, username, password)
# - gbo/drive - MinIO/S3 credentials (accesskey, secret)
# - gbo/cache - Redis credentials (password)
# - gbo/directory - Zitadel credentials (url, project_id, client_id, client_secret)
# - gbo/email - Email credentials (username, password)
# - gbo/llm - LLM API keys (openai_key, anthropic_key, groq_key)
# - gbo/encryption - Encryption keys (master_key)
# - gbo/meet - LiveKit credentials (api_key, api_secret)
# - gbo/alm - Forgejo credentials (url, admin_password, runner_token)
# - gbo/vectordb - Qdrant credentials (url, api_key)
# - gbo/observability - InfluxDB credentials (url, org, bucket, token)
# =====================
# VAULT CONFIGURATION - ONLY THESE VARS ARE ALLOWED
# =====================
# Vault server address
VAULT_ADDR=https://localhost:8200
# Vault authentication token (generated during vault init)
# This will be populated automatically after first bootstrap
VAULT_TOKEN=
# Skip TLS verification for development (set to false in production)
VAULT_SKIP_VERIFY=true
# Cache TTL for secrets in seconds (default: 300 = 5 minutes)
VAULT_CACHE_TTL=300

View file

@ -1,242 +0,0 @@
name: GBCI Bundle
on:
push:
branches: ["main"]
tags: ["v*"]
pull_request:
branches: ["main"]
workflow_dispatch:
env:
CARGO_HOME: /root/.cargo
PATH: /root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
jobs:
build-bundle:
if: false # Workflow disabled - keep file for reference
runs-on: gbo
steps:
- name: Disable SSL verification (temporary)
run: git config --global http.sslVerify false
- uses: actions/checkout@v4
- name: Clone dependencies
run: |
git clone --depth 1 https://github.com/GeneralBots/botlib.git ../botlib
git clone --depth 1 https://github.com/GeneralBots/botui.git ../botui
git clone --depth 1 https://github.com/GeneralBots/botbook.git ../botbook
git clone --depth 1 https://github.com/GeneralBots/botmodels.git ../botmodels
- name: Cache Cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-bundle-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-bundle-
- name: Install Rust
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
echo "/root/.cargo/bin" >> $GITHUB_PATH
/root/.cargo/bin/rustup target add x86_64-unknown-linux-gnu
/root/.cargo/bin/rustup target add aarch64-unknown-linux-gnu
/root/.cargo/bin/rustup target add x86_64-pc-windows-gnu
- name: Install cross-compilation dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
gcc-mingw-w64-x86-64 \
gcc-aarch64-linux-gnu \
libc6-dev-arm64-cross \
zip
- name: Setup environment
run: sudo cp /opt/gbo/bin/system/.env .
# ============================================
# Download Python portable distributions
# ============================================
- name: Download Python portables
run: |
PYTHON_VERSION="3.12.7"
mkdir -p python-installers
# Linux x86_64 - python-build-standalone
curl -L -o python-installers/python-${PYTHON_VERSION}-linux-x86_64.tar.gz \
"https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-${PYTHON_VERSION}+20241016-x86_64-unknown-linux-gnu-install_only.tar.gz"
# Linux ARM64 - python-build-standalone
curl -L -o python-installers/python-${PYTHON_VERSION}-linux-arm64.tar.gz \
"https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-${PYTHON_VERSION}+20241016-aarch64-unknown-linux-gnu-install_only.tar.gz"
# Windows x86_64 - python-build-standalone
curl -L -o python-installers/python-${PYTHON_VERSION}-windows-x86_64.tar.gz \
"https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-${PYTHON_VERSION}+20241016-x86_64-pc-windows-msvc-install_only.tar.gz"
# macOS x86_64 - python-build-standalone
curl -L -o python-installers/python-${PYTHON_VERSION}-macos-x86_64.tar.gz \
"https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-${PYTHON_VERSION}+20241016-x86_64-apple-darwin-install_only.tar.gz"
# macOS ARM64 - python-build-standalone
curl -L -o python-installers/python-${PYTHON_VERSION}-macos-arm64.tar.gz \
"https://github.com/indygreg/python-build-standalone/releases/download/20241016/cpython-${PYTHON_VERSION}+20241016-aarch64-apple-darwin-install_only.tar.gz"
ls -la python-installers/
# ============================================
# Build botserver for all platforms
# ============================================
- name: Build botserver - Linux x86_64
run: /root/.cargo/bin/cargo build --release --locked --target x86_64-unknown-linux-gnu
- name: Build botserver - Linux ARM64
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
run: /root/.cargo/bin/cargo build --release --locked --target aarch64-unknown-linux-gnu
- name: Build botserver - Windows x86_64
env:
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: x86_64-w64-mingw32-gcc
run: /root/.cargo/bin/cargo build --release --locked --target x86_64-pc-windows-gnu
# ============================================
# Build botui for all platforms
# ============================================
- name: Build botui - Linux x86_64
run: |
cd ../botui
/root/.cargo/bin/cargo build --release --locked --target x86_64-unknown-linux-gnu
- name: Build botui - Linux ARM64
env:
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
run: |
cd ../botui
/root/.cargo/bin/cargo build --release --locked --target aarch64-unknown-linux-gnu
- name: Build botui - Windows x86_64
env:
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER: x86_64-w64-mingw32-gcc
run: |
cd ../botui
/root/.cargo/bin/cargo build --release --locked --target x86_64-pc-windows-gnu
# ============================================
# Build botbook documentation
# ============================================
- name: Install mdBook
run: |
if ! command -v mdbook &> /dev/null; then
/root/.cargo/bin/cargo install mdbook
fi
- name: Build botbook
run: |
cd ../botbook
mdbook build
# ============================================
# Create bundle directories
# Structure:
# botserver(.exe) <- root binary
# botserver-components/
# botui(.exe)
# botmodels/
# botbook/
# botserver-installers/
# python-<version>-<platform>.tar.gz
# postgresql, valkey, vault, minio, zitadel, llama, models...
# ============================================
- name: Create bundle structure
run: |
BUNDLE_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
PYTHON_VERSION="3.12.7"
# Linux x86_64 bundle
mkdir -p bundle/linux-x86_64/botserver-components
mkdir -p bundle/linux-x86_64/botserver-installers
cp ./target/x86_64-unknown-linux-gnu/release/botserver bundle/linux-x86_64/botserver || true
cp ../botui/target/x86_64-unknown-linux-gnu/release/botui bundle/linux-x86_64/botserver-components/ || true
cp python-installers/python-${PYTHON_VERSION}-linux-x86_64.tar.gz bundle/linux-x86_64/botserver-installers/
# Linux ARM64 bundle
mkdir -p bundle/linux-arm64/botserver-components
mkdir -p bundle/linux-arm64/botserver-installers
cp ./target/aarch64-unknown-linux-gnu/release/botserver bundle/linux-arm64/botserver || true
cp ../botui/target/aarch64-unknown-linux-gnu/release/botui bundle/linux-arm64/botserver-components/ || true
cp python-installers/python-${PYTHON_VERSION}-linux-arm64.tar.gz bundle/linux-arm64/botserver-installers/
# Windows x86_64 bundle
mkdir -p bundle/windows-x86_64/botserver-components
mkdir -p bundle/windows-x86_64/botserver-installers
cp ./target/x86_64-pc-windows-gnu/release/botserver.exe bundle/windows-x86_64/botserver.exe || true
cp ../botui/target/x86_64-pc-windows-gnu/release/botui.exe bundle/windows-x86_64/botserver-components/ || true
cp python-installers/python-${PYTHON_VERSION}-windows-x86_64.tar.gz bundle/windows-x86_64/botserver-installers/
# ============================================
# Copy shared components to all bundles
# ============================================
- name: Copy botmodels to bundles
run: |
for platform in linux-x86_64 linux-arm64 windows-x86_64; do
mkdir -p bundle/$platform/botserver-components/botmodels
cp -r ../botmodels/* bundle/$platform/botserver-components/botmodels/
done
- name: Copy botbook to bundles
run: |
for platform in linux-x86_64 linux-arm64 windows-x86_64; do
mkdir -p bundle/$platform/botserver-components/botbook
cp -r ../botbook/book/* bundle/$platform/botserver-components/botbook/
done
- name: Copy installers to bundles
run: |
for platform in linux-x86_64 linux-arm64 windows-x86_64; do
cp -r ./botserver-installers/* bundle/$platform/botserver-installers/
done
# ============================================
# Create ZIP archives
# ============================================
- name: Create release archives
run: |
BUNDLE_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
cd bundle
for platform in linux-x86_64 linux-arm64 windows-x86_64; do
if [ -f "$platform/botserver" ] || [ -f "$platform/botserver.exe" ]; then
zip -r "botserver-bundle-${BUNDLE_VERSION}-${platform}.zip" "$platform"
echo "Created: botserver-bundle-${BUNDLE_VERSION}-${platform}.zip"
fi
done
cd ..
# ============================================
# Deploy bundles
# ============================================
- name: Deploy bundle releases
run: |
BUNDLE_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
sudo mkdir -p /opt/gbo/releases/botserver-bundle
sudo cp bundle/*.zip /opt/gbo/releases/botserver-bundle/ || true
# Also keep unpacked bundles for direct access
sudo mkdir -p /opt/gbo/releases/botserver-bundle/unpacked
sudo cp -r bundle/linux-x86_64 /opt/gbo/releases/botserver-bundle/unpacked/ || true
sudo cp -r bundle/linux-arm64 /opt/gbo/releases/botserver-bundle/unpacked/ || true
sudo cp -r bundle/windows-x86_64 /opt/gbo/releases/botserver-bundle/unpacked/ || true
sudo chmod -R 755 /opt/gbo/releases/botserver-bundle/
echo "Bundle releases deployed to /opt/gbo/releases/botserver-bundle/"
ls -la /opt/gbo/releases/botserver-bundle/

View file

@ -1,71 +0,0 @@
name: GBCI
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
env:
CARGO_BUILD_JOBS: 1
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
jobs:
build:
runs-on: gbo
steps:
- name: Disable SSL verification
run: git config --global http.sslVerify false
- uses: actions/checkout@v4
- name: Clone botlib dependency
run: git clone --depth 1 https://github.com/GeneralBots/botlib.git ../botlib
- name: Cache Cargo registry
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-debug-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-debug-
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libpq-dev libssl-dev liblzma-dev pkg-config
- name: Install Rust
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Setup environment
run: sudo cp /opt/gbo/bin/system/.env . 2>/dev/null || true
- name: Build debug
run: |
cargo build --locked -j 1 2>&1 | tee /tmp/build.log
ls -lh target/debug/botserver
- name: Save build log
if: always()
run: |
sudo mkdir -p /opt/gbo/logs
sudo cp /tmp/build.log /opt/gbo/logs/botserver-$(date +%Y%m%d-%H%M%S).log || true
- name: Deploy
run: |
sudo mkdir -p /opt/gbo/releases/botserver/linux
sudo cp target/debug/botserver /opt/gbo/releases/botserver/linux/botserver-x86_64
sudo chmod 755 /opt/gbo/releases/botserver/linux/botserver-x86_64
lxc exec bot:pragmatismo-system -- systemctl stop system || true
sudo cp target/debug/botserver /opt/gbo/bin/system/botserver
sudo chmod +x /opt/gbo/bin/system/botserver
lxc exec bot:pragmatismo-system -- systemctl start system || true

9
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,9 @@
<!-- File a GitHub issue only for bugs or feature requests related to the code **in this repository**. For other topics you can get more information in the README file. -->
### Observed Results:
<!-- This could be a description, error output, steps to reproduce, a feature missed, etc. -->
### Expected behavior:
<!-- What did you expect to happen? -->

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

7
.github/ISSUE_TEMPLATE/custom.md vendored Normal file
View file

@ -0,0 +1,7 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
---

View file

@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

2
.github/ISSUE_TEMPLATE/requirement vendored Normal file
View file

@ -0,0 +1,2 @@
**Description**
A clear and concise description of what the requirement is.

16
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,16 @@
### Changes description
<!-- Describe results, user mentions, screenshots, screencast (gif) -->
### Checklist
Please check if your PR fulfills the following specifications:
- [ ] Tests for the changes have been added
- [ ] Docs have been added/updated
### References
<!-- issues related (for reference or to be closed) and/or links of discuss -->
Closes #N/A

3
.github/invite-contributors.yml vendored Normal file
View file

@ -0,0 +1,3 @@
isOutside: true
# Team Name
team: contributors

44
.github/settings.yml vendored Normal file
View file

@ -0,0 +1,44 @@
repository:
name: botserver
description: botserver
homepage: http://pragmatismo.io/general-bots
topics: node-module
private: false
has_issues: true
has_wiki: false
has_downloads: true
default_branch: develop
allow_squash_merge: true
allow_merge_commit: false
allow_rebase_merge: true
labels:
- name: bug
color: f44336
- name: build
color: 795548
- name: ci
color: fbca04
- name: documentation
color: 607d8b
- name: duplicate
color: 9e9e9e
- name: feature
color: 3f51b5
- name: invalid
color: cddc39
- name: performance
color: 009688
- name: question
color: ff5722
- name: refactor
color: 9c27b0
- name: style
color: 2196f3
- name: test
color: 8bc34a
- name: wontfix
color: ffffff
- name: help wanted
color: 33aa3f
- name: good first issue
color: 7057ff

29
.gitignore vendored
View file

@ -1,16 +1,13 @@
.tmp*
.tmp/*
*.log
target*
.env
*.env
work
*.out
bin
botserver-stack
*logfile*
*-log*
docs/book
*.rdb
botserver-installers/*
!botserver-installers/.gitkeep
node_modules
/packages/default.gbui/build
/dist
/guaribas.sqlite
/guaribas.log
/work
/tmp
/docs
/.env
/chart.html
/chart.png
/chart.svg
/gbtrace.log

5
.npmignore Normal file
View file

@ -0,0 +1,5 @@
node_modules
/packages/default.gbui/build
/guaribas.sqlite
/guaribas.log
/work

41
.vscode/launch.json vendored
View file

@ -1,41 +1,20 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"type": "node",
"request": "launch",
"name": "Debug executable 'botserver'",
"cargo": {
"args": ["build", "--bin=botserver", "--package=botserver"],
"filter": {
"name": "botserver",
"kind": "bin"
}
},
"args": ["--desktop"],
"name": "Debug Program",
"program": "${workspaceRoot}/dist/src/app.js",
"cwd": "${workspaceRoot}",
"env": {
"RUST_LOG": "trace,aws_sigv4=off,aws_smithy_checksums=off,mio=off,reqwest=off,aws_runtime=off,aws_smithy_http_client=off,rustls=off,hyper_util=off,aws_smithy_runtime=off,aws_smithy_runtime_api=off,tracing=off,aws_sdk_s3=off"
"NODE_ENV": "development"
},
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'botserver'",
"cargo": {
"args": ["test", "--no-run", "--bin=botserver", "--package=botserver"],
"filter": {
"name": "botserver",
"kind": "bin"
}
},
"args": [],
"env": {
"RUST_LOG": "trace"
},
"cwd": "${workspaceFolder}"
"args":["--no-deprecation"],
"skipFiles": ["node_modules/**/*.js"],
"outFiles": ["${workspaceRoot}/dist/*.js"],
"stopOnEntry": false,
"console": "integratedTerminal"
}
]
}

4
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"typescript.tsdk": "./node_modules/typescript/lib",
}

View file

@ -1,16 +0,0 @@
[
{
"label": "Debug BotServer",
"build": {
"command": "rm -rf .env ./botserver-stack && cargo",
"args": ["build"]
},
"program": "$ZED_WORKTREE_ROOT/target/debug/botserver",
"env": {
"RUST_LOG": "trace"
},
"sourceLanguages": ["rust"],
"request": "launch",
"adapter": "CodeLLDB"
}
]

View file

@ -1,224 +0,0 @@
# Third-Party Dependencies Configuration
# ======================================
# This file lists all external downloads required by botserver.
#
# Caching Behavior:
# - On first run, files are downloaded from the URLs below
# - Downloaded files are cached in ./botserver-installers/
# - On subsequent runs, cached files are used instead of downloading
# - To force re-download, delete the cached file
#
# Offline Installation:
# - Pre-download all files to ./botserver-installers/
# - The installer will use cached files automatically
# - You can safely delete ./botserver-stack/ without losing downloads
[cache_settings]
# Directory where downloaded files are cached (relative to botserver root)
cache_dir = "botserver-installers"
# Components
# ==========
# Each component has:
# - url: Download URL
# - filename: Local filename in cache
# - sha256: Optional checksum for verification (empty = skip verification)
[components.drive]
name = "MinIO Object Storage"
url = "https://dl.min.io/server/minio/release/linux-amd64/minio"
filename = "minio"
sha256 = ""
[components.tables]
name = "PostgreSQL Database"
url = "https://github.com/theseus-rs/postgresql-binaries/releases/download/17.2.0/postgresql-17.2.0-x86_64-unknown-linux-gnu.tar.gz"
filename = "postgresql-17.2.0-x86_64-unknown-linux-gnu.tar.gz"
sha256 = ""
[components.cache]
name = "Valkey Cache (Redis-compatible)"
# Valkey requires compilation from source - no prebuilt binaries available
# The installer will run 'make' to build valkey-server and valkey-cli
# Requires: gcc, make (usually available on most Linux systems)
url = "https://github.com/valkey-io/valkey/archive/refs/tags/8.0.2.tar.gz"
filename = "valkey-8.0.2.tar.gz"
sha256 = ""
[components.llm]
name = "Llama.cpp Server"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-ubuntu-x64.zip"
filename = "llama-b7345-bin-ubuntu-x64.zip"
sha256 = "91b066ecc53c20693a2d39703c12bc7a69c804b0768fee064d47df702f616e52"
[components.email]
name = "Stalwart Mail Server"
url = "https://github.com/stalwartlabs/mail-server/releases/download/v0.10.7/stalwart-mail-x86_64-linux.tar.gz"
filename = "stalwart-mail-x86_64-linux.tar.gz"
sha256 = ""
[components.proxy]
name = "Caddy Web Server"
url = "https://github.com/caddyserver/caddy/releases/download/v2.9.1/caddy_2.9.1_linux_amd64.tar.gz"
filename = "caddy_2.9.1_linux_amd64.tar.gz"
sha256 = ""
[components.directory]
name = "Zitadel Identity Provider"
url = "https://github.com/zitadel/zitadel/releases/download/v2.70.4/zitadel-linux-amd64.tar.gz"
filename = "zitadel-linux-amd64.tar.gz"
sha256 = ""
[components.alm]
name = "Forgejo Git Server"
url = "https://codeberg.org/forgejo/forgejo/releases/download/v10.0.2/forgejo-10.0.2-linux-amd64"
filename = "forgejo-10.0.2-linux-amd64"
sha256 = ""
[components.alm_ci]
name = "Forgejo Actions Runner"
url = "https://code.forgejo.org/forgejo/runner/releases/download/v6.3.1/forgejo-runner-6.3.1-linux-amd64"
filename = "forgejo-runner-6.3.1-linux-amd64"
sha256 = ""
[components.dns]
name = "CoreDNS Server"
url = "https://github.com/coredns/coredns/releases/download/v1.11.1/coredns_1.11.1_linux_amd64.tgz"
filename = "coredns_1.11.1_linux_amd64.tgz"
sha256 = ""
[components.webmail]
name = "Roundcube Webmail"
url = "https://github.com/roundcube/roundcubemail/releases/download/1.6.6/roundcubemail-1.6.6-complete.tar.gz"
filename = "roundcubemail-1.6.6-complete.tar.gz"
sha256 = ""
[components.meet]
name = "LiveKit Media Server"
url = "https://github.com/livekit/livekit/releases/download/v2.8.2/livekit_2.8.2_linux_amd64.tar.gz"
filename = "livekit_2.8.2_linux_amd64.tar.gz"
sha256 = ""
[components.table_editor]
name = "NocoDB"
url = "http://get.nocodb.com/linux-x64"
filename = "nocodb-linux-x64"
sha256 = ""
[components.vector_db]
name = "Qdrant Vector Database"
url = "https://github.com/qdrant/qdrant/releases/latest/download/qdrant-x86_64-unknown-linux-gnu.tar.gz"
filename = "qdrant-x86_64-unknown-linux-gnu.tar.gz"
sha256 = ""
[components.timeseries_db]
name = "InfluxDB Time Series Database"
url = "https://download.influxdata.com/influxdb/releases/influxdb2-2.7.5-linux-amd64.tar.gz"
filename = "influxdb2-2.7.5-linux-amd64.tar.gz"
sha256 = ""
[components.vault]
name = "HashiCorp Vault"
url = "https://releases.hashicorp.com/vault/1.15.4/vault_1.15.4_linux_amd64.zip"
filename = "vault_1.15.4_linux_amd64.zip"
sha256 = ""
[components.observability]
name = "Vector Log Aggregator"
url = "https://packages.timber.io/vector/0.35.0/vector-0.35.0-x86_64-unknown-linux-gnu.tar.gz"
filename = "vector-0.35.0-x86_64-unknown-linux-gnu.tar.gz"
sha256 = ""
# LLM Models
# ==========
# Large model files for AI/ML functionality
[models.deepseek_small]
name = "DeepSeek R1 Distill Qwen 1.5B (Q3_K_M)"
url = "https://huggingface.co/bartowski/DeepSeek-R1-Distill-Qwen-1.5B-GGUF/resolve/main/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf"
filename = "DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf"
sha256 = ""
[models.bge_embedding]
name = "BGE Small EN v1.5 Embedding Model"
url = "https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf/resolve/main/bge-small-en-v1.5-f32.gguf"
filename = "bge-small-en-v1.5-f32.gguf"
sha256 = ""
# Platform-specific llama.cpp variants
# =====================================
# These are alternative builds for different platforms/GPU support
[components.llm_linux_vulkan]
name = "Llama.cpp Server (Linux Vulkan)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-ubuntu-vulkan-x64.zip"
filename = "llama-b7345-bin-ubuntu-vulkan-x64.zip"
sha256 = "03f0b3acbead2ddc23267073a8f8e0207937c849d3704c46c61cf167c1001442"
[components.llm_linux_s390x]
name = "Llama.cpp Server (Linux s390x)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-ubuntu-s390x.zip"
filename = "llama-b7345-bin-ubuntu-s390x.zip"
sha256 = "688ddad6996b1166eaaa76d5025e304c684116efe655e6e881d877505ecffccb"
[components.llm_macos_arm64]
name = "Llama.cpp Server (macOS ARM64)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-macos-arm64.zip"
filename = "llama-b7345-bin-macos-arm64.zip"
sha256 = "72ae9b4a4605aa1223d7aabaa5326c66c268b12d13a449fcc06f61099cd02a52"
[components.llm_macos_x64]
name = "Llama.cpp Server (macOS x64)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-macos-x64.zip"
filename = "llama-b7345-bin-macos-x64.zip"
sha256 = "bec6b805cf7533f66b38f29305429f521dcb2be6b25dbce73a18df448ec55cc5"
[components.llm_win_cpu_x64]
name = "Llama.cpp Server (Windows x64 CPU)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-win-cpu-x64.zip"
filename = "llama-b7345-bin-win-cpu-x64.zip"
sha256 = "ea449082c8e808a289d9a1e8331f90a0379ead4dd288a1b9a2d2c0a7151836cd"
[components.llm_win_cpu_arm64]
name = "Llama.cpp Server (Windows ARM64 CPU)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-win-cpu-arm64.zip"
filename = "llama-b7345-bin-win-cpu-arm64.zip"
sha256 = "91e3ff43c123c7c30decfe5a44c291827c1e47359abaa2fbad1eb5392b3a0d85"
[components.llm_win_cuda12]
name = "Llama.cpp Server (Windows CUDA 12.4)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-win-cuda-12.4-x64.zip"
filename = "llama-b7345-bin-win-cuda-12.4-x64.zip"
sha256 = "7a82aba2662fa7d4477a7a40894de002854bae1ab8b0039888577c9a2ca24cae"
[components.llm_win_cuda13]
name = "Llama.cpp Server (Windows CUDA 13.1)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-win-cuda-13.1-x64.zip"
filename = "llama-b7345-bin-win-cuda-13.1-x64.zip"
sha256 = "06ea715cefb07e9862394e6d1ffa066f4c33add536b1f1aa058723f86ae05572"
[components.llm_win_vulkan]
name = "Llama.cpp Server (Windows Vulkan)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-win-vulkan-x64.zip"
filename = "llama-b7345-bin-win-vulkan-x64.zip"
sha256 = "3e948bee438f46c8ea0a3faf0416549391ee945ffa624b25bc1f73d60d668679"
# CUDA runtime libraries (required for CUDA builds on Windows)
[components.cudart_win_cuda12]
name = "CUDA Runtime (Windows CUDA 12.4)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/cudart-llama-bin-win-cuda-12.4-x64.zip"
filename = "cudart-llama-bin-win-cuda-12.4-x64.zip"
sha256 = "8c79a9b226de4b3cacfd1f83d24f962d0773be79f1e7b75c6af4ded7e32ae1d6"
[components.cudart_win_cuda13]
name = "CUDA Runtime (Windows CUDA 13.1)"
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/cudart-llama-bin-win-cuda-13.1-x64.zip"
filename = "cudart-llama-bin-win-cuda-13.1-x64.zip"
sha256 = "f96935e7e385e3b2d0189239077c10fe8fd7e95690fea4afec455b1b6c7e3f18"
# Optional larger models (uncomment to include)
# [models.gpt_oss_20b]
# name = "GPT-OSS 20B F16 (requires 16GB+ VRAM)"
# url = "https://huggingface.co/unsloth/gpt-oss-20b-GGUF/resolve/main/gpt-oss-20b-F16.gguf"
# filename = "gpt-oss-20b-F16.gguf"
# sha256 = ""

47
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,47 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
* Writing general pieces of code so it can be widely used.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at security@pragmatismo.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

59
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,59 @@
# Instructions for Logging Issues
## 1. Search for Duplicates
[Search the existing issues](https://github.com/pragmatismo-io/BotServer/issues) before logging a new one.
## 2. Do you have a question?
Please use the issue tracker for bugs and suggestions.
If you have a *question*, please use [Stack Overflow](https://stackoverflow.com/questions/tagged/botserver)
## 3. Did you find a bug?
We are not surprised, we're still in early preview so there are plenty of them right now.
When logging a bug, please be sure to include the following:
* The platform you were using
* If at all possible, an *isolated* way to reproduce the behavior
* The behavior you expect to see, and the actual behavior
## 4. Do you have a suggestion?
We also accept suggestions in the issue tracker.
In general, things we find useful when reviewing suggestions are:
* A description of the problem you're trying to solve
* An overview of the suggested solution
* Examples of how the suggestion would work in various places
# Instructions for Contributing Code
## Contributing bug fixes
General Bots is current in early preview. We're still accepting contributions in the form of bug fixes.
A bug must have an issue tracking it in the issue tracker that has been approved by the Pragmatismo.io team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
## Contributing features
Please open an issue with the `Schema` label to get a discussion started.
## Legal
We appreciate community contributions to code repositories open sourced by Pragmatismo.io. By signing a contributor license agreement, we ensure that the community is free to use your contributions.
## Housekeeping
Your pull request should:
* Include a description of what your change intends to do
* Be a child commit of a reasonably recent commit in the **master** branch
* Requests need not be a single commit, but should be a linear sequence of commits (i.e. no merge commits in your PR)
* Have clear commit messages
* e.g. "Refactor feature", "Fix issue", "Add tests for issue"
## Running (and adding) the Tests
*Coming soon*

8200
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,287 +0,0 @@
[package]
name = "botserver"
version = "6.1.0"
edition = "2021"
keywords = ["chatbot", "ai", "llm", "automation", "bot-framework"]
categories = ["web-programming", "api-bindings", "development-tools"]
authors = [
"Pragmatismo.com.br ",
"General Bots Community ",
"Alan Perdomo",
"Ana Paula Gil",
"Arenas.io",
"Atylla L",
"Christopher de Castilho",
"Dario Junior",
"David Lerner",
"Experimentation Garage",
"Flavio Andrade",
"Heraldo Almeida",
"Joao Parana",
"Jonathas C",
"J Ramos",
"Lucas Picanco",
"Marcos Velasco",
"Matheus 39x",
"Oerlabs Henrique",
"Othon Lima",
"PH Nascimento",
"Phpussente",
"Robson Dantas",
"Rodrigo Rodriguez ",
"Sarah Lourenco",
"Thi Patriota",
"Webgus",
"Zuilho Se",
]
description = "General Bots Server - Open-source bot platform by Pragmatismo.com.br"
license = "AGPL-3.0"
repository = "https://github.com/GeneralBots/BotServer"
[dependencies.botlib]
path = "../botlib"
features = ["database"]
[features]
# ===== DEFAULT FEATURE SET =====
default = ["console", "chat", "automation", "tasks", "drive", "llm", "cache", "progress-bars", "directory"]
# ===== UI FEATURES =====
console = ["dep:crossterm", "dep:ratatui", "monitoring"]
# ===== CORE INTEGRATIONS =====
vectordb = ["dep:qdrant-client"]
llm = []
nvidia = []
# ===== COMMUNICATION CHANNELS =====
email = ["dep:imap", "dep:lettre", "dep:mailparse", "dep:native-tls"]
whatsapp = []
instagram = []
msteams = []
# ===== PRODUCTIVITY FEATURES =====
chat = []
drive = ["dep:aws-config", "dep:aws-sdk-s3", "dep:pdf-extract", "dep:zip", "dep:downloader", "dep:mime_guess", "dep:flate2", "dep:tar"]
tasks = ["dep:cron"]
calendar = []
meet = ["dep:livekit"]
mail = ["email"]
# ===== ENTERPRISE FEATURES =====
compliance = ["dep:csv"]
attendance = []
directory = []
weba = []
timeseries = []
# ===== OPTIONAL INFRASTRUCTURE =====
cache = ["dep:redis"]
monitoring = ["dep:sysinfo"]
automation = ["dep:rhai"]
grpc = ["dep:tonic"]
progress-bars = ["dep:indicatif"]
# ===== META FEATURES (BUNDLES) =====
full = [
"console",
"vectordb", "llm", "nvidia", "timeseries",
"email", "whatsapp", "instagram", "msteams",
"chat", "drive", "tasks", "calendar", "meet", "mail",
"compliance", "attendance", "directory", "weba",
"cache", "monitoring", "automation", "grpc", "progress-bars"
]
communications = ["email", "whatsapp", "instagram", "msteams", "chat", "cache"]
productivity = ["chat", "drive", "tasks", "calendar", "meet", "mail", "cache"]
enterprise = ["compliance", "attendance", "directory", "llm", "vectordb", "monitoring", "timeseries"]
minimal = ["chat"]
lightweight = ["chat", "drive", "tasks"]
[dependencies]
# === CORE RUNTIME (Always Required) ===
aes-gcm = "0.10"
anyhow = "1.0"
argon2 = "0.5"
async-lock = "2.8.0"
async-stream = "0.3"
async-trait = "0.1"
axum = { version = "0.7.5", features = ["ws", "multipart", "macros"] }
axum-server = { version = "0.7", features = ["tls-rustls"] }
base64 = "0.22"
bytes = "1.8"
chrono = { version = "0.4", features = ["serde"] }
color-eyre = "0.6.5"
diesel = { version = "2.1", features = ["postgres", "uuid", "chrono", "serde_json", "r2d2"] }
diesel_migrations = "2.1.0"
dotenvy = "0.15"
env_logger = "0.11"
futures = "0.3"
futures-util = "0.3"
hex = "0.4"
hmac = "0.12.1"
hyper = { version = "0.14", features = ["full"] }
hyper-rustls = { version = "0.24", features = ["http2"] }
log = "0.4"
num-format = "0.4"
once_cell = "1.18.0"
rand = "0.9.2"
regex = "1.11"
reqwest = { version = "0.12", features = ["json", "stream", "multipart", "rustls-tls", "rustls-tls-native-roots"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
toml = "0.8"
sha2 = "0.10.9"
tokio = { version = "1.41", features = ["full"] }
tokio-stream = "0.1"
tower = "0.4"
tower-http = { version = "0.5", features = ["cors", "fs", "trace"] }
tracing = "0.1"
askama = "0.12"
askama_axum = "0.4"
tracing-subscriber = { version = "0.3", features = ["fmt"] }
urlencoding = "2.1"
uuid = { version = "1.11", features = ["serde", "v4"] }
# === TLS/SECURITY DEPENDENCIES ===
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
rustls-pemfile = "2.0"
tokio-rustls = "0.26"
rcgen = { version = "0.14", features = ["pem"] }
x509-parser = "0.15"
rustls-native-certs = "0.6"
webpki-roots = "0.25"
ring = "0.17"
time = { version = "0.3", features = ["formatting", "parsing"] }
jsonwebtoken = "9.3"
tower-cookies = "0.10"
# === FEATURE-SPECIFIC DEPENDENCIES (Optional) ===
# Email Integration (email feature)
imap = { version = "3.0.0-alpha.15", optional = true }
lettre = { version = "0.11", features = ["smtp-transport", "builder", "tokio1", "tokio1-native-tls"], optional = true }
mailparse = { version = "0.15", optional = true }
native-tls = { version = "0.2", optional = true }
# Video Meetings (meet feature)
livekit = { version = "0.7", optional = true }
# Vector Database (vectordb feature)
qdrant-client = { version = "1.12", optional = true }
# File Storage & Drive (drive feature)
aws-config = { version = "1.8.8", optional = true }
aws-sdk-s3 = { version = "1.109.0", features = ["behavior-version-latest"], optional = true }
pdf-extract = { version = "0.10.0", optional = true }
zip = { version = "2.2", optional = true }
downloader = { version = "0.2", optional = true }
mime_guess = { version = "2.0", optional = true }
flate2 = { version = "1.0", optional = true }
tar = { version = "0.4", optional = true }
# Task Management (tasks feature)
cron = { version = "0.15.0", optional = true }
# Automation & Scripting (automation feature)
rhai = { git = "https://github.com/therealprof/rhai.git", branch = "features/use-web-time", features = ["sync"], optional = true }
# Compliance & Reporting (compliance feature)
csv = { version = "1.3", optional = true }
# Console/TUI (console feature)
crossterm = { version = "0.29.0", optional = true }
ratatui = { version = "0.30.0-beta.0", optional = true }
# QR Code Generation (using png directly to avoid image's ravif/paste dependency)
png = "0.18"
qrcode = { version = "0.14", default-features = false }
# Excel/Spreadsheet Support
calamine = "0.26"
rust_xlsxwriter = "0.79"
# Error handling
thiserror = "2.0"
# Caching/Sessions (cache feature)
redis = { version = "0.27", features = ["tokio-comp"], optional = true }
# System Monitoring (monitoring feature)
sysinfo = { version = "0.37.2", optional = true }
# Networking/gRPC (grpc feature)
tonic = { version = "0.14.2", features = ["transport"], optional = true }
# UI Enhancement (progress-bars feature)
indicatif = { version = "0.18.0", optional = true }
smartstring = "1.0.1"
scopeguard = "1.2.0"
# Vault secrets management
vaultrs = "0.7"
# Calendar standards (RFC 5545)
icalendar = "0.17"
# Layered configuration
figment = { version = "0.10", features = ["toml", "env", "json"] }
# Rate limiting
governor = "0.10"
# RSS feed parsing
rss = "2.0"
# HTML parsing/web scraping
scraper = "0.25"
[dev-dependencies]
mockito = "1.7.0"
tempfile = "3"
# === SECURITY AND CODE QUALITY CONFIGURATION ===
[lints.rust]
unused_imports = "warn"
unused_variables = "warn"
unused_mut = "warn"
unsafe_code = "deny"
missing_debug_implementations = "warn"
[lints.clippy]
all = "warn"
pedantic = "warn"
nursery = "warn"
cargo = "warn"
unwrap_used = "warn"
expect_used = "warn"
panic = "warn"
todo = "warn"
[profile.release]
lto = true
opt-level = "z"
strip = true
panic = "abort"
codegen-units = 1
overflow-checks = true
[profile.ci]
inherits = "release"
lto = false
codegen-units = 16
debug = false
[profile.low-memory]
inherits = "release"
lto = "thin"
codegen-units = 16
debug = false
incremental = false
opt-level = "s"
[profile.dev]
debug = 0
incremental = true
codegen-units = 256
opt-level = 0

View file

@ -1,5 +1,5 @@
General Bots is licensed under a dual license. To check which license
edition of General bots you have installed, please ask info@pragmatismo.com.br
edition of General bots you have installed, please ask info@pragmatismo.io
informing your Customer ID.
If you modify this Program, or any covered work, by combining it

678
PROMPT.md
View file

@ -1,678 +0,0 @@
# botserver Development Prompt Guide
**Version:** 6.1.0
**Purpose:** Consolidated LLM context for botserver development
---
## Build Rules - IMPORTANT
**Always use debug builds during development and testing:**
```bash
# CORRECT - debug build (fast compilation)
cargo build
cargo check
# WRONG - do NOT use release builds unless explicitly requested
# cargo build --release
```
Debug builds compile much faster and are sufficient for testing functionality.
Only use `--release` when building final binaries for deployment.
---
## Weekly Maintenance - EVERY MONDAY
### Package Review Checklist
**Every Monday, review the following:**
1. **Dependency Updates**
```bash
cargo outdated
cargo audit
```
2. **Package Consolidation Opportunities**
- Check if new crates can replace custom code
- Look for crates that combine multiple dependencies
- Review `Cargo.toml` for redundant dependencies
3. **Code Reduction Candidates**
- Custom implementations that now have crate equivalents
- Boilerplate that can be replaced with derive macros
- Manual serialization that `serde` can handle
4. **Security Updates**
```bash
cargo audit fix
```
### Packages to Watch
| Area | Potential Packages | Purpose |
|------|-------------------|---------|
| Validation | `validator` | Replace manual validation |
| Date/Time | `chrono`, `time` | Consolidate time handling |
| Email | `lettre` | Simplify email sending |
| File Watching | `notify` | Replace polling with events |
| Background Jobs | `tokio-cron-scheduler` | Simplify scheduling |
---
## Version Management - CRITICAL
**Current version is 6.1.0 - DO NOT CHANGE without explicit approval!**
```bash
# Check current version
grep "^version" Cargo.toml
```
### Rules
1. **Version is 6.1.0 across ALL workspace crates**
2. **NEVER change version without explicit user approval**
3. **All migrations use 6.1.0_* prefix**
4. **Migration folder naming: `6.1.0_{feature_name}/`**
---
## Database Standards - CRITICAL
### TABLES AND INDEXES ONLY
**NEVER create in migrations:**
- ❌ Views (`CREATE VIEW`)
- ❌ Triggers (`CREATE TRIGGER`)
- ❌ Functions (`CREATE FUNCTION`)
- ❌ Stored Procedures
**ALWAYS use:**
- ✅ Tables (`CREATE TABLE IF NOT EXISTS`)
- ✅ Indexes (`CREATE INDEX IF NOT EXISTS`)
- ✅ Constraints (inline in table definitions)
### Why?
- Diesel ORM compatibility
- Simpler rollbacks
- Better portability
- Easier testing
### JSON Storage Pattern
Use TEXT columns with `_json` suffix instead of JSONB:
```sql
-- CORRECT
members_json TEXT DEFAULT '[]'
-- WRONG
members JSONB DEFAULT '[]'::jsonb
```
---
## Official Icons - MANDATORY
**NEVER generate icons with LLM. ALWAYS use official SVG icons from assets.**
Icons are stored in two locations (kept in sync):
- `botui/ui/suite/assets/icons/` - Runtime icons for UI
- `botbook/src/assets/icons/` - Documentation icons
### Available Icons
| Icon | File | Usage |
|------|------|-------|
| Logo | `gb-logo.svg` | Main GB branding |
| Bot | `gb-bot.svg` | Bot/assistant representation |
| Analytics | `gb-analytics.svg` | Charts, metrics, dashboards |
| Calendar | `gb-calendar.svg` | Scheduling, events |
| Chat | `gb-chat.svg` | Conversations, messaging |
| Compliance | `gb-compliance.svg` | Security, auditing |
| Designer | `gb-designer.svg` | Workflow automation |
| Drive | `gb-drive.svg` | File storage, documents |
| Mail | `gb-mail.svg` | Email functionality |
| Meet | `gb-meet.svg` | Video conferencing |
| Paper | `gb-paper.svg` | Document editing |
| Research | `gb-research.svg` | Search, investigation |
| Sources | `gb-sources.svg` | Knowledge bases |
| Tasks | `gb-tasks.svg` | Task management |
### Icon Guidelines
- All icons use `stroke="currentColor"` for CSS theming
- ViewBox: `0 0 24 24`
- Stroke width: `1.5`
- Rounded line caps and joins
**DO NOT:**
- Generate new icons with AI/LLM
- Use emoji or unicode symbols as icons
- Use external icon libraries
- Create inline SVG content
---
## Project Overview
botserver is the core backend for General Bots - an open-source conversational AI platform built in Rust. It provides:
- **Bootstrap System**: Auto-installs PostgreSQL, MinIO, Redis, LLM servers
- **Package Manager**: Manages bot deployments and service lifecycle
- **BASIC Interpreter**: Executes conversation scripts via Rhai
- **Multi-Channel Support**: Web, WhatsApp, Teams, Email
- **Knowledge Base**: Document ingestion with vector search
### Workspace Structure
```
botserver/ # Main server (this project)
botlib/ # Shared library - types, utilities, HTTP client
botui/ # Web/Desktop UI (Axum + Tauri)
botapp/ # Desktop app wrapper (Tauri)
botbook/ # Documentation (mdBook)
botmodels/ # Data models visualization
botplugin/ # Browser extension
```
---
## Database Migrations
### Creating New Migrations
```bash
# 1. Version is always 6.1.0
# 2. List existing migrations
ls -la migrations/
# 3. Create new migration folder
mkdir migrations/6.1.0_my_feature
# 4. Create up.sql and down.sql (TABLES AND INDEXES ONLY)
```
### Migration Structure
```
migrations/
├── 6.0.0_initial_schema/
├── 6.0.1_bot_memories/
├── ...
├── 6.1.0_enterprise_features/
│ ├── up.sql
│ └── down.sql
└── 6.1.0_next_feature/ # YOUR NEW MIGRATION
├── up.sql
└── down.sql
```
### Migration Best Practices
- Use `IF NOT EXISTS` for all CREATE TABLE statements
- Use `IF EXISTS` for all DROP statements in down.sql
- Always create indexes for foreign keys
- **NO triggers** - handle updated_at in application code
- **NO views** - use queries in application code
- **NO functions** - use application logic
- Use TEXT with `_json` suffix for JSON data (not JSONB)
---
## LLM Workflow Strategy
### Two Types of LLM Work
1. **Execution Mode (Fazer)**
- Pre-annotate phrases and send for execution
- Focus on automation freedom
- Less concerned with code details
- Primary concern: Is the LLM destroying something?
- Trust but verify output doesn't break existing functionality
2. **Review Mode (Conferir)**
- Read generated code with full attention
- Line-by-line verification
- Check for correctness, security, performance
- Validate against requirements
### Development Process
1. **One requirement at a time** with sequential commits
2. **Start with docs** - explain user behavior before coding
3. **Design first** - spend time on architecture
4. **On unresolved error** - stop and consult with web search enabled
### LLM Fallback Strategy (After 3 attempts / 10 minutes)
1. DeepSeek-V3-0324 (good architect, reliable)
2. gpt-5-chat (slower but thorough)
3. gpt-oss-120b (final validation)
4. Claude Web (for complex debugging, unit tests, UI)
---
## Code Generation Rules
### CRITICAL REQUIREMENTS
```
- KISS, NO TALK, SECURED ENTERPRISE GRADE THREAD SAFE CODE ONLY
- Use rustc 1.90.0 (1159e78c4 2025-09-14)
- No placeholders, never comment/uncomment code, no explanations
- All code must be complete, professional, production-ready
- REMOVE ALL COMMENTS FROM GENERATED CODE
- Always include full updated code files - never partial
- Only return files that have actual changes
- DO NOT WRITE ERROR HANDLING CODE - LET IT CRASH
- Return 0 warnings - review unused imports!
- NO DEAD CODE - implement real functionality, never use _ for unused
```
### Documentation Rules
```
- Rust code examples ONLY in docs/reference/architecture.md (gbapp chapter)
- All other docs: BASIC, bash, JSON, SQL, YAML only
- Scan for ALL_CAPS.md files created at wrong places - delete or integrate to docs/
- Keep only README.md and PROMPT.md at project root level
```
### Frontend Rules
```
- Use HTMX to minimize JavaScript - delegate logic to Rust server
- NO external CDN - all JS/CSS must be local in vendor/ folders
- Server-side rendering with Askama templates returning HTML
- Endpoints return HTML fragments, not JSON (for HTMX)
```
### Rust Patterns
```rust
// Use rand::rng() instead of rand::thread_rng()
let mut rng = rand::rng();
// Use diesel for database (NOT sqlx)
use diesel::prelude::*;
// All config from AppConfig - no hardcoded values
let url = config.drive.endpoint.clone();
// Logging (all-in-one-line, unique messages)
info!("Processing request id={} user={}", req_id, user_id);
```
### Dependency Management
```
- Use diesel - remove any sqlx references
- After adding to Cargo.toml: cargo audit must show 0 warnings
- If audit fails, find alternative library
- Minimize redundancy - check existing libs before adding new ones
- Review src/ to identify reusable patterns and libraries
```
### botserver Specifics
```
- Sessions MUST be retrieved by id when session_id is present
- Never suggest installing software - bootstrap/package_manager handles it
- Configuration stored in .gbot/config and database bot_configuration table
- Pay attention to shared::utils and shared::models for reuse
```
---
## Documentation Validation
### Chapter Validation Process
For each documentation chapter:
1. Read the chapter instructions step by step
2. Check if source code accomplishes each instruction
3. Verify paths exist and are correct
4. Ensure 100% alignment between docs and implementation
5. Fix either docs or code to match
### Documentation Structure
```
docs/
├── api/ # API documentation (no Rust code)
├── guides/ # How-to guides (no Rust code)
└── reference/
├── architecture.md # ONLY place for Rust code examples
├── basic-language.md # BASIC only
└── configuration.md # Config examples only
```
---
## Adding New Features
### Adding a Rhai Keyword
```rust
pub fn my_keyword(state: &AppState, engine: &mut Engine) {
let db = state.db_custom.clone();
engine.register_custom_syntax(
["MY", "KEYWORD", "$expr$"],
true,
{
let db = db.clone();
move |context, inputs| {
let value = context.eval_expression_tree(&inputs[0])?;
let binding = db.as_ref().unwrap();
let fut = execute_my_keyword(binding, value);
let result = tokio::task::block_in_place(||
tokio::runtime::Handle::current().block_on(fut))
.map_err(|e| format!("DB error: {}", e))?;
Ok(Dynamic::from(result))
}
}
).unwrap();
}
pub async fn execute_my_keyword(
pool: &PgPool,
value: String,
) -> Result<Value, Box<dyn std::error::Error>> {
info!("Executing my_keyword value={}", value);
use diesel::prelude::*;
let result = diesel::insert_into(my_table::table)
.values(&NewRecord { value })
.execute(pool)?;
Ok(json!({ "rows_affected": result }))
}
```
### Adding a Data Model
```rust
use chrono::{DateTime, Utc};
use diesel::prelude::*;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Queryable, Selectable, Insertable, Serialize, Deserialize)]
#[diesel(table_name = crate::schema::users)]
#[diesel(check_for_backend(diesel::pg::Pg))]
pub struct User {
pub id: Uuid,
pub status: i16,
pub email: String,
pub age: Option<i16>,
pub metadata: Vec<u8>,
pub created_at: DateTime<Utc>,
}
```
### Adding a Service/Endpoint (HTMX Pattern)
```rust
use axum::{routing::get, Router, extract::State, response::Html};
use askama::Template;
#[derive(Template)]
#[template(path = "partials/items.html")]
struct ItemsTemplate {
items: Vec<Item>,
}
pub fn configure() -> Router<AppState> {
Router::new()
.route("/api/items", get(list_handler))
}
async fn list_handler(
State(state): State<Arc<AppState>>,
) -> Html<String> {
let conn = state.conn.get().unwrap();
let items = items::table.load::<Item>(&conn).unwrap();
let template = ItemsTemplate { items };
Html(template.render().unwrap())
}
```
---
## Final Steps Before Commit
```bash
# Check for warnings
cargo check 2>&1 | grep warning
# Audit dependencies (must be 0 warnings)
cargo audit
# Build release
cargo build --release
# Run tests
cargo test
# Verify no dead code with _ prefixes
grep -r "let _" src/ --include="*.rs"
# Verify version is 6.1.0
grep "^version" Cargo.toml | grep "6.1.0"
# Verify no views/triggers/functions in migrations
grep -r "CREATE VIEW\|CREATE TRIGGER\|CREATE FUNCTION" migrations/
```
### Pre-Commit Checklist
1. Version is 6.1.0 in all workspace Cargo.toml files
2. No views, triggers, or functions in migrations
3. All JSON columns use TEXT with `_json` suffix
---
## Output Format
### Shell Script Format
```sh
#!/bin/bash
cat > src/module/file.rs << 'EOF'
use std::io;
pub fn my_function() -> Result<(), io::Error> {
Ok(())
}
EOF
```
### Rules
- Only return MODIFIED files
- Never return unchanged files
- Use `cat > path << 'EOF'` format
- Include complete file content
- No partial snippets
---
## Key Files Reference
```
src/main.rs # Entry point, bootstrap, Axum server
src/lib.rs # Module exports, feature gates
src/core/
bootstrap/mod.rs # Auto-install services
session/mod.rs # Session management
bot/mod.rs # Bot orchestration
config/mod.rs # Configuration management
package_manager/ # Service lifecycle
src/basic/ # BASIC/Rhai interpreter
src/shared/
state.rs # AppState definition
utils.rs # Utility functions
models.rs # Database models
```
---
## Dependencies (Key Libraries)
| Library | Version | Purpose |
|---------|---------|---------|
| axum | 0.7.5 | Web framework |
| diesel | 2.1 | PostgreSQL ORM (NOT sqlx) |
| tokio | 1.41 | Async runtime |
| rhai | git | BASIC scripting |
| reqwest | 0.12 | HTTP client |
| serde | 1.0 | Serialization |
| askama | 0.12 | HTML Templates |
---
## Remember
- **Two LLM modes**: Execution (fazer) vs Review (conferir)
- **Rust code**: Only in architecture.md documentation
- **HTMX**: Minimize JS, delegate to server
- **Local assets**: No CDN, all vendor files local
- **Dead code**: Never use _ prefix, implement real code
- **cargo audit**: Must pass with 0 warnings
- **diesel**: No sqlx references
- **Sessions**: Always retrieve by ID when present
- **Config**: Never hardcode values, use AppConfig
- **Bootstrap**: Never suggest manual installation
- **Warnings**: Target zero warnings before commit
- **Version**: Always 6.1.0 - do not change without approval
- **Migrations**: TABLES AND INDEXES ONLY - no views, triggers, functions
- **Stalwart**: Use Stalwart IMAP/JMAP API for email features (sieve, filters, etc.)
- **JSON**: Use TEXT columns with `_json` suffix, not JSONB
---
## Monitor Keywords (ON EMAIL, ON CHANGE)
These keywords register event-driven monitors similar to `SET SCHEDULER`, but triggered by external events.
### ON EMAIL - Email Monitoring
Triggers a script when an email arrives at the specified address.
```basic
' Basic usage - trigger on any email to address
ON EMAIL "support@company.com"
email = GET LAST "email_received_events"
TALK "New email from " + email.from_address + ": " + email.subject
END ON
' With FROM filter - only trigger for specific sender
ON EMAIL "orders@company.com" FROM "supplier@vendor.com"
' Process supplier orders
END ON
' With SUBJECT filter - only trigger for matching subjects
ON EMAIL "alerts@company.com" SUBJECT "URGENT"
' Handle urgent alerts
END ON
```
**Database Tables:**
- `email_monitors` - Configuration for email monitoring
- `email_received_events` - Log of received emails to process
**TriggerKind:** `EmailReceived = 5`
### ON CHANGE - Folder Monitoring
Triggers a script when files change in cloud storage folders (GDrive, OneDrive, Dropbox) or local filesystem.
**Uses same `account://` syntax as COPY, MOVE, and other file operations.**
```basic
' Using account:// syntax (recommended) - auto-detects provider from email
ON CHANGE "account://user@gmail.com/Documents/invoices"
file = GET LAST "folder_change_events"
TALK "File changed: " + file.file_name + " (" + file.event_type + ")"
END ON
' OneDrive via account://
ON CHANGE "account://user@outlook.com/Business/contracts"
' Process OneDrive changes
END ON
' Direct provider syntax (without account)
ON CHANGE "gdrive:///shared/reports"
' Process Google Drive changes (requires USE ACCOUNT first)
END ON
ON CHANGE "onedrive:///documents"
' Process OneDrive changes
END ON
ON CHANGE "dropbox:///team/assets"
' Process Dropbox changes
END ON
' Local filesystem monitoring
ON CHANGE "/var/uploads/incoming"
' Process local filesystem changes
END ON
' With specific event types filter
ON CHANGE "account://user@gmail.com/uploads" EVENTS "create, modify"
' Only trigger on create and modify, ignore delete
END ON
' Watch for deletions only
ON CHANGE "gdrive:///archive" EVENTS "delete"
' Log when files are removed from archive
END ON
```
**Path Syntax:**
- `account://email@domain.com/path` - Uses connected account (auto-detects provider)
- `gdrive:///path` - Google Drive direct
- `onedrive:///path` - OneDrive direct
- `dropbox:///path` - Dropbox direct
- `/local/path` - Local filesystem
**Provider Auto-Detection (from email):**
- `@gmail.com`, `@google.com` → Google Drive
- `@outlook.com`, `@hotmail.com`, `@live.com` → OneDrive
- Other emails → Default to Google Drive
**Event Types:**
- `create` - New file created
- `modify` - File content changed
- `delete` - File deleted
- `rename` - File renamed
- `move` - File moved to different folder
**Database Tables:**
- `folder_monitors` - Configuration for folder monitoring
- `folder_change_events` - Log of detected changes to process
**TriggerKind:** `FolderChange = 6`
### TriggerKind Enum Values
```rust
pub enum TriggerKind {
Scheduled = 0, // SET SCHEDULER
TableUpdate = 1, // ON UPDATE OF "table"
TableInsert = 2, // ON INSERT OF "table"
TableDelete = 3, // ON DELETE OF "table"
Webhook = 4, // WEBHOOK
EmailReceived = 5, // ON EMAIL
FolderChange = 6, // ON CHANGE
}
```

293
README.md
View file

@ -1,154 +1,235 @@
# General Bots - Enterprise-Grade LLM Orchestrator
** **Checkout our FREE [Intranet Quickstart Bot](https://github.com/pragmatismo-io/IntranetBotQuickStart.gbai)** **
![General Bot Logo](https://github.com/GeneralBots/botserver/blob/main/logo.png?raw=true)
Welcome to General Bot Community Edition
----------------
**A strongly-typed LLM conversational platform focused on convention over configuration and code-less approaches.**
![General Bot Logo](https://raw.githubusercontent.com/pragmatismo-io/BotServer/master/logo.png)
## Quick Links
General Bot is a package based chat bot server focused in convention over configuration and code-less approaches, which brings software packages and application server concepts to help parallel bot development.
In this [MSDN](https://blogs.msdn.microsoft.com/buckwoody/2018/09/25/applied-ai-using-a-bot-for-password-reset/) article you can have an overview of a General Bots application.
- **[Getting Started](docs/guides/getting-started.md)** - Installation and first bot
- **[API Reference](docs/api/README.md)** - REST and WebSocket endpoints
- **[BASIC Language](docs/reference/basic-language.md)** - Dialog scripting reference
## What is General Bots?
### What is a Bot Server?
General Bots is a **self-hosted AI automation platform** that provides:
![General Bots Starting From Scrach](https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-open-core-starting-from-scratch.gif)
- **Multi-Vendor LLM API** - Unified interface for OpenAI, Groq, Claude, Anthropic
- **MCP + LLM Tools Generation** - Instant tool creation from code/functions
- **Semantic Caching** - Intelligent response caching (70% cost reduction)
- **Web Automation Engine** - Browser automation + AI intelligence
- **Enterprise Data Connectors** - CRM, ERP, database native integrations
- **Git-like Version Control** - Full history with rollback capabilities
Bot Server accelerates the process of developing a bot. It provisions all code
base, resources and deployment to the cloud, and gives you templates you can
choose from whenever you need a new bot. The server has a database and service
backend allowing you to further modify your bot package directly by downloading
a zip file, editing and uploading it back to the server (deploying process) with
no code. The Bot Server also provides a framework to develop bot packages in a more
advanced fashion writing custom code in editors like Visual Studio Code, Atom or Brackets.
## Quick Start
Everyone can create bots by just copying and pasting some files and using their
favorite tools like Excel (or any text editor) or Photoshop (or any image
editor).
### Prerequisites
Package Quick Reference
------------
|Whatsapp|Web|Core|KB|
|----|-----|----|----|
|[whatsapp.gblib](https://github.com/pragmatismo-io/BotServer/tree/master/packages/whatsapp.gblib)|[default.gbui](https://github.com/pragmatismo-io/BotServer/tree/master/packages/default.gbui)|[core.gbapp](https://github.com/pragmatismo-io/BotServer/tree/master/packages/core.gbapp)|[kb.gbapp](https://github.com/pragmatismo-io/BotServer/tree/master/packages/kb.gbapp)|
- **Rust** (1.75+) - [Install from rustup.rs](https://rustup.rs/)
- **Git** - [Download from git-scm.com](https://git-scm.com/downloads)
![General Bot Logo](https://raw.githubusercontent.com/pragmatismo-io/BotServer/master/docs/images/general-bots-stack.png)
### Installation
### The same build process for everyone
```bash
git clone https://github.com/GeneralBots/botserver
cd botserver
cargo run
```
![General Bots Block Architecture](https://raw.githubusercontent.com/pragmatismo-io/BotServer/master/docs/images/general-bots-block-architecture.png)
On first run, botserver automatically sets up PostgreSQL, S3 storage, Redis cache, and downloads AI models.
GeneralBots aims to delivery bots in azure in a very easy and fast fashion. Use
Office tools like Word or Excel to edit your Bot - using code (JavaScript or TypeScript) just to empower custom requirements.
The server will be available at `http://localhost:8080`.
## Documentation
#### Use Excel for (Hierarchical) Knowledge Base Editing
```
docs/
├── api/ # API documentation
│ ├── README.md # API overview
│ ├── rest-endpoints.md # HTTP endpoints
│ └── websocket.md # Real-time communication
├── guides/ # How-to guides
│ ├── getting-started.md # Quick start
│ ├── deployment.md # Production setup
│ └── templates.md # Using templates
└── reference/ # Technical reference
├── basic-language.md # BASIC keywords
├── configuration.md # Config options
└── architecture.md # System design
```
![General Bots Inside Excel can enable bot production the masses](https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/general-bots-composing-subjects-json-and-excel.gif)
## Key Features
#### Use Visual Studio for a complete .gbai package building system
### 4 Essential Keywords
![General Bots Inside Visual Studio Code provides a complete artificial intelligence based conversational platform](https://raw.githubusercontent.com/pragmatismo-io/BotServer/master/docs/images/general-bots-inside-visual-studio-code-provides-a-complete-artificial-intelligence-based-conversational-platform.png)
```basic
USE KB "kb-name" ' Load knowledge base into vector database
CLEAR KB "kb-name" ' Remove KB from session
USE TOOL "tool-name" ' Make tool available to LLM
CLEAR TOOLS ' Remove all tools from session
```
### Example Bot
How To
------
```basic
' customer-support.bas
USE KB "support-docs"
USE TOOL "create-ticket"
USE TOOL "check-order"
### Run the server locally
SET CONTEXT "support" AS "You are a helpful customer support agent."
1. Install [Node.js](https://www.npmjs.com/get-npm) the current generation General Bot code execution platform;
2. Open a **Terminal** on Linux and Mac or a **Command Prompt** window on Windows;
3. Type `npm install -g botserver` and press *ENTER*;
4. Type `gbot` to run the server core.
TALK "Welcome! How can I help you today?"
```
Notes:
## Command-Line Options
* [*nodejs.install* Chocolatey Package](https://chocolatey.org/packages/nodejs.install) is also available.
* The zip source code of General Bot is also available for [Download](https://codeload.github.com/pragmatismo-io/BotServer/zip/master);
```bash
cargo run # Default: console UI + web server
cargo run -- --noconsole # Background service mode
cargo run -- --desktop # Desktop application (Tauri)
cargo run -- --tenant <name> # Specify tenant
cargo run -- --container # LXC container mode
```
### Configure the server to deploy specific directory
## Environment Variables
1. Create/Edit the .env file and add the ADDITIONAL_DEPLOY_PATH key pointing to the .gbai local parent folder of .gbapp, .gbot, .gbtheme, .gbkb package directories.
2. Specify STORAGE_SYNC to TRUE so database sync is run when the server is run.
3. In case of Microsoft SQL Server add the following keys: STORAGE_SERVER, STORAGE_NAME, STORAGE_USERNAME, STORAGE_PASSWORD, STORAGE_DIALECT to `mssql`.
Only directory service variables are required:
Note:
| Variable | Purpose |
|----------|---------|
| `DIRECTORY_URL` | Zitadel instance URL |
| `DIRECTORY_CLIENT_ID` | OAuth client ID |
| `DIRECTORY_CLIENT_SECRET` | OAuth client secret |
* You can specify several bots separated by semicolon, the BotServer will serve all of them at once.
All service credentials are managed automatically. See [Configuration](docs/reference/configuration.md) for details.
## Setup development environment (Windows)
## Current Status
1. [Optional] Install [Chocolatey](https://chocolatey.org/install), a Windows Package Manager;
2. Install [git](`https://git-scm.com/`), a Software Configuration Management (SCM).;
3. Install [Node.js](npmjs.com/get-npm), a [Runtime system](https://en.wikipedia.org/wiki/Runtime_system).
(https://www.npmjs.com/get-npm) (suggested: LTS 8.x.x);
4. Install [Visual Studio Code](https://chocolatey.org/packages/nodejs.install), Brackets or Atom as an editor of your choice;
5. [Fork](https://en.wikipedia.org/wiki/Fork_(software_development)) by visiting https://github.com/pragmatismo-io/BotServer/fork
6. Clone the just forked repository by running `git clone <your-forked-repository-url>/BotServer.git` ;
7. Run `npm install -g typescript`;
8. Run `npm install` on Command Prompt or PowerShell on the General Bot source-code folder;
9. Enter './packages/default.gbui' folder;
10. Run `npm install` folled by `npm run build` (To build default Bot UI);
11. Enter the On the downloaded folder (../..);
12. Compile the bot server by `tsc`.
13. Run the bot server by `npm start`.
**Version:** 6.0.8
**Build Status:** SUCCESS
**Production Ready:** YES
Note:
## Deployment
* Whenever you are ready to turn your open-source bot ideas in form of .gbapp (source-code) and artifacts like .gbkb, .gbtheme, .gbot or the .gbai full package read [CONTRIBUTING.md](https://github.com/pragmatismo-io/BotServer/blob/master/CONTRIBUTING.md) about performing Pull Requests (PR) and creating other public custom packages repositories of your own personal or organization General Bot Community Edition powered packages.
See [Deployment Guide](docs/guides/deployment.md) for:
### Running unit tests
- Single server setup
- Docker Compose
- LXC containers
- Kubernetes
- Reverse proxy configuration
1. Enter the BotServer root folder.
2. Run tests by `npm test`.
## Contributing
### Just copy the source code to your machine
We welcome contributions! Please read our contributing guidelines before submitting PRs.
1. [Download] the Zip file of (https://codeload.github.com/pragmatismo-io/BotServer/zip/master)
## Security
### Updating the Bot Knoledge Base (.gbkb folder)
Security issues should be reported to: **security@pragmatismo.com.br**
The subjects.json file contains all information related to the subject tree and can be used to build the menu carrousel as well give a set of words to be used as subject catcher in the conversation. A hierarchy can be specified.
## License
### Creating a new Theme folder (.gbtheme folder)
General Bot Copyright (c) pragmatismo.com.br. All rights reserved.
Licensed under the **AGPL-3.0**.
A theme is composed of some CSS files and images. That set of files can change
everything in the General Bot UI. Use them extensively before going to change
the UI application itself (HTML & JS).
According to our dual licensing model, this program can be used either under the terms of the GNU Affero General Public License, version 3, or under a proprietary license.
Package Types
-------------
## Support
- **GitHub Issues:** [github.com/GeneralBots/botserver/issues](https://github.com/GeneralBots/botserver/issues)
- **Stack Overflow:** Tag questions with `generalbots`
- **Video Tutorial:** [7 AI General Bots LLM Templates](https://www.youtube.com/watch?v=KJgvUPXi3Fw)
### .gbai
## Contributors
Embraces all packages types (content, logic & conversation) into a pluggable bot
directory. [A sample .gbai is available](https://github.com/pragmatismo-io/IntranetBotQuickStart.gbai).
<a href="https://github.com/generalbots/botserver/graphs/contributors">
<img src="https://contrib.rocks/image?repo=generalbots/botserver" />
</a>
### .gbapp
---
The artificial intelligence extensions in form of pluggable apps. Dialogs,
Services and all model related to data. A set of interactions, use cases,
integrations in form of conversationals dialogs.
The .gbapp adds the General Bot base library (botlib) for building Node.js TypeScript Apps packages.
**General Bots Code Name:** [Guaribas](https://en.wikipedia.org/wiki/Guaribas)
> "No one should have to do work that can be done by a machine." - Roberto Mangabeira Unger
Four components builds up a General Bot App:
* dialogs
* models
* services
* tests
#### Dialogs
All code contained in a dialog builds the flow to custom conversations in
built-in and additional packages .
#### Models
Models builds the foundation of data relationships in form of entities.
#### Services
Services are a façade for bot back-end logic and other custom processing.
#### Tests
Tests try to automate code execution validation before crashing in production.
### .gbot
An expression of an artificial inteligence entity. A .gbot file defines
all bots dependencies related to services and other resources.
### .gbtheme
A theme of a bot at a given time. CSS files & images that can compose all UI
presentation and using it a branding can be done. [A sample .gbtheme is available](https://github.com/pragmatismo-io/Office365.gbtheme)
### .gbkb
A set of subjects that bot knows in a form of hierarchical menu-based QnA. [A sample .gbkb is available](https://github.com/pragmatismo-io/ProjectOnline.gbkb).
### .gblib
Shared code that can be used across bot apps.
Reference
---------
### GeneralBots admin commands
General Bot can be controlled by the same chat window people talk to, so
here is a list of admin commands related to deploying .gb* files.
| Command | Description |
|-----------------|-----------------------------------------------------------------------------------------------------------------|
| deployPackage | Deploy a KB package. Usage **deployPackage** [package-name]. Then, you need to run rebuildIndex. |
| undeployPackage | Undeploy a KB. Usage **undeployPackage** [package-name]. |
| redeployPackage | Undeploy and then deploys the KB. Usage **redeployPackage** [package-name]. Then, you need to run rebuildIndex. |
| setupSecurity | Setup connection to user directories. |
Discontinued commands:
| Command | Description |Reason |
|-----------------| -----------------------------------------------------------------------------------------------------------------|------|
| rebuildIndex | Rebuild Azure Search indexes, must be run after **deployPackage** or **redeployPackage**. | Now it is called automatically |
### Credits & Inspiration
* Rodrigo Rodriguez (me@rodrigorodriguez.com) - Coding, Docs & Architecture.
* David Lerner (david.lerner@hotmail.com) - UI, UX & Theming.
* Eduardo Romeiro (eromeirosp@outlook.com) - Content & UX.
* Jorge Ramos (jramos@pobox.com) - Coding, Docs & Architecture.
Powered by Microsoft [BOT Framework](https://dev.botframework.com/) and [Azure](http://www.azure.com).
General Bot Code Name is [Guaribas](https://en.wikipedia.org/wiki/Guaribas), the name of a city in Brasil, state of Piaui.
[Roberto Mangabeira Unger](http://www.robertounger.com/en/): "No one should have to do work that can be done by a machine".
## License & Warranty
General Bot Copyright (c) Pragmatismo.io. All rights reserved.
Licensed under the AGPL-3.0.
According to our dual licensing model, this program can be used either
under the terms of the GNU Affero General Public License, version 3,
or under a proprietary license.
The texts of the GNU Affero General Public License with an additional
permission and of our proprietary license can be found at and
in the LICENSE file you have received along with this program.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
"General Bot" is a registered trademark of Pragmatismo.io.
The licensing of the program under the AGPLv3 does not imply a
trademark license. Therefore any rights, title and interest in
our trademarks remain entirely with us.

112
VERSION.md Normal file
View file

@ -0,0 +1,112 @@
# Release History
## Version 0.1.8
* Republishing.
## Version 0.1.7
* 100% automated development environement setup.
* Azure Deployer based on ARM done - setup is easy as F5 in Visual Studio.
* Auto-ngrok - No more reverse proxy manual configuration.
* Strategy to replicate itself in several subscriptions done.
## Version 0.1.6
* Updated packages references.
## Version 0.1.5
* Updated packages references.
## Version 0.1.4
* Error handling improved and logging enriched as well.
* Setting DATABASE_ is now STORAGE_.
## Version 0.1.3
* FIX: Admin now is internationalized.
* FIX: Webchat now receives a private token.
* FIX: OAuth2 now has got revised and included state to avoid CSRF attacks.
* FIX: Now server will only start with a secure administration password.
## Version 0.1.2
* NEW: kb.gbapp now has a complete browser of excel articles.
* FIX: Some security improved.
* NEW: Protocol changes for exchanging questions between UI and Bot Server.
## Version 0.1.0
- NEW: Migration to Bot Framework v4.
## Version 0.0.31
- FIX: Updated dependencies versions.
## Version 0.0.30
- FIX: Packages updated.
- NEW: DATABASE_SYNC_ALTER environment parameter.
- NEW: DATABASE_SYNC_FORCE environment parameter.
- NEW: Define constraint names in MSSQL.
## Version 0.0.29
- NEW: Added STT and TTS capabilities to default.gbui.
## Version 0.0.28
- FIX: gbui packages updated.
## Version 0.0.27
- FIX: Packages updated.
## Version 0.0.26
- FIX: Packages updated.
- NEW: If a bot package's name begins with '.', then it is ignored.
- NEW: Created DATABASE_LOGGING environment parameter.
## Version 0.0.25
- FIX: Whastapp line now can be turned off;
- FIX: More error logging on BuildMin.
## Version 0.0.24
- FIX: AskDialog compilation error.
- FIX: More Whatsapp line adjustments: Duplicated 'Hi!' & log enrichment.
## Version 0.0.23
- FIX: Duplicated asking on main loop removed.
- FIX: Whatsapp log phrase correction.
- FIX: Directline can now receive messages sent in not-in-conversation, projector-only fashion.
## Version 0.0.22
- NEW: Auto-dispatch to dialog based on intent name.
## Version 0.0.21
- FIX: Whatsapp directline client improved.
## Version 0.0.20
- NEW: Whatsapp directline client is now working in preview.
## Version 0.0.19
- NEW: Whatsapp directline client started.
- NEW: Console directline client.
- NEW: Now each .gbapp has it own set of syspackages loaded.
- NEW: Added support for Whatsapp external service key on bot instance model.
## Version 0.0.18
- FIX: .gbapp files now correctly loaded before other package types so custom models can be used to sync DB.
- NEW: Removed Boot Package feature. Now every .gbot found on deploy folders are deployed on startup.

View file

@ -1,89 +0,0 @@
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR"
OUTPUT_FILE="/tmp/prompt.out"
echo "Consolidated LLM Context" > "$OUTPUT_FILE"
prompts=(
"./prompts/dev/platform/shared.md"
"./prompts/dev/platform/cli.md"
"./prompts/dev/platform/ide.md"
"./Cargo.toml"
)
for file in "${prompts[@]}"; do
if [ -f "$file" ]; then
cat "$file" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
fi
done
dirs=(
"auth"
#"automation"
#"basic"
#"bootstrap"
"bot"
#"channels"
#"config"
#"context"
#"drive_monitor"
"email"
"file"
#"kb"
"llm"
#"llm_models"
"meet"
#"org"
#"package_manager"
#"riot_compiler"
"session"
"shared"
#"tests"
#"tools"
#"ui"
#"ui_tree"
#"web_server"
#"web_automation"
)
for dir in "${dirs[@]}"; do
find "$PROJECT_ROOT/src/$dir" -name "*.rs" | while read -r file; do
echo "$file" >> "$OUTPUT_FILE"
cat "$file" >> "$OUTPUT_FILE"
done
done
# Additional specific files
files=(
"$PROJECT_ROOT/src/main.rs"
#"$PROJECT_ROOT/src/basic/keywords/mod.rs"
)
for file in "${files[@]}"; do
echo "$file" >> "$OUTPUT_FILE"
cat "$file" >> "$OUTPUT_FILE"
done
# Remove all blank lines and reduce whitespace greater than 1 space
sed -i 's/[[:space:]]*$//' "$OUTPUT_FILE"
sed -i '/^$/d' "$OUTPUT_FILE"
sed -i 's/ \+/ /g' "$OUTPUT_FILE"
# Calculate and display token count (approximation: words * 1.3)
WORD_COUNT=$(wc -w < "$OUTPUT_FILE")
TOKEN_COUNT=$(echo "$WORD_COUNT * 1.3 / 1" | bc)
FILE_SIZE=$(wc -c < "$OUTPUT_FILE")
echo "" >> "$OUTPUT_FILE"
echo "Approximate token count: $TOKEN_COUNT"
echo "Context size: $FILE_SIZE bytes"
cat "$OUTPUT_FILE" | xclip -selection clipboard
echo "Content copied to clipboard (xclip)"
rm -f "$OUTPUT_FILE"

View file

@ -1,14 +0,0 @@
[general]
# Configure Askama to look for templates in ui/ directory
dirs = ["ui"]
# Enable syntax highlighting hints for editors
syntax = [{ name = "html", ext = ["html"] }]
# Escape HTML by default for security
escape = "html"
# Custom filters module path
[custom]
# Register custom filters from the web::filters module
filters = "crate::web::filters"

View file

@ -1,20 +0,0 @@
{
"base_url": "http://localhost:8300",
"default_org": {
"id": "351468402772017166",
"name": "default",
"domain": "default.localhost"
},
"default_user": {
"id": "admin",
"username": "admin",
"email": "admin@localhost",
"password": "",
"first_name": "Admin",
"last_name": "User"
},
"admin_token": "2YJqHuenWddFpMw4vqw6vEHtgSF5jbvSG4NxTANnV9KJJMnaDSuvbUNSGsS06-QLFZnpFbw",
"project_id": "",
"client_id": "351468407201267726",
"client_secret": "vLxjxWiPv8fVvown7zBOqKdb7RPntqVW8fNfphaiMWtkXFI8fXQX8WoyBE5KmhJA"
}

View file

@ -1,101 +0,0 @@
{
"llama_cpp": {
"version": "b7345",
"base_url": "https://github.com/ggml-org/llama.cpp/releases/download",
"binaries": {
"linux": {
"x64": {
"cpu": "llama-{version}-bin-ubuntu-x64.zip",
"cpu_tar": "llama-{version}-bin-ubuntu-x64.tar.gz",
"vulkan": "llama-{version}-bin-ubuntu-vulkan-x64.zip",
"vulkan_tar": "llama-{version}-bin-ubuntu-vulkan-x64.tar.gz"
},
"s390x": {
"cpu": "llama-{version}-bin-ubuntu-s390x.zip",
"cpu_tar": "llama-{version}-bin-ubuntu-s390x.tar.gz"
}
},
"macos": {
"arm64": {
"cpu": "llama-{version}-bin-macos-arm64.zip",
"cpu_tar": "llama-{version}-bin-macos-arm64.tar.gz"
},
"x64": {
"cpu": "llama-{version}-bin-macos-x64.zip",
"cpu_tar": "llama-{version}-bin-macos-x64.tar.gz"
}
},
"windows": {
"x64": {
"cpu": "llama-{version}-bin-win-cpu-x64.zip",
"cuda_12": "llama-{version}-bin-win-cuda-12.4-x64.zip",
"cuda_13": "llama-{version}-bin-win-cuda-13.1-x64.zip",
"vulkan": "llama-{version}-bin-win-vulkan-x64.zip",
"sycl": "llama-{version}-bin-win-sycl-x64.zip",
"hip": "llama-{version}-bin-win-hip-radeon-x64.zip"
},
"arm64": {
"cpu": "llama-{version}-bin-win-cpu-arm64.zip",
"opencl_adreno": "llama-{version}-bin-win-opencl-adreno-arm64.zip"
}
},
"ios": {
"xcframework": "llama-{version}-xcframework.zip",
"xcframework_tar": "llama-{version}-xcframework.tar.gz"
}
},
"cuda_runtime": {
"windows": {
"cuda_12": "cudart-llama-bin-win-cuda-12.4-x64.zip",
"cuda_13": "cudart-llama-bin-win-cuda-13.1-x64.zip"
}
},
"checksums": {
"llama-b7345-bin-ubuntu-x64.zip": "sha256:91b066ecc53c20693a2d39703c12bc7a69c804b0768fee064d47df702f616e52",
"llama-b7345-bin-ubuntu-x64.tar.gz": "sha256:c5f4c8111887072a5687b42e0700116e93eddf14c5401fa7eba3ab0b8481ff4e",
"llama-b7345-bin-ubuntu-vulkan-x64.zip": "sha256:03f0b3acbead2ddc23267073a8f8e0207937c849d3704c46c61cf167c1001442",
"llama-b7345-bin-ubuntu-vulkan-x64.tar.gz": "sha256:9b02b406106cd20ea0568c43c28c587d7e4908b5b649e943adebb0e1ae726076",
"llama-b7345-bin-ubuntu-s390x.zip": "sha256:688ddad6996b1166eaaa76d5025e304c684116efe655e6e881d877505ecffccb",
"llama-b7345-bin-ubuntu-s390x.tar.gz": "sha256:118011b38b02fee21596ab5b1c40b56369da514645394b6528a466e18f4336f5",
"llama-b7345-bin-macos-arm64.zip": "sha256:72ae9b4a4605aa1223d7aabaa5326c66c268b12d13a449fcc06f61099cd02a52",
"llama-b7345-bin-macos-arm64.tar.gz": "sha256:dc7c6b64848180259db19eb5d8ee8424cffcbb053960e5c45d79db6b9ac4f40d",
"llama-b7345-bin-macos-x64.zip": "sha256:bec6b805cf7533f66b38f29305429f521dcb2be6b25dbce73a18df448ec55cc5",
"llama-b7345-bin-macos-x64.tar.gz": "sha256:9267a292f39a86b2ee5eaa553a06f4a2fda2aee35142cde40a9099432b304313",
"llama-b7345-bin-win-cpu-x64.zip": "sha256:ea449082c8e808a289d9a1e8331f90a0379ead4dd288a1b9a2d2c0a7151836cd",
"llama-b7345-bin-win-cpu-arm64.zip": "sha256:91e3ff43c123c7c30decfe5a44c291827c1e47359abaa2fbad1eb5392b3a0d85",
"llama-b7345-bin-win-cuda-12.4-x64.zip": "sha256:7a82aba2662fa7d4477a7a40894de002854bae1ab8b0039888577c9a2ca24cae",
"llama-b7345-bin-win-cuda-13.1-x64.zip": "sha256:06ea715cefb07e9862394e6d1ffa066f4c33add536b1f1aa058723f86ae05572",
"llama-b7345-bin-win-vulkan-x64.zip": "sha256:3e948bee438f46c8ea0a3faf0416549391ee945ffa624b25bc1f73d60d668679",
"llama-b7345-bin-win-sycl-x64.zip": "sha256:708ddb786cdeb43ceadaa57c0ca669ce05b86753bf859f5a95012c2ea481f9da",
"llama-b7345-bin-win-hip-radeon-x64.zip": "sha256:ba1fe643e27bae8dcdf6d7be459a6dc5d8385f179e71e749c53f52083c68e107",
"llama-b7345-bin-win-opencl-adreno-arm64.zip": "sha256:59d625d21fb64294b075c61ec1a5f01d394baf826bee2df847d0ea3ed21fa3f3",
"llama-b7345-xcframework.zip": "sha256:c94e870ba844e4938d6fccf0bfd64c9fe57884a14a3e2a4966e56e35a6cbaef4",
"llama-b7345-xcframework.tar.gz": "sha256:a542ceace2621d9d860f2ec64c1b2294ac71f292106b95dcaf239aec0a06dd55",
"cudart-llama-bin-win-cuda-12.4-x64.zip": "sha256:8c79a9b226de4b3cacfd1f83d24f962d0773be79f1e7b75c6af4ded7e32ae1d6",
"cudart-llama-bin-win-cuda-13.1-x64.zip": "sha256:f96935e7e385e3b2d0189239077c10fe8fd7e95690fea4afec455b1b6c7e3f18"
}
},
"models": {
"default_llm": {
"name": "DeepSeek-R1-Distill-Qwen-1.5B",
"url": "https://huggingface.co/bartowski/DeepSeek-R1-Distill-Qwen-1.5B-GGUF/resolve/main/DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf",
"filename": "DeepSeek-R1-Distill-Qwen-1.5B-Q3_K_M.gguf",
"size_mb": 1100,
"description": "Small reasoning model, good for CPU or minimal GPU (4GB VRAM)"
},
"default_embedding": {
"name": "BGE Small EN v1.5",
"url": "https://huggingface.co/CompendiumLabs/bge-small-en-v1.5-gguf/resolve/main/bge-small-en-v1.5-f32.gguf",
"filename": "bge-small-en-v1.5-f32.gguf",
"size_mb": 130,
"description": "Embedding model for vector search"
},
"large_llm": {
"name": "GPT-OSS 20B",
"url": "https://huggingface.co/unsloth/gpt-oss-20b-GGUF/resolve/main/gpt-oss-20b-F16.gguf",
"filename": "gpt-oss-20b-F16.gguf",
"size_mb": 40000,
"description": "Large model for GPU with 16GB+ VRAM"
}
}
}

148
deploy.cmd Normal file
View file

@ -0,0 +1,148 @@
@if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off
:: ----------------------
:: General Bots deployment.
:: -------------
:: Verify node.js installed
where node 2>nul >nul
IF %ERRORLEVEL% NEQ 0 (
echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
goto error
)
:: Setup
:: -----
setlocal enabledelayedexpansion
SET ARTIFACTS=%~dp0%..\artifacts
IF NOT DEFINED DEPLOYMENT_SOURCE (
SET DEPLOYMENT_SOURCE=%~dp0%.
)
IF NOT DEFINED DEPLOYMENT_TARGET (
SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
)
IF NOT DEFINED NEXT_MANIFEST_PATH (
SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest
IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
)
)
IF NOT DEFINED KUDU_SYNC_CMD (
:: Install kudu sync
echo Installing Kudu Sync
call npm install kudusync -g --silent
IF !ERRORLEVEL! NEQ 0 goto error
:: Locally just running "kuduSync" would also work
SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd
)
goto Deployment
:: Utility Functions
:: -----------------
:SelectNodeVersion
IF DEFINED KUDU_SELECT_NODE_VERSION_CMD (
:: The following are done only on Windows Azure Websites environment
call %KUDU_SELECT_NODE_VERSION_CMD% "%DEPLOYMENT_SOURCE%" "%DEPLOYMENT_TARGET%" "%DEPLOYMENT_TEMP%"
IF !ERRORLEVEL! NEQ 0 goto error
IF EXIST "%DEPLOYMENT_TEMP%\__nodeVersion.tmp" (
SET /p NODE_EXE=<"%DEPLOYMENT_TEMP%\__nodeVersion.tmp"
IF !ERRORLEVEL! NEQ 0 goto error
)
IF EXIST "%DEPLOYMENT_TEMP%\__npmVersion.tmp" (
SET /p NPM_JS_PATH=<"%DEPLOYMENT_TEMP%\__npmVersion.tmp"
IF !ERRORLEVEL! NEQ 0 goto error
)
IF NOT DEFINED NODE_EXE (
SET NODE_EXE=node
)
SET NPM_CMD="!NODE_EXE!" "!NPM_JS_PATH!"
) ELSE (
SET NPM_CMD=npm
SET NODE_EXE=node
)
goto :EOF
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Deployment
:: ----------
:Deployment
echo Handling node.js deployment.
:: 1. KuduSync
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_SOURCE%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error
)
:: 2. Select node version
call :SelectNodeVersion
:: 3. Install npm packages
IF EXIST "%DEPLOYMENT_TARGET%\package.json" (
pushd "%DEPLOYMENT_TARGET%"
echo [GUARIBASDEPLOYER] Installing packages for server.
call :ExecuteCmd !NPM_CMD! install --production
IF !ERRORLEVEL! NEQ 0 goto error
popd
)
:: 3.1 Install npm packages on UI
IF EXIST "%DEPLOYMENT_TARGET%\deploy\default.gbui\package.json" (
call :ExecuteCmd !NPM_CMD! config set scripts-prepend-node-path true
pushd "%DEPLOYMENT_TARGET%\deploy\default.gbui"
echo [GUARIBASDEPLOYER] Installing packages for default.gbui.
call :ExecuteCmd !NPM_CMD! install
echo [GUARIBASDEPLOYER] Building default.gbui.
call :ExecuteCmd !NPM_CMD! run build
IF !ERRORLEVEL! NEQ 0 goto error
popd
)
:: 4. Install typescript
echo [GUARIBASDEPLOYER] Transpiling...
call :ExecuteCmd node %DEPLOYMENT_TARGET%\node_modules\typescript\bin\tsc -v
call :ExecuteCmd node %DEPLOYMENT_TARGET%\node_modules\typescript\bin\tsc -p "%DEPLOYMENT_TARGET%"
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
goto end
:: Execute command routine that will echo out when error
:ExecuteCmd
setlocal
set _CMD_=%*
call %_CMD_%
if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_%
exit /b %ERRORLEVEL%
:error
endlocal
echo An error has occurred during web site deployment.
call :exitSetErrorLevel
call :exitFromFunction 2>nul
:exitSetErrorLevel
exit /b 1
:exitFromFunction
()
:end
endlocal
echo Finished successfully.

View file

@ -1,539 +0,0 @@
# General Bots Kubernetes Deployment Configuration
# This file contains the core deployment resources for running General Bots
# in a Kubernetes cluster.
#
# Usage:
# kubectl apply -f deployment.yaml
#
# Prerequisites:
# - Kubernetes cluster 1.24+
# - kubectl configured
# - Secrets created (see secrets.yaml)
# - PersistentVolumeClaim for data (optional)
---
apiVersion: v1
kind: Namespace
metadata:
name: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: namespace
---
# ConfigMap for non-sensitive configuration
apiVersion: v1
kind: ConfigMap
metadata:
name: botserver-config
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: config
data:
# Server configuration
SERVER_HOST: "0.0.0.0"
SERVER_PORT: "8080"
# LLM configuration
LLM_SERVER_HOST: "0.0.0.0"
LLM_SERVER_PORT: "8081"
LLM_SERVER_CTX_SIZE: "4096"
LLM_SERVER_N_PREDICT: "1024"
LLM_SERVER_PARALLEL: "6"
LLM_SERVER_CONT_BATCHING: "true"
LLM_CACHE: "true"
LLM_CACHE_TTL: "3600"
# Embedding configuration
EMBEDDING_PORT: "8082"
# Multi-agent configuration
A2A_ENABLED: "true"
A2A_TIMEOUT: "30"
A2A_MAX_HOPS: "5"
# Memory configuration
USER_MEMORY_ENABLED: "true"
USER_MEMORY_MAX_KEYS: "1000"
EPISODIC_MEMORY_ENABLED: "true"
# Hybrid RAG configuration
RAG_HYBRID_ENABLED: "true"
RAG_DENSE_WEIGHT: "0.7"
RAG_SPARSE_WEIGHT: "0.3"
# Observability
OBSERVABILITY_ENABLED: "true"
OBSERVABILITY_METRICS_INTERVAL: "60"
# Sandbox configuration
SANDBOX_RUNTIME: "process" # Use 'lxc' or 'docker' if available
SANDBOX_TIMEOUT: "30"
SANDBOX_MEMORY_MB: "512"
---
# Main botserver Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: botserver
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: botserver
app.kubernetes.io/version: "6.1.1"
spec:
replicas: 3
selector:
matchLabels:
app: botserver
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: botserver
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: botserver
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: "/metrics"
spec:
serviceAccountName: botserver
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
# Init container to wait for dependencies
initContainers:
- name: wait-for-postgres
image: busybox:1.35
command: ['sh', '-c', 'until nc -z postgres-service 5432; do echo waiting for postgres; sleep 2; done']
- name: wait-for-qdrant
image: busybox:1.35
command: ['sh', '-c', 'until nc -z qdrant-service 6333; do echo waiting for qdrant; sleep 2; done']
containers:
- name: botserver
image: generalbots/botserver:latest
imagePullPolicy: Always
ports:
- name: http
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP
envFrom:
- configMapRef:
name: botserver-config
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: botserver-secrets
key: database-url
- name: QDRANT_URL
valueFrom:
secretKeyRef:
name: botserver-secrets
key: qdrant-url
- name: LLM_KEY
valueFrom:
secretKeyRef:
name: botserver-secrets
key: llm-api-key
optional: true
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "2Gi"
cpu: "2000m"
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 30
volumeMounts:
- name: data
mountPath: /data
- name: models
mountPath: /models
readOnly: true
- name: gbai-packages
mountPath: /packages
volumes:
- name: data
persistentVolumeClaim:
claimName: botserver-data
- name: models
persistentVolumeClaim:
claimName: llm-models
- name: gbai-packages
persistentVolumeClaim:
claimName: gbai-packages
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- botserver
topologyKey: kubernetes.io/hostname
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: botserver
---
# LLM Server Deployment (for local model inference)
apiVersion: apps/v1
kind: Deployment
metadata:
name: llm-server
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: llm-server
spec:
replicas: 2
selector:
matchLabels:
app: llm-server
template:
metadata:
labels:
app: llm-server
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: llm-server
spec:
containers:
- name: llm-server
image: generalbots/llm-server:latest
imagePullPolicy: Always
ports:
- name: http
containerPort: 8081
protocol: TCP
env:
- name: MODEL_PATH
value: "/models/DeepSeek-R1-Distill-Qwen-7B-Q4_K_M.gguf"
- name: CTX_SIZE
value: "4096"
- name: N_PREDICT
value: "1024"
- name: PARALLEL
value: "6"
- name: CONT_BATCHING
value: "true"
- name: GPU_LAYERS
value: "35" # Adjust based on available GPU memory
resources:
requests:
memory: "8Gi"
cpu: "2000m"
# Uncomment for GPU support
# nvidia.com/gpu: 1
limits:
memory: "24Gi"
cpu: "8000m"
# nvidia.com/gpu: 1
volumeMounts:
- name: models
mountPath: /models
readOnly: true
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 120
periodSeconds: 30
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
volumes:
- name: models
persistentVolumeClaim:
claimName: llm-models
# Schedule on nodes with GPU
# nodeSelector:
# nvidia.com/gpu.present: "true"
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
---
# Service for botserver
apiVersion: v1
kind: Service
metadata:
name: botserver-service
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: service
spec:
type: ClusterIP
selector:
app: botserver
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
- name: metrics
port: 9090
targetPort: 9090
protocol: TCP
---
# Service for LLM server
apiVersion: v1
kind: Service
metadata:
name: llm-server-service
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: llm-service
spec:
type: ClusterIP
selector:
app: llm-server
ports:
- name: http
port: 8081
targetPort: 8081
protocol: TCP
---
# Headless service for StatefulSet-like DNS (if needed)
apiVersion: v1
kind: Service
metadata:
name: botserver-headless
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: headless-service
spec:
clusterIP: None
selector:
app: botserver
ports:
- name: http
port: 8080
targetPort: 8080
---
# Ingress for external access
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: botserver-ingress
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: ingress
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/websocket-services: "botserver-service"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- bot.example.com
secretName: botserver-tls
rules:
- host: bot.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: botserver-service
port:
number: 80
---
# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: botserver
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: serviceaccount
---
# Role for botserver
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: botserver-role
namespace: generalbots
rules:
- apiGroups: [""]
resources: ["configmaps", "secrets"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: botserver-rolebinding
namespace: generalbots
subjects:
- kind: ServiceAccount
name: botserver
namespace: generalbots
roleRef:
kind: Role
name: botserver-role
apiGroup: rbac.authorization.k8s.io
---
# PodDisruptionBudget for high availability
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: botserver-pdb
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: botserver
---
# PersistentVolumeClaim for botserver data
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: botserver-data
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: storage
spec:
accessModes:
- ReadWriteMany
storageClassName: standard
resources:
requests:
storage: 50Gi
---
# PersistentVolumeClaim for LLM models
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: llm-models
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: storage
spec:
accessModes:
- ReadOnlyMany
storageClassName: standard
resources:
requests:
storage: 100Gi
---
# PersistentVolumeClaim for .gbai packages
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: gbai-packages
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: storage
spec:
accessModes:
- ReadWriteMany
storageClassName: standard
resources:
requests:
storage: 20Gi

View file

@ -1,331 +0,0 @@
# General Bots Kubernetes HorizontalPodAutoscaler Configuration
# This file contains autoscaling configurations for General Bots components.
#
# Usage:
# kubectl apply -f hpa.yaml
#
# Prerequisites:
# - Metrics Server installed in cluster
# - deployment.yaml already applied
---
# HPA for botserver - scales based on CPU and memory
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: botserver-hpa
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: botserver
minReplicas: 3
maxReplicas: 20
metrics:
# Scale based on CPU utilization
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
# Scale based on memory utilization
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
# Scale based on requests per second (requires custom metrics)
# Uncomment if using Prometheus Adapter
# - type: Pods
# pods:
# metric:
# name: http_requests_per_second
# target:
# type: AverageValue
# averageValue: 100
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 5 minutes cooldown before scaling down
policies:
- type: Percent
value: 10
periodSeconds: 60
- type: Pods
value: 2
periodSeconds: 60
selectPolicy: Min # Use the most conservative policy
scaleUp:
stabilizationWindowSeconds: 60 # 1 minute before scaling up
policies:
- type: Percent
value: 100
periodSeconds: 30
- type: Pods
value: 4
periodSeconds: 30
selectPolicy: Max # Scale up aggressively when needed
---
# HPA for LLM server - scales based on CPU (inference is CPU/GPU bound)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: llm-server-hpa
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: llm-server
minReplicas: 2
maxReplicas: 10
metrics:
# Scale based on CPU utilization
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 60 # Lower threshold for LLM - inference is expensive
# Scale based on memory utilization
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
# Scale based on inference queue length (requires custom metrics)
# Uncomment if using Prometheus Adapter
# - type: Pods
# pods:
# metric:
# name: llm_inference_queue_length
# target:
# type: AverageValue
# averageValue: 5
behavior:
scaleDown:
stabilizationWindowSeconds: 600 # 10 minutes - LLM pods are expensive to recreate
policies:
- type: Pods
value: 1
periodSeconds: 120
selectPolicy: Min
scaleUp:
stabilizationWindowSeconds: 120 # 2 minutes
policies:
- type: Pods
value: 2
periodSeconds: 60
selectPolicy: Max
---
# HPA for embedding server (if deployed separately)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: embedding-server-hpa
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: embedding-server
minReplicas: 2
maxReplicas: 8
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 60
selectPolicy: Min
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Pods
value: 2
periodSeconds: 30
selectPolicy: Max
---
# Vertical Pod Autoscaler for botserver (optional - requires VPA installed)
# Automatically adjusts resource requests/limits
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: botserver-vpa
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: botserver
updatePolicy:
updateMode: "Auto" # Options: Off, Initial, Recreate, Auto
resourcePolicy:
containerPolicies:
- containerName: botserver
minAllowed:
cpu: 250m
memory: 512Mi
maxAllowed:
cpu: 4000m
memory: 8Gi
controlledResources: ["cpu", "memory"]
controlledValues: RequestsAndLimits
---
# Vertical Pod Autoscaler for LLM server
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: llm-server-vpa
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: llm-server
updatePolicy:
updateMode: "Off" # Manual for LLM - too disruptive to auto-update
resourcePolicy:
containerPolicies:
- containerName: llm-server
minAllowed:
cpu: 2000m
memory: 8Gi
maxAllowed:
cpu: 16000m
memory: 64Gi
controlledResources: ["cpu", "memory"]
controlledValues: RequestsOnly # Only adjust requests, not limits
---
# Custom metrics for HPA (requires Prometheus + Prometheus Adapter)
# This ServiceMonitor tells Prometheus to scrape botserver metrics
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: botserver-metrics
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: monitoring
spec:
selector:
matchLabels:
app: botserver
endpoints:
- port: metrics
interval: 30s
path: /metrics
namespaceSelector:
matchNames:
- generalbots
---
# PrometheusRule for alerting on scaling events
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: botserver-scaling-alerts
namespace: generalbots
labels:
app.kubernetes.io/name: generalbots
app.kubernetes.io/component: alerts
spec:
groups:
- name: botserver-scaling
rules:
# Alert when approaching max replicas
- alert: BotserverNearMaxReplicas
expr: |
kube_horizontalpodautoscaler_status_current_replicas{horizontalpodautoscaler="botserver-hpa"}
/ kube_horizontalpodautoscaler_spec_max_replicas{horizontalpodautoscaler="botserver-hpa"}
> 0.8
for: 5m
labels:
severity: warning
annotations:
summary: "Botserver near maximum replicas"
description: "Botserver HPA is at {{ $value | humanizePercentage }} of max replicas"
# Alert when at max replicas
- alert: BotserverAtMaxReplicas
expr: |
kube_horizontalpodautoscaler_status_current_replicas{horizontalpodautoscaler="botserver-hpa"}
== kube_horizontalpodautoscaler_spec_max_replicas{horizontalpodautoscaler="botserver-hpa"}
for: 10m
labels:
severity: critical
annotations:
summary: "Botserver at maximum replicas"
description: "Botserver HPA has been at max replicas for 10 minutes - consider increasing max"
# Alert on rapid scaling
- alert: BotserverRapidScaling
expr: |
increase(kube_horizontalpodautoscaler_status_current_replicas{horizontalpodautoscaler="botserver-hpa"}[10m])
> 5
for: 1m
labels:
severity: warning
annotations:
summary: "Botserver scaling rapidly"
description: "Botserver has scaled by {{ $value }} replicas in 10 minutes"
# Alert on LLM server max replicas
- alert: LLMServerAtMaxReplicas
expr: |
kube_horizontalpodautoscaler_status_current_replicas{horizontalpodautoscaler="llm-server-hpa"}
== kube_horizontalpodautoscaler_spec_max_replicas{horizontalpodautoscaler="llm-server-hpa"}
for: 5m
labels:
severity: critical
annotations:
summary: "LLM Server at maximum replicas"
description: "LLM Server HPA is at max - inference capacity may be constrained"

View file

@ -1,5 +0,0 @@
[migrations_directory]
dir = "migrations"
[print_schema]
file = "src/shared/schema.rs"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,013 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,865 @@
/*! normalize.css v1.1.3 | MIT License | git.io/normalize */
/* ========================================================================== HTML5 display definitions ========================================================================== */
/** Correct `block` display not defined in IE 6/7/8/9 and Firefox 3. */
article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; }
/** Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3. */
audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
/** Prevent modern browsers from displaying `audio` without controls. Remove excess height in iOS 5 devices. */
audio:not([controls]) { display: none; height: 0; }
/** Address styling not present in IE 7/8/9, Firefox 3, and Safari 4. Known issue: no IE 6 support. */
[hidden] { display: none; }
/* ========================================================================== Base ========================================================================== */
/** 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using `em` units. 2. Prevent iOS text size adjust after orientation change, without disabling user zoom. */
html { font-size: 100%; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ font-family: sans-serif; }
/** Address `font-family` inconsistency between `textarea` and other form elements. */
button, input, select, textarea { font-family: sans-serif; }
/** Address margins handled incorrectly in IE 6/7. */
body { margin: 0; }
/* ========================================================================== Links ========================================================================== */
/** Address `outline` inconsistency between Chrome and other browsers. */
a:focus { outline: thin dotted; }
a:active, a:hover { outline: 0; }
/** Improve readability when focused and also mouse hovered in all browsers. */
/* ========================================================================== Typography ========================================================================== */
/** Address font sizes and margins set differently in IE 6/7. Address font sizes within `section` and `article` in Firefox 4+, Safari 5, and Chrome. */
h1 { font-size: 2em; margin: 0.67em 0; }
h2 { font-size: 1.5em; margin: 0.83em 0; }
h3 { font-size: 1.17em; margin: 1em 0; }
h4, .tsd-index-panel h3 { font-size: 1em; margin: 1.33em 0; }
h5 { font-size: 0.83em; margin: 1.67em 0; }
h6 { font-size: 0.67em; margin: 2.33em 0; }
/** Address styling not present in IE 7/8/9, Safari 5, and Chrome. */
abbr[title] { border-bottom: 1px dotted; }
/** Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome. */
b, strong { font-weight: bold; }
blockquote { margin: 1em 40px; }
/** Address styling not present in Safari 5 and Chrome. */
dfn { font-style: italic; }
/** Address differences between Firefox and other browsers. Known issue: no IE 6/7 normalization. */
hr { box-sizing: content-box; height: 0; }
/** Address styling not present in IE 6/7/8/9. */
mark { background: #ff0; color: #000; }
/** Address margins set differently in IE 6/7. */
p, pre { margin: 1em 0; }
/** Correct font family set oddly in IE 6, Safari 4/5, and Chrome. */
code, kbd, pre, samp { font-family: monospace, serif; _font-family: "courier new", monospace; font-size: 1em; }
/** Improve readability of pre-formatted text in all browsers. */
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
/** Address CSS quotes not supported in IE 6/7. */
q { quotes: none; }
q:before, q:after { content: ""; content: none; }
/** Address `quotes` property not supported in Safari 4. */
/** Address inconsistent and variable font size in all browsers. */
small { font-size: 80%; }
/** Prevent `sub` and `sup` affecting `line-height` in all browsers. */
sub { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; top: -0.5em; }
sub { bottom: -0.25em; }
/* ========================================================================== Lists ========================================================================== */
/** Address margins set differently in IE 6/7. */
dl, menu, ol, ul { margin: 1em 0; }
dd { margin: 0 0 0 40px; }
/** Address paddings set differently in IE 6/7. */
menu, ol, ul { padding: 0 0 0 40px; }
/** Correct list images handled incorrectly in IE 7. */
nav ul, nav ol { list-style: none; list-style-image: none; }
/* ========================================================================== Embedded content ========================================================================== */
/** 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3. 2. Improve image quality when scaled in IE 7. */
img { border: 0; /* 1 */ -ms-interpolation-mode: bicubic; }
/* 2 */
/** Correct overflow displayed oddly in IE 9. */
svg:not(:root) { overflow: hidden; }
/* ========================================================================== Figures ========================================================================== */
/** Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11. */
figure, form { margin: 0; }
/* ========================================================================== Forms ========================================================================== */
/** Correct margin displayed oddly in IE 6/7. */
/** Define consistent border, margin, and padding. */
fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; }
/** 1. Correct color not being inherited in IE 6/7/8/9. 2. Correct text not wrapping in Firefox 3. 3. Correct alignment displayed oddly in IE 6/7. */
legend { border: 0; /* 1 */ padding: 0; white-space: normal; /* 2 */ *margin-left: -7px; }
/* 3 */
/** 1. Correct font size not being inherited in all browsers. 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5, and Chrome. 3. Improve appearance and consistency in all browsers. */
button, input, select, textarea { font-size: 100%; /* 1 */ margin: 0; /* 2 */ vertical-align: baseline; /* 3 */ *vertical-align: middle; }
/* 3 */
/** Address Firefox 3+ setting `line-height` on `input` using `!important` in the UA stylesheet. */
button, input { line-height: normal; }
/** Address inconsistent `text-transform` inheritance for `button` and `select`. All other form control elements do not inherit `text-transform` values. Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+. Correct `select` style inheritance in Firefox 4+ and Opera. */
button, select { text-transform: none; }
/** 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` and `video` controls. 2. Correct inability to style clickable `input` types in iOS. 3. Improve usability and consistency of cursor style between image-type `input` and others. 4. Remove inner spacing in IE 7 without affecting normal text inputs. Known issue: inner spacing remains in IE 6. */
button, html input[type="button"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ *overflow: visible; }
/* 4 */
input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ *overflow: visible; }
/* 4 */
/** Re-set default cursor for disabled elements. */
button[disabled], html input[disabled] { cursor: default; }
/** 1. Address box sizing set to content-box in IE 8/9. 2. Remove excess padding in IE 8/9. 3. Remove excess padding in IE 7. Known issue: excess padding remains in IE 6. */
input { /* 3 */ }
input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ *height: 13px; /* 3 */ *width: 13px; }
input[type="search"] { -webkit-appearance: textfield; /* 1 */ /* 2 */ box-sizing: content-box; }
input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; }
/** 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome (include `-moz` to future-proof). */
/** Remove inner padding and search cancel button in Safari 5 and Chrome on OS X. */
/** Remove inner padding and border in Firefox 3+. */
button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
/** 1. Remove default vertical scrollbar in IE 6/7/8/9. 2. Improve readability and alignment in all browsers. */
textarea { overflow: auto; /* 1 */ vertical-align: top; }
/* 2 */
/* ========================================================================== Tables ========================================================================== */
/** Remove most spacing between table cells. */
table { border-collapse: collapse; border-spacing: 0; }
/* Visual Studio-like style based on original C# coloring by Jason Diamond <jason@diamond.name> */
.hljs { display: inline-block; padding: 0.5em; background: white; color: black; }
.hljs-comment, .hljs-annotation, .hljs-template_comment, .diff .hljs-header, .hljs-chunk, .apache .hljs-cbracket { color: #008000; }
.hljs-keyword, .hljs-id, .hljs-built_in, .css .smalltalk .hljs-class, .hljs-winutils, .bash .hljs-variable, .tex .hljs-command, .hljs-request, .hljs-status, .nginx .hljs-title { color: #00f; }
.xml .hljs-tag { color: #00f; }
.xml .hljs-tag .hljs-value { color: #00f; }
.hljs-string, .hljs-title, .hljs-parent, .hljs-tag .hljs-value, .hljs-rules .hljs-value { color: #a31515; }
.ruby .hljs-symbol { color: #a31515; }
.ruby .hljs-symbol .hljs-string { color: #a31515; }
.hljs-template_tag, .django .hljs-variable, .hljs-addition, .hljs-flow, .hljs-stream, .apache .hljs-tag, .hljs-date, .tex .hljs-formula, .coffeescript .hljs-attribute { color: #a31515; }
.ruby .hljs-string, .hljs-decorator, .hljs-filter .hljs-argument, .hljs-localvars, .hljs-array, .hljs-attr_selector, .hljs-pseudo, .hljs-pi, .hljs-doctype, .hljs-deletion, .hljs-envvar, .hljs-shebang, .hljs-preprocessor, .hljs-pragma, .userType, .apache .hljs-sqbracket, .nginx .hljs-built_in, .tex .hljs-special, .hljs-prompt { color: #2b91af; }
.hljs-phpdoc, .hljs-javadoc, .hljs-xmlDocTag { color: #808080; }
.vhdl .hljs-typename { font-weight: bold; }
.vhdl .hljs-string { color: #666666; }
.vhdl .hljs-literal { color: #a31515; }
.vhdl .hljs-attribute { color: #00b0e8; }
.xml .hljs-attribute { color: #f00; }
.col > :first-child, .col-1 > :first-child, .col-2 > :first-child, .col-3 > :first-child, .col-4 > :first-child, .col-5 > :first-child, .col-6 > :first-child, .col-7 > :first-child, .col-8 > :first-child, .col-9 > :first-child, .col-10 > :first-child, .col-11 > :first-child, .tsd-panel > :first-child, ul.tsd-descriptions > li > :first-child, .col > :first-child > :first-child, .col-1 > :first-child > :first-child, .col-2 > :first-child > :first-child, .col-3 > :first-child > :first-child, .col-4 > :first-child > :first-child, .col-5 > :first-child > :first-child, .col-6 > :first-child > :first-child, .col-7 > :first-child > :first-child, .col-8 > :first-child > :first-child, .col-9 > :first-child > :first-child, .col-10 > :first-child > :first-child, .col-11 > :first-child > :first-child, .tsd-panel > :first-child > :first-child, ul.tsd-descriptions > li > :first-child > :first-child, .col > :first-child > :first-child > :first-child, .col-1 > :first-child > :first-child > :first-child, .col-2 > :first-child > :first-child > :first-child, .col-3 > :first-child > :first-child > :first-child, .col-4 > :first-child > :first-child > :first-child, .col-5 > :first-child > :first-child > :first-child, .col-6 > :first-child > :first-child > :first-child, .col-7 > :first-child > :first-child > :first-child, .col-8 > :first-child > :first-child > :first-child, .col-9 > :first-child > :first-child > :first-child, .col-10 > :first-child > :first-child > :first-child, .col-11 > :first-child > :first-child > :first-child, .tsd-panel > :first-child > :first-child > :first-child, ul.tsd-descriptions > li > :first-child > :first-child > :first-child { margin-top: 0; }
.col > :last-child, .col-1 > :last-child, .col-2 > :last-child, .col-3 > :last-child, .col-4 > :last-child, .col-5 > :last-child, .col-6 > :last-child, .col-7 > :last-child, .col-8 > :last-child, .col-9 > :last-child, .col-10 > :last-child, .col-11 > :last-child, .tsd-panel > :last-child, ul.tsd-descriptions > li > :last-child, .col > :last-child > :last-child, .col-1 > :last-child > :last-child, .col-2 > :last-child > :last-child, .col-3 > :last-child > :last-child, .col-4 > :last-child > :last-child, .col-5 > :last-child > :last-child, .col-6 > :last-child > :last-child, .col-7 > :last-child > :last-child, .col-8 > :last-child > :last-child, .col-9 > :last-child > :last-child, .col-10 > :last-child > :last-child, .col-11 > :last-child > :last-child, .tsd-panel > :last-child > :last-child, ul.tsd-descriptions > li > :last-child > :last-child, .col > :last-child > :last-child > :last-child, .col-1 > :last-child > :last-child > :last-child, .col-2 > :last-child > :last-child > :last-child, .col-3 > :last-child > :last-child > :last-child, .col-4 > :last-child > :last-child > :last-child, .col-5 > :last-child > :last-child > :last-child, .col-6 > :last-child > :last-child > :last-child, .col-7 > :last-child > :last-child > :last-child, .col-8 > :last-child > :last-child > :last-child, .col-9 > :last-child > :last-child > :last-child, .col-10 > :last-child > :last-child > :last-child, .col-11 > :last-child > :last-child > :last-child, .tsd-panel > :last-child > :last-child > :last-child, ul.tsd-descriptions > li > :last-child > :last-child > :last-child { margin-bottom: 0; }
.container { max-width: 1200px; margin: 0 auto; padding: 0 40px; }
@media (max-width: 640px) { .container { padding: 0 20px; } }
.container-main { padding-bottom: 200px; }
.row { position: relative; margin: 0 -10px; }
.row:after { visibility: hidden; display: block; content: ""; clear: both; height: 0; }
.col, .col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11 { box-sizing: border-box; float: left; padding: 0 10px; }
.col-1 { width: 8.33333%; }
.offset-1 { margin-left: 8.33333%; }
.col-2 { width: 16.66667%; }
.offset-2 { margin-left: 16.66667%; }
.col-3 { width: 25%; }
.offset-3 { margin-left: 25%; }
.col-4 { width: 33.33333%; }
.offset-4 { margin-left: 33.33333%; }
.col-5 { width: 41.66667%; }
.offset-5 { margin-left: 41.66667%; }
.col-6 { width: 50%; }
.offset-6 { margin-left: 50%; }
.col-7 { width: 58.33333%; }
.offset-7 { margin-left: 58.33333%; }
.col-8 { width: 66.66667%; }
.offset-8 { margin-left: 66.66667%; }
.col-9 { width: 75%; }
.offset-9 { margin-left: 75%; }
.col-10 { width: 83.33333%; }
.offset-10 { margin-left: 83.33333%; }
.col-11 { width: 91.66667%; }
.offset-11 { margin-left: 91.66667%; }
.tsd-kind-icon { display: block; position: relative; padding-left: 20px; text-indent: -20px; }
.tsd-kind-icon:before { content: ''; display: inline-block; vertical-align: middle; width: 17px; height: 17px; margin: 0 3px 2px 0; background-image: url(../images/icons.png); }
@media (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { .tsd-kind-icon:before { background-image: url(../images/icons@2x.png); background-size: 238px 204px; } }
.tsd-signature.tsd-kind-icon:before { background-position: 0 -153px; }
.tsd-kind-object-literal > .tsd-kind-icon:before { background-position: 0px -17px; }
.tsd-kind-object-literal.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -17px; }
.tsd-kind-object-literal.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -17px; }
.tsd-kind-class > .tsd-kind-icon:before { background-position: 0px -34px; }
.tsd-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -34px; }
.tsd-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -34px; }
.tsd-kind-class.tsd-has-type-parameter > .tsd-kind-icon:before { background-position: 0px -51px; }
.tsd-kind-class.tsd-has-type-parameter.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -51px; }
.tsd-kind-class.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -51px; }
.tsd-kind-interface > .tsd-kind-icon:before { background-position: 0px -68px; }
.tsd-kind-interface.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -68px; }
.tsd-kind-interface.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -68px; }
.tsd-kind-interface.tsd-has-type-parameter > .tsd-kind-icon:before { background-position: 0px -85px; }
.tsd-kind-interface.tsd-has-type-parameter.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -85px; }
.tsd-kind-interface.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -85px; }
.tsd-kind-module > .tsd-kind-icon:before { background-position: 0px -102px; }
.tsd-kind-module.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -102px; }
.tsd-kind-module.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -102px; }
.tsd-kind-external-module > .tsd-kind-icon:before { background-position: 0px -102px; }
.tsd-kind-external-module.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -102px; }
.tsd-kind-external-module.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -102px; }
.tsd-kind-enum > .tsd-kind-icon:before { background-position: 0px -119px; }
.tsd-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -119px; }
.tsd-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -119px; }
.tsd-kind-enum-member > .tsd-kind-icon:before { background-position: 0px -136px; }
.tsd-kind-enum-member.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -136px; }
.tsd-kind-enum-member.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -136px; }
.tsd-kind-signature > .tsd-kind-icon:before { background-position: 0px -153px; }
.tsd-kind-signature.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -153px; }
.tsd-kind-signature.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -153px; }
.tsd-kind-type-alias > .tsd-kind-icon:before { background-position: 0px -170px; }
.tsd-kind-type-alias.tsd-is-protected > .tsd-kind-icon:before { background-position: -17px -170px; }
.tsd-kind-type-alias.tsd-is-private > .tsd-kind-icon:before { background-position: -34px -170px; }
.tsd-kind-variable > .tsd-kind-icon:before { background-position: -136px -0px; }
.tsd-kind-variable.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -0px; }
.tsd-kind-variable.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -0px; }
.tsd-kind-variable.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -0px; }
.tsd-kind-variable.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -0px; }
.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -0px; }
.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -0px; }
.tsd-kind-variable.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -0px; }
.tsd-kind-variable.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -0px; }
.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -0px; }
.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -0px; }
.tsd-kind-variable.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -0px; }
.tsd-kind-variable.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -0px; }
.tsd-kind-property > .tsd-kind-icon:before { background-position: -136px -0px; }
.tsd-kind-property.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -0px; }
.tsd-kind-property.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -0px; }
.tsd-kind-property.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -0px; }
.tsd-kind-property.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -0px; }
.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -0px; }
.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -0px; }
.tsd-kind-property.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -0px; }
.tsd-kind-property.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -0px; }
.tsd-kind-property.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -0px; }
.tsd-kind-property.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -0px; }
.tsd-kind-property.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -0px; }
.tsd-kind-property.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -0px; }
.tsd-kind-get-signature > .tsd-kind-icon:before { background-position: -136px -17px; }
.tsd-kind-get-signature.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -17px; }
.tsd-kind-get-signature.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -17px; }
.tsd-kind-get-signature.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -17px; }
.tsd-kind-set-signature > .tsd-kind-icon:before { background-position: -136px -34px; }
.tsd-kind-set-signature.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -34px; }
.tsd-kind-set-signature.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -34px; }
.tsd-kind-set-signature.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -34px; }
.tsd-kind-accessor > .tsd-kind-icon:before { background-position: -136px -51px; }
.tsd-kind-accessor.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -51px; }
.tsd-kind-accessor.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -51px; }
.tsd-kind-accessor.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -51px; }
.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -51px; }
.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -51px; }
.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -51px; }
.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -51px; }
.tsd-kind-accessor.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -51px; }
.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -51px; }
.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -51px; }
.tsd-kind-accessor.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -51px; }
.tsd-kind-accessor.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -51px; }
.tsd-kind-function > .tsd-kind-icon:before { background-position: -136px -68px; }
.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -68px; }
.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -68px; }
.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -68px; }
.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -68px; }
.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -68px; }
.tsd-kind-function.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -68px; }
.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -68px; }
.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-function.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -68px; }
.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -68px; }
.tsd-kind-method > .tsd-kind-icon:before { background-position: -136px -68px; }
.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -68px; }
.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -68px; }
.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -68px; }
.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -68px; }
.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -68px; }
.tsd-kind-method.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -68px; }
.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -68px; }
.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-method.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -68px; }
.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -68px; }
.tsd-kind-call-signature > .tsd-kind-icon:before { background-position: -136px -68px; }
.tsd-kind-call-signature.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -68px; }
.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -68px; }
.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -68px; }
.tsd-kind-function.tsd-has-type-parameter > .tsd-kind-icon:before { background-position: -136px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -85px; }
.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -85px; }
.tsd-kind-method.tsd-has-type-parameter > .tsd-kind-icon:before { background-position: -136px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -85px; }
.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -85px; }
.tsd-kind-constructor > .tsd-kind-icon:before { background-position: -136px -102px; }
.tsd-kind-constructor.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -102px; }
.tsd-kind-constructor.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -102px; }
.tsd-kind-constructor.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -102px; }
.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -102px; }
.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -102px; }
.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -102px; }
.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -102px; }
.tsd-kind-constructor.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -102px; }
.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -102px; }
.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -102px; }
.tsd-kind-constructor.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -102px; }
.tsd-kind-constructor.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -102px; }
.tsd-kind-constructor-signature > .tsd-kind-icon:before { background-position: -136px -102px; }
.tsd-kind-constructor-signature.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -102px; }
.tsd-kind-constructor-signature.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -102px; }
.tsd-kind-constructor-signature.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -102px; }
.tsd-kind-index-signature > .tsd-kind-icon:before { background-position: -136px -119px; }
.tsd-kind-index-signature.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -119px; }
.tsd-kind-index-signature.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -119px; }
.tsd-kind-index-signature.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -119px; }
.tsd-kind-event > .tsd-kind-icon:before { background-position: -136px -136px; }
.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -136px; }
.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -136px; }
.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -136px; }
.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -136px; }
.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -136px; }
.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -136px; }
.tsd-kind-event.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -136px; }
.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -136px; }
.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -136px; }
.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -136px; }
.tsd-kind-event.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -136px; }
.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -136px; }
.tsd-is-static > .tsd-kind-icon:before { background-position: -136px -153px; }
.tsd-is-static.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -153px; }
.tsd-is-static.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -153px; }
.tsd-is-static.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -153px; }
.tsd-is-static.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -153px; }
.tsd-is-static.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -153px; }
.tsd-is-static.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -153px; }
.tsd-is-static.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -153px; }
.tsd-is-static.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -153px; }
.tsd-is-static.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -153px; }
.tsd-is-static.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -153px; }
.tsd-is-static.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -153px; }
.tsd-is-static.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -153px; }
.tsd-is-static.tsd-kind-function > .tsd-kind-icon:before { background-position: -136px -170px; }
.tsd-is-static.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -170px; }
.tsd-is-static.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -170px; }
.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -170px; }
.tsd-is-static.tsd-kind-method > .tsd-kind-icon:before { background-position: -136px -170px; }
.tsd-is-static.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -170px; }
.tsd-is-static.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -170px; }
.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -170px; }
.tsd-is-static.tsd-kind-call-signature > .tsd-kind-icon:before { background-position: -136px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -170px; }
.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -170px; }
.tsd-is-static.tsd-kind-event > .tsd-kind-icon:before { background-position: -136px -187px; }
.tsd-is-static.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { background-position: -153px -187px; }
.tsd-is-static.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { background-position: -51px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { background-position: -68px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { background-position: -85px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited > .tsd-kind-icon:before { background-position: -102px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { background-position: -170px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { background-position: -187px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { background-position: -119px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface > .tsd-kind-icon:before { background-position: -204px -187px; }
.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited > .tsd-kind-icon:before { background-position: -221px -187px; }
.no-transition { transition: none !important; }
@-webkit-keyframes fade-in { from { opacity: 0; }
to { opacity: 1; } }
@keyframes fade-in { from { opacity: 0; }
to { opacity: 1; } }
@-webkit-keyframes fade-out { from { opacity: 1; visibility: visible; }
to { opacity: 0; } }
@keyframes fade-out { from { opacity: 1; visibility: visible; }
to { opacity: 0; } }
@-webkit-keyframes fade-in-delayed { 0% { opacity: 0; }
33% { opacity: 0; }
100% { opacity: 1; } }
@keyframes fade-in-delayed { 0% { opacity: 0; }
33% { opacity: 0; }
100% { opacity: 1; } }
@-webkit-keyframes fade-out-delayed { 0% { opacity: 1; visibility: visible; }
66% { opacity: 0; }
100% { opacity: 0; } }
@keyframes fade-out-delayed { 0% { opacity: 1; visibility: visible; }
66% { opacity: 0; }
100% { opacity: 0; } }
@-webkit-keyframes shift-to-left { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); }
to { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); } }
@keyframes shift-to-left { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); }
to { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); } }
@-webkit-keyframes unshift-to-left { from { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); }
to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } }
@keyframes unshift-to-left { from { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); }
to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } }
@-webkit-keyframes pop-in-from-right { from { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); }
to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } }
@keyframes pop-in-from-right { from { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); }
to { -webkit-transform: translate(0, 0); transform: translate(0, 0); } }
@-webkit-keyframes pop-out-to-right { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); visibility: visible; }
to { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); } }
@keyframes pop-out-to-right { from { -webkit-transform: translate(0, 0); transform: translate(0, 0); visibility: visible; }
to { -webkit-transform: translate(100%, 0); transform: translate(100%, 0); } }
body { background: #fdfdfd; font-family: "Segoe UI", sans-serif; font-size: 16px; color: #222; }
a { color: #4da6ff; text-decoration: none; }
a:hover { text-decoration: underline; }
code, pre { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 0.2em; margin: 0; font-size: 14px; background-color: rgba(0, 0, 0, 0.04); }
pre { padding: 10px; }
pre code { padding: 0; font-size: 100%; background-color: transparent; }
.tsd-typography { line-height: 1.333em; }
.tsd-typography ul { list-style: square; padding: 0 0 0 20px; margin: 0; }
.tsd-typography h4, .tsd-typography .tsd-index-panel h3, .tsd-index-panel .tsd-typography h3, .tsd-typography h5, .tsd-typography h6 { font-size: 1em; margin: 0; }
.tsd-typography h5, .tsd-typography h6 { font-weight: normal; }
.tsd-typography p, .tsd-typography ul, .tsd-typography ol { margin: 1em 0; }
@media (min-width: 901px) and (max-width: 1024px) { html.default .col-content { width: 72%; }
html.default .col-menu { width: 28%; }
html.default .tsd-navigation { padding-left: 10px; } }
@media (max-width: 900px) { html.default .col-content { float: none; width: 100%; }
html.default .col-menu { position: fixed !important; overflow: auto; -webkit-overflow-scrolling: touch; overflow-scrolling: touch; z-index: 1024; top: 0 !important; bottom: 0 !important; left: auto !important; right: 0 !important; width: 100%; padding: 20px 20px 0 0; max-width: 450px; visibility: hidden; background-color: #fff; -webkit-transform: translate(100%, 0); transform: translate(100%, 0); }
html.default .col-menu > *:last-child { padding-bottom: 20px; }
html.default .overlay { content: ""; display: block; position: fixed; z-index: 1023; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.75); visibility: hidden; }
html.default.to-has-menu .overlay { -webkit-animation: fade-in 0.4s; animation: fade-in 0.4s; }
html.default.to-has-menu header, html.default.to-has-menu footer, html.default.to-has-menu .col-content { -webkit-animation: shift-to-left 0.4s; animation: shift-to-left 0.4s; }
html.default.to-has-menu .col-menu { -webkit-animation: pop-in-from-right 0.4s; animation: pop-in-from-right 0.4s; }
html.default.from-has-menu .overlay { -webkit-animation: fade-out 0.4s; animation: fade-out 0.4s; }
html.default.from-has-menu header, html.default.from-has-menu footer, html.default.from-has-menu .col-content { -webkit-animation: unshift-to-left 0.4s; animation: unshift-to-left 0.4s; }
html.default.from-has-menu .col-menu { -webkit-animation: pop-out-to-right 0.4s; animation: pop-out-to-right 0.4s; }
html.default.has-menu body { overflow: hidden; }
html.default.has-menu .overlay { visibility: visible; }
html.default.has-menu header, html.default.has-menu footer, html.default.has-menu .col-content { -webkit-transform: translate(-25%, 0); transform: translate(-25%, 0); }
html.default.has-menu .col-menu { visibility: visible; -webkit-transform: translate(0, 0); transform: translate(0, 0); } }
.tsd-page-title { padding: 70px 0 20px 0; margin: 0 0 40px 0; background: #fff; box-shadow: 0 0 5px rgba(0, 0, 0, 0.35); }
.tsd-page-title h1 { margin: 0; }
.tsd-breadcrumb { margin: 0; padding: 0; color: #808080; }
.tsd-breadcrumb a { color: #808080; text-decoration: none; }
.tsd-breadcrumb a:hover { text-decoration: underline; }
.tsd-breadcrumb li { display: inline; }
.tsd-breadcrumb li:after { content: " / "; }
html.minimal .container { margin: 0; }
html.minimal .container-main { padding-top: 50px; padding-bottom: 0; }
html.minimal .content-wrap { padding-left: 300px; }
html.minimal .tsd-navigation { position: fixed !important; overflow: auto; -webkit-overflow-scrolling: touch; overflow-scrolling: touch; box-sizing: border-box; z-index: 1; left: 0; top: 40px; bottom: 0; width: 300px; padding: 20px; margin: 0; }
html.minimal .tsd-member .tsd-member { margin-left: 0; }
html.minimal .tsd-page-toolbar { position: fixed; z-index: 2; }
html.minimal #tsd-filter .tsd-filter-group { right: 0; -webkit-transform: none; transform: none; }
html.minimal footer { background-color: transparent; }
html.minimal footer .container { padding: 0; }
html.minimal .tsd-generator { padding: 0; }
@media (max-width: 900px) { html.minimal .tsd-navigation { display: none; }
html.minimal .content-wrap { padding-left: 0; } }
dl.tsd-comment-tags { overflow: hidden; }
dl.tsd-comment-tags dt { clear: both; float: left; padding: 1px 5px; margin: 0 10px 0 0; border-radius: 4px; border: 1px solid #808080; color: #808080; font-size: 0.8em; font-weight: normal; }
dl.tsd-comment-tags dd { margin: 0 0 10px 0; }
dl.tsd-comment-tags p { margin: 0; }
.tsd-panel.tsd-comment .lead { font-size: 1.1em; line-height: 1.333em; margin-bottom: 2em; }
.tsd-panel.tsd-comment .lead:last-child { margin-bottom: 0; }
.toggle-protected .tsd-is-private { display: none; }
.toggle-public .tsd-is-private, .toggle-public .tsd-is-protected, .toggle-public .tsd-is-private-protected { display: none; }
.toggle-inherited .tsd-is-inherited { display: none; }
.toggle-only-exported .tsd-is-not-exported { display: none; }
.toggle-externals .tsd-is-external { display: none; }
#tsd-filter { position: relative; display: inline-block; height: 40px; vertical-align: bottom; }
.no-filter #tsd-filter { display: none; }
#tsd-filter .tsd-filter-group { display: inline-block; height: 40px; vertical-align: bottom; white-space: nowrap; }
#tsd-filter input { display: none; }
@media (max-width: 900px) { #tsd-filter .tsd-filter-group { display: block; position: absolute; top: 40px; right: 20px; height: auto; background-color: #fff; visibility: hidden; -webkit-transform: translate(50%, 0); transform: translate(50%, 0); box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); }
.has-options #tsd-filter .tsd-filter-group { visibility: visible; }
.to-has-options #tsd-filter .tsd-filter-group { -webkit-animation: fade-in 0.2s; animation: fade-in 0.2s; }
.from-has-options #tsd-filter .tsd-filter-group { -webkit-animation: fade-out 0.2s; animation: fade-out 0.2s; }
#tsd-filter label, #tsd-filter .tsd-select { display: block; padding-right: 20px; } }
footer { border-top: 1px solid #eee; background-color: #fff; }
footer.with-border-bottom { border-bottom: 1px solid #eee; }
footer .tsd-legend-group { font-size: 0; }
footer .tsd-legend { display: inline-block; width: 25%; padding: 0; font-size: 16px; list-style: none; line-height: 1.333em; vertical-align: top; }
@media (max-width: 900px) { footer .tsd-legend { width: 50%; } }
.tsd-hierarchy { list-style: square; padding: 0 0 0 20px; margin: 0; }
.tsd-hierarchy .target { font-weight: bold; }
.tsd-index-panel .tsd-index-content { margin-bottom: -30px !important; }
.tsd-index-panel .tsd-index-section { margin-bottom: 30px !important; }
.tsd-index-panel h3 { margin: 0 -20px 10px -20px; padding: 0 20px 10px 20px; border-bottom: 1px solid #eee; }
.tsd-index-panel ul.tsd-index-list { -webkit-column-count: 3; -moz-column-count: 3; -ms-column-count: 3; -o-column-count: 3; column-count: 3; -webkit-column-gap: 20px; -moz-column-gap: 20px; -ms-column-gap: 20px; -o-column-gap: 20px; column-gap: 20px; padding: 0; list-style: none; line-height: 1.333em; }
@media (max-width: 900px) { .tsd-index-panel ul.tsd-index-list { -webkit-column-count: 1; -moz-column-count: 1; -ms-column-count: 1; -o-column-count: 1; column-count: 1; } }
@media (min-width: 901px) and (max-width: 1024px) { .tsd-index-panel ul.tsd-index-list { -webkit-column-count: 2; -moz-column-count: 2; -ms-column-count: 2; -o-column-count: 2; column-count: 2; } }
.tsd-index-panel ul.tsd-index-list li { -webkit-column-break-inside: avoid; -moz-column-break-inside: avoid; -ms-column-break-inside: avoid; -o-column-break-inside: avoid; column-break-inside: avoid; -webkit-page-break-inside: avoid; -moz-page-break-inside: avoid; -ms-page-break-inside: avoid; -o-page-break-inside: avoid; page-break-inside: avoid; }
.tsd-index-panel a, .tsd-index-panel .tsd-parent-kind-module a { color: #9600ff; }
.tsd-index-panel .tsd-parent-kind-interface a { color: #7da01f; }
.tsd-index-panel .tsd-parent-kind-enum a { color: #cc9900; }
.tsd-index-panel .tsd-parent-kind-class a { color: #4da6ff; }
.tsd-index-panel .tsd-kind-module a { color: #9600ff; }
.tsd-index-panel .tsd-kind-interface a { color: #7da01f; }
.tsd-index-panel .tsd-kind-enum a { color: #cc9900; }
.tsd-index-panel .tsd-kind-class a { color: #4da6ff; }
.tsd-index-panel .tsd-is-private a { color: #808080; }
.tsd-flag { display: inline-block; padding: 1px 5px; border-radius: 4px; color: #fff; background-color: #808080; text-indent: 0; font-size: 14px; font-weight: normal; }
.tsd-anchor { position: absolute; top: -100px; }
.tsd-member { position: relative; }
.tsd-member .tsd-anchor + h3 { margin-top: 0; margin-bottom: 0; border-bottom: none; }
.tsd-navigation { padding: 0 0 0 40px; }
.tsd-navigation a { display: block; padding-top: 2px; padding-bottom: 2px; border-left: 2px solid transparent; color: #222; text-decoration: none; transition: border-left-color 0.1s; }
.tsd-navigation a:hover { text-decoration: underline; }
.tsd-navigation ul { margin: 0; padding: 0; list-style: none; }
.tsd-navigation li { padding: 0; }
.tsd-navigation.primary { padding-bottom: 40px; }
.tsd-navigation.primary a { display: block; padding-top: 6px; padding-bottom: 6px; }
.tsd-navigation.primary ul li a { padding-left: 5px; }
.tsd-navigation.primary ul li li a { padding-left: 25px; }
.tsd-navigation.primary ul li li li a { padding-left: 45px; }
.tsd-navigation.primary ul li li li li a { padding-left: 65px; }
.tsd-navigation.primary ul li li li li li a { padding-left: 85px; }
.tsd-navigation.primary ul li li li li li li a { padding-left: 105px; }
.tsd-navigation.primary > ul { border-bottom: 1px solid #eee; }
.tsd-navigation.primary li { border-top: 1px solid #eee; }
.tsd-navigation.primary li.current > a { font-weight: bold; }
.tsd-navigation.primary li.label span { display: block; padding: 20px 0 6px 5px; color: #808080; }
.tsd-navigation.primary li.globals + li > span, .tsd-navigation.primary li.globals + li > a { padding-top: 20px; }
.tsd-navigation.secondary ul { transition: opacity 0.2s; }
.tsd-navigation.secondary ul li a { padding-left: 25px; }
.tsd-navigation.secondary ul li li a { padding-left: 45px; }
.tsd-navigation.secondary ul li li li a { padding-left: 65px; }
.tsd-navigation.secondary ul li li li li a { padding-left: 85px; }
.tsd-navigation.secondary ul li li li li li a { padding-left: 105px; }
.tsd-navigation.secondary ul li li li li li li a { padding-left: 125px; }
.tsd-navigation.secondary ul.current a { border-left-color: #eee; }
.tsd-navigation.secondary li.focus > a, .tsd-navigation.secondary ul.current li.focus > a { border-left-color: #000; }
.tsd-navigation.secondary li.current { margin-top: 20px; margin-bottom: 20px; border-left-color: #eee; }
.tsd-navigation.secondary li.current > a { font-weight: bold; }
@media (min-width: 901px) { .menu-sticky-wrap { position: static; }
.no-csspositionsticky .menu-sticky-wrap.sticky { position: fixed; }
.no-csspositionsticky .menu-sticky-wrap.sticky-current { position: fixed; }
.no-csspositionsticky .menu-sticky-wrap.sticky-current ul.before-current, .no-csspositionsticky .menu-sticky-wrap.sticky-current ul.after-current { opacity: 0; }
.no-csspositionsticky .menu-sticky-wrap.sticky-bottom { position: absolute; top: auto !important; left: auto !important; bottom: 0; right: 0; }
.csspositionsticky .menu-sticky-wrap.sticky { position: -webkit-sticky; position: sticky; }
.csspositionsticky .menu-sticky-wrap.sticky-current { position: -webkit-sticky; position: sticky; } }
.tsd-panel { margin: 20px 0; padding: 20px; background-color: #fff; box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); }
.tsd-panel:empty { display: none; }
.tsd-panel > h1, .tsd-panel > h2, .tsd-panel > h3 { margin: 1.5em -20px 10px -20px; padding: 0 20px 10px 20px; border-bottom: 1px solid #eee; }
.tsd-panel > h1.tsd-before-signature, .tsd-panel > h2.tsd-before-signature, .tsd-panel > h3.tsd-before-signature { margin-bottom: 0; border-bottom: 0; }
.tsd-panel table { display: block; width: 100%; overflow: auto; margin-top: 10px; word-break: normal; word-break: keep-all; }
.tsd-panel table th { font-weight: bold; }
.tsd-panel table th, .tsd-panel table td { padding: 6px 13px; border: 1px solid #ddd; }
.tsd-panel table tr { background-color: #fff; border-top: 1px solid #ccc; }
.tsd-panel table tr:nth-child(2n) { background-color: #f8f8f8; }
.tsd-panel-group { margin: 60px 0; }
.tsd-panel-group > h1, .tsd-panel-group > h2, .tsd-panel-group > h3 { padding-left: 20px; padding-right: 20px; }
#tsd-search { transition: background-color 0.2s; }
#tsd-search .title { position: relative; z-index: 2; }
#tsd-search .field { position: absolute; left: 0; top: 0; right: 40px; height: 40px; }
#tsd-search .field input { box-sizing: border-box; position: relative; top: -50px; z-index: 1; width: 100%; padding: 0 10px; opacity: 0; outline: 0; border: 0; background: transparent; color: #222; }
#tsd-search .field label { position: absolute; overflow: hidden; right: -40px; }
#tsd-search .field input, #tsd-search .title { transition: opacity 0.2s; }
#tsd-search .results { position: absolute; visibility: hidden; top: 40px; width: 100%; margin: 0; padding: 0; list-style: none; box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); }
#tsd-search .results li { padding: 0 10px; background-color: #fdfdfd; }
#tsd-search .results li:nth-child(even) { background-color: #fff; }
#tsd-search .results li.state { display: none; }
#tsd-search .results li.current, #tsd-search .results li:hover { background-color: #eee; }
#tsd-search .results a { display: block; }
#tsd-search .results a:before { top: 10px; }
#tsd-search .results span.parent { color: #808080; font-weight: normal; }
#tsd-search.has-focus { background-color: #eee; }
#tsd-search.has-focus .field input { top: 0; opacity: 1; }
#tsd-search.has-focus .title { z-index: 0; opacity: 0; }
#tsd-search.has-focus .results { visibility: visible; }
#tsd-search.loading .results li.state.loading { display: block; }
#tsd-search.failure .results li.state.failure { display: block; }
.tsd-signature { margin: 0 0 1em 0; padding: 10px; border: 1px solid #eee; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; }
.tsd-signature.tsd-kind-icon { padding-left: 30px; }
.tsd-signature.tsd-kind-icon:before { top: 10px; left: 10px; }
.tsd-panel > .tsd-signature { margin-left: -20px; margin-right: -20px; border-width: 1px 0; }
.tsd-panel > .tsd-signature.tsd-kind-icon { padding-left: 40px; }
.tsd-panel > .tsd-signature.tsd-kind-icon:before { left: 20px; }
.tsd-signature-symbol { color: #808080; font-weight: normal; }
.tsd-signature-type { font-style: italic; font-weight: normal; }
.tsd-signatures { padding: 0; margin: 0 0 1em 0; border: 1px solid #eee; }
.tsd-signatures .tsd-signature { margin: 0; border-width: 1px 0 0 0; transition: background-color 0.1s; }
.tsd-signatures .tsd-signature:first-child { border-top-width: 0; }
.tsd-signatures .tsd-signature.current { background-color: #eee; }
.tsd-signatures.active > .tsd-signature { cursor: pointer; }
.tsd-panel > .tsd-signatures { margin-left: -20px; margin-right: -20px; border-width: 1px 0; }
.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon { padding-left: 40px; }
.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon:before { left: 20px; }
.tsd-panel > a.anchor + .tsd-signatures { border-top-width: 0; margin-top: -20px; }
ul.tsd-descriptions { position: relative; overflow: hidden; transition: height 0.3s; padding: 0; list-style: none; }
ul.tsd-descriptions.active > .tsd-description { display: none; }
ul.tsd-descriptions.active > .tsd-description.current { display: block; }
ul.tsd-descriptions.active > .tsd-description.fade-in { -webkit-animation: fade-in-delayed 0.3s; animation: fade-in-delayed 0.3s; }
ul.tsd-descriptions.active > .tsd-description.fade-out { -webkit-animation: fade-out-delayed 0.3s; animation: fade-out-delayed 0.3s; position: absolute; display: block; top: 0; left: 0; right: 0; opacity: 0; visibility: hidden; }
ul.tsd-descriptions h4, ul.tsd-descriptions .tsd-index-panel h3, .tsd-index-panel ul.tsd-descriptions h3 { font-size: 16px; margin: 1em 0 0.5em 0; }
ul.tsd-parameters, ul.tsd-type-parameters { list-style: square; margin: 0; padding-left: 20px; }
ul.tsd-parameters > li.tsd-parameter-siganture, ul.tsd-type-parameters > li.tsd-parameter-siganture { list-style: none; margin-left: -20px; }
ul.tsd-parameters h5, ul.tsd-type-parameters h5 { font-size: 16px; margin: 1em 0 0.5em 0; }
ul.tsd-parameters .tsd-comment, ul.tsd-type-parameters .tsd-comment { margin-top: -0.5em; }
.tsd-sources { font-size: 14px; color: #808080; margin: 0 0 1em 0; }
.tsd-sources a { color: #808080; text-decoration: underline; }
.tsd-sources ul, .tsd-sources p { margin: 0 !important; }
.tsd-sources ul { list-style: none; padding: 0; }
.tsd-page-toolbar { position: absolute; z-index: 1; top: 0; left: 0; width: 100%; height: 40px; color: #333; background: #fff; border-bottom: 1px solid #eee; }
.tsd-page-toolbar a { color: #333; text-decoration: none; }
.tsd-page-toolbar a.title { font-weight: bold; }
.tsd-page-toolbar a.title:hover { text-decoration: underline; }
.tsd-page-toolbar .table-wrap { display: table; width: 100%; height: 40px; }
.tsd-page-toolbar .table-cell { display: table-cell; position: relative; white-space: nowrap; line-height: 40px; }
.tsd-page-toolbar .table-cell:first-child { width: 100%; }
.tsd-widget:before, .tsd-select .tsd-select-label:before, .tsd-select .tsd-select-list li:before { content: ""; display: inline-block; width: 40px; height: 40px; margin: 0 -8px 0 0; background-image: url(../images/widgets.png); background-repeat: no-repeat; text-indent: -1024px; vertical-align: bottom; }
@media (-webkit-min-device-pixel-ratio: 1.5), (min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { .tsd-widget:before, .tsd-select .tsd-select-label:before, .tsd-select .tsd-select-list li:before { background-image: url(../images/widgets@2x.png); background-size: 320px 40px; } }
.tsd-widget { display: inline-block; overflow: hidden; opacity: 0.6; height: 40px; transition: opacity 0.1s, background-color 0.2s; vertical-align: bottom; cursor: pointer; }
.tsd-widget:hover { opacity: 0.8; }
.tsd-widget.active { opacity: 1; background-color: #eee; }
.tsd-widget.no-caption { width: 40px; }
.tsd-widget.no-caption:before { margin: 0; }
.tsd-widget.search:before { background-position: 0 0; }
.tsd-widget.menu:before { background-position: -40px 0; }
.tsd-widget.options:before { background-position: -80px 0; }
.tsd-widget.options, .tsd-widget.menu { display: none; }
@media (max-width: 900px) { .tsd-widget.options, .tsd-widget.menu { display: inline-block; } }
input[type=checkbox] + .tsd-widget:before { background-position: -120px 0; }
input[type=checkbox]:checked + .tsd-widget:before { background-position: -160px 0; }
.tsd-select { position: relative; display: inline-block; height: 40px; transition: opacity 0.1s, background-color 0.2s; vertical-align: bottom; cursor: pointer; }
.tsd-select .tsd-select-label { opacity: 0.6; transition: opacity 0.2s; }
.tsd-select .tsd-select-label:before { background-position: -240px 0; }
.tsd-select.active .tsd-select-label { opacity: 0.8; }
.tsd-select.active .tsd-select-list { visibility: visible; opacity: 1; transition-delay: 0s; }
.tsd-select .tsd-select-list { position: absolute; visibility: hidden; top: 40px; left: 0; margin: 0; padding: 0; opacity: 0; list-style: none; box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); transition: visibility 0s 0.2s, opacity 0.2s; }
.tsd-select .tsd-select-list li { padding: 0 20px 0 0; background-color: #fdfdfd; }
.tsd-select .tsd-select-list li:before { background-position: 40px 0; }
.tsd-select .tsd-select-list li:nth-child(even) { background-color: #fff; }
.tsd-select .tsd-select-list li:hover { background-color: #eee; }
.tsd-select .tsd-select-list li.selected:before { background-position: -200px 0; }
@media (max-width: 900px) { .tsd-select .tsd-select-list { top: 0; left: auto; right: 100%; margin-right: -5px; }
.tsd-select .tsd-select-label:before { background-position: -280px 0; } }
img { max-width: 100%; }

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,237 @@
<!doctype html>
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>GBServer | botserver</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../assets/css/main.css">
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="../assets/js/search.js" data-base="..">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="../index.html" class="title">botserver</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<input type="checkbox" id="tsd-filter-only-exported" />
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
</div>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="../globals.html">Globals</a>
</li>
<li>
<a href="../modules/_src_app_.html">&quot;src/app&quot;</a>
</li>
<li>
<a href="_src_app_.gbserver.html">GBServer</a>
</li>
</ul>
<h1>Class GBServer</h1>
</div>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<section class="tsd-panel tsd-comment">
<div class="tsd-comment tsd-typography">
<div class="lead">
<p>General Bots open-core entry point.</p>
</div>
</div>
</section>
<section class="tsd-panel tsd-hierarchy">
<h3>Hierarchy</h3>
<ul class="tsd-hierarchy">
<li>
<span class="target">GBServer</span>
</li>
</ul>
</section>
<section class="tsd-panel-group tsd-index-group">
<h2>Index</h2>
<section class="tsd-panel tsd-index-panel">
<div class="tsd-index-content">
<section class="tsd-index-section ">
<h3>Methods</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-static"><a href="_src_app_.gbserver.html#run" class="tsd-kind-icon">run</a></li>
</ul>
</section>
</div>
</section>
</section>
<section class="tsd-panel-group tsd-member-group ">
<h2>Methods</h2>
<section class="tsd-panel tsd-member tsd-kind-method tsd-parent-kind-class tsd-is-static">
<a name="run" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagStatic">Static</span> run</h3>
<ul class="tsd-signatures tsd-kind-method tsd-parent-kind-class tsd-is-static">
<li class="tsd-signature tsd-kind-icon">run<span class="tsd-signature-symbol">(</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">void</span></li>
</ul>
<ul class="tsd-descriptions">
<li class="tsd-description">
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/app.ts#L70">src/app.ts:70</a></li>
</ul>
</aside>
<div class="tsd-comment tsd-typography">
<div class="lead">
<p> Program entry-point.</p>
</div>
</div>
<h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4>
</li>
</ul>
</section>
</section>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class="globals ">
<a href="../globals.html"><em>Globals</em></a>
</li>
<li class="current tsd-kind-external-module">
<a href="../modules/_src_app_.html">"src/app"</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
</ul>
<ul class="current">
<li class="current tsd-kind-class tsd-parent-kind-external-module">
<a href="_src_app_.gbserver.html" class="tsd-kind-icon">GBServer</a>
<ul>
<li class=" tsd-kind-method tsd-parent-kind-class tsd-is-static">
<a href="_src_app_.gbserver.html#run" class="tsd-kind-icon">run</a>
</li>
</ul>
</li>
</ul>
<ul class="after-current">
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="../modules/_src_app_.html#apppackages" class="tsd-kind-icon">app<wbr>Packages</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="../modules/_src_app_.html#bodyparser" class="tsd-kind-icon">body<wbr>Parser</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="../modules/_src_app_.html#express" class="tsd-kind-icon">express</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="../modules/_src_app_.html#logger" class="tsd-kind-icon">logger</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="../modules/_src_app_.html#opn" class="tsd-kind-icon">opn</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
</ul>
</div>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="http://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="../assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="../assets/js/search.js"><' + '/script>');</script>
</body>
</html>

340
docs/reference/globals.html Normal file
View file

@ -0,0 +1,340 @@
<!doctype html>
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>botserver</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="assets/css/main.css">
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="assets/js/search.js" data-base=".">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="index.html" class="title">botserver</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<input type="checkbox" id="tsd-filter-only-exported" />
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
</div>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="globals.html">Globals</a>
</li>
</ul>
<h1> botserver</h1>
</div>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<section class="tsd-panel-group tsd-index-group">
<h2>Index</h2>
<section class="tsd-panel tsd-index-panel">
<div class="tsd-index-content">
<section class="tsd-index-section ">
<h3>External modules</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-external-module"><a href="modules/_packages_admin_gbapp_dialogs_admindialog_.html" class="tsd-kind-icon">"packages/admin.gbapp/dialogs/<wbr>Admin<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_admin_gbapp_index_.html" class="tsd-kind-icon">"packages/admin.gbapp/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_admin_gbapp_models_adminmodel_.html" class="tsd-kind-icon">"packages/admin.gbapp/models/<wbr>Admin<wbr>Model"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_admin_gbapp_services_gbadminservice_.html" class="tsd-kind-icon">"packages/admin.gbapp/services/GBAdmin<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_admin_gbapp_strings_.html" class="tsd-kind-icon">"packages/admin.gbapp/strings"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_analytics_gblib_index_.html" class="tsd-kind-icon">"packages/analytics.gblib/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_analytics_gblib_models_index_.html" class="tsd-kind-icon">"packages/analytics.gblib/models/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_analytics_gblib_services_analyticsservice_.html" class="tsd-kind-icon">"packages/analytics.gblib/services/<wbr>Analytics<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_azuredeployer_gbapp_dialogs_botfarmdialog_.html" class="tsd-kind-icon">"packages/azuredeployer.gbapp/dialogs/<wbr>Bot<wbr>Farm<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_azuredeployer_gbapp_index_.html" class="tsd-kind-icon">"packages/azuredeployer.gbapp/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_azuredeployer_gbapp_services_azuredeployerservice_.html" class="tsd-kind-icon">"packages/azuredeployer.gbapp/services/<wbr>Azure<wbr>Deployer<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_azuredeployer_gbapp_strings_.html" class="tsd-kind-icon">"packages/azuredeployer.gbapp/strings"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_console_gblib_index_.html" class="tsd-kind-icon">"packages/console.gblib/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_console_gblib_services_consoledirectline_.html" class="tsd-kind-icon">"packages/console.gblib/services/<wbr>Console<wbr>Direct<wbr>Line"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_dialogs_welcomedialog_.html" class="tsd-kind-icon">"packages/core.gbapp/dialogs/<wbr>Welcome<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_dialogs_whoamidialog_.html" class="tsd-kind-icon">"packages/core.gbapp/dialogs/<wbr>Who<wbr>AmIDialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_index_.html" class="tsd-kind-icon">"packages/core.gbapp/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_models_gbmodel_.html" class="tsd-kind-icon">"packages/core.gbapp/models/GBModel"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_services_gbconfigservice_.html" class="tsd-kind-icon">"packages/core.gbapp/services/GBConfig<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_services_gbconversationalservice_.html" class="tsd-kind-icon">"packages/core.gbapp/services/GBConversational<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_services_gbcoreservice_.html" class="tsd-kind-icon">"packages/core.gbapp/services/GBCore<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_services_gbdeployer_.html" class="tsd-kind-icon">"packages/core.gbapp/services/GBDeployer"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_services_gbimporter_.html" class="tsd-kind-icon">"packages/core.gbapp/services/GBImporter"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_services_gbminservice_.html" class="tsd-kind-icon">"packages/core.gbapp/services/GBMin<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_core_gbapp_strings_.html" class="tsd-kind-icon">"packages/core.gbapp/strings"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_customer_satisfaction_gbapp_dialogs_feedbackdialog_.html" class="tsd-kind-icon">"packages/customer-<wbr>satisfaction.gbapp/dialogs/<wbr>Feedback<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_customer_satisfaction_gbapp_dialogs_qualitydialog_.html" class="tsd-kind-icon">"packages/customer-<wbr>satisfaction.gbapp/dialogs/<wbr>Quality<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_customer_satisfaction_gbapp_index_.html" class="tsd-kind-icon">"packages/customer-<wbr>satisfaction.gbapp/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_customer_satisfaction_gbapp_models_index_.html" class="tsd-kind-icon">"packages/customer-<wbr>satisfaction.gbapp/models/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_customer_satisfaction_gbapp_services_csservice_.html" class="tsd-kind-icon">"packages/customer-<wbr>satisfaction.gbapp/services/CSService"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_customer_satisfaction_gbapp_strings_.html" class="tsd-kind-icon">"packages/customer-<wbr>satisfaction.gbapp/strings"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_kb_gbapp_dialogs_askdialog_.html" class="tsd-kind-icon">"packages/kb.gbapp/dialogs/<wbr>Ask<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_kb_gbapp_dialogs_faqdialog_.html" class="tsd-kind-icon">"packages/kb.gbapp/dialogs/<wbr>Faq<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_kb_gbapp_dialogs_menudialog_.html" class="tsd-kind-icon">"packages/kb.gbapp/dialogs/<wbr>Menu<wbr>Dialog"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_kb_gbapp_index_.html" class="tsd-kind-icon">"packages/kb.gbapp/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_kb_gbapp_models_index_.html" class="tsd-kind-icon">"packages/kb.gbapp/models/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_kb_gbapp_services_kbservice_.html" class="tsd-kind-icon">"packages/kb.gbapp/services/KBService"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_kb_gbapp_strings_.html" class="tsd-kind-icon">"packages/kb.gbapp/strings"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_security_gblib_index_.html" class="tsd-kind-icon">"packages/security.gblib/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_security_gblib_models_index_.html" class="tsd-kind-icon">"packages/security.gblib/models/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_security_gblib_services_secservice_.html" class="tsd-kind-icon">"packages/security.gblib/services/<wbr>Sec<wbr>Service"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_whatsapp_gblib_index_.html" class="tsd-kind-icon">"packages/whatsapp.gblib/index"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_packages_whatsapp_gblib_services_whatsappdirectline_.html" class="tsd-kind-icon">"packages/whatsapp.gblib/services/<wbr>Whatsapp<wbr>Direct<wbr>Line"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_src_app_.html" class="tsd-kind-icon">"src/app"</a></li>
<li class="tsd-kind-external-module"><a href="modules/_src_logger_.html" class="tsd-kind-icon">"src/logger"</a></li>
</ul>
</section>
</div>
</section>
</section>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class="globals current ">
<a href="globals.html"><em>Globals</em></a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_dialogs_admindialog_.html">"packages/admin.gbapp/dialogs/<wbr>Admin<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_index_.html">"packages/admin.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_models_adminmodel_.html">"packages/admin.gbapp/models/<wbr>Admin<wbr>Model"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_services_gbadminservice_.html">"packages/admin.gbapp/services/GBAdmin<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_strings_.html">"packages/admin.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_analytics_gblib_index_.html">"packages/analytics.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_analytics_gblib_models_index_.html">"packages/analytics.gblib/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_analytics_gblib_services_analyticsservice_.html">"packages/analytics.gblib/services/<wbr>Analytics<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_dialogs_botfarmdialog_.html">"packages/azuredeployer.gbapp/dialogs/<wbr>Bot<wbr>Farm<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_index_.html">"packages/azuredeployer.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_services_azuredeployerservice_.html">"packages/azuredeployer.gbapp/services/<wbr>Azure<wbr>Deployer<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_strings_.html">"packages/azuredeployer.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_console_gblib_index_.html">"packages/console.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_console_gblib_services_consoledirectline_.html">"packages/console.gblib/services/<wbr>Console<wbr>Direct<wbr>Line"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_dialogs_welcomedialog_.html">"packages/core.gbapp/dialogs/<wbr>Welcome<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_dialogs_whoamidialog_.html">"packages/core.gbapp/dialogs/<wbr>Who<wbr>AmIDialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_index_.html">"packages/core.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_models_gbmodel_.html">"packages/core.gbapp/models/GBModel"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbconfigservice_.html">"packages/core.gbapp/services/GBConfig<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbconversationalservice_.html">"packages/core.gbapp/services/GBConversational<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbcoreservice_.html">"packages/core.gbapp/services/GBCore<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbdeployer_.html">"packages/core.gbapp/services/GBDeployer"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbimporter_.html">"packages/core.gbapp/services/GBImporter"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbminservice_.html">"packages/core.gbapp/services/GBMin<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_strings_.html">"packages/core.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_dialogs_feedbackdialog_.html">"packages/customer-<wbr>satisfaction.gbapp/dialogs/<wbr>Feedback<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_dialogs_qualitydialog_.html">"packages/customer-<wbr>satisfaction.gbapp/dialogs/<wbr>Quality<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_index_.html">"packages/customer-<wbr>satisfaction.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_models_index_.html">"packages/customer-<wbr>satisfaction.gbapp/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_services_csservice_.html">"packages/customer-<wbr>satisfaction.gbapp/services/CSService"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_strings_.html">"packages/customer-<wbr>satisfaction.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_dialogs_askdialog_.html">"packages/kb.gbapp/dialogs/<wbr>Ask<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_dialogs_faqdialog_.html">"packages/kb.gbapp/dialogs/<wbr>Faq<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_dialogs_menudialog_.html">"packages/kb.gbapp/dialogs/<wbr>Menu<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_index_.html">"packages/kb.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_models_index_.html">"packages/kb.gbapp/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_services_kbservice_.html">"packages/kb.gbapp/services/KBService"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_strings_.html">"packages/kb.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_security_gblib_index_.html">"packages/security.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_security_gblib_models_index_.html">"packages/security.gblib/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_security_gblib_services_secservice_.html">"packages/security.gblib/services/<wbr>Sec<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_whatsapp_gblib_index_.html">"packages/whatsapp.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_whatsapp_gblib_services_whatsappdirectline_.html">"packages/whatsapp.gblib/services/<wbr>Whatsapp<wbr>Direct<wbr>Line"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_src_app_.html">"src/app"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_src_logger_.html">"src/logger"</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
</ul>
</nav>
</div>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
</ul>
</div>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="http://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="assets/js/search.js"><' + '/script>');</script>
</body>
</html>

286
docs/reference/index.html Normal file
View file

@ -0,0 +1,286 @@
<!doctype html>
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>botserver</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="assets/css/main.css">
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="assets/js/search.js" data-base=".">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="index.html" class="title">botserver</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<input type="checkbox" id="tsd-filter-only-exported" />
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
</div>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="globals.html">Globals</a>
</li>
</ul>
<h1> botserver</h1>
</div>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<div class="tsd-panel tsd-typography">
<p><em>This is a General Bots open core package, more information can be found on the <a href="https://github.com/pragmatismo-io/BotServer">BotServer</a> repository.</em></p>
</div>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class="globals ">
<a href="globals.html"><em>Globals</em></a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_dialogs_admindialog_.html">"packages/admin.gbapp/dialogs/<wbr>Admin<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_index_.html">"packages/admin.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_models_adminmodel_.html">"packages/admin.gbapp/models/<wbr>Admin<wbr>Model"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_services_gbadminservice_.html">"packages/admin.gbapp/services/GBAdmin<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_admin_gbapp_strings_.html">"packages/admin.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_analytics_gblib_index_.html">"packages/analytics.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_analytics_gblib_models_index_.html">"packages/analytics.gblib/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_analytics_gblib_services_analyticsservice_.html">"packages/analytics.gblib/services/<wbr>Analytics<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_dialogs_botfarmdialog_.html">"packages/azuredeployer.gbapp/dialogs/<wbr>Bot<wbr>Farm<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_index_.html">"packages/azuredeployer.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_services_azuredeployerservice_.html">"packages/azuredeployer.gbapp/services/<wbr>Azure<wbr>Deployer<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_azuredeployer_gbapp_strings_.html">"packages/azuredeployer.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_console_gblib_index_.html">"packages/console.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_console_gblib_services_consoledirectline_.html">"packages/console.gblib/services/<wbr>Console<wbr>Direct<wbr>Line"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_dialogs_welcomedialog_.html">"packages/core.gbapp/dialogs/<wbr>Welcome<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_dialogs_whoamidialog_.html">"packages/core.gbapp/dialogs/<wbr>Who<wbr>AmIDialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_index_.html">"packages/core.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_models_gbmodel_.html">"packages/core.gbapp/models/GBModel"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbconfigservice_.html">"packages/core.gbapp/services/GBConfig<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbconversationalservice_.html">"packages/core.gbapp/services/GBConversational<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbcoreservice_.html">"packages/core.gbapp/services/GBCore<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbdeployer_.html">"packages/core.gbapp/services/GBDeployer"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbimporter_.html">"packages/core.gbapp/services/GBImporter"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_services_gbminservice_.html">"packages/core.gbapp/services/GBMin<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_core_gbapp_strings_.html">"packages/core.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_dialogs_feedbackdialog_.html">"packages/customer-<wbr>satisfaction.gbapp/dialogs/<wbr>Feedback<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_dialogs_qualitydialog_.html">"packages/customer-<wbr>satisfaction.gbapp/dialogs/<wbr>Quality<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_index_.html">"packages/customer-<wbr>satisfaction.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_models_index_.html">"packages/customer-<wbr>satisfaction.gbapp/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_services_csservice_.html">"packages/customer-<wbr>satisfaction.gbapp/services/CSService"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_customer_satisfaction_gbapp_strings_.html">"packages/customer-<wbr>satisfaction.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_dialogs_askdialog_.html">"packages/kb.gbapp/dialogs/<wbr>Ask<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_dialogs_faqdialog_.html">"packages/kb.gbapp/dialogs/<wbr>Faq<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_dialogs_menudialog_.html">"packages/kb.gbapp/dialogs/<wbr>Menu<wbr>Dialog"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_index_.html">"packages/kb.gbapp/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_models_index_.html">"packages/kb.gbapp/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_services_kbservice_.html">"packages/kb.gbapp/services/KBService"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_kb_gbapp_strings_.html">"packages/kb.gbapp/strings"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_security_gblib_index_.html">"packages/security.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_security_gblib_models_index_.html">"packages/security.gblib/models/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_security_gblib_services_secservice_.html">"packages/security.gblib/services/<wbr>Sec<wbr>Service"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_whatsapp_gblib_index_.html">"packages/whatsapp.gblib/index"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_packages_whatsapp_gblib_services_whatsappdirectline_.html">"packages/whatsapp.gblib/services/<wbr>Whatsapp<wbr>Direct<wbr>Line"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_src_app_.html">"src/app"</a>
</li>
<li class=" tsd-kind-external-module">
<a href="modules/_src_logger_.html">"src/logger"</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
</ul>
</nav>
</div>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
</ul>
</div>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="http://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="assets/js/search.js"><' + '/script>');</script>
</body>
</html>

View file

@ -0,0 +1,248 @@
<!doctype html>
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>&quot;src/app&quot; | botserver</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../assets/css/main.css">
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="../assets/js/search.js" data-base="..">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="../index.html" class="title">botserver</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<input type="checkbox" id="tsd-filter-only-exported" />
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
</div>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="../globals.html">Globals</a>
</li>
<li>
<a href="_src_app_.html">&quot;src/app&quot;</a>
</li>
</ul>
<h1>External module &quot;src/app&quot;</h1>
</div>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<section class="tsd-panel-group tsd-index-group">
<h2>Index</h2>
<section class="tsd-panel tsd-index-panel">
<div class="tsd-index-content">
<section class="tsd-index-section ">
<h3>Classes</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-class tsd-parent-kind-external-module"><a href="../classes/_src_app_.gbserver.html" class="tsd-kind-icon">GBServer</a></li>
</ul>
</section>
<section class="tsd-index-section tsd-is-not-exported">
<h3>Variables</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_app_.html#apppackages" class="tsd-kind-icon">app<wbr>Packages</a></li>
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_app_.html#bodyparser" class="tsd-kind-icon">body<wbr>Parser</a></li>
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_app_.html#express" class="tsd-kind-icon">express</a></li>
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_app_.html#logger" class="tsd-kind-icon">logger</a></li>
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_app_.html#opn" class="tsd-kind-icon">opn</a></li>
</ul>
</section>
</div>
</section>
</section>
<section class="tsd-panel-group tsd-member-group tsd-is-not-exported">
<h2>Variables</h2>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="apppackages" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagLet">Let</span> app<wbr>Packages</h3>
<div class="tsd-signature tsd-kind-icon">app<wbr>Packages<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol">[]</span><span class="tsd-signature-symbol"> =&nbsp;new Array&lt;IGBPackage&gt;()</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/app.ts#L59">src/app.ts:59</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="bodyparser" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagConst">Const</span> body<wbr>Parser</h3>
<div class="tsd-signature tsd-kind-icon">body<wbr>Parser<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol"> =&nbsp;require(&quot;body-parser&quot;)</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/app.ts#L38">src/app.ts:38</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="express" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagConst">Const</span> express</h3>
<div class="tsd-signature tsd-kind-icon">express<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol"> =&nbsp;require(&quot;express&quot;)</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/app.ts#L37">src/app.ts:37</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="logger" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagConst">Const</span> logger</h3>
<div class="tsd-signature tsd-kind-icon">logger<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol"> =&nbsp;require(&quot;./logger&quot;)</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/app.ts#L36">src/app.ts:36</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="opn" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagConst">Const</span> opn</h3>
<div class="tsd-signature tsd-kind-icon">opn<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol"> =&nbsp;require(&#x27;opn&#x27;)</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/app.ts#L39">src/app.ts:39</a></li>
</ul>
</aside>
</section>
</section>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class="globals ">
<a href="../globals.html"><em>Globals</em></a>
</li>
<li class="current tsd-kind-external-module">
<a href="_src_app_.html">"src/app"</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
<li class=" tsd-kind-class tsd-parent-kind-external-module">
<a href="../classes/_src_app_.gbserver.html" class="tsd-kind-icon">GBServer</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_app_.html#apppackages" class="tsd-kind-icon">app<wbr>Packages</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_app_.html#bodyparser" class="tsd-kind-icon">body<wbr>Parser</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_app_.html#express" class="tsd-kind-icon">express</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_app_.html#logger" class="tsd-kind-icon">logger</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_app_.html#opn" class="tsd-kind-icon">opn</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
</ul>
</div>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="http://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="../assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="../assets/js/search.js"><' + '/script>');</script>
</body>
</html>

View file

@ -0,0 +1,427 @@
<!doctype html>
<html class="default no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>&quot;src/logger&quot; | botserver</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../assets/css/main.css">
</head>
<body>
<header>
<div class="tsd-page-toolbar">
<div class="container">
<div class="table-wrap">
<div class="table-cell" id="tsd-search" data-index="../assets/js/search.js" data-base="..">
<div class="field">
<label for="tsd-search-field" class="tsd-widget search no-caption">Search</label>
<input id="tsd-search-field" type="text" />
</div>
<ul class="results">
<li class="state loading">Preparing search index...</li>
<li class="state failure">The search index is not available</li>
</ul>
<a href="../index.html" class="title">botserver</a>
</div>
<div class="table-cell" id="tsd-widgets">
<div id="tsd-filter">
<a href="#" class="tsd-widget options no-caption" data-toggle="options">Options</a>
<div class="tsd-filter-group">
<div class="tsd-select" id="tsd-filter-visibility">
<span class="tsd-select-label">All</span>
<ul class="tsd-select-list">
<li data-value="public">Public</li>
<li data-value="protected">Public/Protected</li>
<li data-value="private" class="selected">All</li>
</ul>
</div>
<input type="checkbox" id="tsd-filter-inherited" checked />
<label class="tsd-widget" for="tsd-filter-inherited">Inherited</label>
<input type="checkbox" id="tsd-filter-externals" checked />
<label class="tsd-widget" for="tsd-filter-externals">Externals</label>
<input type="checkbox" id="tsd-filter-only-exported" />
<label class="tsd-widget" for="tsd-filter-only-exported">Only exported</label>
</div>
</div>
<a href="#" class="tsd-widget menu no-caption" data-toggle="menu">Menu</a>
</div>
</div>
</div>
</div>
<div class="tsd-page-title">
<div class="container">
<ul class="tsd-breadcrumb">
<li>
<a href="../globals.html">Globals</a>
</li>
<li>
<a href="_src_logger_.html">&quot;src/logger&quot;</a>
</li>
</ul>
<h1>External module &quot;src/logger&quot;</h1>
</div>
</div>
</header>
<div class="container container-main">
<div class="row">
<div class="col-8 col-content">
<section class="tsd-panel-group tsd-index-group">
<h2>Index</h2>
<section class="tsd-panel tsd-index-panel">
<div class="tsd-index-content">
<section class="tsd-index-section tsd-is-not-exported">
<h3>Variables</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_logger_.html#createlogger" class="tsd-kind-icon">create<wbr>Logger</a></li>
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_logger_.html#format" class="tsd-kind-icon">format</a></li>
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_logger_.html#logger" class="tsd-kind-icon">logger</a></li>
<li class="tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_logger_.html#transports" class="tsd-kind-icon">transports</a></li>
</ul>
</section>
<section class="tsd-index-section tsd-is-not-exported">
<h3>Object literals</h3>
<ul class="tsd-index-list">
<li class="tsd-kind-object-literal tsd-parent-kind-external-module tsd-is-not-exported"><a href="_src_logger_.html#config" class="tsd-kind-icon">config</a></li>
</ul>
</section>
</div>
</section>
</section>
<section class="tsd-panel-group tsd-member-group tsd-is-not-exported">
<h2>Variables</h2>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="createlogger" class="tsd-anchor"></a>
<h3>create<wbr>Logger</h3>
<div class="tsd-signature tsd-kind-icon">create<wbr>Logger<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L33">src/logger.ts:33</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="format" class="tsd-anchor"></a>
<h3>format</h3>
<div class="tsd-signature tsd-kind-icon">format<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L33">src/logger.ts:33</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="logger" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagConst">Const</span> logger</h3>
<div class="tsd-signature tsd-kind-icon">logger<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span><span class="tsd-signature-symbol"> =&nbsp;createLogger({format: format.combine(format.colorize(),format.simple(),format.label({ label: &#x27;GeneralBots&#x27; }),format.timestamp(),format.printf(nfo &#x3D;&gt; {return &#x60;${nfo.timestamp} [${nfo.label}] ${nfo.level}: ${nfo.message}&#x60;})),levels: config.levels,transports: [new transports.Console()]})</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L58">src/logger.ts:58</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a name="transports" class="tsd-anchor"></a>
<h3>transports</h3>
<div class="tsd-signature tsd-kind-icon">transports<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">any</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L33">src/logger.ts:33</a></li>
</ul>
</aside>
</section>
</section>
<section class="tsd-panel-group tsd-member-group tsd-is-not-exported">
<h2>Object literals</h2>
<section class="tsd-panel tsd-member tsd-kind-object-literal tsd-parent-kind-external-module tsd-is-not-exported">
<a name="config" class="tsd-anchor"></a>
<h3><span class="tsd-flag ts-flagConst">Const</span> config</h3>
<div class="tsd-signature tsd-kind-icon">config<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">object</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L35">src/logger.ts:35</a></li>
</ul>
</aside>
<section class="tsd-panel tsd-member tsd-kind-object-literal tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors" class="tsd-anchor"></a>
<h3>colors</h3>
<div class="tsd-signature tsd-kind-icon">colors<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">object</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L46">src/logger.ts:46</a></li>
</ul>
</aside>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.custom" class="tsd-anchor"></a>
<h3>custom</h3>
<div class="tsd-signature tsd-kind-icon">custom<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;yellow&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L54">src/logger.ts:54</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.data" class="tsd-anchor"></a>
<h3>data</h3>
<div class="tsd-signature tsd-kind-icon">data<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;grey&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L50">src/logger.ts:50</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.debug" class="tsd-anchor"></a>
<h3>debug</h3>
<div class="tsd-signature tsd-kind-icon">debug<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;blue&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L48">src/logger.ts:48</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.error" class="tsd-anchor"></a>
<h3>error</h3>
<div class="tsd-signature tsd-kind-icon">error<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;red&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L47">src/logger.ts:47</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.info" class="tsd-anchor"></a>
<h3>info</h3>
<div class="tsd-signature tsd-kind-icon">info<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;green&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L51">src/logger.ts:51</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.silly" class="tsd-anchor"></a>
<h3>silly</h3>
<div class="tsd-signature tsd-kind-icon">silly<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;magenta&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L53">src/logger.ts:53</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.verbose" class="tsd-anchor"></a>
<h3>verbose</h3>
<div class="tsd-signature tsd-kind-icon">verbose<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;cyan&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L52">src/logger.ts:52</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.colors.warn" class="tsd-anchor"></a>
<h3>warn</h3>
<div class="tsd-signature tsd-kind-icon">warn<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">string</span><span class="tsd-signature-symbol"> =&nbsp;&quot;yellow&quot;</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L49">src/logger.ts:49</a></li>
</ul>
</aside>
</section>
</section>
<section class="tsd-panel tsd-member tsd-kind-object-literal tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels" class="tsd-anchor"></a>
<h3>levels</h3>
<div class="tsd-signature tsd-kind-icon">levels<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">object</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L36">src/logger.ts:36</a></li>
</ul>
</aside>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.custom-1" class="tsd-anchor"></a>
<h3>custom</h3>
<div class="tsd-signature tsd-kind-icon">custom<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;7</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L44">src/logger.ts:44</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.data-1" class="tsd-anchor"></a>
<h3>data</h3>
<div class="tsd-signature tsd-kind-icon">data<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;3</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L40">src/logger.ts:40</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.debug-1" class="tsd-anchor"></a>
<h3>debug</h3>
<div class="tsd-signature tsd-kind-icon">debug<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;1</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L38">src/logger.ts:38</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.error-1" class="tsd-anchor"></a>
<h3>error</h3>
<div class="tsd-signature tsd-kind-icon">error<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;0</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L37">src/logger.ts:37</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.info-1" class="tsd-anchor"></a>
<h3>info</h3>
<div class="tsd-signature tsd-kind-icon">info<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;4</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L41">src/logger.ts:41</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.silly-1" class="tsd-anchor"></a>
<h3>silly</h3>
<div class="tsd-signature tsd-kind-icon">silly<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;6</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L43">src/logger.ts:43</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.verbose-1" class="tsd-anchor"></a>
<h3>verbose</h3>
<div class="tsd-signature tsd-kind-icon">verbose<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;5</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L42">src/logger.ts:42</a></li>
</ul>
</aside>
</section>
<section class="tsd-panel tsd-member tsd-kind-variable tsd-parent-kind-object-literal tsd-is-not-exported">
<a name="config.levels.warn-1" class="tsd-anchor"></a>
<h3>warn</h3>
<div class="tsd-signature tsd-kind-icon">warn<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol"> =&nbsp;2</span></div>
<aside class="tsd-sources">
<ul>
<li>Defined in <a href="https://github.com/pragmatismo-io/botserver/blob/ecf2ba3/src/logger.ts#L39">src/logger.ts:39</a></li>
</ul>
</aside>
</section>
</section>
</section>
</section>
</div>
<div class="col-4 col-menu menu-sticky-wrap menu-highlight">
<nav class="tsd-navigation primary">
<ul>
<li class="globals ">
<a href="../globals.html"><em>Globals</em></a>
</li>
<li class="current tsd-kind-external-module">
<a href="_src_logger_.html">"src/logger"</a>
</li>
</ul>
</nav>
<nav class="tsd-navigation secondary menu-sticky">
<ul class="before-current">
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_logger_.html#createlogger" class="tsd-kind-icon">create<wbr>Logger</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_logger_.html#format" class="tsd-kind-icon">format</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_logger_.html#logger" class="tsd-kind-icon">logger</a>
</li>
<li class=" tsd-kind-variable tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_logger_.html#transports" class="tsd-kind-icon">transports</a>
</li>
<li class=" tsd-kind-object-literal tsd-parent-kind-external-module tsd-is-not-exported">
<a href="_src_logger_.html#config" class="tsd-kind-icon">config</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<footer class="with-border-bottom">
<div class="container">
<h2>Legend</h2>
<div class="tsd-legend-group">
<ul class="tsd-legend">
<li class="tsd-kind-module"><span class="tsd-kind-icon">Module</span></li>
<li class="tsd-kind-object-literal"><span class="tsd-kind-icon">Object literal</span></li>
<li class="tsd-kind-variable"><span class="tsd-kind-icon">Variable</span></li>
<li class="tsd-kind-function"><span class="tsd-kind-icon">Function</span></li>
<li class="tsd-kind-function tsd-has-type-parameter"><span class="tsd-kind-icon">Function with type parameter</span></li>
<li class="tsd-kind-index-signature"><span class="tsd-kind-icon">Index signature</span></li>
<li class="tsd-kind-type-alias"><span class="tsd-kind-icon">Type alias</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-enum"><span class="tsd-kind-icon">Enumeration</span></li>
<li class="tsd-kind-enum-member"><span class="tsd-kind-icon">Enumeration member</span></li>
<li class="tsd-kind-property tsd-parent-kind-enum"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-enum"><span class="tsd-kind-icon">Method</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-interface"><span class="tsd-kind-icon">Interface</span></li>
<li class="tsd-kind-interface tsd-has-type-parameter"><span class="tsd-kind-icon">Interface with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-interface"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-interface"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-interface"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-interface"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-class"><span class="tsd-kind-icon">Class</span></li>
<li class="tsd-kind-class tsd-has-type-parameter"><span class="tsd-kind-icon">Class with type parameter</span></li>
<li class="tsd-kind-constructor tsd-parent-kind-class"><span class="tsd-kind-icon">Constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class"><span class="tsd-kind-icon">Property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class"><span class="tsd-kind-icon">Method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class"><span class="tsd-kind-icon">Accessor</span></li>
<li class="tsd-kind-index-signature tsd-parent-kind-class"><span class="tsd-kind-icon">Index signature</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-constructor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited constructor</span></li>
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-inherited"><span class="tsd-kind-icon">Inherited accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-protected"><span class="tsd-kind-icon">Protected accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private property</span></li>
<li class="tsd-kind-method tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private method</span></li>
<li class="tsd-kind-accessor tsd-parent-kind-class tsd-is-private"><span class="tsd-kind-icon">Private accessor</span></li>
</ul>
<ul class="tsd-legend">
<li class="tsd-kind-property tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static property</span></li>
<li class="tsd-kind-call-signature tsd-parent-kind-class tsd-is-static"><span class="tsd-kind-icon">Static method</span></li>
</ul>
</div>
</div>
</footer>
<div class="container tsd-generator">
<p>Generated using <a href="http://typedoc.org/" target="_blank">TypeDoc</a></p>
</div>
<div class="overlay"></div>
<script src="../assets/js/main.js"></script>
<script>if (location.protocol == 'file:') document.write('<script src="../assets/js/search.js"><' + '/script>');</script>
</body>
</html>

View file

@ -1,98 +0,0 @@
#!/bin/bash
set -e # Exit on error
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR"
OUTPUT_FILE="/tmp/prompt.out"
# Check required commands
command -v cargo >/dev/null 2>&1 || { echo "cargo is required but not installed" >&2; exit 1; }
command -v xclip >/dev/null 2>&1 || { echo "xclip is required but not installed" >&2; exit 1; }
echo "Please, fix this consolidated LLM Context" > "$OUTPUT_FILE"
prompts=(
"./prompts/dev/platform/fix-errors.md"
"./prompts/dev/platform/shared.md"
"./Cargo.toml"
)
# Validate files exist
for file in "${prompts[@]}"; do
if [ ! -f "$file" ]; then
echo "Required file not found: $file" >&2
exit 1
fi
done
for file in "${prompts[@]}"; do
cat "$file" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
done
dirs=(
# "auth"
# "automation"
#"basic"
# "bot"
"bootstrap"
# "package_manager"
# "channels"
# "config"
# "context"
# "email"
# "file"
# "llm"
"drive_monitor"
# "llm_legacy"
# "org"
# "session"
"file"
"kb"
"shared"
#"tests"
# "tools"
# "web_automation"
# "whatsapp"
)
for dir in "${dirs[@]}"; do
if [ -d "$PROJECT_ROOT/src/$dir" ]; then
find "$PROJECT_ROOT/src/$dir" -name "*.rs" | while read -r file; do
if [ -f "$file" ]; then
echo "$file" >> "$OUTPUT_FILE"
cat "$file" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
fi
done
fi
done
# Also append the specific files you mentioned
echo "$PROJECT_ROOT/src/main.rs" >> "$OUTPUT_FILE"
cat "$PROJECT_ROOT/src/main.rs" >> "$OUTPUT_FILE"
echo "$PROJECT_ROOT/src/basic/keywords/get.rs" >> "$OUTPUT_FILE"
cat "$PROJECT_ROOT/src/basic/keywords/get.rs" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
echo "Compiling..."
cargo build --message-format=short 2>&1 | grep -E 'error' >> "$OUTPUT_FILE"
# Calculate and display token count (approximation: words * 1.3)
WORD_COUNT=$(wc -w < "$OUTPUT_FILE") || { echo "Error counting words" >&2; exit 1; }
TOKEN_COUNT=$(echo "$WORD_COUNT * 1.3 / 1" | bc) || { echo "Error calculating tokens" >&2; exit 1; }
FILE_SIZE=$(wc -c < "$OUTPUT_FILE") || { echo "Error getting file size" >&2; exit 1; }
echo "" >> "$OUTPUT_FILE"
echo "Approximate token count: $TOKEN_COUNT"
echo "Context size: $FILE_SIZE bytes"
if ! cat "$OUTPUT_FILE" | xclip -selection clipboard; then
echo "Error copying to clipboard" >&2
exit 1
fi
echo "Content copied to clipboard (xclip)"
rm -f "$OUTPUT_FILE"

2
gbot.cmd Normal file
View file

@ -0,0 +1,2 @@
@echo off
node dist/src/app.js

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
{}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

BIN
logo.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -1,12 +0,0 @@
DROP TABLE public.usage_analytics;
DROP TABLE public.message_history;
DROP TABLE public.context_injections;
DROP TABLE public.whatsapp_numbers;
DROP TABLE public.user_sessions;
DROP TABLE public.bot_channels;
DROP TABLE public.users;
DROP TABLE public.tools;
DROP TABLE public.system_automations;
DROP TABLE public.organizations;
DROP TABLE public.clicks;
DROP TABLE public.bots;

View file

@ -1,242 +0,0 @@
CREATE TABLE public.bots (
id uuid DEFAULT gen_random_uuid() NOT NULL,
"name" varchar(255) NOT NULL,
description text NULL,
llm_provider varchar(100) NOT NULL,
llm_config jsonb DEFAULT '{}'::jsonb NOT NULL,
context_provider varchar(100) NOT NULL,
context_config jsonb DEFAULT '{}'::jsonb NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
is_active bool DEFAULT true NULL,
CONSTRAINT bots_pkey PRIMARY KEY (id)
);
-- public.clicks definition
-- Drop table
-- DROP TABLE public.clicks;
CREATE TABLE public.clicks (
campaign_id text NOT NULL,
email text NOT NULL,
updated_at timestamptz DEFAULT now() NULL,
CONSTRAINT clicks_campaign_id_email_key UNIQUE (campaign_id, email)
);
-- public.organizations definition
-- Drop table
-- DROP TABLE public.organizations;
CREATE TABLE public.organizations (
org_id uuid DEFAULT gen_random_uuid() NOT NULL,
"name" varchar(255) NOT NULL,
slug varchar(255) NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT organizations_pkey PRIMARY KEY (org_id),
CONSTRAINT organizations_slug_key UNIQUE (slug)
);
CREATE INDEX idx_organizations_created_at ON public.organizations USING btree (created_at);
CREATE INDEX idx_organizations_slug ON public.organizations USING btree (slug);
-- public.system_automations definition
-- Drop table
-- DROP TABLE public.system_automations;
CREATE TABLE public.system_automations (
id uuid DEFAULT gen_random_uuid() NOT NULL,
bot_id uuid NOT NULL,
kind int4 NOT NULL,
"target" varchar(32) NULL,
schedule bpchar(20) NULL,
param varchar(32) NOT NULL,
is_active bool DEFAULT true NOT NULL,
last_triggered timestamptz NULL,
created_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT system_automations_pkey PRIMARY KEY (id)
);
CREATE INDEX idx_system_automations_active ON public.system_automations USING btree (kind) WHERE is_active;
-- public.tools definition
-- Drop table
-- DROP TABLE public.tools;
CREATE TABLE public.tools (
id uuid DEFAULT gen_random_uuid() NOT NULL,
"name" varchar(255) NOT NULL,
description text NOT NULL,
parameters jsonb DEFAULT '{}'::jsonb NOT NULL,
script text NOT NULL,
is_active bool DEFAULT true NULL,
created_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT tools_name_key UNIQUE (name),
CONSTRAINT tools_pkey PRIMARY KEY (id)
);
-- public.users definition
-- Drop table
-- DROP TABLE public.users;
CREATE TABLE public.users (
id uuid DEFAULT gen_random_uuid() NOT NULL,
username varchar(255) NOT NULL,
email varchar(255) NOT NULL,
password_hash varchar(255) NOT NULL,
phone_number varchar(50) NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
is_active bool DEFAULT true NULL,
CONSTRAINT users_email_key UNIQUE (email),
CONSTRAINT users_pkey PRIMARY KEY (id),
CONSTRAINT users_username_key UNIQUE (username)
);
-- public.bot_channels definition
-- Drop table
-- DROP TABLE public.bot_channels;
CREATE TABLE public.bot_channels (
id uuid DEFAULT gen_random_uuid() NOT NULL,
bot_id uuid NOT NULL,
channel_type int4 NOT NULL,
config jsonb DEFAULT '{}'::jsonb NOT NULL,
is_active bool DEFAULT true NULL,
created_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT bot_channels_bot_id_channel_type_key UNIQUE (bot_id, channel_type),
CONSTRAINT bot_channels_pkey PRIMARY KEY (id),
CONSTRAINT bot_channels_bot_id_fkey FOREIGN KEY (bot_id) REFERENCES public.bots(id) ON DELETE CASCADE
);
CREATE INDEX idx_bot_channels_type ON public.bot_channels USING btree (channel_type) WHERE is_active;
-- public.user_sessions definition
-- Drop table
-- DROP TABLE public.user_sessions;
CREATE TABLE public.user_sessions (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid NOT NULL,
bot_id uuid NOT NULL,
title varchar(500) DEFAULT 'New Conversation'::character varying NOT NULL,
answer_mode int4 DEFAULT 0 NOT NULL,
context_data jsonb DEFAULT '{}'::jsonb NOT NULL,
current_tool varchar(255) NULL,
message_count int4 DEFAULT 0 NOT NULL,
total_tokens int4 DEFAULT 0 NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
last_activity timestamptz DEFAULT now() NOT NULL,
CONSTRAINT user_sessions_pkey PRIMARY KEY (id),
CONSTRAINT user_sessions_bot_id_fkey FOREIGN KEY (bot_id) REFERENCES public.bots(id) ON DELETE CASCADE,
CONSTRAINT user_sessions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX idx_user_sessions_updated_at ON public.user_sessions USING btree (updated_at);
CREATE INDEX idx_user_sessions_user_bot ON public.user_sessions USING btree (user_id, bot_id);
-- public.whatsapp_numbers definition
-- Drop table
-- DROP TABLE public.whatsapp_numbers;
CREATE TABLE public.whatsapp_numbers (
id uuid DEFAULT gen_random_uuid() NOT NULL,
bot_id uuid NOT NULL,
phone_number varchar(50) NOT NULL,
is_active bool DEFAULT true NULL,
created_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT whatsapp_numbers_phone_number_bot_id_key UNIQUE (phone_number, bot_id),
CONSTRAINT whatsapp_numbers_pkey PRIMARY KEY (id),
CONSTRAINT whatsapp_numbers_bot_id_fkey FOREIGN KEY (bot_id) REFERENCES public.bots(id) ON DELETE CASCADE
);
-- public.context_injections definition
-- Drop table
-- DROP TABLE public.context_injections;
CREATE TABLE public.context_injections (
id uuid DEFAULT gen_random_uuid() NOT NULL,
session_id uuid NOT NULL,
injected_by uuid NOT NULL,
context_data jsonb NOT NULL,
reason text NULL,
created_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT context_injections_pkey PRIMARY KEY (id),
CONSTRAINT context_injections_injected_by_fkey FOREIGN KEY (injected_by) REFERENCES public.users(id) ON DELETE CASCADE,
CONSTRAINT context_injections_session_id_fkey FOREIGN KEY (session_id) REFERENCES public.user_sessions(id) ON DELETE CASCADE
);
-- public.message_history definition
-- Drop table
-- DROP TABLE public.message_history;
CREATE TABLE public.message_history (
id uuid DEFAULT gen_random_uuid() NOT NULL,
session_id uuid NOT NULL,
user_id uuid NOT NULL,
"role" int4 NOT NULL,
content_encrypted text NOT NULL,
message_type int4 DEFAULT 0 NOT NULL,
media_url text NULL,
token_count int4 DEFAULT 0 NOT NULL,
processing_time_ms int4 NULL,
llm_model varchar(100) NULL,
created_at timestamptz DEFAULT now() NOT NULL,
message_index int4 NOT NULL,
CONSTRAINT message_history_pkey PRIMARY KEY (id),
CONSTRAINT message_history_session_id_fkey FOREIGN KEY (session_id) REFERENCES public.user_sessions(id) ON DELETE CASCADE,
CONSTRAINT message_history_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX idx_message_history_created_at ON public.message_history USING btree (created_at);
CREATE INDEX idx_message_history_session_id ON public.message_history USING btree (session_id);
-- public.usage_analytics definition
-- Drop table
-- DROP TABLE public.usage_analytics;
CREATE TABLE public.usage_analytics (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid NOT NULL,
bot_id uuid NOT NULL,
session_id uuid NOT NULL,
"date" date DEFAULT CURRENT_DATE NOT NULL,
message_count int4 DEFAULT 0 NOT NULL,
total_tokens int4 DEFAULT 0 NOT NULL,
total_processing_time_ms int4 DEFAULT 0 NOT NULL,
CONSTRAINT usage_analytics_pkey PRIMARY KEY (id),
CONSTRAINT usage_analytics_bot_id_fkey FOREIGN KEY (bot_id) REFERENCES public.bots(id) ON DELETE CASCADE,
CONSTRAINT usage_analytics_session_id_fkey FOREIGN KEY (session_id) REFERENCES public.user_sessions(id) ON DELETE CASCADE,
CONSTRAINT usage_analytics_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE
);
CREATE INDEX idx_usage_analytics_date ON public.usage_analytics USING btree (date);

View file

@ -1,3 +0,0 @@
DROP INDEX idx_bot_memories_key;
DROP INDEX idx_bot_memories_bot_id;
DROP TABLE bot_memories;

View file

@ -1,13 +0,0 @@
CREATE TABLE bot_memories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
key TEXT NOT NULL,
value TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(bot_id, key)
);
CREATE INDEX idx_bot_memories_bot_id ON bot_memories(bot_id);
CREATE INDEX idx_bot_memories_key ON bot_memories(key);

View file

@ -1,23 +0,0 @@
-- Drop triggers
DROP TRIGGER IF EXISTS update_basic_tools_updated_at ON basic_tools;
DROP TRIGGER IF EXISTS update_kb_collections_updated_at ON kb_collections;
DROP TRIGGER IF EXISTS update_kb_documents_updated_at ON kb_documents;
-- Drop function
DROP FUNCTION IF EXISTS update_updated_at_column;
-- Drop indexes
DROP INDEX IF EXISTS idx_basic_tools_active;
DROP INDEX IF EXISTS idx_basic_tools_name;
DROP INDEX IF EXISTS idx_basic_tools_bot_id;
DROP INDEX IF EXISTS idx_kb_collections_name;
DROP INDEX IF EXISTS idx_kb_collections_bot_id;
DROP INDEX IF EXISTS idx_kb_documents_indexed_at;
DROP INDEX IF EXISTS idx_kb_documents_hash;
DROP INDEX IF EXISTS idx_kb_documents_collection;
DROP INDEX IF EXISTS idx_kb_documents_bot_id;
-- Drop tables
DROP TABLE IF EXISTS basic_tools;
DROP TABLE IF EXISTS kb_collections;
DROP TABLE IF EXISTS kb_documents;

View file

@ -1,102 +0,0 @@
-- Migration: Create KB and Tools tables
-- Description: Tables for Knowledge Base management and BASIC tools compilation
-- Table for KB documents metadata
CREATE TABLE IF NOT EXISTS kb_documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL,
collection_name TEXT NOT NULL,
file_path TEXT NOT NULL,
file_size BIGINT NOT NULL DEFAULT 0,
file_hash TEXT NOT NULL,
first_published_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_modified_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
indexed_at TIMESTAMPTZ,
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(bot_id, collection_name, file_path)
);
-- Index for faster lookups
CREATE INDEX IF NOT EXISTS idx_kb_documents_bot_id ON kb_documents(bot_id);
CREATE INDEX IF NOT EXISTS idx_kb_documents_collection ON kb_documents(collection_name);
CREATE INDEX IF NOT EXISTS idx_kb_documents_hash ON kb_documents(file_hash);
CREATE INDEX IF NOT EXISTS idx_kb_documents_indexed_at ON kb_documents(indexed_at);
-- Table for KB collections
CREATE TABLE IF NOT EXISTS kb_collections (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL,
name TEXT NOT NULL,
folder_path TEXT NOT NULL,
qdrant_collection TEXT NOT NULL,
document_count INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(bot_id, name)
);
-- Index for KB collections
CREATE INDEX IF NOT EXISTS idx_kb_collections_bot_id ON kb_collections(bot_id);
CREATE INDEX IF NOT EXISTS idx_kb_collections_name ON kb_collections(name);
-- Table for compiled BASIC tools
CREATE TABLE IF NOT EXISTS basic_tools (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL,
tool_name TEXT NOT NULL,
file_path TEXT NOT NULL,
ast_path TEXT NOT NULL,
mcp_json JSONB,
tool_json JSONB,
compiled_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(bot_id, tool_name)
);
-- Index for BASIC tools
CREATE INDEX IF NOT EXISTS idx_basic_tools_bot_id ON basic_tools(bot_id);
CREATE INDEX IF NOT EXISTS idx_basic_tools_name ON basic_tools(tool_name);
CREATE INDEX IF NOT EXISTS idx_basic_tools_active ON basic_tools(is_active);
-- Function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Triggers for updating updated_at
DROP TRIGGER IF EXISTS update_kb_documents_updated_at ON kb_documents;
CREATE TRIGGER update_kb_documents_updated_at
BEFORE UPDATE ON kb_documents
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
DROP TRIGGER IF EXISTS update_kb_collections_updated_at ON kb_collections;
CREATE TRIGGER update_kb_collections_updated_at
BEFORE UPDATE ON kb_collections
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
DROP TRIGGER IF EXISTS update_basic_tools_updated_at ON basic_tools;
CREATE TRIGGER update_basic_tools_updated_at
BEFORE UPDATE ON basic_tools
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
-- Comments for documentation
COMMENT ON TABLE kb_documents IS 'Stores metadata about documents in Knowledge Base collections';
COMMENT ON TABLE kb_collections IS 'Stores information about KB collections and their Qdrant mappings';
COMMENT ON TABLE basic_tools IS 'Stores compiled BASIC tools with their MCP and OpenAI tool definitions';
COMMENT ON COLUMN kb_documents.file_hash IS 'SHA256 hash of file content for change detection';
COMMENT ON COLUMN kb_documents.indexed_at IS 'Timestamp when document was last indexed in Qdrant';
COMMENT ON COLUMN kb_collections.qdrant_collection IS 'Name of corresponding Qdrant collection';
COMMENT ON COLUMN basic_tools.mcp_json IS 'Model Context Protocol tool definition';
COMMENT ON COLUMN basic_tools.tool_json IS 'OpenAI-compatible tool definition';

View file

@ -1,11 +0,0 @@
-- Drop indexes
DROP INDEX IF EXISTS idx_session_tool_name;
DROP INDEX IF EXISTS idx_session_tool_session;
DROP INDEX IF EXISTS idx_user_kb_website;
DROP INDEX IF EXISTS idx_user_kb_name;
DROP INDEX IF EXISTS idx_user_kb_bot_id;
DROP INDEX IF EXISTS idx_user_kb_user_id;
-- Drop tables
DROP TABLE IF EXISTS session_tool_associations;
DROP TABLE IF EXISTS user_kb_associations;

View file

@ -1,33 +0,0 @@
-- Migration 6.0.3: Additional KB and session tables
-- This migration adds user_kb_associations and session_tool_associations tables
-- Note: kb_documents, kb_collections, and basic_tools are already created in 6.0.2
-- Table for user KB associations (which KBs are active for a user)
CREATE TABLE IF NOT EXISTS user_kb_associations (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
bot_id TEXT NOT NULL,
kb_name TEXT NOT NULL,
is_website INTEGER NOT NULL DEFAULT 0,
website_url TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
UNIQUE(user_id, bot_id, kb_name)
);
CREATE INDEX IF NOT EXISTS idx_user_kb_user_id ON user_kb_associations(user_id);
CREATE INDEX IF NOT EXISTS idx_user_kb_bot_id ON user_kb_associations(bot_id);
CREATE INDEX IF NOT EXISTS idx_user_kb_name ON user_kb_associations(kb_name);
CREATE INDEX IF NOT EXISTS idx_user_kb_website ON user_kb_associations(is_website);
-- Table for session tool associations (which tools are available in a session)
CREATE TABLE IF NOT EXISTS session_tool_associations (
id TEXT PRIMARY KEY,
session_id TEXT NOT NULL,
tool_name TEXT NOT NULL,
added_at TEXT NOT NULL,
UNIQUE(session_id, tool_name)
);
CREATE INDEX IF NOT EXISTS idx_session_tool_session ON session_tool_associations(session_id);
CREATE INDEX IF NOT EXISTS idx_session_tool_name ON session_tool_associations(tool_name);

View file

@ -1,54 +0,0 @@
-- Drop indexes first
DROP INDEX IF EXISTS idx_gbot_sync_bot;
DROP INDEX IF EXISTS idx_component_logs_created;
DROP INDEX IF EXISTS idx_component_logs_level;
DROP INDEX IF EXISTS idx_component_logs_component;
DROP INDEX IF EXISTS idx_component_status;
DROP INDEX IF EXISTS idx_component_name;
DROP INDEX IF EXISTS idx_connection_config_active;
DROP INDEX IF EXISTS idx_connection_config_name;
DROP INDEX IF EXISTS idx_connection_config_bot;
DROP INDEX IF EXISTS idx_model_config_default;
DROP INDEX IF EXISTS idx_model_config_active;
DROP INDEX IF EXISTS idx_model_config_type;
DROP INDEX IF EXISTS idx_bot_config_key;
DROP INDEX IF EXISTS idx_bot_config_bot;
DROP INDEX IF EXISTS idx_tenant_config_key;
DROP INDEX IF EXISTS idx_tenant_config_tenant;
DROP INDEX IF EXISTS idx_server_config_type;
DROP INDEX IF EXISTS idx_server_config_key;
-- Drop tables
DROP TABLE IF EXISTS gbot_config_sync;
DROP TABLE IF EXISTS component_logs;
DROP TABLE IF EXISTS component_installations;
DROP TABLE IF EXISTS connection_configurations;
DROP TABLE IF EXISTS model_configurations;
DROP TABLE IF EXISTS bot_configuration;
DROP TABLE IF EXISTS tenant_configuration;
DROP TABLE IF EXISTS server_configuration;
-- Remove added columns if they exist
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'user_sessions' AND column_name = 'tenant_id'
) THEN
ALTER TABLE user_sessions DROP COLUMN tenant_id;
END IF;
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'bots' AND column_name = 'tenant_id'
) THEN
ALTER TABLE bots DROP COLUMN tenant_id;
END IF;
END $$;
-- Drop tenant indexes if they exist
DROP INDEX IF EXISTS idx_user_sessions_tenant;
DROP INDEX IF EXISTS idx_bots_tenant;
-- Remove default tenant
DELETE FROM tenants WHERE slug = 'default';

View file

@ -1,231 +0,0 @@
-- Migration 6.0.4: Configuration Management System
-- Eliminates .env dependency by storing all configuration in database
-- ============================================================================
-- SERVER CONFIGURATION TABLE
-- Stores server-wide configuration (replaces .env variables)
-- ============================================================================
CREATE TABLE IF NOT EXISTS server_configuration (
id TEXT PRIMARY KEY,
config_key TEXT NOT NULL UNIQUE,
config_value TEXT NOT NULL,
config_type TEXT NOT NULL DEFAULT 'string', -- string, integer, boolean, encrypted
description TEXT,
is_encrypted BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_server_config_key ON server_configuration(config_key);
CREATE INDEX IF NOT EXISTS idx_server_config_type ON server_configuration(config_type);
-- ============================================================================
-- TENANT CONFIGURATION TABLE
-- Stores tenant-level configuration (multi-tenancy support)
-- ============================================================================
CREATE TABLE IF NOT EXISTS tenant_configuration (
id TEXT PRIMARY KEY,
tenant_id UUID NOT NULL,
config_key TEXT NOT NULL,
config_value TEXT NOT NULL,
config_type TEXT NOT NULL DEFAULT 'string',
is_encrypted BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(tenant_id, config_key)
);
CREATE INDEX IF NOT EXISTS idx_tenant_config_tenant ON tenant_configuration(tenant_id);
CREATE INDEX IF NOT EXISTS idx_tenant_config_key ON tenant_configuration(config_key);
-- ============================================================================
-- BOT CONFIGURATION TABLE
-- Stores bot-specific configuration (replaces bot config JSON)
-- ============================================================================
CREATE TABLE IF NOT EXISTS bot_configuration (
id TEXT PRIMARY KEY,
bot_id UUID NOT NULL,
config_key TEXT NOT NULL,
config_value TEXT NOT NULL,
config_type TEXT NOT NULL DEFAULT 'string',
is_encrypted BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(bot_id, config_key)
);
CREATE INDEX IF NOT EXISTS idx_bot_config_bot ON bot_configuration(bot_id);
CREATE INDEX IF NOT EXISTS idx_bot_config_key ON bot_configuration(config_key);
-- ============================================================================
-- MODEL CONFIGURATIONS TABLE
-- Stores LLM and Embedding model configurations
-- ============================================================================
CREATE TABLE IF NOT EXISTS model_configurations (
id TEXT PRIMARY KEY,
model_name TEXT NOT NULL UNIQUE, -- Friendly name: "deepseek-1.5b", "gpt-oss-20b"
model_type TEXT NOT NULL, -- 'llm' or 'embed'
provider TEXT NOT NULL, -- 'openai', 'groq', 'local', 'ollama', etc.
endpoint TEXT NOT NULL,
api_key TEXT, -- Encrypted
model_id TEXT NOT NULL, -- Actual model identifier
context_window INTEGER,
max_tokens INTEGER,
temperature REAL DEFAULT 0.7,
is_active BOOLEAN NOT NULL DEFAULT true,
is_default BOOLEAN NOT NULL DEFAULT false,
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_model_config_type ON model_configurations(model_type);
CREATE INDEX IF NOT EXISTS idx_model_config_active ON model_configurations(is_active);
CREATE INDEX IF NOT EXISTS idx_model_config_default ON model_configurations(is_default);
-- ============================================================================
-- CONNECTION CONFIGURATIONS TABLE
-- Stores custom database connections (replaces CUSTOM_* env vars)
-- ============================================================================
CREATE TABLE IF NOT EXISTS connection_configurations (
id TEXT PRIMARY KEY,
bot_id UUID NOT NULL,
connection_name TEXT NOT NULL, -- Used in BASIC: FIND "conn1.table"
connection_type TEXT NOT NULL, -- 'postgres', 'mysql', 'mssql', 'mongodb', etc.
host TEXT NOT NULL,
port INTEGER NOT NULL,
database_name TEXT NOT NULL,
username TEXT NOT NULL,
password TEXT NOT NULL, -- Encrypted
ssl_enabled BOOLEAN NOT NULL DEFAULT false,
additional_params JSONB DEFAULT '{}'::jsonb,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE(bot_id, connection_name)
);
CREATE INDEX IF NOT EXISTS idx_connection_config_bot ON connection_configurations(bot_id);
CREATE INDEX IF NOT EXISTS idx_connection_config_name ON connection_configurations(connection_name);
CREATE INDEX IF NOT EXISTS idx_connection_config_active ON connection_configurations(is_active);
-- ============================================================================
-- COMPONENT INSTALLATIONS TABLE
-- Tracks installed components (postgres, minio, qdrant, etc.)
-- ============================================================================
CREATE TABLE IF NOT EXISTS component_installations (
id TEXT PRIMARY KEY,
component_name TEXT NOT NULL UNIQUE, -- 'tables', 'drive', 'vectordb', 'cache', 'llm'
component_type TEXT NOT NULL, -- 'database', 'storage', 'vector', 'cache', 'compute'
version TEXT NOT NULL,
install_path TEXT NOT NULL, -- Relative to botserver-stack
binary_path TEXT, -- Path to executable
data_path TEXT, -- Path to data directory
config_path TEXT, -- Path to config file
log_path TEXT, -- Path to log directory
status TEXT NOT NULL DEFAULT 'stopped', -- 'running', 'stopped', 'error', 'installing'
port INTEGER,
pid INTEGER,
auto_start BOOLEAN NOT NULL DEFAULT true,
metadata JSONB DEFAULT '{}'::jsonb,
installed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
last_started_at TIMESTAMPTZ,
last_stopped_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_component_name ON component_installations(component_name);
CREATE INDEX IF NOT EXISTS idx_component_status ON component_installations(status);
-- ============================================================================
-- TENANTS TABLE
-- Multi-tenancy support
-- ============================================================================
CREATE TABLE IF NOT EXISTS tenants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL UNIQUE,
slug TEXT NOT NULL UNIQUE,
is_active BOOLEAN NOT NULL DEFAULT true,
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_tenants_slug ON tenants(slug);
CREATE INDEX IF NOT EXISTS idx_tenants_active ON tenants(is_active);
-- ============================================================================
-- BOT SESSIONS ENHANCEMENT
-- Add tenant_id to existing sessions if column doesn't exist
-- ============================================================================
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'user_sessions' AND column_name = 'tenant_id'
) THEN
ALTER TABLE user_sessions ADD COLUMN tenant_id UUID;
CREATE INDEX idx_user_sessions_tenant ON user_sessions(tenant_id);
END IF;
END $$;
-- ============================================================================
-- BOTS TABLE ENHANCEMENT
-- Add tenant_id if it doesn't exist
-- ============================================================================
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'bots' AND column_name = 'tenant_id'
) THEN
ALTER TABLE bots ADD COLUMN tenant_id UUID;
CREATE INDEX idx_bots_tenant ON bots(tenant_id);
END IF;
END $$;
INSERT INTO tenants (id, name, slug, is_active) VALUES
(gen_random_uuid(), 'Default Tenant', 'default', true)
ON CONFLICT (slug) DO NOTHING;
-- ============================================================================
-- DEFAULT MODELS
-- Add some default model configurations
-- ============================================================================
INSERT INTO model_configurations (id, model_name, model_type, provider, endpoint, model_id, context_window, max_tokens, is_default) VALUES
(gen_random_uuid()::text, 'gpt-4', 'llm', 'openai', 'http://localhost:8081/v1', 'gpt-4', 8192, 4096, true),
(gen_random_uuid()::text, 'gpt-3.5-turbo', 'llm', 'openai', 'http://localhost:8081/v1', 'gpt-3.5-turbo', 4096, 2048, false),
(gen_random_uuid()::text, 'bge-large', 'embed', 'local', 'http://localhost:8081', 'BAAI/bge-large-en-v1.5', 512, 1024, true)
ON CONFLICT (model_name) DO NOTHING;
-- ============================================================================
-- COMPONENT LOGGING TABLE
-- Track component lifecycle events
-- ============================================================================
CREATE TABLE IF NOT EXISTS component_logs (
id TEXT PRIMARY KEY,
component_name TEXT NOT NULL,
log_level TEXT NOT NULL, -- 'info', 'warning', 'error', 'debug'
message TEXT NOT NULL,
details JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_component_logs_component ON component_logs(component_name);
CREATE INDEX IF NOT EXISTS idx_component_logs_level ON component_logs(log_level);
CREATE INDEX IF NOT EXISTS idx_component_logs_created ON component_logs(created_at);
-- ============================================================================
-- GBOT CONFIG SYNC TABLE
-- Tracks .gbot/config.csv file changes and last sync
-- ============================================================================
CREATE TABLE IF NOT EXISTS gbot_config_sync (
id TEXT PRIMARY KEY,
bot_id UUID NOT NULL UNIQUE,
config_file_path TEXT NOT NULL,
last_sync_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
file_hash TEXT NOT NULL,
sync_count INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_gbot_sync_bot ON gbot_config_sync(bot_id);

View file

@ -1,26 +0,0 @@
-- Revert clicks table changes
CREATE TABLE IF NOT EXISTS public.old_clicks (
campaign_id text NOT NULL,
email text NOT NULL,
updated_at timestamptz DEFAULT now() NULL,
CONSTRAINT clicks_campaign_id_email_key UNIQUE (campaign_id, email)
);
INSERT INTO public.old_clicks (campaign_id, email, updated_at)
SELECT campaign_id, email, updated_at FROM public.clicks;
DROP TABLE public.clicks;
ALTER TABLE public.old_clicks RENAME TO clicks;
-- Remove system_automations constraints and indexes
DROP INDEX IF EXISTS idx_system_automations_bot_kind_param;
ALTER TABLE public.system_automations DROP CONSTRAINT IF EXISTS system_automations_bot_kind_param_unique;
DROP INDEX IF EXISTS idx_system_automations_bot_id;
ALTER TABLE public.system_automations DROP COLUMN IF EXISTS bot_id;
DROP INDEX IF EXISTS idx_system_automations_name;
ALTER TABLE public.system_automations DROP COLUMN IF EXISTS name;
-- Remove bot_configuration constraint
ALTER TABLE bot_configuration DROP CONSTRAINT IF EXISTS bot_configuration_config_key_unique;

View file

@ -1,55 +0,0 @@
-- Migration 6.0.5: Add update-summary.bas scheduled automation
-- Description: Creates a scheduled automation that runs every minute to update summaries
-- This replaces the announcements system in legacy mode
-- Note: Bots are now created dynamically during bootstrap based on template folders
-- Add name column to system_automations if it doesn't exist
ALTER TABLE public.system_automations ADD COLUMN IF NOT EXISTS name VARCHAR(255);
-- Create index on name column for faster lookups
CREATE INDEX IF NOT EXISTS idx_system_automations_name ON public.system_automations(name);
-- Note: bot_configuration already has UNIQUE(bot_id, config_key) from migration 6.0.4
-- Do NOT add a global unique constraint on config_key alone as that breaks multi-bot configs
-- Migration 6.0.9: Add bot_id column to system_automations
-- Description: Introduces a bot_id column to associate automations with a specific bot.
-- The column is added as UUID and indexed for efficient queries.
-- Add bot_id column if it does not exist
ALTER TABLE public.system_automations
ADD COLUMN IF NOT EXISTS bot_id UUID NOT NULL;
-- Create an index on bot_id for faster lookups
CREATE INDEX IF NOT EXISTS idx_system_automations_bot_id
ON public.system_automations (bot_id);
ALTER TABLE public.system_automations
ADD CONSTRAINT system_automations_bot_kind_param_unique
UNIQUE (bot_id, kind, param);
-- Add index for the new constraint
CREATE INDEX IF NOT EXISTS idx_system_automations_bot_kind_param
ON public.system_automations (bot_id, kind, param);
-- Migration 6.0.7: Fix clicks table primary key
-- Required by Diesel before we can run other migrations
-- Create new table with proper structure
CREATE TABLE IF NOT EXISTS public.new_clicks (
id SERIAL PRIMARY KEY,
campaign_id text NOT NULL,
email text NOT NULL,
updated_at timestamptz DEFAULT now() NULL,
CONSTRAINT new_clicks_campaign_id_email_key UNIQUE (campaign_id, email)
);
-- Copy data from old table
INSERT INTO public.new_clicks (campaign_id, email, updated_at)
SELECT campaign_id, email, updated_at FROM public.clicks;
-- Drop old table and rename new one
DROP TABLE public.clicks;
ALTER TABLE public.new_clicks RENAME TO clicks;

View file

@ -1,19 +0,0 @@
-- Drop login tokens table
DROP TABLE IF EXISTS public.user_login_tokens;
-- Drop user preferences table
DROP TABLE IF EXISTS public.user_preferences;
-- Remove session enhancement
ALTER TABLE public.user_sessions
DROP CONSTRAINT IF EXISTS user_sessions_email_account_id_fkey,
DROP COLUMN IF EXISTS active_email_account_id;
-- Drop email folders table
DROP TABLE IF EXISTS public.email_folders;
-- Drop email drafts table
DROP TABLE IF EXISTS public.email_drafts;
-- Drop user email accounts table
DROP TABLE IF EXISTS public.user_email_accounts;

View file

@ -1,102 +0,0 @@
-- Add user_email_accounts table for storing user email credentials
CREATE TABLE public.user_email_accounts (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid NOT NULL,
email varchar(255) NOT NULL,
display_name varchar(255) NULL,
imap_server varchar(255) NOT NULL,
imap_port int4 DEFAULT 993 NOT NULL,
smtp_server varchar(255) NOT NULL,
smtp_port int4 DEFAULT 587 NOT NULL,
username varchar(255) NOT NULL,
password_encrypted text NOT NULL,
is_primary bool DEFAULT false NOT NULL,
is_active bool DEFAULT true NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT user_email_accounts_pkey PRIMARY KEY (id),
CONSTRAINT user_email_accounts_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE,
CONSTRAINT user_email_accounts_user_email_key UNIQUE (user_id, email)
);
CREATE INDEX idx_user_email_accounts_user_id ON public.user_email_accounts USING btree (user_id);
CREATE INDEX idx_user_email_accounts_active ON public.user_email_accounts USING btree (is_active) WHERE is_active;
-- Add email drafts table
CREATE TABLE public.email_drafts (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid NOT NULL,
account_id uuid NOT NULL,
to_address text NOT NULL,
cc_address text NULL,
bcc_address text NULL,
subject varchar(500) NULL,
body text NULL,
attachments jsonb DEFAULT '[]'::jsonb NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT email_drafts_pkey PRIMARY KEY (id),
CONSTRAINT email_drafts_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE,
CONSTRAINT email_drafts_account_id_fkey FOREIGN KEY (account_id) REFERENCES public.user_email_accounts(id) ON DELETE CASCADE
);
CREATE INDEX idx_email_drafts_user_id ON public.email_drafts USING btree (user_id);
CREATE INDEX idx_email_drafts_account_id ON public.email_drafts USING btree (account_id);
-- Add email folders metadata table (for caching and custom folders)
CREATE TABLE public.email_folders (
id uuid DEFAULT gen_random_uuid() NOT NULL,
account_id uuid NOT NULL,
folder_name varchar(255) NOT NULL,
folder_path varchar(500) NOT NULL,
unread_count int4 DEFAULT 0 NOT NULL,
total_count int4 DEFAULT 0 NOT NULL,
last_synced timestamptz NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT email_folders_pkey PRIMARY KEY (id),
CONSTRAINT email_folders_account_id_fkey FOREIGN KEY (account_id) REFERENCES public.user_email_accounts(id) ON DELETE CASCADE,
CONSTRAINT email_folders_account_path_key UNIQUE (account_id, folder_path)
);
CREATE INDEX idx_email_folders_account_id ON public.email_folders USING btree (account_id);
-- Add sessions table enhancement for storing current email account
ALTER TABLE public.user_sessions
ADD COLUMN IF NOT EXISTS active_email_account_id uuid NULL,
ADD CONSTRAINT user_sessions_email_account_id_fkey
FOREIGN KEY (active_email_account_id) REFERENCES public.user_email_accounts(id) ON DELETE SET NULL;
-- Add user preferences table
CREATE TABLE public.user_preferences (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid NOT NULL,
preference_key varchar(100) NOT NULL,
preference_value jsonb NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
updated_at timestamptz DEFAULT now() NOT NULL,
CONSTRAINT user_preferences_pkey PRIMARY KEY (id),
CONSTRAINT user_preferences_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE,
CONSTRAINT user_preferences_user_key_unique UNIQUE (user_id, preference_key)
);
CREATE INDEX idx_user_preferences_user_id ON public.user_preferences USING btree (user_id);
-- Add login tokens table for session management
CREATE TABLE public.user_login_tokens (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid NOT NULL,
token_hash varchar(255) NOT NULL,
expires_at timestamptz NOT NULL,
created_at timestamptz DEFAULT now() NOT NULL,
last_used timestamptz DEFAULT now() NOT NULL,
user_agent text NULL,
ip_address varchar(50) NULL,
is_active bool DEFAULT true NOT NULL,
CONSTRAINT user_login_tokens_pkey PRIMARY KEY (id),
CONSTRAINT user_login_tokens_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE,
CONSTRAINT user_login_tokens_token_hash_key UNIQUE (token_hash)
);
CREATE INDEX idx_user_login_tokens_user_id ON public.user_login_tokens USING btree (user_id);
CREATE INDEX idx_user_login_tokens_expires ON public.user_login_tokens USING btree (expires_at) WHERE is_active;

View file

@ -1,9 +0,0 @@
-- Migration 6.0.7: Session KB Tracking (ROLLBACK)
-- Drops session KB tracking table
DROP INDEX IF EXISTS idx_session_kb_active;
DROP INDEX IF EXISTS idx_session_kb_name;
DROP INDEX IF EXISTS idx_session_kb_bot_id;
DROP INDEX IF EXISTS idx_session_kb_session_id;
DROP TABLE IF EXISTS session_kb_associations;

View file

@ -1,29 +0,0 @@
-- Migration 6.0.7: Session KB Tracking
-- Adds table to track which KBs are active in each conversation session
-- Table for tracking KBs active in a session (set by ADD_KB in .bas tools)
CREATE TABLE IF NOT EXISTS session_kb_associations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL REFERENCES user_sessions(id) ON DELETE CASCADE,
bot_id UUID NOT NULL REFERENCES bots(id) ON DELETE CASCADE,
kb_name TEXT NOT NULL,
kb_folder_path TEXT NOT NULL,
qdrant_collection TEXT NOT NULL,
added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
added_by_tool TEXT,
is_active BOOLEAN NOT NULL DEFAULT true,
UNIQUE(session_id, kb_name)
);
CREATE INDEX IF NOT EXISTS idx_session_kb_session_id ON session_kb_associations(session_id);
CREATE INDEX IF NOT EXISTS idx_session_kb_bot_id ON session_kb_associations(bot_id);
CREATE INDEX IF NOT EXISTS idx_session_kb_name ON session_kb_associations(kb_name);
CREATE INDEX IF NOT EXISTS idx_session_kb_active ON session_kb_associations(is_active) WHERE is_active = true;
-- Comments
COMMENT ON TABLE session_kb_associations IS 'Tracks which Knowledge Base collections are active in each conversation session';
COMMENT ON COLUMN session_kb_associations.kb_name IS 'Name of the KB folder (e.g., "circular", "comunicado", "geral")';
COMMENT ON COLUMN session_kb_associations.kb_folder_path IS 'Full path to KB folder: work/{bot}/{bot}.gbkb/{kb_name}';
COMMENT ON COLUMN session_kb_associations.qdrant_collection IS 'Qdrant collection name for this KB';
COMMENT ON COLUMN session_kb_associations.added_by_tool IS 'Name of the .bas tool that added this KB (e.g., "change-subject.bas")';
COMMENT ON COLUMN session_kb_associations.is_active IS 'Whether this KB is currently active in the session';

View file

@ -1,23 +0,0 @@
-- Drop triggers
DROP TRIGGER IF EXISTS update_directory_users_updated_at ON public.directory_users;
DROP TRIGGER IF EXISTS update_oauth_applications_updated_at ON public.oauth_applications;
-- Drop function if no other triggers use it
DROP FUNCTION IF EXISTS update_updated_at_column() CASCADE;
-- Drop tables in reverse order of dependencies
DROP TABLE IF EXISTS public.bot_access CASCADE;
DROP TABLE IF EXISTS public.oauth_applications CASCADE;
DROP TABLE IF EXISTS public.directory_users CASCADE;
-- Drop indexes
DROP INDEX IF EXISTS idx_bots_org_id;
-- Remove columns from bots table
ALTER TABLE public.bots
DROP CONSTRAINT IF EXISTS bots_org_id_fkey,
DROP COLUMN IF EXISTS org_id,
DROP COLUMN IF EXISTS is_default;
-- Note: We don't delete the default organization or bot data as they may have other relationships
-- The application should handle orphaned data appropriately

View file

@ -1,246 +0,0 @@
-- Add organization relationship to bots
ALTER TABLE public.bots
ADD COLUMN IF NOT EXISTS org_id UUID,
ADD COLUMN IF NOT EXISTS is_default BOOLEAN DEFAULT false;
-- Add foreign key constraint to organizations
ALTER TABLE public.bots
ADD CONSTRAINT bots_org_id_fkey
FOREIGN KEY (org_id) REFERENCES public.organizations(org_id) ON DELETE CASCADE;
-- Create index for org_id lookups
CREATE INDEX IF NOT EXISTS idx_bots_org_id ON public.bots(org_id);
-- Create directory_users table to map directory (Zitadel) users to our system
CREATE TABLE IF NOT EXISTS public.directory_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
directory_id VARCHAR(255) NOT NULL UNIQUE, -- Zitadel user ID
username VARCHAR(255) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL UNIQUE,
org_id UUID NOT NULL REFERENCES public.organizations(org_id) ON DELETE CASCADE,
bot_id UUID REFERENCES public.bots(id) ON DELETE SET NULL,
first_name VARCHAR(255),
last_name VARCHAR(255),
is_admin BOOLEAN DEFAULT false,
is_bot_user BOOLEAN DEFAULT false, -- true for bot service accounts
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);
-- Create indexes for directory_users
CREATE INDEX IF NOT EXISTS idx_directory_users_org_id ON public.directory_users(org_id);
CREATE INDEX IF NOT EXISTS idx_directory_users_bot_id ON public.directory_users(bot_id);
CREATE INDEX IF NOT EXISTS idx_directory_users_email ON public.directory_users(email);
CREATE INDEX IF NOT EXISTS idx_directory_users_directory_id ON public.directory_users(directory_id);
-- Create bot_access table to manage which users can access which bots
CREATE TABLE IF NOT EXISTS public.bot_access (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL REFERENCES public.bots(id) ON DELETE CASCADE,
user_id UUID NOT NULL REFERENCES public.directory_users(id) ON DELETE CASCADE,
access_level VARCHAR(50) NOT NULL DEFAULT 'user', -- 'owner', 'admin', 'user', 'viewer'
granted_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
granted_by UUID REFERENCES public.directory_users(id),
UNIQUE(bot_id, user_id)
);
-- Create indexes for bot_access
CREATE INDEX IF NOT EXISTS idx_bot_access_bot_id ON public.bot_access(bot_id);
CREATE INDEX IF NOT EXISTS idx_bot_access_user_id ON public.bot_access(user_id);
-- Create OAuth application registry for directory integrations
CREATE TABLE IF NOT EXISTS public.oauth_applications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
org_id UUID NOT NULL REFERENCES public.organizations(org_id) ON DELETE CASCADE,
project_id VARCHAR(255),
client_id VARCHAR(255) NOT NULL UNIQUE,
client_secret_encrypted TEXT NOT NULL, -- Store encrypted
redirect_uris TEXT[] NOT NULL DEFAULT '{}',
application_name VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW() NOT NULL,
updated_at TIMESTAMPTZ DEFAULT NOW() NOT NULL
);
-- Create index for OAuth applications
CREATE INDEX IF NOT EXISTS idx_oauth_applications_org_id ON public.oauth_applications(org_id);
CREATE INDEX IF NOT EXISTS idx_oauth_applications_client_id ON public.oauth_applications(client_id);
-- Insert default organization if it doesn't exist
INSERT INTO public.organizations (org_id, name, slug, created_at, updated_at)
VALUES (
'f47ac10b-58cc-4372-a567-0e02b2c3d479'::uuid, -- Fixed UUID for default org
'Default Organization',
'default',
NOW(),
NOW()
) ON CONFLICT (slug) DO NOTHING;
-- Insert default bot for the default organization
DO $$
DECLARE
v_org_id UUID;
v_bot_id UUID;
BEGIN
-- Get the default organization ID
SELECT org_id INTO v_org_id FROM public.organizations WHERE slug = 'default';
-- Generate or use fixed UUID for default bot
v_bot_id := 'f47ac10b-58cc-4372-a567-0e02b2c3d480'::uuid;
-- Insert default bot if it doesn't exist
INSERT INTO public.bots (
id,
org_id,
name,
description,
llm_provider,
llm_config,
context_provider,
context_config,
is_default,
is_active,
created_at,
updated_at
)
VALUES (
v_bot_id,
v_org_id,
'Default Bot',
'Default bot for the default organization',
'openai',
'{"model": "gpt-4", "temperature": 0.7}'::jsonb,
'none',
'{}'::jsonb,
true,
true,
NOW(),
NOW()
) ON CONFLICT (id) DO UPDATE
SET org_id = EXCLUDED.org_id,
is_default = true,
updated_at = NOW();
-- Insert default admin user (admin@default)
INSERT INTO public.directory_users (
directory_id,
username,
email,
org_id,
bot_id,
first_name,
last_name,
is_admin,
is_bot_user,
created_at,
updated_at
)
VALUES (
'admin-default-001', -- Will be replaced with actual Zitadel ID
'admin',
'admin@default',
v_org_id,
v_bot_id,
'Admin',
'Default',
true,
false,
NOW(),
NOW()
) ON CONFLICT (email) DO UPDATE
SET org_id = EXCLUDED.org_id,
bot_id = EXCLUDED.bot_id,
is_admin = true,
updated_at = NOW();
-- Insert default regular user (user@default)
INSERT INTO public.directory_users (
directory_id,
username,
email,
org_id,
bot_id,
first_name,
last_name,
is_admin,
is_bot_user,
created_at,
updated_at
)
VALUES (
'user-default-001', -- Will be replaced with actual Zitadel ID
'user',
'user@default',
v_org_id,
v_bot_id,
'User',
'Default',
false,
false,
NOW(),
NOW()
) ON CONFLICT (email) DO UPDATE
SET org_id = EXCLUDED.org_id,
bot_id = EXCLUDED.bot_id,
is_admin = false,
updated_at = NOW();
-- Grant bot access to admin user
INSERT INTO public.bot_access (bot_id, user_id, access_level, granted_at)
SELECT
v_bot_id,
id,
'owner',
NOW()
FROM public.directory_users
WHERE email = 'admin@default'
ON CONFLICT (bot_id, user_id) DO UPDATE
SET access_level = 'owner',
granted_at = NOW();
-- Grant bot access to regular user
INSERT INTO public.bot_access (bot_id, user_id, access_level, granted_at)
SELECT
v_bot_id,
id,
'user',
NOW()
FROM public.directory_users
WHERE email = 'user@default'
ON CONFLICT (bot_id, user_id) DO UPDATE
SET access_level = 'user',
granted_at = NOW();
END $$;
-- Create function to update updated_at timestamps
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
-- Add triggers for updated_at columns if they don't exist
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_directory_users_updated_at') THEN
CREATE TRIGGER update_directory_users_updated_at
BEFORE UPDATE ON public.directory_users
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_trigger WHERE tgname = 'update_oauth_applications_updated_at') THEN
CREATE TRIGGER update_oauth_applications_updated_at
BEFORE UPDATE ON public.oauth_applications
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
END IF;
END $$;
-- Add comment documentation
COMMENT ON TABLE public.directory_users IS 'Maps directory (Zitadel) users to the system and their associated bots';
COMMENT ON TABLE public.bot_access IS 'Controls which users have access to which bots and their permission levels';
COMMENT ON TABLE public.oauth_applications IS 'OAuth application configurations for directory integration';
COMMENT ON COLUMN public.bots.is_default IS 'Indicates if this is the default bot for an organization';
COMMENT ON COLUMN public.directory_users.is_bot_user IS 'True if this user is a service account for bot operations';
COMMENT ON COLUMN public.bot_access.access_level IS 'Access level: owner (full control), admin (manage), user (use), viewer (read-only)';

View file

@ -1,7 +0,0 @@
-- Drop session_website_associations table and related indexes
DROP TABLE IF EXISTS session_website_associations;
-- Drop website_crawls table and related objects
DROP TRIGGER IF EXISTS website_crawls_updated_at_trigger ON website_crawls;
DROP FUNCTION IF EXISTS update_website_crawls_updated_at();
DROP TABLE IF EXISTS website_crawls;

View file

@ -1,86 +0,0 @@
-- Create website_crawls table for tracking crawled websites
CREATE TABLE IF NOT EXISTS website_crawls (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
bot_id UUID NOT NULL,
url TEXT NOT NULL,
last_crawled TIMESTAMPTZ,
next_crawl TIMESTAMPTZ,
expires_policy VARCHAR(20) NOT NULL DEFAULT '1d',
max_depth INTEGER DEFAULT 3,
max_pages INTEGER DEFAULT 100,
crawl_status SMALLINT DEFAULT 0, -- 0=pending, 1=success, 2=processing, 3=error
pages_crawled INTEGER DEFAULT 0,
error_message TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
-- Ensure unique URL per bot
CONSTRAINT unique_bot_url UNIQUE (bot_id, url),
-- Foreign key to bots table
CONSTRAINT fk_website_crawls_bot
FOREIGN KEY (bot_id)
REFERENCES bots(id)
ON DELETE CASCADE
);
-- Create indexes for efficient queries
CREATE INDEX IF NOT EXISTS idx_website_crawls_bot_id ON website_crawls(bot_id);
CREATE INDEX IF NOT EXISTS idx_website_crawls_next_crawl ON website_crawls(next_crawl);
CREATE INDEX IF NOT EXISTS idx_website_crawls_url ON website_crawls(url);
CREATE INDEX IF NOT EXISTS idx_website_crawls_status ON website_crawls(crawl_status);
-- Create trigger to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_website_crawls_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER website_crawls_updated_at_trigger
BEFORE UPDATE ON website_crawls
FOR EACH ROW
EXECUTE FUNCTION update_website_crawls_updated_at();
-- Create session_website_associations table for tracking websites added to sessions
-- Similar to session_kb_associations but for websites
CREATE TABLE IF NOT EXISTS session_website_associations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
session_id UUID NOT NULL,
bot_id UUID NOT NULL,
website_url TEXT NOT NULL,
collection_name TEXT NOT NULL,
is_active BOOLEAN DEFAULT true,
added_at TIMESTAMPTZ DEFAULT NOW(),
added_by_tool VARCHAR(255),
-- Ensure unique website per session
CONSTRAINT unique_session_website UNIQUE (session_id, website_url),
-- Foreign key to sessions table
CONSTRAINT fk_session_website_session
FOREIGN KEY (session_id)
REFERENCES user_sessions(id)
ON DELETE CASCADE,
-- Foreign key to bots table
CONSTRAINT fk_session_website_bot
FOREIGN KEY (bot_id)
REFERENCES bots(id)
ON DELETE CASCADE
);
-- Create indexes for efficient queries
CREATE INDEX IF NOT EXISTS idx_session_website_associations_session_id
ON session_website_associations(session_id) WHERE is_active = true;
CREATE INDEX IF NOT EXISTS idx_session_website_associations_bot_id
ON session_website_associations(bot_id);
CREATE INDEX IF NOT EXISTS idx_session_website_associations_url
ON session_website_associations(website_url);
CREATE INDEX IF NOT EXISTS idx_session_website_associations_collection
ON session_website_associations(collection_name);

View file

@ -1,248 +0,0 @@
-- Rollback Migration: 6.1.0 Enterprise Features
-- WARNING: This will delete all enterprise feature data!
-- NOTE: TABLES AND INDEXES ONLY - No views, triggers, or functions per project standards
-- Includes rollback for: config ID fixes, connected accounts, bot hierarchy, monitors
-- ============================================================================
-- ROLLBACK: Bot Hierarchy and Monitors (from 6.1.3)
-- ============================================================================
-- Drop comments first
COMMENT ON TABLE public.user_organizations IS NULL;
COMMENT ON TABLE public.email_received_events IS NULL;
COMMENT ON TABLE public.folder_change_events IS NULL;
COMMENT ON TABLE public.folder_monitors IS NULL;
COMMENT ON TABLE public.email_monitors IS NULL;
COMMENT ON COLUMN public.bots.inherit_parent_config IS NULL;
COMMENT ON COLUMN public.bots.enabled_tabs_json IS NULL;
COMMENT ON COLUMN public.bots.parent_bot_id IS NULL;
COMMENT ON TABLE public.system_automations IS NULL;
-- Drop user organizations table
DROP INDEX IF EXISTS idx_user_orgs_default;
DROP INDEX IF EXISTS idx_user_orgs_org;
DROP INDEX IF EXISTS idx_user_orgs_user;
DROP TABLE IF EXISTS public.user_organizations;
-- Drop email received events table
DROP INDEX IF EXISTS idx_email_events_received;
DROP INDEX IF EXISTS idx_email_events_processed;
DROP INDEX IF EXISTS idx_email_events_monitor;
DROP TABLE IF EXISTS public.email_received_events;
-- Drop folder change events table
DROP INDEX IF EXISTS idx_folder_events_created;
DROP INDEX IF EXISTS idx_folder_events_processed;
DROP INDEX IF EXISTS idx_folder_events_monitor;
DROP TABLE IF EXISTS public.folder_change_events;
-- Drop folder monitors table
DROP INDEX IF EXISTS idx_folder_monitors_account_email;
DROP INDEX IF EXISTS idx_folder_monitors_active;
DROP INDEX IF EXISTS idx_folder_monitors_provider;
DROP INDEX IF EXISTS idx_folder_monitors_bot_id;
DROP TABLE IF EXISTS public.folder_monitors;
-- Drop email monitors table
DROP INDEX IF EXISTS idx_email_monitors_active;
DROP INDEX IF EXISTS idx_email_monitors_email;
DROP INDEX IF EXISTS idx_email_monitors_bot_id;
DROP TABLE IF EXISTS public.email_monitors;
-- Remove bot hierarchy columns
DROP INDEX IF EXISTS idx_bots_parent_bot_id;
ALTER TABLE public.bots DROP COLUMN IF EXISTS inherit_parent_config;
ALTER TABLE public.bots DROP COLUMN IF EXISTS enabled_tabs_json;
ALTER TABLE public.bots DROP COLUMN IF EXISTS parent_bot_id;
-- ============================================================================
-- ROLLBACK: Connected Accounts (from 6.1.2)
-- ============================================================================
DROP INDEX IF EXISTS idx_account_sync_items_unique;
DROP INDEX IF EXISTS idx_account_sync_items_embedding;
DROP INDEX IF EXISTS idx_account_sync_items_date;
DROP INDEX IF EXISTS idx_account_sync_items_type;
DROP INDEX IF EXISTS idx_account_sync_items_account;
DROP TABLE IF EXISTS account_sync_items;
DROP INDEX IF EXISTS idx_session_account_assoc_unique;
DROP INDEX IF EXISTS idx_session_account_assoc_active;
DROP INDEX IF EXISTS idx_session_account_assoc_account;
DROP INDEX IF EXISTS idx_session_account_assoc_session;
DROP TABLE IF EXISTS session_account_associations;
DROP INDEX IF EXISTS idx_connected_accounts_bot_email;
DROP INDEX IF EXISTS idx_connected_accounts_status;
DROP INDEX IF EXISTS idx_connected_accounts_provider;
DROP INDEX IF EXISTS idx_connected_accounts_email;
DROP INDEX IF EXISTS idx_connected_accounts_user_id;
DROP INDEX IF EXISTS idx_connected_accounts_bot_id;
DROP TABLE IF EXISTS connected_accounts;
-- ============================================================================
-- ROLLBACK: Config ID Type Fixes (from 6.1.1)
-- Revert UUID columns back to TEXT
-- ============================================================================
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'bot_configuration'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE bot_configuration
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'server_configuration'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE server_configuration
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'tenant_configuration'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE tenant_configuration
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'model_configurations'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE model_configurations
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'connection_configurations'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE connection_configurations
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'component_installations'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE component_installations
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'component_logs'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE component_logs
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'gbot_config_sync'
AND column_name = 'id'
AND data_type = 'uuid') THEN
ALTER TABLE gbot_config_sync
ALTER COLUMN id TYPE TEXT USING id::text;
END IF;
END $$;
-- ============================================================================
-- ROLLBACK: Original 6.1.0 Enterprise Features
-- ============================================================================
-- Drop test support tables
DROP TABLE IF EXISTS test_execution_logs;
DROP TABLE IF EXISTS test_accounts;
-- Drop calendar tables
DROP TABLE IF EXISTS calendar_shares;
DROP TABLE IF EXISTS calendar_resource_bookings;
DROP TABLE IF EXISTS calendar_resources;
-- Drop task tables
DROP TABLE IF EXISTS task_recurrence;
DROP TABLE IF EXISTS task_time_entries;
DROP TABLE IF EXISTS task_dependencies;
-- Drop collaboration tables
DROP TABLE IF EXISTS document_presence;
-- Drop drive tables
DROP TABLE IF EXISTS storage_quotas;
DROP TABLE IF EXISTS file_sync_status;
DROP TABLE IF EXISTS file_trash;
DROP TABLE IF EXISTS file_activities;
DROP TABLE IF EXISTS file_shares;
DROP TABLE IF EXISTS file_comments;
DROP TABLE IF EXISTS file_versions;
-- Drop meet tables
DROP TABLE IF EXISTS user_virtual_backgrounds;
DROP TABLE IF EXISTS meeting_captions;
DROP TABLE IF EXISTS meeting_waiting_room;
DROP TABLE IF EXISTS meeting_questions;
DROP TABLE IF EXISTS meeting_polls;
DROP TABLE IF EXISTS meeting_breakout_rooms;
DROP TABLE IF EXISTS meeting_recordings;
-- Drop email tables (order matters due to foreign keys)
DROP TABLE IF EXISTS shared_mailbox_members;
DROP TABLE IF EXISTS shared_mailboxes;
DROP TABLE IF EXISTS distribution_lists;
DROP TABLE IF EXISTS email_label_assignments;
DROP TABLE IF EXISTS email_labels;
DROP TABLE IF EXISTS email_rules;
DROP TABLE IF EXISTS email_auto_responders;
DROP TABLE IF EXISTS email_templates;
DROP TABLE IF EXISTS scheduled_emails;
DROP TABLE IF EXISTS email_signatures;
DROP TABLE IF EXISTS global_email_signatures;
-- Drop triggers and functions
DROP TRIGGER IF EXISTS external_connections_updated_at_trigger ON external_connections;
DROP FUNCTION IF EXISTS update_external_connections_updated_at();
DROP TRIGGER IF EXISTS dynamic_table_definitions_updated_at_trigger ON dynamic_table_definitions;
DROP FUNCTION IF EXISTS update_dynamic_table_definitions_updated_at();
-- Drop indexes
DROP INDEX IF EXISTS idx_external_connections_name;
DROP INDEX IF EXISTS idx_external_connections_bot_id;
DROP INDEX IF EXISTS idx_dynamic_table_fields_name;
DROP INDEX IF EXISTS idx_dynamic_table_fields_table_id;
DROP INDEX IF EXISTS idx_dynamic_table_definitions_connection;
DROP INDEX IF EXISTS idx_dynamic_table_definitions_name;
DROP INDEX IF EXISTS idx_dynamic_table_definitions_bot_id;
-- Drop tables (order matters due to foreign keys)
DROP TABLE IF EXISTS external_connections;
DROP TABLE IF EXISTS dynamic_table_fields;
DROP TABLE IF EXISTS dynamic_table_definitions;

File diff suppressed because it is too large Load diff

7696
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

97
package.json Normal file
View file

@ -0,0 +1,97 @@
{
"name": "botserver",
"version": "0.1.8",
"description": "General Bot Community Edition open-core server.",
"main": "./src/app.ts",
"homepage": "http://www.generalbot.com",
"contributors": [
"Rodrigo Rodriguez <me@rodrigorodriguez.com>",
"Jorge Ramos <jramos@pobox.com>"
],
"license": "AGPL-3.0",
"preferGlobal": true,
"bin": {
"gbot": "./dist/src/app.js"
},
"repository": {
"type": "git",
"url": "https://github.com/pragmatismo-io/BotServer.git"
},
"scripts": {
"clean": "rimraf dist",
"start": "node ./dist/src/app.js",
"startIde": "npm-run-all clean --parallel watch:build watch:server --print-label",
"watch:build": "tsc --watch",
"watch:server": "nodemon './dist/index.js' --watch './dist'",
"test": "mocha -r ts-node/register src/**/*.test.ts",
"build-docs": "typedoc --options typedoc.json src/"
},
"engines": {
"node": "=8.11.1"
},
"dependencies": {
"@microsoft/microsoft-graph-client": "1.3.0",
"@types/chai": "4.1.7",
"@types/mocha": "5.2.5",
"@types/sequelize": "4.27.30",
"@types/url-join": "0.8.2",
"@types/winston": "2.4.4",
"adal-node": "0.1.28",
"async": "2.6.1",
"async-promises": "0.2.1",
"azure-arm-cognitiveservices": "2.2.0",
"azure-arm-resource": "7.0.1",
"azure-arm-search": "^1.2.0-preview",
"azure-arm-sql": "5.3.0",
"azure-arm-website": "5.4.0",
"body-parser": "1.18.3",
"botbuilder": "^4.1.3",
"botbuilder-ai": "^4.1.3",
"botbuilder-azure": "^4.1.3",
"botbuilder-choices": "^4.0.0-preview1.2",
"botbuilder-dialogs": "^4.1.3",
"botbuilder-prompts": "^4.0.0-preview1.2",
"botlib": "0.1.6",
"chai": "4.2.0",
"child_process": "^1.0.2",
"chokidar": "2.0.4",
"cli-spinner": "^0.2.8",
"csv-parse": "3.1.3",
"dotenv-extended": "2.3.0",
"express": "4.16.4",
"express-promise-router": "3.0.3",
"fs-extra": "7.0.0",
"fs-walk": "0.0.2",
"ip": "^1.1.5",
"localize": "0.4.7",
"marked": "0.5.1",
"mocha": "5.2.0",
"mocha-typescript": "1.1.17",
"ms": "2.1.1",
"ms-rest-azure": "2.5.9",
"nexmo": "2.4.0",
"ngrok": "^3.1.0",
"opn": "^5.4.0",
"pragmatismo-io-framework": "1.0.18",
"process-exists": "^3.1.0",
"public-ip": "^2.4.0",
"reflect-metadata": "0.1.12",
"request-promise-native": "1.0.5",
"scanf": "^1.0.2",
"sequelize": "4.41.0",
"sequelize-typescript": "0.6.6",
"simple-git": "^1.106.0",
"sqlite3": "4.0.3",
"strict-password-generator": "^1.1.1",
"swagger-client": "3.8.21",
"tedious": "3.0.1",
"ts-node": "7.0.1",
"tslint": "^5.11.0",
"typedoc": "0.13.0",
"typescript": "3.1.6",
"url-join": "4.0.0",
"wait-until": "0.0.2",
"walk-promise": "0.2.0",
"winston": "3.1.0"
}
}

View file

@ -0,0 +1,168 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict";
const UrlJoin = require("url-join");
import { GBMinInstance } from "botlib";
import { IGBDialog } from "botlib";
import { GBDeployer } from "../../core.gbapp/services/GBDeployer";
import { GBImporter } from "../../core.gbapp/services/GBImporter";
import { GBConfigService } from "../../core.gbapp/services/GBConfigService";
import { BotAdapter } from "botbuilder";
import { GBAdminService } from "../services/GBAdminService";
import { Messages } from "../strings";
import { WaterfallDialog } from "botbuilder-dialogs";
/**
* Dialogs for administration tasks.
*/
export class AdminDialog extends IGBDialog {
static async createFarmCommand(text: any, min: GBMinInstance) {}
static async undeployPackageCommand(text: any, min: GBMinInstance) {
let packageName = text.split(" ")[1];
let importer = new GBImporter(min.core);
let deployer = new GBDeployer(min.core, importer);
await deployer.undeployPackageFromLocalPath(
min.instance,
UrlJoin("packages", packageName)
);
}
static async deployPackageCommand(text: string, deployer: GBDeployer) {
let packageName = text.split(" ")[1];
let additionalPath = GBConfigService.get("ADDITIONAL_DEPLOY_PATH");
await deployer.deployPackageFromLocalPath(
UrlJoin(additionalPath, packageName)
);
}
/**
* Setup dialogs flows and define services call.
*
* @param bot The bot adapter.
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
// Setup services.
let importer = new GBImporter(min.core);
let deployer = new GBDeployer(min.core, importer);
min.dialogs.add(
new WaterfallDialog("/admin", [
async step => {
const locale = step.context.activity.locale;
const prompt = Messages[locale].authenticate;
await step.prompt("textPrompt", prompt);
return await step.next();
},
async step => {
const locale = step.context.activity.locale;
let password = step.result;
if (
password === GBConfigService.get("ADMIN_PASS") &&
GBAdminService.StrongRegex.test(password)
) {
await step.context.sendActivity(Messages[locale].welcome);
await step.prompt("textPrompt", Messages[locale].which_task);
} else {
await step.prompt("textPrompt", Messages[locale].wrong_password);
await step.endDialog();
}
return await step.next();
},
async step => {
const locale = step.context.activity.locale;
var text = step.result;
let cmdName = text.split(" ")[0];
step.context.sendActivity(Messages[locale].working(cmdName));
let unknownCommand = false;
if (text === "quit") {
await step.replaceDialog("/");
} else if (cmdName === "createFarm") {
await AdminDialog.createFarmCommand(text, deployer);
await step.replaceDialog("/admin", { firstRun: false });
} else if (cmdName === "deployPackage") {
await AdminDialog.deployPackageCommand(text, deployer);
await step.replaceDialog("/admin", { firstRun: false });
} else if (cmdName === "redeployPackage") {
await AdminDialog.undeployPackageCommand(text, min);
await AdminDialog.deployPackageCommand(text, deployer);
await step.replaceDialog("/admin", { firstRun: false });
} else if (cmdName === "undeployPackage") {
await AdminDialog.undeployPackageCommand(text, min);
await step.replaceDialog("/admin", { firstRun: false });
} else if (cmdName === "setupSecurity") {
await AdminDialog.setupSecurity(min, step);
} else {
unknownCommand = true;
}
if (unknownCommand) {
await step.context.sendActivity(Messages[locale].unknown_command);
} else {
await step.context.sendActivity(
Messages[locale].finshed_working(cmdName)
);
}
await step.endDialog();
await step.replaceDialog("/answer", { query: text });
return await step.next();
}
])
);
}
private static async setupSecurity(min: any, step: any) {
const locale = step.activity.locale;
let state = `${min.instance.instanceId}${Math.floor(
Math.random() * 1000000000
)}`;
await min.adminService.setValue(
min.instance.instanceId,
"AntiCSRFAttackState",
state
);
let url = `https://login.microsoftonline.com/${
min.instance.authenticatorTenant
}/oauth2/authorize?client_id=${
min.instance.authenticatorClientId
}&response_type=code&redirect_uri=${min.instance.botEndpoint}/${
min.instance.botId
}/token&state=${state}&response_mode=query`;
await step.sendActivity(Messages[locale].consent(url));
}
}

View file

@ -0,0 +1,64 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
'use strict'
const UrlJoin = require('url-join')
import { AdminDialog } from './dialogs/AdminDialog'
import { GBMinInstance, IGBPackage, IGBCoreService } from 'botlib'
import { Sequelize } from 'sequelize-typescript'
import { GuaribasAdmin } from './models/AdminModel';
export class GBAdminPackage implements IGBPackage {
sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
core.sequelize.addModels([
GuaribasAdmin
])
}
unloadPackage(core: IGBCoreService): void {
}
loadBot(min: GBMinInstance): void {
AdminDialog.setup(min.bot, min)
}
unloadBot(min: GBMinInstance): void {
}
onNewSession(min: GBMinInstance, step: any): void {
}
}

View file

@ -0,0 +1,64 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict";
import {
Table,
Column,
Model,
CreatedAt,
UpdatedAt,
} from "sequelize-typescript";
@Table
export class GuaribasAdmin extends Model<GuaribasAdmin>
{
@Column
instanceId: number;
@Column
key: string;
@Column
value: string;
@Column
@CreatedAt
createdAt: Date;
@Column
@UpdatedAt
updatedAt: Date;
}

View file

@ -0,0 +1,188 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict";
import { GuaribasAdmin } from "../models/AdminModel";
import { IGBCoreService } from "botlib";
import { AuthenticationContext, TokenResponse } from "adal-node";
const UrlJoin = require("url-join");
const msRestAzure = require("ms-rest-azure");
const PasswordGenerator = require("strict-password-generator").default;
export class GBAdminService {
static GB_PROMPT: string = "GeneralBots: "
static generateUuid(): string {
return msRestAzure.generateUuid();
}
static masterBotInstanceId = 0;
public static StrongRegex = new RegExp(
"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*+_-])(?=.{8,})"
);
core: IGBCoreService;
constructor(core: IGBCoreService) {
this.core = core;
}
public async setValue(
instanceId: number,
key: string,
value: string
): Promise<GuaribasAdmin> {
let options = { where: {} };
options.where = { key: key };
let admin = await GuaribasAdmin.findOne(options);
if (admin == null) {
admin = new GuaribasAdmin();
admin.key = key;
}
admin.value = value;
admin.instanceId = instanceId;
return admin.save();
}
public async getValue(instanceId: number, key: string) {
let options = { where: {} };
options.where = { key: key, instanceId: instanceId };
let obj = await GuaribasAdmin.findOne(options);
return Promise.resolve(obj.value);
}
public async acquireElevatedToken(instanceId): Promise<string> {
return new Promise<string>(async (resolve, reject) => {
let instance = await this.core.loadInstanceById(instanceId);
let expiresOn = new Date(await this.getValue(instanceId, "expiresOn"));
if (expiresOn.getTime() > new Date().getTime()) {
let accessToken = await this.getValue(instanceId, "accessToken");
resolve(accessToken);
} else {
let authorizationUrl = UrlJoin(
instance.authenticatorAuthorityHostUrl,
instance.authenticatorTenant,
"/oauth2/authorize"
);
let refreshToken = await this.getValue(instanceId, "refreshToken");
let resource = "https://graph.microsoft.com";
var authenticationContext = new AuthenticationContext(authorizationUrl);
authenticationContext.acquireTokenWithRefreshToken(
refreshToken,
instance.authenticatorClientId,
instance.authenticatorClientSecret,
resource,
async (err, res) => {
if (err) {
reject(err);
} else {
let token = res as TokenResponse;
await this.setValue(
instanceId,
"accessToken",
token.accessToken
);
await this.setValue(
instanceId,
"refreshToken",
token.refreshToken
);
await this.setValue(
instanceId,
"expiresOn",
token.expiresOn.toString()
);
resolve(token.accessToken);
}
}
);
}
});
}
public static async getADALTokenFromUsername(
username: string,
password: string
) {
let credentials = await GBAdminService.getADALCredentialsFromUsername(
username,
password
);
let accessToken = credentials.tokenCache._entries[0].accessToken;
return accessToken;
}
public static async getADALCredentialsFromUsername(
username: string,
password: string
) {
let credentials = await msRestAzure.loginWithUsernamePassword(
username,
password
);
return credentials;
}
public static getRndPassword() {
const passwordGenerator = new PasswordGenerator();
const options = {
upperCaseAlpha: true,
lowerCaseAlpha: true,
number: true,
specialCharacter: true,
minimumLength: 12,
maximumLength: 14
};
let password = passwordGenerator.generatePassword(options);
password = password.replace(/@[=:;\?]/g, "#");
return password;
}
public static getRndReadableIdentifier() {
const passwordGenerator = new PasswordGenerator();
const options = {
upperCaseAlpha: false,
lowerCaseAlpha: true,
number: false,
specialCharacter: false,
minimumLength: 12,
maximumLength: 14
};
let name = passwordGenerator.generatePassword(options);
return name;
}
}

View file

@ -0,0 +1,22 @@
export const Messages = {
"en-US": {
authenticate: "Please, authenticate:",
welcome: "Welcome to Pragmatismo.io GeneralBots Administration.",
which_task: "Which task do you wanna run now?",
working:(command)=> `I'm working on ${command}...`,
finshed_working:"Done.",
unknown_command: text =>
`Well, but ${text} is not a administrative General Bots command, I will try to search for it.`,
hi: text => `Hello, ${text}.`,
undeployPackage: text => `Undeploying package ${text}...`,
deployPackage: text => `Deploying package ${text}...`,
redeployPackage: text => `Redeploying package ${text}...`,
packageUndeployed: text => `Package ${text} undeployed...`,
consent: (url)=>`Please, consent access to this app at: [Microsoft Online](${url}).`,
wrong_password: "Sorry, wrong password. Please, try again."
},
"pt-BR": {
show_video: "Vou te mostrar um vídeo. Por favor, aguarde...",
hi: msg => `Oi, ${msg}.`
}
};

View file

@ -0,0 +1,62 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict"
const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from "sequelize-typescript"
export class GBAnalyticsPackage implements IGBPackage {
sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
}
unloadPackage(core: IGBCoreService): void {
}
loadBot(min: GBMinInstance): void {
}
unloadBot(min: GBMinInstance): void {
}
onNewSession(min: GBMinInstance, step: any): void {
}
}

View file

@ -0,0 +1,146 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict"
import {
DataTypes,
DataTypeUUIDv4,
DataTypeDate,
DataTypeDecimal
} from "sequelize"
import {
Sequelize,
Table,
Column,
Model,
HasMany,
BelongsTo,
BelongsToMany,
Length,
ForeignKey,
CreatedAt,
UpdatedAt,
DataType,
IsUUID,
PrimaryKey,
AutoIncrement
} from "sequelize-typescript"
import { GuaribasSubject } from "../../kb.gbapp/models"
import { GuaribasUser } from "../../security.gblib/models"
import { GuaribasChannel, GuaribasInstance } from "../../core.gbapp/models/GBModel"
@Table
export class GuaribasConversation extends Model<GuaribasConversation> {
@PrimaryKey
@AutoIncrement
@Column
conversationId: number
@ForeignKey(() => GuaribasSubject)
@Column
startSubjectId: number
@BelongsTo(() => GuaribasSubject)
startSubject: GuaribasSubject
@ForeignKey(() => GuaribasChannel)
@Column
channelId: string
@Column rateDate: Date
@Column(DataType.FLOAT)
@Column
rate: number
@Column
@CreatedAt
createdAt: Date
@Column text: string
@HasMany(() => GuaribasConversationMessage)
conversationMessage: GuaribasConversationMessage[]
@ForeignKey(() => GuaribasUser)
@Column
startedByUserId: number
@BelongsTo(() => GuaribasUser)
startedBy: GuaribasUser
}
@Table
export class GuaribasConversationMessage extends Model<GuaribasConversationMessage> {
@PrimaryKey
@AutoIncrement
@Column
conversationMessageId: number
@ForeignKey(() => GuaribasSubject)
@Column
subjectId: number
@Column(DataType.TEXT)
content: string
@Column
@CreatedAt
createdAt: Date
@Column
@UpdatedAt
updatedAt: Date
@ForeignKey(() => GuaribasConversation)
@Column
conversationId: number
@BelongsTo(() => GuaribasConversation)
conversation: GuaribasConversation
@ForeignKey(() => GuaribasInstance)
@Column
instanceId: number
@ForeignKey(() => GuaribasUser)
@Column
userId: number
@BelongsTo(() => GuaribasUser)
user: GuaribasUser
}

View file

@ -0,0 +1,67 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
import { GuaribasUser } from "../../security.gblib/models"
import { GuaribasConversation, GuaribasConversationMessage } from "../models"
export class AnalyticsService {
async createConversation(
user: GuaribasUser
): Promise<GuaribasConversation> {
return new Promise<GuaribasConversation>(
(resolve, reject) => {
let conversation = new GuaribasConversation()
conversation.startedBy = user
conversation.startedByUserId = user.userId
conversation.save().then((value: GuaribasConversation) => {
resolve(value)
})
})
}
createMessage(
conversation: GuaribasConversation,
user: GuaribasUser,
content: string
): Promise<GuaribasConversationMessage> {
return new Promise<GuaribasConversationMessage>(
(resolve, reject) => {
let message = GuaribasConversationMessage.build()
message.conversation = conversation
message.user = user
message.content = content
message.save().then((value: GuaribasConversationMessage) => {
resolve(value)
})
})
}
}

View file

@ -0,0 +1,67 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict";
import { GBMinInstance } from "botlib";
import { IGBDialog } from "botlib";
import { BotAdapter } from "botbuilder";
import { Messages } from "../strings";
export class BotFarmDialog extends IGBDialog {
/**
* Setup dialogs flows and define services call.
*
* @param bot The bot adapter.
* @param min The minimal bot instance data.
*/
static setup(bot: BotAdapter, min: GBMinInstance) {
min.dialogs.add("/createBotFarm", [
async step => {
let locale = step.context.activity.locale;
await step.prompt("choicePrompt", Messages[locale].what_about_me, [
"1",
"2",
"3",
"4",
"5"
]);
},
async step => {
let locale = step.context.activity.locale;
await step.context.sendActivity(Messages[locale].thanks);
}
]);
}
}

View file

@ -0,0 +1,61 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict"
const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from "sequelize-typescript"
export class GBWhatsappPackage implements IGBPackage {
sysPackages: IGBPackage[] = null
loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
}
unloadPackage(core: IGBCoreService): void {
}
loadBot(min: GBMinInstance): void {
}
unloadBot(min: GBMinInstance): void {
}
onNewSession(min: GBMinInstance, step: any): void {
}
}

View file

@ -0,0 +1,909 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict";
import { GBService, IGBInstance } from "botlib";
import {
ResourceManagementClient,
SubscriptionClient
} from "azure-arm-resource";
import { WebSiteManagementClient } from "azure-arm-website";
import { SqlManagementClient } from "azure-arm-sql";
import { CognitiveServicesManagementClient } from "azure-arm-cognitiveservices";
import { CognitiveServicesAccount } from "azure-arm-cognitiveservices/lib/models";
import { SearchManagementClient } from "azure-arm-search";
import { WebResource, ServiceClient, HttpMethods } from "ms-rest-js";
import * as simplegit from "simple-git/promise";
import { AppServicePlan } from "azure-arm-website/lib/models";
import { GBConfigService } from "../../../packages/core.gbapp/services/GBConfigService";
import { GBAdminService } from "../../../packages/admin.gbapp/services/GBAdminService";
import { GBCorePackage } from "../../../packages/core.gbapp";
import { GBDeployer } from "packages/core.gbapp/services/GBDeployer";
const Spinner = require("cli-spinner").Spinner;
const scanf = require("scanf");
const git = simplegit();
const logger = require("../../../src/logger");
const UrlJoin = require("url-join");
const iconUrl =
"https://github.com/pragmatismo-io/BotServer/blob/master/docs/images/generalbots-logo-squared.png";
const publicIp = require("public-ip");
export class AzureDeployerService extends GBService {
instance: IGBInstance;
resourceClient: ResourceManagementClient.ResourceManagementClient;
webSiteClient: WebSiteManagementClient;
storageClient: SqlManagementClient;
cognitiveClient: CognitiveServicesManagementClient;
searchClient: SearchManagementClient;
provider = "Microsoft.BotService";
subscriptionClient: SubscriptionClient.SubscriptionClient;
accessToken: string;
location: string;
public subscriptionId: string;
static apiVersion = "2017-12-01";
farmName: any;
deployer: GBDeployer;
constructor(deployer: GBDeployer){
super();
this.deployer = deployer;
}
public static async getSubscriptions(credentials) {
let subscriptionClient = new SubscriptionClient.default(credentials);
return subscriptionClient.subscriptions.list();
}
public async deployFarm(proxyAddress: string): Promise<IGBInstance> {
let culture = "en-us";
// Tries do get information from .env file otherwise asks in command-line.
let instance: IGBInstance = {};
instance = await this.ensureConfiguration(instance);
instance.marketplacePassword = GBAdminService.getRndPassword();
let spinner = new Spinner("%s");
spinner.start();
spinner.setSpinnerString("|/-\\");
let keys: any;
let name = instance.botId;
logger.info(`Deploying Deploy Group (It may take a few minutes)...`);
await this.createDeployGroup(name, instance.cloudLocation);
logger.info(`Deploying Bot Server...`);
let serverFarm = await this.createHostingPlan(
name,
`${name}-server-plan`,
instance.cloudLocation
);
await this.createServer(
serverFarm.id,
name,
`${name}-server`,
instance.cloudLocation
);
logger.info(`Deploying Bot Storage...`);
let administratorLogin = `sa${GBAdminService.getRndReadableIdentifier()}`;
let administratorPassword = GBAdminService.getRndPassword();
let storageServer = `${name}-storage-server`;
let storageName = `${name}-storage`;
await this.createStorageServer(
name,
storageServer,
administratorLogin,
administratorPassword,
storageServer,
instance.cloudLocation
);
await this.createStorage(
name,
storageServer,
storageName,
instance.cloudLocation
);
instance.storageUsername = administratorLogin;
instance.storagePassword = administratorPassword;
instance.storageName = storageName;
instance.storageDialect = "mssql";
instance.storageServer = storageServer;
logger.info(`Deploying Search...`);
let searchName = `${name}-search`;
await this.createSearch(name, searchName, instance.cloudLocation);
let searchKeys = await this.searchClient.adminKeys.get(
name,
searchName
);
instance.searchHost = `${searchName}.search.windows.net`;
instance.searchIndex = "azuresql-index";
instance.searchIndexer = "azuresql-indexer";
instance.searchKey = searchKeys.primaryKey;
this.deployer.rebuildIndex(instance);
logger.info(`Deploying Speech...`);
let speech = await this.createSpeech(
name,
`${name}-speech`,
instance.cloudLocation
);
keys = await this.cognitiveClient.accounts.listKeys(name, speech.name);
instance.speechKeyEndpoint = speech.endpoint;
instance.speechKey = keys.key1;
logger.info(`Deploying SpellChecker...`);
let spellChecker = await this.createSpellChecker(
name,
`${name}-spellchecker`,
instance.cloudLocation
);
keys = await this.cognitiveClient.accounts.listKeys(
name,
spellChecker.name
);
instance.spellCheckerKey = keys.key1;
instance.spellCheckerEndpoint = spellChecker.endpoint;
logger.info(`Deploying Text Analytics...`);
let textAnalytics = await this.createTextAnalytics(
name,
`${name}-textanalytics`,
instance.cloudLocation
);
keys = await this.cognitiveClient.accounts.listKeys(
name,
textAnalytics.name
);
instance.textAnalyticsEndpoint = textAnalytics.endpoint;
instance.textAnalyticsKey = keys.key1;
logger.info(`Deploying NLP...`);
let nlp = await this.createNLP(name, `${name}-nlp`, instance.cloudLocation);
keys = await this.cognitiveClient.accounts.listKeys(name, nlp.name);
let nlpAppId = await this.createLUISApp(
name,
name,
instance.cloudLocation,
culture,
instance.nlpAuthoringKey
);
instance.nlpEndpoint = nlp.endpoint;
instance.nlpKey = keys.key1;
instance.nlpAppId = nlpAppId;
logger.info(`Deploying Bot...`);
instance = await this.deployBootBot(
instance,
name,
`${proxyAddress}/api/messages/${name}`,
instance.nlpAppId,
instance.nlpKey,
instance.cloudSubscriptionId
);
spinner.stop();
return instance;
}
public async openStorageFirewall(groupName, serverName) {
let username = GBConfigService.get("CLOUD_USERNAME");
let password = GBConfigService.get("CLOUD_PASSWORD");
let subscriptionId = GBConfigService.get("CLOUD_SUBSCRIPTIONID");
let credentials = await GBAdminService.getADALCredentialsFromUsername(
username,
password
);
let storageClient = new SqlManagementClient(credentials, subscriptionId);
let ip = await publicIp.v4();
let params = {
startIpAddress: ip,
endIpAddress: ip
};
await storageClient.firewallRules.createOrUpdate(
groupName,
serverName,
"gb",
params
);
}
private async ensureConfiguration(instance: IGBInstance) {
let username = GBConfigService.get("CLOUD_USERNAME");
let password = GBConfigService.get("CLOUD_PASSWORD");
let subscriptionId = GBConfigService.get("CLOUD_SUBSCRIPTIONID");
let location = GBConfigService.get("CLOUD_LOCATION");
let botId = GBConfigService.get("BOT_ID");
// No .env so asks for cloud credentials to start a new farm.
if (!username || !password || !subscriptionId || !location || !botId) {
process.stdout.write(
"A empty enviroment is detected. To start automatic deploy, please enter some information:\n"
);
}
let retriveUsername = () => {
if (!username) {
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_USERNAME:`);
username = scanf("%s").replace(/(\n|\r)+$/, "");
}
};
let retrivePassword = () => {
if (!password) {
process.stdout.write(`${GBAdminService.GB_PROMPT}CLOUD_PASSWORD:`);
password = scanf("%s").replace(/(\n|\r)+$/, "");
}
};
let retrieveBotId = () => {
if (!botId) {
process.stdout.write(
`${GBAdminService.GB_PROMPT}Bot Id must only contain lowercase letters, digits or dashes, cannot start or end with or contain consecutive dashes and is limited from 4 to 42 characters long.\n`
);
process.stdout.write(`${GBAdminService.GB_PROMPT}BOT_ID:`);
botId = scanf("%s").replace(/(\n|\r)+$/, ""); // TODO: Update this regexp to match description of it.
}
};
let authoringKey = GBConfigService.get("NLP_AUTHORING_KEY");
let retriveAuthoringKey = () => {
if (!authoringKey) {
process.stdout.write(
`${GBAdminService.GB_PROMPT}Due to this opened issue: https://github.com/Microsoft/botbuilder-tools/issues/550\n`
);
process.stdout.write(`${GBAdminService.GB_PROMPT}Please enter your LUIS Authoring Key:`);
authoringKey = scanf("%s").replace(/(\n|\r)+$/, "");
}
};
while (!authoringKey) {
retriveAuthoringKey();
}
while (!botId) {
retrieveBotId();
}
while (!username) {
retriveUsername();
}
while (!password) {
retrivePassword();
}
// Connects to the cloud and retrives subscriptions.
let credentials = await GBAdminService.getADALCredentialsFromUsername(
username,
password
);
if (!subscriptionId) {
let map = {};
let index = 1;
let list = await AzureDeployerService.getSubscriptions(credentials);
list.forEach(element => {
console.log(
`${index}: ${element.displayName} (${element.subscriptionId})`
);
map[index++] = element;
});
let subscriptionIndex;
let retrieveSubscription = () => {
if (!subscriptionIndex) {
process.stdout.write("CLOUD_SUBSCRIPTIONID (type a number):");
subscriptionIndex = scanf("%d");
}
};
while (!subscriptionIndex) {
retrieveSubscription();
}
subscriptionId = map[subscriptionIndex].subscriptionId;
}
let retriveLocation = () => {
if (!location) {
process.stdout.write("CLOUD_LOCATION (eg. 'westus'):");
location = scanf("%s");
}
};
while (!location) {
retriveLocation();
}
// Prepares the first instance on bot farm.
instance.botId = botId;
instance.cloudUsername = username;
instance.cloudPassword = password;
instance.cloudSubscriptionId = subscriptionId;
instance.cloudLocation = location;
instance.nlpAuthoringKey = authoringKey;
instance.adminPass = GBAdminService.getRndPassword();
this.resourceClient = new ResourceManagementClient.default(
credentials,
subscriptionId
);
this.webSiteClient = new WebSiteManagementClient(
credentials,
subscriptionId
);
this.storageClient = new SqlManagementClient(credentials, subscriptionId);
this.cognitiveClient = new CognitiveServicesManagementClient(
credentials,
subscriptionId
);
this.searchClient = new SearchManagementClient(credentials, subscriptionId);
this.accessToken = credentials.tokenCache._entries[0].accessToken;
return instance;
}
public async deployBootBot(
instance,
botId,
endpoint,
nlpAppId,
nlpKey,
subscriptionId
) {
let appId = GBConfigService.get("MARKETPLACE_ID");
let appPassword = GBConfigService.get("MARKETPLACE_SECRET");
if (!appId || !appPassword) {
process.stdout.write(
"Sorry, this part cannot be automated yet due to Microsoft schedule, please go to https://apps.dev.microsoft.com/portal/register-app to generate manually an App ID and App Secret.\n"
);
}
let retriveAppId = () => {
if (!appId) {
process.stdout.write("Generated Application Id (MARKETPLACE_ID):");
appId = scanf("%s").replace(/(\n|\r)+$/, "");
}
};
let retriveAppPassword = () => {
if (!appPassword) {
process.stdout.write("Generated Password (MARKETPLACE_SECRET):");
appPassword = scanf("%s").replace(/(\n|\r)+$/, "");
}
};
retriveAppId();
retriveAppPassword();
await this.internalDeployBot(
instance,
this.accessToken,
botId,
botId,
botId,
"General BootBot",
endpoint,
"global",
nlpAppId,
nlpKey,
appId,
appPassword,
subscriptionId
);
instance.marketplaceId = appId;
instance.marketplacePassword = appPassword;
instance.botId = botId;
return instance;
}
private async createStorageServer(
group,
name,
administratorLogin,
administratorPassword,
serverName,
location
) {
var params = {
location: location,
administratorLogin: administratorLogin,
administratorLoginPassword: administratorPassword,
fullyQualifiedDomainName: `${serverName}.database.windows.net`
};
return this.storageClient.servers.createOrUpdate(group, name, params);
}
private async registerProviders(subscriptionId, baseUrl, accessToken) {
let query = `subscriptions/${subscriptionId}/providers/${
this.provider
}/register?api-version=2018-02-01`;
let requestUrl = UrlJoin(baseUrl, query);
let req = new WebResource();
req.method = "POST";
req.url = requestUrl;
req.headers = {};
req.headers["Content-Type"] = "application/json; charset=utf-8";
req.headers["accept-language"] = "*";
req.headers["Authorization"] = "Bearer " + accessToken;
let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req);
// TODO: Check res for error.
}
/**
* @see https://github.com/Azure/azure-rest-api-specs/blob/master/specification/botservice/resource-manager/Microsoft.BotService/preview/2017-12-01/botservice.json
*/
private async internalDeployBot(
instance,
accessToken,
botId,
name,
group,
description,
endpoint,
location,
nlpAppId,
nlpKey,
appId,
appPassword,
subscriptionId
) {
return new Promise(async (resolve, reject) => {
let baseUrl = `https://management.azure.com/`;
await this.registerProviders(subscriptionId, baseUrl, accessToken);
instance.marketplaceId = appId;
instance.marketplacePassword = appPassword;
instance.engineName = GBCorePackage.CurrentEngineName;
let parameters = {
location: location,
sku: {
name: "F0"
},
name: botId,
kind: "bot",
properties: {
description: description,
displayName: name,
endpoint: endpoint,
iconUrl: iconUrl,
luisAppIds: [nlpAppId],
luisKey: nlpKey,
msaAppId: appId,
msaAppPassword: appPassword,
enabledChannels: ["webchat"], // , "skype", "facebook"],
configuredChannels: ["webchat"] // , "skype", "facebook"]
}
};
let httpClient = new ServiceClient();
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider
}/botServices/${botId}?api-version=${AzureDeployerService.apiVersion}`;
let url = UrlJoin(baseUrl, query);
let req = this.createRequestObject(
url,
accessToken,
"PUT",
JSON.stringify(parameters)
);
let res = await httpClient.sendRequest(req);
if (!(res.bodyAsJson as any).id) {
reject(res.bodyAsText);
return;
}
setTimeout(async () => {
try {
query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/Microsoft.BotService/botServices/${botId}/channels/WebChatChannel/listChannelWithKeys?api-version=${
AzureDeployerService.apiVersion
}`;
url = UrlJoin(baseUrl, query);
req = this.createRequestObject(
url,
accessToken,
"GET",
JSON.stringify(parameters)
);
let resChannel = await httpClient.sendRequest(req);
let key = (resChannel.bodyAsJson as any).properties.properties
.sites[0].key;
instance.webchatKey = key;
resolve(instance);
} catch (error) {
reject(error);
}
}, 20000);
});
}
public async updateBotProxy(botId, group, endpoint) {
let baseUrl = `https://management.azure.com/`;
let username = GBConfigService.get("CLOUD_USERNAME");
let password = GBConfigService.get("CLOUD_PASSWORD");
let subscriptionId = GBConfigService.get("CLOUD_SUBSCRIPTIONID");
let accessToken = await GBAdminService.getADALTokenFromUsername(
username,
password
);
let httpClient = new ServiceClient();
let parameters = {
properties: {
endpoint: endpoint
}
};
let query = `subscriptions/${subscriptionId}/resourceGroups/${group}/providers/${
this.provider
}/botServices/${botId}?api-version=${AzureDeployerService.apiVersion}`;
let url = UrlJoin(baseUrl, query);
let req = this.createRequestObject(
url,
accessToken,
"PATCH",
JSON.stringify(parameters)
);
let res = await httpClient.sendRequest(req);
if (!(res.bodyAsJson as any).id) {
throw res.bodyAsText;
}
logger.info(`Bot proxy updated at: ${endpoint}.`);
}
private createRequestObject(
url: string,
accessToken: string,
verb: HttpMethods,
body: string
) {
let req = new WebResource();
req.method = verb;
req.url = url;
req.headers = {};
req.headers["Content-Type"] = "application/json";
req.headers["accept-language"] = "*";
req.headers["Authorization"] = "Bearer " + accessToken;
req.body = body;
return req;
}
private async createLUISApp(
name: string,
description: string,
location: string,
culture: string,
authoringKey: string
) {
let parameters = {
name: name,
description: description,
culture: culture
};
let body = JSON.stringify(parameters);
let apps = await this.makeNlpRequest(
location,
authoringKey,
null,
"GET",
"apps"
);
let app = (apps.bodyAsJson as any).filter(x => x.name == name)[0];
let id: string;
if (!app) {
let res = await this.makeNlpRequest(
location,
authoringKey,
body,
"POST",
"apps"
);
id = res.bodyAsText;
} else {
id = app.id;
}
return id;
}
private async makeNlpRequest(
location: string,
authoringKey: string,
body: string,
method: HttpMethods,
resource: string
) {
let req = new WebResource();
req.method = method;
req.url = `https://${location}.api.cognitive.microsoft.com/luis/api/v2.0/${resource}`;
req.headers = {};
req.headers["Content-Type"] = "application/json";
req.headers["accept-language"] = "*";
req.headers["Ocp-Apim-Subscription-Key"] = authoringKey;
req.body = body;
let httpClient = new ServiceClient();
let res = await httpClient.sendRequest(req);
return res;
}
private async createSearch(group, name, location) {
var params = {
sku: { name: "free" },
location: location
};
return this.searchClient.services.createOrUpdate(group, name, params);
}
private async createStorage(group, serverName, name, location) {
var params = {
sku: { name: "Free" },
createMode: "Default",
location: location
};
return this.storageClient.databases.createOrUpdate(
group,
serverName,
name,
params
);
}
private async createCognitiveServices(
group,
name,
location,
kind
): Promise<CognitiveServicesAccount> {
let params = {
sku: { name: "F0" },
createMode: "Default",
location: location,
kind: kind,
properties: {}
};
return await this.cognitiveClient.accounts.create(group, name, params);
}
private async createSpeech(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
location,
"SpeechServices"
);
}
private async createNLP(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(group, name, location, "LUIS");
}
private async createSpellChecker(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
"global",
"Bing.SpellCheck.v7"
);
}
private async createTextAnalytics(
group,
name,
location
): Promise<CognitiveServicesAccount> {
return await this.createCognitiveServices(
group,
name,
location,
"TextAnalytics"
);
}
private async createDeployGroup(name, location) {
var params = { location: location };
return this.resourceClient.resourceGroups.createOrUpdate(name, params);
}
private async createHostingPlan(
group,
name,
location
): Promise<AppServicePlan> {
let params = {
serverFarmWithRichSkuName: name,
location: location,
sku: {
name: "F1",
capacity: 1,
tier: "Free"
}
};
return this.webSiteClient.appServicePlans.createOrUpdate(
group,
name,
params
);
}
private async createServer(farmId, group, name, location) {
var parameters = {
location: location,
serverFarmId: farmId
};
return this.webSiteClient.webApps.createOrUpdate(group, name, parameters);
}
private async updateWebisteConfig(group, serverFarmId, name, location) {
var siteConfig = {
location: location,
serverFarmId: serverFarmId,
numberOfWorkers: 1,
phpVersion: "5.5"
};
// TODO: Copy .env to app settings.
return this.webSiteClient.webApps.createOrUpdateConfiguration(
group,
name,
siteConfig
);
}
async deployGeneralBotsToAzure() {
let status = await git.status();
// TODO: Copy github to webapp.
}
static getKBSearchSchema(indexName) {
return {
name: indexName,
fields: [
{
name: "questionId",
type: "Edm.String",
searchable: false,
filterable: false,
retrievable: true,
sortable: false,
facetable: false,
key: true
},
{
name: "subject1",
type: "Edm.String",
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: "subject2",
type: "Edm.String",
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: "subject3",
type: "Edm.String",
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: "subject4",
type: "Edm.String",
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: "content",
type: "Edm.String",
searchable: true,
filterable: false,
retrievable: false,
sortable: false,
facetable: false,
key: false
},
{
name: "answerId",
type: "Edm.Int32",
searchable: false,
filterable: false,
retrievable: true,
sortable: false,
facetable: false,
key: false
},
{
name: "instanceId",
type: "Edm.Int32",
searchable: false,
filterable: true,
retrievable: true,
sortable: false,
facetable: false,
key: false
},
{
name: "packageId",
type: "Edm.Int32",
searchable: false,
filterable: true,
retrievable: true,
sortable: false,
facetable: false,
key: false
}
],
scoringProfiles: [],
defaultScoringProfile: null,
corsOptions: null
};
}
}

View file

@ -0,0 +1,8 @@
export const Messages = {
"en-US": {
about_suggestions: "Suggestions are welcomed and improve my quality...",
},
"pt-BR": {
about_suggestions: "Sugestões melhoram muito minha qualidade...",
}
};

View file

@ -0,0 +1,61 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
"use strict"
const UrlJoin = require("url-join")
import { GBMinInstance, IGBPackage, IGBCoreService } from "botlib"
import { Sequelize } from 'sequelize-typescript'
import { ConsoleDirectLine } from "./services/ConsoleDirectLine"
export class GBConsolePackage implements IGBPackage {
sysPackages: IGBPackage[] = null
channel: ConsoleDirectLine
loadPackage(core: IGBCoreService, sequelize: Sequelize): void {
}
unloadPackage(core: IGBCoreService): void {
}
loadBot(min: GBMinInstance): void {
this.channel = new ConsoleDirectLine(min.instance.webchatKey)
}
unloadBot(min: GBMinInstance): void {
}
onNewSession(min: GBMinInstance, step: any): void {
}
}

View file

@ -0,0 +1,194 @@
/*****************************************************************************\
| ( )_ _ |
| _ _ _ __ _ _ __ ___ ___ _ _ | ,_)(_) ___ ___ _ |
| ( '_`\ ( '__)/'_` ) /'_ `\/' _ ` _ `\ /'_` )| | | |/',__)/' _ `\ /'_`\ |
| | (_) )| | ( (_| |( (_) || ( ) ( ) |( (_| || |_ | |\__, \| ( ) |( (_) ) |
| | ,__/'(_) `\__,_)`\__ |(_) (_) (_)`\__,_)`\__)(_)(____/(_) (_)`\___/' |
| | | ( )_) | |
| (_) \___/' |
| |
| General Bots Copyright (c) Pragmatismo.io. All rights reserved. |
| Licensed under the AGPL-3.0. |
| |
| According to our dual licensing model, this program can be used either |
| under the terms of the GNU Affero General Public License, version 3, |
| or under a proprietary license. |
| |
| The texts of the GNU Affero General Public License with an additional |
| permission and of our proprietary license can be found at and |
| in the LICENSE file you have received along with this program. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY, without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU Affero General Public License for more details. |
| |
| "General Bots" is a registered trademark of Pragmatismo.io. |
| The licensing of the program under the AGPLv3 does not imply a |
| trademark license. Therefore any rights, title and interest in |
| our trademarks remain entirely with us. |
| |
\*****************************************************************************/
const Path = require("path")
const Fs = require("fs")
const _ = require("lodash")
const Parse = require("csv-parse")
const Async = require("async")
const UrlJoin = require("url-join")
const Walk = require("fs-walk")
const logger = require("../../../src/logger")
const Swagger = require('swagger-client')
const rp = require('request-promise')
import { GBService } from "botlib"
export class ConsoleDirectLine extends GBService {
pollInterval = 1000
directLineSecret = ''
directLineClientName = 'DirectLineClient'
directLineSpecUrl = 'https://docs.botframework.com/en-us/restapi/directline3/swagger.json'
constructor(directLineSecret) {
super()
this.directLineSecret = directLineSecret
// TODO: Migrate to Swagger 3.
let directLineClient = rp(this.directLineSpecUrl)
.then(function (spec) {
return new Swagger({
spec: JSON.parse(spec.trim()),
usePromise: true
})
})
.then(function (client) {
client.clientAuthorizations.add('AuthorizationBotConnector',
new Swagger.ApiKeyAuthorization('Authorization', 'Bearer ' + directLineSecret, 'header'))
return client
})
.catch(function (err) {
console.error('Error initializing DirectLine client', err)
})
// TODO: Remove *this* issue.
let _this_ = this
directLineClient.then((client)=> {
client.Conversations.Conversations_StartConversation()
.then(function (response) {
return response.obj.conversationId
})
.then(function (conversationId) {
_this_.sendMessagesFromConsole(client, conversationId)
_this_.pollMessages(client, conversationId)
})
.catch(function (err) {
console.error('Error starting conversation', err)
})
})
}
sendMessagesFromConsole(client, conversationId) {
let _this_ = this
process.stdin.resume()
var stdin = process.stdin
process.stdout.write('Command> ')
stdin.addListener('data', function (e) {
var input = e.toString().trim()
if (input) {
// exit
if (input.toLowerCase() === 'exit') {
return process.exit()
}
client.Conversations.Conversations_PostActivity(
{
conversationId: conversationId,
activity: {
textFormat: 'plain',
text: input,
type: 'message',
from: {
id: _this_.directLineClientName,
name: _this_.directLineClientName
}
}
}).catch(function (err) {
console.error('Error sending message:', err)
})
process.stdout.write('Command> ')
}
})
}
/** TBD: Poll Messages from conversation using DirectLine client */
pollMessages(client, conversationId) {
let _this_ = this
console.log('Starting polling message for conversationId: ' + conversationId)
var watermark = null
setInterval(function () {
client.Conversations.Conversations_GetActivities({ conversationId: conversationId, watermark: watermark })
.then(function (response) {
watermark = response.obj.watermark // use watermark so subsequent requests skip old messages
return response.obj.activities
})
.then(_this_.printMessages, _this_.directLineClientName)
}, this.pollInterval)
}
printMessages(activities, directLineClientName) {
if (activities && activities.length) {
// ignore own messages
activities = activities.filter(function (m) { return m.from.id !== directLineClientName })
if (activities.length) {
// print other messages
activities.forEach(activity => {
console.log(activity.text)
}, this)
process.stdout.write('Command> ')
}
}
}
printMessage(activity) {
if (activity.text) {
console.log(activity.text)
}
if (activity.attachments) {
activity.attachments.forEach(function (attachment) {
switch (attachment.contentType) {
case "application/vnd.microsoft.card.hero":
this.renderHeroCard(attachment)
break
case "image/png":
console.log('Opening the requested image ' + attachment.contentUrl)
open(attachment.contentUrl)
break
}
})
}
}
renderHeroCard(attachment) {
var width = 70
var contentLine = function (content) {
return ' '.repeat((width - content.length) / 2) +
content +
' '.repeat((width - content.length) / 2)
}
console.log('/' + '*'.repeat(width + 1))
console.log('*' + contentLine(attachment.content.title) + '*')
console.log('*' + ' '.repeat(width) + '*')
console.log('*' + contentLine(attachment.content.text) + '*')
console.log('*'.repeat(width + 1) + '/')
}
}

View file

@ -0,0 +1 @@
*This is a General Bots open core package, more information can be found on the [BotServer](https://github.com/pragmatismo-io/BotServer) repository.*

Some files were not shown because too many files have changed in this diff Show more