langgraph-api 0.2.44__py3-none-any.whl → 0.2.45__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 langgraph-api might be problematic. Click here for more details.
- langgraph_api/__init__.py +1 -1
- langgraph_api/js/remote.py +22 -15
- langgraph_api/logging.py +16 -3
- langgraph_api/models/run.py +12 -0
- langgraph_api/stream.py +28 -2
- {langgraph_api-0.2.44.dist-info → langgraph_api-0.2.45.dist-info}/METADATA +3 -3
- {langgraph_api-0.2.44.dist-info → langgraph_api-0.2.45.dist-info}/RECORD +18 -10
- langgraph_runtime/checkpoint.py +4 -0
- langgraph_runtime/database.py +4 -0
- langgraph_runtime/lifespan.py +4 -0
- langgraph_runtime/metrics.py +4 -0
- langgraph_runtime/ops.py +4 -0
- langgraph_runtime/queue.py +4 -0
- langgraph_runtime/retry.py +4 -0
- langgraph_runtime/store.py +4 -0
- {langgraph_api-0.2.44.dist-info → langgraph_api-0.2.45.dist-info}/WHEEL +0 -0
- {langgraph_api-0.2.44.dist-info → langgraph_api-0.2.45.dist-info}/entry_points.txt +0 -0
- {langgraph_api-0.2.44.dist-info → langgraph_api-0.2.45.dist-info}/licenses/LICENSE +0 -0
langgraph_api/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.2.
|
|
1
|
+
__version__ = "0.2.45"
|
langgraph_api/js/remote.py
CHANGED
|
@@ -452,27 +452,27 @@ async def run_js_http_process(paths_str: str, http_config: dict, watch: bool = F
|
|
|
452
452
|
attempt += 1
|
|
453
453
|
|
|
454
454
|
|
|
455
|
-
|
|
456
|
-
|
|
455
|
+
class PassthroughSerialiser(SerializerProtocol):
|
|
456
|
+
def dumps(self, obj: Any) -> bytes:
|
|
457
|
+
return json_dumpb(obj)
|
|
457
458
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
return json_dumpb(obj)
|
|
459
|
+
def dumps_typed(self, obj: Any) -> tuple[str, bytes]:
|
|
460
|
+
return "json", json_dumpb(obj)
|
|
461
461
|
|
|
462
|
-
|
|
463
|
-
|
|
462
|
+
def loads(self, data: bytes) -> Any:
|
|
463
|
+
return orjson.loads(data)
|
|
464
464
|
|
|
465
|
-
|
|
466
|
-
|
|
465
|
+
def loads_typed(self, data: tuple[str, bytes]) -> Any:
|
|
466
|
+
type, payload = data
|
|
467
|
+
if type != "json":
|
|
468
|
+
raise ValueError(f"Unsupported type {type}")
|
|
469
|
+
return orjson.loads(payload)
|
|
467
470
|
|
|
468
|
-
def loads_typed(self, data: tuple[str, bytes]) -> Any:
|
|
469
|
-
type, payload = data
|
|
470
|
-
if type != "json":
|
|
471
|
-
raise ValueError(f"Unsupported type {type}")
|
|
472
|
-
return orjson.loads(payload)
|
|
473
471
|
|
|
474
|
-
|
|
472
|
+
def _get_passthrough_checkpointer(conn: AsyncConnectionProto):
|
|
473
|
+
from langgraph_runtime.checkpoint import Checkpointer
|
|
475
474
|
|
|
475
|
+
checkpointer = Checkpointer(conn)
|
|
476
476
|
# This checkpointer does not attempt to revive LC-objects.
|
|
477
477
|
# Instead, it will pass through the JSON values as-is.
|
|
478
478
|
checkpointer.serde = PassthroughSerialiser()
|
|
@@ -687,7 +687,11 @@ async def run_remote_checkpointer():
|
|
|
687
687
|
payload = orjson.loads(await request.body())
|
|
688
688
|
return ApiResponse(await cb(payload))
|
|
689
689
|
except ValueError as exc:
|
|
690
|
+
await logger.error(exc)
|
|
690
691
|
return ApiResponse({"error": str(exc)}, status_code=400)
|
|
692
|
+
except Exception as exc:
|
|
693
|
+
await logger.error(exc)
|
|
694
|
+
return ApiResponse({"error": str(exc)}, status_code=500)
|
|
691
695
|
|
|
692
696
|
return wrapped
|
|
693
697
|
|
|
@@ -800,15 +804,18 @@ async def js_healthcheck():
|
|
|
800
804
|
transport=httpx.AsyncHTTPTransport(verify=SSL),
|
|
801
805
|
) as checkpointer_client,
|
|
802
806
|
):
|
|
807
|
+
graph_passed = False
|
|
803
808
|
try:
|
|
804
809
|
res = await graph_client.get("/ok")
|
|
805
810
|
res.raise_for_status()
|
|
811
|
+
graph_passed = True
|
|
806
812
|
res = await checkpointer_client.get("/ok")
|
|
807
813
|
res.raise_for_status()
|
|
808
814
|
return True
|
|
809
815
|
except httpx.HTTPError as exc:
|
|
810
816
|
logger.warning(
|
|
811
817
|
"JS healthcheck failed. Either the JS server is not running or the event loop is blocked by a CPU-intensive task.",
|
|
818
|
+
graph_passed=graph_passed,
|
|
812
819
|
error=exc,
|
|
813
820
|
)
|
|
814
821
|
raise HTTPException(
|
langgraph_api/logging.py
CHANGED
|
@@ -57,6 +57,16 @@ class AddPrefixedEnvVars:
|
|
|
57
57
|
return event_dict
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
class AddApiVersion:
|
|
61
|
+
def __call__(
|
|
62
|
+
self, logger: logging.Logger, method_name: str, event_dict: EventDict
|
|
63
|
+
) -> EventDict:
|
|
64
|
+
from langgraph_api import __version__
|
|
65
|
+
|
|
66
|
+
event_dict["langgraph_api_version"] = __version__
|
|
67
|
+
return event_dict
|
|
68
|
+
|
|
69
|
+
|
|
60
70
|
class AddLoggingContext:
|
|
61
71
|
def __call__(
|
|
62
72
|
self, logger: logging.Logger, method_name: str, event_dict: EventDict
|
|
@@ -90,11 +100,14 @@ shared_processors = [
|
|
|
90
100
|
structlog.stdlib.PositionalArgumentsFormatter(),
|
|
91
101
|
structlog.stdlib.ExtraAdder(),
|
|
92
102
|
AddPrefixedEnvVars("LANGSMITH_LANGGRAPH_"), # injected by docker build
|
|
103
|
+
AddApiVersion(),
|
|
93
104
|
structlog.processors.TimeStamper(fmt="iso", utc=True),
|
|
94
105
|
structlog.processors.StackInfoRenderer(),
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
106
|
+
(
|
|
107
|
+
structlog.processors.dict_tracebacks
|
|
108
|
+
if LOG_JSON
|
|
109
|
+
else structlog.processors.format_exc_info
|
|
110
|
+
),
|
|
98
111
|
structlog.processors.UnicodeDecoder(),
|
|
99
112
|
AddLoggingContext(),
|
|
100
113
|
]
|
langgraph_api/models/run.py
CHANGED
|
@@ -29,6 +29,13 @@ from langgraph_api.utils import AsyncConnectionProto, get_auth_ctx
|
|
|
29
29
|
from langgraph_runtime.ops import Runs, logger
|
|
30
30
|
|
|
31
31
|
|
|
32
|
+
class LangSmithTracer(TypedDict, total=False):
|
|
33
|
+
"""Configuration for LangSmith tracing."""
|
|
34
|
+
|
|
35
|
+
example_id: str | None
|
|
36
|
+
project_name: str | None
|
|
37
|
+
|
|
38
|
+
|
|
32
39
|
class RunCreateDict(TypedDict):
|
|
33
40
|
"""Payload for creating a run."""
|
|
34
41
|
|
|
@@ -87,6 +94,8 @@ class RunCreateDict(TypedDict):
|
|
|
87
94
|
"""Start the run after this many seconds. Defaults to 0."""
|
|
88
95
|
if_not_exists: IfNotExists
|
|
89
96
|
"""Create the thread if it doesn't exist. If False, reply with 404."""
|
|
97
|
+
langsmith_tracer: LangSmithTracer | None
|
|
98
|
+
"""Configuration for additional tracing with LangSmith."""
|
|
90
99
|
|
|
91
100
|
|
|
92
101
|
def ensure_ids(
|
|
@@ -295,6 +304,9 @@ async def create_valid_run(
|
|
|
295
304
|
user_id = None
|
|
296
305
|
if not configurable.get("langgraph_request_id"):
|
|
297
306
|
configurable["langgraph_request_id"] = request_id
|
|
307
|
+
if ls_tracing := payload.get("langsmith_tracer"):
|
|
308
|
+
configurable["__langsmith_project__"] = ls_tracing.get("project_name")
|
|
309
|
+
configurable["__langsmith_example_id__"] = ls_tracing.get("example_id")
|
|
298
310
|
if request_start_time:
|
|
299
311
|
configurable["__request_start_time_ms__"] = request_start_time
|
|
300
312
|
after_seconds = payload.get("after_seconds", 0)
|
langgraph_api/stream.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from collections.abc import AsyncIterator, Callable
|
|
2
|
-
from contextlib import AsyncExitStack, aclosing
|
|
2
|
+
from contextlib import AsyncExitStack, aclosing, asynccontextmanager
|
|
3
3
|
from functools import lru_cache
|
|
4
4
|
from typing import Any, cast
|
|
5
5
|
|
|
@@ -20,6 +20,7 @@ from langgraph.errors import (
|
|
|
20
20
|
InvalidUpdateError,
|
|
21
21
|
)
|
|
22
22
|
from langgraph.pregel.debug import CheckpointPayload, TaskResultPayload
|
|
23
|
+
from langsmith.utils import get_tracer_project
|
|
23
24
|
from pydantic import ValidationError
|
|
24
25
|
from pydantic.v1 import ValidationError as ValidationErrorLegacy
|
|
25
26
|
|
|
@@ -71,6 +72,12 @@ def _preprocess_debug_checkpoint(payload: CheckpointPayload | None) -> dict[str,
|
|
|
71
72
|
return payload
|
|
72
73
|
|
|
73
74
|
|
|
75
|
+
@asynccontextmanager
|
|
76
|
+
async def async_tracing_context(*args, **kwargs):
|
|
77
|
+
with langsmith.tracing_context(*args, **kwargs):
|
|
78
|
+
yield
|
|
79
|
+
|
|
80
|
+
|
|
74
81
|
async def astream_state(
|
|
75
82
|
stack: AsyncExitStack,
|
|
76
83
|
conn: AsyncConnectionProto,
|
|
@@ -131,6 +138,25 @@ async def astream_state(
|
|
|
131
138
|
use_astream_events = "events" in stream_mode or isinstance(graph, BaseRemotePregel)
|
|
132
139
|
# yield metadata chunk
|
|
133
140
|
yield "metadata", {"run_id": run_id, "attempt": attempt}
|
|
141
|
+
|
|
142
|
+
# is a langsmith tracing project is specified, additionally pass that in to tracing context
|
|
143
|
+
if ls_project := config["configurable"].get("__langsmith_project__"):
|
|
144
|
+
updates = None
|
|
145
|
+
if example_id := config["configurable"].get("__langsmith_example_id__"):
|
|
146
|
+
updates = {"reference_example_id": example_id}
|
|
147
|
+
|
|
148
|
+
await stack.enter_async_context(
|
|
149
|
+
async_tracing_context(
|
|
150
|
+
replicas=[
|
|
151
|
+
(
|
|
152
|
+
ls_project,
|
|
153
|
+
updates,
|
|
154
|
+
),
|
|
155
|
+
(get_tracer_project(), None),
|
|
156
|
+
]
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
|
|
134
160
|
# stream run
|
|
135
161
|
if use_astream_events:
|
|
136
162
|
async with (
|
|
@@ -269,7 +295,7 @@ async def astream_state(
|
|
|
269
295
|
yield mode, chunk
|
|
270
296
|
# --- end shared logic with astream_events ---
|
|
271
297
|
if is_remote_pregel:
|
|
272
|
-
#
|
|
298
|
+
# increment the remote runs
|
|
273
299
|
try:
|
|
274
300
|
nodes_executed = await graph.fetch_nodes_executed()
|
|
275
301
|
incr_nodes(None, incr=nodes_executed)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: langgraph-api
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.45
|
|
4
4
|
Author-email: Nuno Campos <nuno@langchain.dev>, Will Fu-Hinthorn <will@langchain.dev>
|
|
5
5
|
License: Elastic-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -9,12 +9,12 @@ Requires-Dist: cloudpickle>=3.0.0
|
|
|
9
9
|
Requires-Dist: cryptography<45.0,>=42.0.0
|
|
10
10
|
Requires-Dist: httpx>=0.25.0
|
|
11
11
|
Requires-Dist: jsonschema-rs<0.30,>=0.20.0
|
|
12
|
-
Requires-Dist: langchain-core>=0.
|
|
12
|
+
Requires-Dist: langchain-core>=0.3.64
|
|
13
13
|
Requires-Dist: langgraph-checkpoint>=2.0.23
|
|
14
14
|
Requires-Dist: langgraph-runtime-inmem<0.3,>=0.2.0
|
|
15
15
|
Requires-Dist: langgraph-sdk>=0.1.66
|
|
16
16
|
Requires-Dist: langgraph>=0.3.27
|
|
17
|
-
Requires-Dist: langsmith>=0.
|
|
17
|
+
Requires-Dist: langsmith>=0.3.45
|
|
18
18
|
Requires-Dist: orjson>=3.9.7
|
|
19
19
|
Requires-Dist: pyjwt>=2.9.0
|
|
20
20
|
Requires-Dist: sse-starlette<2.2.0,>=2.1.0
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
langgraph_api/__init__.py,sha256=
|
|
1
|
+
langgraph_api/__init__.py,sha256=48yajatRDmJidbzrkcvrcmL96an-Z7rF0VahutQn2wk,23
|
|
2
2
|
langgraph_api/asgi_transport.py,sha256=eqifhHxNnxvI7jJqrY1_8RjL4Fp9NdN4prEub2FWBt8,5091
|
|
3
3
|
langgraph_api/asyncio.py,sha256=nelZwKL7iOjM5GHj1rVjiPE7igUIKLNKtc-3urxmlfo,9250
|
|
4
4
|
langgraph_api/cli.py,sha256=9Ou3tGDDY_VVLt5DFle8UviJdpI4ZigC5hElYvq2-To,14519
|
|
@@ -8,7 +8,7 @@ langgraph_api/cron_scheduler.py,sha256=i87j4pJrcsmsqMKeKUs69gaAjrGaSM3pM3jnXdN5J
|
|
|
8
8
|
langgraph_api/errors.py,sha256=Bu_i5drgNTyJcLiyrwVE_6-XrSU50BHf9TDpttki9wQ,1690
|
|
9
9
|
langgraph_api/graph.py,sha256=MPm8DvInBQsq2em45c2YD5bW6T_G1LlDkAuWq-19gCQ,23240
|
|
10
10
|
langgraph_api/http.py,sha256=gYbxxjY8aLnsXeJymcJ7G7Nj_yToOGpPYQqmZ1_ggfA,5240
|
|
11
|
-
langgraph_api/logging.py,sha256=
|
|
11
|
+
langgraph_api/logging.py,sha256=1BXELwUBY8gZeOWCYElbBu_GyHLM2jjlDVJznlekqvQ,4268
|
|
12
12
|
langgraph_api/metadata.py,sha256=2sz9ECnbnQtgqN6ptDkRmymaVKfQPgaX-JuDJDJB47c,4254
|
|
13
13
|
langgraph_api/patch.py,sha256=Dgs0PXHytekX4SUL6KsjjN0hHcOtGLvv1GRGbh6PswU,1408
|
|
14
14
|
langgraph_api/queue_entrypoint.py,sha256=_41ZveMDdn9bapjA7Ik9FG3r4hyIwXESUM5F1PdlieE,2309
|
|
@@ -19,7 +19,7 @@ langgraph_api/server.py,sha256=Z_VL-kIphybTRDWBIqHMfRhgCmAFyTRqAGlgnHQF0Zg,6973
|
|
|
19
19
|
langgraph_api/sse.py,sha256=F7swfjKBDrlUmXZ_dWuDVHtp-3o1Cpjq1lwp0bJD-nw,4223
|
|
20
20
|
langgraph_api/state.py,sha256=8jx4IoTCOjTJuwzuXJKKFwo1VseHjNnw_CCq4x1SW14,2284
|
|
21
21
|
langgraph_api/store.py,sha256=_xGhdwEIMoY1_hIy_oWwxZp4Y7FH833BNJfgFIhT80E,4640
|
|
22
|
-
langgraph_api/stream.py,sha256=
|
|
22
|
+
langgraph_api/stream.py,sha256=NfpOI5_SzHLcExgcjaF8ggeKCk9n1ocoQTWmjFwsrVQ,13700
|
|
23
23
|
langgraph_api/thread_ttl.py,sha256=-Ox8NFHqUH3wGNdEKMIfAXUubY5WGifIgCaJ7npqLgw,1762
|
|
24
24
|
langgraph_api/utils.py,sha256=92mSti9GfGdMRRWyESKQW5yV-75Z9icGHnIrBYvdypU,3619
|
|
25
25
|
langgraph_api/validation.py,sha256=zMuKmwUEBjBgFMwAaeLZmatwGVijKv2sOYtYg7gfRtc,4950
|
|
@@ -52,7 +52,7 @@ langgraph_api/js/client.mts,sha256=N9CTH7mbXGSD-gpv-XyruYsHI-rgrObL8cQoAp5s3_U,3
|
|
|
52
52
|
langgraph_api/js/errors.py,sha256=Cm1TKWlUCwZReDC5AQ6SgNIVGD27Qov2xcgHyf8-GXo,361
|
|
53
53
|
langgraph_api/js/global.d.ts,sha256=j4GhgtQSZ5_cHzjSPcHgMJ8tfBThxrH-pUOrrJGteOU,196
|
|
54
54
|
langgraph_api/js/package.json,sha256=7_qkj-b0_bpHFFyBDgGaZl3BeuSqkbCD7wNn-ZvQeGA,1333
|
|
55
|
-
langgraph_api/js/remote.py,sha256=
|
|
55
|
+
langgraph_api/js/remote.py,sha256=yNK8ajiRXxpzbUFWT1wPdK0XyRW1TejzBPAAeVUCtQY,36192
|
|
56
56
|
langgraph_api/js/schema.py,sha256=7idnv7URlYUdSNMBXQcw7E4SxaPxCq_Oxwnlml8q5ik,408
|
|
57
57
|
langgraph_api/js/sse.py,sha256=lsfp4nyJyA1COmlKG9e2gJnTttf_HGCB5wyH8OZBER8,4105
|
|
58
58
|
langgraph_api/js/tsconfig.json,sha256=imCYqVnqFpaBoZPx8k1nO4slHIWBFsSlmCYhO73cpBs,341
|
|
@@ -70,16 +70,24 @@ langgraph_api/middleware/http_logger.py,sha256=aj4mdisRobFePkD3Iy6-w_Mujwx4TQRaE
|
|
|
70
70
|
langgraph_api/middleware/private_network.py,sha256=eYgdyU8AzU2XJu362i1L8aSFoQRiV7_aLBPw7_EgeqI,2111
|
|
71
71
|
langgraph_api/middleware/request_id.py,sha256=fmtp0jLqoSqXTD39d9PW7jVlIvGqGurqgteMCeexRvY,1106
|
|
72
72
|
langgraph_api/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
-
langgraph_api/models/run.py,sha256=
|
|
73
|
+
langgraph_api/models/run.py,sha256=j1s9KRfFXgjKUudB9z7IVJ34Klo85PPeaVFtmWHhEdo,14514
|
|
74
74
|
langgraph_api/tunneling/cloudflare.py,sha256=iKb6tj-VWPlDchHFjuQyep2Dpb-w2NGfJKt-WJG9LH0,3650
|
|
75
75
|
langgraph_license/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
76
76
|
langgraph_license/validation.py,sha256=ZKraAVJArAABKqrmHN-EN18ncoNUmRm500Yt1Sc7tUA,537
|
|
77
77
|
langgraph_runtime/__init__.py,sha256=O4GgSmu33c-Pr8Xzxj_brcK5vkm70iNTcyxEjICFZxA,1075
|
|
78
|
+
langgraph_runtime/checkpoint.py,sha256=J2ePryEyKJWGgxjs27qEHrjj87uPMX3Rqm3hLvG63uk,119
|
|
79
|
+
langgraph_runtime/database.py,sha256=ANEtfm4psr19FtpVcNs5CFWHw-JhfHvIMnkaORa4QSM,117
|
|
80
|
+
langgraph_runtime/lifespan.py,sha256=-YIHyEEaP_F2tSdTP0tNjfAJXs7KfxaIsWdmQAUi2KM,117
|
|
81
|
+
langgraph_runtime/metrics.py,sha256=CIBw3tjTg1c-o3_2InA-qV34028fQcYWBYkpN6zdEoI,116
|
|
82
|
+
langgraph_runtime/ops.py,sha256=ht_U9LPbHWy0l95b_Q0Vvtd7kYxeZsaSKSf0WpwHUoo,112
|
|
83
|
+
langgraph_runtime/queue.py,sha256=m7req6Ca9NOw1yp-zo30zGhldRWDFk4QVL_tgrVrhQg,114
|
|
84
|
+
langgraph_runtime/retry.py,sha256=V0duD01fO7GUQ_btQkp1aoXcEOFhXooGVP6q4yMfuyY,114
|
|
85
|
+
langgraph_runtime/store.py,sha256=7mowndlsIroGHv3NpTSOZDJR0lCuaYMBoTnTrewjslw,114
|
|
78
86
|
LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
79
87
|
logging.json,sha256=3RNjSADZmDq38eHePMm1CbP6qZ71AmpBtLwCmKU9Zgo,379
|
|
80
88
|
openapi.json,sha256=_4GFDqbq1X9vD4_FxwahuVODJMOHx-U76gkY4rdy3DA,138189
|
|
81
|
-
langgraph_api-0.2.
|
|
82
|
-
langgraph_api-0.2.
|
|
83
|
-
langgraph_api-0.2.
|
|
84
|
-
langgraph_api-0.2.
|
|
85
|
-
langgraph_api-0.2.
|
|
89
|
+
langgraph_api-0.2.45.dist-info/METADATA,sha256=C9WHgMJRJQpBF0i6FG8m4eqhgPTPLJ8V1JbBpRi2tAM,3891
|
|
90
|
+
langgraph_api-0.2.45.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
91
|
+
langgraph_api-0.2.45.dist-info/entry_points.txt,sha256=hGedv8n7cgi41PypMfinwS_HfCwA7xJIfS0jAp8htV8,78
|
|
92
|
+
langgraph_api-0.2.45.dist-info/licenses/LICENSE,sha256=ZPwVR73Biwm3sK6vR54djCrhaRiM4cAD2zvOQZV8Xis,3859
|
|
93
|
+
langgraph_api-0.2.45.dist-info/RECORD,,
|
langgraph_runtime/ops.py
ADDED
|
File without changes
|
|
File without changes
|
|
File without changes
|