Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agents/langchain-deepagents-code/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ RUN python3 -m venv --copies "$VIRTUAL_ENV" \
-r /tmp/deepagents-code-requirements.lock \
&& "$VIRTUAL_ENV/bin/pip3" check \
&& "$VIRTUAL_ENV/bin/python3" -I -c \
"from importlib.metadata import version; expected = {'aiohttp': '3.14.3', 'cryptography': '50.0.0', 'deepagents-code': '0.1.34', 'mcp': '1.28.1', 'pillow': '12.3.0', 'pyasn1': '0.6.4', 'uv': '0.11.33'}; actual = {name: version(name) for name in expected}; assert actual == expected, actual" \
"from importlib.metadata import version; expected = {'aiohttp': '3.14.3', 'cryptography': '50.0.0', 'deepagents-code': '0.1.54', 'mcp': '1.28.1', 'pillow': '12.3.0', 'pyasn1': '0.6.4', 'uv': '0.11.33'}; actual = {name: version(name) for name in expected}; assert actual == expected, actual" \
&& ln -sf "$VIRTUAL_ENV/bin/dcode" /usr/local/bin/dcode \
&& ln -sf "$VIRTUAL_ENV/bin/deepagents-code" /usr/local/bin/deepagents-code \
&& rm -f /tmp/deepagents-code-requirements.lock \
Expand Down
4 changes: 2 additions & 2 deletions agents/langchain-deepagents-code/dcode-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if [ "${1:-}" = "--nemoclaw-mcp-capability" ] && [ "$#" -eq 1 ]; then
exit 0
fi

unset BASH_ENV ENV OPENAI_PROXY
unset BASH_ENV ENV OPENAI_PROXY DEEPAGENTS_CODE_APPROVAL_MODE DEEPAGENTS_CODE_STARTUP_MODE
while IFS= read -r _nemoclaw_auto_approval_env; do
unset "$_nemoclaw_auto_approval_env"
done < <(compgen -A variable NEMOCLAW_DCODE_AUTO_APPROVAL || true)
Expand Down Expand Up @@ -637,7 +637,7 @@ try:
except Exception:
sys.exit(1)
# Schema pin: detection assumes a truthy top-level "credentials" key,
# matching the auth.json shape in deepagents-code==0.1.34. Nested or
# matching the auth.json shape reviewed for deepagents-code==0.1.54. Nested or
# renamed shapes ({"auth":{...}}, {"state":{"credentials":...}}, top-level
# list) are not detected. When bumping the upstream pin, re-review this
# assumption against the new auth.json schema.
Expand Down
24 changes: 15 additions & 9 deletions agents/langchain-deepagents-code/dependency-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,23 @@ Update it whenever `requirements.lock` changes.
The Dockerfile installs this lockfile with `pip3 install --require-hashes`, so this review covers the exact package versions selected for the managed image install.
The lock now selects `aiohttp==3.14.3`, `cryptography==50.0.0`, `uv==0.11.33`, `mcp==1.28.1`, `Pillow==12.3.0`, and `pyasn1==0.6.4`.
These selections clear `GHSA-cq5v-8q36-5273` and `GHSA-g6cj-pr64-35w5`.
The direct MCP and pyasn1 requirements are temporary, hash-locked constraints for the released Deep Agents Code `0.1.34` graph.
Deep Agents Code `0.1.45` and later contain the MCP and pyasn1 fixes, but their hook boundary has changed.
Remove the temporary direct constraints only as part of a separately validated semantic migration to `>=0.1.45` that preserves NemoClaw's managed runtime hooks.
The Deep Agents Code selector is the published `0.1.54` release at commit
`81258067f4c74c3ede7d2b2895d9835137ba5977`. Its reviewed wheel is
`deepagents_code-0.1.54-py3-none-any.whl` with SHA-256
`fbfd0fc31caf5a8b0f1ff4ddea4da0de7837b0ffd3e6a222118c6480c99671ae`;
the corresponding source archive has SHA-256
`74df86f91a11d5dbace943d1c747bf67a2354670416c343a6e909133feecaf27`.
This migration crosses the `0.1.45` MCP and pyasn1 fixes while retaining the
managed hook, approval, credential, update, and startup-mode guards at the
NemoClaw launcher and exact-version package-patch boundaries.

