diff --git a/clawd/.dockerignore b/clawd/.dockerignore new file mode 100644 index 0000000..c1250f7 --- /dev/null +++ b/clawd/.dockerignore @@ -0,0 +1 @@ +appdata/* \ No newline at end of file diff --git a/clawd/Dockerfile b/clawd/Dockerfile new file mode 100644 index 0000000..09470e0 --- /dev/null +++ b/clawd/Dockerfile @@ -0,0 +1,58 @@ +# Clawdbot AI Agent Gateway +FROM node:22-bookworm-slim + +LABEL org.opencontainers.image.description="Clawdbot - AI Agent Gateway for WhatsApp, Telegram, Discord, and iMessage" + +# Install runtime dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + git \ + python3 \ + python3-pip \ + ffmpeg \ + imagemagick \ + ghostscript \ + libxcb1 \ + libxkbcommon0 \ + dumb-init \ + tini \ + && rm -rf /var/lib/apt/lists/* + +# Create app user first +RUN useradd -m -u 1001 -s /bin/bash clawdbot + +# Set working directory +WORKDIR /home/clawdbot + +# Create necessary directories with proper permissions +RUN mkdir -p \ + /home/system/components/clawd/config \ + /home/system/components/clawd/data/.clawdbot \ + /home/system/components/clawd/data/clawd && \ + chown -R clawdbot:clawdbot /home/system/components/clawd /home/clawdbot + +# Install Clawdbot as root first (npm install works better) +RUN npm install -g clawdbot@latest + +# Copy scripts and config template +COPY --chown=clawdbot:clawdbot ./entrypoint.sh /app/entrypoint.sh +COPY --chown=clawdbot:clawdbot ./init-clawdbot.sh /app/init-clawdbot.sh +RUN chmod +x /app/entrypoint.sh /app/init-clawdbot.sh && chown clawdbot /app + +COPY --chown=clawdbot:clawdbot ./clawdbot.json.template /app/clawdbot.json.template + +# Switch to app user for runtime +USER clawdbot + +# Expose ports +EXPOSE 18789 18790 18793 80 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \ + CMD curl -f http://localhost:18789/health || exit 1 + +# Use tini to handle signals properly +ENTRYPOINT ["/usr/bin/tini", "--"] + +# Start the Clawdbot gateway +CMD ["/app/entrypoint.sh"] diff --git a/clawd/README.md b/clawd/README.md new file mode 100644 index 0000000..f3e5a73 --- /dev/null +++ b/clawd/README.md @@ -0,0 +1,192 @@ +# Clawdbot - AI Agent Gateway EdgeApp + +**Clawdbot** is an AI agent gateway that integrates WhatsApp, Telegram, Discord, and iMessage into a unified control plane. This EdgeApp runs Clawdbot as a centralized hub that local instances can connect to. + +## Overview + +- 🤖 **AI-Powered**: Integrates Claude (Anthropic) and other LLMs via Pi agent +- 📱 **Multi-Channel**: WhatsApp, Telegram, Discord, iMessage all in one place +- 🌐 **Distributed**: Central gateway with local client connections +- 🔒 **Secure**: Token-based auth, per-agent sandboxing +- 🎛️ **Configurable**: Dashboard UI for channel setup and credentials + +## Quick Start + +### Installation + +```bash +# Clone or sync the edgebox-iot/apps repo +cd ~/Repositories/edgebox-iot/apps + +# Build locally +make build apps="clawd" + +# Run locally +make run apps="clawd" +``` + +Access the dashboard at: **http://clawd.local** + +### Configuration + +The Clawdbot gateway is configurable via the Edgebox dashboard. Key settings: + +- **Telegram Bot Token**: Get from [@BotFather](https://t.me/BotFather) +- **Discord Bot Token**: Create at [Discord Developer Portal](https://discord.com/developers) +- **Gateway Token**: Optional security token for remote access +- **Primary Model**: Which LLM to use (default: Claude Opus 4.5) + +### Ports + +- **18789**: Gateway WebSocket (loopback by default, use token for remote) +- **18790**: Bridge for iOS/Android node pairing +- **18793**: Canvas host (WebView assets) +- **80**: Web UI (reverse-proxied via Traefik) + +## Architecture + +``` +┌─────────────────────────────────┐ +│ Edgebox System │ +│ ┌─────────────────────────┐ │ +│ │ Clawdbot Gateway │ │ +│ │ - WhatsApp/Telegram │ │ +│ │ - Discord/iMessage │ │ +│ │ - WebChat UI │ │ +│ │ - Auth Management │ │ +│ └─────────────────────────┘ │ +│ ↑ ↓ │ +│ ┌─────────────────────────┐ │ +│ │ Traefik Reverse Proxy │ │ +│ │ (clawd.local) │ │ +│ └─────────────────────────┘ │ +└─────────────────────────────────┘ + ↑ + LAN / Tailnet + ↓ +┌─────────────────────────────────┐ +│ Local Clawdbot (Mac/Linux) │ +│ Connects to central Gateway │ +└─────────────────────────────────┘ +``` + +## Local Client Configuration + +To connect a local Clawdbot instance to this central gateway: + +```json +{ + "gateway": { + "bind": "remote", + "host": "clawd.local", + "port": 18789, + "token": "${CLAWDBOT_GATEWAY_TOKEN}" + }, + "agents": { + "defaults": { + "workspace": "~/clawd-local" + } + } +} +``` + +## File Structure + +``` +clawd/ +├── Dockerfile # Node 22 + Clawdbot +├── entrypoint.sh # Init script +├── clawdbot.json.template # Default config +├── edgebox-compose.yml # Docker Compose config +├── edgebox.env # Metadata (EDGEAPP_NAME, etc.) +├── edgeapp.template.env # Config variables for dashboard +├── edgeapp-icon.png # App icon +├── edgebox-postinstall.sh # Post-install hook +└── src/ # Static assets (if any) +``` + +## Environment Variables + +| Variable | Type | Required | Description | +|----------|------|----------|-------------| +| `TELEGRAM_BOT_TOKEN` | string | false | Telegram Bot API token | +| `DISCORD_BOT_TOKEN` | string | false | Discord Bot token | +| `CLAWDBOT_GATEWAY_TOKEN` | string | false | Security token for remote access | +| `CLAWDBOT_PRIMARY_MODEL` | string | false | Primary LLM (default: claude-opus-4-5) | +| `ANTHROPIC_API_KEY` | string | false | Anthropic API key | +| `OPENAI_API_KEY` | string | false | OpenAI API key (fallback) | + +## Persistence + +- **Config**: `/home/system/components/clawd/config/clawdbot.json` +- **Workspace**: `/home/system/components/clawd/data/clawd` +- **State**: `/home/system/components/clawd/data/.clawdbot` + +Data persists across container restarts via Docker volumes. + +## Extending + +### Add a New Agent + +Edit `clawdbot.json`: + +```json +{ + "agents": { + "list": [ + { "id": "main", "workspace": "..." }, + { "id": "work", "workspace": "..." } + ] + }, + "bindings": [ + { "agentId": "work", "match": { "channel": "discord" } } + ] +} +``` + +### Multi-instance Setup + +Run multiple app instances with different ports: + +```bash +# Instance 1 +docker-compose -p clawd-1 up -d + +# Instance 2 +docker-compose -p clawd-2 up -d +``` + +## Troubleshooting + +### Health Check Fails + +```bash +# Check logs +docker logs edgebox-clawd-ws + +# Verify ports are open +lsof -i :18789 +``` + +### Can't Connect from Local Client + +- Ensure `CLAWDBOT_GATEWAY_TOKEN` is set in both gateway and client +- Check network connectivity: `ping clawd.local` +- Verify firewall allows port 18789 + +### Channel Credentials Not Loading + +- Set env variables in docker-compose or Edgebox dashboard +- Restart the container after changing credentials +- Check logs for auth errors + +## Resources + +- **Clawdbot Docs**: https://docs.clawd.bot +- **Clawdbot GitHub**: https://github.com/clawdbot/clawdbot +- **Edgebox Docs**: https://edgebox.io +- **Clawdbot Discord**: https://discord.com/invite/clawd + +## License + +MIT - Same as Clawdbot diff --git a/clawd/clawdbot.json.template b/clawd/clawdbot.json.template new file mode 100644 index 0000000..1ba1bcf --- /dev/null +++ b/clawd/clawdbot.json.template @@ -0,0 +1,30 @@ +{ + "gateway": { + "port": 18789, + "mode": "local", + "bind": "lan", + "auth": { + "token": "clawd-default-token" + } + }, + "agents": { + "defaults": { + "workspace": "/home/system/components/clawd/data/clawd", + "models": { + "anthropic/claude-opus-4-5": { "alias": "opus" }, + "anthropic/claude-sonnet-4-5": { "alias": "sonnet" } + }, + "model": { + "primary": "anthropic/claude-opus-4-5" + } + } + }, + "channels": { + "telegram": { + "enabled": false + }, + "discord": { + "enabled": false + } + } +} diff --git a/clawd/edgeapp.template.env b/clawd/edgeapp.template.env new file mode 100644 index 0000000..6de9d0a --- /dev/null +++ b/clawd/edgeapp.template.env @@ -0,0 +1,21 @@ +# Clawdbot Configuration Template +# Format: VARIABLE_NAME=type|required|description +# Types: bool, string, number, array +# Required: true/false + +# Channel Credentials +TELEGRAM_BOT_TOKEN=string|false|Telegram Bot API token from @BotFather +DISCORD_BOT_TOKEN=string|false|Discord Bot token from Developer Portal +WHATSAPP_ENABLED=bool|false|Enable WhatsApp channel + +# Gateway Access +CLAWDBOT_GATEWAY_TOKEN=string|false|Security token for remote gateway access (required for non-loopback) + +# Model/Agent Configuration +CLAWDBOT_PRIMARY_MODEL=string|false|Primary LLM model (default: anthropic/claude-opus-4-5) +ANTHROPIC_API_KEY=string|false|Anthropic API key for Claude +OPENAI_API_KEY=string|false|OpenAI API key (fallback) + +# Optional: Advanced Configuration +CLAWDBOT_THINKING_DEFAULT=string|false|Default thinking level (off/low/high) +CLAWDBOT_TIMEOUT_SECONDS=number|false|Agent timeout in seconds (default: 600) diff --git a/clawd/edgebox-compose.yml b/clawd/edgebox-compose.yml new file mode 100644 index 0000000..9d11ed9 --- /dev/null +++ b/clawd/edgebox-compose.yml @@ -0,0 +1,71 @@ +services: + ############## + # Clawdbot AI Agent Gateway + ############## + clawd-ws: + image: ghcr.io/edgebox-iot/apps/${COMPOSE_APP_SLUG-clawd}:1.0.0 + build: + context: "./" + container_name: '${COMPOSE_PROJECT_NAME-edgebox}-${COMPOSE_APP_SLUG-clawd}-ws' + restart: unless-stopped + environment: + # Traefik reverse proxy variables + VIRTUAL_HOST: ${LOCAL_URL-clawd.local}${INTERNET_URL-} + VIRTUAL_PORT: 80 + + # Clawdbot configuration paths + CLAWDBOT_WORKSPACE: ${CLAWDBOT_WORKSPACE-/home/system/components/clawd/data/clawd} + CLAWDBOT_STATE_DIR: ${CLAWDBOT_STATE_DIR-/home/system/components/clawd/data/.clawdbot} + CLAWDBOT_CONFIG_PATH: ${CLAWDBOT_CONFIG_PATH-/home/system/components/clawd/config/clawdbot.json} + + # Gateway token for remote access + CLAWDBOT_GATEWAY_TOKEN: ${CLAWDBOT_GATEWAY_TOKEN} + + # Channel credentials + TELEGRAM_BOT_TOKEN: ${TELEGRAM_BOT_TOKEN} + DISCORD_BOT_TOKEN: ${DISCORD_BOT_TOKEN} + + # Node environment + NODE_ENV: production + NODE_OPTIONS: --max-old-space-size=1024 + + volumes: + # System time (read-only) + - /etc/localtime:/etc/localtime:ro + # Config directory (persistent) + - ./appdata/${COMPOSE_APP_SLUG-clawd}-config:/home/system/components/clawd/config:rw + # Data directory (persistent state, auth profiles, workspace) + - ./appdata/${COMPOSE_APP_SLUG-clawd}-data:/home/system/components/clawd/data:rw + + # Expose all necessary ports + ports: + # Gateway WebSocket + - "18789:18789" + # Bridge for node pairing (LAN/Tailnet) + - "18790:18790" + # Canvas host (WebView assets) + - "18793:18793" + + # Network settings (traefik optional for dev) + networks: + default: null + + # Health check + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:18789/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + + # Logging + logging: + driver: "json-file" + options: + max-size: "50m" + max-file: "5" + +networks: + default: + driver: bridge + diff --git a/clawd/edgebox-hosts.txt b/clawd/edgebox-hosts.txt new file mode 100644 index 0000000..1879a66 --- /dev/null +++ b/clawd/edgebox-hosts.txt @@ -0,0 +1,2 @@ +clawd + diff --git a/clawd/edgebox-icon.png b/clawd/edgebox-icon.png new file mode 100644 index 0000000..e07ed52 Binary files /dev/null and b/clawd/edgebox-icon.png differ diff --git a/clawd/edgebox.env b/clawd/edgebox.env new file mode 100644 index 0000000..588c37d --- /dev/null +++ b/clawd/edgebox.env @@ -0,0 +1,14 @@ +############################################ +# Edgebox WS and API environment variables +############################################ + +# Metadata values - Used by edgebox api service for UI and update control purposes +EDGEAPP_NAME=Clawdbot +EDGEAPP_DESCRIPTION=AI Agent Gateway (WhatsApp/Telegram/Discord/iMessage) +EDGEAPP_VERSION=1.0.0 + +# Compose values - Used by edgebox ws service for containers setup +COMPOSE_PROJECT_NAME=edgebox +COMPOSE_APP_SLUG=clawd + + diff --git a/clawd/entrypoint.sh b/clawd/entrypoint.sh new file mode 100644 index 0000000..ee74541 --- /dev/null +++ b/clawd/entrypoint.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# Clawdbot Edgebox App Entrypoint + +set -e + +echo "[Clawdbot] Initializing Edgebox app..." + +# Create necessary directories +mkdir -p \ + /home/system/components/clawd/config \ + /home/system/components/clawd/data/.clawdbot \ + /home/system/components/clawd/data/clawd + +# Create default config if not present +if [ ! -f /home/system/components/clawd/config/clawdbot.json ]; then + echo "[Clawdbot] Creating default configuration from template..." + cp /app/clawdbot.json.template /home/system/components/clawd/config/clawdbot.json +else + echo "[Clawdbot] Using existing configuration" +fi + +# Initialize agent with env var defaults (idempotent) +/app/init-clawdbot.sh + +# Ensure auth-profiles directory +mkdir -p /home/system/components/clawd/data/.clawdbot/agents/main/agent + +echo "[Clawdbot] Configuration ready at: /home/system/components/clawd/config/clawdbot.json" +echo "[Clawdbot] Workspace at: /home/system/components/clawd/data/clawd" +echo "[Clawdbot] Starting Gateway on 0.0.0.0:18789..." +echo "[Clawdbot] Bridge on 0.0.0.0:18790" +echo "[Clawdbot] Canvas host on 0.0.0.0:18793" +echo "" + +# Start Clawdbot gateway +# Gateway configuration is in clawdbot.json +exec clawdbot gateway --port 18789 diff --git a/clawd/init-clawdbot.sh b/clawd/init-clawdbot.sh new file mode 100644 index 0000000..ad4faa1 --- /dev/null +++ b/clawd/init-clawdbot.sh @@ -0,0 +1,45 @@ +#!/bin/sh +# Clawdbot Edgebox App - Zero-config Initialization +# Configures Clawdbot with environment variables on first startup + +set -e + +WORKSPACE="${CLAWDBOT_WORKSPACE:-/home/system/components/clawd/data/clawd}" +STATE_DIR="${CLAWDBOT_STATE_DIR:-/home/system/components/clawd/data/.clawdbot}" +MAIN_AGENT_DIR="$STATE_DIR/agents/main/agent" + +# Create directories +mkdir -p "$MAIN_AGENT_DIR" + +# Check if agent is already initialized +if [ -f "$MAIN_AGENT_DIR/identity.json" ]; then + echo "[Clawdbot] Agent already initialized, skipping onboarding" + exit 0 +fi + +echo "[Clawdbot] Initializing default agent with environment configuration..." + +# Create identity.json with defaults from env vars or sensible defaults +cat > "$MAIN_AGENT_DIR/identity.json" << EOF +{ + "id": "main", + "name": "${CLAWDBOT_AGENT_NAME:-Clawd}", + "model": "${CLAWDBOT_AGENT_MODEL:-anthropic/claude-opus-4-5}", + "type": "agent" +} +EOF + +echo "[Clawdbot] Agent identity created:" +cat "$MAIN_AGENT_DIR/identity.json" + +# Create a minimal settings file if it doesn't exist +if [ ! -f "$MAIN_AGENT_DIR/settings.json" ]; then + cat > "$MAIN_AGENT_DIR/settings.json" << EOF +{ + "workspace": "$WORKSPACE", + "capabilities": {} +} +EOF +fi + +echo "[Clawdbot] Agent initialization complete!"