|
1 | 1 | import asyncio |
| 2 | +import json |
| 3 | +import uuid |
| 4 | +from pathlib import Path |
2 | 5 |
|
3 | 6 | import click |
4 | 7 | from uipath.core.tracing import UiPathTraceManager |
|
14 | 17 |
|
15 | 18 | from uipath._cli._chat._bridge import get_chat_bridge |
16 | 19 | from uipath._cli._debug._bridge import get_debug_bridge |
| 20 | +from uipath._cli._evals._span_collection import ExecutionSpanCollector |
| 21 | +from uipath._cli._evals.mocks.mocks import ( |
| 22 | + clear_execution_context, |
| 23 | + set_execution_context, |
| 24 | +) |
| 25 | +from uipath._cli._evals.mocks.types import ( |
| 26 | + LLMMockingStrategy, |
| 27 | + MockingContext, |
| 28 | + MockingStrategyType, |
| 29 | + ToolSimulation, |
| 30 | +) |
17 | 31 | from uipath._cli._utils._debug import setup_debugging |
18 | 32 | from uipath._cli._utils._studio_project import StudioClient |
19 | 33 | from uipath._utils._bindings import ResourceOverwritesContext |
|
26 | 40 | console = ConsoleLogger() |
27 | 41 |
|
28 | 42 |
|
| 43 | +def load_simulation_config() -> MockingContext | None: |
| 44 | + """Load simulation.json from current directory and convert to MockingContext. |
| 45 | +
|
| 46 | + Returns: |
| 47 | + MockingContext with LLM mocking strategy if simulation.json exists and is valid, |
| 48 | + None otherwise. |
| 49 | + """ |
| 50 | + simulation_path = Path.cwd() / "simulation.json" |
| 51 | + |
| 52 | + if not simulation_path.exists(): |
| 53 | + return None |
| 54 | + |
| 55 | + try: |
| 56 | + with open(simulation_path, "r", encoding="utf-8") as f: |
| 57 | + simulation_data = json.load(f) |
| 58 | + |
| 59 | + # Check if simulation is enabled |
| 60 | + if not simulation_data.get("enabled", True): |
| 61 | + return None |
| 62 | + |
| 63 | + # Extract tools to simulate |
| 64 | + tools_to_simulate = [ |
| 65 | + ToolSimulation(name=tool["name"]) |
| 66 | + for tool in simulation_data.get("toolsToSimulate", []) |
| 67 | + ] |
| 68 | + |
| 69 | + if not tools_to_simulate: |
| 70 | + return None |
| 71 | + |
| 72 | + # Create LLM mocking strategy |
| 73 | + mocking_strategy = LLMMockingStrategy( |
| 74 | + type=MockingStrategyType.LLM, |
| 75 | + prompt=simulation_data.get("instructions", ""), |
| 76 | + tools_to_simulate=tools_to_simulate, |
| 77 | + ) |
| 78 | + |
| 79 | + # Create MockingContext for debugging |
| 80 | + mocking_context = MockingContext( |
| 81 | + strategy=mocking_strategy, |
| 82 | + name="debug-simulation", |
| 83 | + inputs={}, |
| 84 | + ) |
| 85 | + |
| 86 | + console.info(f"Loaded simulation config for {len(tools_to_simulate)} tool(s)") |
| 87 | + return mocking_context |
| 88 | + |
| 89 | + except Exception as e: |
| 90 | + console.warning(f"Failed to load simulation.json: {e}") |
| 91 | + return None |
| 92 | + |
| 93 | + |
29 | 94 | @click.command() |
30 | 95 | @click.argument("entrypoint", required=False) |
31 | 96 | @click.argument("input", required=False, default=None) |
@@ -114,6 +179,17 @@ async def execute_debug_runtime(): |
114 | 179 | debug_runtime: UiPathRuntimeProtocol | None = None |
115 | 180 | factory: UiPathRuntimeFactoryProtocol | None = None |
116 | 181 |
|
| 182 | + # Load simulation config and set up execution context for tool mocking |
| 183 | + mocking_ctx = load_simulation_config() |
| 184 | + span_collector: ExecutionSpanCollector | None = None |
| 185 | + execution_id = str(uuid.uuid4()) |
| 186 | + |
| 187 | + if mocking_ctx: |
| 188 | + # Create span collector for trace access during mocking |
| 189 | + span_collector = ExecutionSpanCollector() |
| 190 | + # Set execution context to enable tool simulation |
| 191 | + set_execution_context(mocking_ctx, span_collector, execution_id) |
| 192 | + |
117 | 193 | try: |
118 | 194 | trigger_poll_interval: float = 5.0 |
119 | 195 |
|
@@ -163,6 +239,10 @@ async def execute_debug_runtime(): |
163 | 239 | ) |
164 | 240 |
|
165 | 241 | finally: |
| 242 | + # Clear execution context after debugging completes |
| 243 | + if mocking_ctx: |
| 244 | + clear_execution_context() |
| 245 | + |
166 | 246 | if debug_runtime: |
167 | 247 | await debug_runtime.dispose() |
168 | 248 | if chat_runtime: |
|
0 commit comments