Development Guide
ACE = AI Computing Explorer
This guide covers setting up a development environment and contributing to Open ACE.
Development Setup
Prerequisites
- Python 3.9+
- Git
- A code editor (VS Code, PyCharm, etc.)
Setup Steps
# Clone the repository
git clone https://github.com/open-ace/open-ace.git
cd open-ace
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt
# Install development dependencies
pip install pytest pytest-cov playwright
# Initialize configuration
python3 cli.py config init
Project Structure
open-ace/
├── server.py # Web server entry point
├── requirements.txt # Python dependencies
│
├── app/ # Flask application
│ ├── __init__.py # create_app() factory
│ ├── routes/ # 24 Blueprint route modules
│ ├── services/ # 13 business logic services
│ ├── repositories/ # 11 data access repositories
│ ├── modules/ # Domain logic packages
│ │ ├── analytics/ # Usage analytics, ROI, cost optimization
│ │ ├── compliance/ # Audit analysis, reports, retention
│ │ ├── governance/ # Audit logging, alerts, quotas, content filter
│ │ ├── sso/ # OAuth2/OIDC SSO
│ │ └── workspace/ # Remote agents, sessions, collaboration
│ ├── models/ # Data models (User, Message, Session, Tenant, etc.)
│ ├── auth/ # Authentication decorators
│ └── utils/ # Helpers, validators, formatters
│
├── frontend/ # React + TypeScript SPA
│ └── src/
│ ├── api/ # API client modules
│ ├── hooks/ # React Query hooks
│ ├── components/ # UI components (common, features, work, layout)
│ ├── store/ # Zustand state management
│ ├── i18n/ # Internationalization (en/zh/ja/ko)
│ ├── types/ # TypeScript interfaces
│ └── utils/ # Formatters, helpers
│
├── remote-agent/ # Remote agent daemon
│ ├── agent.py # Main daemon loop
│ ├── executor.py # CLI subprocess management
│ ├── cli_adapters/ # Tool adapters (Claude, Qwen, Codex, OpenClaw)
│ ├── terminal_server.py # WebSocket PTY server
│ └── session_sync.py # Session history sync
│
├── scripts/ # Data collection scripts
│ ├── fetch_*.py # Per-tool data fetchers
│ ├── shared/ # Shared modules (config, db, utils)
│ └ ── migrations/ # Alembic database migrations
│
├── k8s/ # Kubernetes manifests
├── schema/ # Database schema files
├── static/ # Built frontend assets
├── templates/ # HTML templates
├── tests/ # Test files
│ ├── unit/ # Unit tests
│ ├── e2e/ # End-to-end tests
│ └── issues/ # Issue-specific tests
└── docs/ # Documentation (en/ + cn/)
Frontend Development
Setup
cd frontend
npm install
Development Server
# Start dev server on port 3000 (proxies API to localhost:5000)
npm run dev
The backend must be running on port 5000 for the frontend to work.
Build
# Build for production (outputs to ../static/js/dist/)
npm run build
Testing
# Unit tests
npm run test
# E2E tests with Playwright
npx playwright test
See FRONTEND-GUIDE.md for the complete frontend reference.
Code Style
We follow PEP 8 style guidelines:
- Use 4 spaces for indentation
- Maximum line length: 100 characters
- Use meaningful variable and function names
- Add docstrings to functions and classes
Example
def get_daily_usage(date: str, tool_name: str = None) -> dict:
"""
Get token usage for a specific date.
Args:
date: Date in YYYY-MM-DD format
tool_name: Optional tool filter
Returns:
Dictionary with usage statistics
"""
from app.repositories.database import get_connection, adapt_sql
conn = get_connection()
cursor = conn.cursor()
if tool_name:
cursor.execute(
adapt_sql("SELECT * FROM daily_usage WHERE date = ? AND tool_name = ?"),
(date, tool_name)
)
else:
cursor.execute(
adapt_sql("SELECT * FROM daily_usage WHERE date = ?"),
(date,)
)
return cursor.fetchall()
Testing
Run Tests
# Run all tests
pytest
# Run with verbose output
pytest -v
# Run unit tests only
pytest tests/unit/
# Run integration tests (SQLite + PostgreSQL)
pytest tests/integration/
# Run integration tests with PostgreSQL only
pytest tests/integration/ -k "_pg"
# Run specific test file
pytest tests/unit/test_db.py
# Run with coverage
pytest --cov=app tests/
Test Organization
tests/
├── unit/ # Unit tests
│ ├── test_message_service.py
│ ├── test_usage_service.py
│ └── ...
├── integration/ # Integration tests (SQLite + PostgreSQL)
│ ├── test_auth_service_pg.py
│ ├── test_auth_service_sqlite.py
│ ├── test_governance_repo_pg.py
│ ├── test_governance_repo_sqlite.py
│ └── ...
├── e2e/ # End-to-end tests
│ ├── manage/ # Admin UI tests
│ ├── remote/ # Remote workspace tests
│ └── terminal/ # Terminal tests
├── regression/ # Full regression test suite
├── performance/ # Performance tests
├── ui/ # UI screenshot/interaction tests
├── issues/ # Issue-specific tests
│ ├── 164/
│ ├── 517/
│ └── ...
└── conftest.py # Shared fixtures
Writing Tests
import pytest
from scripts.shared import db
def test_get_connection():
"""Test database connection."""
conn = db.get_connection()
assert conn is not None
conn.close()
def test_get_daily_usage():
"""Test daily usage query."""
result = db.get_daily_usage("2026-03-21")
assert isinstance(result, list)
UI Testing with Playwright
Setup
# Install Playwright
pip install playwright
# Install browsers
playwright install chromium
Running UI Tests
# Run UI tests
pytest tests/ui/
# Run specific test
pytest tests/ui/test_screenshot.py
Example UI Test
import asyncio
from playwright.async_api import async_playwright
async def test_login():
"""Test login functionality."""
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
# Navigate to login
await page.goto('http://localhost:5000/login')
# Fill form
await page.fill('#username', 'admin')
await page.fill('#password', 'admin123')
await page.click('button[type="submit"]')
# Wait for redirect
await page.wait_for_url('http://localhost:5000/')
await browser.close()
Database Migrations
Database schema migrations use Alembic. See migrations/ directory for migration files.
# Run migrations
alembic upgrade head
# Create a new migration
alembic revision --autogenerate -m "description"
Data Migration
For data migration scripts (e.g., SQLite to PostgreSQL), see scripts/utils/:
# Migrate from SQLite to PostgreSQL
python3 scripts/utils/migrate_to_postgres.py
Adding a New Data Source
To add support for a new AI tool:
- Create
scripts/fetch_newtool.py - Implement log parsing logic
- Add to configuration template
- Add tests
Template
#!/usr/bin/env python3
"""Fetch usage data from NewTool."""
import os
import sys
from pathlib import Path
# Add shared modules
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'shared'))
import db
import utils
def fetch_newtool(days: int = 7):
"""Fetch NewTool usage data."""
log_path = Path.home() / '.newtool' / 'logs'
for log_file in log_path.glob('*.jsonl'):
# Parse log file
# Extract token usage
# Save to database
pass
if __name__ == '__main__':
fetch_newtool()
Debugging
Enable Debug Logging
import logging
logging.basicConfig(level=logging.DEBUG)
Database Inspection
# Open SQLite database
sqlite3 ~/.open-ace/ace.db
# Query tables
.tables
.schema daily_usage
SELECT * FROM daily_usage LIMIT 10;
# PostgreSQL (if configured)
psql $DATABASE_URL
\dt
\d daily_usage
SELECT * FROM daily_usage LIMIT 10;
Release Process
- Update
VERSIONfile - Update
CHANGELOG.md - Create git tag
- Build release package
# Build release
./scripts/release.sh --version 1.1.0
Getting Help
- Check existing documentation in
docs/ - Search existing issues on GitHub
- Open a new issue for bugs or feature requests