The image build runs `pip3 check` and asserts all seven installed package versions, including Deep Agents Code itself, before publishing.
The complete point-in-time audit now reports only two duplicate database records for `setuptools==82.0.1`; that record is outside the Critical/High remediation scope.
This review does not claim the complete lock is vulnerability-free.

## Managed `fetch_url` Proxy Adapter

Deep Agents Code `0.1.34` deliberately disables ambient proxies and resolves
Deep Agents Code `0.1.54` deliberately disables ambient proxies and resolves
destination DNS locally before pinning the address used by `fetch_url`. That is
the wrong transport inside a NemoClaw-managed sandbox: ordinary egress and
destination resolution must pass through the policy proxy, so the direct path
Expand Down Expand Up @@ -62,18 +68,18 @@ behavior.

## Released Nemotron 3 Ultra Profile

Deep Agents Code `0.1.34` pins `deepagents==0.7.0a6`, whose official wheel
Deep Agents Code `0.1.54` pins `deepagents==0.7.0a6`, whose official wheel
contains the Nemotron 3 Ultra harness profile merged in Deep Agents PR #4192.
NemoClaw no longer vendors or overlays that source.

- Native profile SHA-256: `c8e8dd2b0182334b54be4f46ff0c7b45fbb95dc13bd9a92c249eb47a14fa13d7`
- Unmodified built-in bootstrap SHA-256: `005a91e7fc4ca6b21220673dd9d02d6686bf63e1e4f1102d124b01f96886efcf`
- First-party adapter: `nemoclaw-deepagents-profile==0.1.0`
- Adapter module SHA-256: `8fe85c62293c74147848732dc56c33e8ab60133fa41c071da4328ac60f2bf44f`
- Adapter project metadata SHA-256: `7ba7b77bd6f889cc861eddbe3e38fc1f4433a85b7bc2a9b516e19a19a37a7686`
- Adapter module SHA-256: `8fba11c64c561cad2568714363199f6ac28826e028f7743e19a2439a6de5a874`
- Adapter project metadata SHA-256: `c7bc651acc8c719aafb74993578b31c105a2190dc7dcf329c52c098cb6fa9c5f`
- Adapter wheel license expression: `Apache-2.0`
- Adapter dependency audit result: `No known vulnerabilities found`. Its only
requirements are the exact `deepagents-code==0.1.34` and
requirements are the exact `deepagents-code==0.1.54` and
`deepagents==0.7.0a6` entries covered by the lockfile audit command above; no
additional third-party distribution is introduced.

Expand Down Expand Up @@ -216,7 +222,7 @@ rejection, and unchanged concrete-command states. The
deleted source-backport license path, `LICENSE.langchain-deepagents`, is not
staged into the image, and image regression tests enforce that absence.

