uipath-core 0.1.4__py3-none-any.whl → 0.1.6__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.
@@ -16,6 +16,7 @@ from .guardrails import (
16
16
  GuardrailScope,
17
17
  GuardrailSelector,
18
18
  GuardrailValidationResult,
19
+ GuardrailValidationResultType,
19
20
  NumberRule,
20
21
  Rule,
21
22
  SelectorType,
@@ -43,4 +44,5 @@ __all__ = [
43
44
  "GuardrailScope",
44
45
  "GuardrailSelector",
45
46
  "GuardrailValidationResult",
47
+ "GuardrailValidationResultType",
46
48
  ]
@@ -10,10 +10,15 @@ from ._evaluators import (
10
10
  evaluate_word_rule,
11
11
  )
12
12
  from .guardrails import (
13
+ AllFieldsSelector,
14
+ ApplyTo,
13
15
  BooleanRule,
14
16
  DeterministicGuardrail,
17
+ FieldSource,
15
18
  GuardrailValidationResult,
19
+ GuardrailValidationResultType,
16
20
  NumberRule,
21
+ SpecificFieldsSelector,
17
22
  UniversalRule,
18
23
  WordRule,
19
24
  )
@@ -27,6 +32,16 @@ class DeterministicGuardrailsService(BaseModel):
27
32
  guardrail: DeterministicGuardrail,
28
33
  ) -> GuardrailValidationResult:
29
34
  """Evaluate deterministic guardrail rules against input data (pre-execution)."""
35
+ # Check if guardrail contains any output-dependent rules
36
+ has_output_rule = self._has_output_dependent_rule(guardrail, [ApplyTo.OUTPUT])
37
+
38
+ # If guardrail has output-dependent rules, skip evaluation in pre-execution
39
+ # Output rules will be evaluated during post-execution
40
+ if has_output_rule:
41
+ return GuardrailValidationResult(
42
+ result=GuardrailValidationResultType.PASSED,
43
+ reason="Guardrail contains output-dependent rules that will be evaluated during post-execution",
44
+ )
30
45
  return self._evaluate_deterministic_guardrail(
31
46
  input_data=input_data,
32
47
  output_data={},
@@ -41,12 +56,61 @@ class DeterministicGuardrailsService(BaseModel):
41
56
  guardrail: DeterministicGuardrail,
42
57
  ) -> GuardrailValidationResult:
43
58
  """Evaluate deterministic guardrail rules against input and output data."""
59
+ # Check if guardrail contains any output-dependent rules
60
+ has_output_rule = self._has_output_dependent_rule(
61
+ guardrail, [ApplyTo.OUTPUT, ApplyTo.INPUT_AND_OUTPUT]
62
+ )
63
+
64
+ # If guardrail has no output-dependent rules, skip post-execution evaluation
65
+ # Only input rules exist and they should have been evaluated during pre-execution
66
+ if not has_output_rule:
67
+ return GuardrailValidationResult(
68
+ result=GuardrailValidationResultType.PASSED,
69
+ reason="Guardrail contains only input-dependent rules that were evaluated during pre-execution",
70
+ )
71
+
44
72
  return self._evaluate_deterministic_guardrail(
45
73
  input_data=input_data,
46
74
  output_data=output_data,
47
75
  guardrail=guardrail,
48
76
  )
49
77
 
78
+ @staticmethod
79
+ def _has_output_dependent_rule(
80
+ guardrail: DeterministicGuardrail,
81
+ universal_rules_apply_to_values: list[ApplyTo],
82
+ ) -> bool:
83
+ """Check if at least one rule EXCLUSIVELY requires output data.
84
+
85
+ Args:
86
+ guardrail: The guardrail to check
87
+ universal_rules_apply_to_values: List of ApplyTo values to consider as output-dependent for UniversalRules.
88
+
89
+ Returns:
90
+ True if at least one rule exclusively depends on output data, False otherwise.
91
+ """
92
+ for rule in guardrail.rules:
93
+ # UniversalRule: only return True if it applies to values in universal_rules_apply_to_values
94
+ if isinstance(rule, UniversalRule):
95
+ if rule.apply_to in universal_rules_apply_to_values:
96
+ return True
97
+ # Rules with field_selector
98
+ elif isinstance(rule, (WordRule, NumberRule, BooleanRule)):
99
+ field_selector = rule.field_selector
100
+ # AllFieldsSelector applies to both input and output, not exclusively output
101
+ # SpecificFieldsSelector: only return True if at least one field has OUTPUT source
102
+ if isinstance(field_selector, SpecificFieldsSelector):
103
+ if field_selector.fields and any(
104
+ field.source == FieldSource.OUTPUT
105
+ for field in field_selector.fields
106
+ ):
107
+ return True
108
+ elif isinstance(field_selector, AllFieldsSelector):
109
+ if FieldSource.OUTPUT in field_selector.sources:
110
+ return True
111
+
112
+ return False
113
+
50
114
  @staticmethod
