fix(agent): skip empty switch conditions (#15691)

## What
- make `Switch` ignore conditions that have no evaluable items
- add a regression for blank `cpn_id` items falling through to the else
branch
- keep the existing non-empty `and` condition behavior covered

Fixes #15643.

## Verified
- `python -m py_compile agent\component\switch.py
test\unit_test\agent\component\test_switch.py`
- `python -m pytest test\unit_test\agent\component\test_switch.py -q` ->
`2 passed`
- `python -m ruff check agent\component\switch.py
test\unit_test\agent\component\test_switch.py`
- `git diff --check`

I also checked `python -m ruff format --check` on the touched files. It
would reformat pre-existing style in `agent/component/switch.py` beyond
this bug fix, so I kept the patch scoped instead of reformatting the
whole file.
This commit is contained in:
Yufeng He
2026-06-05 17:20:44 +08:00
committed by GitHub
parent aab01af6f2
commit 6cba5a544a
2 changed files with 60 additions and 1 deletions

View File

@@ -88,7 +88,7 @@ class Switch(ComponentBase, ABC):
self.set_output("_next", cond["to"])
return
if all(res):
if res and all(res):
self.set_output("next", [self._canvas.get_component_name(cpn_id) for cpn_id in cond["to"]])
self.set_output("_next", cond["to"])
return

View File

@@ -0,0 +1,59 @@
from agent.component.switch import Switch, SwitchParam
class _Canvas:
def __init__(self, variables=None):
self.variables = variables or {}
def is_canceled(self):
return False
def get_variable_value(self, cpn_id):
return self.variables[cpn_id]
def get_component_name(self, cpn_id):
return cpn_id
def _switch(param, variables=None):
cpn = Switch.__new__(Switch)
cpn._canvas = _Canvas(variables)
cpn._id = "switch"
cpn._param = param
return cpn
def test_switch_empty_condition_falls_through_to_else():
param = SwitchParam()
param.conditions = [
{
"logical_operator": "and",
"items": [{"cpn_id": "", "operator": "=", "value": "yes"}],
"to": ["case_target"],
}
]
param.end_cpn_ids = ["else_target"]
cpn = _switch(param)
cpn._invoke()
assert cpn.output("_next") == ["else_target"]
assert cpn.output("next") == ["else_target"]
def test_switch_non_empty_and_condition_still_matches():
param = SwitchParam()
param.conditions = [
{
"logical_operator": "and",
"items": [{"cpn_id": "answer", "operator": "=", "value": "yes"}],
"to": ["case_target"],
}
]
param.end_cpn_ids = ["else_target"]
cpn = _switch(param, {"answer": "yes"})
cpn._invoke()
assert cpn.output("_next") == ["case_target"]
assert cpn.output("next") == ["case_target"]