76c4c74201
CI / lint (pull_request) Successful in 36s
CI / quality (pull_request) Successful in 40s
CI / build (pull_request) Successful in 44s
CI / security (pull_request) Successful in 51s
CI / typecheck (pull_request) Successful in 52s
CI / integration_tests (pull_request) Successful in 1m3s
CI / unit_tests (pull_request) Successful in 3m38s
CI / coverage (pull_request) Successful in 3m36s
CI / status-check (pull_request) Successful in 3s
CI / lint (push) Successful in 1m2s
CI / typecheck (push) Successful in 1m2s
CI / security (push) Successful in 1m2s
CI / quality (push) Successful in 40s
CI / integration_tests (push) Successful in 1m8s
CI / build (push) Successful in 49s
CI / unit_tests (push) Successful in 3m40s
CI / coverage (push) Successful in 3m36s
CI / status-check (push) Successful in 3s
- **`src/cleveractors/runtime_types.py`** — `ActorResult` and `NodeUsage` dataclasses
extracted to break circular imports (CONTRIBUTING.md §Import Guidelines). 100% coverage.
- **`src/cleveractors/runtime.py`** — `create_executor()` factory, `Executor` class
with `execute()` dispatching to module-level functions in `runtime_dispatch`.
Imports `_execute_*` at module level (no function-local imports). 100% coverage.
- **`src/cleveractors/runtime_dispatch.py`** — Four dispatch functions: `_execute_llm`,
`_execute_graph`, `_execute_tool`, `_execute_multi_actor`. All imports at module
level except `from cleveractors.runtime import Executor` inside `_execute_multi_actor`
(the only remaining circular dep — Executor calls _execute_multi_actor which creates
a new Executor; cannot be resolved without further restructuring). 99.69% coverage
(only the `if TYPE_CHECKING:` guard line is uncovered — not a real gap).
- **`src/cleveractors/runtime_tokens.py`** — Token estimation via tiktoken with
heuristic fallback. 100% coverage.
Key design decisions and fixes:
- **Circular import resolution**: `ActorResult`/`NodeUsage` moved to `runtime_types.py`;
both `runtime.py` and `runtime_dispatch.py` import from it at module level.
- **`messages` forwarded to `_execute_llm`**: builds `context={"conversation_history":[...]}`
passed to `LLMAgent.process_message` for multi-turn support.
- **`parallel_execution` aligned with `PureGraphConfig` default (True)**:
reads from legacy `route` dict or v2.0 `routes.main` dict; defaults to True.
- **Factory normalization**: always merges `actors` into `agents` (actors take
precedence) so configs using both keys work correctly.
- **Generic exception in agent creation re-raised as `ConfigurationError`**:
no double-logging; exception message preserved in `ConfigurationError`.
- **`cleveragents_block` guarded against `None`**: uses `or {}` coercion.
- **Type annotations added**: `top_provider`, `top_model`, `top_sp`,
`temperature_raw`, `max_tokens_raw`, `config_block`, `tools` in dispatch functions.
- **No `finally` in `_execute_tool`**: documented with comment (ToolAgent has no cleanup).
- **Dead step removed**: `step_rxe_invalid_node_type` was unreferenced and incorrect.
- **BDD coverage**: `parallel_execution=False` override verified via `PureGraphConfig`
constructor args; conversation history forwarding verified; AC7 immutability for
multi-actor path verified.
- ✅ `nox -e lint` — passes
- ✅ `nox -e format` — passes
- ✅ `nox -e typecheck` — passes (0 errors, 1 expected warning)
- ✅ `nox -e unit_tests` — 2113 scenarios pass, 0 failures, 0 skipped
- ✅ `nox -e integration_tests` — 76 tests pass
- ✅ `nox -e coverage_report` — 97.21% (9870 covered, 283 missing, 10153 total)
PR-modified files: `runtime_types.py` 100%, `runtime.py` 100%,
`runtime_dispatch.py` 99.69% (1 uncoverable TYPE_CHECKING guard), `runtime_tokens.py` 100%
ISSUES CLOSED: #13
115 lines
6.6 KiB
Gherkin
115 lines
6.6 KiB
Gherkin
Feature: Runtime Executor Extended Coverage
|
|
As a developer
|
|
I want the runtime executor to handle additional edge cases in graph, tool, and multi-actor execution
|
|
So that all code paths in the runtime module are exercised
|
|
|
|
Background:
|
|
Given the runtime extended test context is initialized (rxe)
|
|
|
|
Scenario: execute detects graph type from routes key in CleverAgents v2.0 format
|
|
Given a config dict with routes key but no type field (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test v2 graph" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _normalize_graph_config handles v2.0 routes with dict nodes
|
|
Given a config dict with type graph and v2.0 routes format with dict nodes (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test v2 dict nodes" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _normalize_graph_config handles v2.0 routes with list nodes
|
|
Given a config dict with type graph and v2.0 routes format with list nodes (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test v2 list nodes" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _execute_llm builds conversation history from messages
|
|
Given a config dict with type llm provider model and system_prompt in config block (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
And conversation history messages are provided (rxe)
|
|
When I execute the extended runtime actor with message "test conversation" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _execute_llm picks up provider from config block when not at top level
|
|
Given a config dict with type llm and provider model in nested config block (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test config block" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _execute_graph handles agent name from node ID in v2.0 actors block
|
|
Given a config dict with type graph and v2.0 routes with actors block (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test agents block" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _execute_graph raises ConfigurationError for unexpected agent creation failure
|
|
Given a config dict with type graph and route with agents block having missing agent (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test missing agent" (rxe)
|
|
Then a ConfigurationError should be raised about agent creation failure (rxe)
|
|
|
|
Scenario: _execute_graph merges global context from config with conversation history
|
|
Given a config dict with type graph and route with global context (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
And conversation history messages are provided (rxe)
|
|
When I execute the extended runtime actor with message "test global context" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _execute_tool builds conversation history from messages
|
|
Given a config dict with type tool and tools list (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
And conversation history messages are provided (rxe)
|
|
When I execute the extended runtime actor with message "test tool with history" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _execute_multi_actor uses default actor from cleveragents block
|
|
Given a multi-actor config dict with cleveragents default_actor (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test default actor" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
And the node usage IDs should be prefixed with the default actor name (rxe)
|
|
|
|
Scenario: _execute_graph handles actor context without global key
|
|
Given a config dict with type graph and route with actor context without global key (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test actor context" (rxe)
|
|
Then the execution should return an ActorResult (rxe)
|
|
|
|
Scenario: _execute_graph handles missing credential provider gracefully
|
|
Given a config dict with type llm and unknown provider (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test missing creds" (rxe)
|
|
Then a ConfigurationError should be raised about missing credentials (rxe)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# M3: parallel_execution override for legacy route format
|
|
# ---------------------------------------------------------------------------
|
|
|
|
Scenario: _execute_graph passes parallel_execution=False to PureGraphConfig for legacy route
|
|
Given a config dict with type graph and route with parallel_execution false (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor and capture PureGraphConfig args (rxe)
|
|
Then PureGraphConfig should have received parallel_execution=False (rxe)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# M4: conversation history forwarding verified by call_args assertion
|
|
# ---------------------------------------------------------------------------
|
|
|
|
Scenario: _execute_llm forwards conversation history to LLMAgent.process_message
|
|
Given a config dict with type llm provider model and system_prompt in config block (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
And conversation history messages are provided (rxe)
|
|
When I execute the LLM actor and capture process_message call args (rxe)
|
|
Then process_message should have received conversation_history in context (rxe)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# m5: AC7 immutability for multi-actor path
|
|
# ---------------------------------------------------------------------------
|
|
|
|
Scenario: _execute_multi_actor does not mutate the stored config_dict (AC7)
|
|
Given a multi-actor config dict with cleveragents default_actor (rxe)
|
|
And credentials dict with openai provider (rxe)
|
|
When I execute the extended runtime actor with message "test ac7 multi" (rxe)
|
|
Then the multi-actor config_dict should be unchanged after execution (rxe)
|