diff --git a/docs/quick_start.md b/docs/quick_start.md index c7192c128..0ecf3d117 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -72,8 +72,8 @@ Activate with: source .venv/bin/activate # For Windows Bash: source .venv/Scripts/activate > source .venv/bin/activate -# Install the uipath package -> uv add uipath-langchain +# Install the uipath package and extras +> uv add "uipath-langchain[bedrock,vertex]" # Verify the uipath installation > uipath -lv @@ -98,8 +98,8 @@ uipath-langchain version 0.1.0 # Upgrade pip to the latest version > python -m pip install --upgrade pip -# Install the uipath package -> pip install uipath-langchain +# Install the uipath package and extras +> pip install "uipath-langchain[bedrock,vertex]" # Verify the uipath installation > uipath -lv @@ -120,8 +120,8 @@ Generate your first UiPath LangChain agent: ✓ Created 'main.py' file. ✓ Created 'langgraph.json' file. ✓ Created 'pyproject.toml' file. -💡 Initialize project: uipath init -💡 Run agent: uipath run agent '{"topic": "UiPath"}' +💡 Initialize project: uipath init +💡 Run agent: uipath run agent '{"topic": "UiPath"}' ``` This command creates the following files: diff --git a/pyproject.toml b/pyproject.toml index fd1e32b6c..06af45dbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-langchain" -version = "0.16.13" +version = "0.16.14" description = "Python SDK that enables developers to build and deploy LangGraph agents to the UiPath Cloud Platform" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" @@ -90,6 +90,7 @@ dev = [ "pytest_httpx>=0.35.0", "rust-just>=1.39.0", "types-protobuf<7", + "packaging>=24.0", ] [tool.hatch.build.targets.wheel] diff --git a/src/uipath_langchain/_cli/cli_new.py b/src/uipath_langchain/_cli/cli_new.py index 2962e1890..7d49a8f9a 100644 --- a/src/uipath_langchain/_cli/cli_new.py +++ b/src/uipath_langchain/_cli/cli_new.py @@ -7,6 +7,12 @@ console = ConsoleLogger() +# The `uipath-langchain` minor release that scaffolded projects are pinned to. +# Deliberately a constant: the guard test in tests/cli/test_new.py fails on +# every minor bump so the scaffold (pin, template, hints) gets reviewed +# alongside the release rather than drifting silently. +UIPATH_LANGCHAIN_SCAFFOLD_MINOR = "0.16" + def generate_script(target_directory): template_script_path = os.path.join( @@ -25,13 +31,14 @@ def generate_script(target_directory): def generate_pyproject(target_directory, project_name): project_toml_path = os.path.join(target_directory, "pyproject.toml") + major, minor = (int(part) for part in UIPATH_LANGCHAIN_SCAFFOLD_MINOR.split(".")) toml_content = f"""[project] name = "{project_name}" version = "0.0.1" description = "{project_name}" authors = [{{ name = "John Doe", email = "john.doe@myemail.com" }}] dependencies = [ - "uipath-langchain[bedrock,vertex]>=0.10.0, <0.11.0", + "uipath-langchain[bedrock,vertex]>={major}.{minor}.0, <{major}.{minor + 1}.0", ] requires-python = ">=3.11" """ @@ -55,9 +62,9 @@ def langgraph_new_middleware(name: str) -> MiddlewareResult: init_command = """uipath init""" run_command = """uipath run agent '{"topic": "UiPath"}'""" console.hint( - f""" Initialize project: {click.style(init_command, fg="cyan")}""" + f"""Initialize project: {click.style(init_command, fg="cyan")}""" ) - console.hint(f""" Run agent: {click.style(run_command, fg="cyan")}""") + console.hint(f"""Run agent: {click.style(run_command, fg="cyan")}""") return MiddlewareResult(should_continue=False) except Exception as e: console.error(f"Error creating demo agent {str(e)}") diff --git a/tests/cli/test_new.py b/tests/cli/test_new.py new file mode 100644 index 000000000..eaf8258d8 --- /dev/null +++ b/tests/cli/test_new.py @@ -0,0 +1,56 @@ +import os +import re +from importlib.metadata import version + +import pytest +from packaging.specifiers import SpecifierSet +from packaging.version import Version + +from uipath_langchain._cli.cli_new import ( + UIPATH_LANGCHAIN_SCAFFOLD_MINOR, + langgraph_new_middleware, +) + +PIN_RE = re.compile(r'"uipath-langchain\[bedrock,vertex\]([^"]*)"') + + +class TestUipathLangchainScaffoldPin: + """The scaffolded pin must admit the uipath-langchain release it ships with.""" + + def test_scaffold_pin_admits_installed_version(self) -> None: + """Guard: fails on every minor bump so the scaffold gets reviewed. + + When this fails, review the scaffold in ``cli_new.py`` (pin constant, + ``main.py`` template, post-scaffold hints) for the new minor, then bump + ``UIPATH_LANGCHAIN_SCAFFOLD_MINOR``. + """ + installed = Version(version("uipath-langchain")) + installed_minor = f"{installed.major}.{installed.minor}" + assert UIPATH_LANGCHAIN_SCAFFOLD_MINOR == installed_minor, ( + f"uipath-langchain minor changed to {installed_minor} but " + f"UIPATH_LANGCHAIN_SCAFFOLD_MINOR is {UIPATH_LANGCHAIN_SCAFFOLD_MINOR}; " + f"review the scaffold in cli_new.py (pin, template, hints) and bump " + f"the constant" + ) + + def test_scaffolded_pin_contains_installed_version( + self, tmp_path, monkeypatch: pytest.MonkeyPatch + ) -> None: + """Regression guard: runs against the real installed package, not a mock. + + A stale range would make ``uv sync`` downgrade the project's venv right + after ``uipath new``. + """ + monkeypatch.chdir(tmp_path) + result = langgraph_new_middleware("demo") + assert result.should_continue is False + assert os.path.exists("main.py") + assert os.path.exists("langgraph.json") + content = (tmp_path / "pyproject.toml").read_text() + match = PIN_RE.search(content) + assert match is not None, content + installed = version("uipath-langchain") + assert SpecifierSet(match.group(1)).contains(installed, prereleases=True), ( + f"scaffolded pin '{match.group(1)}' does not contain installed " + f"uipath-langchain {installed}" + ) diff --git a/uv.lock b/uv.lock index 67bb724be..0269d6e00 100644 --- a/uv.lock +++ b/uv.lock @@ -9,7 +9,7 @@ resolution-markers = [ ] [options] -exclude-newer = "2026-08-26T20:22:33.9044027Z" +exclude-newer = "0001-01-01T00:00:00Z" # This has no effect and is included for backwards compatibility when using relative exclude-newer values. exclude-newer-span = "P2D" [options.exclude-newer-package] @@ -4546,7 +4546,7 @@ wheels = [ [[package]] name = "uipath-langchain" -version = "0.16.13" +version = "0.16.14" source = { editable = "." } dependencies = [ { name = "a2a-sdk" }, @@ -4596,6 +4596,7 @@ dev = [ { name = "filelock" }, { name = "mypy" }, { name = "numpy" }, + { name = "packaging" }, { name = "pre-commit" }, { name = "pytest" }, { name = "pytest-asyncio" }, @@ -4647,6 +4648,7 @@ dev = [ { name = "filelock", specifier = ">=3.20.3" }, { name = "mypy", specifier = ">=1.14.1" }, { name = "numpy", specifier = ">=1.24.0" }, + { name = "packaging", specifier = ">=24.0" }, { name = "pre-commit", specifier = ">=4.5.1" }, { name = "pytest", specifier = ">=7.4.0" }, { name = "pytest-asyncio", specifier = ">=1.0.0" },