uipath 2.1.111__py3-none-any.whl → 2.1.113__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.

Potentially problematic release.


This version of uipath might be problematic. Click here for more details.

@@ -4,7 +4,7 @@ import logging
4
4
  import os
5
5
  from abc import ABC, abstractmethod
6
6
  from enum import Enum
7
- from typing import Any, Dict, List, Optional, Set
7
+ from typing import Any, Dict, List, Literal, Optional, Set
8
8
 
9
9
  from pydantic import BaseModel
10
10
  from pysignalr.client import SignalRClient
@@ -123,7 +123,7 @@ class UiPathDebugBridge(ABC):
123
123
  pass
124
124
 
125
125
  @abstractmethod
126
- def get_breakpoints(self) -> List[str]:
126
+ def get_breakpoints(self) -> List[str] | Literal["*"]:
127
127
  """Get nodes to suspend execution at.
128
128
 
129
129
  Returns:
@@ -220,7 +220,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
220
220
  """Print error."""
221
221
  self.console.print()
222
222
  self.console.print("[red]─" * 40)
223
- self.console.print(f"[red]✗ Error[/red] [dim]{execution_id}")
223
+ self.console.print("[red]✗ Error[/red]")
224
224
  self.console.print("[red]─" * 40)
225
225
 
226
226
  # Truncate very long errors
@@ -228,7 +228,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
228
228
  if len(error) > 500:
229
229
  error_display = error[:500] + "\n[dim]... (truncated)"
230
230
 
231
- self.console.print(f"[white]{error_display}[/white]")
231
+ self.console.print(f"[red]{error_display}[/red]")
232
232
  self.console.print("[red]─" * 40)
233
233
 
234
234
  async def wait_for_resume(self) -> Any:
@@ -252,21 +252,14 @@ class ConsoleDebugBridge(UiPathDebugBridge):
252
252
  # These commands don't resume execution, loop again
253
253
  continue
254
254
 
255
- # Reset step modes if continuing
256
- if command_result["command"] == DebugCommand.CONTINUE:
257
- self.state.step_mode = False
258
-
259
- if command_result["command"] == DebugCommand.QUIT:
260
- raise DebuggerQuitException("User requested exit")
261
-
262
255
  # Commands that resume execution: CONTINUE, STEP
263
256
  self.console.print()
264
257
  return command_result
265
258
 
266
- def get_breakpoints(self) -> List[str]:
259
+ def get_breakpoints(self) -> List[str] | Literal["*"]:
267
260
  """Get nodes to suspend execution at."""
268
261
  if self.state.step_mode:
269
- return ["*"] # Suspend at all nodes
262
+ return "*" # Suspend at all nodes
270
263
  return list(self.state.breakpoints) # Only suspend at breakpoints
271
264
 
272
265
  def _parse_command(self, user_input: str) -> Dict[str, Any]:
@@ -283,6 +276,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
283
276
  args = parts[1:] if len(parts) > 1 else []
284
277
 
285
278
  if cmd in ["c", "continue"]:
279
+ self.state.step_mode = False
286
280
  return {"command": DebugCommand.CONTINUE, "args": None}
287
281
 
288
282
  elif cmd in ["s", "step"]:
@@ -318,7 +312,7 @@ class ConsoleDebugBridge(UiPathDebugBridge):
318
312
  }
319
313
 
320
314
  elif cmd in ["q", "quit", "exit"]:
321
- raise KeyboardInterrupt("User requested exit")
315
+ raise DebuggerQuitException("User requested exit")
322
316
 
323
317
  elif cmd in ["h", "help", "?"]:
324
318
  self._print_help()
@@ -465,26 +459,75 @@ class SignalRDebugBridge(UiPathDebugBridge):
465
459
  self._client = SignalRClient(self.hub_url, headers=all_headers)
466
460
 
467
461
  # Register event handlers
468
- self._client.on("ResumeExecution", self._handle_resume)
462
+ self._client.on("Start", self._handle_start)
463
+ self._client.on("Resume", self._handle_resume)
464
+ self._client.on("Step", self._handle_step)
465
+ self._client.on("AddBreakpoints", self._handle_add_breakpoints)
466
+ self._client.on("RemoveBreakpoints", self._handle_remove_breakpoints)
467
+ self._client.on("Quit", self._handle_quit)
469
468
  self._client.on_open(self._handle_open)
470
469
  self._client.on_close(self._handle_close)
471
470
  self._client.on_error(self._handle_error)
472
471
 
473
- # Start connection in background
474
- asyncio.create_task(self._client.run())
472
+ self._run_task = asyncio.create_task(self._client.run())
473
+
474
+ async def cleanup_run_task() -> str:
475
+ error_message = (
476
+ "Failed to establish WebSocket connection within 10s timeout"
477
+ )
478
+
479
+ if self._run_task:
480
+ if not self._run_task.done():
481
+ self._run_task.cancel()
482
+ try:
483
+ await self._run_task
484
+ except asyncio.CancelledError:
485
+ pass # Expected on cancel
486
+ except Exception as task_error:
487
+ error_msg = str(task_error).strip()
488
+ error_detail = f": {error_msg}" if error_msg else ""
489
+ return f"{error_message}: {type(task_error).__name__}{error_detail}"
490
+
491
+ return error_message
492
+
493
+ try:
494
+ # Wait for connection with timeout
495
+ await asyncio.wait_for(self._connected_event.wait(), timeout=10.0)
496
+ except asyncio.TimeoutError as e:
497
+ # Clean up on timeout
498
+ raise RuntimeError(await cleanup_run_task()) from e
499
+ except Exception:
500
+ # Clean up on any other error
501
+ await cleanup_run_task()
502
+ raise
475
503
 
476
- # Wait for connection to establish
477
- await asyncio.wait_for(self._connected_event.wait(), timeout=30.0)
504
+ # Check if run_task failed
505
+ if self._run_task.done():
506
+ exception = self._run_task.exception()
507
+ if exception:
508
+ raise exception
478
509
 
479
510
  async def disconnect(self) -> None:
480
511
  """Close SignalR connection."""
481
- if self._client and hasattr(self._client, "_transport"):
482
- transport = self._client._transport
483
- if transport and hasattr(transport, "_ws") and transport._ws:
484
- try:
512
+ if not self._client:
513
+ return
514
+
515
+ # Cancel the run task first
516
+ if self._run_task and not self._run_task.done():
517
+ self._run_task.cancel()
518
+ try:
519
+ await self._run_task
520
+ except (Exception, asyncio.CancelledError):
521
+ pass
522
+
523
+ # Try to close the client cleanly
524
+ try:
525
+ if hasattr(self._client, "_transport"):
526
+ transport = self._client._transport
527
+ if transport and hasattr(transport, "_ws") and transport._ws:
485
528
  await transport._ws.close()
486
- except Exception as e:
487
- logger.warning(f"Error closing SignalR WebSocket: {e}")
529
+ except Exception as e:
530
+ logger.warning(f"Error closing SignalR WebSocket: {e}")
488
531
 
489
532
  async def emit_execution_started(self, execution_id: str, **kwargs) -> None:
490
533
  """Send execution started event."""
@@ -541,6 +584,9 @@ class SignalRDebugBridge(UiPathDebugBridge):
541
584
  error: str,
542
585
  ) -> None:
543
586
  """Send execution error event."""
587
+ if not self._connected_event.is_set():
588
+ return
589
+
544
590
  logger.error(f"Execution error: {execution_id} - {error}")
545
591
  await self._send(
546
592
  "OnExecutionError",
@@ -558,24 +604,139 @@ class SignalRDebugBridge(UiPathDebugBridge):
558
604
  logger.info("Resume command received")
559
605
  return self._resume_data
560
606
 
561
- def get_breakpoints(self) -> List[str]:
607
+ def get_breakpoints(self) -> List[str] | Literal["*"]:
562
608
  """Get nodes to suspend execution at."""
563
609
  if self.state.step_mode:
564
- return ["*"] # Suspend at all nodes
610
+ return "*" # Suspend at all nodes
565
611
  return list(self.state.breakpoints) # Only suspend at breakpoints
566
612
 
567
- async def _send(self, method: str, data: Dict[str, Any]) -> None:
568
- """Send message to SignalR hub."""
613
+ async def _send(self, event_name: str, data: Dict[str, Any]) -> None:
614
+ """Send message to SignalR hub via SendCommand.
615
+
616
+ Args:
617
+ event_name: The event/command name (e.g., "OnExecutionStarted")
618
+ data: The data payload to send
619
+ """
569
620
  if not self._client:
570
621
  raise RuntimeError("SignalR client not connected")
622
+ try:
623
+ # Wrap the event in SendCommand protocol
624
+ # Server expects: SendCommand(event_name, json_string_of_data)
625
+ data_json = json.dumps(data)
626
+ arguments: list[Any] = [event_name, data_json]
627
+ await self._client.send(method="SendCommand", arguments=arguments)
628
+ logger.debug(f"Sent command: {event_name} with data: {data}")
629
+ except Exception as e:
630
+ logger.error(f"Error sending command {event_name} to SignalR hub: {e}")
631
+
632
+ async def _handle_start(self, args: list[Any]) -> None:
633
+ """Handle Start command from SignalR server.
571
634
 
