Execute a list of steps sequentially.
(
self,
steps: list[dict[str, Any]],
context: StepContext,
state: RunState,
registry: dict[str, Any],
*,
step_offset: int = 0,
)
| 794 | state.record_step_result(step_id, data) |
| 795 | |
| 796 | def _execute_steps( |
| 797 | self, |
| 798 | steps: list[dict[str, Any]], |
| 799 | context: StepContext, |
| 800 | state: RunState, |
| 801 | registry: dict[str, Any], |
| 802 | *, |
| 803 | step_offset: int = 0, |
| 804 | ) -> None: |
| 805 | """Execute a list of steps sequentially.""" |
| 806 | for i, step_config in enumerate(steps): |
| 807 | step_id = step_config.get("id", f"step-{i}") |
| 808 | step_type = step_config.get("type", "command") |
| 809 | |
| 810 | state.current_step_id = step_id |
| 811 | if step_offset >= 0: |
| 812 | state.current_step_index = step_offset + i |
| 813 | state.save() |
| 814 | |
| 815 | state.append_log( |
| 816 | {"event": "step_started", "step_id": step_id, "type": step_type} |
| 817 | ) |
| 818 | |
| 819 | # Log progress — use the engine's on_step_start callback if set, |
| 820 | # otherwise stay silent (library-safe default). |
| 821 | label = step_config.get("command", "") or step_type |
| 822 | if self.on_step_start is not None: |
| 823 | with self._callback_lock: |
| 824 | self.on_step_start(step_id, label) |
| 825 | |
| 826 | step_impl = registry.get(step_type) |
| 827 | if not step_impl: |
| 828 | state.status = RunStatus.FAILED |
| 829 | state.append_log( |
| 830 | { |
| 831 | "event": "step_failed", |
| 832 | "step_id": step_id, |
| 833 | "error": f"Unknown step type: {step_type!r}", |
| 834 | } |
| 835 | ) |
| 836 | state.save() |
| 837 | return |
| 838 | |
| 839 | result: StepResult = step_impl.execute(step_config, context) |
| 840 | |
| 841 | # Record step results — prefer resolved values from step output |
| 842 | step_data = { |
| 843 | "type": step_type, |
| 844 | "integration": result.output.get("integration") |
| 845 | or step_config.get("integration") |
| 846 | or context.default_integration, |
| 847 | "model": result.output.get("model") |
| 848 | or step_config.get("model") |
| 849 | or context.default_model, |
| 850 | "options": result.output.get("options") |
| 851 | or step_config.get("options", {}), |
| 852 | "input": result.output.get("input") |
| 853 | or step_config.get("input", {}), |
no test coverage detected