diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index eed24ea..47efc97 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -111,9 +111,24 @@ jobs: > ``` > Then open the app normally. This only needs to be done once. + ### CLI Binary (Terminal Only) + | Platform | Download | Size | + |----------|----------|------| + | **Linux** (x64) | [`cachi-linux-x64.tar.gz`](https://github.com/${{ github.repository }}/releases/download/v${{ steps.bump_version.outputs.new_version }}/cachi-linux-x64.tar.gz) | — | + | **macOS** (Apple Silicon) | [`cachi-mac-arm64.tar.gz`](https://github.com/${{ github.repository }}/releases/download/v${{ steps.bump_version.outputs.new_version }}/cachi-mac-arm64.tar.gz) | — | + | **Windows** (x64) | [`cachi-win-x64.zip`](https://github.com/${{ github.repository }}/releases/download/v${{ steps.bump_version.outputs.new_version }}/cachi-win-x64.zip) | — | + + ### Mini Server (Dashboard — no Python required) + | Platform | Download | Size | + |----------|----------|------| + | **Linux** (x64) | [`cachibot-server-mini-linux-x64.tar.gz`](https://github.com/${{ github.repository }}/releases/download/v${{ steps.bump_version.outputs.new_version }}/cachibot-server-mini-linux-x64.tar.gz) | — | + + > Lightweight server with web dashboard, database, and auth. No knowledge base or platform integrations. Ideal for Raspberry Pi, VPS, and edge deployments. + ### Python Package (pip) ```bash - pip install cachibot==${{ steps.bump_version.outputs.new_version }} + pip install cachibot==${{ steps.bump_version.outputs.new_version }} # CLI only + pip install cachibot[full]==${{ steps.bump_version.outputs.new_version }} # CLI + server + all extras ``` --- @@ -222,7 +237,7 @@ jobs: shell: bash run: | echo "${{ needs.release.outputs.new_version }}" > VERSION - pip install -e . + pip install -e ".[full]" pip install pyinstaller - name: Clean __pycache__ @@ -275,6 +290,157 @@ jobs: name: ${{ matrix.artifact }} path: dist/cachibot-server/ + # ========================================================================= + # 2b. Build CLI-only binary with PyInstaller (3 platforms) + # ========================================================================= + build-cli: + needs: release + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-latest + artifact: cachi-linux-x64 + archive_name: cachi-linux-x64.tar.gz + archive_cmd: tar -czf + - os: macos-latest + artifact: cachi-mac-arm64 + archive_name: cachi-mac-arm64.tar.gz + archive_cmd: tar -czf + - os: windows-latest + artifact: cachi-win-x64 + archive_name: cachi-win-x64.zip + archive_cmd: zip -r + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + with: + ref: v${{ needs.release.outputs.new_version }} + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: pip + + - name: Install CachiBot (core only) + PyInstaller + shell: bash + run: | + echo "${{ needs.release.outputs.new_version }}" > VERSION + pip install -e . + pip install pyinstaller + + - name: Clean __pycache__ + shell: bash + run: find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true + + - name: Build CLI binary + run: pyinstaller cachibot-cli.spec --clean + + - name: Smoke test CLI binary + shell: bash + run: | + BINARY="./dist/cachi/cachi" + if [[ "$RUNNER_OS" == "Windows" ]]; then + BINARY="./dist/cachi/cachi.exe" + fi + "$BINARY" --help + echo "CLI smoke test passed" + + - name: Archive CLI binary + shell: bash + run: | + cd dist + if [[ "${{ matrix.archive_name }}" == *.zip ]]; then + ${{ matrix.archive_cmd }} "${{ matrix.archive_name }}" cachi/ + else + ${{ matrix.archive_cmd }} "${{ matrix.archive_name }}" cachi/ + fi + + - name: Upload CLI archive to GitHub Release + shell: bash + run: | + gh release upload "v${{ needs.release.outputs.new_version }}" \ + "dist/${{ matrix.archive_name }}" \ + --clobber + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # ========================================================================= + # 2c. Build mini server binary (Linux only — for Pi / VPS / edge) + # ========================================================================= + build-server-mini: + needs: release + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + ref: v${{ needs.release.outputs.new_version }} + + - name: Download frontend artifact + uses: actions/download-artifact@v4 + with: + name: frontend-dist + path: frontend/dist + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: pip + + - name: Install CachiBot (server extras) + PyInstaller + run: | + echo "${{ needs.release.outputs.new_version }}" > VERSION + pip install -e ".[server]" + pip install pyinstaller + + - name: Clean __pycache__ + run: find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true + + - name: Build mini server binary + run: pyinstaller cachibot-server-mini.spec --clean + + - name: Smoke test mini server binary + timeout-minutes: 2 + run: | + PORT=15870 + ./dist/cachibot-server-mini/cachibot-server-mini --port $PORT --host 127.0.0.1 & + SERVER_PID=$! + + for i in $(seq 1 60); do + if curl -sf "http://127.0.0.1:$PORT/api/health" > /dev/null 2>&1; then + echo "Server healthy after ${i}s" + break + fi + if ! kill -0 $SERVER_PID 2>/dev/null; then + echo "ERROR: Server exited prematurely" + exit 1 + fi + sleep 1 + done + + HEALTH=$(curl -sf "http://127.0.0.1:$PORT/api/health") + echo "Health: $HEALTH" + + kill $SERVER_PID 2>/dev/null || true + wait $SERVER_PID 2>/dev/null || true + echo "Mini server smoke test passed" + + - name: Archive mini server binary + run: | + cd dist + tar -czf cachibot-server-mini-linux-x64.tar.gz cachibot-server-mini/ + + - name: Upload to GitHub Release + run: | + gh release upload "v${{ needs.release.outputs.new_version }}" \ + "dist/cachibot-server-mini-linux-x64.tar.gz" \ + --clobber + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # ========================================================================= # 3. Build Electron desktop app (3 platforms) # ========================================================================= @@ -355,8 +521,8 @@ jobs: files-folder: ${{ github.workspace }}/release files-folder-filter: exe - # Re-upload signed Windows exe to GitHub Release - - name: Upload signed exe to release + # Re-upload signed Windows exe and regenerate latest.yml + - name: Upload signed exe and update latest.yml if: matrix.platform == 'win' shell: bash run: | @@ -365,6 +531,12 @@ jobs: EXE_PATH="${{ github.workspace }}/release/${EXE_NAME}" if [[ -f "$EXE_PATH" ]]; then gh release upload "v${VERSION}" "$EXE_PATH" --clobber + SHA512=$(openssl dgst -sha512 -binary "$EXE_PATH" | openssl base64 -A) + SIZE=$(wc -c < "$EXE_PATH" | tr -d ' ') + RELEASE_DATE=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z") + printf 'version: %s\nfiles:\n - url: %s\n sha512: %s\n size: %s\npath: %s\nsha512: %s\nreleaseDate: '\''%s'\''\n' \ + "$VERSION" "$EXE_NAME" "$SHA512" "$SIZE" "$EXE_NAME" "$SHA512" "$RELEASE_DATE" > latest.yml + gh release upload "v${VERSION}" latest.yml --clobber fi env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -422,7 +594,7 @@ jobs: # 5. Update release body with actual asset sizes # ========================================================================= update-release: - needs: [release, build-desktop, build-mobile] + needs: [release, build-cli, build-server-mini, build-desktop, build-mobile] runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index fc45172..98da7f0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@
The Armored AI Agent
-Visual. Transparent. Secure.
+Lightweight. Modular. Armored.
Website · @@ -49,9 +49,43 @@ ## Why CachiBot? -Most AI platforms force you to choose: chatbot UIs with no automation, workflow builders with no conversational AI, or developer frameworks that take weeks to ship. +### Lean by Default -**CachiBot gives you all three.** Build specialized bots, deploy them to any messaging platform, run them in collaborative rooms, and automate workflows — all from a visual dashboard with full transparency into what your agents are doing. +Most AI agent frameworks install the kitchen sink. CachiBot doesn't. + +``` +pip install cachibot +``` + +That gives you a fully functional AI agent with tool use, sandboxed code execution, file operations, and 14+ LLM providers. The full install tree is **~36 packages** — mostly small, pure-Python libraries. No FastAPI. No SQLAlchemy. No torch. No numpy. No 200MB embedding models downloading on first run. + +Pick exactly what you need — mix and match: + +```bash +pip install cachibot # just the agent +pip install cachibot[server] # + web dashboard +pip install cachibot[server,telegram] # + dashboard + Telegram +pip install cachibot[server,knowledge] # + dashboard + RAG +pip install cachibot[server,discord,slack] # + dashboard + Discord + Slack +pip install cachibot[full] # everything +``` + +| Extra | What It Adds | +|-------|-------------| +| `server` | Web dashboard, database, auth, WebSocket streaming | +| `knowledge` | RAG pipeline — PDF/DOCX ingestion, vector search, embeddings | +| `telegram` | Telegram bot adapter | +| `discord` | Discord bot adapter | +| `slack` | Slack bot adapter | +| `teams` | Microsoft Teams bot adapter | +| `platforms` | All platform adapters | +| `full` | All of the above | + +Or skip Python entirely — grab the `cachi` standalone binary from [Releases](https://github.com/jhd3197/CachiBot/releases). One file. No runtime. + +### Full Platform When You Need It + +CachiBot scales from a terminal command to a multi-agent platform. Build specialized bots, deploy them to any messaging platform, run them in collaborative rooms, and automate workflows — all from a visual dashboard with full transparency into what your agents are doing.  @@ -87,16 +121,20 @@ irm cachibot.ai/install.ps1 | iex ### pip ```bash -pip install cachibot +pip install cachibot # agent only — see "Lean by Default" above for all extras +cachibot server # start the dashboard (requires cachibot[server]) ``` -Then start the server: +### Standalone Binaries -```bash -cachibot server -``` +Pre-built binaries on every release — no Python required: + +| Binary | What It Is | Platforms | +|--------|-----------|-----------| +| `cachi` | Terminal agent (CLI only) | Linux x64, macOS ARM64, Windows x64 | +| `cachibot-server-mini` | Web dashboard + database + auth | Linux x64 | -Open **http://localhost:5870** — the frontend is bundled and served automatically. No separate build step. +The mini server is the full web UI without knowledge base or platform integrations — runs on a Raspberry Pi, a $5/mo VPS, anywhere. Grab them from [GitHub Releases](https://github.com/jhd3197/CachiBot/releases). ### Docker @@ -123,17 +161,24 @@ export MOONSHOT_API_KEY="your-key" # Kimi ### CLI Usage +Works with both `cachibot` and the short alias `cachi`: + +```bash +cachi "summarize this project" # Run a single task +cachi # Interactive mode +cachi --model claude/sonnet # Override model +cachi --workspace ./my-project # Set workspace +cachi --approve # Require approval for each action +cachi --verbose # Show thinking process +``` + +With `cachibot[server]` installed: + ```bash -cachibot server # Start the dashboard -cachibot "summarize this project" # Run a single task -cachibot # Interactive mode -cachibot --model claude/sonnet # Override model -cachibot --workspace ./my-project # Set workspace -cachibot --approve # Require approval for each action -cachibot --verbose # Show thinking process -cachibot diagnose # Check installation health -cachibot repair # Fix corrupted installation -cachi server # Short alias +cachi server # Start the web dashboard +cachi db migrate # Run database migrations +cachi diagnose # Check installation health +cachi repair # Fix corrupted installation ``` ## Features @@ -301,7 +346,7 @@ cd CachiBot # Backend python -m venv venv && source venv/bin/activate # or .\venv\Scripts\activate on Windows -pip install -e ".[dev]" +pip install -e ".[full,dev]" # Frontend cd frontend && npm install && cd .. diff --git a/cachibot/cli.py b/cachibot/cli.py index fde3be3..99ed567 100644 --- a/cachibot/cli.py +++ b/cachibot/cli.py @@ -21,7 +21,6 @@ from cachibot import __version__ from cachibot.agent import CachibotAgent from cachibot.config import Config -from cachibot.db_commands import db_app, setup_db_app # Custom theme for Cachibot CACHIBOT_THEME = Theme( @@ -45,9 +44,14 @@ no_args_is_help=False, ) -# Database management sub-commands -app.add_typer(db_app, name="db", help="Database management commands") -app.add_typer(setup_db_app, name="setup-db", help="Database setup wizards") +# Database management sub-commands (requires server extras) +try: + from cachibot.db_commands import db_app, setup_db_app + + app.add_typer(db_app, name="db", help="Database management commands") + app.add_typer(setup_db_app, name="setup-db", help="Database setup wizards") +except ImportError: + pass # Telemetry sub-commands telemetry_app = typer.Typer(name="telemetry", help="Anonymous telemetry management") @@ -352,7 +356,11 @@ def server( reload: bool = typer.Option(False, "--reload", "-r", help="Enable auto-reload (dev mode)"), ) -> None: """Start the Cachibot API server.""" - from cachibot.api.server import run_server as start_api_server + try: + from cachibot.api.server import run_server as start_api_server + except ImportError: + console.print("[error]Server deps not installed. Run: pip install cachibot\\[server][/]") + raise typer.Exit(1) console.print(f"[info]Starting Cachibot server on http://{host}:{port}[/]") start_api_server(host=host, port=port, workspace=workspace, reload=reload) @@ -375,9 +383,15 @@ def reset_password( import hashlib async def _reset() -> None: - from cachibot.services.auth_service import get_auth_service - from cachibot.storage import db - from cachibot.storage.user_repository import UserRepository + try: + from cachibot.services.auth_service import get_auth_service + from cachibot.storage import db + from cachibot.storage.user_repository import UserRepository + except ImportError: + console.print( + "[error]Server deps not installed. Run: pip install cachibot\\[server][/]" + ) + raise typer.Exit(1) await db.init_db() repo = UserRepository() @@ -423,7 +437,11 @@ def repair() -> None: Detects tilde-prefixed corrupted packages left by interrupted pip installs, removes them, force-reinstalls the current version, and verifies the result. """ - from cachibot.services.update_service import repair_installation + try: + from cachibot.services.update_service import repair_installation + except ImportError: + console.print("[error]Server deps not installed. Run: pip install cachibot\\[server][/]") + raise typer.Exit(1) console.print("[info]Running installation repair...[/]\n") ok, detail = asyncio.run(repair_installation()) @@ -448,12 +466,16 @@ def repair() -> None: @app.command("diagnose") def diagnose() -> None: """Run installation diagnostics and show environment info.""" - from cachibot.services.update_service import ( - _is_venv, - _python_info, - detect_corruption, - verify_installation, - ) + try: + from cachibot.services.update_service import ( + _is_venv, + _python_info, + detect_corruption, + verify_installation, + ) + except ImportError: + console.print("[error]Server deps not installed. Run: pip install cachibot\\[server][/]") + raise typer.Exit(1) console.print("[info]CachiBot Installation Diagnostics[/]\n") diff --git a/cachibot/services/document_processor.py b/cachibot/services/document_processor.py index 83f1ad6..fdd870c 100644 --- a/cachibot/services/document_processor.py +++ b/cachibot/services/document_processor.py @@ -9,8 +9,6 @@ import uuid from pathlib import Path -import pymupdf - from cachibot.models.knowledge import DocChunk, DocumentStatus from cachibot.services.vector_store import VectorStore, get_vector_store from cachibot.storage.repository import KnowledgeRepository @@ -101,6 +99,8 @@ def extract_text(self, file_path: Path, file_type: str) -> str: def _extract_pdf(self, file_path: Path) -> str: """Extract text from PDF using PyMuPDF.""" + import pymupdf + doc = pymupdf.open(file_path) try: # Join pages with form feed character (standard page separator) diff --git a/desktop/pyinstaller-cli.py b/desktop/pyinstaller-cli.py new file mode 100644 index 0000000..b91f456 --- /dev/null +++ b/desktop/pyinstaller-cli.py @@ -0,0 +1,15 @@ +""" +Standalone entry point for PyInstaller-bundled CachiBot CLI. + +Lean terminal-only binary — no server, database, or platform dependencies. +""" + + +def main(): + from cachibot.cli import app + + app() + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index cb0e737..fd11a1b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -39,7 +39,11 @@ dependencies = [ "tukuy>=0.0.30", "typer>=0.12.0", "rich>=13.0.0", - # API server + "pydantic>=2.9.0", +] + +[project.optional-dependencies] +server = [ "fastapi>=0.115.0", "uvicorn[standard]>=0.32.0", "sqlalchemy[asyncio]>=2.0.0", @@ -49,33 +53,38 @@ dependencies = [ "pgvector>=0.3.0", "pydantic[email]>=2.9.0", "websockets>=14.0", - # Knowledge base (Phase 2) - "fastembed>=0.4.0", - "pymupdf>=1.26.0", - "python-docx>=1.1.0", "aiofiles>=24.1.0", "python-multipart>=0.0.9", - # Scheduling "croniter>=2.0.0", - # Platform integrations - "aiogram>=3.0.0", - "discord.py>=2.0.0", + "bcrypt>=4.0.0", + "PyJWT>=2.8.0", + "cryptography>=42.0.0", +] +knowledge = [ + "fastembed>=0.4.0", + "pymupdf>=1.26.0", + "python-docx>=1.1.0", +] +# Individual platform extras +telegram = ["aiogram>=3.0.0"] +discord = ["discord.py>=2.0.0"] +slack = [ "slack-bolt>=1.18.0", "slack-sdk>=3.27.0", +] +teams = [ "botbuilder-core>=4.14.0", "botbuilder-integration-aiohttp>=4.14.0", "aiohttp>=3.9.0", - # Authentication - "bcrypt>=4.0.0", - "PyJWT>=2.8.0", - # Encryption - "cryptography>=42.0.0", ] - -[project.optional-dependencies] +# Convenience bundles +platforms = ["cachibot[telegram,discord,slack,teams]"] +full = ["cachibot[server,knowledge,platforms]"] dev = [ + "cachibot[full]", "pytest>=8.0.0", "pytest-asyncio>=0.23.0", + "httpx>=0.27.0", "ruff>=0.5.0", "mypy>=1.10.0", "bandit>=1.7.0",