diff --git a/.gitignore b/.gitignore index fbeaa6d..bc0c047 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ __pycache__ .serena .claude/settings.local.json PRPs/local +/logs/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d334cc3..a24ae9c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,8 +53,10 @@ Archon uses true microservices architecture with clear separation of concerns: ### Prerequisites - [Docker Desktop](https://www.docker.com/products/docker-desktop/) +- [Node.js 18+](https://nodejs.org/) (for hybrid development mode) - [Supabase](https://supabase.com/) account (free tier works) - [OpenAI API key](https://platform.openai.com/api-keys) or alternative LLM provider +- (Optional) [Make](https://www.gnu.org/software/make/) for simplified workflows - Basic knowledge of Python (FastAPI) and TypeScript (React) ### Initial Setup @@ -74,7 +76,11 @@ After forking the repository, you'll need to: 3. **Start Development Environment** ```bash - docker-compose up --build -d + # Using Docker Compose directly + docker compose --profile full up --build -d + + # Or using Make (if installed) + make dev-docker ``` 4. **Configure API Keys** @@ -211,14 +217,17 @@ Test these things using both the UI and the MCP server. This process will be sim **Test commands:** ```bash - # Backend tests - cd python && python -m pytest - - # Frontend tests - cd archon-ui-main && npm run test + # Using Make (if installed) + make test # Run all tests + make test-fe # Frontend tests only + make test-be # Backend tests only + + # Or manually + cd python && python -m pytest # Backend tests + cd archon-ui-main && npm run test # Frontend tests # Full integration test - docker-compose up --build -d + docker compose --profile full up --build -d # Test via UI at http://localhost:3737 ``` @@ -324,7 +333,10 @@ Test these things using both the UI and the MCP server. This process will be sim 2. **Testing Your Changes** ```bash - # Run Python tests + # Using Make (if installed) + make test-be + + # Or manually cd python && python -m pytest tests/ # Run specific test categories @@ -334,8 +346,8 @@ Test these things using both the UI and the MCP server. This process will be sim 3. **Code Quality** ```bash - # We encourage you to use linters for all code # Follow service patterns from existing code + # Maintain consistency with the codebase ``` ### Frontend Development (React) @@ -353,7 +365,10 @@ Test these things using both the UI and the MCP server. This process will be sim 2. **Testing Your Changes** ```bash - # Run frontend tests + # Using Make (if installed) + make test-fe + + # Or manually cd archon-ui-main && npm run test # Run with coverage @@ -365,7 +380,10 @@ Test these things using both the UI and the MCP server. This process will be sim 3. **Development Server** ```bash - # For faster iteration, run frontend locally + # Using Make for hybrid mode (if installed) + make dev # Backend in Docker, frontend local + + # Or manually for faster iteration cd archon-ui-main && npm run dev # Still connects to Docker backend services ``` diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ff5ff99 --- /dev/null +++ b/Makefile @@ -0,0 +1,109 @@ +# Archon Makefile - Simple, Secure, Cross-Platform +SHELL := /bin/bash +.SHELLFLAGS := -ec + +# Docker compose command - prefer newer 'docker compose' plugin over standalone 'docker-compose' +COMPOSE ?= $(shell docker compose version >/dev/null 2>&1 && echo "docker compose" || echo "docker-compose") + +.PHONY: help dev dev-docker stop test test-fe test-be lint lint-fe lint-be clean install check + +help: + @echo "Archon Development Commands" + @echo "===========================" + @echo " make dev - Backend in Docker, frontend local (recommended)" + @echo " make dev-docker - Everything in Docker" + @echo " make stop - Stop all services" + @echo " make test - Run all tests" + @echo " make test-fe - Run frontend tests only" + @echo " make test-be - Run backend tests only" + @echo " make lint - Run all linters" + @echo " make lint-fe - Run frontend linter only" + @echo " make lint-be - Run backend linter only" + @echo " make clean - Remove containers and volumes" + @echo " make install - Install dependencies" + @echo " make check - Check environment setup" + +# Install dependencies +install: + @echo "Installing dependencies..." + @cd archon-ui-main && npm install + @cd python && uv sync + @echo "✓ Dependencies installed" + +# Check environment +check: + @echo "Checking environment..." + @node -v >/dev/null 2>&1 || { echo "✗ Node.js not found (require Node 18+)."; exit 1; } + @node check-env.js + @echo "Checking Docker..." + @docker --version > /dev/null 2>&1 || { echo "✗ Docker not found"; exit 1; } + @$(COMPOSE) version > /dev/null 2>&1 || { echo "✗ Docker Compose not found"; exit 1; } + @echo "✓ Environment OK" + + +# Hybrid development (recommended) +dev: check + @echo "Starting hybrid development..." + @echo "Backend: Docker | Frontend: Local with hot reload" + @$(COMPOSE) --profile backend up -d --build + @set -a; [ -f .env ] && . ./.env; set +a; \ + echo "Backend running at http://$${HOST:-localhost}:$${ARCHON_SERVER_PORT:-8181}" + @echo "Starting frontend..." + @cd archon-ui-main && \ + VITE_ARCHON_SERVER_PORT=$${ARCHON_SERVER_PORT:-8181} \ + VITE_ARCHON_SERVER_HOST=$${HOST:-} \ + npm run dev + +# Full Docker development +dev-docker: check + @echo "Starting full Docker environment..." + @$(COMPOSE) --profile full up -d --build + @echo "✓ All services running" + @echo "Frontend: http://localhost:3737" + @echo "API: http://localhost:8181" + +# Stop all services +stop: + @echo "Stopping all services..." + @$(COMPOSE) --profile backend --profile frontend --profile full down + @echo "✓ Services stopped" + +# Run all tests +test: test-fe test-be + +# Run frontend tests +test-fe: + @echo "Running frontend tests..." + @cd archon-ui-main && npm test + +# Run backend tests +test-be: + @echo "Running backend tests..." + @cd python && uv run pytest + +# Run all linters +lint: lint-fe lint-be + +# Run frontend linter +lint-fe: + @echo "Linting frontend..." + @cd archon-ui-main && npm run lint + +# Run backend linter +lint-be: + @echo "Linting backend..." + @cd python && uv run ruff check --fix + +# Clean everything (with confirmation) +clean: + @echo "⚠️ This will remove all containers and volumes" + @read -p "Are you sure? (y/N) " -n 1 -r; \ + echo; \ + if [[ $$REPLY =~ ^[Yy]$$ ]]; then \ + $(COMPOSE) down -v --remove-orphans; \ + echo "✓ Cleaned"; \ + else \ + echo "Cancelled"; \ + fi + +.DEFAULT_GOAL := help diff --git a/README.md b/README.md index 6f9efa9..a641f0e 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,10 @@ This new vision for Archon replaces the old one (the agenteer). Archon used to b ### Prerequisites - [Docker Desktop](https://www.docker.com/products/docker-desktop/) +- [Node.js 18+](https://nodejs.org/) (for hybrid development mode) - [Supabase](https://supabase.com/) account (free tier or local Supabase both work) - [OpenAI API key](https://platform.openai.com/api-keys) (Gemini and Ollama are supported too!) +- (OPTIONAL) [Make](https://www.gnu.org/software/make/) (see [Installing Make](#installing-make) below) ### Setup Instructions @@ -70,13 +72,17 @@ This new vision for Archon replaces the old one (the agenteer). Archon used to b 3. **Database Setup**: In your [Supabase project](https://supabase.com/dashboard) SQL Editor, copy, paste, and execute the contents of `migration/complete_setup.sql` -4. **Start Services**: +4. **Start Services** (choose one): + + **Full Docker Mode (Recommended for Normal Archon Usage)** ```bash - docker-compose up --build -d + docker compose --profile full up --build -d + # or + make dev-docker # (Alternative: Requires make installed ) ``` - This starts the core microservices: + This starts all core microservices in Docker: - **Server**: Core API and business logic (Port: 8181) - **MCP Server**: Protocol interface for AI clients (Port: 8051) - **Agents (coming soon!)**: AI operations and streaming (Port: 8052) @@ -89,6 +95,19 @@ This new vision for Archon replaces the old one (the agenteer). Archon used to b - Go to **Settings** → Select your LLM/embedding provider and set the API key (OpenAI is default) - Test by uploading a document or crawling a website +### 🚀 Quick Command Reference + +| Command | Description | +| ----------------- | ------------------------------------------------------- | +| `make dev` | Start hybrid dev (backend in Docker, frontend local) ⭐ | +| `make dev-docker` | Everything in Docker | +| `make stop` | Stop all services | +| `make test` | Run all tests | +| `make lint` | Run linters | +| `make install` | Install dependencies | +| `make check` | Check environment setup | +| `make clean` | Remove containers and volumes (with confirmation) | + ## 🔄 Database Reset (Start Fresh if Needed) If you need to completely reset your database and start fresh: @@ -105,7 +124,7 @@ If you need to completely reset your database and start fresh: 3. **Restart Services**: ```bash - docker-compose up -d + docker compose --profile full up -d ``` 4. **Reconfigure**: @@ -116,6 +135,41 @@ The reset script safely removes all tables, functions, triggers, and policies wi +## 🛠️ Installing Make (OPTIONAL) + +Make is required for the local development workflow. Installation varies by platform: + +### Windows + +```bash +# Option 1: Using Chocolatey +choco install make + +# Option 2: Using Scoop +scoop install make + +# Option 3: Using WSL2 +wsl --install +# Then in WSL: sudo apt-get install make +``` + +### macOS + +```bash +# Make comes pre-installed on macOS +# If needed: brew install make +``` + +### Linux + +```bash +# Debian/Ubuntu +sudo apt-get install make + +# RHEL/CentOS/Fedora +sudo yum install make +``` + ## ⚡ Quick Test Once everything is running: @@ -221,11 +275,11 @@ Archon uses true microservices architecture with clear separation of concerns: By default, Archon services run on the following ports: -- **Archon-UI**: 3737 -- **Archon-Server**: 8181 -- **Archon-MCP**: 8051 -- **Archon-Agents**: 8052 -- **Archon-Docs**: 3838 (optional) +- **archon-ui**: 3737 +- **archon-server**: 8181 +- **archon-mcp**: 8051 +- **archon-agents**: 8052 +- **archon-docs**: 3838 (optional) ### Changing Ports @@ -269,27 +323,140 @@ This is useful when: After changing hostname or ports: -1. Restart Docker containers: `docker-compose down && docker-compose up -d` +1. Restart Docker containers: `docker compose down && docker compose --profile full up -d` 2. Access the UI at: `http://${HOST}:${ARCHON_UI_PORT}` 3. Update your AI client configuration with the new hostname and MCP port ## 🔧 Development -For development with hot reload: +### Quick Start ```bash -# Backend services (with auto-reload) -docker-compose up archon-server archon-mcp archon-agents --build +# Install dependencies +make install -# Frontend (with hot reload) -cd archon-ui-main && npm run dev +# Start development (recommended) +make dev # Backend in Docker, frontend local with hot reload -# Documentation (with hot reload) -cd docs && npm start +# Alternative: Everything in Docker +make dev-docker # All services in Docker + +# Stop everything (local FE needs to be stopped manually) +make stop +``` + +### Development Modes + +#### Hybrid Mode (Recommended) - `make dev` + +Best for active development with instant frontend updates: + +- Backend services run in Docker (isolated, consistent) +- Frontend runs locally with hot module replacement +- Instant UI updates without Docker rebuilds + +#### Full Docker Mode - `make dev-docker` + +For all services in Docker environment: + +- All services run in Docker containers +- Better for integration testing +- Slower frontend updates + +### Testing & Code Quality + +```bash +# Run tests +make test # Run all tests +make test-fe # Run frontend tests +make test-be # Run backend tests + +# Run linters +make lint # Lint all code +make lint-fe # Lint frontend code +make lint-be # Lint backend code + +# Check environment +make check # Verify environment setup + +# Clean up +make clean # Remove containers and volumes (asks for confirmation) +``` + +### Viewing Logs + +```bash +# View logs using Docker Compose directly +docker compose logs -f # All services +docker compose logs -f archon-server # API server +docker compose logs -f archon-mcp # MCP server +docker compose logs -f archon-ui # Frontend ``` **Note**: The backend services are configured with `--reload` flag in their uvicorn commands and have source code mounted as volumes for automatic hot reloading when you make changes. +## 🔍 Troubleshooting + +### Common Issues and Solutions + +#### Port Conflicts + +If you see "Port already in use" errors: + +```bash +# Check what's using a port (e.g., 3737) +lsof -i :3737 + +# Stop all containers and local services +make stop + +# Change the port in .env +``` + +#### Docker Permission Issues (Linux) + +If you encounter permission errors with Docker: + +```bash +# Add your user to the docker group +sudo usermod -aG docker $USER + +# Log out and back in, or run +newgrp docker +``` + +#### Windows-Specific Issues + +- **Make not found**: Install Make via Chocolatey, Scoop, or WSL2 (see [Installing Make](#installing-make)) +- **Line ending issues**: Configure Git to use LF endings: + ```bash + git config --global core.autocrlf false + ``` + +#### Frontend Can't Connect to Backend + +- Check backend is running: `curl http://localhost:8181/health` +- Verify port configuration in `.env` +- For custom ports, ensure both `ARCHON_SERVER_PORT` and `VITE_ARCHON_SERVER_PORT` are set + +#### Docker Compose Hangs + +If `docker compose` commands hang: + +```bash +# Reset Docker Compose +docker compose down --remove-orphans +docker system prune -f + +# Restart Docker Desktop (if applicable) +``` + +#### Hot Reload Not Working + +- **Frontend**: Ensure you're running in hybrid mode (`make dev`) for best HMR experience +- **Backend**: Check that volumes are mounted correctly in `docker-compose.yml` +- **File permissions**: On some systems, mounted volumes may have permission issues + ## 📈 Progress

