fix(cli): force flow events on for the TUI so STEPS renders under suppress_flow_events

Review follow-up: the STEPS panel and header are driven by flow method events
(FlowStarted / MethodExecution*), but the declarative runtime skips emitting
those when the flow declared config.suppress_flow_events. Interactive TUI runs
would then keep STEPS on "waiting…" and the header on "Starting flow…" while
nested crews still execute.

_run_declarative_flow_tui now forces flow.suppress_flow_events = False for the
interactive run (mirroring how the conversational path mutates the flow for the
TUI). The headless/terminal path never reaches this and keeps the flow's
declared setting. Regression test: test_run_declarative_flow_tui_enables_flow_events.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBYGqJHC2TMC6fonFziuuh
This commit is contained in:
Joao Moura
2026-07-08 07:36:41 -07:00
parent 260f85e1b4
commit 6b7529f2d9
2 changed files with 23 additions and 0 deletions

View File

@@ -102,6 +102,16 @@ def _run_declarative_flow_tui(flow: Any, resolved_inputs: dict[str, Any] | None)
# listener, and the TUI's trace/telemetry features depend on it.
EventListener()
# The STEPS panel and header are driven by flow method events. A flow may
# declare ``config.suppress_flow_events`` (a headless/production
# optimization) which would leave STEPS stuck on "waiting…" here — so force
# emission on for the interactive TUI run. The headless path never reaches
# this and keeps the flow's declared setting.
try:
flow.suppress_flow_events = False
except Exception: # noqa: S110
pass
app = CrewRunApp(crew_name=getattr(flow, "name", None) or type(flow).__name__)
app._flow = flow
app._flow_inputs = resolved_inputs

View File

@@ -540,6 +540,19 @@ def test_run_declarative_flow_tui_no_deploy_when_not_requested(
assert deploy_calls == []
def test_run_declarative_flow_tui_enables_flow_events(
monkeypatch: pytest.MonkeyPatch,
) -> None:
# The STEPS panel depends on flow method events; a flow that declared
# suppress_flow_events must have it forced off for the interactive TUI run.
_install_fake_flow_app(monkeypatch, status="completed")
flow = SimpleNamespace(name="Flow", suppress_flow_events=True)
run_declarative_flow_module._run_declarative_flow_tui(flow, None)
assert flow.suppress_flow_events is False
def test_flow_method_types_from_definition() -> None:
flow = SimpleNamespace(
_definition=SimpleNamespace(