---
name: add-language-support
description: >
  Guide for adding a new programming language to the multi-language system.
  Use when extending the aiservice to support a new language (e.g., Rust, Go).
  Covers directory creation, handler implementation, registry registration,
  protocol compliance, prompt templates, router updates, and tests.
---

# Add Language Support

Use this workflow when adding a new programming language to the codeflash-internal optimization system. Follow steps in order — each builds on the previous.

## Step 1: Create Language Directory

Create the directory structure under `core/languages/`.

1. Create `core/languages/<lang>/` with `__init__.py`
2. Create subdirectories for each feature:
   ```
   core/languages/<lang>/
   ├── __init__.py           # Handler class + @register_handler decorator
   ├── optimizer/            # Optimization handler
   │   ├── __init__.py
   │   └── optimizer.py
   └── testgen/              # Test generation handler (if supported)
       ├── __init__.py
       └── testgen.py
   ```
3. Follow existing patterns from `core/languages/python/` or `core/languages/js_ts/`

**Checkpoint**: The directory structure should match existing language modules. Verify with `ls core/languages/`.

## Step 2: Implement Handler Class

Create the handler class in `core/languages/<lang>/__init__.py`.

1. Read `core/protocols/base.py` for the `LanguageHandler` protocol
2. Implement the handler:
   ```python
   from core.registry import register_handler

   @register_handler("<lang>")
   class <Lang>Handler:
       language = "<lang>"
       supports_testgen = False      # Set True if implementing testgen
       supports_optimizer = True     # Set True if implementing optimizer
       supports_code_repair = False
       supports_jit_rewrite = False
       supports_optimization_review = False
       supports_explanations = False
   ```
3. Set `supports_*` flags for each feature you implement
4. The `@register_handler` decorator registers the class with the global registry

**Checkpoint**: After this step, `registry.list_available()` should include your language ID.

## Step 3: Register the Module

Ensure the handler module is imported so the decorator fires.

1. Read `core/languages/__init__.py` — check how existing languages are imported
2. Add your language import so `@register_handler` fires on startup
3. Import should be at module level or via lazy import pattern

**Checkpoint**: Run `python -c "from core.languages import <lang>"` to verify no import errors.

## Step 4: Implement Protocol Methods

Implement the protocol methods for each supported feature.

1. Read `core/protocols/optimizer.py` — `OptimizerProtocol` requires `optimizer_optimize(request, data)`
2. Read `core/protocols/testgen.py` — `TestGenProtocol` requires `testgen_generate(request, data)`
3. Read `core/protocols/code_repair.py` — `CodeRepairProtocol` requires `code_repair_repair(user_id, optimization_id, ctx)`
4. Follow the pattern from Python/JS handlers:
   ```python
   async def optimizer_optimize(self, request, data):
       # 1. Build context from data.source_code
       # 2. Call call_llm() with language-specific prompts
       # 3. Parse response
       # 4. Return (status_code, response_schema)
   ```

**Checkpoint**: Each method must be `async def` and return the expected response type.

## Step 5: Create Prompt Templates

Create language-specific prompt templates.

1. Create `.md` files alongside the handler modules (e.g., `optimizer/system_prompt.md`)
2. Use Jinja2 templating for dynamic content
3. Prompts should include language-specific context (version, conventions, stdlib)
4. Follow the pattern from `core/languages/python/optimizer/context_utils/`

**Checkpoint**: Prompts should produce valid, non-empty system and user messages.

## Step 6: Update Routers

Add language dispatch to the shared routers.

1. Edit `core/shared/optimizer_router.py` — add a branch for your language:
   ```python
   if data.language == "<lang>":
       from core.languages.<lang>.optimizer import optimize_<lang>  # noqa: PLC0415
       return await optimize_<lang>(request, data)
   ```
2. Edit `core/shared/testgen_router.py` — add the same pattern if testgen is supported
3. Use lazy imports (inside the function body) to avoid circular dependencies

**Checkpoint**: Both routers should dispatch correctly for the new language.

## Step 7: Add Tests

Write tests for the new language handler.

1. Create `tests/<lang>/` directory mirroring the source structure
2. Test handler registration: verify `registry.get_handler("<lang>")` returns the correct class
3. Test feature dispatch: verify `get_handler_for_feature("<lang>", "optimizer")` works
4. Test optimization flow end-to-end (mock LLM calls)
5. Use `@pytest.mark.asyncio` for async tests
6. Run: `uv run pytest tests/<lang>/ -v`

**Checkpoint**: All tests must pass. Run `uv run prek run --all-files` for formatting/lint.

## Key Files Reference

| File | What to modify |
|------|---------------|
| `core/languages/<lang>/` | New handler directory |
| `core/registry.py` | No changes needed (decorator handles it) |
| `core/dispatcher.py` | No changes needed (dynamic lookup) |
| `core/protocols/` | Reference for protocol methods |
| `core/shared/optimizer_router.py` | Add language dispatch branch |
| `core/shared/testgen_router.py` | Add language dispatch branch (if testgen) |
| `core/languages/__init__.py` | Add import for decorator registration |