572
- await self._client.send(method=method, arguments=[data])
635
+ Args:
636
+ args: List containing command arguments, typically [dict_with_args]
637
+ """
638
+ logger.info(f"Start command received with args: {args}")
639
+ if not args or len(args) == 0:
640
+ logger.warning("Start command received with empty args.")
641
+ return
642
+
643
+ command_args = args[0] if isinstance(args[0], dict) else {}
644
+ self.state.breakpoints = set(command_args.get("breakpoints", []))
645
+ step_mode = command_args.get("enableStepMode", False)
646
+ self.state.step_mode = step_mode
573
647
 
574
648
  async def _handle_resume(self, args: list[Any]) -> None:
575
- """Handle resume command from SignalR server."""
576
- if self._resume_event and len(args) > 0:
577
- self._resume_data = args[0]
649
+ """Handle Resume command from SignalR server.
650
+
651
+ Args:
652
+ args: List containing command arguments
653
+ """
654
+ logger.info(f"Resume command received with args: {args}")
655
+ command_args = args[0] if args and len(args) > 0 else {}
656
+
657
+ if self._resume_event:
658
+ self._resume_data = command_args
578
659
  self._resume_event.set()
660
+ logger.info("Resume event set")
661
+ else:
662
+ logger.warning("Resume command received but no resume event is waiting")
663
+
664
+ async def _handle_step(self, args: list[Any]) -> None:
665
+ """Handle Step command from SignalR server.
666
+
667
+ Args:
668
+ args: List containing command arguments
669
+ """
670
+ logger.info(f"Step command received with args: {args}")
671
+ self.state.step_mode = True
672
+ logger.info("Step mode enabled")
673
+
674
+ async def _handle_add_breakpoints(self, args: list[Any]) -> None:
675
+ """Handle AddBreakpoints command from SignalR server.
676
+
677
+ Args:
678
+ args: List containing command arguments with breakpoints list
679
+ """
680
+ logger.info(f"AddBreakpoints command received with args: {args}")
681
+ if not args or len(args) == 0:
682
+ logger.warning("AddBreakpoints command received with empty args.")
683
+ return
684
+
685
+ command_args = args[0] if isinstance(args[0], dict) else {}
686
+ break_points = command_args.get("breakpoints", [])
687
+
688
+ for bp in break_points:
689
+ node_name = (
690
+ bp.get("node", {}).get("name")
691
+ if isinstance(bp.get("node"), dict)
692
+ else None
693
+ )
694
+ if node_name:
695
+ self.state.add_breakpoint(node_name)
696
+ logger.info(f"Breakpoint set at: {node_name}")
697
+ else:
698
+ logger.warning(f"Breakpoint command received without node name: {bp}")
699
+
700
+ async def _handle_remove_breakpoints(self, args: list[Any]) -> None:
701
+ """Handle RemoveBreakpoints command from SignalR server.
702
+
703
+ Args:
704
+ args: List containing command arguments with breakpoints list
705
+ """
706
+ logger.info(f"RemoveBreakpoints command received with args: {args}")
707
+ if not args or len(args) == 0:
708
+ self.state.clear_all_breakpoints()
709
+ logger.info("All breakpoints cleared")
710
+ return
711
+
712
+ command_args = args[0] if isinstance(args[0], dict) else {}
713
+ break_points = command_args.get("breakpoints", [])
714
+
715
+ if not break_points:
716
+ self.state.clear_all_breakpoints()
717
+ logger.info("All breakpoints cleared")
718
+ else:
719
+ for bp in break_points:
720
+ node_name = (
721
+ bp.get("node", {}).get("name")
722
+ if isinstance(bp.get("node"), dict)
723
+ else None
724
+ )
725
+ if node_name:
726
+ self.state.remove_breakpoint(node_name)
727
+ logger.info(f"Breakpoint removed: {node_name}")
728
+
729
+ async def _handle_quit(self, args: list[Any]) -> None:
730
+ """Handle Quit command from SignalR server.
731
+
732
+ Args:
733
+ args: List containing command arguments
734
+ """
735
+ if args:
736
+ logger.info(f"Quit command received from server with args: {args}")
737
+ else:
738
+ logger.info("Quit command received from server")
739
+ raise DebuggerQuitException("Quit command received from server")
579
740
 
580
741
  async def _handle_open(self) -> None:
581
742
  """Handle SignalR connection open."""
@@ -35,6 +35,7 @@ class UiPathDebugRuntime(UiPathBaseRuntime, Generic[T, C]):
35
35
  self.context: UiPathRuntimeContext = context
36
36
  self.factory: UiPathRuntimeFactory[T, C] = factory
37
37
  self.debug_bridge: UiPathDebugBridge = debug_bridge
38
+ self.execution_id: str = context.job_id or "default"
38
39
  self._inner_runtime: Optional[T] = None
39
40
 
40
41
  @classmethod
@@ -57,7 +58,7 @@ class UiPathDebugRuntime(UiPathBaseRuntime, Generic[T, C]):
57
58
  raise RuntimeError("Failed to create inner runtime")
58
59
 
59
60
  await self.debug_bridge.emit_execution_started(
60
- execution_id=self.context.job_id or "default"
61
+ execution_id=self.execution_id
61
62
  )
62
63
 
63
64
  # Try to stream events from inner runtime
@@ -78,8 +79,11 @@ class UiPathDebugRuntime(UiPathBaseRuntime, Generic[T, C]):
78
79
 
79
80
  except Exception as e:
80
81
  # Emit execution error
82
+ self.context.result = UiPathRuntimeResult(
83
+ status=UiPathRuntimeStatus.FAULTED,
84
+ )
81
85
  await self.debug_bridge.emit_execution_error(
82
- execution_id=self.context.job_id or "default",
86
+ execution_id=self.execution_id,
83
87
  error=str(e),
84
88
  )
85
89
  raise
@@ -8,7 +8,11 @@ from pydantic.alias_generators import to_camel
8
8
  from pydantic_core import core_schema
9
9
 
10
10
  from uipath._cli._runtime._contracts import UiPathRuntimeResult
11
- from uipath.eval.models.models import EvaluationResult, ScoreType
11
+ from uipath.eval.models.models import (
12
+ EvaluationResult,
13
+ ScoreType,
14
+ TrajectoryEvaluationTrace,
15
+ )
12
16
 
13
17
 
14
18
  class UiPathEvalRunExecutionOutput(BaseModel):
@@ -22,6 +26,22 @@ class UiPathEvalRunExecutionOutput(BaseModel):
22
26
  result: UiPathRuntimeResult
23
27
 
24
28
 
29
+ class UiPathSerializableEvalRunExecutionOutput(BaseModel):
30
+ execution_time: float
31
+ trace: TrajectoryEvaluationTrace
32
+ result: UiPathRuntimeResult
33
+
34
+
35
+ def convert_eval_execution_output_to_serializable(
36
+ output: UiPathEvalRunExecutionOutput,
37
+ ) -> UiPathSerializableEvalRunExecutionOutput:
38
+ return UiPathSerializableEvalRunExecutionOutput(
39
+ execution_time=output.execution_time,
40
+ result=output.result,
41
+ trace=TrajectoryEvaluationTrace.from_readable_spans(output.spans),
42
+ )
43
+
44
+
25
45
  class EvaluationResultDto(BaseModel):
26
46
  model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
27
47
 
@@ -67,19 +87,13 @@ class EvaluationRunResultDto(BaseModel):
67
87
  evaluator_id: str
68
88
  result: EvaluationResultDto
69
89
 
70
- @model_serializer(mode="wrap")
71
- def serialize_model(self, serializer, info):
72
- data = serializer(self)
73
- if isinstance(data, dict):
74
- data.pop("evaluatorId", None)
75
- return data
76
-
77
90
 
78
91
  class EvaluationRunResult(BaseModel):
79
92
  model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
80
93
 
81
94
  evaluation_name: str
82
95
  evaluation_run_results: List[EvaluationRunResultDto]
96
+ agent_execution_output: Optional[UiPathSerializableEvalRunExecutionOutput] = None
83
97
 
84
98
  @property
85
99
  def score(self) -> float:
@@ -38,6 +38,7 @@ from .._runtime._contracts import (
38
38
  )
39
39
  from .._runtime._logging import ExecutionLogHandler
40
40
  from .._utils._eval_set import EvalHelpers
41
+ from ..models.runtime_schema import Entrypoint
41
42
  from ._evaluator_factory import EvaluatorFactory
42
43
  from ._models._evaluation_set import (
43
44
  AnyEvaluationItem,
@@ -53,6 +54,7 @@ from ._models._output import (
53
54
  EvaluationRunResultDto,
54
55
  UiPathEvalOutput,
55
56
  UiPathEvalRunExecutionOutput,
57
+ convert_eval_execution_output_to_serializable,
56
58
  )
57
59
  from ._span_collection import ExecutionSpanCollector
58
60
  from .mocks.mocks import (
@@ -147,6 +149,7 @@ class UiPathEvalContext(UiPathRuntimeContext):
147
149
  workers: Optional[int] = 1
148
150
  eval_set: Optional[str] = None
149
151
  eval_ids: Optional[List[str]] = None
152
+ verbose: bool = False
150
153
 
151
154
 
152
155
  class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
@@ -173,6 +176,15 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
173
176
 
174
177
  self.logs_exporter: ExecutionLogsExporter = ExecutionLogsExporter()
175
178
  self.execution_id = str(uuid.uuid4())
179
+ self.entrypoint: Optional[Entrypoint] = None
180
+
181
+ async def get_entrypoint(self):
182
+ if not self.entrypoint:
183
+ temp_runtime = self.factory.new_runtime(
184
+ entrypoint=self.context.entrypoint, runtime_dir=os.getcwd()
185
+ )
186
+ self.entrypoint = await temp_runtime.get_entrypoint()
187
+ return self.entrypoint
176
188
 
177
189
  @classmethod
178
190
  def from_eval_context(
@@ -187,13 +199,6 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
187
199
  if self.context.eval_set is None:
188
200
  raise ValueError("eval_set must be provided for evaluation runs")
189
201
 
190
- # Get entrypoint from a temporary runtime
191
- temp_context = self.factory.new_context(
192
- entrypoint=self.context.entrypoint, runtime_dir=os.getcwd()
193
- )
194
- temp_runtime = self.factory.from_context(temp_context)
195
- self.entrypoint = await temp_runtime.get_entrypoint()
196
-
197
202
  event_bus = self.event_bus
198
203
 
199
204
  # Load eval set (path is already resolved in cli_eval.py)
@@ -360,6 +365,12 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
360
365
 
361
366
  try:
362
367
  agent_execution_output = await self.execute_runtime(eval_item, execution_id)
368
+ if self.context.verbose:
369
+ evaluation_run_results.agent_execution_output = (
370
+ convert_eval_execution_output_to_serializable(
371
+ agent_execution_output
372
+ )
373
+ )
363
374
  evaluation_item_results: list[EvalItemResult] = []
364
375
 
365
376
  for evaluator in evaluators:
@@ -477,7 +488,9 @@ class UiPathEvalRuntime(UiPathBaseRuntime, Generic[T, C]):
477
488
  self, eval_item: AnyEvaluationItem
478
489
  ) -> AnyEvaluationItem:
479
490
  """Use LLM to generate a mock input for an evaluation item."""
480
- generated_input = await generate_llm_input(eval_item, self.entrypoint.input)
491
+ generated_input = await generate_llm_input(
492
+ eval_item, (await self.get_entrypoint()).input
493
+ )
481
494
  updated_eval_item = eval_item.model_copy(update={"inputs": generated_input})
482
495
  return updated_eval_item
483
496
 
@@ -382,7 +382,7 @@ class UiPathRuntimeContext(BaseModel):
382
382
  log_handler: Optional[logging.Handler] = None
383
383
  chat_handler: Optional[UiPathConversationHandler] = None
384
384
  is_conversational: Optional[bool] = None
385
- breakpoints: Optional[List[str]] = None
385
+ breakpoints: Optional[List[str] | Literal["*"]] = None
386
386
 
387
387
  model_config = {"arbitrary_types_allowed": True, "extra": "allow"}
388
388
 
@@ -536,6 +536,7 @@ class UiPathRuntimeError(UiPathBaseRuntimeError):
536
536
  title: str,
537
537
  detail: str,
538
538
  category: UiPathErrorCategory = UiPathErrorCategory.UNKNOWN,
539
+ status: Optional[int] = None,
539
540
  prefix: str = "Python",
540
541
  include_traceback: bool = True,
541
542
  ):
@@ -544,6 +545,7 @@ class UiPathRuntimeError(UiPathBaseRuntimeError):
544
545
  title=title,
545
546
  detail=detail,
546
547
  category=category,
548
+ status=status,
547
549
  prefix=prefix,
548
550
  include_traceback=include_traceback,
549
551
  )
@@ -127,19 +127,19 @@ Documents service
127
127
  # Create a validation action for a document based on the extraction response. More details about validation actions can be found in the [official documentation](https://docs.uipath.com/ixp/automation-cloud/latest/user-guide/validating-extractions).
128
128
  sdk.documents.create_validation_action(action_title: str, action_priority: <enum 'ActionPriority, action_catalog: str, action_folder: str, storage_bucket_name: str, storage_bucket_directory_path: str, extraction_response: uipath.models.documents.ExtractionResponse) -> uipath.models.documents.ValidationAction
129
129
 
130
- # Asynchronously create a validation action for a document based on the extraction response.
130
+ # Asynchronous version of the [`create_validation_action`][uipath._services.documents_service.DocumentsService.create_validation_action] method.
131
131
  sdk.documents.create_validation_action_async(action_title: str, action_priority: <enum 'ActionPriority, action_catalog: str, action_folder: str, storage_bucket_name: str, storage_bucket_directory_path: str, extraction_response: uipath.models.documents.ExtractionResponse) -> uipath.models.documents.ValidationAction
132
132
 
133
133
  # Extract predicted data from a document using an IXP project.
134
- sdk.documents.extract(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None) -> uipath.models.documents.ExtractionResponse
134
+ sdk.documents.extract(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None, project_type: <enum 'ProjectType="IXP", document_type_name: Optional[str]=None) -> typing.Union[uipath.models.documents.ExtractionResponse, uipath.models.documents.ExtractionResponseIXP]
135
135
 
136
- # Asynchronously extract predicted data from a document using an IXP project.
137
- sdk.documents.extract_async(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None) -> uipath.models.documents.ExtractionResponse
136
+ # Asynchronously version of the [`extract`][uipath._services.documents_service.DocumentsService.extract] method.
137
+ sdk.documents.extract_async(project_name: str, tag: str, file: Union[IO[bytes], bytes, str, NoneType]=None, file_path: Optional[str]=None, project_type: <enum 'ProjectType="IXP", document_type_name: Optional[str]=None) -> typing.Union[uipath.models.documents.ExtractionResponse, uipath.models.documents.ExtractionResponseIXP]
138
138
 
139
139
  # Get the result of a validation action.
140
140
  sdk.documents.get_validation_result(validation_action: uipath.models.documents.ValidationAction) -> uipath.models.documents.ValidatedResult
141
141
 
142
- # Asynchronously get the result of a validation action.
142
+ # Asynchronous version of the [`get_validation_result`][uipath._services.documents_service.DocumentsService.get_validation_result] method.
143
143
  sdk.documents.get_validation_result_async(validation_action: uipath.models.documents.ValidationAction) -> uipath.models.documents.ValidatedResult
144
144
 
145
145
  ```