Three private tiles published to the codeflash workspace: - codeflash-internal-rules: 6 eager rules (code-style, architecture, optimization-patterns, git-conventions, testing-rules, multi-language-handlers) - codeflash-internal-docs: 8 lazy doc pages (domain-types, optimization-pipeline, test-generation-pipeline, context-extraction, aiservice/cf-api endpoints, configuration-thresholds, llm-provider-abstraction) - codeflash-internal-skills: 4 on-demand skills (debug-optimization-failure, add-language-support, add-api-endpoint, debug-test-generation)
5.4 KiB
| name | description |
|---|---|
| add-language-support | 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/.
- Create
core/languages/<lang>/with__init__.py - 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 - Follow existing patterns from
core/languages/python/orcore/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.
- Read
core/protocols/base.pyfor theLanguageHandlerprotocol - Implement the handler:
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 - Set
supports_*flags for each feature you implement - The
@register_handlerdecorator 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.
- Read
core/languages/__init__.py— check how existing languages are imported - Add your language import so
@register_handlerfires on startup - 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.
- Read
core/protocols/optimizer.py—OptimizerProtocolrequiresoptimizer_optimize(request, data) - Read
core/protocols/testgen.py—TestGenProtocolrequirestestgen_generate(request, data) - Read
core/protocols/code_repair.py—CodeRepairProtocolrequirescode_repair_repair(user_id, optimization_id, ctx) - Follow the pattern from Python/JS handlers:
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.
- Create
.mdfiles alongside the handler modules (e.g.,optimizer/system_prompt.md) - Use Jinja2 templating for dynamic content
- Prompts should include language-specific context (version, conventions, stdlib)
- 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.
- Edit
core/shared/optimizer_router.py— add a branch for your language:if data.language == "<lang>": from core.languages.<lang>.optimizer import optimize_<lang> # noqa: PLC0415 return await optimize_<lang>(request, data) - Edit
core/shared/testgen_router.py— add the same pattern if testgen is supported - 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.
- Create
tests/<lang>/directory mirroring the source structure - Test handler registration: verify
registry.get_handler("<lang>")returns the correct class - Test feature dispatch: verify
get_handler_for_feature("<lang>", "optimizer")works - Test optimization flow end-to-end (mock LLM calls)
- Use
@pytest.mark.asynciofor async tests - 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 |