From fd0135628160cc143a7602015a086318995f2eb9 Mon Sep 17 00:00:00 2001 From: Muizz Lateef Date: Thu, 2 Apr 2026 14:49:47 +0100 Subject: [PATCH 1/2] refactor: consolidate ProcessingMode into RunMode as single source of truth (#83) Remove the duplicate `ProcessingMode` enum from `processing/types.py` (ONLINE | BATCH) and replace all usages with `RunMode` from `config/types.py`. Eliminate the `is_batch_mode` boolean bridge in `PreparationContext` so the mode flows as a typed enum end-to-end, removing unnecessary round-trip conversions. - Delete `ProcessingMode` from `processing/types.py` - Update `ProcessingContext.mode` to use `RunMode` - Replace `is_batch_mode: bool` with `mode: RunMode` on `PreparationContext` - Remove bridge conversion in `TaskPreparer._render_prompt()` - Update all imports across 12 production files and 5 test files - Update stale docstring in `config/interfaces.py` Closes #83 --- agent_actions/config/interfaces.py | 2 +- .../preprocessing/staging/initial_pipeline.py | 4 +- .../llm/batch/processing/preparator.py | 3 +- .../processing/batch_context_adapter.py | 5 +- agent_actions/processing/batch_processor.py | 6 +- .../processing/invocation/factory.py | 6 +- agent_actions/processing/prepared_task.py | 7 ++- agent_actions/processing/record_processor.py | 6 +- agent_actions/processing/task_preparer.py | 5 +- agent_actions/processing/types.py | 11 +--- agent_actions/prompt/data_generator.py | 6 +- agent_actions/workflow/pipeline.py | 4 +- tests/core/test_invocation_strategy.py | 13 +++-- tests/core/test_record_processor.py | 8 +-- tests/core/test_task_preparer.py | 57 ++++++++++--------- .../unit/core/test_enrichment_unification.py | 4 +- .../core/test_upstream_unprocessed_filter.py | 8 +-- 17 files changed, 75 insertions(+), 80 deletions(-) diff --git a/agent_actions/config/interfaces.py b/agent_actions/config/interfaces.py index 5029509..8e54ece 100644 --- a/agent_actions/config/interfaces.py +++ b/agent_actions/config/interfaces.py @@ -15,7 +15,7 @@ class ProcessingMode(Enum): This enum controls *how* a single component runs: synchronously, asynchronously, or auto-detected. Values: SYNC, ASYNC, AUTO. - Not to be confused with ``processing.types.ProcessingMode`` which controls the + Not to be confused with ``config.types.RunMode`` which controls the *pipeline-level* dispatch mode (ONLINE vs BATCH). """ diff --git a/agent_actions/input/preprocessing/staging/initial_pipeline.py b/agent_actions/input/preprocessing/staging/initial_pipeline.py index a15838e..c471956 100644 --- a/agent_actions/input/preprocessing/staging/initial_pipeline.py +++ b/agent_actions/input/preprocessing/staging/initial_pipeline.py @@ -15,7 +15,7 @@ from agent_actions.output.writer import FileWriter from agent_actions.processing.processor import RecordProcessor from agent_actions.processing.result_collector import ResultCollector -from agent_actions.processing.types import ProcessingContext, ProcessingMode +from agent_actions.processing.types import ProcessingContext from agent_actions.prompt.formatter import PromptFormatter from agent_actions.storage.backend import DISPOSITION_PASSTHROUGH, NODE_LEVEL_RECORD_ID from agent_actions.utils.constants import CHUNK_CONFIG_KEY @@ -683,7 +683,7 @@ def _process_online_mode_with_record_processor( processing_context = ProcessingContext( agent_config=cast("ActionConfigDict", ctx.agent_config), agent_name=ctx.agent_name, - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=True, file_path=str(file_path), output_directory=str(output_directory), diff --git a/agent_actions/llm/batch/processing/preparator.py b/agent_actions/llm/batch/processing/preparator.py index aba848d..9df9e7f 100644 --- a/agent_actions/llm/batch/processing/preparator.py +++ b/agent_actions/llm/batch/processing/preparator.py @@ -4,6 +4,7 @@ from pathlib import Path from typing import Any +from agent_actions.config.types import RunMode from agent_actions.errors import ConfigurationError from agent_actions.llm.batch.core.batch_constants import ContextMetaKeys, FilterStatus from agent_actions.llm.batch.core.batch_context_metadata import BatchContextMetadata @@ -256,7 +257,7 @@ def _build_preparation_context( agent_config=agent_config, agent_name=agent_name, is_first_stage=False, # Batch is always subsequent-stage - is_batch_mode=True, # Batch processing mode + mode=RunMode.BATCH, source_data=source_data, agent_indices=self.action_indices, dependency_configs=self.dependency_configs, diff --git a/agent_actions/processing/batch_context_adapter.py b/agent_actions/processing/batch_context_adapter.py index 6dbb21d..da74c3d 100644 --- a/agent_actions/processing/batch_context_adapter.py +++ b/agent_actions/processing/batch_context_adapter.py @@ -2,10 +2,9 @@ from typing import Any, cast -from agent_actions.config.types import ActionConfigDict +from agent_actions.config.types import ActionConfigDict, RunMode from agent_actions.processing.types import ( ProcessingContext, - ProcessingMode, ProcessingResult, RecoveryMetadata, ) @@ -25,7 +24,7 @@ def to_processing_context( return ProcessingContext( agent_config=cast(ActionConfigDict, agent_config), agent_name=agent_config.get("agent_type", "unknown_action"), - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, is_first_stage=False, current_item=original_row, record_index=record_index, diff --git a/agent_actions/processing/batch_processor.py b/agent_actions/processing/batch_processor.py index 898910d..c318af7 100644 --- a/agent_actions/processing/batch_processor.py +++ b/agent_actions/processing/batch_processor.py @@ -2,9 +2,11 @@ from typing import Any, Optional +from agent_actions.config.types import RunMode + from .invocation import BatchProvider, InvocationStrategy from .record_processor import RecordProcessor -from .types import ProcessingContext, ProcessingMode, ProcessingResult +from .types import ProcessingContext, ProcessingResult class BatchProcessor: @@ -19,7 +21,7 @@ def __init__( agent_config: dict[str, Any], agent_name: str, strategy: InvocationStrategy | None = None, - mode: ProcessingMode = ProcessingMode.ONLINE, + mode: RunMode = RunMode.ONLINE, provider: Optional["BatchProvider"] = None, ): self._processor = RecordProcessor( diff --git a/agent_actions/processing/invocation/factory.py b/agent_actions/processing/invocation/factory.py index ea710c1..ab70140 100644 --- a/agent_actions/processing/invocation/factory.py +++ b/agent_actions/processing/invocation/factory.py @@ -7,10 +7,10 @@ if TYPE_CHECKING: from agent_actions.processing.recovery.response_validator import ResponseValidator +from agent_actions.config.types import RunMode from agent_actions.processing.invocation.batch import BatchStrategy from agent_actions.processing.invocation.online import OnlineStrategy from agent_actions.processing.invocation.strategy import BatchProvider, InvocationStrategy -from agent_actions.processing.types import ProcessingMode class InvocationStrategyFactory: @@ -18,7 +18,7 @@ class InvocationStrategyFactory: @staticmethod def create( - mode: ProcessingMode, + mode: RunMode, agent_config: dict[str, Any], provider: BatchProvider | None = None, ) -> InvocationStrategy: @@ -27,7 +27,7 @@ def create( Raises: ValueError: If BATCH mode requested without provider. """ - if mode == ProcessingMode.BATCH: + if mode == RunMode.BATCH: if provider is None: raise ValueError( f"BatchProvider required for BATCH mode (action: '{agent_config.get('agent_type', 'unknown')}')" diff --git a/agent_actions/processing/prepared_task.py b/agent_actions/processing/prepared_task.py index 1263b07..eab1cf6 100644 --- a/agent_actions/processing/prepared_task.py +++ b/agent_actions/processing/prepared_task.py @@ -4,6 +4,8 @@ from enum import Enum from typing import TYPE_CHECKING, Any, Optional, cast +from agent_actions.config.types import RunMode + if TYPE_CHECKING: from agent_actions.processing.types import ProcessingContext from agent_actions.storage.backend import StorageBackend @@ -64,7 +66,7 @@ class PreparationContext: agent_config: dict[str, Any] agent_name: str is_first_stage: bool = False - is_batch_mode: bool = False + mode: RunMode = RunMode.ONLINE source_data: list[dict[str, Any]] | None = None agent_indices: dict[str, int] | None = None dependency_configs: dict[str, Any] | None = None @@ -80,14 +82,13 @@ class PreparationContext: @classmethod def from_processing_context(cls, context: "ProcessingContext") -> "PreparationContext": """Create PreparationContext from a ProcessingContext.""" - from agent_actions.processing.types import ProcessingMode from agent_actions.utils.tools_resolver import resolve_tools_path return cls( agent_config=cast(dict[str, Any], context.agent_config), agent_name=context.agent_name, is_first_stage=context.is_first_stage, - is_batch_mode=context.mode == ProcessingMode.BATCH, + mode=context.mode, source_data=context.source_data, agent_indices=context.agent_indices, dependency_configs=context.dependency_configs, diff --git a/agent_actions/processing/record_processor.py b/agent_actions/processing/record_processor.py index c25ff06..0be6b3f 100644 --- a/agent_actions/processing/record_processor.py +++ b/agent_actions/processing/record_processor.py @@ -5,6 +5,7 @@ from datetime import UTC, datetime from typing import Any, Optional, cast +from agent_actions.config.types import RunMode from agent_actions.errors import ConfigurationError, SchemaValidationError from agent_actions.errors.operations import TemplateVariableError from agent_actions.errors.processing import EmptyOutputError @@ -29,7 +30,6 @@ from .task_preparer import TaskPreparer, get_task_preparer from .types import ( ProcessingContext, - ProcessingMode, ProcessingResult, ProcessingStatus, ) @@ -54,13 +54,13 @@ def __init__( agent_config: dict[str, Any], agent_name: str, strategy: InvocationStrategy | None = None, - mode: ProcessingMode = ProcessingMode.ONLINE, + mode: RunMode = RunMode.ONLINE, provider: Optional["BatchProvider"] = None, ): self.agent_config = agent_config self.agent_name = agent_name - if strategy is not None and (mode != ProcessingMode.ONLINE or provider is not None): + if strategy is not None and (mode != RunMode.ONLINE or provider is not None): logger.warning( "Both 'strategy' and 'mode'/'provider' specified for %s; " "'strategy' takes precedence", diff --git a/agent_actions/processing/task_preparer.py b/agent_actions/processing/task_preparer.py index f1271e6..7499c7a 100644 --- a/agent_actions/processing/task_preparer.py +++ b/agent_actions/processing/task_preparer.py @@ -5,7 +5,6 @@ from collections.abc import Callable from typing import Any -from agent_actions.config.types import RunMode from agent_actions.processing.prepared_task import ( GuardStatus, PreparationContext, @@ -261,13 +260,11 @@ def _render_prompt( """Render prompt template using pre-loaded field context.""" from agent_actions.prompt.service import PromptPreparationService - mode: RunMode = RunMode.BATCH if context.is_batch_mode else RunMode.ONLINE - return PromptPreparationService.prepare_prompt_with_field_context( agent_config=context.agent_config, agent_name=context.agent_name, contents=content if isinstance(content, dict) else {}, - mode=mode, + mode=context.mode, field_context=field_context, tools_path=context.tools_path, ) diff --git a/agent_actions/processing/types.py b/agent_actions/processing/types.py index bbd81c0..a26a3c4 100644 --- a/agent_actions/processing/types.py +++ b/agent_actions/processing/types.py @@ -4,7 +4,7 @@ from enum import Enum from typing import TYPE_CHECKING, Any, Optional -from agent_actions.config.types import ActionConfigDict +from agent_actions.config.types import ActionConfigDict, RunMode if TYPE_CHECKING: from agent_actions.storage.backend import StorageBackend @@ -22,13 +22,6 @@ class ProcessingStatus(Enum): UNPROCESSED = "unprocessed" # Upstream failed/skipped this record -class ProcessingMode(Enum): - """Workflow-level data flow mode: ONLINE (synchronous) or BATCH (queued).""" - - ONLINE = "online" - BATCH = "batch" - - @dataclass class RetryState: """Retry-related state for a processing operation.""" @@ -285,7 +278,7 @@ class ProcessingContext: agent_config: ActionConfigDict agent_name: str - mode: ProcessingMode = ProcessingMode.ONLINE + mode: RunMode = RunMode.ONLINE is_first_stage: bool = False source_data: list[dict[str, Any]] = field(default_factory=list) file_path: str | None = None diff --git a/agent_actions/prompt/data_generator.py b/agent_actions/prompt/data_generator.py index fda5d3d..694a55a 100644 --- a/agent_actions/prompt/data_generator.py +++ b/agent_actions/prompt/data_generator.py @@ -11,15 +11,13 @@ from agent_actions.storage.backend import StorageBackend from agent_actions.config.di.container import registry from agent_actions.config.interfaces import IGenerator, ProcessingMode +from agent_actions.config.types import RunMode from agent_actions.errors import GenerationError from agent_actions.processing.processor import RecordProcessor from agent_actions.processing.types import ( ProcessingContext, ProcessingStatus, ) -from agent_actions.processing.types import ( - ProcessingMode as CoreProcessingMode, -) logger = logging.getLogger(__name__) @@ -78,7 +76,7 @@ def create_agent_with_data( context = ProcessingContext( agent_config=cast(ActionConfigDict, self.agent_config), agent_name=self.agent_name, - mode=CoreProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=False, # This is subsequent-stage processing source_data=source_content if isinstance(source_content, list) else [], file_path=file_path, diff --git a/agent_actions/workflow/pipeline.py b/agent_actions/workflow/pipeline.py index 87c41c6..9151878 100644 --- a/agent_actions/workflow/pipeline.py +++ b/agent_actions/workflow/pipeline.py @@ -19,7 +19,7 @@ from agent_actions.output.writer import FileWriter from agent_actions.processing.processor import RecordProcessor from agent_actions.processing.result_collector import ResultCollector -from agent_actions.processing.types import ProcessingContext, ProcessingMode +from agent_actions.processing.types import ProcessingContext from agent_actions.prompt.context.scope_file_mode import apply_observe_for_file_mode from agent_actions.storage.backend import DISPOSITION_PASSTHROUGH, NODE_LEVEL_RECORD_ID from agent_actions.utils.constants import MODEL_VENDOR_KEY @@ -448,7 +448,7 @@ def _process_by_strategy( context = ProcessingContext( agent_config=self.config.action_config, agent_name=self.config.action_name, - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=False, source_data=source_data, # Pass the loaded source data file_path=file_path, diff --git a/tests/core/test_invocation_strategy.py b/tests/core/test_invocation_strategy.py index 244fb74..f7c3693 100644 --- a/tests/core/test_invocation_strategy.py +++ b/tests/core/test_invocation_strategy.py @@ -4,6 +4,7 @@ import pytest +from agent_actions.config.types import RunMode from agent_actions.processing.invocation import ( BatchStrategy, BatchSubmissionResult, @@ -12,7 +13,7 @@ OnlineStrategy, ) from agent_actions.processing.prepared_task import GuardStatus, PreparedTask -from agent_actions.processing.types import ProcessingContext, ProcessingMode +from agent_actions.processing.types import ProcessingContext @pytest.fixture @@ -62,7 +63,7 @@ def basic_context(): return ProcessingContext( agent_config={"agent_type": "test_agent", "prompt": "test"}, agent_name="test_agent", - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, ) @@ -339,7 +340,7 @@ def test_batch_mode_requires_provider(self): """Test BATCH mode raises error without provider.""" with pytest.raises(ValueError, match="BatchProvider required"): InvocationStrategyFactory.create( - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, agent_config={"agent_type": "test"}, ) @@ -355,7 +356,7 @@ def test_batch_mode_without_provider_raises(self): RecordProcessor( agent_config={}, agent_name="test", - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, ) @@ -376,11 +377,11 @@ def test_batch_invocation_returns_deferred_not_filtered( response=None, deferred=True) fell through to the RP002 filter branch, discarding queued batch tasks. """ + from agent_actions.config.types import RunMode from agent_actions.processing.prepared_task import GuardStatus, PreparedTask from agent_actions.processing.processor import RecordProcessor from agent_actions.processing.types import ( ProcessingContext, - ProcessingMode, ProcessingStatus, ) @@ -414,7 +415,7 @@ def test_batch_invocation_returns_deferred_not_filtered( context = ProcessingContext( agent_config={"agent_type": "test"}, agent_name="test", - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, ) result = processor.process({"raw": "data"}, context) diff --git a/tests/core/test_record_processor.py b/tests/core/test_record_processor.py index c1549d9..6782ee4 100644 --- a/tests/core/test_record_processor.py +++ b/tests/core/test_record_processor.py @@ -4,10 +4,10 @@ import pytest +from agent_actions.config.types import RunMode from agent_actions.processing.processor import RecordProcessor from agent_actions.processing.types import ( ProcessingContext, - ProcessingMode, ProcessingResult, ProcessingStatus, ) @@ -129,7 +129,7 @@ def process(self, item, context): agent_name="test_action", agent_indices={"test_action": 0}, is_first_stage=False, - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, ) # ConfigurationError should be re-raised, not caught @@ -160,7 +160,7 @@ def process(self, item, context): agent_name="test_action", agent_indices={"test_action": 0}, is_first_stage=False, - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, ) # TemplateVariableError should be re-raised, not caught @@ -182,7 +182,7 @@ def process(self, item, context): agent_name="test_action", agent_indices={"test_action": 0}, is_first_stage=False, - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, ) # Other exceptions should be caught and converted to failed results diff --git a/tests/core/test_task_preparer.py b/tests/core/test_task_preparer.py index 21199f9..783922d 100644 --- a/tests/core/test_task_preparer.py +++ b/tests/core/test_task_preparer.py @@ -68,12 +68,13 @@ class TestPreparationContext: def test_from_processing_context(self): """Test creating PreparationContext from ProcessingContext.""" - from agent_actions.processing.types import ProcessingContext, ProcessingMode + from agent_actions.config.types import RunMode + from agent_actions.processing.types import ProcessingContext processing_ctx = ProcessingContext( agent_config={"agent_type": "test", "prompt": "test"}, agent_name="test_agent", - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=True, source_data=[{"a": 1}], file_path="/tmp/test.json", @@ -94,34 +95,36 @@ class TestPreparationContextBatchMode: """Tests for batch mode derivation in PreparationContext.""" def test_preparation_context_batch_mode_derived(self): - """is_batch_mode is True when ProcessingContext.mode is BATCH.""" - from agent_actions.processing.types import ProcessingContext, ProcessingMode + """mode is RunMode.BATCH when ProcessingContext.mode is BATCH.""" + from agent_actions.config.types import RunMode + from agent_actions.processing.types import ProcessingContext processing_ctx = ProcessingContext( agent_config={"agent_type": "test", "prompt": "test"}, agent_name="test_agent", - mode=ProcessingMode.BATCH, + mode=RunMode.BATCH, is_first_stage=True, ) prep_ctx = PreparationContext.from_processing_context(processing_ctx) - assert prep_ctx.is_batch_mode is True + assert prep_ctx.mode == RunMode.BATCH def test_preparation_context_online_mode_not_batch(self): - """is_batch_mode is False when ProcessingContext.mode is ONLINE.""" - from agent_actions.processing.types import ProcessingContext, ProcessingMode + """mode is RunMode.ONLINE when ProcessingContext.mode is ONLINE.""" + from agent_actions.config.types import RunMode + from agent_actions.processing.types import ProcessingContext processing_ctx = ProcessingContext( agent_config={"agent_type": "test", "prompt": "test"}, agent_name="test_agent", - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=True, ) prep_ctx = PreparationContext.from_processing_context(processing_ctx) - assert prep_ctx.is_batch_mode is False + assert prep_ctx.mode == RunMode.ONLINE class TestTaskPreparerNormalization: @@ -354,14 +357,16 @@ def test_no_guard_skips_evaluation(self, mock_render_prompt, mock_load_ctx): class TestModeSelection: - """Tests for batch/online mode selection based on is_batch_mode flag.""" + """Tests for batch/online mode selection based on RunMode.""" @patch( "agent_actions.prompt.service.PromptPreparationService.prepare_prompt_with_field_context" ) @patch("agent_actions.processing.task_preparer.TaskPreparer._load_full_context") def test_online_mode_uses_online(self, mock_load_ctx, mock_prepare): - """Test that online processing (is_batch_mode=False) uses online mode.""" + """Test that online processing (mode=RunMode.ONLINE) uses online mode.""" + from agent_actions.config.types import RunMode + mock_load_ctx.return_value = {"content": "test"} mock_result = MagicMock() @@ -371,29 +376,29 @@ def test_online_mode_uses_online(self, mock_load_ctx, mock_prepare): mock_result.prompt_context = {} mock_prepare.return_value = mock_result - # Online context - is_batch_mode=False (default) context = PreparationContext( agent_config={"agent_type": "test", "prompt": "test"}, agent_name="test", is_first_stage=True, - is_batch_mode=False, - version_context=None, # No loop context, but should still be online + mode=RunMode.ONLINE, + version_context=None, ) preparer = TaskPreparer() preparer.prepare({"content": "test"}, context) - # Verify online mode was used mock_prepare.assert_called_once() call_kwargs = mock_prepare.call_args[1] - assert call_kwargs["mode"] == "online" + assert call_kwargs["mode"] == RunMode.ONLINE @patch( "agent_actions.prompt.service.PromptPreparationService.prepare_prompt_with_field_context" ) @patch("agent_actions.processing.task_preparer.TaskPreparer._load_full_context") def test_batch_mode_uses_batch(self, mock_load_ctx, mock_prepare): - """Test that batch processing (is_batch_mode=True) uses batch mode.""" + """Test that batch processing (mode=RunMode.BATCH) uses batch mode.""" + from agent_actions.config.types import RunMode + mock_load_ctx.return_value = {"content": "test"} mock_result = MagicMock() @@ -403,21 +408,19 @@ def test_batch_mode_uses_batch(self, mock_load_ctx, mock_prepare): mock_result.prompt_context = {} mock_prepare.return_value = mock_result - # Batch context - is_batch_mode=True context = PreparationContext( agent_config={"agent_type": "test", "prompt": "test"}, agent_name="test", is_first_stage=False, - is_batch_mode=True, + mode=RunMode.BATCH, ) preparer = TaskPreparer() preparer.prepare({"content": "test"}, context) - # Verify batch mode was used mock_prepare.assert_called_once() call_kwargs = mock_prepare.call_args[1] - assert call_kwargs["mode"] == "batch" + assert call_kwargs["mode"] == RunMode.BATCH @patch( "agent_actions.prompt.service.PromptPreparationService.prepare_prompt_with_field_context" @@ -425,6 +428,8 @@ def test_batch_mode_uses_batch(self, mock_load_ctx, mock_prepare): @patch("agent_actions.processing.task_preparer.TaskPreparer._load_full_context") def test_online_with_loop_uses_online(self, mock_load_ctx, mock_prepare): """Test that online processing with loop context also uses online mode.""" + from agent_actions.config.types import RunMode + mock_load_ctx.return_value = {"content": "test"} mock_result = MagicMock() @@ -434,22 +439,20 @@ def test_online_with_loop_uses_online(self, mock_load_ctx, mock_prepare): mock_result.prompt_context = {} mock_prepare.return_value = mock_result - # Online context with loop context = PreparationContext( agent_config={"agent_type": "test", "prompt": "test"}, agent_name="test", is_first_stage=False, - is_batch_mode=False, - version_context={"iteration": 1}, # Has loop context + mode=RunMode.ONLINE, + version_context={"iteration": 1}, ) preparer = TaskPreparer() preparer.prepare({"content": "test"}, context) - # Verify online mode was used mock_prepare.assert_called_once() call_kwargs = mock_prepare.call_args[1] - assert call_kwargs["mode"] == "online" + assert call_kwargs["mode"] == RunMode.ONLINE class TestGuardBeforePromptRendering: diff --git a/tests/unit/core/test_enrichment_unification.py b/tests/unit/core/test_enrichment_unification.py index 23752f8..710b1e1 100644 --- a/tests/unit/core/test_enrichment_unification.py +++ b/tests/unit/core/test_enrichment_unification.py @@ -8,10 +8,10 @@ import pytest +from agent_actions.config.types import RunMode from agent_actions.processing.enrichment import EnrichmentPipeline from agent_actions.processing.types import ( ProcessingContext, - ProcessingMode, ProcessingResult, RecoveryMetadata, RetryMetadata, @@ -40,7 +40,7 @@ def _make_context(agent_config, record_index=0, is_first_stage=True, current_ite return ProcessingContext( agent_config=agent_config, agent_name=agent_config.get("agent_type", "test"), - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=is_first_stage, record_index=record_index, current_item=current_item, diff --git a/tests/unit/core/test_upstream_unprocessed_filter.py b/tests/unit/core/test_upstream_unprocessed_filter.py index 285071a..197ae37 100644 --- a/tests/unit/core/test_upstream_unprocessed_filter.py +++ b/tests/unit/core/test_upstream_unprocessed_filter.py @@ -13,6 +13,7 @@ import pytest +from agent_actions.config.types import RunMode from agent_actions.processing.enrichment import EnrichmentPipeline from agent_actions.processing.prepared_task import GuardStatus, PreparationContext from agent_actions.processing.processor import RecordProcessor @@ -20,7 +21,6 @@ from agent_actions.processing.task_preparer import TaskPreparer from agent_actions.processing.types import ( ProcessingContext, - ProcessingMode, ProcessingResult, ProcessingStatus, ) @@ -129,7 +129,7 @@ def test_creates_unprocessed_result(self): context = ProcessingContext( agent_config=config, agent_name="test_action", - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=False, ) @@ -203,7 +203,7 @@ def test_lineage_added_to_unprocessed(self): context = ProcessingContext( agent_config=config, agent_name="enrich_action", - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=True, record_index=0, ) @@ -234,7 +234,7 @@ def test_metadata_enricher_skips_unprocessed(self): context = ProcessingContext( agent_config=config, agent_name="meta_action", - mode=ProcessingMode.ONLINE, + mode=RunMode.ONLINE, is_first_stage=True, record_index=0, ) From 41582fb6f7d9b7a5999c80172fefb55fb20ddf3a Mon Sep 17 00:00:00 2001 From: Muizz Lateef Date: Thu, 2 Apr 2026 14:55:42 +0100 Subject: [PATCH 2/2] chore: remove redundant import and update _MANIFEST.md - Remove duplicate `from agent_actions.config.types import RunMode` local import in test_invocation_strategy.py (already at module level) - Update processing/_MANIFEST.md to reflect RunMode usage in prepared_task.py and types.py --- agent_actions/processing/_MANIFEST.md | 4 ++-- tests/core/test_invocation_strategy.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/agent_actions/processing/_MANIFEST.md b/agent_actions/processing/_MANIFEST.md index 6d541ff..7b046c1 100644 --- a/agent_actions/processing/_MANIFEST.md +++ b/agent_actions/processing/_MANIFEST.md @@ -23,6 +23,6 @@ lineage helpers, recovery flows, and transformation pipelines. | `helpers.py` | Module | Shared helpers (UUID construction, tuple flattening) for processors. | `processing` | | `processor.py` | Module | Base processor that glues loaders, transformers, and error handling. | `input`, `processing` | | `result_collector.py` | Module | Collects main vs side outputs, handles duplicates. Counts UNPROCESSED results separately from successes. | `output` | -| `prepared_task.py` | Module | `GuardStatus` enum (PASSED, SKIPPED, FILTERED, UPSTREAM_UNPROCESSED) and `PreparedTask` dataclass output by TaskPreparer. | `typing` | +| `prepared_task.py` | Module | `GuardStatus` enum (PASSED, SKIPPED, FILTERED, UPSTREAM_UNPROCESSED), `PreparedTask` dataclass, and `PreparationContext` (carries `mode: RunMode` directly). | `typing` | | `task_preparer.py` | Module | Unified task preparation (normalize, prompt, guard) for batch/online. Short-circuits upstream-unprocessed records before context loading. | `input`, `prompt` | -| `types.py` | Module | `ProcessingStatus` enum (SUCCESS, SKIPPED, FILTERED, FAILED, EXHAUSTED, DEFERRED, UNPROCESSED), `ProcessingResult` factories, and `ProcessingContext`. | `typing` | +| `types.py` | Module | `ProcessingStatus` enum (SUCCESS, SKIPPED, FILTERED, FAILED, EXHAUSTED, DEFERRED, UNPROCESSED), `ProcessingResult` factories, and `ProcessingContext` (uses `RunMode` for mode). | `typing` | diff --git a/tests/core/test_invocation_strategy.py b/tests/core/test_invocation_strategy.py index f7c3693..6482359 100644 --- a/tests/core/test_invocation_strategy.py +++ b/tests/core/test_invocation_strategy.py @@ -377,7 +377,6 @@ def test_batch_invocation_returns_deferred_not_filtered( response=None, deferred=True) fell through to the RP002 filter branch, discarding queued batch tasks. """ - from agent_actions.config.types import RunMode from agent_actions.processing.prepared_task import GuardStatus, PreparedTask from agent_actions.processing.processor import RecordProcessor from agent_actions.processing.types import (