Files
letta-server/pyproject.toml
Kian Jones 82495b68a3 chore(ci): Add uv support and use for unit tests (#4127)
* cherrypick just relevant commits?

* make work with poetry

* update poetry?

* regen?

* change tests and dev to dependency groups instead of optional extras

* Fix Poetry/UV compatibility issues

- Fix sqlite-vec dependency: Remove optional flag from Poetry section to match main deps
- Regenerate poetry.lock to sync with pyproject.toml changes
- Test both package managers successfully:
  - Poetry: `poetry install --with dev --with test -E postgres -E external-tools -E cloud-tool-sandbox`
  - UV: `uv sync --group dev --group test --extra postgres --extra external-tools --extra cloud-tool-sandbox`

Resolves Poetry lock sync errors and ensures sqlite-vec is available for tests.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* more robust pip install

* Fix fern SDK wheel installation in CI workflow

Replace unreliable command substitution with proper error handling:
- Check if directory exists before attempting to find wheels
- Store wheel file path in variable to avoid empty arguments
- Provide clear error messages when directory/wheels are missing
- Prevents "required arguments were not provided" error in uv pip install

Fixes: error: the following required arguments were not provided: <PACKAGE>

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* debugging

* trigger CI

* ls

* revert whl installation to -e

* programmatic HIT version insertion

* version templating properly

* set var properly

* labelling

* remove version insertion

* ?

* try using sed '2r /dev/stdin'

* version

* try again smh

* not trigger on poetry version

* only add once

* filter only for project not poetry

* hand re-construct the file

* save tail?

* fix docker command

* please please please

* rename test -> tests

* update poetry and rename group to -E

* move async into tests extra and regen lock files and add sqlite extra

* remove loading cached venv from cloud api integration

* add uv dependency to CI runners

* test removing the custom event loop

* regen poetry.lock and try to fix async tests

* wrap async pg exception and event loop tweak in plugins

* remove event loop from plugins test and remove caching from cloud-api-integration-test

* migrate all tests away from event loop for pytest-asyncio

* pin firecrawl

* pin e2b

* take claude's suggestion

* deeper down the claude rabbit hole

* increase timeout for httpbin.org

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-08-26 11:51:31 -07:00

251 lines
9.1 KiB
TOML

[project]
name = "letta"
version = "0.10.0"
description = "Create LLM agents with long-term memory and custom tools"
authors = [
{name = "Letta Team", email = "contact@letta.com"},
]
license = {text = "Apache License"}
readme = "README.md"
requires-python = "<3.14,>=3.11"
dependencies = [
"typer>=0.15.2",
"questionary>=2.0.1",
"pytz>=2023.3.post1",
"tqdm>=4.66.1",
"black[jupyter]>=24.2.0",
"setuptools>=70",
"prettytable>=3.9.0",
"docstring-parser>=0.16,<0.17",
"httpx>=0.28.0",
"numpy>=2.1.0",
"demjson3>=3.0.6",
"pyyaml>=6.0.1",
"sqlalchemy-json>=0.7.0",
"pydantic>=2.10.6",
"html2text>=2020.1.16",
"sqlalchemy[asyncio]>=2.0.41",
"python-box>=7.1.1",
"sqlmodel>=0.0.16",
"python-multipart>=0.0.19",
"sqlalchemy-utils>=0.41.2",
"pydantic-settings>=2.2.1",
"httpx-sse>=0.4.0",
"nltk>=3.8.1",
"jinja2>=3.1.5",
"composio-core>=0.7.7",
"alembic>=1.13.3",
"pyhumps>=3.8.0",
"pathvalidate>=3.2.1",
"sentry-sdk[fastapi]==2.19.1",
"rich>=13.9.4",
"brotli>=1.1.0",
"grpcio>=1.68.1",
"grpcio-tools>=1.68.1",
"llama-index>=0.12.2",
"llama-index-embeddings-openai>=0.3.1",
"anthropic>=0.49.0",
"letta_client>=0.1.276",
"openai>=1.99.9",
"opentelemetry-api==1.30.0",
"opentelemetry-sdk==1.30.0",
"opentelemetry-instrumentation-requests==0.51b0",
"opentelemetry-instrumentation-sqlalchemy==0.51b0",
"opentelemetry-exporter-otlp==1.30.0",
"faker>=36.1.0",
"colorama>=0.4.6",
"marshmallow-sqlalchemy>=1.4.1",
"datamodel-code-generator[http]>=0.25.0",
"mcp[cli]>=1.9.4",
"firecrawl-py==2.16.5",
"apscheduler>=3.11.0",
"aiomultiprocess>=0.9.1",
"matplotlib>=3.10.1",
"tavily-python>=0.7.2",
"mistralai>=1.8.1",
"structlog>=25.4.0",
"certifi>=2025.6.15",
"markitdown[docx,pdf,pptx]>=0.1.2",
"orjson>=3.11.1",
]
[project.optional-dependencies]
postgres = ["pgvector>=0.2.3", "pg8000>=1.30.3", "psycopg2-binary>=2.9.10", "psycopg2>=2.9.10", "asyncpg>=0.30.0"]
redis = ["redis>=6.2.0"]
pinecone = ["pinecone[asyncio]>=7.3.0"]
dev = ["pytest>=8.0.0", "pytest-asyncio>=0.24.0", "pexpect>=4.9.0", "black>=24.2.0", "pre-commit>=3.5.0", "pyright>=1.1.347", "pytest-order>=1.2.0", "autoflake>=2.3.0", "isort>=5.13.2", "locust>=2.31.5"]
experimental = ["uvloop>=0.21.0; sys_platform != 'win32'", "granian[reload]>=2.3.2", "google-cloud-profiler>=4.1.0"]
server = ["websockets>=12.0", "fastapi>=0.115.6", "uvicorn>=0.24.0.post1"]
cloud-tool-sandbox = ["e2b-code-interpreter==1.5.2", "modal>=1.1.0"]
external-tools = ["docker>=7.1.0", "langchain>=0.3.7", "wikipedia>=1.4.0", "langchain-community>=0.3.7", "firecrawl-py==2.16.5"]
tests = ["wikipedia>=1.4.0", "pytest-asyncio>=0.24.0"]
sqlite = ["aiosqlite>=0.21.0", "sqlite-vec>=0.1.7a2"]
bedrock = ["boto3>=1.36.24", "aioboto3>=14.3.0"]
google = ["google-genai>=1.15.0"]
desktop = ["pyright>=1.1.347", "fastapi>=0.115.6", "uvicorn>=0.24.0.post1", "docker>=7.1.0", "langchain>=0.3.7", "wikipedia>=1.4.0", "langchain-community>=0.3.7", "locust>=2.31.5", "sqlite-vec>=0.1.7a2", "pgvector>=0.2.3"]
all = ["pgvector>=0.2.3", "turbopuffer>=0.5.17", "pg8000>=1.30.3", "psycopg2-binary>=2.9.10", "psycopg2>=2.9.10", "pytest", "pytest-asyncio>=0.24.0", "pexpect>=4.9.0", "black>=24.2.0", "pre-commit>=3.5.0", "pyright>=1.1.347", "pytest-order>=1.2.0", "autoflake>=2.3.0", "isort>=5.13.2", "fastapi>=0.115.6", "uvicorn>=0.24.0.post1", "docker>=7.1.0", "langchain>=0.3.7", "wikipedia>=1.4.0", "langchain-community>=0.3.7", "locust>=2.31.5", "uvloop>=0.21.0; sys_platform != 'win32'", "granian[reload]>=2.3.2", "redis>=6.2.0", "pinecone[asyncio]>=7.3.0", "google-cloud-profiler>=4.1.0"]
[project.scripts]
letta = "letta.main:app"
[tool.poetry]
name = "letta"
version = "0.10.0"
packages = [
{include = "letta"},
]
description = "Create LLM agents with long-term memory and custom tools"
authors = [
"Letta Team <contact@letta.com>",
]
license = "Apache License"
readme = "README.md"
[tool.poetry.scripts]
letta = "letta.main:app"
[tool.poetry.dependencies]
python = "<3.14,>=3.11"
typer = "^0.15.2"
questionary = "^2.0.1"
pytz = "^2023.3.post1"
tqdm = "^4.66.1"
black = {extras = ["jupyter"], version = "^24.2.0"}
setuptools = "^70"
prettytable = "^3.9.0"
pgvector = { version = "^0.2.3", optional = true }
pre-commit = {version = "^3.5.0", optional = true }
pg8000 = {version = "^1.30.3", optional = true}
docstring-parser = ">=0.16,<0.17"
httpx = "^0.28.0"
numpy = "^2.1.0"
demjson3 = "^3.0.6"
pyyaml = "^6.0.1"
sqlalchemy-json = "^0.7.0"
fastapi = { version = "^0.115.6", optional = true}
uvicorn = {version = "^0.24.0.post1", optional = true}
pydantic = "^2.10.6"
html2text = "^2020.1.16"
sqlalchemy = {extras = ["asyncio"], version = "^2.0.41"}
pexpect = {version = "^4.9.0", optional = true}
pyright = {version = "^1.1.347", optional = true}
#pymilvus = {version ="^2.4.3", optional = true}
python-box = "^7.1.1"
sqlmodel = "^0.0.16"
autoflake = {version = "^2.3.0", optional = true}
python-multipart = "^0.0.19"
sqlalchemy-utils = "^0.41.2"
pytest-order = {version = "^1.2.0", optional = true}
pytest-asyncio = {version = "^0.24.0", optional = true}
pydantic-settings = "^2.2.1"
httpx-sse = "^0.4.0"
isort = { version = "^5.13.2", optional = true }
docker = {version = "^7.1.0", optional = true}
nltk = "^3.8.1"
jinja2 = "^3.1.5"
locust = {version = "^2.31.5", optional = true}
wikipedia = {version = "^1.4.0", optional = true}
composio-core = "^0.7.7"
alembic = "^1.13.3"
pyhumps = "^3.8.0"
psycopg2 = {version = "^2.9.10", optional = true}
psycopg2-binary = {version = "^2.9.10", optional = true}
pathvalidate = "^3.2.1"
langchain-community = {version = "^0.3.7", optional = true}
langchain = {version = "^0.3.7", optional = true}
sentry-sdk = {extras = ["fastapi"], version = "2.19.1"}
rich = "^13.9.4"
brotli = "^1.1.0"
grpcio = "^1.68.1"
grpcio-tools = "^1.68.1"
llama-index = "^0.12.2"
llama-index-embeddings-openai = "^0.3.1"
e2b-code-interpreter = {version = "^1.0.3", optional = true}
anthropic = "^0.49.0"
letta_client = "^0.1.277"
openai = "^1.99.9"
opentelemetry-api = "1.30.0"
opentelemetry-sdk = "1.30.0"
opentelemetry-instrumentation-requests = "0.51b0"
opentelemetry-instrumentation-sqlalchemy = "0.51b0"
opentelemetry-exporter-otlp = "1.30.0"
google-genai = {version = "^1.15.0", optional = true}
faker = "^36.1.0"
colorama = "^0.4.6"
marshmallow-sqlalchemy = "^1.4.1"
boto3 = {version = "^1.36.24", optional = true}
datamodel-code-generator = {extras = ["http"], version = "^0.25.0"}
mcp = {extras = ["cli"], version = "^1.9.4"}
firecrawl-py = "^2.8.0"
apscheduler = "^3.11.0"
aiomultiprocess = "^0.9.1"
matplotlib = "^3.10.1"
asyncpg = {version = "^0.30.0", optional = true}
tavily-python = "^0.7.2"
mistralai = "^1.8.1"
uvloop = {version = "^0.21.0", optional = true, markers = "sys_platform != 'win32'"}
granian = {version = "^2.3.2", extras = ["reload"], optional = true}
redis = {version = "^6.2.0", optional = true}
structlog = "^25.4.0"
certifi = "^2025.6.15"
aioboto3 = {version = "^14.3.0", optional = true}
pinecone = {extras = ["asyncio"], version = "^7.3.0", optional = true}
markitdown = {extras = ["docx", "pdf", "pptx"], version = "^0.1.2"}
google-cloud-profiler = {version = "^4.1.0", optional = true}
sqlite-vec = {version = "^0.1.7a2", optional = true}
orjson = "^3.11.1"
modal = {version = "^1.1.0", optional = true}
turbopuffer = {version = "^0.5.17", optional = true}
[tool.poetry.extras]
postgres = ["pgvector", "pg8000", "psycopg2-binary", "psycopg2", "asyncpg"]
redis = ["redis"]
pinecone = ["pinecone"]
dev = ["pytest", "pytest-asyncio", "pexpect", "black", "pre-commit", "pyright", "pytest-order", "autoflake", "isort", "locust"]
experimental = ["uvloop", "granian", "google-cloud-profiler"]
server = ["websockets", "fastapi", "uvicorn"]
cloud-tool-sandbox = ["e2b-code-interpreter", "modal"] # TODO: split this up
external-tools = ["docker", "langchain", "wikipedia", "langchain-community", "firecrawl-py"]
tests = ["wikipedia"]
bedrock = ["boto3", "aioboto3"]
google = ["google-genai"]
desktop = ["pyright", "websockets", "fastapi", "uvicorn", "docker", "langchain", "wikipedia", "langchain-community", "locust", "sqlite-vec", "pgvector"]
all = ["pgvector", "turbopuffer", "pg8000", "psycopg2-binary", "psycopg2", "pytest", "pytest-asyncio", "pexpect", "black", "pre-commit", "pyright", "pytest-order", "autoflake", "isort", "websockets", "fastapi", "uvicorn", "docker", "langchain", "wikipedia", "langchain-community", "locust", "uvloop", "granian", "redis", "pinecone", "google-cloud-profiler"]
[tool.poetry.group.dev.dependencies]
black = "^24.4.2"
ipykernel = "^6.29.5"
ipdb = "^0.13.13"
pytest-mock = "^3.14.0"
[tool.poetry.group."dev,tests".dependencies]
pytest-json-report = "^1.5.0"
[tool.poetry.group.sqlite.dependencies]
aiosqlite = "^0.21.0"
# https://github.com/asg017/sqlite-vec/issues/148
sqlite-vec = "^0.1.7a2"
[tool.poetry.group.desktop.dependencies]
sqlite-vec = "^0.1.7a2"
[tool.black]
line-length = 140
target-version = ['py310', 'py311', 'py312', 'py313']
extend-exclude = "examples/*"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.isort]
profile = "black"
line_length = 140
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true