diff --git a/archon-ui-main/Dockerfile b/archon-ui-main/Dockerfile index 2ad5d5f..2a1efe8 100644 --- a/archon-ui-main/Dockerfile +++ b/archon-ui-main/Dockerfile @@ -18,8 +18,8 @@ RUN mkdir -p /app/coverage && chmod 777 /app/coverage # Copy source code COPY . . -# Expose Vite's default port -EXPOSE 5173 +# Expose the port configured in package.json (3737) +EXPOSE 3737 -# Start Vite dev server with host binding for Docker -CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] +# Start Vite dev server (already configured with --port 3737 --host in package.json) +CMD ["npm", "run", "dev"] diff --git a/archon-ui-main/src/components/BackendStartupError.tsx b/archon-ui-main/src/components/BackendStartupError.tsx index a7a1e78..8d6447e 100644 --- a/archon-ui-main/src/components/BackendStartupError.tsx +++ b/archon-ui-main/src/components/BackendStartupError.tsx @@ -28,12 +28,12 @@ export const BackendStartupError: React.FC = () => { Check Docker Logs

- Check the Archon-Server logs in Docker Desktop for detailed error information. + Check the Archon API server container logs in Docker Desktop for detailed error information.

1. Open Docker Desktop

2. Go to Containers tab

