uipath 2.1.44__py3-none-any.whl → 2.1.46__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,3 @@
1
- import copy
2
1
  from collections import defaultdict
3
2
  from time import time
4
3
  from typing import Dict, Generic, List, Optional, Sequence, TypeVar
@@ -6,8 +5,6 @@ from typing import Dict, Generic, List, Optional, Sequence, TypeVar
6
5
  from opentelemetry.sdk.trace import ReadableSpan
7
6
  from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
8
7
 
9
- from uipath.eval._helpers import auto_discover_entrypoint
10
-
11
8
  from .._runtime._contracts import (
12
9
  UiPathBaseRuntime,
13
10
  UiPathRuntimeContext,
@@ -54,49 +51,21 @@ class ExecutionSpanExporter(SpanExporter):
54
51
  self.clear()
55
52
 
56
53
 
57
- class UiPathEvalContext(UiPathRuntimeContext, Generic[C]):
54
+ class UiPathEvalContext(UiPathRuntimeContext):
58
55
  """Context used for evaluation runs."""
59
56
 
60
- runtime_context: C
61
- no_report: bool
62
- workers: int
57
+ no_report: Optional[bool] = False
58
+ workers: Optional[int] = 1
63
59
  eval_set: Optional[str] = None
64
60
  eval_ids: Optional[List[str]] = None
65
61
 
66
- def __init__(
67
- self,
68
- runtime_context: C,
69
- no_report: bool,
70
- workers: int,
71
- eval_set: Optional[str] = None,
72
- eval_ids: Optional[List[str]] = None,
73
- **kwargs,
74
- ):
75
- super().__init__(
76
- runtime_context=runtime_context, # type: ignore
77
- no_report=no_report,
78
- workers=workers,
79
- eval_set=eval_set,
80
- eval_ids=eval_ids,
81
- **kwargs,
82
- )
83
- self._auto_discover()
84
-
85
- def _auto_discover(self):
86
- self.runtime_context.entrypoint = (
87
- self.runtime_context.entrypoint or auto_discover_entrypoint()
88
- )
89
- self.eval_set = self.eval_set or EvalHelpers.auto_discover_eval_set()
90
-
91
62
 
92
63
  class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
93
64
  """Specialized runtime for evaluation runs, with access to the factory."""
94
65
 
95
- def __init__(
96
- self, context: "UiPathEvalContext[C]", factory: "UiPathRuntimeFactory[T, C]"
97
- ):
66
+ def __init__(self, context: UiPathEvalContext, factory: UiPathRuntimeFactory[T, C]):
98
67
  super().__init__(context)
99
- self.context: "UiPathEvalContext[C]" = context
68
+ self.context: UiPathEvalContext = context
100
69
  self.factory: UiPathRuntimeFactory[T, C] = factory
101
70
  self.span_exporter: ExecutionSpanExporter = ExecutionSpanExporter()
102
71
  self.factory.add_span_exporter(self.span_exporter)
@@ -104,8 +73,8 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
104
73
  @classmethod
105
74
  def from_eval_context(
106
75
  cls,
107
- context: "UiPathEvalContext[C]",
108
- factory: "UiPathRuntimeFactory[T, C]",
76
+ context: UiPathEvalContext,
77
+ factory: UiPathRuntimeFactory[T, C],
109
78
  ) -> "UiPathEvalRuntime[T, C]":
110
79
  return cls(context, factory)
111
80
 
@@ -119,30 +88,26 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
119
88
  )
120
89
  execution_output_list: list[UiPathEvalRunExecutionOutput] = []
121
90
  for eval_item in evaluation_set.evaluations:
122
- execution_output_list.append(await self.execute_agent(eval_item))
91
+ execution_output = await self.execute_runtime(eval_item)
92
+ execution_output_list.append(execution_output)
123
93
 
124
94
  self.context.result = UiPathRuntimeResult(
125
95
  output={
126
96
  "results": execution_output_list,
127
97
  },
128
98
  status=UiPathRuntimeStatus.SUCCESSFUL,
129
- resume=None,
130
99
  )
131
100
 
132
- return self.context.runtime_context.result
133
-
134
- def _prepare_new_runtime_context(self, eval_item: EvaluationItem) -> C:
135
- runtime_context = copy.deepcopy(self.context.runtime_context)
136
- runtime_context.execution_id = eval_item.id
137
- runtime_context.input_json = eval_item.inputs
138
- # here we can pass other values from eval_item: expectedAgentBehavior, simulationInstructions etc.
139
- return runtime_context
101
+ return self.context.result
140
102
 
141
- # TODO: this would most likely need to be ported to a public AgentEvaluator class
142
- async def execute_agent(
103
+ async def execute_runtime(
143
104
  self, eval_item: EvaluationItem
144
- ) -> "UiPathEvalRunExecutionOutput":
145
- runtime_context = self._prepare_new_runtime_context(eval_item)
105
+ ) -> UiPathEvalRunExecutionOutput:
106
+ runtime_context: C = self.factory.new_context(
107
+ execution_id=eval_item.id,
108
+ input_json=eval_item.inputs,
109
+ is_eval_run=True,
110
+ )
146
111
  start_time = time()
147
112
  result = await self.factory.execute_in_root_span(
148
113
  runtime_context, root_span=eval_item.name
@@ -30,6 +30,9 @@ from ._logging import LogsInterceptor
30
30
 
31
31
  logger = logging.getLogger(__name__)
32
32
 
33
+ T = TypeVar("T", bound="UiPathBaseRuntime")
34
+ C = TypeVar("C", bound="UiPathRuntimeContext")
35
+
33
36
 
34
37
  class UiPathResumeTriggerType(str, Enum):
35
38
  """Constants representing different types of resume job triggers in the system."""
@@ -315,21 +318,48 @@ class UiPathRuntimeContext(BaseModel):
315
318
  model_config = {"arbitrary_types_allowed": True}
316
319
 
317
320
  @classmethod
318
- def from_config(cls, config_path=None, **kwargs):
319
- """Load configuration from uipath.json file.
321
+ def with_defaults(cls: type[C], config_path: Optional[str] = None, **kwargs) -> C:
322
+ """Construct a context with defaults, reading env vars and config file."""
323
+ resolved_config_path = config_path or os.environ.get(
324
+ "UIPATH_CONFIG_PATH", "uipath.json"
325
+ )
320
326
 
321
- Args:
322
- config_path: Path to the configuration file. If None, uses the default "uipath.json"
323
- **kwargs: Additional keyword arguments to use as fallback for configuration values
327
+ base = cls.from_config(resolved_config_path)
328
+
329
+ bool_map = {"true": True, "false": False}
330
+ tracing_enabled = os.environ.get("UIPATH_TRACING_ENABLED", True)
331
+ if isinstance(tracing_enabled, str) and tracing_enabled.lower() in bool_map:
332
+ tracing_enabled = bool_map[tracing_enabled.lower()]
333
+
334
+ # Apply defaults from env
335
+ base.job_id = os.environ.get("UIPATH_JOB_KEY")
336
+ base.trace_id = os.environ.get("UIPATH_TRACE_ID")
337
+ base.tracing_enabled = tracing_enabled
338
+ base.logs_min_level = os.environ.get("LOG_LEVEL", "INFO")
339
+
340
+ base.trace_context = UiPathTraceContext(
341
+ trace_id=os.environ.get("UIPATH_TRACE_ID"),
342
+ parent_span_id=os.environ.get("UIPATH_PARENT_SPAN_ID"),
343
+ root_span_id=os.environ.get("UIPATH_ROOT_SPAN_ID"),
344
+ enabled=tracing_enabled,
345
+ job_id=os.environ.get("UIPATH_JOB_KEY"),
346
+ org_id=os.environ.get("UIPATH_ORGANIZATION_ID"),
347
+ tenant_id=os.environ.get("UIPATH_TENANT_ID"),
348
+ process_key=os.environ.get("UIPATH_PROCESS_UUID"),
349
+ folder_key=os.environ.get("UIPATH_FOLDER_KEY"),
350
+ reference_id=os.environ.get("UIPATH_JOB_KEY") or str(uuid4()),
351
+ )
324
352
 
325
- Returns:
326
- An instance of the class with fields populated from the config file
327
- """
328
- import json
329
- import os
353
+ # Override with kwargs
354
+ for k, v in kwargs.items():
355
+ setattr(base, k, v)
330
356
 
331
- path = config_path or "uipath.json"
357
+ return base
332
358
 
359
+ @classmethod
360
+ def from_config(cls: type[C], config_path: Optional[str] = None, **kwargs) -> C:
361
+ """Load configuration from uipath.json file."""
362
+ path = config_path or "uipath.json"
333
363
  config = {}
334
364
 
335
365
  if os.path.exists(path):
@@ -346,7 +376,6 @@ class UiPathRuntimeContext(BaseModel):
346
376
  }
