Compare commits

...
Author SHA1 Message Date
William Fu-Hinthorn 656737009b Update 2025-03-07 10:49:59 -08:00
William Fu-Hinthorn ecdf70a2ab langgraph-cli-install 2025-03-07 10:21:20 -08:00
13 changed files with 428 additions and 1 deletions
+41
View File
@@ -0,0 +1,41 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# Virtual environments
venv/
env/
ENV/
# Editor
.idea/
.vscode/
*.swp
*.swo
# OS specific
.DS_Store
# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 LangChain, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+24
View File
@@ -0,0 +1,24 @@
.PHONY: install format lint clean build publish
install:
poetry install
format:
poetry run ruff format langgraph_cli_install tests
lint:
poetry run ruff check langgraph_cli_install tests
test:
poetry run pytest
clean:
rm -rf dist/
rm -rf build/
rm -rf *.egg-info/
build: clean
poetry build
publish: build
poetry publish
+50
View File
@@ -0,0 +1,50 @@
# LangGraph CLI Installer
A simple installer for the LangGraph CLI that uses `uv` to create an isolated environment.
## Why?
This lightweight installer creates an isolated installation of LangGraph CLI without worrying about Python environment conflicts or dependencies. It uses [uv](https://github.com/astral-sh/uv) to create a standalone environment with LangGraph CLI.
Key benefits:
- Prevents conflicts with other Python packages
- No knowledge of virtual environments needed
- Adds to your PATH automatically
- Installs the latest version of LangGraph CLI
## Quick Install
Simply run:
```bash
pip install langgraph-cli-install && langgraph-cli-install
```
This will:
1. Install the uv package if not already installed
2. Create an isolated environment with the latest LangGraph CLI
3. Add the CLI to your PATH automatically
After installation, you can run `langgraph --help` to get started.
## How It Works
This installer is similar to [aider-install](https://github.com/paul-gauthier/aider/blob/main/aider_install/main.py). It:
1. Uses the `uv` Python installer to create an isolated environment
2. Installs the latest `langgraph-cli` in that environment
3. Adds the installed binary to your PATH
This approach dramatically reduces installation issues caused by Python environment conflicts.
## Manual Installation
If you prefer not to use this installer, you can install LangGraph CLI directly:
```bash
pip install langgraph-cli
```
## License
MIT
@@ -0,0 +1,7 @@
"""LangGraph CLI Installer package."""
__version__ = "0.1.0"
from .main import main
__all__ = ["main"]
@@ -0,0 +1,109 @@
"""LangGraph CLI Installation Script.
Main entry point for installing langgraph-cli in an isolated environment.
This script uses uv to create an isolated installation of langgraph-cli.
"""
import platform
import subprocess
import sys
import uv
def main():
"""Install langgraph-cli using uv in an isolated environment."""
print("Installing LangGraph CLI...")
try:
uv_bin = uv.find_uv_bin()
# Get best Python version for installation (prefer 3.12 if available)
python_version = get_latest_python_version()
# Create an isolated environment with langgraph-cli
print(f"Creating isolated environment using {python_version}...")
subprocess.check_call(
[
uv_bin,
"tool",
"install",
"--force",
"--python",
python_version,
"langgraph-cli@latest",
]
)
# Update PATH so the tool is available
subprocess.check_call([uv_bin, "tool", "update-shell"])
# Show install location and help
show_success_message(uv_bin)
except subprocess.CalledProcessError as e:
print(f"\nFailed to install langgraph-cli: {e}")
sys.exit(1)
except Exception as e:
print(f"\nAn error occurred: {e}")
sys.exit(1)
def get_latest_python_version() -> str:
"""Get the latest compatible Python version for installation."""
# Try to use Python 3.13 if possible, otherwise fall back to the current version
target_version = "3.13"
try:
# Check if this version is available through uv
uv_bin = uv.find_uv_bin()
result = subprocess.run(
[uv_bin, "python", "list"],
capture_output=True,
text=True,
check=False,
)
if target_version in result.stdout:
return f"python{target_version}"
except Exception:
pass
# Fall back to current version
major, minor = sys.version_info.major, sys.version_info.minor
return f"python{major}.{minor}"
def show_success_message(uv_bin):
"""Show success message and installation details."""
# Get installation path
result = subprocess.run(
[uv_bin, "tool", "list"],
capture_output=True,
text=True,
check=True,
)
install_path = None
for line in result.stdout.splitlines():
if "langgraph-cli" in line:
parts = line.strip().split()
if len(parts) >= 2:
install_path = parts[1]
break
# Success message
print("\n🎉 LangGraph CLI has been successfully installed!\n")
print("You can now use it by running:")
print(" langgraph --help")
if install_path:
print(f"\nInstalled at: {install_path}")
# Provide hint about shell restart if needed
if platform.system() != "Windows":
print("\nNote: You may need to restart your terminal or run:")
print(" source ~/.bashrc # or ~/.zshrc depending on your shell")
print("to ensure the langgraph command is available in your PATH.")
if __name__ == "__main__":
main()
+44
View File
@@ -0,0 +1,44 @@
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]]
name = "packaging"
version = "23.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
]
[[package]]
name = "uv"
version = "0.1.45"
description = "An extremely fast Python package installer and resolver, written in Rust."
optional = false
python-versions = ">=3.8"
files = [
{file = "uv-0.1.45-py3-none-linux_armv6l.whl", hash = "sha256:088af576fb0e0462cd5f718d03fb1a9f16ce5ae61fdb2a9d3ea938fc826cecc1"},
{file = "uv-0.1.45-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b94180009264f3f7ee74250f8e4f99c8cb0cb3633e3a9c9c66cdef3eb69be575"},
{file = "uv-0.1.45-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4e5d55f0f8b6ae416c72d78106e224c8e8338356da21ddebecc7b1723de80924"},
{file = "uv-0.1.45-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:7fdb235aaf420fa8ac9009999b1654a23540f03e25c35094543c2f48d7c41aef"},
{file = "uv-0.1.45-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de81501c0b03160d0944906d1a713f108258360e20c58385974acb7253b56166"},
{file = "uv-0.1.45-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:346aa2d0a4ad3c0c3f7852c1edf5e5a8e5d2ef34c7474e9089877291c2da979c"},
{file = "uv-0.1.45-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a601eed14d484d36d421e4208911a56aaf758ea6c385ef8edf8ad9f8ead57ce1"},
{file = "uv-0.1.45-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ca2d5a5e06c5f71c7b213e14fa59129e63b77de3ffbcf84ecc98d647d73a821"},
{file = "uv-0.1.45-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:90b68c80dddebeca69b26a2af1e2e683804bcf2b5f22d107af03d9156d6218c6"},
{file = "uv-0.1.45-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd7f2f64fdded940342dc37234c11ae3508222c3c9b6b0eac5879dcd586010fa"},
{file = "uv-0.1.45-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:a39141e179fea043151a165c9155031e7976b0e4b076c0c33a45b58a420134e0"},
{file = "uv-0.1.45-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:68718add6ee2cef2816f9bf8a1dbf2d8cf63d98ddf45840f340029f65a49fd89"},
{file = "uv-0.1.45-py3-none-musllinux_1_1_i686.whl", hash = "sha256:110e0f45ddb2fe832ce50b0308be90e5439e0c02d3ffe042feeb3f759811f31f"},
{file = "uv-0.1.45-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:0f6cfe885f109bacc055edd5df2c837616ae2238b9324a9d37835a96b204ab2f"},
{file = "uv-0.1.45-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:87e77d25e8f358c0d5de1983497ee4cf4cea8fc73373d1ef1063533352db2f89"},
{file = "uv-0.1.45-py3-none-win32.whl", hash = "sha256:ddb93620c9e01fa83573c2648df4bee3fa548ca940de51c8a2c3566a23a0c776"},
{file = "uv-0.1.45-py3-none-win_amd64.whl", hash = "sha256:8e2eeea4eec0e09f7d67378152428b5308dba8b33990d045d7a31d19bf18ca1f"},
{file = "uv-0.1.45.tar.gz", hash = "sha256:40fab956bc7af50dfa4bda14e5871528f57603eb9bf8595eb3144aace0ed8c47"},
]
[metadata]
lock-version = "2.0"
python-versions = "^3.8.0,<4.0"
content-hash = "ac29a6587488fe83583561554cb37b0812f4609cf34fedc4afae8df804db0d73"
+36
View File
@@ -0,0 +1,36 @@
[tool.poetry]
name = "langgraph-cli-install"
version = "0.0.1-rc1"
description = "Simple installer for langgraph-cli"
authors = []
license = "MIT"
readme = "README.md"
repository = "https://www.github.com/langchain-ai/langgraph"
packages = [{ include = "langgraph_cli_install" }]
[tool.poetry.scripts]
langgraph-cli-install = "langgraph_cli_install.main:main"
[tool.poetry.dependencies]
python = "^3.9.0,<4.0"
packaging = ">=23.0"
uv = ">=0.6.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.ruff]
lint.select = [
# pycodestyle
"E",
# Pyflakes
"F",
# pyupgrade
"UP",
# flake8-bugbear
"B",
# isort
"I",
]
lint.ignore = ["E501", "B008"]
+36
View File
@@ -0,0 +1,36 @@
"""Setup script for the langgraph-cli-install package."""
from setuptools import find_packages, setup
if __name__ == "__main__":
setup(
name="langgraph-cli-install",
version="0.1.0",
description="Simple installer for langgraph-cli",
author="",
author_email="",
license="MIT",
packages=find_packages(),
include_package_data=True,
entry_points={
"console_scripts": [
"langgraph-cli-install=langgraph_cli_install.main:main",
],
},
python_requires=">=3.8",
install_requires=[
"uv>=0.1.24",
"packaging>=23.0",
],
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
)
+1
View File
@@ -0,0 +1 @@
"""Test package for langgraph-cli-install."""
+50
View File
@@ -0,0 +1,50 @@
"""Tests for the main module."""
import sys
from unittest.mock import MagicMock, patch
from langgraph_cli_install.main import get_latest_python_version, main
def test_get_latest_python_version():
"""Test that the get_latest_python_version function returns a string."""
with patch("subprocess.run") as mock_run:
mock_result = MagicMock()
mock_result.stdout = "python3.12"
mock_run.return_value = mock_result
with patch("uv.find_uv_bin", return_value="/path/to/uv"):
version = get_latest_python_version()
assert isinstance(version, str)
assert "python" in version
def test_get_latest_python_version_fallback():
"""Test fallback to current version when 3.12 is not available."""
with patch("subprocess.run") as mock_run:
mock_result = MagicMock()
mock_result.stdout = "python3.8" # No 3.12 here
mock_run.return_value = mock_result
with patch("uv.find_uv_bin", return_value="/path/to/uv"):
# Mock sys.version_info
old_version_info = sys.version_info
sys.version_info = MagicMock()
sys.version_info.major = 3
sys.version_info.minor = 9
try:
version = get_latest_python_version()
assert isinstance(version, str)
assert "python3.9" in version
finally:
# Restore original version_info
sys.version_info = old_version_info
def test_main_exception():
"""Test main function handles exceptions."""
with patch("uv.find_uv_bin", side_effect=Exception("Test error")):
with patch("sys.exit") as mock_exit:
main()
mock_exit.assert_called_once_with(1)
+8
View File
@@ -0,0 +1,8 @@
"""Test that the version is defined."""
import langgraph_cli_install
def test_version():
"""Test that the version is defined."""
assert langgraph_cli_install.__version__ is not None
+1 -1
View File
@@ -198,7 +198,7 @@ class CorsConfig(TypedDict, total=False):
allow_origin_regex: str
"""Optional. A regex pattern for matching allowed origins, used if you have dynamic subdomains.
Example: "^https://.*\.mycompany\.com$"
Example: "^https://\\.*\\.mycompany\\.com$"
"""
expose_headers: list[str]
"""Optional. List of headers that browsers are allowed to read from the response in cross-origin contexts."""