forked from cleveragents/cleveragents-core
120274da99
Create DecisionService application-layer service that wraps DecisionRepository with structured logging and UnitOfWork transaction management. Wire DecisionService and PlanLifecycleService into the DI container as Factory providers. Inject DecisionService into PlanLifecycleService so that phase transitions automatically record decisions: start_strategize records a strategy_choice decision and start_execute records an implementation_choice decision. Decision recording is optional and never blocks lifecycle transitions. Add Behave feature (5 scenarios), Robot Framework smoke tests (2 test cases), ASV benchmarks (3 benchmark classes), and DI reference documentation. ISSUES CLOSED: #173
109 lines
4.4 KiB
Markdown
109 lines
4.4 KiB
Markdown
# Dependency Injection Reference
|
|
|
|
The CleverAgents DI container is built on `dependency-injector`'s
|
|
`DeclarativeContainer`. All service registrations live in
|
|
`src/cleveragents/application/container.py`.
|
|
|
|
## Container Overview
|
|
|
|
| Provider | Type | Description |
|
|
|-------------------------------|-----------|-----------------------------------------|
|
|
| `settings` | Singleton | Application settings |
|
|
| `provider_registry` | Singleton | AI provider registry |
|
|
| `database_url` | Callable | Database URL resolution |
|
|
| `unit_of_work` | Factory | Unit of Work (new per request) |
|
|
| `ai_provider` | Singleton | AI provider instance |
|
|
| `project_service` | Factory | Project management service |
|
|
| `vector_store_service` | Factory | Vector store operations |
|
|
| `context_service` | Factory | Context management service |
|
|
| `actor_service` | Factory | Actor configuration service |
|
|
| `actor_registry` | Factory | Actor registry with provider binding |
|
|
| `plan_service` | Factory | Legacy plan management (deprecated) |
|
|
| **`decision_service`** | Factory | Decision tree recording service |
|
|
| **`plan_lifecycle_service`** | Factory | V3 four-phase plan lifecycle |
|
|
| `resource_registry_service` | Factory | Resource registry operations |
|
|
| `namespaced_project_repo` | Factory | Namespaced project repository |
|
|
| `project_resource_link_repo` | Factory | Project-resource link repository |
|
|
| `stream_router` | Singleton | Reactive stream routing |
|
|
| `langgraph_bridge` | Singleton | LangGraph integration bridge |
|
|
| `route_bridge` | Singleton | Reactive route bridge |
|
|
|
|
## Decision Service Registration
|
|
|
|
The `DecisionService` is registered as a **Factory** provider, meaning
|
|
each resolution returns a new instance. It depends on:
|
|
|
|
- `settings` — Application settings (Singleton)
|
|
- `unit_of_work` — Unit of Work (Factory)
|
|
|
|
```python
|
|
decision_service = providers.Factory(
|
|
DecisionService,
|
|
settings=settings,
|
|
unit_of_work=unit_of_work,
|
|
)
|
|
```
|
|
|
|
`DecisionService` wraps `DecisionRepository` (accessible via
|
|
`UnitOfWorkContext.decisions`) and provides:
|
|
|
|
| Method | Description |
|
|
|-------------------------|--------------------------------------------|
|
|
| `record_decision()` | Persist a new decision |
|
|
| `get_decision()` | Retrieve a decision by ID |
|
|
| `get_decisions_for_plan()` | Get all decisions for a plan |
|
|
| `get_decision_tree()` | BFS traversal of the decision tree |
|
|
| `get_path_to_root()` | Walk from a decision up to the root |
|
|
| `mark_superseded()` | Mark a decision as superseded |
|
|
| `list_by_type()` | List decisions by type for a plan |
|
|
|
|
## Plan Lifecycle Service Registration
|
|
|
|
The `PlanLifecycleService` is registered as a **Factory** provider
|
|
with the `DecisionService` injected:
|
|
|
|
```python
|
|
plan_lifecycle_service = providers.Factory(
|
|
PlanLifecycleService,
|
|
settings=settings,
|
|
unit_of_work=unit_of_work,
|
|
decision_service=decision_service,
|
|
)
|
|
```
|
|
|
|
When a `DecisionService` is wired, the lifecycle service automatically
|
|
records decisions during phase transitions:
|
|
|
|
- **start_strategize** → records a `strategy_choice` decision
|
|
- **start_execute** → records an `implementation_choice` decision
|
|
|
|
If no `DecisionService` is provided (e.g. in legacy tests), decision
|
|
recording is silently skipped.
|
|
|
|
## Usage Example
|
|
|
|
```python
|
|
from cleveragents.application.container import get_container
|
|
|
|
container = get_container()
|
|
|
|
# Resolve services
|
|
decision_svc = container.decision_service()
|
|
lifecycle_svc = container.plan_lifecycle_service()
|
|
|
|
# Record a decision manually
|
|
from cleveragents.domain.models.core.decision import Decision, DecisionType
|
|
|
|
decision = Decision(
|
|
plan_id="01HV...",
|
|
sequence_number=0,
|
|
decision_type=DecisionType.STRATEGY_CHOICE,
|
|
question="Which approach?",
|
|
chosen_option="Approach A",
|
|
)
|
|
decision_svc.record_decision(decision)
|
|
|
|
# Retrieve decisions
|
|
decisions = decision_svc.get_decisions_for_plan("01HV...")
|
|
```
|