347
377
 
348
378
  attributes_set = set()
349
- # set values from config file if available
350
379
  if "runtime" in config:
351
380
  runtime_config = config["runtime"]
352
381
  for config_key, attr_name in mapping.items():
@@ -354,10 +383,8 @@ class UiPathRuntimeContext(BaseModel):
354
383
  attributes_set.add(attr_name)
355
384
  setattr(instance, attr_name, runtime_config[config_key])
356
385
 
357
- # fallback to kwargs for any values not set from config file
358
386
  for _, attr_name in mapping.items():
359
387
  if attr_name in kwargs and hasattr(instance, attr_name):
360
- # Only set from kwargs if not already set from config file
361
388
  if attr_name not in attributes_set:
362
389
  setattr(instance, attr_name, kwargs[attr_name])
363
390
 
@@ -383,7 +410,7 @@ class UiPathRuntimeError(Exception):
383
410
  if (
384
411
  tb and tb.strip() != "NoneType: None"
385
412
  ): # Ensure there's an actual traceback
386
- detail = f"{detail}\n\nTraceback:\n{tb}"
413
+ detail = f"{detail}\n\n{tb}"
387
414
 
388
415
  if status is None:
389
416
  status = self._extract_http_status()
@@ -473,6 +500,21 @@ class UiPathBaseRuntime(ABC):
473
500
  with open(self.context.input_file) as f:
474
501
  self.context.input = f.read()
475
502
 
503
+ try:
504
+ if self.context.input:
505
+ self.context.input_json = json.loads(self.context.input)
506
+ if self.context.input_json is None:
507
+ self.context.input_json = {}
508
+ except json.JSONDecodeError as e:
509
+ raise UiPathRuntimeError(
510
+ "INPUT_INVALID_JSON",
511
+ "Invalid JSON input",
512
+ f"The input data is not valid JSON: {str(e)}",
513
+ UiPathErrorCategory.USER,
514
+ ) from e
515
+
516
+ await self.validate()
517
+
476
518
  # Intercept all stdout/stderr/logs and write them to a file (runtime/evals), stdout (debug)
