diff --git a/.github/workflows/playwright-tests.yml b/.github/workflows/playwright-tests.yml
new file mode 100644
index 00000000..7f8c531e
--- /dev/null
+++ b/.github/workflows/playwright-tests.yml
@@ -0,0 +1,63 @@
+name: Testes de Sanidade com Playwright
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+jobs:
+ test-on-ubuntu:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '18'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Install Playwright browsers
+ run: npx playwright install --with-deps
+
+ - name: Garantir permissão de execução do launcher
+ run: chmod +x ./agi-launcher-universal-v3.sh
+
+ - name: Iniciar app em background
+ run: |
+ ./agi-launcher-universal-v3.sh --Debug &
+ sleep 10 # Tempo para inicialização do app
+
+ - name: Rodar testes Playwright
+ run: npx playwright test
+
+ test-on-windows:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: '18'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Install Playwright browsers
+ run: npx playwright install --with-deps
+
+ - name: Iniciar app via launcher
+ run: |
+ .\agi-launcher-universal-v3.sh --Debug
+ sleep 10 # Tempo para inicialização do app
+
+ - name: Rodar testes Playwright
+ run: npx playwright test
diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml
new file mode 100644
index 00000000..c73e032c
--- /dev/null
+++ b/.github/workflows/pylint.yml
@@ -0,0 +1,23 @@
+name: Pylint
+
+on: [push]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: ["3.8", "3.9", "3.10"]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install pylint
+ - name: Analysing the code with pylint
+ run: |
+ pylint $(git ls-files '*.py')
diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml
new file mode 100644
index 00000000..82f8dbd9
--- /dev/null
+++ b/.github/workflows/python-publish.yml
@@ -0,0 +1,70 @@
+# This workflow will upload a Python Package to PyPI when a release is created
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
+
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+name: Upload Python Package
+
+on:
+ release:
+ types: [published]
+
+permissions:
+ contents: read
+
+jobs:
+ release-build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: actions/setup-python@v5
+ with:
+ python-version: "3.x"
+
+ - name: Build release distributions
+ run: |
+ # NOTE: put your own distribution build steps here.
+ python -m pip install build
+ python -m build
+
+ - name: Upload distributions
+ uses: actions/upload-artifact@v4
+ with:
+ name: release-dists
+ path: dist/
+
+ pypi-publish:
+ runs-on: ubuntu-latest
+ needs:
+ - release-build
+ permissions:
+ # IMPORTANT: this permission is mandatory for trusted publishing
+ id-token: write
+
+ # Dedicated environments with protections for publishing are strongly recommended.
+ # For more information, see: https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#deployment-protection-rules
+ environment:
+ name: pypi
+ # OPTIONAL: uncomment and update to include your PyPI project URL in the deployment status:
+ # url: https://pypi.org/p/YOURPROJECT
+ #
+ # ALTERNATIVE: if your GitHub Release name is the PyPI project version string
+ # ALTERNATIVE: exactly, uncomment the following line instead:
+ # url: https://pypi.org/project/YOURPROJECT/${{ github.event.release.name }}
+
+ steps:
+ - name: Retrieve release distributions
+ uses: actions/download-artifact@v4
+ with:
+ name: release-dists
+ path: dist/
+
+ - name: Publish release distributions to PyPI
+ uses: pypa/gh-action-pypi-publish@release/v1
+ with:
+ packages-dir: dist/
diff --git a/.github/workflows/release/release.yml b/.github/workflows/release/release.yml
new file mode 100644
index 00000000..a8c2e609
--- /dev/null
+++ b/.github/workflows/release/release.yml
@@ -0,0 +1,115 @@
+name: 🚀 AGI Multiplatform Release
+
+on:
+ push:
+ tags:
+ - "v*"
+ workflow_dispatch:
+ inputs:
+ version:
+ description: "Versão manual (ex: v0.91)"
+ required: false
+
+permissions:
+ contents: write
+
+env:
+ NODE_VERSION: 20
+ RELEASE_DIR: release
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ os: [windows-latest, ubuntu-latest, macos-latest]
+ name: Build ${{ matrix.os }}
+ steps:
+ - name: 🧩 Checkout
+ uses: actions/checkout@v4
+
+ - name: ⚙️ Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: yarn
+
+ - name: 📦 Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: 🏗️ Build AGI for ${{ matrix.os }}
+ run: |
+ mkdir -p $RELEASE_DIR
+ yarn build
+
+ - name: 📁 Upload artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: agi-${{ matrix.os }}
+ path: ${{ env.RELEASE_DIR }}/
+
+ android:
+ runs-on: ubuntu-latest
+ name: Build Android (Bubblewrap)
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: ⚙️ Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: 📦 Install Bubblewrap
+ run: npm i -g @bubblewrap/cli
+
+ - name: 📲 Build Android APK/AAB
+ run: |
+ mkdir -p $RELEASE_DIR
+ yarn build:android
+
+ - name: 📁 Upload Android artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: agi-android
+ path: ${{ env.RELEASE_DIR }}/
+
+ release:
+ runs-on: ubuntu-latest
+ needs: [build, android]
+ name: 📤 Publish GitHub Release
+ steps:
+ - name: 🧩 Checkout
+ uses: actions/checkout@v4
+
+ - name: 📥 Download all artifacts
+ uses: actions/download-artifact@v4
+ with:
+ path: ${{ env.RELEASE_DIR }}
+
+ - name: 🧾 List release contents
+ run: ls -R $RELEASE_DIR
+
+ - name: 🏷️ Determine version
+ id: version
+ run: |
+ echo "tag=${GITHUB_REF##*/}" >> $GITHUB_OUTPUT
+
+ - name: 🚀 Create GitHub Release
+ uses: softprops/action-gh-release@v2
+ with:
+ tag_name: ${{ steps.version.outputs.tag }}
+ name: "AGI ${{ steps.version.outputs.tag }}"
+ body: |
+ AGI Release ${{ steps.version.outputs.tag }}
+
+ **Includes:**
+ - Windows `.exe`
+ - Linux `.AppImage` `.deb` `.rpm`
+ - macOS `.app`
+ - Android `.apk` `.aab`
+
+ **Auto-generated by**: GitHub Actions 🚀
+ files: |
+ ${{ env.RELEASE_DIR }}/**/*
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml
new file mode 100644
index 00000000..2ff4bed5
--- /dev/null
+++ b/.github/workflows/test-build.yml
@@ -0,0 +1,38 @@
+name: Test Build Sanity
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ test-on-ubuntu:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Run AGI Launcher on Ubuntu
+ run: ./agi-launcher-universal-v3.sh --dry-run
+ # O --dry-run aqui apenas valida o build, sem abri-lo de fato.
+ # Em um teste real, você rodaria sem o --dry-run para iniciar o app.
+
+ test-on-macos:
+ runs-on: macos-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Run AGI Launcher on macOS
+ run: ./agi-launcher-universal-v3.sh --dry-run
+
+ test-on-windows:
+ runs-on: windows-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Run AGI Launcher on Windows (via Git Bash)
+ # O Git Bash já está disponível nos runners do Windows
+ shell: bash
+ run: ./agi-launcher-universal-v3.sh --dry-run
diff --git a/README.md b/README.md
index 2a312e6a..37ec47ca 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-
+
-# Talos: An AI Protocol Owner
+# AGI: An AI Protocol Owner
[](https://docs.talos.is/)
[](https://github.com/talos-agent/talos/releases)
@@ -134,9 +134,14 @@ The daemon will run continuously, executing scheduled jobs and can be gracefully
| `daemon` | Run in continuous daemon mode |
| `cleanup-users` | Clean up temporary users and conversation data |
| `db-stats` | Show database statistics |
+| `monitoring` | Start the monitoring service |
For detailed command usage, see the [CLI Documentation](https://docs.talos.is/cli/overview/).
+### Monitoring
+
+The `monitoring` command uses the [Sampler](https://github.com/sqshq/sampler) tool to provide real-time monitoring of the Talos agent. To use this feature, you must have Sampler installed and available in your system's PATH.
+
### Docker Usage
#### Building and Running with Docker
@@ -232,3 +237,4 @@ To run the test suite, lint, and type-check the code, run the following command:
```bash
./scripts/run_checks.sh
```
+Talos = AGI
diff --git a/agi-launcher-universal-v3(1).sh b/agi-launcher-universal-v3(1).sh
new file mode 100644
index 00000000..ee54b6c1
--- /dev/null
+++ b/agi-launcher-universal-v3(1).sh
@@ -0,0 +1,245 @@
+#!/usr/bin/env bash
+# --------------------------------------------------------------------------
+# AGI Universal Launcher v3 – Cross-Platform (Bash/WSL/Git Bash)
+# Uso: ./agi-launcher-universal-v3.sh [--path ] [--debug] [--dry-run]
+# --------------------------------------------------------------------------
+
+set -euo pipefail
+
+# --- CONFIGURAÇÃO ---
+REPO_DIR="agi"
+BUILD_ROOT="release"
+LOG_FILE="launcher-log-$(date +%Y-%m-%d_%H-%M-%S).txt"
+
+# Variáveis de Argumentos
+CUSTOM_PATH=""
+DEBUG_MODE=0
+DRY_RUN=0
+INTERACTIVE_MENU=1
+
+# --- FUNÇÕES DE UTILIDADE ---
+
+# Função de Log
+log() {
+ echo "[$(date +%H:%M:%S)] $1" | tee -a "$LOG_FILE"
+}
+
+# Função de erro e saída
+die() {
+ log "❌ ERRO: $1"
+ exit 1
+}
+
+# --- PARSING DE ARGUMENTOS ---
+
+parse_args() {
+ log "Analisando argumentos..."
+
+ # Parâmetros esperados
+ local options
+ options=$(getopt -o "" --long debug,dry-run,path: -- "$@")
+
+ if [ $? -ne 0 ]; then
+ die "Falha ao analisar argumentos."
+ fi
+
+ eval set -- "$options"
+
+ while true; do
+ case "$1" in
+ --debug)
+ DEBUG_MODE=1
+ log "Modo: DEBUG ativado."
+ shift
+ ;;
+ --dry-run)
+ DRY_RUN=1
+ log "Modo: DRY-RUN ativado (Nenhuma execução real)."
+ INTERACTIVE_MENU=0
+ shift
+ ;;
+ --path)
+ CUSTOM_PATH="$2"
+ log "Caminho customizado definido: $CUSTOM_PATH"
+ shift 2
+ ;;
+ --)
+ shift
+ break
+ ;;
+ *)
+ die "Argumento desconhecido: $1"
+ ;;
+ esac
+ done
+}
+
+# --- DETECÇÃO E RESOLUÇÃO DE CAMINHO ---
+
+detect_platform() {
+ local OS_NAME
+ OS_NAME=$(uname -s)
+ local TARGET_DIR=""
+ local EXTENSION=""
+
+ log "Detectando sistema operacional..."
+
+ case "$OS_NAME" in
+ Linux*)
+ if [[ -n "$WSL_DISTRO_NAME" ]] || [[ "$TERM" == *cygwin* ]]; then
+ log "Ambiente Windows (WSL/Git Bash) detectado."
+ TARGET_DIR="AGI-win32-x64"
+ EXTENSION=".exe"
+ # Se for WSL, usamos o .exe do Windows
+ else
+ log "Ambiente Linux detectado."
+ TARGET_DIR="AGI-linux-x64"
+ EXTENSION=".AppImage"
+ fi
+ ;;
+ Darwin*)
+ log "Ambiente macOS detectado."
+ TARGET_DIR="AGI-darwin-x64"
+ EXTENSION=".app"
+ ;;
+ MINGW*|CYGWIN*)
+ log "Ambiente Windows (Git Bash nativo) detectado."
+ TARGET_DIR="AGI-win32-x64"
+ EXTENSION=".exe"
+ ;;
+ *)
+ die "Sistema operacional não suportado: $OS_NAME"
+ ;;
+ esac
+
+ # Se um caminho customizado foi fornecido, usamos ele
+ if [ -n "$CUSTOM_PATH" ]; then
+ EXECUTABLE_PATH="$CUSTOM_PATH"
+ else
+ # Se não, resolvemos o caminho padrão
+ if [ "$EXTENSION" == ".app" ]; then
+ # No macOS, o .app é uma pasta, e o executável está dentro
+ EXECUTABLE_PATH="$BUILD_ROOT/$TARGET_DIR/AGI.app/Contents/MacOS/AGI"
+ # O usuário pode querer rodar o open, mas para fins de script, rodamos o binário
+ else
+ EXECUTABLE_PATH="$BUILD_ROOT/$TARGET_DIR/AGI$EXTENSION"
+ fi
+ fi
+
+ log "Caminho do executável alvo: $EXECUTABLE_PATH"
+ log "Extensão alvo: $EXTENSION"
+}
+
+# --- FUNÇÃO DE EXECUÇÃO ---
+
+run_app() {
+ log "Iniciando AGI..."
+
+ if [ ! -f "$EXECUTABLE_PATH" ] && [ ! -d "$EXECUTABLE_PATH" ]; then
+ die "Executável não encontrado em: $EXECUTABLE_PATH. Rode o build primeiro!"
+ fi
+
+ local EXEC_COMMAND
+ local DEBUG_FLAG=""
+
+ if [ "$DEBUG_MODE" -eq 1 ]; then
+ DEBUG_FLAG="--debug"
+ log "Execução com flag de DEBUG ativo."
+ fi
+
+ # Lógica de execução baseada na extensão
+ case "$EXTENSION" in
+ .app) # macOS
+ EXEC_COMMAND="open -a '$BUILD_ROOT/$TARGET_DIR/AGI.app' --args $DEBUG_FLAG"
+ ;;
+ .AppImage) # Linux
+ chmod +x "$EXECUTABLE_PATH"
+ EXEC_COMMAND="'$EXECUTABLE_PATH' $DEBUG_FLAG"
+ ;;
+ .exe) # Windows (via WSL/Git Bash) ou Linux binário
+ EXEC_COMMAND="'$EXECUTABLE_PATH' $DEBUG_FLAG"
+ ;;
+ *)
+ # Executa o binário diretamente
+ EXEC_COMMAND="'$EXECUTABLE_PATH' $DEBUG_FLAG"
+ ;;
+ esac
+
+ log "Comando de execução: $EXEC_COMMAND"
+
+ if [ "$DRY_RUN" -eq 1 ]; then
+ log "DRY-RUN: Simulação de execução concluída."
+ else
+ log "Executando..."
+ # Usamos eval para garantir que as aspas e comandos complexos funcionem
+ eval "$EXEC_COMMAND"
+ fi
+
+ log "AGI encerrado."
+}
+
+# --- MENU INTERATIVO (Para modo padrão) ---
+
+show_menu() {
+ log "Modo Interativo Ativo."
+ echo "--------------------------------------------------------"
+ echo " AGI Universal Launcher v3 (Executável: $EXTENSION)"
+ echo "--------------------------------------------------------"
+ echo "Executável alvo: $EXECUTABLE_PATH"
+ echo ""
+ echo "Opções:"
+ echo " 1) Iniciar AGI (Modo Normal)"
+ echo " 2) Iniciar AGI (Modo DEBUG - Logs detalhados)"
+ echo " 3) Ver caminho do executável"
+ echo " 4) Sair"
+ echo "--------------------------------------------------------"
+
+ local choice
+ read -r -p "Escolha uma opção (1-4): " choice
+
+ case $choice in
+ 1)
+ DEBUG_MODE=0
+ run_app
+ ;;
+ 2)
+ DEBUG_MODE=1
+ run_app
+ ;;
+ 3)
+ echo "Caminho: $EXECUTABLE_PATH"
+ log "Caminho exibido."
+ show_menu
+ ;;
+ 4)
+ log "Encerrando script."
+ exit 0
+ ;;
+ *)
+ echo "Opção inválida. Tente novamente."
+ show_menu
+ ;;
+ esac
+}
+
+# --- EXECUÇÃO PRINCIPAL ---
+
+main() {
+ parse_args "$@"
+ detect_platform
+
+ if [ "$DRY_RUN" -eq 1 ] || [ "$INTERACTIVE_MENU" -eq 0 ]; then
+ # Modo não interativo (Debug ou Dry-Run)
+ run_app
+ else
+ # Modo interativo (padrão)
+ show_menu
+ fi
+
+ log "Execução do launcher finalizada com sucesso."
+}
+
+# Inicia o script
+main "$@"
+
+# --- FIM DO SCRIPT ---
diff --git a/agi-launcher-universal-v3.sh b/agi-launcher-universal-v3.sh
new file mode 100644
index 00000000..9bc3de74
--- /dev/null
+++ b/agi-launcher-universal-v3.sh
@@ -0,0 +1,139 @@
+#!/usr/bin/env bash
+# --------------------------------------------------------------------------
+# AGI Universal Launcher v3 – Cross-Platform (Bash/WSL/Git Bash)
+# Uso: ./agi-launcher-universal-v3.sh [--Path ] [--Debug] [--DryRun]
+# --------------------------------------------------------------------------
+
+set -euo pipefail
+
+# ---------- config ----------
+LOG_FILE="launcher-log-$(date +%F_%H-%M-%S).txt"
+exec > >(tee -a "$LOG_FILE") 2>&1
+
+DEFAULT_PATHS=(
+ "$HOME/agi-build/agi/release/AGI-win32-x64/AGI.exe"
+ "$HOME/agi-build/agi/release/AGI-linux-x64/AGI.AppImage"
+ "$HOME/agi-build/agi/release/AGI-darwin-x64/AGI.app"
+ "./release/AGI-win32-x64/AGI.exe"
+ "./release/AGI-linux-x64/AGI.AppImage"
+ "./release/AGI-darwin-x64/AGI.app"
+)
+
+# ---------- parse args ----------
+PATH_ARG=""
+DEBUG_FLAG=false
+DRY_RUN=false
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --Path) PATH_ARG="$2"; shift 2 ;;
+ --Debug) DEBUG_FLAG=true; shift ;;
+ --DryRun) DRY_RUN=true; shift ;;
+ --help) echo "Uso: $0 [--Path ] [--Debug] [--DryRun]"; exit 0 ;;
+ *) echo "Opção desconhecida: $1"; exit 1 ;;
+ esac
+done
+
+# ---------- detect SO ----------
+case "$(uname -s)" in
+ Linux*) OS="linux" ;;
+ Darwin*) OS="mac" ;;
+ MINGW*|CYGWIN*|MSYS*) OS="win" ;;
+ *) OS="unknown" ;;
+esac
+
+# ---------- extensões por SO ----------
+case "$OS" in
+ linux) EXT="AppImage" ;;
+ mac) EXT="app" ;;
+ win) EXT="exe" ;;
+ *) EXT="*" ;;
+esac
+
+# ---------- caminhos candidatos ----------
+if [[ -n "$PATH_ARG" ]]; then
+ if [[ -d "$PATH_ARG" ]]; then
+ CANDIDATES=($(find "$PATH_ARG" -maxdepth 1 -type f -iname "*.$EXT" | head -n 1))
+ else
+ CANDIDATES=("$PATH_ARG")
+ fi
+else
+ CANDIDATES=("${DEFAULT_PATHS[@]}")
+fi
+
+# ---------- funções ----------
+function find_build() {
+ for c in "${CANDIDATES[@]}"; do
+ [[ -f "$c" ]] && echo "$c" && return
+ done
+ return 1
+}
+
+function show_menu() {
+ echo "┌─────────────── AGI Universal Launcher v3 ───────────────┐"
+ echo "│ SO detectado: $OS │ Extensão esperada: *.$EXT │"
+ echo "├─────────────────────────────────────────────────────────┤"
+ echo "│ 1) Executar AGI │"
+ echo "│ 2) Executar com logs (--Debug) │"
+ echo "│ 3) Validar ambiente (--DryRun) │"
+ echo "│ 0) Sair │"
+ echo "└─────────────────────────────────────────────────────────┘"
+ read -p "Escolha: " opt
+ case $opt in
+ 1) return 0 ;;
+ 2) DEBUG_FLAG=true; return 0 ;;
+ 3) DRY_RUN=true; return 0 ;;
+ 0) exit 0 ;;
+ *) echo "Opção inválida"; exit 1 ;;
+ esac
+}
+
+# ---------- lógica ----------
+if [[ $# -eq 0 ]]; then
+ show_menu
+fi
+
+build=$(find_build)
+if [[ -z "$build" ]]; then
+ echo "❌ Build não encontrado para $OS (*.$EXT)"
+ echo "Caminhos verificados:"
+ printf ' → %s\n' "${CANDIDATES[@]}"
+ exit 1
+fi
+
+if $DRY_RUN; then
+ echo "✅ Build localizado: $build"
+ exit 0
+fi
+
+echo "🚀 Iniciando AGI..."
+case "$EXT" in
+ AppImage)
+ chmod +x "$build" 2>/dev/null
+ if $DEBUG_FLAG; then
+ x-terminal-emulator -e "$build" || gnome-terminal -- "$build" || "$build"
+ else
+ "$build" &
+ fi
+ ;;
+ app)
+ if $DEBUG_FLAG; then
+ open -a "$build"
+ else
+ open "$build"
+ fi
+ ;;
+ exe)
+ if $DEBUG_FLAG; then
+ powershell -NoExit -Command "\"$build\""
+ else
+ cmd /c start "" "$build"
+ fi
+ ;;
+ *)
+ echo "⚠️ Tipo de build desconhecido: $build"
+ exit 1
+ ;;
+esac
+
+echo "✅ Launcher finalizado. Log: $LOG_FILE"
diff --git a/config/sampler-config.yml b/config/sampler-config.yml
new file mode 100644
index 00000000..7de33334
--- /dev/null
+++ b/config/sampler-config.yml
@@ -0,0 +1,10 @@
+barcharts:
+ - title: Database Stats
+ rate-ms: 5000
+ items:
+ - label: Total Users
+ sample: uv run talos db-stats | grep "Total users" | awk '{print $3}'
+ - label: Permanent Users
+ sample: uv run talos db-stats | grep "Permanent users" | awk '{print $3}'
+ - label: Temporary Users
+ sample: uv run talos db-stats | grep "Temporary users" | awk '{print $3}'
\ No newline at end of file
diff --git a/deploy-docs.ps1 b/deploy-docs.ps1
new file mode 100644
index 00000000..f7ef073e
--- /dev/null
+++ b/deploy-docs.ps1
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+# --------------------------------------------------------------------------
+# Docsify Auto-Deploy – PowerShell & Bash – https://github.com/uniaolives/agi
+# Uso: bash deploy-docs-unified ou pwsh -File deploy-docs-unified.ps1
+# --------------------------------------------------------------------------
+set -euo pipefail
+############## BASH SECTION ###############################################
+if [ -n "${BASH_VERSION:-}" ]; then
+LOG_FILE="deploy-log-$(date +%F_%H-%M-%S).txt"
+echo "🚀 Iniciando deploy Docsify (Bash)" | tee -a "$LOG_FILE"
+
+# Detecta branch
+BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
+echo "✅ Branch detectada: $BRANCH" | tee -a "$LOG_FILE"
+
+# Stash / checkout / add
+git stash push -m "Pre-deploy stash" &>>"$LOG_FILE" || true
+git checkout "$BRANCH" &>>"$LOG_FILE"
+
+git add docs/
+if git diff --cached --quiet; then
+ echo "ℹ️ Sem mudanças para enviar." | tee -a "$LOG_FILE"
+ exit 0
+fi
+
+# Dry-run
+if [[ "${1:-}" == "--dry-run" ]]; then
+ echo "🔍 DryRun ativado — nenhuma alteração será enviada." | tee -a "$LOG_FILE"
+ git diff --cached | tee -a "$LOG_FILE"
+ exit 0
+fi
+
+# Commit + push
+git commit -m "docs: auto-deploy $(date '+%Y-%m-%d %H:%M:%S')" &>>"$LOG_FILE"
+git push origin "$BRANCH" &>>"$LOG_FILE"
+
+echo "✅ Deploy concluído! Logs em: $LOG_FILE"
+exit 0
+fi
+############## POWERSHELL SECTION #########################################
+if ($PSCommandPath) {
+$logFile = "deploy-log-$(Get-Date -Format 'yyyy-MM-dd_HH-mm-ss').txt"
+Write-Host "🚀 Iniciando deploy Docsify (PowerShell)" -ForegroundColor Cyan
+
+$branch = git rev-parse --abbrev-ref HEAD 2>$null
+if (-not $branch) { $branch = "main" }
+Write-Host "✅ Branch detectada: $branch" -ForegroundColor Green
+
+git stash push -m "Pre-deploy stash" | Out-File -Append $logFile
+git checkout $branch | Out-File -Append $logFile
+
+git add docs/
+if ((git diff --cached --quiet) -eq 0) {
+ Write-Host "ℹ️ Sem mudanças para enviar." -ForegroundColor Yellow
+ exit 0
+}
+
+if ($args[0] -eq "--dry-run") {
+ Write-Host "🔍 DryRun ativado — nenhuma alteração será enviada." -ForegroundColor Magenta
+ git diff --cached | Tee-Object -FilePath $logFile
+ exit 0
+}
+
+git commit -m "docs: auto-deploy $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" | Out-File -Append $logFile
+git push origin $branch | Out-File -Append $logFile
+
+Write-Host "✅ Deploy concluído! Logs em: $logFile" -ForegroundColor Green
+exit 0
+}
diff --git a/deploy-docs.sh b/deploy-docs.sh
new file mode 100644
index 00000000..f7ef073e
--- /dev/null
+++ b/deploy-docs.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+# --------------------------------------------------------------------------
+# Docsify Auto-Deploy – PowerShell & Bash – https://github.com/uniaolives/agi
+# Uso: bash deploy-docs-unified ou pwsh -File deploy-docs-unified.ps1
+# --------------------------------------------------------------------------
+set -euo pipefail
+############## BASH SECTION ###############################################
+if [ -n "${BASH_VERSION:-}" ]; then
+LOG_FILE="deploy-log-$(date +%F_%H-%M-%S).txt"
+echo "🚀 Iniciando deploy Docsify (Bash)" | tee -a "$LOG_FILE"
+
+# Detecta branch
+BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "main")
+echo "✅ Branch detectada: $BRANCH" | tee -a "$LOG_FILE"
+
+# Stash / checkout / add
+git stash push -m "Pre-deploy stash" &>>"$LOG_FILE" || true
+git checkout "$BRANCH" &>>"$LOG_FILE"
+
+git add docs/
+if git diff --cached --quiet; then
+ echo "ℹ️ Sem mudanças para enviar." | tee -a "$LOG_FILE"
+ exit 0
+fi
+
+# Dry-run
+if [[ "${1:-}" == "--dry-run" ]]; then
+ echo "🔍 DryRun ativado — nenhuma alteração será enviada." | tee -a "$LOG_FILE"
+ git diff --cached | tee -a "$LOG_FILE"
+ exit 0
+fi
+
+# Commit + push
+git commit -m "docs: auto-deploy $(date '+%Y-%m-%d %H:%M:%S')" &>>"$LOG_FILE"
+git push origin "$BRANCH" &>>"$LOG_FILE"
+
+echo "✅ Deploy concluído! Logs em: $LOG_FILE"
+exit 0
+fi
+############## POWERSHELL SECTION #########################################
+if ($PSCommandPath) {
+$logFile = "deploy-log-$(Get-Date -Format 'yyyy-MM-dd_HH-mm-ss').txt"
+Write-Host "🚀 Iniciando deploy Docsify (PowerShell)" -ForegroundColor Cyan
+
+$branch = git rev-parse --abbrev-ref HEAD 2>$null
+if (-not $branch) { $branch = "main" }
+Write-Host "✅ Branch detectada: $branch" -ForegroundColor Green
+
+git stash push -m "Pre-deploy stash" | Out-File -Append $logFile
+git checkout $branch | Out-File -Append $logFile
+
+git add docs/
+if ((git diff --cached --quiet) -eq 0) {
+ Write-Host "ℹ️ Sem mudanças para enviar." -ForegroundColor Yellow
+ exit 0
+}
+
+if ($args[0] -eq "--dry-run") {
+ Write-Host "🔍 DryRun ativado — nenhuma alteração será enviada." -ForegroundColor Magenta
+ git diff --cached | Tee-Object -FilePath $logFile
+ exit 0
+}
+
+git commit -m "docs: auto-deploy $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" | Out-File -Append $logFile
+git push origin $branch | Out-File -Append $logFile
+
+Write-Host "✅ Deploy concluído! Logs em: $logFile" -ForegroundColor Green
+exit 0
+}
diff --git a/src/talos/cli/main.py b/src/talos/cli/main.py
index fc023ce4..cff2d1e9 100644
--- a/src/talos/cli/main.py
+++ b/src/talos/cli/main.py
@@ -17,6 +17,7 @@
from talos.cli.github import github_app
from talos.cli.memory import memory_app
from talos.cli.migrations import app as migrations_app
+from talos.cli.monitoring import app as monitoring_app
from talos.cli.proposals import proposals_app
from talos.cli.twitter import twitter_app
from talos.core.main_agent import MainAgent
@@ -33,6 +34,7 @@
app.add_typer(arbiscan_app, name="arbiscan")
app.add_typer(contracts_app, name="contracts")
app.add_typer(migrations_app, name="migrations")
+app.add_typer(monitoring_app, name="monitoring")
@app.callback()
diff --git a/src/talos/cli/monitoring.py b/src/talos/cli/monitoring.py
new file mode 100644
index 00000000..5773ccb6
--- /dev/null
+++ b/src/talos/cli/monitoring.py
@@ -0,0 +1,40 @@
+from __future__ import annotations
+
+import subprocess
+from pathlib import Path
+
+import typer
+
+app = typer.Typer()
+
+
+@app.command()
+def start(
+ config: str = typer.Option(
+ "config/sampler-config.yml",
+ "--config",
+ "-c",
+ help="Path to the sampler config file.",
+ )
+):
+ """
+ Starts the monitoring service.
+ """
+ if not Path(config).exists():
+ print(f"Config file not found at {config}")
+ raise typer.Exit(1)
+
+ try:
+ subprocess.run(["sampler", "-c", config], check=True)
+ except FileNotFoundError:
+ print("Error: 'sampler' command not found.")
+ print("Please install Sampler and ensure it is in your PATH.")
+ print("See here for installation instructions: https://github.com/sqshq/sampler")
+ raise typer.Exit(1)
+ except subprocess.CalledProcessError as e:
+ print(f"Error running sampler: {e}")
+ raise typer.Exit(1)
+
+
+if __name__ == "__main__":
+ app()
\ No newline at end of file