Repository: emcie-co/parlant
File: src/parlant/core/services/indexing/relative_action_proposer.py (Python)

Code before:
    build_node_wrappers,
    get_journey_transition_map_text,
)
from parlant.core.engines.alpha.optimization_policy import OptimizationPolicy
from parlant.core.engines.alpha.prompt_builder import PromptBuilder
from parlant.core.guidelines import Guideline
from parlant.core.journeys import Journey
from parlant.core.loggers import Logger
from parlant.core.nlp.generation import SchematicGenerator
from parlant.core.services.indexing.common import EvaluationError, ProgressReport
from parlant.core.services.tools.service_registry import ServiceRegistry
from parlant.core.shots import Shot, ShotCollection


class RewrittenActionResult(DefaultBaseModel):
    index: str
    rewritten_actions: str


class RelativeActionProposition(DefaultBaseModel):
    actions: Sequence[RewrittenActionResult]


class RelativeActionBatch(DefaultBaseModel):
    index: str
    conditions: Sequence[str]
    action: str
    needs_rewrite_rational: str
    needs_rewrite: bool
    former_reference: Optional[str] = None
    rewritten_action: Optional[str] = None


class RelativeActionSchema(DefaultBaseModel):
    actions: Sequence[RelativeActionBatch]


@dataclass
class RelativeActionShot(Shot):
    journey_title: str
    journey_steps: dict[str, _JourneyNode]
    expected_result: RelativeActionSchema


class RelativeActionProposer:
    def __init__(
        self,
        logger: Logger,
        optimization_policy: OptimizationPolicy,
        schematic_generator: SchematicGenerator[RelativeActionSchema],
        service_registry: ServiceRegistry,

Review comment (suggestion):
For extra robustness, let's define this as `conditions: Sequence[str] | None = None`

This will help with cases where some models decide to place `null` instead of an empty list - I've seen it before.

Code after:
    build_node_wrappers,
    get_journey_transition_map_text,
)
from parlant.core.engines.alpha.optimization_policy import OptimizationPolicy
from parlant.core.engines.alpha.prompt_builder import PromptBuilder
from parlant.core.guidelines import Guideline
from parlant.core.journeys import Journey
from parlant.core.loggers import Logger
from parlant.core.nlp.generation import SchematicGenerator
from parlant.core.services.indexing.common import EvaluationError, ProgressReport
from parlant.core.services.tools.service_registry import ServiceRegistry
from parlant.core.shots import Shot, ShotCollection


class RewrittenActionResult(DefaultBaseModel):
    index: str
    rewritten_actions: str


class RelativeActionProposition(DefaultBaseModel):
    actions: Sequence[RewrittenActionResult]


class RelativeActionBatch(DefaultBaseModel):
    index: str
    conditions: Sequence[str] | None = None
    action: str
    needs_rewrite_rational: str
    needs_rewrite: bool
    former_reference: Optional[str] = None
    rewritten_action: Optional[str] = None


class RelativeActionSchema(DefaultBaseModel):
    actions: Sequence[RelativeActionBatch]


@dataclass
class RelativeActionShot(Shot):
    journey_title: str
    journey_steps: dict[str, _JourneyNode]
    expected_result: RelativeActionSchema


class RelativeActionProposer:
    def __init__(
        self,
        logger: Logger,
        optimization_policy: OptimizationPolicy,
        schematic_generator: SchematicGenerator[RelativeActionSchema],
        service_registry: ServiceRegistry,