Deep Agents Code `0.1.34` is the released consumer; prerelease risk is limited
Deep Agents Code `0.1.54` is the released consumer; prerelease risk is limited
to its exact `deepagents==0.7.0a6` SDK pin. That risk is accepted because the
consumer and SDK are hash locked and all source, version, middleware, graph,
and dispatch contracts are enforced by the isolated image-build validator.
Expand Down
4 changes: 2 additions & 2 deletions agents/langchain-deepagents-code/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
name: langchain-deepagents-code
display_name: "LangChain Deep Agents Code"
description: "Terminal coding agent built on the Deep Agents SDK"
version_constraint: ">=0.1.34"
version_constraint: ">=0.1.54"
language: python
license: MIT
homepage: "https://docs.langchain.com/oss/python/deepagents/code/overview"
Expand All @@ -18,7 +18,7 @@ homepage: "https://docs.langchain.com/oss/python/deepagents/code/overview"
install_method: pip
binary_path: /usr/local/bin/dcode
version_command: "dcode --version"
expected_version: "0.1.34"
expected_version: "0.1.54"
version_scheme: semver
runtime:
kind: terminal
Expand Down
21 changes: 16 additions & 5 deletions agents/langchain-deepagents-code/patch-managed-deepagents-code.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# sourceBoundary: deepagents-code owns those Python entrypoints and child env;
# langgraph-cli owns the analytics opt-out; NemoClaw owns the sandbox image
# posture and therefore validates every patched symbol before build.
# whyNotSourceFix: upstream 0.1.34 has no single managed-runtime hook that can
# whyNotSourceFix: upstream 0.1.54 has no single managed-runtime hook that can
# enforce these constraints across CLI, UI, headless, server, and restart paths.
# regressionTest: the exact version plus AST symbol/method gates fail the image
# build on drift, while hostile analytics values exercise patched entrypoints and
Expand All @@ -26,7 +26,7 @@
import importlib.util
from pathlib import Path

EXPECTED_DCODE_VERSION = "0.1.34"
EXPECTED_DCODE_VERSION = "0.1.54"
PATCH_MARKER = "NemoClaw-managed Deep Agents Code hardening v2."
TOOL_DISCLOSURE_PATCH_MARKER = "NemoClaw-managed progressive tool disclosure."
OBSERVABILITY_PATCH_MARKER = "NemoClaw-managed backend-neutral observability."
Expand Down Expand Up @@ -67,6 +67,8 @@
os.environ.pop("PYTHONHOME", None)
os.environ.pop("PYTHONPATH", None)
os.environ.pop("OPENAI_PROXY", None)
os.environ.pop("DEEPAGENTS_CODE_APPROVAL_MODE", None)
os.environ.pop("DEEPAGENTS_CODE_STARTUP_MODE", None)

from deepagents_code._nemoclaw_managed import assert_safe_runtime

Expand Down Expand Up @@ -94,6 +96,8 @@
os.environ.pop("PYTHONHOME", None)
os.environ.pop("PYTHONPATH", None)
os.environ.pop("OPENAI_PROXY", None)
os.environ.pop("DEEPAGENTS_CODE_APPROVAL_MODE", None)
os.environ.pop("DEEPAGENTS_CODE_STARTUP_MODE", None)

from deepagents_code._nemoclaw_managed import (
assert_safe_runtime as _nemoclaw_assert_safe_runtime,
Expand Down Expand Up @@ -164,6 +168,13 @@
args.acp = False
if hasattr(args, "startup_cmd"):
args.startup_cmd = None
# 0.1.54 adds persisted startup/approval modes. Managed sessions always
# start in manual mode; the separately attested -y capability remains the
# only route to thread-scoped auto-approval.
if hasattr(args, "startup_mode"):
args.startup_mode = "manual"
if hasattr(args, "approval_mode"):
args.approval_mode = "manual"

_nemoclaw_assert_safe_runtime()
if (
Expand Down Expand Up @@ -228,7 +239,7 @@ async def _nemoclaw_handle_command(self, command: str) -> None:
or (root == "/goal" and len(tokens) <= 3)
)
)
if blocked_model_params or blocked_grader_model or root in {"/auth", "/connect", "/update", "/auto-update", "/install", "/mcp"}:
if blocked_model_params or blocked_grader_model or root in {"/auth", "/connect", "/update", "/auto-update", "/install", "/mcp", "/mode", "/auto", "/yolo"}:
await self._mount_message(UserMessage(command))
await self._mount_message(AppMessage(_NEMOCLAW_MANAGED_UI_MESSAGE))
return
Expand Down Expand Up @@ -559,7 +570,7 @@ def _get_provider_kwargs(provider: str, *, model_name: str | None = None) -> dic
return kwargs
'''

# Source-of-truth boundary: upstream Deep Agents Code 0.1.34 resolves and pins
# Source-of-truth boundary: upstream Deep Agents Code 0.1.54 resolves and pins
# destination DNS locally, then disables environment proxies. That is a sound
# standalone SSRF defense but cannot operate in OpenShell's proxy-only network
# namespace, where direct DNS and direct target connections are rejected. The
Expand Down Expand Up @@ -599,7 +610,7 @@ def _nemoclaw_get_class_path(self, provider_name: str):
ModelConfig.get_class_path = _nemoclaw_get_class_path
'''

