uipath-core 0.2.4__tar.gz → 0.3.1__tar.gz
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.
- {uipath_core-0.2.4 → uipath_core-0.3.1}/PKG-INFO +1 -1
- {uipath_core-0.2.4 → uipath_core-0.3.1}/pyproject.toml +1 -1
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/__init__.py +14 -0
- uipath_core-0.3.1/src/uipath/core/chat/interrupt.py +92 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/guardrails/guardrails.py +34 -2
- uipath_core-0.3.1/tests/guardrails/test_guardrails_models.py +53 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/uv.lock +1 -1
- uipath_core-0.2.4/src/uipath/core/chat/interrupt.py +0 -35
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.cursorrules +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.editorconfig +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.gitattributes +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.github/workflows/cd.yml +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.github/workflows/ci.yml +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.github/workflows/commitlint.yml +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.github/workflows/lint.yml +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.github/workflows/publish-dev.yml +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.github/workflows/test.yml +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.gitignore +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.pre-commit-config.yaml +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.python-version +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.vscode/extensions.json +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.vscode/launch.json +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/.vscode/settings.json +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/CONTRIBUTING.md +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/LICENSE +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/README.md +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/justfile +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/__init__.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/async_stream.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/citation.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/content.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/conversation.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/error.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/event.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/exchange.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/message.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/meta.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/chat/tool.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/errors/__init__.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/errors/errors.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/guardrails/__init__.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/guardrails/_deterministic_guardrails_service.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/guardrails/_evaluators.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/py.typed +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/serialization/__init__.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/serialization/json.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/__init__.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/_utils.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/decorators.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/exporters.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/processors.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/span_utils.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/trace_manager.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/src/uipath/core/tracing/types.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/__init__.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/conftest.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/guardrails/test_deterministic_guardrails_service.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/serialization/test_json.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_external_integration.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_serialization.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_span_filtering.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_span_nesting.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_span_registry.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_trace_manager.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_traced.py +0 -0
- {uipath_core-0.2.4 → uipath_core-0.3.1}/tests/tracing/test_tracing_utils.py +0 -0
|
@@ -79,9 +79,16 @@ from .exchange import (
|
|
|
79
79
|
UiPathConversationExchangeStartEvent,
|
|
80
80
|
)
|
|
81
81
|
from .interrupt import (
|
|
82
|
+
InterruptTypeEnum,
|
|
83
|
+
UiPathConversationGenericInterruptEndEvent,
|
|
84
|
+
UiPathConversationGenericInterruptStartEvent,
|
|
82
85
|
UiPathConversationInterruptEndEvent,
|
|
83
86
|
UiPathConversationInterruptEvent,
|
|
84
87
|
UiPathConversationInterruptStartEvent,
|
|
88
|
+
UiPathConversationToolCallConfirmationEndValue,
|
|
89
|
+
UiPathConversationToolCallConfirmationInterruptEndEvent,
|
|
90
|
+
UiPathConversationToolCallConfirmationInterruptStartEvent,
|
|
91
|
+
UiPathConversationToolCallConfirmationValue,
|
|
85
92
|
)
|
|
86
93
|
from .message import (
|
|
87
94
|
UiPathConversationMessage,
|
|
@@ -122,9 +129,16 @@ __all__ = [
|
|
|
122
129
|
"UiPathConversationMessageEvent",
|
|
123
130
|
"UiPathConversationMessage",
|
|
124
131
|
# Interrupt
|
|
132
|
+
"InterruptTypeEnum",
|
|
125
133
|
"UiPathConversationInterruptStartEvent",
|
|
126
134
|
"UiPathConversationInterruptEndEvent",
|
|
127
135
|
"UiPathConversationInterruptEvent",
|
|
136
|
+
"UiPathConversationToolCallConfirmationValue",
|
|
137
|
+
"UiPathConversationToolCallConfirmationEndValue",
|
|
138
|
+
"UiPathConversationToolCallConfirmationInterruptStartEvent",
|
|
139
|
+
"UiPathConversationToolCallConfirmationInterruptEndEvent",
|
|
140
|
+
"UiPathConversationGenericInterruptStartEvent",
|
|
141
|
+
"UiPathConversationGenericInterruptEndEvent",
|
|
128
142
|
# Content
|
|
129
143
|
"UiPathConversationContentPartChunkEvent",
|
|
130
144
|
"UiPathConversationContentPartStartEvent",
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Interrupt events for human-in-the-loop patterns."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Any, Literal, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class InterruptTypeEnum(str, Enum):
|
|
10
|
+
"""Enum of known interrupt types."""
|
|
11
|
+
|
|
12
|
+
TOOL_CALL_CONFIRMATION = "uipath_cas_tool_call_confirmation"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class UiPathConversationToolCallConfirmationValue(BaseModel):
|
|
16
|
+
"""Schema for tool call confirmation interrupt value."""
|
|
17
|
+
|
|
18
|
+
tool_call_id: str = Field(..., alias="toolCallId")
|
|
19
|
+
tool_name: str = Field(..., alias="toolName")
|
|
20
|
+
input_schema: Any = Field(..., alias="inputSchema")
|
|
21
|
+
input_value: Any | None = Field(None, alias="inputValue")
|
|
22
|
+
|
|
23
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class UiPathConversationToolCallConfirmationInterruptStartEvent(BaseModel):
|
|
27
|
+
"""Tool call confirmation interrupt start event with strong typing."""
|
|
28
|
+
|
|
29
|
+
type: Literal["uipath_cas_tool_call_confirmation"]
|
|
30
|
+
value: UiPathConversationToolCallConfirmationValue
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class UiPathConversationGenericInterruptStartEvent(BaseModel):
|
|
36
|
+
"""Generic interrupt start event for custom interrupt types."""
|
|
37
|
+
|
|
38
|
+
type: str
|
|
39
|
+
value: Any
|
|
40
|
+
|
|
41
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
UiPathConversationInterruptStartEvent = Union[
|
|
45
|
+
UiPathConversationToolCallConfirmationInterruptStartEvent,
|
|
46
|
+
UiPathConversationGenericInterruptStartEvent,
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class UiPathConversationToolCallConfirmationEndValue(BaseModel):
|
|
51
|
+
"""Schema for tool call confirmation end value."""
|
|
52
|
+
|
|
53
|
+
approved: bool
|
|
54
|
+
input: Any | None = None
|
|
55
|
+
|
|
56
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class UiPathConversationToolCallConfirmationInterruptEndEvent(BaseModel):
|
|
60
|
+
"""Tool call confirmation interrupt end event with strong typing."""
|
|
61
|
+
|
|
62
|
+
type: Literal["uipath_cas_tool_call_confirmation"]
|
|
63
|
+
value: UiPathConversationToolCallConfirmationEndValue
|
|
64
|
+
|
|
65
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class UiPathConversationGenericInterruptEndEvent(BaseModel):
|
|
69
|
+
"""Generic interrupt end event for custom interrupt types."""
|
|
70
|
+
|
|
71
|
+
type: str
|
|
72
|
+
value: Any
|
|
73
|
+
|
|
74
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
UiPathConversationInterruptEndEvent = Union[
|
|
78
|
+
UiPathConversationToolCallConfirmationInterruptEndEvent,
|
|
79
|
+
UiPathConversationGenericInterruptEndEvent,
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class UiPathConversationInterruptEvent(BaseModel):
|
|
84
|
+
"""Encapsulates interrupt-related events within a message."""
|
|
85
|
+
|
|
86
|
+
interrupt_id: str = Field(..., alias="interruptId")
|
|
87
|
+
start: UiPathConversationInterruptStartEvent | None = Field(
|
|
88
|
+
None, alias="startInterrupt"
|
|
89
|
+
)
|
|
90
|
+
end: UiPathConversationInterruptEndEvent | None = Field(None, alias="endInterrupt")
|
|
91
|
+
|
|
92
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
"""Guardrails models for UiPath Platform."""
|
|
2
2
|
|
|
3
3
|
from enum import Enum
|
|
4
|
-
from typing import Annotated, Callable, Literal
|
|
4
|
+
from typing import Annotated, Any, Callable, Literal
|
|
5
5
|
|
|
6
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _decapitalize_first_letter(s: str) -> str:
|
|
10
|
+
"""Convert first letter to lowercase (e.g., 'SimpleText' -> 'simpleText')."""
|
|
11
|
+
if not s or len(s) == 0:
|
|
12
|
+
return s
|
|
13
|
+
if len(s) == 1:
|
|
14
|
+
return s.lower()
|
|
15
|
+
return s[0].lower() + s[1:]
|
|
7
16
|
|
|
8
17
|
|
|
9
18
|
class GuardrailValidationResultType(str, Enum):
|
|
@@ -56,6 +65,12 @@ class FieldReference(BaseModel):
|
|
|
56
65
|
|
|
57
66
|
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
58
67
|
|
|
68
|
+
@field_validator("source", mode="before")
|
|
69
|
+
@classmethod
|
|
70
|
+
def normalize_type(cls, v: Any) -> Any:
|
|
71
|
+
"""Normalize type by decapitalizing first letter."""
|
|
72
|
+
return _decapitalize_first_letter(v) if isinstance(v, str) else v
|
|
73
|
+
|
|
59
74
|
|
|
60
75
|
class SelectorType(str, Enum):
|
|
61
76
|
"""Selector type enumeration."""
|
|
@@ -72,6 +87,17 @@ class AllFieldsSelector(BaseModel):
|
|
|
72
87
|
|
|
73
88
|
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
74
89
|
|
|
90
|
+
@field_validator("sources", mode="before")
|
|
91
|
+
@classmethod
|
|
92
|
+
def normalize_sources(cls, v: Any) -> Any:
|
|
93
|
+
"""Normalize sources by decapitalizing first letter of each item."""
|
|
94
|
+
if isinstance(v, list):
|
|
95
|
+
return [
|
|
96
|
+
_decapitalize_first_letter(item) if isinstance(item, str) else item
|
|
97
|
+
for item in v
|
|
98
|
+
]
|
|
99
|
+
return v
|
|
100
|
+
|
|
75
101
|
|
|
76
102
|
class SpecificFieldsSelector(BaseModel):
|
|
77
103
|
"""Specific fields selector."""
|
|
@@ -128,6 +154,12 @@ class UniversalRule(BaseModel):
|
|
|
128
154
|
|
|
129
155
|
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
130
156
|
|
|
157
|
+
@field_validator("apply_to", mode="before")
|
|
158
|
+
@classmethod
|
|
159
|
+
def normalize_type(cls, v: Any) -> Any:
|
|
160
|
+
"""Normalize type by decapitalizing first letter."""
|
|
161
|
+
return _decapitalize_first_letter(v) if isinstance(v, str) else v
|
|
162
|
+
|
|
131
163
|
|
|
132
164
|
class NumberRule(BaseModel):
|
|
133
165
|
"""Number rule model."""
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Tests for guardrails models normalization validators."""
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from uipath.core.guardrails import (
|
|
6
|
+
AllFieldsSelector,
|
|
7
|
+
FieldReference,
|
|
8
|
+
FieldSource,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestGuardrailsModelsNormalization:
|
|
16
|
+
"""Test guardrails models field normalization."""
|
|
17
|
+
|
|
18
|
+
def test_field_reference_normalizes_capitalized_source(
|
|
19
|
+
self,
|
|
20
|
+
) -> None:
|
|
21
|
+
"""Test that FieldReference normalizes capitalized source values to lowercase."""
|
|
22
|
+
# Create FieldReference with capitalized "Input" - should normalize to FieldSource.INPUT
|
|
23
|
+
field_ref = FieldReference(path="testField", source="Input") # type: ignore[arg-type]
|
|
24
|
+
assert field_ref.source == FieldSource.INPUT
|
|
25
|
+
|
|
26
|
+
# Create FieldReference with capitalized "Output" - should normalize to FieldSource.OUTPUT
|
|
27
|
+
field_ref = FieldReference(path="testField", source="Output") # type: ignore[arg-type]
|
|
28
|
+
assert field_ref.source == FieldSource.OUTPUT
|
|
29
|
+
|
|
30
|
+
# Create FieldReference with lowercase "input" - should work as-is
|
|
31
|
+
field_ref = FieldReference(path="testField", source="input") # type: ignore[arg-type]
|
|
32
|
+
assert field_ref.source == FieldSource.INPUT
|
|
33
|
+
|
|
34
|
+
def test_all_fields_selector_normalizes_capitalized_sources(
|
|
35
|
+
self,
|
|
36
|
+
) -> None:
|
|
37
|
+
"""Test that AllFieldsSelector normalizes capitalized source values in the list."""
|
|
38
|
+
# Create AllFieldsSelector with capitalized "Input" and "Output" - should normalize
|
|
39
|
+
selector = AllFieldsSelector(
|
|
40
|
+
selector_type="all",
|
|
41
|
+
sources=["Input", "Output"], # type: ignore[list-item]
|
|
42
|
+
)
|
|
43
|
+
assert FieldSource.INPUT in selector.sources
|
|
44
|
+
assert FieldSource.OUTPUT in selector.sources
|
|
45
|
+
assert len(selector.sources) == 2
|
|
46
|
+
|
|
47
|
+
# Create AllFieldsSelector with mixed case - should normalize all
|
|
48
|
+
selector = AllFieldsSelector(
|
|
49
|
+
selector_type="all",
|
|
50
|
+
sources=["Input", "output"], # type: ignore[list-item]
|
|
51
|
+
)
|
|
52
|
+
assert FieldSource.INPUT in selector.sources
|
|
53
|
+
assert FieldSource.OUTPUT in selector.sources
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
"""Interrupt events for human-in-the-loop patterns."""
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class UiPathConversationInterruptStartEvent(BaseModel):
|
|
9
|
-
"""Signals the start of an interrupt - a pause point where the agent needs external input."""
|
|
10
|
-
|
|
11
|
-
type: str
|
|
12
|
-
value: Any
|
|
13
|
-
|
|
14
|
-
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
class UiPathConversationInterruptEndEvent(BaseModel):
|
|
18
|
-
"""Signals the interrupt end event with the provided value."""
|
|
19
|
-
|
|
20
|
-
# Can be any type
|
|
21
|
-
model_config = ConfigDict(
|
|
22
|
-
validate_by_name=True, validate_by_alias=True, extra="allow"
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class UiPathConversationInterruptEvent(BaseModel):
|
|
27
|
-
"""Encapsulates interrupt-related events within a message."""
|
|
28
|
-
|
|
29
|
-
interrupt_id: str = Field(..., alias="interruptId")
|
|
30
|
-
start: UiPathConversationInterruptStartEvent | None = Field(
|
|
31
|
-
None, alias="startInterrupt"
|
|
32
|
-
)
|
|
33
|
-
end: Any | None = Field(None, alias="endInterrupt")
|
|
34
|
-
|
|
35
|
-
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{uipath_core-0.2.4 → uipath_core-0.3.1}/tests/guardrails/test_deterministic_guardrails_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|