Skip to main content

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:

  1. Create scripts/fetch_newtool.py
  2. Implement log parsing logic
  3. Add to configuration template
  4. 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

  1. Update VERSION file
  2. Update CHANGELOG.md
  3. Create git tag
  4. 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