Feature Development Guide for Copex
Repository Structure
code
src/copex/ ├── client.py # Core client with retry logic and streaming ├── cli.py # Typer CLI commands ├── config.py # CopexConfig and configuration ├── models.py # Model, ReasoningEffort, EventType enums ├── ralph.py # RalphWiggum loop implementation ├── checkpoint.py # CheckpointStore and CheckpointedRalph ├── persistence.py # SessionStore and PersistentSession ├── metrics.py # MetricsCollector for usage tracking ├── tools.py # ParallelToolExecutor ├── mcp.py # MCPManager and MCPServerConfig ├── ui.py # Rich UI components └── __init__.py # Public API exports
Adding a CLI Command
- •Add command in
cli.py:
python
@app.command()
def mycommand(
arg: Annotated[str, typer.Argument(help="Description")],
option: Annotated[str, typer.Option("--opt", "-o", help="Description")] = "default",
) -> None:
"""Command description shown in help."""
# Implementation
asyncio.run(_mycommand_async(arg, option))
- •Add async implementation:
python
async def _mycommand_async(arg: str, option: str) -> None:
client = Copex(config)
await client.start()
try:
# Implementation
finally:
await client.stop()
Adding a New Event Type
- •Add to
models.py:
python
class EventType(str, Enum):
# ... existing
NEW_EVENT = "new.event"
- •Handle in
client.pyon_event():
python
elif event_type == EventType.NEW_EVENT.value:
# Handle the event
if on_chunk:
on_chunk(StreamChunk(type="new_type", delta=...))
Adding Config Options
- •Add to
CopexConfiginconfig.py:
python
@dataclass
class CopexConfig:
# ... existing
new_option: str = "default"
- •
Update
to_client_options()orto_session_options()if needed. - •
Update default config in
cli.pyinitcommand.
Patterns to Follow
Async/Await
python
async def my_function() -> str:
result = await some_async_operation()
return result
Type Hints
python
def process(items: list[str], callback: Callable[[str], None] | None = None) -> dict[str, Any]:
...
Dataclasses
python
@dataclass
class MyData:
field: str
optional: int | None = None
items: list[str] = field(default_factory=list)
Rich Output
python
from rich.console import Console
from rich.panel import Panel
console = Console()
console.print(Panel("Content", title="Title", border_style="blue"))
Testing New Features
- •Add test in
tests/test_*.py - •Use
FakeSessionto mock SDK - •Run:
python -m pytest tests/ -v
Export Public API
Add to src/copex/__init__.py:
python
from copex.newmodule import NewClass
__all__ = [
# ... existing
"NewClass",
]