-

3. Click on Archon-Server

+

3. Look for the Archon server container (typically named archon-server or similar)

4. View the logs for the specific error message

diff --git a/archon-ui-main/src/config/api.ts b/archon-ui-main/src/config/api.ts index 6b7799b..ec3eb25 100644 --- a/archon-ui-main/src/config/api.ts +++ b/archon-ui-main/src/config/api.ts @@ -20,14 +20,11 @@ export function getApiUrl(): string { // For development, construct from window location const protocol = window.location.protocol; const host = window.location.hostname; - const port = import.meta.env.ARCHON_SERVER_PORT; + // Use configured port or default to 8181 + const port = import.meta.env.VITE_ARCHON_SERVER_PORT || '8181'; - if (!port) { - throw new Error( - 'ARCHON_SERVER_PORT environment variable is required. ' + - 'Please set it in your environment variables. ' + - 'Default value: 8181' - ); + if (!import.meta.env.VITE_ARCHON_SERVER_PORT) { + console.info('[Archon] Using default ARCHON_SERVER_PORT: 8181'); } return `${protocol}//${host}:${port}`; diff --git a/archon-ui-main/test/config/api.test.ts b/archon-ui-main/test/config/api.test.ts index ac06c78..bbf58f5 100644 --- a/archon-ui-main/test/config/api.test.ts +++ b/archon-ui-main/test/config/api.test.ts @@ -41,23 +41,33 @@ describe('API Configuration', () => { expect(getApiUrl()).toBe(''); }); - it('should throw error when ARCHON_SERVER_PORT is not set in development', async () => { - // Development mode without port + it('should use default port 8181 when no port environment variables are set in development', async () => { + // Development mode without any port variables delete (import.meta.env as any).PROD; delete (import.meta.env as any).VITE_API_URL; + delete (import.meta.env as any).VITE_ARCHON_SERVER_PORT; + delete (import.meta.env as any).VITE_PORT; delete (import.meta.env as any).ARCHON_SERVER_PORT; + // Mock window.location + Object.defineProperty(window, 'location', { + value: { + protocol: 'http:', + hostname: 'localhost' + }, + writable: true + }); + const { getApiUrl } = await import('../../src/config/api'); - expect(() => getApiUrl()).toThrow('ARCHON_SERVER_PORT environment variable is required'); - expect(() => getApiUrl()).toThrow('Default value: 8181'); + expect(getApiUrl()).toBe('http://localhost:8181'); }); - it('should use ARCHON_SERVER_PORT when set in development', async () => { - // Development mode with custom port + it('should use VITE_ARCHON_SERVER_PORT when set in development', async () => { + // Development mode with custom port via VITE_ prefix delete (import.meta.env as any).PROD; delete (import.meta.env as any).VITE_API_URL; - (import.meta.env as any).ARCHON_SERVER_PORT = '9191'; + (import.meta.env as any).VITE_ARCHON_SERVER_PORT = '9191'; // Mock window.location Object.defineProperty(window, 'location', { @@ -73,10 +83,10 @@ describe('API Configuration', () => { }); it('should use custom port with https protocol', async () => { - // Development mode with custom port and https + // Development mode with custom port and https via VITE_ prefix delete (import.meta.env as any).PROD; delete (import.meta.env as any).VITE_API_URL; - (import.meta.env as any).ARCHON_SERVER_PORT = '8443'; + (import.meta.env as any).VITE_ARCHON_SERVER_PORT = '8443'; // Mock window.location with https Object.defineProperty(window, 'location', { @@ -139,7 +149,7 @@ describe('API Configuration', () => { vi.resetModules(); delete (import.meta.env as any).PROD; delete (import.meta.env as any).VITE_API_URL; - (import.meta.env as any).ARCHON_SERVER_PORT = port; + (import.meta.env as any).VITE_ARCHON_SERVER_PORT = port; Object.defineProperty(window, 'location', { value: { @@ -174,11 +184,10 @@ describe('MCP Client Service Configuration', () => { it('should throw error when ARCHON_MCP_PORT is not set', async () => { delete (import.meta.env as any).ARCHON_MCP_PORT; - const { MCPClientService } = await import('../../src/services/mcpClientService'); - const service = new MCPClientService(); + const { mcpClientService } = await import('../../src/services/mcpClientService'); - await expect(service.createArchonClient()).rejects.toThrow('ARCHON_MCP_PORT environment variable is required'); - await expect(service.createArchonClient()).rejects.toThrow('Default value: 8051'); + await expect(mcpClientService.createArchonClient()).rejects.toThrow('ARCHON_MCP_PORT environment variable is required'); + await expect(mcpClientService.createArchonClient()).rejects.toThrow('Default value: 8051'); }); it('should use ARCHON_MCP_PORT when set', async () => { @@ -205,11 +214,10 @@ describe('MCP Client Service Configuration', () => { }) }); - const { MCPClientService } = await import('../../src/services/mcpClientService'); - const service = new MCPClientService(); + const { mcpClientService } = await import('../../src/services/mcpClientService'); try { - await service.createArchonClient(); + await mcpClientService.createArchonClient(); // Verify the fetch was called with the correct URL expect(global.fetch).toHaveBeenCalledWith( diff --git a/archon-ui-main/vite.config.ts b/archon-ui-main/vite.config.ts index 0c81261..f6b7563 100644 --- a/archon-ui-main/vite.config.ts +++ b/archon-ui-main/vite.config.ts @@ -15,7 +15,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { // Get host and port from environment variables or use defaults // For internal Docker communication, use the service name // For external access, use the HOST from environment - const isDocker = process.env.DOCKER_ENV === 'true' || !!process.env.HOSTNAME; + const isDocker = process.env.DOCKER_ENV === 'true' || existsSync('/.dockerenv'); const internalHost = 'archon-server'; // Docker service name for internal communication const externalHost = process.env.HOST || 'localhost'; // Host for external access const host = isDocker ? internalHost : externalHost; @@ -278,7 +278,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { ], server: { host: '0.0.0.0', // Listen on all network interfaces with explicit IP - port: 5173, // Match the port expected in Docker + port: parseInt(process.env.ARCHON_UI_PORT || env.ARCHON_UI_PORT || '3737'), // Use configurable port strictPort: true, // Exit if port is in use proxy: { '/api': { diff --git a/check-env.js b/check-env.js new file mode 100644 index 0000000..938084d --- /dev/null +++ b/check-env.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node + +const fs = require('fs'); +const path = require('path'); + +// Secure path resolution +const projectRoot = process.cwd(); +const envPath = path.resolve(projectRoot, '.env'); + +// Security: Validate path is within project +if (!envPath.startsWith(projectRoot)) { + console.error('Security error: Invalid .env path'); + process.exit(1); +} + +// Check if .env exists +if (!fs.existsSync(envPath)) { + console.error('ERROR: .env file not found!'); + console.error('Copy .env.example to .env and add your credentials:'); + console.error(' cp .env.example .env'); + process.exit(1); +} + +// Parse .env file +const envContent = fs.readFileSync(envPath, 'utf8'); +const envVars = {}; + +envContent.split('\n').forEach(line => { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) return; + + const [key, ...valueParts] = trimmed.split('='); + if (key) { + const value = valueParts.join('=').trim().replace(/^["']|["']$/g, ''); + envVars[key.trim()] = value; + } +}); + +// Only check ESSENTIAL variables +const required = ['SUPABASE_URL', 'SUPABASE_SERVICE_KEY']; +const errors = []; + +required.forEach(varName => { + if (!envVars[varName] || envVars[varName] === '') { + errors.push(`Missing: ${varName}`); + } +}); + +if (errors.length > 0) { + console.error('ERROR: Required environment variables missing:'); + errors.forEach(err => console.error(` - ${err}`)); + console.error('\nPlease add these to your .env file'); + process.exit(1); +} + +// Validate URL format +try { + new URL(envVars['SUPABASE_URL']); +} catch (e) { + console.error('ERROR: SUPABASE_URL is not a valid URL'); + console.error(` Found: ${envVars['SUPABASE_URL']}`); + console.error(' Expected format: https://your-project.supabase.co'); + process.exit(1); +} + +// Basic validation for service key +if (envVars['SUPABASE_SERVICE_KEY'].length < 10) { + console.error('ERROR: SUPABASE_SERVICE_KEY appears to be invalid (too short)'); + console.error(' Please check your Supabase project settings'); + process.exit(1); +} + +console.log('✓ Environment configured correctly'); \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 62338d2..28c3f95 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,13 +1,22 @@ +# Docker Compose Profiles Strategy: +# - "backend": Starts only backend services (server, mcp, agents) for hybrid development +# - "frontend": Starts only the frontend UI service +# - "full": Starts all services for complete Docker deployment +# Use --profile flag to control which services start: +# docker compose --profile backend up # Backend only for hybrid dev (or docker-compose) +# docker compose --profile full up # Everything in Docker (or docker-compose) + services: # Server Service (FastAPI + Socket.IO + Crawling) archon-server: + profiles: ["backend", "full"] build: context: ./python dockerfile: Dockerfile.server args: BUILDKIT_INLINE_CACHE: 1 ARCHON_SERVER_PORT: ${ARCHON_SERVER_PORT:-8181} - container_name: Archon-Server + container_name: archon-server ports: - "${ARCHON_SERVER_PORT:-8181}:${ARCHON_SERVER_PORT:-8181}" environment: @@ -55,13 +64,14 @@ services: # Lightweight MCP Server Service (HTTP-based) archon-mcp: + profiles: ["backend", "full"] build: context: ./python dockerfile: Dockerfile.mcp args: BUILDKIT_INLINE_CACHE: 1 ARCHON_MCP_PORT: ${ARCHON_MCP_PORT:-8051} - container_name: Archon-MCP + container_name: archon-mcp ports: - "${ARCHON_MCP_PORT:-8051}:${ARCHON_MCP_PORT:-8051}" environment: @@ -99,13 +109,14 @@ services: # AI Agents Service (ML/Reranking) archon-agents: + profiles: ["backend", "full"] build: context: ./python dockerfile: Dockerfile.agents args: BUILDKIT_INLINE_CACHE: 1 ARCHON_AGENTS_PORT: ${ARCHON_AGENTS_PORT:-8052} - container_name: Archon-Agents + container_name: archon-agents ports: - "${ARCHON_AGENTS_PORT:-8052}:${ARCHON_AGENTS_PORT:-8052}" environment: @@ -132,19 +143,21 @@ services: start_period: 40s # Frontend - frontend: + archon-frontend: + profiles: ["frontend", "full"] build: ./archon-ui-main - container_name: Archon-UI + container_name: archon-ui ports: - - "${ARCHON_UI_PORT:-3737}:5173" + - "${ARCHON_UI_PORT:-3737}:3737" environment: - VITE_API_URL=http://${HOST:-localhost}:${ARCHON_SERVER_PORT:-8181} + - VITE_ARCHON_SERVER_PORT=${ARCHON_SERVER_PORT:-8181} - ARCHON_SERVER_PORT=${ARCHON_SERVER_PORT:-8181} - HOST=${HOST:-localhost} networks: - app-network healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:5173"] + test: ["CMD", "curl", "-f", "http://localhost:3737"] interval: 30s timeout: 10s retries: 3 diff --git a/python/src/server/api_routes/mcp_api.py b/python/src/server/api_routes/mcp_api.py index 84021d6..db43496 100644 --- a/python/src/server/api_routes/mcp_api.py +++ b/python/src/server/api_routes/mcp_api.py @@ -49,7 +49,7 @@ class MCPServerManager: """Manages the MCP Docker container lifecycle.""" def __init__(self): - self.container_name = "Archon-MCP" # Container name from docker-compose.yml + self.container_name = None # Will be resolved dynamically self.docker_client = None self.container = None self.status: str = "stopped" @@ -62,16 +62,29 @@ class MCPServerManager: self._min_operation_interval = 2.0 # Minimum 2 seconds between operations self._initialize_docker_client() + def _resolve_container(self): + """Simple container resolution - just use fixed name.""" + if not self.docker_client: + return None + + try: + # Simple: Just look for the fixed container name + container = self.docker_client.containers.get("archon-mcp") + self.container_name = "archon-mcp" + mcp_logger.info("Found MCP container") + return container + except NotFound: + mcp_logger.warning("MCP container not found - is it running?") + self.container_name = "archon-mcp" + return None + def _initialize_docker_client(self): """Initialize Docker client and get container reference.""" try: self.docker_client = docker.from_env() - try: - self.container = self.docker_client.containers.get(self.container_name) - mcp_logger.info(f"Found Docker container: {self.container_name}") - except NotFound: - mcp_logger.warning(f"Docker container {self.container_name} not found") - self.container = None + self.container = self._resolve_container() + if not self.container: + mcp_logger.warning("MCP container not found during initialization") except Exception as e: mcp_logger.error(f"Failed to initialize Docker client: {str(e)}") self.docker_client = None @@ -85,10 +98,17 @@ class MCPServerManager: if self.container: self.container.reload() # Refresh container info else: - self.container = self.docker_client.containers.get(self.container_name) + # Try to resolve container again if we don't have it + self.container = self._resolve_container() + if not self.container: + return "not_found" return self.container.status except NotFound: + # Try to resolve again in case container was recreated + self.container = self._resolve_container() + if self.container: + return self.container.status return "not_found" except Exception as e: mcp_logger.error(f"Error getting container status: {str(e)}")