477
519
  self.logs_interceptor = LogsInterceptor(
478
520
  min_level=self.context.logs_min_level,
@@ -620,14 +662,16 @@ class UiPathBaseRuntime(ABC):
620
662
  return os.path.join("__uipath", "state.db")
621
663
 
622
664
 
623
- T = TypeVar("T", bound=UiPathBaseRuntime)
624
- C = TypeVar("C", bound=UiPathRuntimeContext)
625
-
626
-
627
665
  class UiPathRuntimeFactory(Generic[T, C]):
628
666
  """Generic factory for UiPath runtime classes."""
629
667
 
630
- def __init__(self, runtime_class: Type[T], context_class: Type[C]):
668
+ def __init__(
669
+ self,
670
+ runtime_class: Type[T],
671
+ context_class: Type[C],
672
+ runtime_generator: Optional[Callable[[C], T]] = None,
673
+ context_generator: Optional[Callable[..., C]] = None,
674
+ ):
631
675
  if not issubclass(runtime_class, UiPathBaseRuntime):
632
676
  raise TypeError(
633
677
  f"runtime_class {runtime_class.__name__} must inherit from UiPathBaseRuntime"
@@ -640,10 +684,11 @@ class UiPathRuntimeFactory(Generic[T, C]):
640
684
 
641
685
  self.runtime_class = runtime_class
642
686
  self.context_class = context_class
687
+ self.runtime_generator = runtime_generator
688
+ self.context_generator = context_generator
643
689
  self.tracer_provider: TracerProvider = TracerProvider()
644
690
  self.tracer_span_processors: List[SpanProcessor] = []
645
691
  trace.set_tracer_provider(self.tracer_provider)
646
-
647
692
  if os.getenv("UIPATH_JOB_KEY"):
648
693
  self.add_span_exporter(LlmOpsHttpExporter())
649
694
 
@@ -674,36 +719,49 @@ class UiPathRuntimeFactory(Generic[T, C]):
674
719
 
675
720
  def new_context(self, **kwargs) -> C:
676
721
  """Create a new context instance."""
722
+ if self.context_generator:
723
+ return self.context_generator(**kwargs)
677
724
  return self.context_class(**kwargs)
678
725
 
726
+ def new_runtime(self) -> T:
727
+ """Create a new runtime instance."""
728
+ context = self.new_context()
729
+ if self.runtime_generator:
730
+ return self.runtime_generator(context)
731
+ return self.runtime_class.from_context(context)
732
+
679
733
  def from_context(self, context: C) -> T:
680
734
  """Create runtime instance from context."""
735
+ if self.runtime_generator:
736
+ return self.runtime_generator(context)
681
737
  return self.runtime_class.from_context(context)
682
738
 
683
739
  async def execute(self, context: C) -> Optional[UiPathRuntimeResult]:
684
740
  """Execute runtime with context."""
685
741
  async with self.from_context(context) as runtime:
686
- result = await runtime.execute()
687
- for span_processor in self.tracer_span_processors:
688
- span_processor.force_flush()
689
- return result
742
+ try:
743
+ return await runtime.execute()
744
+ finally:
745
+ for span_processor in self.tracer_span_processors:
746
+ span_processor.force_flush()
690
747
 
691
748
  async def execute_in_root_span(
692
749
  self, context: C, root_span: str = "root"
693
750
  ) -> Optional[UiPathRuntimeResult]:
694
751
  """Execute runtime with context."""
695
752
  async with self.from_context(context) as runtime:
696
- tracer: Tracer = trace.get_tracer("uipath-runtime")
697
- with tracer.start_as_current_span(
698
- root_span,
699
- attributes={"execution.id": context.execution_id}
700
- if context.execution_id
701
- else {},
702
- ):
703
- result = await runtime.execute()
704
- for span_processor in self.tracer_span_processors:
705
- span_processor.force_flush()
706
- return result
753
+ try:
754
+ tracer: Tracer = trace.get_tracer("uipath-runtime")
755
+ with tracer.start_as_current_span(
756
+ root_span,
757
+ attributes={"execution.id": context.execution_id}
758
+ if context.execution_id
759
+ else {},
760
+ ):
761
+ return await runtime.execute()
762
+ finally:
763
+ for span_processor in self.tracer_span_processors:
764
+ span_processor.force_flush()
707
765
 
708
766
 
709
767
  class UiPathExecutionTraceProcessorMixin:
@@ -1,30 +1,37 @@
1
1
  """Python script runtime implementation for executing and managing python scripts."""
2
2
 
3
- import importlib.util
4
- import inspect
5
- import json
6
3
  import logging
7
- import os
8
- from dataclasses import asdict, is_dataclass
9
- from typing import Any, Dict, Optional, Type, TypeVar, cast, get_type_hints
10
-
11
- from pydantic import BaseModel
4
+ from typing import Any, Awaitable, Callable, Optional, TypeVar
12
5
 
13
6
  from ._contracts import (
14
7
  UiPathBaseRuntime,
15
8
  UiPathErrorCategory,
9
+ UiPathRuntimeContext,
16
10
  UiPathRuntimeError,
17
11
  UiPathRuntimeResult,
18
12
  UiPathRuntimeStatus,
19
13
  )
14
+ from ._script_executor import ScriptExecutor
20
15
 
21
16
  logger = logging.getLogger(__name__)
22
17
 
23
18
  T = TypeVar("T")
19
+ R = TypeVar("R")
20
+ AsyncFunc = Callable[[T], Awaitable[R]]
24
21
 
25
22
 
26
23
  class UiPathRuntime(UiPathBaseRuntime):
27
- """Runtime for executing Python scripts."""
24
+ def __init__(self, context: UiPathRuntimeContext, executor: AsyncFunc[Any, Any]):
25
+ self.context = context
26
+ self.executor = executor
27
+
28
+ async def cleanup(self) -> None:
29
+ """Cleanup runtime resources."""
30
+ pass
31
+
32
+ async def validate(self):
33
+ """Validate runtime context."""
34
+ pass
28
35
 
29
36
  async def execute(self) -> Optional[UiPathRuntimeResult]:
30
37
  """Execute the Python script with the provided input and configuration.
@@ -35,15 +42,8 @@ class UiPathRuntime(UiPathBaseRuntime):
35
42
  Raises:
36
43
  UiPathRuntimeError: If execution fails
37
44
  """
38
- await self.validate()
39
-
40
45
  try:
41
- if self.context.entrypoint is None:
42
- return None
43
-
44
- script_result = await self._execute_python_script(
45
- self.context.entrypoint, self.context.input_json
46
- )
46
+ script_result = await self.executor(self.context.input_json)
47
47
 
48
48
  if self.context.job_id is None:
49
49
  logger.info(script_result)
@@ -65,248 +65,15 @@ class UiPathRuntime(UiPathBaseRuntime):
65
65
  UiPathErrorCategory.SYSTEM,
66
66
  ) from e
67
67
 
68
- async def validate(self) -> None:
69
- """Validate runtime inputs."""
70
- if not self.context.entrypoint:
71
- raise UiPathRuntimeError(
72
- "ENTRYPOINT_MISSING",
73
- "No entrypoint specified",
74
- "Please provide a path to a Python script.",
75
- UiPathErrorCategory.USER,
76
- )
77
-
78
- if not os.path.exists(self.context.entrypoint):
79
- raise UiPathRuntimeError(
80
- "ENTRYPOINT_NOT_FOUND",
81
- "Script not found",
82
- f"Script not found at path {self.context.entrypoint}.",
83
- UiPathErrorCategory.USER,
84
- )
85
-
86
- try:
87
- if self.context.input:
88
- self.context.input_json = json.loads(self.context.input)
89
- if self.context.input_json is None:
90
- self.context.input_json = {}
91
- except json.JSONDecodeError as e:
92
- raise UiPathRuntimeError(
93
- "INPUT_INVALID_JSON",
94
- "Invalid JSON input",
95
- f"The input data is not valid JSON: {str(e)}",
96
- UiPathErrorCategory.USER,
97
- ) from e
98
-
99
- async def cleanup(self) -> None:
100
- """Cleanup runtime resources."""
101
- pass
102
-
103
- async def _execute_python_script(self, script_path: str, input_data: Any) -> Any:
104
- """Execute the Python script with the given input."""
105
- spec = importlib.util.spec_from_file_location("dynamic_module", script_path)
106
- if not spec or not spec.loader:
107
- raise UiPathRuntimeError(
108
- "IMPORT_ERROR",
109
- "Module import failed",
110
- f"Could not load spec for {script_path}",
111
- UiPathErrorCategory.USER,
112
- )
113
-
114
- module = importlib.util.module_from_spec(spec)
115
- try:
116
- spec.loader.exec_module(module)
117
- except Exception as e:
118
- raise UiPathRuntimeError(
119
- "MODULE_EXECUTION_ERROR",
120
- "Module execution failed",
121
- f"Error executing module: {str(e)}",
122
- UiPathErrorCategory.USER,
123
- ) from e
124
-
125
- for func_name in ["main", "run", "execute"]:
126
- if hasattr(module, func_name):
127
- main_func = getattr(module, func_name)
128
- sig = inspect.signature(main_func)
129
- params = list(sig.parameters.values())
130
-
131
- # Check if the function is asynchronous
132
- is_async = inspect.iscoroutinefunction(main_func)
133
-
134
- # Case 1: No parameters
135
- if not params:
136
- try:
137
- result = await main_func() if is_async else main_func()
138
- return (
139
- self._convert_from_class(result)
140
- if result is not None
141
- else {}
142
- )
143
- except Exception as e:
144
- raise UiPathRuntimeError(
145
- "FUNCTION_EXECUTION_ERROR",
146
- f"Error executing {func_name} function",
147
- f"Error: {str(e)}",
148
- UiPathErrorCategory.USER,
149
- ) from e
150
-
151
- input_param = params[0]
152
- input_type = input_param.annotation
153
-
154
- # Case 2: Class, dataclass, or Pydantic model parameter
155
- if input_type != inspect.Parameter.empty and (
156
- is_dataclass(input_type)
157
- or self._is_pydantic_model(input_type)
158
- or hasattr(input_type, "__annotations__")
159
- ):
160
- try:
161
- valid_type = cast(Type[Any], input_type)
162
- typed_input = self._convert_to_class(input_data, valid_type)
163
- result = (
164
- await main_func(typed_input)
165
- if is_async
166
- else main_func(typed_input)
167
- )
168
- return (
169
- self._convert_from_class(result)
170
- if result is not None
171
- else {}
172
- )
173
- except Exception as e:
174
- raise UiPathRuntimeError(
175
- "FUNCTION_EXECUTION_ERROR",
176
- f"Error executing {func_name} function with typed input",
177
- f"Error: {str(e)}",
178
- UiPathErrorCategory.USER,
179
- ) from e
180
-
181
- # Case 3: Dict parameter
182
- else:
183
- try:
184
- result = (
185
- await main_func(input_data)
186
- if is_async
187
- else main_func(input_data)
188
- )
189
- return (
190
- self._convert_from_class(result)
191
- if result is not None
192
- else {}
193
- )
194
- except Exception as e:
195
- raise UiPathRuntimeError(
196
- "FUNCTION_EXECUTION_ERROR",
197
- f"Error executing {func_name} function with dictionary input",
198
- f"Error: {str(e)}",
199
- UiPathErrorCategory.USER,
200
- ) from e
201
-
202
- raise UiPathRuntimeError(
203
- "ENTRYPOINT_FUNCTION_MISSING",
204
- "No entry function found",
205
- f"No main function (main, run, or execute) found in {script_path}",
206
- UiPathErrorCategory.USER,
207
- )
208
-
209
- def _convert_to_class(self, data: Dict[str, Any], cls: Type[T]) -> T:
210
- """Convert a dictionary to either a dataclass, Pydantic model, or regular class instance."""
211
- # Handle Pydantic models
212
- try:
213
- if inspect.isclass(cls) and issubclass(cls, BaseModel):
214
- return cls.model_validate(data)
215
- except TypeError:
216
- # issubclass can raise TypeError if cls is not a class
217
- pass
218
-
219
- # Handle dataclasses
220
- if is_dataclass(cls):
221
- field_types = get_type_hints(cls)
222
- converted_data = {}
223
68
 
224
- for field_name, field_type in field_types.items():
225
- if field_name not in data:
226
- continue
227
-
228
- value = data[field_name]
229
- if (
230
- is_dataclass(field_type)
231
- or self._is_pydantic_model(field_type)
232
- or hasattr(field_type, "__annotations__")
233
- ) and isinstance(value, dict):
234
- typed_field = cast(Type[Any], field_type)
235
- value = self._convert_to_class(value, typed_field)
236
- converted_data[field_name] = value
237
-
238
- return cls(**converted_data)
239
-
240
- # Handle regular classes
241
- else:
242
- sig = inspect.signature(cls.__init__)
243
- params = sig.parameters
244
-
245
- init_args = {}
246
-
247
- for param_name, param in params.items():
248
- if param_name == "self":
249
- continue
250
-
251
- if param_name in data:
252
- value = data[param_name]
253
- param_type = (
254
- param.annotation
255
- if param.annotation != inspect.Parameter.empty
256
- else Any
257
- )
258
-
259
- if (
260
- is_dataclass(param_type)
261
- or self._is_pydantic_model(param_type)
262
- or hasattr(param_type, "__annotations__")
263
- ) and isinstance(value, dict):
264
- typed_param = cast(Type[Any], param_type)
265
- value = self._convert_to_class(value, typed_param)
266
-
267
- init_args[param_name] = value
268
- elif param.default != inspect.Parameter.empty:
269
- init_args[param_name] = param.default
270
-
271
- return cls(**init_args)
272
-
273
- def _is_pydantic_model(self, cls: Type[Any]) -> bool:
274
- """Safely check if a class is a Pydantic model."""
275
- try:
276
- return inspect.isclass(cls) and issubclass(cls, BaseModel)
277
- except TypeError:
278
- # issubclass can raise TypeError if cls is not a class
279
- return False
280
-
281
- def _convert_from_class(self, obj: Any) -> Dict[str, Any]:
282
- """Convert a class instance (dataclass, Pydantic model, or regular) to a dictionary."""
283
- if obj is None:
284
- return {}
285
-
286
- # Handle Pydantic models
287
- if isinstance(obj, BaseModel):
288
- return obj.model_dump()
69
+ class UiPathScriptRuntime(UiPathRuntime):
70
+ """Runtime for executing Python scripts."""
289
71
 
290
- # Handle dataclasses
291
- elif is_dataclass(obj):
292
- # Make sure obj is an instance, not a class
293
- if isinstance(obj, type):
294
- return {}
295
- return asdict(obj)
72
+ def __init__(self, context: UiPathRuntimeContext, entrypoint: str):
73
+ executor = ScriptExecutor(entrypoint)
74
+ super().__init__(context, executor)
296
75
 
297
- # Handle regular classes
298
- elif hasattr(obj, "__dict__"):
299
- result = {}
300
- for key, value in obj.__dict__.items():
301
- # Skip private attributes
302
- if not key.startswith("_"):
303
- if (
304
- isinstance(value, BaseModel)
305
- or hasattr(value, "__dict__")
306
- or is_dataclass(value)
307
- ):
308
- result[key] = self._convert_from_class(value)
309
- else:
310
- result[key] = value
311
- return result
312
- return {} if obj is None else {str(type(obj).__name__): str(obj)} # Fallback
76
+ @classmethod
77
+ def from_context(cls, context: UiPathRuntimeContext):
78
+ """Create runtime instance from context."""
79
+ return UiPathScriptRuntime(context, context.entrypoint or "")
@@ -0,0 +1,254 @@
1
+ """Python script runtime implementation for executing and managing python scripts."""
2
+
3
+ import importlib.util
4
+ import inspect
5
+ import os
6
+ from dataclasses import asdict, is_dataclass
7
+ from typing import Any, Dict, Type, TypeVar, cast, get_type_hints
8
+
9
+ from pydantic import BaseModel
10
+
11
+ from ._contracts import (
12
+ UiPathErrorCategory,
13
+ UiPathRuntimeError,
14
+ )
15
+
16
+ T = TypeVar("T")
17
+
18
+
19
+ class ScriptExecutor:
20
+ def __init__(self, entrypoint: str):
21
+ self.entrypoint = entrypoint
22
+ self.validate_entrypoint()
23
+
24
+ async def __call__(self, input: Any) -> Any:
25
+ return await self._execute_python_script(input)
26
+
27
+ def validate_entrypoint(self) -> None:
28
+ """Validate runtime inputs."""
29
+ if not self.entrypoint:
30
+ raise UiPathRuntimeError(
31
+ "ENTRYPOINT_MISSING",
32
+ "No entrypoint specified",
33
+ "Please provide a path to a Python script.",
34
+ UiPathErrorCategory.USER,
35
+ )
36
+
37
+ if not os.path.exists(self.entrypoint):
38
+ raise UiPathRuntimeError(
39
+ "ENTRYPOINT_NOT_FOUND",
40
+ "Script not found",
41
+ f"Script not found at path {self.entrypoint}.",
42
+ UiPathErrorCategory.USER,
43
+ )
44
+
45
+ async def _execute_python_script(self, input_data: Any) -> Any:
46
+ """Execute the Python script with the given input."""
47
+ spec = importlib.util.spec_from_file_location("dynamic_module", self.entrypoint)
48
+ if not spec or not spec.loader:
49
+ raise UiPathRuntimeError(
50
+ "IMPORT_ERROR",
51
+ "Module import failed",
52
+ f"Could not load spec for {self.entrypoint}",
53
+ UiPathErrorCategory.USER,
54
+ )
55
+
56
+ module = importlib.util.module_from_spec(spec)
57
+ try:
58
+ spec.loader.exec_module(module)
59
+ except Exception as e:
60
+ raise UiPathRuntimeError(
61
+ "MODULE_EXECUTION_ERROR",
62
+ "Module execution failed",
63
+ f"Error executing module: {str(e)}",
64
+ UiPathErrorCategory.USER,
65
+ ) from e
66
+
67
+ for func_name in ["main", "run", "execute"]:
68
+ if hasattr(module, func_name):
69
+ main_func = getattr(module, func_name)
70
+ sig = inspect.signature(main_func)
71
+ params = list(sig.parameters.values())
72
+
73
+ # Check if the function is asynchronous
74
+ is_async = inspect.iscoroutinefunction(main_func)
75
+
76
+ # Case 1: No parameters
77
+ if not params:
78
+ try:
79
+ result = await main_func() if is_async else main_func()
80
+ return (
81
+ self._convert_from_class(result)
82
+ if result is not None
83
+ else {}
84
+ )
85
+ except Exception as e:
86
+ raise UiPathRuntimeError(
87
+ "FUNCTION_EXECUTION_ERROR",
88
+ f"Error executing {func_name} function",
89
+ f"Error: {str(e)}",
90
+ UiPathErrorCategory.USER,
91
+ ) from e
92
+
93
+ input_param = params[0]
94
+ input_type = input_param.annotation
95
+
96
+ # Case 2: Class, dataclass, or Pydantic model parameter
97
+ if input_type != inspect.Parameter.empty and (
98
+ is_dataclass(input_type)
99
+ or self._is_pydantic_model(input_type)
100
+ or hasattr(input_type, "__annotations__")
101
+ ):
102
+ try:
103
+ valid_type = cast(Type[Any], input_type)
104
+ typed_input = self._convert_to_class(input_data, valid_type)
105
+ result = (
106
+ await main_func(typed_input)
107
+ if is_async
108
+ else main_func(typed_input)
109
+ )
110
+ return (
111
+ self._convert_from_class(result)
112
+ if result is not None
113
+ else {}
114
+ )
115
+ except Exception as e:
116
+ raise UiPathRuntimeError(
117
+ "FUNCTION_EXECUTION_ERROR",
118
+ f"Error executing {func_name} function with typed input",
119
+ f"Error: {str(e)}",
120
+ UiPathErrorCategory.USER,
121
+ ) from e
122
+
123
+ # Case 3: Dict parameter
124
+ else:
125
+ try:
126
+ result = (
127
+ await main_func(input_data)
128
+ if is_async
129
+ else main_func(input_data)
130
+ )
131
+ return (
132
+ self._convert_from_class(result)
133
+ if result is not None
134
+ else {}
135
+ )
136
+ except Exception as e:
137
+ raise UiPathRuntimeError(
138
+ "FUNCTION_EXECUTION_ERROR",
139
+ f"Error executing {func_name} function with dictionary input",
140
+ f"Error: {str(e)}",
141
+ UiPathErrorCategory.USER,
142
+ ) from e
143
+
144
+ raise UiPathRuntimeError(
145
+ "ENTRYPOINT_FUNCTION_MISSING",
146
+ "No entry function found",
147
+ f"No main function (main, run, or execute) found in {self.entrypoint}",
148
+ UiPathErrorCategory.USER,
149
+ )
150
+
151
+ def _convert_to_class(self, data: Dict[str, Any], cls: Type[T]) -> T:
152
+ """Convert a dictionary to either a dataclass, Pydantic model, or regular class instance."""
153
+ # Handle Pydantic models
154
+ try:
155
+ if inspect.isclass(cls) and issubclass(cls, BaseModel):
156
+ return cls.model_validate(data)
157
+ except TypeError:
158
+ # issubclass can raise TypeError if cls is not a class
159
+ pass
160
+
161
+ # Handle dataclasses
162
+ if is_dataclass(cls):
163
+ field_types = get_type_hints(cls)
164
+ converted_data = {}
165
+
166
+ for field_name, field_type in field_types.items():
167
+ if field_name not in data:
168
+ continue
169
+
170
+ value = data[field_name]
171
+ if (
172
+ is_dataclass(field_type)
173
+ or self._is_pydantic_model(field_type)
174
+ or hasattr(field_type, "__annotations__")
175
+ ) and isinstance(value, dict):
176
+ typed_field = cast(Type[Any], field_type)
177
+ value = self._convert_to_class(value, typed_field)
178
+ converted_data[field_name] = value
179
+
180
+ return cls(**converted_data)
181
+
182
+ # Handle regular classes
183
+ else:
184
+ sig = inspect.signature(cls.__init__)
185
+ params = sig.parameters
186
+
187
+ init_args = {}
188
+
189
+ for param_name, param in params.items():
190
+ if param_name == "self":
191
+ continue
192
+
193
+ if param_name in data:
194
+ value = data[param_name]
195
+ param_type = (
196
+ param.annotation
197
+ if param.annotation != inspect.Parameter.empty
198
+ else Any
199
+ )
200
+
201
+ if (
202
+ is_dataclass(param_type)
203
+ or self._is_pydantic_model(param_type)
204
+ or hasattr(param_type, "__annotations__")
205
+ ) and isinstance(value, dict):
206
+ typed_param = cast(Type[Any], param_type)
207
+ value = self._convert_to_class(value, typed_param)
208
+
209
+ init_args[param_name] = value
210
+ elif param.default != inspect.Parameter.empty:
211
+ init_args[param_name] = param.default
212
+
213
+ return cls(**init_args)
214
+
215
+ def _is_pydantic_model(self, cls: Type[Any]) -> bool:
216
+ """Safely check if a class is a Pydantic model."""
217
+ try:
218
+ return inspect.isclass(cls) and issubclass(cls, BaseModel)
219
+ except TypeError:
220
+ # issubclass can raise TypeError if cls is not a class
221
+ return False
222
+
223
+ def _convert_from_class(self, obj: Any) -> Dict[str, Any]:
224
+ """Convert a class instance (dataclass, Pydantic model, or regular) to a dictionary."""
225
+ if obj is None:
226
+ return {}
227
+
228
+ # Handle Pydantic models
229
+ if isinstance(obj, BaseModel):
230
+ return obj.model_dump()
231
+
232
+ # Handle dataclasses
233
+ elif is_dataclass(obj):
234
+ # Make sure obj is an instance, not a class
235
+ if isinstance(obj, type):
236
+ return {}
237
+ return asdict(obj)
238
+
239
+ # Handle regular classes
240
+ elif hasattr(obj, "__dict__"):
241
+ result = {}
242
+ for key, value in obj.__dict__.items():
243
+ # Skip private attributes
244
+ if not key.startswith("_"):
245
+ if (
246
+ isinstance(value, BaseModel)
247
+ or hasattr(value, "__dict__")
248
+ or is_dataclass(value)
249
+ ):
250
+ result[key] = self._convert_from_class(value)
251
+ else:
252
+ result[key] = value
253
+ return result
254
+ return {} if obj is None else {str(type(obj).__name__): str(obj)} # Fallback
uipath/_cli/cli_dev.py CHANGED
@@ -6,7 +6,7 @@ import click
6
6
 
7
7
  from uipath._cli._dev._terminal import UiPathDevTerminal
8
8
  from uipath._cli._runtime._contracts import UiPathRuntimeContext, UiPathRuntimeFactory
9
- from uipath._cli._runtime._runtime import UiPathRuntime
9
+ from uipath._cli._runtime._runtime import UiPathScriptRuntime
10
10
  from uipath._cli._utils._console import ConsoleLogger
11
11
  from uipath._cli._utils._debug import setup_debugging
12
12
  from uipath._cli.cli_init import init # type: ignore[attr-defined]
@@ -53,7 +53,9 @@ def dev(interface: Optional[str], debug: bool, debug_port: int) -> None:
53
53
 
54
54
  try:
55
55
  if interface == "terminal":
56
- runtime_factory = UiPathRuntimeFactory(UiPathRuntime, UiPathRuntimeContext)
56
+ runtime_factory = UiPathRuntimeFactory(
57
+ UiPathScriptRuntime, UiPathRuntimeContext
58
+ )
57
59
  app = UiPathDevTerminal(runtime_factory)
58
60
  asyncio.run(app.run_async())
59
61
  else:
uipath/_cli/cli_eval.py CHANGED
@@ -10,15 +10,16 @@ import click
10
10
  from uipath._cli._evals._runtime import UiPathEvalContext, UiPathEvalRuntime
11
11
  from uipath._cli._runtime._contracts import (
12
12
  UiPathRuntimeContext,
13
- UiPathRuntimeContextBuilder,
14
13
  UiPathRuntimeFactory,
15
14
  )
16
- from uipath._cli._runtime._runtime import UiPathRuntime
15
+ from uipath._cli._runtime._runtime import UiPathScriptRuntime
17
16
  from uipath._cli.middlewares import MiddlewareResult, Middlewares
17
+ from uipath.eval._helpers import auto_discover_entrypoint
18
18
 
19
19
  from .._utils.constants import ENV_JOB_ID
20
20
  from ..telemetry import track
21
21
  from ._utils._console import ConsoleLogger
22
+ from ._utils._eval_set import EvalHelpers
22
23
 
23
24
  console = ConsoleLogger()
24
25
 
@@ -39,42 +40,35 @@ def eval_agent_middleware(
39
40
  no_report: bool = False,
40
41
  **kwargs,
41
42
  ) -> MiddlewareResult:
42
- def generate_eval_context(
43
- runtime_context: UiPathRuntimeContext,
44
- ) -> UiPathEvalContext:
45
- os.makedirs("evals/results", exist_ok=True)
46
- timestamp = datetime.now(timezone.utc).strftime("%M-%H-%d-%m-%Y")
47
- base_context = UiPathRuntimeContextBuilder().with_defaults().build()
48
- # TODO: the name should include the eval_set name. those files should not be commited to SW
49
- base_context.execution_output_file = (
50
- f"evals/results/{timestamp}.json"
51
- if not os.getenv("UIPATH_JOB_KEY")
52
- else None
53
- )
54
- return UiPathEvalContext(
55
- runtime_context=runtime_context,
56
- no_report=no_report,
57
- workers=workers,
58
- eval_set=eval_set,
59
- eval_ids=eval_ids,
60
- **kwargs,
61
- **base_context.model_dump(),
62
- )
43
+ """Middleware to run an evaluation set against the agent."""
44
+ timestamp = datetime.now(timezone.utc).strftime("%M-%H-%d-%m-%Y")
45
+
46
+ eval_context = UiPathEvalContext.with_defaults()
47
+ eval_context.no_report = no_report
48
+ eval_context.workers = workers
49
+ eval_context.eval_set = eval_set or EvalHelpers.auto_discover_eval_set()
50
+ eval_context.eval_ids = eval_ids
51
+ eval_context.execution_output_file = (
52
+ f"evals/results/{timestamp}.json" if not os.getenv("UIPATH_JOB_KEY") else None
53
+ )
54
+
55
+ runtime_entrypoint = entrypoint or auto_discover_entrypoint()
56
+
57
+ def generate_runtime_context(**context_kwargs) -> UiPathRuntimeContext:
58
+ runtime_context = UiPathRuntimeContext.with_defaults(**context_kwargs)
59
+ runtime_context.entrypoint = runtime_entrypoint
60
+ return runtime_context
63
61
 
64
62
  try:
65
- runtime_factory = UiPathRuntimeFactory(UiPathRuntime, UiPathRuntimeContext)
66
- context = (
67
- UiPathRuntimeContextBuilder()
68
- .with_defaults(**kwargs)
69
- .with_entrypoint(entrypoint)
70
- .with_entrypoint(entrypoint)
71
- .mark_eval_run()
72
- .build()
63
+ runtime_factory = UiPathRuntimeFactory(
64
+ UiPathScriptRuntime,
65
+ UiPathRuntimeContext,
66
+ context_generator=generate_runtime_context,
73
67
  )
74
68
 
75
69
  async def execute():
76
70
  async with UiPathEvalRuntime.from_eval_context(
77
- factory=runtime_factory, context=generate_eval_context(context)
71
+ factory=runtime_factory, context=eval_context
78
72
  ) as eval_runtime:
79
73
  await eval_runtime.execute()
80
74
 
uipath/_cli/cli_run.py CHANGED
@@ -1,9 +1,8 @@
1
1
  # type: ignore
2
2
  import asyncio
3
3
  import os
4
- import traceback
5
4
  from os import environ as env
6
- from typing import Optional, Tuple
5
+ from typing import Optional
7
6
 
8
7
  import click
9
8
 
@@ -15,138 +14,16 @@ from .._utils.constants import (
15
14
  from ..telemetry import track
16
15
  from ._runtime._contracts import (
17
16
  UiPathRuntimeContext,
18
- UiPathRuntimeContextBuilder,
19
17
  UiPathRuntimeError,
20
18
  UiPathRuntimeFactory,
21
19
  )
22
- from ._runtime._runtime import UiPathRuntime
20
+ from ._runtime._runtime import UiPathScriptRuntime
23
21
  from ._utils._console import ConsoleLogger
24
- from .middlewares import MiddlewareResult, Middlewares
22
+ from .middlewares import Middlewares
25
23
 
26
24
  console = ConsoleLogger()
27
25
 
28
26
 
29
- def python_run_middleware(
30
- entrypoint: Optional[str],
31
- input: Optional[str],
32
- resume: bool,
33
- **kwargs,
34
- ) -> MiddlewareResult:
35
- """Middleware to handle Python script execution.
36
-
37
- Args:
38
- entrypoint: Path to the Python script to execute
39
- input: JSON string with input data
40
- resume: Flag indicating if this is a resume execution
41
- debug: Enable debugging with debugpy
42
- debug_port: Port for debug server (default: 5678)
43
-
44
- Returns:
45
- MiddlewareResult with execution status and messages
46
- """
47
- if not entrypoint:
48
- return MiddlewareResult(
49
- should_continue=False,
50
- error_message="""No entrypoint specified. Please provide a path to a Python script.
51
- Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""",
52
- )
53
-
54
- if not os.path.exists(entrypoint):
55
- return MiddlewareResult(
56
- should_continue=False,
57
- error_message=f"""Script not found at path {entrypoint}.
58
- Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""",
59
- )
60
-
61
- try:
62
- runtime_factory = UiPathRuntimeFactory(UiPathRuntime, UiPathRuntimeContext)
63
- context = (
64
- UiPathRuntimeContextBuilder()
65
- .with_defaults(**kwargs)
66
- .with_entrypoint(entrypoint)
67
- .with_input(input, input_file=kwargs.get("input_file"))
68
- .with_resume(resume)
69
- .build()
70
- )
71
-
72
- asyncio.run(runtime_factory.execute(context))
73
-
74
- return MiddlewareResult(should_continue=False)
75
-
76
- except UiPathRuntimeError as e:
77
- return MiddlewareResult(
78
- should_continue=False,
79
- error_message=f"Error: {e.error_info.title} - {e.error_info.detail}",
80
- should_include_stacktrace=False,
81
- )
82
- except Exception as e:
83
- # Handle unexpected errors
84
- return MiddlewareResult(
85
- should_continue=False,
86
- error_message=f"Error: Unexpected error occurred - {str(e)}",
87
- should_include_stacktrace=True,
88
- )
89
-
90
-
91
- def run_core(
92
- entrypoint: Optional[str],
93
- resume: bool,
94
- input: Optional[str] = None,
95
- input_file: Optional[str] = None,
96
- execution_output_file: Optional[str] = None,
97
- logs_file: Optional[str] = None,
98
- **kwargs,
99
- ) -> Tuple[bool, Optional[str], Optional[str]]:
100
- """Core execution logic that can be called programmatically.
101
-
102
- Args:
103
- entrypoint: Path to the Python script to execute
104
- input: JSON string with input data
105
- resume: Flag indicating if this is a resume execution
106
- input_file: Path to input JSON file
107
- execution_output_file: Path to execution output file
108
- logs_file: Path where execution output will be written
109
- **kwargs: Additional arguments to be forwarded to the middleware
110
-
111
- Returns:
112
- Tuple containing:
113
- - success: True if execution was successful
114
- - error_message: Error message if any
115
- - info_message: Info message if any
116
- """
117
- # Process through middleware chain
118
- result = Middlewares.next(
119
- "run",
120
- entrypoint,
121
- input,
122
- resume,
123
- input_file=input_file,
124
- execution_output_file=execution_output_file,
125
- logs_file=logs_file,
126
- **kwargs,
127
- )
128
-
129
- if result.should_continue:
130
- result = python_run_middleware(
131
- entrypoint=entrypoint,
132
- input=input,
133
- resume=resume,
134
- input_file=input_file,
135
- execution_output_file=execution_output_file,
136
- logs_file=logs_file,
137
- **kwargs,
138
- )
139
-
140
- if result.should_continue:
141
- return False, "Could not process the request with any available handler.", None
142
-
143
- return (
144
- not bool(result.error_message),
145
- result.error_message,
146
- result.info_message,
147
- )
148
-
149
-
150
27
  @click.command()
151
28
  @click.argument("entrypoint", required=False)
152
29
  @click.argument("input", required=False, default="{}")
@@ -198,27 +75,53 @@ def run(
198
75
  if not setup_debugging(debug, debug_port):
199
76
  console.error(f"Failed to start debug server on port {debug_port}")
200
77
 
201
- success, error_message, info_message = run_core(
202
- entrypoint=entrypoint,
203
- input=input,
204
- resume=resume,
78
+ result = Middlewares.next(
79
+ "run",
80
+ entrypoint,
81
+ input,
82
+ resume,
205
83
  input_file=input_file,
206
84
  execution_output_file=output_file,
207
85
  debug=debug,
208
86
  debug_port=debug_port,
209
87
  )
210
88
 
211
- if error_message:
212
- console.error(error_message, include_traceback=True)
213
- if not success: # If there was an error and execution failed
214
- console.error(traceback.format_exc())
215
- click.get_current_context().exit(1)
216
-
217
- if info_message:
218
- console.info(info_message)
89
+ if result.error_message:
90
+ console.error(result.error_message)
219
91
 
220
- if success:
221
- console.success("Successful execution.")
92
+ if result.should_continue:
93
+ if not entrypoint:
94
+ console.error("""No entrypoint specified. Please provide a path to a Python script.
95
+ Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""")
96
+
97
+ if not os.path.exists(entrypoint):
98
+ console.error(f"""Script not found at path {entrypoint}.
99
+ Usage: `uipath run <entrypoint_path> <input_arguments> [-f <input_json_file_path>]`""")
100
+
101
+ try:
102
+ runtime_factory = UiPathRuntimeFactory(
103
+ UiPathScriptRuntime, UiPathRuntimeContext
104
+ )
105
+ context = UiPathRuntimeContext.with_defaults(
106
+ entrypoint=entrypoint,
107
+ input=input,
108
+ input_file=input_file,
109
+ resume=resume,
110
+ execution_output_file=output_file,
111
+ debug=debug,
112
+ )
113
+
114
+ asyncio.run(runtime_factory.execute(context))
115
+
116
+ except UiPathRuntimeError as e:
117
+ console.error(f"{e.error_info.title} - {e.error_info.detail}")
118
+ except Exception as e:
119
+ # Handle unexpected errors
120
+ console.error(
121
+ f"Error: Unexpected error occurred - {str(e)}", include_traceback=True
122
+ )
123
+
124
+ console.success("Successful execution.")
222
125
 
223
126
 
224
127
  if __name__ == "__main__":
@@ -7,7 +7,7 @@ from .._config import Config
7
7
  from .._execution_context import ExecutionContext
8
8
  from .._folder_context import FolderContext
9
9
  from .._utils import Endpoint, RequestSpec, header_folder, infer_bindings
10
- from .._utils.constants import ENV_JOB_ID, HEADER_JOB_KEY
10
+ from .._utils.constants import ENV_JOB_KEY, HEADER_JOB_KEY
11
11
  from ..models.job import Job
12
12
  from ..tracing._traced import traced
13
13
  from . import AttachmentsService
@@ -241,7 +241,7 @@ class ProcessesService(FolderContext, BaseService):
241
241
  **header_folder(folder_key, folder_path),
242
242
  },
243
243
  )
244
- job_key = os.environ.get(ENV_JOB_ID, None)
244
+ job_key = os.environ.get(ENV_JOB_KEY, None)
245
245
  if job_key:
246
246
  request_scope.headers[HEADER_JOB_KEY] = job_key
247
247
  return request_scope
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath
3
- Version: 2.1.44
3
+ Version: 2.1.46
4
4
  Summary: Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools.
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-python
@@ -8,8 +8,8 @@ uipath/_cli/README.md,sha256=GLtCfbeIKZKNnGTCsfSVqRQ27V1btT1i2bSAyW_xZl4,474
8
8
  uipath/_cli/__init__.py,sha256=kf4GINkunFGMZkTk2Z4f1Q3-OsxpNnV6u_9BsBt1i0E,2229
9
9
  uipath/_cli/cli_auth.py,sha256=i3ykLlCg68xgPXHHaa0agHwGFIiLiTLzOiF6Su8XaEo,2436
10
10
  uipath/_cli/cli_deploy.py,sha256=KPCmQ0c_NYD5JofSDao5r6QYxHshVCRxlWDVnQvlp5w,645
11
- uipath/_cli/cli_dev.py,sha256=JRzXrAUM_sj6FCVG-VveYADTwR8yQ330SgYs3LgbvJc,2104
12
- uipath/_cli/cli_eval.py,sha256=ZXCwjNBgp-aROIA9hcl2w5eqsrxWJAteAPmWs4hEwKQ,4525
11
+ uipath/_cli/cli_dev.py,sha256=nEfpjw1PZ72O6jmufYWVrueVwihFxDPOeJakdvNHdOA,2146
12
+ uipath/_cli/cli_eval.py,sha256=fYJWQlyiIc8SpTzY9QPNQWOx40PagMEKdsGZIu9As2A,4402
13
13
  uipath/_cli/cli_init.py,sha256=ls577uNm2zWccknIhtVFS3ah2ds0QSy2_TgMp6z7Wt4,6049
14
14
  uipath/_cli/cli_invoke.py,sha256=4jyhqcy7tPrpxvaUhW-9gut6ddsCGMdJJcpOXXmIe8g,4348
15
15
  uipath/_cli/cli_new.py,sha256=9378NYUBc9j-qKVXV7oja-jahfJhXBg8zKVyaon7ctY,2102
@@ -17,7 +17,7 @@ uipath/_cli/cli_pack.py,sha256=NmwZTfwZ2fURiHyiX1BM0juAtBOjPB1Jmcpu-rD7p-4,11025
17
17
  uipath/_cli/cli_publish.py,sha256=FmBCdeh4zFaESOLfzTTPxGcOwUtsQ_WkvF_fjHEdU8s,6448
18
18
  uipath/_cli/cli_pull.py,sha256=vwS0KMX6O2L6RaPy8tw_qzXe4dC7kf_G6nbLm0I62eI,6831
19
19
  uipath/_cli/cli_push.py,sha256=-j-gDIbT8GyU2SybLQqFl5L8KI9nu3CDijVtltDgX20,3132
20
- uipath/_cli/cli_run.py,sha256=C0V7Tt_kYAk2vbQO7hVE6DRUqZW1Xo35LgqhnQhF3Ng,6539
20
+ uipath/_cli/cli_run.py,sha256=7CJ3e388KCXzB5qh1eHIOL4fe7lMIxt7_1kC7iAz0A8,3559
21
21
  uipath/_cli/middlewares.py,sha256=GvMhDnx1BmA7rIe12s6Uqv1JdqNZhvraU0a91oqGag4,4976
22
22
  uipath/_cli/spinner.py,sha256=bS-U_HA5yne11ejUERu7CQoXmWdabUD2bm62EfEdV8M,1107
23
23
  uipath/_cli/_auth/_auth_server.py,sha256=22km0F1NFNXgyLbvtAx3ssiQlVGHroLdtDCWEqiCiMg,7106
@@ -44,7 +44,7 @@ uipath/_cli/_dev/_terminal/_styles/terminal.tcss,sha256=ktVpKwXIXw2VZp8KIZD6fO9i
44
44
  uipath/_cli/_dev/_terminal/_utils/_chat.py,sha256=YUZxYVdmEManwHDuZsczJT1dWIYE1dVBgABlurwMFcE,8493
45
45
  uipath/_cli/_dev/_terminal/_utils/_exporter.py,sha256=oI6D_eMwrh_2aqDYUh4GrJg8VLGrLYhDahR-_o0uJns,4144
46
46
  uipath/_cli/_dev/_terminal/_utils/_logger.py,sha256=jeNShEED27cNIHTe_NNx-2kUiXpSLTmi0onM6tVkqRM,888
47
- uipath/_cli/_evals/_runtime.py,sha256=PEMaW7EOHyyIgqDVMEdSKmGbRAO15HtZpzV4Jgmjuq0,5948
47
+ uipath/_cli/_evals/_runtime.py,sha256=q4h3zp_7Ygkhj1zE_YTKKXRp3BhkHaPj8CWqjkzerTk,4748
48
48
  uipath/_cli/_evals/progress_reporter.py,sha256=m1Dio1vG-04nFTFz5ijM_j1dhudlgOzQukmTkkg6wS4,11490
49
49
  uipath/_cli/_evals/_evaluators/__init__.py,sha256=jD7KNLjbsUpsESFXX11eW2MEPXDNuPp2-t-IPB-inlM,734
50
50
  uipath/_cli/_evals/_evaluators/_deterministic_evaluator_base.py,sha256=BTl0puBjp9iCsU3YFfYWqk4TOz4iE19O3q1-dK6qUOI,1723
@@ -59,11 +59,12 @@ uipath/_cli/_evals/_models/_agent_execution_output.py,sha256=llvApU4JkTnNgQ5DvHP
59
59
  uipath/_cli/_evals/_models/_evaluation_set.py,sha256=tVHykSget-G3sOCs9bSchMYUTpFqzXVlYYbY8L9SI0c,1518
60
60
  uipath/_cli/_evals/_models/_evaluators.py,sha256=l57NEVyYmzSKuoIXuGkE94Br01hAMg35fiS2MlTkaQM,2115
61
61
  uipath/_cli/_push/sw_file_handler.py,sha256=AX4TKM-q6CNGw3JyBW02M8ktPZuFMcAU9LN3Ii0Q2QI,18202
62
- uipath/_cli/_runtime/_contracts.py,sha256=C1zocpvNWgq6FUhWJZpVvoWrH2GBS3xA229PcMovYdY,25975
62
+ uipath/_cli/_runtime/_contracts.py,sha256=iAjrYaKS4y4unaNnwiCityfvWMg15f7quNn32f6LFkU,28406
63
63
  uipath/_cli/_runtime/_escalation.py,sha256=x3vI98qsfRA-fL_tNkRVTFXioM5Gv2w0GFcXJJ5eQtg,7981
64
64
  uipath/_cli/_runtime/_hitl.py,sha256=VKbM021nVg1HEDnTfucSLJ0LsDn83CKyUtVzofS2qTU,11369
65
65
  uipath/_cli/_runtime/_logging.py,sha256=MGklGKPjYKjs7J5Jy9eplA9zCDsdtEbkZdCbTwgut_4,8311
66
- uipath/_cli/_runtime/_runtime.py,sha256=TXtXzscRPLdYJURH0Y-7sXsigC-2k_LttBOz7EUfWUQ,11449
66
+ uipath/_cli/_runtime/_runtime.py,sha256=gby9-avNNlEATEfSXtY8FfJ8nREsSCGA4wMgDlSXTDE,2297
67
+ uipath/_cli/_runtime/_script_executor.py,sha256=PjbmEbyCMofGH2F85b8RFsxdV3Tqw0kVqdWOOk2ZLlI,9687
67
68
  uipath/_cli/_templates/.psmdcp.template,sha256=C7pBJPt98ovEljcBvGtEUGoWjjQhu9jls1bpYjeLOKA,611
68
69
  uipath/_cli/_templates/.rels.template,sha256=-fTcw7OA1AcymHr0LzBqbMAAtzZTRXLTNa_ljq087Jk,406
69
70
  uipath/_cli/_templates/[Content_Types].xml.template,sha256=bYsKDz31PkIF9QksjgAY_bqm57YC8U_owsZeNZAiBxQ,584
@@ -94,7 +95,7 @@ uipath/_services/context_grounding_service.py,sha256=EBf7lIIYz_s1ubf_07OAZXQHjS8
94
95
  uipath/_services/folder_service.py,sha256=9JqgjKhWD-G_KUnfUTP2BADxL6OK9QNZsBsWZHAULdE,2749
95
96
  uipath/_services/jobs_service.py,sha256=UwsY0Cir7Yd5_mTeH0uHLmcmQZpdbT8KNx3z3F0cHZA,32775
96
97
  uipath/_services/llm_gateway_service.py,sha256=oZR--75V8ULdLjVC7lo-lJ5786J_qfXUDe0R9iWNAKs,24306
97
- uipath/_services/processes_service.py,sha256=y2LWLIpvWnmcdtKgXCA7q0a5WPD4mBeitTICHYTQng0,8505
98
+ uipath/_services/processes_service.py,sha256=MxNyNo6EdSUhmp7QX9HYUU2JsZfiOcW7OUl86To2fXs,8507
98
99
  uipath/_services/queues_service.py,sha256=VaG3dWL2QK6AJBOLoW2NQTpkPfZjsqsYPl9-kfXPFzA,13534
99
100
  uipath/_utils/__init__.py,sha256=VdcpnENJIa0R6Y26NoxY64-wUVyvb4pKfTh1wXDQeMk,526
100
101
  uipath/_utils/_endpoint.py,sha256=yYHwqbQuJIevpaTkdfYJS9CrtlFeEyfb5JQK5osTCog,2489
@@ -144,8 +145,8 @@ uipath/tracing/_traced.py,sha256=qeVDrds2OUnpdUIA0RhtF0kg2dlAZhyC1RRkI-qivTM,185
144
145
  uipath/tracing/_utils.py,sha256=wJRELaPu69iY0AhV432Dk5QYf_N_ViRU4kAUG1BI1ew,10384
145
146
  uipath/utils/__init__.py,sha256=VD-KXFpF_oWexFg6zyiWMkxl2HM4hYJMIUDZ1UEtGx0,105
146
147
  uipath/utils/_endpoints_manager.py,sha256=iRTl5Q0XAm_YgcnMcJOXtj-8052sr6jpWuPNz6CgT0Q,8408
147
- uipath-2.1.44.dist-info/METADATA,sha256=63AwBAFGwMtIvk-7t6s5vuZ6YZoSG1vPyX-JIYtVkUo,6482
148
- uipath-2.1.44.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
149
- uipath-2.1.44.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
150
- uipath-2.1.44.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
151
- uipath-2.1.44.dist-info/RECORD,,
148
+ uipath-2.1.46.dist-info/METADATA,sha256=Qga422Nhs3DwhXAFzumjkUsV3Gxz2LgpEc4Vr_TqDgQ,6482
149
+ uipath-2.1.46.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
150
+ uipath-2.1.46.dist-info/entry_points.txt,sha256=9C2_29U6Oq1ExFu7usihR-dnfIVNSKc-0EFbh0rskB4,43
151
+ uipath-2.1.46.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
152
+ uipath-2.1.46.dist-info/RECORD,,