# Source-of-truth boundary: pinned upstream deepagents-code==0.1.34 cannot inject
# Source-of-truth boundary: pinned upstream deepagents-code==0.1.54 cannot inject
# managed progressive-disclosure or Relay middleware into both main and subagent
# graphs, nor attach a metadata-only callback to the compiled graph. Without this
# root-owned image patch, those graphs omit NemoClaw's runtime controls; this repo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ description = "NemoClaw-managed Deep Agents harness profile aliases"
requires-python = ">=3.11"
license = "Apache-2.0"
dependencies = [
"deepagents-code==0.1.34",
"deepagents-code==0.1.54",
"deepagents==0.7.0a6",
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pathlib import Path
from typing import Any

EXPECTED_DCODE_VERSION = "0.1.34"
EXPECTED_DCODE_VERSION = "0.1.54"
EXPECTED_DEEPAGENTS_VERSION = "0.7.0a6"
EXPECTED_NATIVE_PROFILE_SHA256 = (
"c8e8dd2b0182334b54be4f46ff0c7b45fbb95dc13bd9a92c249eb47a14fa13d7"
Expand Down
2 changes: 1 addition & 1 deletion agents/langchain-deepagents-code/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
#
uv==0.11.33
deepagents-code[nvidia,openrouter]==0.1.34
deepagents-code[nvidia,openrouter]==0.1.54
nemo-relay[langgraph]==0.4.0
# Fix the C HTTP response parser out-of-bounds read.
aiohttp==3.14.3
Expand Down
6 changes: 3 additions & 3 deletions agents/langchain-deepagents-code/requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -619,9 +619,9 @@ deepagents-acp==0.0.8 \
--hash=sha256:0380c8e804a5d5c0fa245a5b1d7dfde8a867f7a9a17ef54749a69da31ed341cf \
--hash=sha256:9fb5cecfe9e9238de27e69ac76e7b0bc80a31cbff268c542bf5c9f4727dde1f4
# via deepagents-code
deepagents-code==0.1.34 \
--hash=sha256:4b5d659afb388aacb1dc3c668de94bdea3ffd17f5eb3368c686e2ff79b8e7f91 \
--hash=sha256:fec34e7a08f6851762c3c068aaa881dab41084ad41f210c57be29a11d96bb308
deepagents-code==0.1.54 \
--hash=sha256:74df86f91a11d5dbace943d1c747bf67a2354670416c343a6e909133feecaf27 \
--hash=sha256:fbfd0fc31caf5a8b0f1ff4ddea4da0de7837b0ffd3e6a222118c6480c99671ae
# via -r agents/langchain-deepagents-code/requirements.in
distro==1.9.0 \
--hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \
Expand Down
2 changes: 1 addition & 1 deletion agents/langchain-deepagents-code/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ fi

_PROXY_URL="http://${PROXY_HOST}:${PROXY_PORT}"
_NO_PROXY_VAL="localhost,127.0.0.1,::1,${PROXY_HOST}"
# Deep Agents Code 0.1.34 intentionally ignores environment proxies in
# Deep Agents Code 0.1.54 intentionally ignores environment proxies in
# fetch_url so it can pin direct DNS results against rebinding. OpenShell's
# sandbox instead requires all ordinary egress, including DNS resolution for a
# destination, to stay behind its policy proxy. This explicit variable opts the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

EXPECTED_VERSIONS = {
"nemoclaw-deepagents-profile": "0.1.0",
"deepagents-code": "0.1.34",
"deepagents-code": "0.1.54",
"deepagents": "0.7.0a6",
"langchain": "1.3.11",
"langchain-core": "1.4.8",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
from pydantic import Field, ValidationError

PINNED_VERSIONS = {
"deepagents-code": "0.1.34",
"deepagents-code": "0.1.54",
"deepagents": "0.7.0a6",
"langchain": "1.3.11",
"langchain-core": "1.4.8",
Expand Down
2 changes: 1 addition & 1 deletion src/lib/actions/sandbox/rebuild-flow-helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function makeBackupResult(): ReturnType<typeof sandboxState.backupSandboxState>
timestamp: "2026-06-01T00-00-00-000Z",
agentType: "langchain-deepagents-code",
agentVersion: null,
expectedVersion: "0.1.34",
expectedVersion: "0.1.54",
stateDirs: [".state"],
backedUpDirs: [".state"],
stateFiles: [{ path: "config.toml", strategy: "copy" }],
Expand Down
8 changes: 4 additions & 4 deletions src/lib/agent/base-image.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ describe("agent base image provisioning", () => {
makeAgent({
name: "langchain-deepagents-code",
displayName: "LangChain Deep Agents Code",
expectedVersion: "0.1.34",
expectedVersion: "0.1.54",
dockerfileBasePath: "/test/root/agents/langchain-deepagents-code/Dockerfile.base",
dockerfilePath: "/test/root/agents/langchain-deepagents-code/Dockerfile",
}),
Expand All @@ -366,7 +366,7 @@ describe("agent base image provisioning", () => {
],
validateImage: expect.any(Function),
validationDescription:
"deepagents-code==0.1.34 and the immutable security package inventory",
"deepagents-code==0.1.54 and the immutable security package inventory",
}),
);
});
Expand All @@ -386,7 +386,7 @@ describe("agent base image provisioning", () => {
makeAgent({
name: "langchain-deepagents-code",
displayName: "LangChain Deep Agents Code",
expectedVersion: "0.1.34",
expectedVersion: "0.1.54",
dockerfileBasePath: "/test/root/agents/langchain-deepagents-code/Dockerfile.base",
dockerfilePath: "/test/root/agents/langchain-deepagents-code/Dockerfile",
}),
Expand Down Expand Up @@ -417,7 +417,7 @@ describe("agent base image provisioning", () => {
makeAgent({
name: "langchain-deepagents-code",
displayName: "LangChain Deep Agents Code",
expectedVersion: "0.1.34",
expectedVersion: "0.1.54",
dockerfileBasePath: "/test/root/agents/langchain-deepagents-code/Dockerfile.base",
dockerfilePath: "/test/root/agents/langchain-deepagents-code/Dockerfile",
}),
Expand Down
18 changes: 9 additions & 9 deletions src/lib/agent/deep-agents-code-base-image.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ describe("Deep Agents Code base image compatibility", () => {
});

it("accepts only the exact installed distribution version (#6456)", () => {
mocks.dockerCapture.mockReturnValueOnce("0.1.34\n").mockReturnValueOnce("0.1.12\n");
mocks.dockerCapture.mockReturnValueOnce("0.1.54\n").mockReturnValueOnce("0.1.12\n");

expect(deepAgentsCodeBaseImageMatchesVersion("dcode-base:current", "0.1.34")).toBe(true);
expect(deepAgentsCodeBaseImageMatchesVersion("dcode-base:stale", "0.1.34")).toBe(false);
expect(deepAgentsCodeBaseImageMatchesVersion("dcode-base:current", "0.1.54")).toBe(true);
expect(deepAgentsCodeBaseImageMatchesVersion("dcode-base:stale", "0.1.54")).toBe(false);
});

it("binds the manifest version and source files into resolution options (#6456)", () => {
Expand Down Expand Up @@ -58,11 +58,11 @@ describe("Deep Agents Code base image compatibility", () => {
makeAgent({
name: "langchain-deepagents-code",
displayName: "LangChain Deep Agents Code",
expectedVersion: "0.1.34",
expectedVersion: "0.1.54",
}),
"/test/root/agents/langchain-deepagents-code/Dockerfile.base",
);
mocks.dockerCapture.mockReturnValueOnce("0.1.34").mockReturnValueOnce("");
mocks.dockerCapture.mockReturnValueOnce("0.1.54").mockReturnValueOnce("");

expect(options?.validateImage?.("dcode-base:v0.0.96")).toBe(false);
expect(mocks.dockerCapture).toHaveBeenCalledTimes(2);
Expand All @@ -88,9 +88,9 @@ describe("Deep Agents Code base image compatibility", () => {
});

it("runs the version probe in a locked-down container (#6456)", () => {
mocks.dockerCapture.mockReturnValue("0.1.34");
mocks.dockerCapture.mockReturnValue("0.1.54");

deepAgentsCodeBaseImageMatchesVersion("dcode-base:current", "0.1.34");
deepAgentsCodeBaseImageMatchesVersion("dcode-base:current", "0.1.54");

expect(mocks.dockerCapture).toHaveBeenCalledWith(
[
Expand Down Expand Up @@ -118,14 +118,14 @@ describe("Deep Agents Code base image compatibility", () => {
const warn = vi.spyOn(console, "warn").mockImplementation(() => undefined);
mocks.dockerCapture.mockReturnValue("");

expect(deepAgentsCodeBaseImageMatchesVersion("dcode-base:unreadable", "0.1.34")).toBe(false);
expect(deepAgentsCodeBaseImageMatchesVersion("dcode-base:unreadable", "0.1.54")).toBe(false);
expect(warn).toHaveBeenCalledWith(
expect.stringContaining("dcode-base:unreadable returned no Deep Agents Code version output"),
);
expect(warn).toHaveBeenCalledWith(
expect.stringContaining("the container or metadata probe may have failed"),
);
expect(warn).toHaveBeenCalledWith(expect.stringContaining("deepagents-code==0.1.34"));
expect(warn).toHaveBeenCalledWith(expect.stringContaining("deepagents-code==0.1.54"));
warn.mockRestore();
});
});
4 changes: 2 additions & 2 deletions src/lib/agent/onboard-terminal-fixtures.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe("Deep Agents Code terminal onboard fixtures", () => {
calls,
);

expect(output).toBe("dcode 0.1.34");
expect(output).toBe("dcode 0.1.54");
});

it("requires the exact smoke-runner argument before appending its exit marker", () => {
Expand Down Expand Up @@ -62,7 +62,7 @@ describe("Deep Agents Code terminal onboard fixtures", () => {
calls,
);

expect(plainOutput).toBe("dcode 0.1.34");
expect(plainOutput).toBe("dcode 0.1.54");
expect(smokeOutput).toContain("NEMOCLAW_AGENT_SMOKE_EXIT:0");
});

Expand Down
4 changes: 2 additions & 2 deletions src/lib/agent/onboard-terminal-fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function recordDeepAgentsRuntimeCall(
args: string[],
calls: string[],
probeOutput: string,
smokeVersion = "0.1.34",
smokeVersion = "0.1.54",
): string {
calls.push(args.join(" "));
const separatorIndex = args.indexOf("--");
Expand Down Expand Up @@ -34,7 +34,7 @@ function recordDeepAgentsRuntimeCall(
}

export function recordSuccessfulDeepAgentsRuntimeCall(args: string[], calls: string[]): string {
return recordDeepAgentsRuntimeCall(args, calls, "dcode 0.1.34");
return recordDeepAgentsRuntimeCall(args, calls, "dcode 0.1.54");
}

// Like recordSuccessfulDeepAgentsRuntimeCall, but the plain version-drift
Expand Down
Loading
Loading