Skip to content

Commit 66ae6b9

Browse files
mjnoviceclaude
andcommitted
refactor: remove dummy eval item from debug simulation
Now that mocking is decoupled from evals (PR #1148), update the debug command to use MockingContext directly instead of creating a dummy EvaluationItem. This simplifies the code and better reflects the separation of concerns. Changes: - Update load_simulation_config to return MockingContext instead of EvaluationItem - Replace EvaluationSimulationTool with ToolSimulation - Update all tests to work with MockingContext - Remove unnecessary evaluation_criterias field Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
1 parent f4480e1 commit 66ae6b9

File tree

2 files changed

+42
-52
lines changed

2 files changed

+42
-52
lines changed

src/uipath/_cli/cli_debug.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@
1717

1818
from uipath._cli._chat._bridge import get_chat_bridge
1919
from uipath._cli._debug._bridge import get_debug_bridge
20-
from uipath._cli._evals._models._evaluation_set import (
21-
EvaluationItem,
22-
EvaluationSimulationTool,
23-
LLMMockingStrategy,
24-
MockingStrategyType,
25-
)
2620
from uipath._cli._evals._span_collection import ExecutionSpanCollector
2721
from uipath._cli._evals.mocks.mocks import (
2822
clear_execution_context,
2923
set_execution_context,
3024
)
25+
from uipath._cli._evals.mocks.types import (
26+
LLMMockingStrategy,
27+
MockingContext,
28+
MockingStrategyType,
29+
ToolSimulation,
30+
)
3131
from uipath._cli._utils._debug import setup_debugging
3232
from uipath._cli._utils._studio_project import StudioClient
3333
from uipath._utils._bindings import ResourceOverwritesContext
@@ -40,11 +40,11 @@
4040
console = ConsoleLogger()
4141

4242

43-
def load_simulation_config() -> EvaluationItem | None:
44-
"""Load simulation.json from current directory and convert to EvaluationItem.
43+
def load_simulation_config() -> MockingContext | None:
44+
"""Load simulation.json from current directory and convert to MockingContext.
4545
4646
Returns:
47-
EvaluationItem with LLM mocking strategy if simulation.json exists and is valid,
47+
MockingContext with LLM mocking strategy if simulation.json exists and is valid,
4848
None otherwise.
4949
"""
5050
simulation_path = Path.cwd() / "simulation.json"
@@ -62,7 +62,7 @@ def load_simulation_config() -> EvaluationItem | None:
6262

6363
# Extract tools to simulate
6464
tools_to_simulate = [
65-
EvaluationSimulationTool(name=tool["name"])
65+
ToolSimulation(name=tool["name"])
6666
for tool in simulation_data.get("toolsToSimulate", [])
6767
]
6868

@@ -76,18 +76,15 @@ def load_simulation_config() -> EvaluationItem | None:
7676
tools_to_simulate=tools_to_simulate,
7777
)
7878

79-
# Create a minimal EvaluationItem for debugging
80-
# We use empty inputs since the actual input comes from the debug command
81-
eval_item = EvaluationItem(
82-
id=str(uuid.uuid4()),
79+
# Create MockingContext for debugging
80+
mocking_context = MockingContext(
81+
strategy=mocking_strategy,
8382
name="debug-simulation",
8483
inputs={},
85-
evaluation_criterias={},
86-
mocking_strategy=mocking_strategy,
8784
)
8885

8986
console.info(f"Loaded simulation config for {len(tools_to_simulate)} tool(s)")
90-
return eval_item
87+
return mocking_context
9188

9289
except Exception as e:
9390
console.warning(f"Failed to load simulation.json: {e}")
@@ -183,15 +180,15 @@ async def execute_debug_runtime():
183180
factory: UiPathRuntimeFactoryProtocol | None = None
184181

185182
# Load simulation config and set up execution context for tool mocking
186-
eval_item = load_simulation_config()
183+
mocking_ctx = load_simulation_config()
187184
span_collector: ExecutionSpanCollector | None = None
188185
execution_id = str(uuid.uuid4())
189186

190-
if eval_item:
187+
if mocking_ctx:
191188
# Create span collector for trace access during mocking
192189
span_collector = ExecutionSpanCollector()
193190
# Set execution context to enable tool simulation
194-
set_execution_context(eval_item, span_collector, execution_id)
191+
set_execution_context(mocking_ctx, span_collector, execution_id)
195192

196193
try:
197194
trigger_poll_interval: float = 5.0
@@ -243,7 +240,7 @@ async def execute_debug_runtime():
243240

244241
finally:
245242
# Clear execution context after debugging completes
246-
if eval_item:
243+
if mocking_ctx:
247244
clear_execution_context()
248245

249246
if debug_runtime:

tests/cli/test_debug_simulation.py

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
from click.testing import CliRunner
1010

1111
from uipath._cli import cli
12-
from uipath._cli._evals._models._evaluation_set import (
13-
EvaluationItem,
14-
LLMMockingStrategy,
15-
)
1612
from uipath._cli._evals.mocks.mocks import (
1713
clear_execution_context,
1814
is_tool_simulated,
1915
)
16+
from uipath._cli._evals.mocks.types import (
17+
LLMMockingStrategy,
18+
MockingContext,
19+
)
2020
from uipath._cli.cli_debug import load_simulation_config
2121
from uipath._cli.middlewares import MiddlewareResult
2222

@@ -78,16 +78,13 @@ def test_loads_valid_simulation_config(
7878
result = load_simulation_config()
7979

8080
assert result is not None
81-
assert isinstance(result, EvaluationItem)
81+
assert isinstance(result, MockingContext)
8282
assert result.name == "debug-simulation"
83-
assert result.mocking_strategy is not None
84-
assert isinstance(result.mocking_strategy, LLMMockingStrategy)
85-
assert (
86-
result.mocking_strategy.prompt
87-
== valid_simulation_config["instructions"]
88-
)
89-
assert len(result.mocking_strategy.tools_to_simulate) == 3
90-
assert result.mocking_strategy.tools_to_simulate[0].name == "Web Reader"
83+
assert result.strategy is not None
84+
assert isinstance(result.strategy, LLMMockingStrategy)
85+
assert result.strategy.prompt == valid_simulation_config["instructions"]
86+
assert len(result.strategy.tools_to_simulate) == 3
87+
assert result.strategy.tools_to_simulate[0].name == "Web Reader"
9188

9289
def test_returns_none_when_disabled(
9390
self, temp_dir: str, disabled_simulation_config: dict[str, Any]
@@ -134,10 +131,10 @@ def test_handles_missing_required_fields(self, temp_dir: str):
134131
# Should return None because toolsToSimulate is missing/empty
135132
assert result is None
136133

137-
def test_creates_evaluation_item_with_empty_inputs(
134+
def test_creates_mocking_context_with_empty_inputs(
138135
self, temp_dir: str, valid_simulation_config: dict[str, Any]
139136
):
140-
"""Test that EvaluationItem is created with empty inputs."""
137+
"""Test that MockingContext is created with empty inputs."""
141138
simulation_path = Path(temp_dir) / "simulation.json"
142139
with open(simulation_path, "w", encoding="utf-8") as f:
143140
json.dump(valid_simulation_config, f)
@@ -147,7 +144,6 @@ def test_creates_evaluation_item_with_empty_inputs(
147144

148145
assert result is not None
149146
assert result.inputs == {}
150-
assert result.evaluation_criterias == {}
151147

152148
def test_uses_default_empty_instructions_when_missing(self, temp_dir: str):
153149
"""Test that empty string is used when instructions field is missing."""
@@ -163,7 +159,7 @@ def test_uses_default_empty_instructions_when_missing(self, temp_dir: str):
163159
result = load_simulation_config()
164160

165161
assert result is not None
166-
assert result.mocking_strategy.prompt == ""
162+
assert result.strategy.prompt == ""
167163

168164

169165
class TestDebugCommandSimulationIntegration:
@@ -287,16 +283,13 @@ def main(input):
287283

288284
# Verify set_execution_context was called
289285
assert mock_set_context.called
290-
# Verify the EvaluationItem passed has the right structure
286+
# Verify the MockingContext passed has the right structure
291287
call_args = mock_set_context.call_args
292-
eval_item = call_args[0][0]
293-
assert isinstance(eval_item, EvaluationItem)
294-
assert eval_item.mocking_strategy is not None
288+
mocking_ctx = call_args[0][0]
289+
assert isinstance(mocking_ctx, MockingContext)
290+
assert mocking_ctx.strategy is not None
295291
assert (
296-
len(
297-
eval_item.mocking_strategy.tools_to_simulate
298-
)
299-
== 3
292+
len(mocking_ctx.strategy.tools_to_simulate) == 3
300293
)
301294

302295
# Verify clear_execution_context was called in finally block
@@ -348,16 +341,16 @@ def test_simulation_config_enables_tool_mocking(
348341
json.dump(valid_simulation_config, f)
349342

350343
with patch("pathlib.Path.cwd", return_value=Path(temp_dir)):
351-
eval_item = load_simulation_config()
352-
assert eval_item is not None
344+
mocking_ctx = load_simulation_config()
345+
assert mocking_ctx is not None
353346

354347
# Manually set context (simulating what debug command does)
355348
from uipath._cli._evals._span_collection import ExecutionSpanCollector
356349

357350
span_collector = ExecutionSpanCollector()
358351
from uipath._cli._evals.mocks.mocks import set_execution_context
359352

360-
set_execution_context(eval_item, span_collector, "test-execution-id")
353+
set_execution_context(mocking_ctx, span_collector, "test-execution-id")
361354

362355
# Verify tools are detected as simulated
363356
assert is_tool_simulated("Web Reader") is True
@@ -438,15 +431,15 @@ def test_handles_tool_name_normalization(self, temp_dir: str):
438431
json.dump(config, f)
439432

440433
with patch("pathlib.Path.cwd", return_value=Path(temp_dir)):
441-
eval_item = load_simulation_config()
442-
assert eval_item is not None
434+
mocking_ctx = load_simulation_config()
435+
assert mocking_ctx is not None
443436

444437
# Set context to test name normalization
445438
from uipath._cli._evals._span_collection import ExecutionSpanCollector
446439
from uipath._cli._evals.mocks.mocks import set_execution_context
447440

448441
span_collector = ExecutionSpanCollector()
449-
set_execution_context(eval_item, span_collector, "test-id")
442+
set_execution_context(mocking_ctx, span_collector, "test-id")
450443

451444
# Both underscore and space versions should be detected
452445
assert is_tool_simulated("Web_Reader") is True

0 commit comments

Comments
 (0)