51
115
  def _evaluate_deterministic_guardrail(
52
116
  input_data: dict[str, Any],
@@ -65,15 +129,17 @@ class DeterministicGuardrailsService(BaseModel):
65
129
  passed, reason = evaluate_universal_rule(rule, output_data)
66
130
  else:
67
131
  return GuardrailValidationResult(
68
- validation_passed=False,
132
+ result=GuardrailValidationResultType.VALIDATION_FAILED,
69
133
  reason=f"Unknown rule type: {type(rule)}",
70
134
  )
71
135
 
72
136
  if not passed:
73
137
  return GuardrailValidationResult(
74
- validation_passed=False, reason=reason or "Rule validation failed"
138
+ result=GuardrailValidationResultType.VALIDATION_FAILED,
139
+ reason=reason or "Rule validation failed",
75
140
  )
76
141
 
77
142
  return GuardrailValidationResult(
78
- validation_passed=True, reason="All deterministic guardrail rules passed"
143
+ result=GuardrailValidationResultType.PASSED,
144
+ reason="All deterministic guardrail rules passed",
79
145
  )
@@ -120,23 +120,25 @@ def get_fields_from_selector(
120
120
  fields: list[tuple[Any, FieldReference]] = []
121
121
 
122
122
  if isinstance(field_selector, AllFieldsSelector):
123
- # For "all" selector, we need to collect all fields from both input and output
123
+ # For "all" selector, we need to collect all fields from the specified sources
124
124
  # This is a simplified implementation - in practice, you might want to
125
125
  # recursively collect all nested fields
126
- for key, value in input_data.items():
127
- fields.append(
128
- (
129
- value,
130
- FieldReference(path=key, source=FieldSource.INPUT),
126
+ if FieldSource.INPUT in field_selector.sources:
127
+ for key, value in input_data.items():
128
+ fields.append(
129
+ (
130
+ value,
131
+ FieldReference(path=key, source=FieldSource.INPUT),
132
+ )
131
133
  )
132
- )
133
- for key, value in output_data.items():
134
- fields.append(
135
- (
136
- value,
137
- FieldReference(path=key, source=FieldSource.OUTPUT),
134
+ if FieldSource.OUTPUT in field_selector.sources:
135
+ for key, value in output_data.items():
136
+ fields.append(
137
+ (
138
+ value,
139
+ FieldReference(path=key, source=FieldSource.OUTPUT),
140
+ )
138
141
  )
139
- )
140
142
  elif isinstance(field_selector, SpecificFieldsSelector):
141
143
  # For specific fields, extract values based on field references
142
144
  for field_ref in field_selector.fields:
@@ -286,13 +288,13 @@ def evaluate_universal_rule(
286
288
 
287
289
  Universal rules trigger based on the apply_to scope and execution phase:
288
290
  - Pre-execution (empty output_data):
289
- - INPUT: triggers (validation_passed = False)
290
- - OUTPUT: does not trigger (validation_passed = True)
291
- - INPUT_AND_OUTPUT: triggers (validation_passed = False)
291
+ - INPUT: triggers (result = VALIDATION_FAILED)
292
+ - OUTPUT: does not trigger (result = PASSED)
293
+ - INPUT_AND_OUTPUT: triggers (result = VALIDATION_FAILED)
292
294
  - Post-execution (output_data has data):
293
- - INPUT: does not trigger (validation_passed = True)
294
- - OUTPUT: triggers (validation_passed = False)
295
- - INPUT_AND_OUTPUT: triggers (validation_passed = False)
295
+ - INPUT: does not trigger (result = PASSED)
296
+ - OUTPUT: triggers (result = VALIDATION_FAILED)
297
+ - INPUT_AND_OUTPUT: triggers (result = VALIDATION_FAILED)
296
298
  """
297
299
  # Determine if this is pre-execution (no output data) or post-execution
298
300
  is_pre_execution = not output_data or len(output_data) == 0
@@ -6,18 +6,27 @@ from typing import Annotated, Callable, Literal
6
6
  from pydantic import BaseModel, ConfigDict, Field
7
7
 
8
8
 
9
+ class GuardrailValidationResultType(str, Enum):
10
+ """Guardrail validation result type enumeration."""
11
+
12
+ PASSED = "passed"
13
+ VALIDATION_FAILED = "validation_failed"
14
+ ENTITLEMENTS_MISSING = "entitlements_missing"
15
+ FEATURE_DISABLED = "feature_disabled"
16
+
17
+
9
18
  class GuardrailValidationResult(BaseModel):
10
19
  """Result returned from validating input with a given guardrail.
11
20
 
12
21
  Attributes:
13
- validation_passed: Indicates whether the input data passed the guardrail validation.
22
+ result: The validation result type.
14
23
  reason: Textual explanation describing why the validation passed or failed.
15
24
  """
16
25
 
17
26
  model_config = ConfigDict(populate_by_name=True)
18
27
 
19
- validation_passed: bool = Field(
20
- alias="validation_passed", description="Whether the input passed validation."
28
+ result: GuardrailValidationResultType = Field(
29
+ alias="result", description="Validation result."
21
30
  )
22
31
  reason: str = Field(
23
32
  alias="reason", description="Explanation for the validation result."
@@ -59,6 +68,7 @@ class AllFieldsSelector(BaseModel):
59
68
  """All fields selector."""
60
69
 
61
70
  selector_type: Literal["all"] = Field(alias="$selectorType")
71
+ sources: list[FieldSource]
62
72
 
63
73
  model_config = ConfigDict(populate_by_name=True, extra="allow")
64
74
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: uipath-core
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: UiPath Core abstractions
5
5
  Project-URL: Homepage, https://uipath.com
6
6
  Project-URL: Repository, https://github.com/UiPath/uipath-core-python
@@ -14,10 +14,10 @@ uipath/core/chat/meta.py,sha256=3t0eS9UHoAPHre97QTUeVbjDhnMX4zj4-qG6ju0B8wY,315
14
14
  uipath/core/chat/tool.py,sha256=6e5pyX3hOWM5fIzr_fdG49Mbzz6XzJD3nsmha-yGa2k,2308
15
15
  uipath/core/errors/__init__.py,sha256=gjxdLibZ0fjwgzPuLJY04P8dIX9rbSM2wQ97jP34ucE,278
16
16
  uipath/core/errors/errors.py,sha256=5LajjuTfNW82ju07wT5mD3tXk0S-Ju7OqJqQpPN0F6g,486
17
- uipath/core/guardrails/__init__.py,sha256=baH9Vj8f6spKOpxv3dUl5UKg-LWthaoZ0RidtlFjyEQ,956
18
- uipath/core/guardrails/_deterministic_guardrails_service.py,sha256=3WGcgpyUIvTXBvheEXjX-XguytxquWJkBevrVeM2tcc,2841
19
- uipath/core/guardrails/_evaluators.py,sha256=5llj14Xh1mzREh8JC9LjsymGsuGrz8x6Sv6K5s4P1sE,14446
20
- uipath/core/guardrails/guardrails.py,sha256=X2EVZVhD2PSXmfudgLdPB9ccsyqfPWESzuOzH9MGCrg,4703
17
+ uipath/core/guardrails/__init__.py,sha256=hUCmD4y5te2iy01YnJlBuf2RWvqxmsNzoyOamXLXf2E,1028
18
+ uipath/core/guardrails/_deterministic_guardrails_service.py,sha256=uX8f2HSGZ1bf5QFM9fnz0CvglxI3UIqY4OhHrKzemaU,5967
19
+ uipath/core/guardrails/_evaluators.py,sha256=ovmVm-8iB8Pm9arjG7mHM9-GIRkrG3V6oHRPHKxZVO0,14601
20
+ uipath/core/guardrails/guardrails.py,sha256=DraeFkoDKVDnc0EKdFYYP29lQu7U2hneTsj1dxveHU4,4935
21
21
  uipath/core/tracing/__init__.py,sha256=1XNLYZ4J76XkRrizGO486mS6yxzVXUbrldpvxTyJe3E,483
22
22
  uipath/core/tracing/_utils.py,sha256=FiCFGOFa4czruhlSF87Q5Q4jX9KKPHZiw8k14K7W5v4,6636
23
23
  uipath/core/tracing/decorators.py,sha256=ag_MFwZ0TywrhbpLKqQwF1guvRA9sYiItxao5LN9_Iw,10942
@@ -25,7 +25,7 @@ uipath/core/tracing/exporters.py,sha256=FClouEEQfk3F8J7G_NFoarDJM3R0-gA5jUxA5xRH
25
25
  uipath/core/tracing/processors.py,sha256=R_652rtjPmfpUtaXoIcmfZrRZylVXFRNwjOmJUUxOQw,1408
26
26
  uipath/core/tracing/span_utils.py,sha256=WYBrd6ZbawAs7r1Js-Zvo9_8GzkD9LhHNOls00bK_xI,12235
27
27
  uipath/core/tracing/trace_manager.py,sha256=51rscJcepkTK4bWoCZdE-DFc9wt2F-aSuFBaSXmkHl0,3130
28
- uipath_core-0.1.4.dist-info/METADATA,sha256=z8rkXBn1096teW-f17J-a5QNegco4Qm02xWVvutjwQQ,938
29
- uipath_core-0.1.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
30
- uipath_core-0.1.4.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
31
- uipath_core-0.1.4.dist-info/RECORD,,
28
+ uipath_core-0.1.6.dist-info/METADATA,sha256=R2wS5I85yHd-uTvGgepwbhKiZA7cLb389XJ5R57ED7I,938
29
+ uipath_core-0.1.6.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
30
+ uipath_core-0.1.6.dist-info/licenses/LICENSE,sha256=-KBavWXepyDjimmzH5fVAsi-6jNVpIKFc2kZs0Ri4ng,1058
31
+ uipath_core-0.1.6.dist-info/RECORD,,