mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-09-22 09:35:07 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
656737009b | ||
|
|
ecdf70a2ab |
@@ -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/
|
||||||
@@ -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.
|
||||||
@@ -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
|
||||||
@@ -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()
|
||||||
Generated
+44
@@ -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"
|
||||||
@@ -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"]
|
||||||
@@ -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",
|
||||||
|
],
|
||||||
|
)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
"""Test package for langgraph-cli-install."""
|
||||||
@@ -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)
|
||||||
@@ -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
|
||||||
@@ -198,7 +198,7 @@ class CorsConfig(TypedDict, total=False):
|
|||||||
allow_origin_regex: str
|
allow_origin_regex: str
|
||||||
"""Optional. A regex pattern for matching allowed origins, used if you have dynamic subdomains.
|
"""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]
|
expose_headers: list[str]
|
||||||
"""Optional. List of headers that browsers are allowed to read from the response in cross-origin contexts."""
|
"""Optional. List of headers that browsers are allowed to read from the response in cross-origin contexts."""
|
||||||
|
|||||||
Reference in New Issue
Block a user