Skip to content

Layered Dependencies en

EnerOS Bot edited this page Jul 5, 2026 · 1 revision

中文 | English

Layered Dependencies

Maintained version: v0.51.2 | Last updated: 2026-07-06

EnerOS strictly follows unidirectional dependencies: lower layers do not depend on upper layers; reverse and circular dependencies are forbidden. This is one of the project's hard constraints (see project memory "Hard Constraints").

See docs/developer-guide.md §1.3.


Dependency Direction

L0 Foundation (no internal deps, or only depends on eneros-core)
  ↑
L1 Kernel / Protocol (depends on L0)
  ↑
L2 Capability (depends on L0, L1)
  ↑
L3 Orchestration (depends on L0, L1, L2)
  ↑
L3 Application (depends on all lower layers)

Per-Layer Dependencies

eneros-core ◄── eneros-topology
             ◄── eneros-powerflow
             ◄── eneros-constraint
             ◄── eneros-equipment
             ◄── eneros-timeseries
             ◄── eneros-eventbus
             ◄── eneros-memory
             ◄── eneros-tenant
             ◄── eneros-tool
             ◄── eneros-reasoning
             ◄── eneros-os

eneros-core + eneros-eventbus ◄── eneros-device
eneros-core + eneros-equipment ◄── eneros-bridge
eneros-core + eneros-topology + eneros-powerflow + eneros-equipment ◄── eneros-network
eneros-core + eneros-device ◄── eneros-scada
eneros-powerflow + eneros-equipment ◄── eneros-analysis
eneros-core + eneros-os ◄── eneros-gateway
eneros-gateway + eneros-agent + eneros-reasoning + eneros-tool ◄── eneros-api
eneros-gateway + eneros-agent + eneros-constraint ◄── eneros-dashboard

Special Handling: Avoiding Circular Dependencies

1. eneros-plugin is independent

eneros-plugin is independent of eneros-device/eneros-agent/eneros-analysis, using mirror types to avoid circular dependencies. Third-party plugins call via eneros-sdk, which wraps common types.

2. eneros-network::conversion module

eneros-network depends on eneros-topology + eneros-powerflow + eneros-equipment simultaneously. When v0.50.0 introduced GridSimulator::from_ieee14()power_network_to_topology() conversion, the function was placed in the eneros-network::conversion module to avoid eneros-powerflow reverse-depending on eneros-network.

3. eneros-nl's NlDataProvider trait

eneros-nl (L9 natural language query layer) needs to query topology/timeseries/alert data, but cannot depend on eneros-topology/eneros-timeseries/eneros-scada (to avoid reverse dependencies). It uses the NlDataProvider trait for dependency injection; the caller (eneros-api) implements the trait to provide data.

4. eneros-sdk mirror types

Types exposed by eneros-sdk to third-party plugin developers maintain a mirror relationship with eneros-plugin internal types (same name + same structure), avoiding plugins directly depending on eneros-plugin internal modules at compile time.


Dependency Management Tools

# Check circular dependencies
cargo tree --workspace --duplicate

# Check duplicate versions
cargo deny check bans

# Check licenses
cargo deny check licenses

# Check security advisories
cargo audit

CI enforces the above in .github/workflows/ci.yml + security.yml. New dependencies must:

  • Be MIT-compatible licensed
  • Pass cargo audit and cargo deny
  • Be necessary and minimal
  • Not be GPL/AGPL or contain unpatched RUSTSEC vulnerabilities

Adding a New Crate

New crates require:

  1. Determine the layer (L0/L1/L2/L3)
  2. Only depend on same-layer or lower-layer crates
  3. Add to Cargo.toml workspace members
  4. Update Crate Index and docs/developer-guide.md
  5. Structural changes require /spec + ADR + full doc sync (see 记忆系统.md part 4 matrix)

Next Steps

Clone this wiki locally