mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-18 13:45:44 +02:00
Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8ca30d8e0 | ||
|
|
6d20a0b9c7 | ||
|
|
df8becd5cf | ||
|
|
056ba91a71 | ||
|
|
02300de24c | ||
|
|
ac16bdb795 | ||
|
|
0d4ac836e3 | ||
|
|
201c8015ea | ||
|
|
cf3e8252f5 | ||
|
|
7a5e3c1e79 | ||
|
|
218c60717e | ||
|
|
28b9f578b0 | ||
|
|
bef76b791c | ||
|
|
a1b34efdb0 | ||
|
|
7ab5788f25 | ||
|
|
b0a1029d55 | ||
|
|
c2ef3f3fd3 | ||
|
|
d455bd841d | ||
|
|
69a09adef6 | ||
|
|
35aa98b110 | ||
|
|
0f83d9fafe | ||
|
|
52d66df92c | ||
|
|
4ec92f9fb1 | ||
|
|
2b72953064 | ||
|
|
232014e8ef | ||
|
|
9fd3dfc542 | ||
|
|
ff38f75594 | ||
|
|
bbdd007341 | ||
|
|
3c75e414e5 | ||
|
|
575401c78c | ||
|
|
092c9ecde6 | ||
|
|
8336686e89 | ||
|
|
8b080a091e | ||
|
|
1157ec77b4 | ||
|
|
a10a66cbd1 | ||
|
|
ae525fb74f | ||
|
|
a6dde39be7 | ||
|
|
c1661dd07f | ||
|
|
2d848ffddd | ||
|
|
4c8d965710 | ||
|
|
4ac1c628ee | ||
|
|
41f8e61589 | ||
|
|
57a877279d | ||
|
|
d6dea53323 | ||
|
|
504e91ad5a | ||
|
|
10abf2deb1 | ||
|
|
5796ca9a0a | ||
|
|
fca3e4513c | ||
|
|
c5744f583b | ||
|
|
d298b489b4 | ||
|
|
c4144bb48f | ||
|
|
2c3e380a35 | ||
|
|
cf39fa5a91 | ||
|
|
7e666b58cd |
@@ -1,21 +1,21 @@
|
||||
name: "\U0001F41B Bug Report"
|
||||
description: Report a bug in LangGraph. To report a security issue, please instead use the security option below. For questions, please use the LangChain Forum at forum.langchain.com.
|
||||
labels: [pending,bug]
|
||||
labels: [pending, bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to file a bug report.
|
||||
|
||||
|
||||
Use this to report BUGS in LangGraph. For usage questions, feature requests and general design questions, please use the [LangChain Forum](https://forum.langchain.com/).
|
||||
|
||||
|
||||
Relevant links to check before filing a bug report to see if your issue has already been reported, fixed or
|
||||
if there's another way to solve your problem:
|
||||
|
||||
|
||||
* [LangChain Forum](https://forum.langchain.com/),
|
||||
* [LangGraph Github Issues](https://github.com/langchain-ai/langgraph/issues),
|
||||
* [LangGraph how-to guides](https://langchain-ai.github.io/langgraph/how-tos/).
|
||||
* [LangChain documentation with the integrated search](https://python.langchain.com/docs/get_started/introduction),
|
||||
* [LangChain documentation with the integrated search](https://docs.langchain.com/),
|
||||
* [GitHub search](https://github.com/langchain-ai/langgraph),
|
||||
- type: checkboxes
|
||||
id: checks
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import logging
|
||||
import pathlib
|
||||
import sys
|
||||
import time
|
||||
from urllib import request, error
|
||||
from urllib import error, request
|
||||
|
||||
import langgraph_cli
|
||||
import langgraph_cli.config
|
||||
@@ -11,9 +12,13 @@ from langgraph_cli.constants import DEFAULT_PORT
|
||||
from langgraph_cli.exec import Runner, subp_exec
|
||||
from langgraph_cli.progress import Progress
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
|
||||
def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
|
||||
"""Spin up API with Postgres/Redis via docker compose and wait until ready."""
|
||||
logger.info("Starting test...")
|
||||
with Runner() as runner, Progress(message="Pulling...") as set:
|
||||
# Detect docker/compose capabilities
|
||||
capabilities = langgraph_cli.docker.check_capabilities(runner)
|
||||
@@ -57,7 +62,9 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
|
||||
sys.stderr.write(f"docker compose up failed: {e}\n")
|
||||
try:
|
||||
sys.stderr.write("\n== docker compose ps ==\n")
|
||||
runner.run(subp_exec(*compose_cmd, *args, "ps", input=stdin, verbose=False))
|
||||
runner.run(
|
||||
subp_exec(*compose_cmd, *args, "ps", input=stdin, verbose=False)
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
@@ -93,7 +100,7 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
|
||||
set("")
|
||||
base_url = f"http://localhost:{port}"
|
||||
ok_url = f"{base_url}/ok"
|
||||
print(f"Waiting for {ok_url} to respond with 200...")
|
||||
logger.info(f"Waiting for {ok_url} to respond with 200...")
|
||||
deadline = time.time() + 30
|
||||
last_err: Exception | None = None
|
||||
while time.time() < deadline:
|
||||
@@ -107,13 +114,16 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
|
||||
break
|
||||
else:
|
||||
last_err = RuntimeError(f"Unexpected status: {resp.status}")
|
||||
print(f"Unexpected status: {resp.status}")
|
||||
logger.error(f"Unexpected status: {resp.status}")
|
||||
except error.URLError as e:
|
||||
logger.error(f"URLError: {e}")
|
||||
last_err = e
|
||||
except Exception as e: # noqa: BLE001
|
||||
logger.error(f"Exception: {e}")
|
||||
last_err = e
|
||||
time.sleep(0.5)
|
||||
else:
|
||||
logger.error("Timeout waiting for /ok to return 200")
|
||||
# Bring stack down before raising
|
||||
args_down = [*args, "down", "-v", "--remove-orphans"]
|
||||
try:
|
||||
@@ -131,15 +141,23 @@ def test(config: pathlib.Path, port: int, tag: str, verbose: bool):
|
||||
)
|
||||
|
||||
# Clean up: bring compose stack down to free ports for next test
|
||||
args_down = [*args, "down", "-v", "--remove-orphans"]
|
||||
runner.run(
|
||||
subp_exec(
|
||||
*compose_cmd,
|
||||
*args_down,
|
||||
input=stdin,
|
||||
verbose=verbose,
|
||||
logger.info("Test succeeded. Bringing down compose stack...")
|
||||
try:
|
||||
args_down = [*args, "down", "-v", "--remove-orphans"]
|
||||
runner.run(
|
||||
subp_exec(
|
||||
*compose_cmd,
|
||||
*args_down,
|
||||
input=stdin,
|
||||
verbose=verbose,
|
||||
)
|
||||
)
|
||||
)
|
||||
logger.info("Compose stack down. Finishing...")
|
||||
except Exception:
|
||||
logger.exception("Failed to bring down compose stack")
|
||||
pass
|
||||
|
||||
logger.info("Test finished")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -150,4 +168,10 @@ if __name__ == "__main__":
|
||||
parser.add_argument("-c", "--config", type=str, default="./langgraph.json")
|
||||
parser.add_argument("-p", "--port", type=int, default=DEFAULT_PORT)
|
||||
args = parser.parse_args()
|
||||
test(pathlib.Path(args.config), args.port, args.tag, verbose=True)
|
||||
try:
|
||||
test(pathlib.Path(args.config), args.port, args.tag, verbose=True)
|
||||
except BaseException:
|
||||
logger.exception("Test failed")
|
||||
raise
|
||||
|
||||
logger.info("Test execution finished")
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.14"
|
||||
example:
|
||||
- name: A
|
||||
workdir: libs/cli/examples
|
||||
@@ -66,19 +66,19 @@ jobs:
|
||||
timeout 60 python "$REPO_ROOT/.github/scripts/run_langgraph_cli_test.py" -t ${{ matrix.example.tag }}
|
||||
|
||||
- name: Build JS service
|
||||
if: steps.changed-files.outputs.all
|
||||
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' }}
|
||||
working-directory: libs/cli/js-examples
|
||||
run: |
|
||||
langgraph build -t langgraph-test-e
|
||||
|
||||
- name: Build JS monorepo service
|
||||
if: steps.changed-files.outputs.all
|
||||
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' }}
|
||||
working-directory: libs/cli/js-monorepo-example
|
||||
run: |
|
||||
langgraph build -t langgraph-test-f -c apps/agent/langgraph.json --build-command "yarn run turbo build" --install-command "yarn install"
|
||||
|
||||
- name: Build Python monorepo service
|
||||
if: steps.changed-files.outputs.all
|
||||
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' }}
|
||||
working-directory: libs/cli/python-monorepo-example
|
||||
run: |
|
||||
langgraph build -t langgraph-test-g -c apps/agent/langgraph.json
|
||||
@@ -87,24 +87,32 @@ jobs:
|
||||
timeout 60 python ../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-g -c apps/agent/langgraph.json
|
||||
|
||||
- name: Build and test prerelease reqs service
|
||||
if: steps.changed-files.outputs.all
|
||||
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' }}
|
||||
working-directory: libs/cli/examples/graph_prerelease_reqs
|
||||
run: |
|
||||
langgraph build -t langgraph-test-h
|
||||
cp ../.env.example .env
|
||||
if [ -n "${{ secrets.LANGSMITH_API_KEY }}" ]; then echo "LANGSMITH_API_KEY=${{ secrets.LANGSMITH_API_KEY }}" >> .env; fi
|
||||
timeout 60 python ../../../../.github/scripts/run_langgraph_cli_test.py -t langgraph-test-h
|
||||
echo "Finished starting up langgraph-test-h"
|
||||
LANGGRAPH_VERSION=$(docker run --rm --entrypoint "" langgraph-test-h python -c "import sys; from importlib.metadata import version; v = version('langgraph'); print(v);")
|
||||
if [ "$LANGGRAPH_VERSION" != "1.0.0a2" ]; then
|
||||
if [ "$LANGGRAPH_VERSION" != "1.0.2" ]; then
|
||||
echo "LANGGRAPH_VERSION != 1.0.2; $LANGGRAPH_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
LANGCHAIN_OPENAI_VERSION=$(docker run --rm --entrypoint "" langgraph-test-h python -c "import sys; from importlib.metadata import version; v = version('langchain-openai'); print(v);")
|
||||
if [ "$LANGCHAIN_OPENAI_VERSION" != "0.3.0" ]; then
|
||||
if [ "$LANGCHAIN_OPENAI_VERSION" != "1.0.1" ]; then
|
||||
echo "LANGCHAIN_OPENAI_VERSION != 1.0.1; $LANGCHAIN_OPENAI_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
LANGCHAIN_ANTHROPIC_VERSION=$(docker run --rm --entrypoint "" langgraph-test-h python -c "import sys; from importlib.metadata import version; v = version('langchain-anthropic'); print(v);")
|
||||
if [ "$LANGCHAIN_ANTHROPIC_VERSION" != "1.0.0a5" ]; then
|
||||
echo "LANGCHAIN_ANTHROPIC_VERSION != 1.0.0a5; $LANGCHAIN_ANTHROPIC_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Build and test prerelease reqs fail service
|
||||
if: steps.changed-files.outputs.all
|
||||
if: ${{ steps.changed-files.outputs.all && matrix.example.name == 'A' }}
|
||||
working-directory: libs/cli/examples/graph_prerelease_reqs_fail
|
||||
run: |
|
||||
langgraph build -t langgraph-test-i || [ $? -eq 1 ]
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
if: steps.changed-files.outputs.all
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: uv sync --frozen --group dev
|
||||
run: uv sync --frozen --group lint
|
||||
|
||||
- name: Get .mypy_cache to speed up mypy
|
||||
if: steps.changed-files.outputs.all
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
- name: Install test dependencies
|
||||
if: steps.changed-files.outputs.all
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: uv sync --group dev
|
||||
run: uv sync --group lint
|
||||
|
||||
- name: Get .mypy_cache_test to speed up mypy
|
||||
if: steps.changed-files.outputs.all
|
||||
|
||||
@@ -21,6 +21,7 @@ jobs:
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
|
||||
name: "test #${{ matrix.python-version }}"
|
||||
steps:
|
||||
@@ -41,7 +42,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
run: uv sync --frozen --group dev
|
||||
run: uv sync --frozen --group test --no-dev
|
||||
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
|
||||
@@ -16,6 +16,7 @@ jobs:
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3.13"
|
||||
- "3.14"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
@@ -38,7 +39,7 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
shell: bash
|
||||
run: uv sync --frozen --group dev
|
||||
run: uv sync --frozen --group test --no-dev
|
||||
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: test-dist
|
||||
path: ${{ inputs.working-directory }}/dist/
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: test-dist
|
||||
path: ${{ inputs.working-directory }}/dist/
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
enable-cache: true
|
||||
cache-suffix: "bench"
|
||||
- name: Install dependencies
|
||||
run: uv sync --group dev
|
||||
run: uv sync --group test
|
||||
- name: Run benchmarks
|
||||
run: OUTPUT=out/benchmark-baseline.json make -s benchmark
|
||||
- name: Save outputs
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
enable-cache: true
|
||||
cache-suffix: "bench"
|
||||
- name: Install dependencies
|
||||
run: uv sync --group dev
|
||||
run: uv sync --group test
|
||||
- name: Download baseline
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
|
||||
- name: Upload build
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: dist
|
||||
path: ${{ inputs.working-directory }}/dist/
|
||||
@@ -221,7 +221,7 @@ jobs:
|
||||
uv run python -c "import $IMPORT_NAME; print(dir($IMPORT_NAME))"
|
||||
|
||||
- name: Import test dependencies
|
||||
run: uv sync --group dev
|
||||
run: uv sync --group test
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
|
||||
# Overwrite the local version of the package with the test PyPI version.
|
||||
@@ -269,7 +269,7 @@ jobs:
|
||||
enable-cache: true
|
||||
cache-suffix: "release"
|
||||
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: dist
|
||||
path: ${{ inputs.working-directory }}/dist/
|
||||
@@ -310,7 +310,7 @@ jobs:
|
||||
enable-cache: true
|
||||
cache-suffix: "release"
|
||||
|
||||
- uses: actions/download-artifact@v5
|
||||
- uses: actions/download-artifact@v6
|
||||
with:
|
||||
name: dist
|
||||
path: ${{ inputs.working-directory }}/dist/
|
||||
|
||||
@@ -64,7 +64,7 @@ While LangGraph can be used standalone, it also integrates seamlessly with any L
|
||||
|
||||
- [LangSmith](http://www.langchain.com/langsmith) — Helpful for agent evals and observability. Debug poor-performing LLM app runs, evaluate agent trajectories, gain visibility in production, and improve performance over time.
|
||||
- [LangSmith Deployment](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) — Deploy and scale agents effortlessly with a purpose-built deployment platform for long running, stateful workflows. Discover, reuse, configure, and share agents across teams — and iterate quickly with visual prototyping in [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/).
|
||||
- [LangChain](https://python.langchain.com/docs/introduction/) – Provides integrations and composable components to streamline LLM application development.
|
||||
- [LangChain](https://docs.langchain.com/oss/python/langchain/overview) – Provides integrations and composable components to streamline LLM application development.
|
||||
|
||||
> [!NOTE]
|
||||
> Looking for the JS version of LangGraph? See the [JS repo](https://github.com/langchain-ai/langgraphjs) and the [JS docs](https://langchain-ai.github.io/langgraphjs/).
|
||||
@@ -81,4 +81,4 @@ While LangGraph can be used standalone, it also integrates seamlessly with any L
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
|
||||
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
|
||||
|
||||
Binary file not shown.
@@ -2108,9 +2108,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"hono@npm:^4.5.4":
|
||||
version: 4.9.7
|
||||
resolution: "hono@npm:4.9.7"
|
||||
checksum: 10c0/089184660a9211ea216ab95bafa45260e371651cb019db49828064b7982b0ae61cc3c4715324bfeb9037aa2460c39ffa2c91d84ad0c8d500fa77cbcc7fc07a8f
|
||||
version: 4.10.3
|
||||
resolution: "hono@npm:4.10.3"
|
||||
checksum: 10c0/bdcc4c7066c74ba7cfa63ed6550768a0f43a420286c8f8f74b7012ea4901b8b06778fa8e98264b46f1a86920f056b7ede1f07814da4934912f9945def4977c29
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ REDIRECT_MAP = {
|
||||
# cloud redirects
|
||||
"cloud/index.md": "https://docs.langchain.com/oss/python/langgraph/overview",
|
||||
"cloud/how-tos/index.md": "https://docs.langchain.com/langsmith/home",
|
||||
"cloud/concepts/api.md": "https://docs.langchain.com/langsmith/langgraph-server",
|
||||
"cloud/concepts/api.md": "https://docs.langchain.com/langsmith/agent-server",
|
||||
"cloud/concepts/cloud.md": "https://docs.langchain.com/langsmith/cloud",
|
||||
"cloud/faq/studio.md": "https://docs.langchain.com/langsmith/studio",
|
||||
"cloud/how-tos/human_in_the_loop_edit_state.md": "https://docs.langchain.com/langsmith/add-human-in-the-loop",
|
||||
@@ -111,8 +111,8 @@ REDIRECT_MAP = {
|
||||
"tutorials/introduction.ipynb": "https://docs.langchain.com/oss/python/langgraph/overview",
|
||||
"agents/deployment.md": "https://docs.langchain.com/oss/python/langgraph/local-server",
|
||||
# deployment redirects
|
||||
"how-tos/deploy-self-hosted.md": "https://docs.langchain.com/langsmith/hosting",
|
||||
"concepts/self_hosted.md": "https://docs.langchain.com/langsmith/hosting",
|
||||
"how-tos/deploy-self-hosted.md": "https://docs.langchain.com/langsmith/platform-setup",
|
||||
"concepts/self_hosted.md": "https://docs.langchain.com/langsmith/platform-setup",
|
||||
"tutorials/deployment.md": "https://docs.langchain.com/langsmith/deployments",
|
||||
# assistant redirects
|
||||
"cloud/how-tos/assistant_versioning.md": "https://docs.langchain.com/langsmith/configuration-cloud",
|
||||
@@ -129,16 +129,30 @@ REDIRECT_MAP = {
|
||||
"how-tos/human_in_the_loop/edit-graph-state.ipynb": "https://docs.langchain.com/oss/python/langgraph/use-time-travel",
|
||||
|
||||
# LGP mintlify migration redirects
|
||||
"examples/index.md": "https://docs.langchain.com/oss/python/learn",
|
||||
"guides/index.md": "https://docs.langchain.com/oss/python/langgraph/overview",
|
||||
"concepts/index.md": "https://docs.langchain.com/oss/python/langgraph/overview",
|
||||
"tutorials/index.md": "https://docs.langchain.com/oss/python/learn",
|
||||
"llms-txt-overview.md": "https://docs.langchain.com/llms.txt",
|
||||
"tutorials/rag/langgraph_adaptive_rag.md": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
|
||||
"tutorials/multi_agent/multi-agent-collaboration.ipynb": "https://docs.langchain.com/oss/python/langchain/multi-agent",
|
||||
"how-tos/create-react-agent-manage-message-history.ipynb": "https://docs.langchain.com/oss/python/langgraph/add-memory",
|
||||
"how-tos/many-tools.ipynb": "https://docs.langchain.com/oss/python/langchain/tools",
|
||||
"tutorials/customer-support/customer-support.ipynb": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
|
||||
"how-tos/react-agent-structured-output.ipynb": "https://docs.langchain.com/oss/python/langchain/agents#structured-output",
|
||||
"tutorials/code_assistant/langgraph_code_assistant.ipynb": "https://docs.langchain.com/oss/python/langgraph/agentic-rag",
|
||||
"tutorials/multi_agent/hierarchical_agent_teams.ipynb": "https://docs.langchain.com/oss/python/langchain/supervisor",
|
||||
"tutorials/auth/getting_started.md": "https://docs.langchain.com/langsmith/auth",
|
||||
"tutorials/auth/resource_auth.md": "https://docs.langchain.com/langsmith/resource-auth",
|
||||
"tutorials/auth/add_auth_server.md": "https://docs.langchain.com/langsmith/add-auth-server",
|
||||
"how-tos/use-remote-graph.md": "https://docs.langchain.com/langsmith/use-remote-graph",
|
||||
"how-tos/autogen-integration.md": "https://docs.langchain.com/langsmith/autogen-integration",
|
||||
"how-tos/human_in_the_loop/wait-user-input.ipynb": "https://docs.langchain.com/oss/python/langgraph/interrupts",
|
||||
"cloud/how-tos/use_stream_react.md": "https://docs.langchain.com/langsmith/use-stream-react",
|
||||
"cloud/how-tos/generative_ui_react.md": "https://docs.langchain.com/langsmith/generative-ui-react",
|
||||
"concepts/langgraph_platform.md": "https://docs.langchain.com/langsmith/deployments",
|
||||
"concepts/langgraph_components.md": "https://docs.langchain.com/langsmith/components",
|
||||
"concepts/langgraph_server.md": "https://docs.langchain.com/langsmith/langgraph-server",
|
||||
"concepts/langgraph_server.md": "https://docs.langchain.com/langsmith/agent-server",
|
||||
"concepts/langgraph_data_plane.md": "https://docs.langchain.com/langsmith/data-plane",
|
||||
"concepts/langgraph_control_plane.md": "https://docs.langchain.com/langsmith/control-plane",
|
||||
"concepts/langgraph_cli.md": "https://docs.langchain.com/langsmith/cli",
|
||||
@@ -180,7 +194,7 @@ REDIRECT_MAP = {
|
||||
"cloud/concepts/data_storage_and_privacy.md": "https://docs.langchain.com/langsmith/data-storage-and-privacy",
|
||||
"cloud/deployment/semantic_search.md": "https://docs.langchain.com/langsmith/semantic-search",
|
||||
"how-tos/ttl/configure_ttl.md": "https://docs.langchain.com/langsmith/configure-ttl",
|
||||
"concepts/deployment_options.md": "https://docs.langchain.com/langsmith/hosting",
|
||||
"concepts/deployment_options.md": "https://docs.langchain.com/langsmith/platform-setup",
|
||||
"cloud/quick_start.md": "https://docs.langchain.com/langsmith/deployment-quickstart",
|
||||
"cloud/deployment/setup.md": "https://docs.langchain.com/langsmith/setup-app-requirements-txt",
|
||||
"cloud/deployment/setup_pyproject.md": "https://docs.langchain.com/langsmith/setup-pyproject",
|
||||
@@ -201,7 +215,7 @@ REDIRECT_MAP = {
|
||||
"cloud/deployment/egress.md": "https://docs.langchain.com/langsmith/env-var",
|
||||
"cloud/how-tos/streaming.md": "https://docs.langchain.com/langsmith/streaming",
|
||||
"cloud/reference/api/api_ref.md": "https://docs.langchain.com/langsmith/server-api-ref",
|
||||
"cloud/reference/langgraph_server_changelog.md": "https://docs.langchain.com/langsmith/langgraph-server-changelog",
|
||||
"cloud/reference/langgraph_server_changelog.md": "https://docs.langchain.com/langsmith/agent-server-changelog",
|
||||
"cloud/reference/api/api_ref_control_plane.md": "https://docs.langchain.com/langsmith/api-ref-control-plane",
|
||||
"cloud/reference/cli.md": "https://docs.langchain.com/langsmith/cli",
|
||||
"cloud/reference/env_var.md": "https://docs.langchain.com/langsmith/env-var",
|
||||
@@ -219,12 +233,15 @@ REDIRECT_MAP = {
|
||||
"tutorials/get-started/6-time-travel.md": "https://docs.langchain.com/oss/python/langgraph/quickstart",
|
||||
"tutorials/langsmith/local-server.md": "https://docs.langchain.com/oss/python/langgraph/local-server",
|
||||
"tutorials/workflows.md": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
|
||||
"tutorials/plan-and-execute/plan-and-execute.ipynb": "https://docs.langchain.com/oss/python/langchain/middleware/built-in#to-do-list",
|
||||
"tutorials/langgraph-platform/local-server/local-server.md": "https://docs.langchain.com/langsmith/local-server",
|
||||
"concepts/agentic_concepts.md": "https://docs.langchain.com/oss/python/langgraph/workflows-agents",
|
||||
"guides/index.md": "https://docs.langchain.com/oss/python/langchain/overview",
|
||||
"agents/overview.md": "https://docs.langchain.com/oss/python/langchain/agents",
|
||||
"agents/run_agents.md": "https://docs.langchain.com/oss/python/langgraph/quickstart",
|
||||
"concepts/low_level.md": "https://docs.langchain.com/oss/python/langgraph/graph-api",
|
||||
"how-tos/graph-api.md": "https://docs.langchain.com/oss/python/langgraph/graph-api",
|
||||
"how-tos/react-agent-from-scratch.ipynb": "https://docs.langchain.com/oss/python/langchain/quickstart",
|
||||
"concepts/functional_api.md": "https://docs.langchain.com/oss/python/langgraph/functional-api",
|
||||
"how-tos/use-functional-api.md": "https://docs.langchain.com/oss/python/langgraph/functional-api",
|
||||
"concepts/pregel.md": "https://docs.langchain.com/oss/python/langgraph/pregel",
|
||||
@@ -282,8 +299,8 @@ REDIRECT_MAP = {
|
||||
"reference/supervisor.md": "https://reference.langchain.com/python/langgraph/supervisor/",
|
||||
"reference/swarm.md": "https://reference.langchain.com/python/langgraph/swarm/",
|
||||
"reference/mcp.md": "https://reference.langchain.com/python/langgraph/mcp/",
|
||||
"cloud/reference/sdk/python_sdk_ref.md": "https://reference.langchain.com/python/platform/python_sdk/",
|
||||
"reference/remote_graph.md": "https://reference.langchain.com/python/platform/remote_graph/",
|
||||
"cloud/reference/sdk/python_sdk_ref.md": "https://reference.langchain.com/python/langsmith/deployment/sdk/",
|
||||
"reference/remote_graph.md": "https://reference.langchain.com/python/langsmith/deployment/remote_graph/",
|
||||
|
||||
# additional exclude-search entries from mkdocs.yml
|
||||
"additional-resources/index.md": "https://docs.langchain.com/oss/python/langchain/overview",
|
||||
@@ -294,8 +311,8 @@ REDIRECT_MAP = {
|
||||
"cloud/deployment/custom_docker.md": "https://docs.langchain.com/langsmith/custom-docker",
|
||||
"cloud/deployment/egress.md": "https://docs.langchain.com/langsmith/env-var",
|
||||
"cloud/deployment/graph_rebuild.md": "https://docs.langchain.com/langsmith/graph-rebuild",
|
||||
"cloud/deployment/self_hosted_control_plane.md": "https://docs.langchain.com/langsmith/hosting",
|
||||
"cloud/deployment/self_hosted_data_plane.md": "https://docs.langchain.com/langsmith/hosting",
|
||||
"cloud/deployment/self_hosted_control_plane.md": "https://docs.langchain.com/langsmith/platform-setup",
|
||||
"cloud/deployment/self_hosted_data_plane.md": "https://docs.langchain.com/langsmith/platform-setup",
|
||||
"cloud/deployment/semantic_search.md": "https://docs.langchain.com/langsmith/semantic-search",
|
||||
"cloud/deployment/setup_javascript.md": "https://docs.langchain.com/langsmith/setup-javascript",
|
||||
"cloud/deployment/setup_pyproject.md": "https://docs.langchain.com/langsmith/setup-pyproject",
|
||||
@@ -331,7 +348,7 @@ REDIRECT_MAP = {
|
||||
"cloud/reference/api/api_ref.md": "https://docs.langchain.com/langsmith/server-api-ref",
|
||||
"cloud/reference/cli.md": "https://docs.langchain.com/langsmith/cli",
|
||||
"cloud/reference/env_var.md": "https://docs.langchain.com/langsmith/env-var",
|
||||
"cloud/reference/langgraph_server_changelog.md": "https://docs.langchain.com/langsmith/langgraph-server-changelog",
|
||||
"cloud/reference/langgraph_server_changelog.md": "https://docs.langchain.com/langsmith/agent-server-changelog",
|
||||
"cloud/reference/sdk/js_ts_sdk_ref.md": "https://reference.langchain.com/javascript/modules/langsmith.html",
|
||||
"concepts/application_structure.md": "https://docs.langchain.com/langsmith/application-structure",
|
||||
"concepts/assistants.md": "https://docs.langchain.com/langsmith/assistants",
|
||||
@@ -345,9 +362,9 @@ REDIRECT_MAP = {
|
||||
"concepts/langgraph_control_plane.md": "https://docs.langchain.com/langsmith/control-plane",
|
||||
"concepts/langgraph_data_plane.md": "https://docs.langchain.com/langsmith/data-plane",
|
||||
"concepts/langgraph_platform.md": "https://docs.langchain.com/langsmith/home",
|
||||
"concepts/langgraph_self_hosted_control_plane.md": "https://docs.langchain.com/langsmith/hosting",
|
||||
"concepts/langgraph_self_hosted_data_plane.md": "https://docs.langchain.com/langsmith/hosting",
|
||||
"concepts/langgraph_server.md": "https://docs.langchain.com/langsmith/langgraph-server",
|
||||
"concepts/langgraph_self_hosted_control_plane.md": "https://docs.langchain.com/langsmith/platform-setup",
|
||||
"concepts/langgraph_self_hosted_data_plane.md": "https://docs.langchain.com/langsmith/platform-setup",
|
||||
"concepts/langgraph_server.md": "https://docs.langchain.com/langsmith/agent-server",
|
||||
"concepts/langgraph_standalone_container.md": "https://docs.langchain.com/langsmith/docker",
|
||||
"concepts/langgraph_studio.md": "https://docs.langchain.com/langsmith/studio",
|
||||
"concepts/plans.md": "https://docs.langchain.com/langsmith/home",
|
||||
@@ -793,6 +810,17 @@ def on_post_build(config):
|
||||
# Track which paths have explicit redirects
|
||||
redirected_paths = set()
|
||||
|
||||
# Collect all existing HTML files in the site
|
||||
all_html_files = set()
|
||||
for root, dirs, files in os.walk(site_dir):
|
||||
for file in files:
|
||||
if file.endswith(".html"):
|
||||
# Get relative path from site_dir
|
||||
html_path = os.path.relpath(os.path.join(root, file), site_dir)
|
||||
# Normalize path separators to forward slashes
|
||||
html_path = html_path.replace(os.sep, "/")
|
||||
all_html_files.add(html_path)
|
||||
|
||||
# Process explicit redirects from REDIRECT_MAP
|
||||
for page_old, page_new in REDIRECT_MAP.items():
|
||||
# Convert .ipynb to .md for path calculation
|
||||
@@ -847,6 +875,24 @@ def on_post_build(config):
|
||||
|
||||
_write_html(site_dir, old_html_path, new_html_path)
|
||||
|
||||
# Create catch-all redirects for any HTML files not explicitly redirected
|
||||
catchall_url = "https://docs.langchain.com/oss/python/langgraph/overview"
|
||||
for html_file in all_html_files:
|
||||
# Skip if this file is already explicitly redirected
|
||||
if html_file in redirected_paths:
|
||||
continue
|
||||
|
||||
# Skip the root index.html (we handle that separately)
|
||||
if html_file == "index.html":
|
||||
continue
|
||||
|
||||
# Skip reference documentation (keep those accessible)
|
||||
if html_file.startswith("reference/"):
|
||||
continue
|
||||
|
||||
# Create redirect for this unmapped file
|
||||
_write_html(site_dir, html_file, catchall_url)
|
||||
|
||||
# Create root index.html redirect
|
||||
root_redirect_html = """<!doctype html>
|
||||
<html lang="en">
|
||||
@@ -872,10 +918,14 @@ def on_post_build(config):
|
||||
|
||||
# Create server-side catch-all redirect file for Netlify/Cloudflare Pages
|
||||
# This handles any pages not explicitly mapped in REDIRECT_MAP
|
||||
# Note: This won't work on GitHub Pages, but kept for potential future use
|
||||
redirects_content = """# Netlify/Cloudflare Pages redirect rules
|
||||
# Specific redirects are handled by individual HTML redirect pages
|
||||
# This is the catch-all for any unmapped pages
|
||||
|
||||
# Exclude reference docs from catch-all
|
||||
/reference/* 200
|
||||
|
||||
# Catch-all: redirect any page not explicitly mapped
|
||||
/* https://docs.langchain.com/oss/python/langgraph/overview 301
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 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.
|
||||
@@ -97,7 +97,7 @@ class PostgresSaver(BasePostgresSaver):
|
||||
strict=False,
|
||||
):
|
||||
cur.execute(migration)
|
||||
cur.execute(f"INSERT INTO checkpoint_migrations (v) VALUES ({v})")
|
||||
cur.execute("INSERT INTO checkpoint_migrations (v) VALUES (%s)", (v,))
|
||||
if self.pipe:
|
||||
self.pipe.sync()
|
||||
|
||||
|
||||
@@ -102,7 +102,9 @@ class AsyncPostgresSaver(BasePostgresSaver):
|
||||
strict=False,
|
||||
):
|
||||
await cur.execute(migration)
|
||||
await cur.execute(f"INSERT INTO checkpoint_migrations (v) VALUES ({v})")
|
||||
await cur.execute(
|
||||
"INSERT INTO checkpoint_migrations (v) VALUES (%s)", (v,)
|
||||
)
|
||||
if self.pipe:
|
||||
await self.pipe.sync()
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ MIGRATIONS = [
|
||||
"""
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS checkpoint_writes_thread_id_idx ON checkpoint_writes(thread_id);
|
||||
""",
|
||||
"""ALTER TABLE checkpoint_writes ADD COLUMN task_path TEXT NOT NULL DEFAULT '';""",
|
||||
"""ALTER TABLE checkpoint_writes ADD COLUMN IF NOT EXISTS task_path TEXT NOT NULL DEFAULT '';""",
|
||||
]
|
||||
|
||||
SELECT_SQL = """
|
||||
|
||||
@@ -77,7 +77,7 @@ MIGRATIONS = [
|
||||
CREATE INDEX CONCURRENTLY IF NOT EXISTS checkpoint_writes_thread_id_idx ON checkpoint_writes(thread_id);
|
||||
""",
|
||||
"""
|
||||
ALTER TABLE checkpoint_writes ADD COLUMN task_path TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE checkpoint_writes ADD COLUMN IF NOT EXISTS task_path TEXT NOT NULL DEFAULT '';
|
||||
""",
|
||||
]
|
||||
|
||||
@@ -252,7 +252,7 @@ class ShallowPostgresSaver(BasePostgresSaver):
|
||||
strict=False,
|
||||
):
|
||||
cur.execute(migration)
|
||||
cur.execute(f"INSERT INTO checkpoint_migrations (v) VALUES ({v})")
|
||||
cur.execute("INSERT INTO checkpoint_migrations (v) VALUES (%s)", (v,))
|
||||
if self.pipe:
|
||||
self.pipe.sync()
|
||||
|
||||
@@ -614,7 +614,9 @@ class AsyncShallowPostgresSaver(BasePostgresSaver):
|
||||
strict=False,
|
||||
):
|
||||
await cur.execute(migration)
|
||||
await cur.execute(f"INSERT INTO checkpoint_migrations (v) VALUES ({v})")
|
||||
await cur.execute(
|
||||
"INSERT INTO checkpoint_migrations (v) VALUES (%s)", (v,)
|
||||
)
|
||||
if self.pipe:
|
||||
await self.pipe.sync()
|
||||
|
||||
|
||||
@@ -91,7 +91,12 @@ WHERE expires_at IS NOT NULL;
|
||||
VECTOR_MIGRATIONS: Sequence[Migration] = [
|
||||
Migration(
|
||||
"""
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'vector') THEN
|
||||
CREATE EXTENSION vector;
|
||||
END IF;
|
||||
END $$;
|
||||
""",
|
||||
),
|
||||
Migration(
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "langgraph-checkpoint-postgres"
|
||||
version = "2.0.25"
|
||||
version = "3.0.1"
|
||||
description = "Library with a Postgres implementation of LangGraph checkpoint saver."
|
||||
authors = []
|
||||
requires-python = ">=3.10"
|
||||
@@ -12,28 +12,37 @@ readme = "README.md"
|
||||
license = "MIT"
|
||||
license-files = ['LICENSE']
|
||||
dependencies = [
|
||||
"langgraph-checkpoint>=2.1.2,<3.0.0",
|
||||
"langgraph-checkpoint>=2.1.2,<4.0.0",
|
||||
"orjson>=3.10.1",
|
||||
"psycopg>=3.2.0",
|
||||
"psycopg-pool>=3.2.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint-postgres"
|
||||
Twitter = "https://x.com/LangChainAI"
|
||||
Slack = "https://www.langchain.com/join-community"
|
||||
Reddit = "https://www.reddit.com/r/LangChain/"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
test = [
|
||||
"pytest",
|
||||
"anyio",
|
||||
"pytest-asyncio",
|
||||
"pytest-mock",
|
||||
"mypy",
|
||||
"psycopg[binary]",
|
||||
"langgraph-checkpoint",
|
||||
"pytest-watcher",
|
||||
]
|
||||
lint = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
"mypy",
|
||||
]
|
||||
dev = [
|
||||
{include-group = "test"},
|
||||
{include-group = "lint"},
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
default-groups = ['dev']
|
||||
|
||||
Generated
+208
-122
@@ -1,5 +1,5 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
revision = 3
|
||||
requires-python = ">=3.10"
|
||||
|
||||
[[package]]
|
||||
@@ -234,7 +234,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint"
|
||||
version = "2.1.2"
|
||||
version = "3.0.1"
|
||||
source = { editable = "../checkpoint" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
@@ -244,7 +244,7 @@ dependencies = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "langchain-core", specifier = ">=0.2.38" },
|
||||
{ name = "ormsgpack", specifier = ">=1.10.0" },
|
||||
{ name = "ormsgpack", specifier = ">=1.12.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
@@ -262,10 +262,26 @@ dev = [
|
||||
{ name = "redis" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "dataclasses-json" },
|
||||
{ name = "numpy" },
|
||||
{ name = "pandas" },
|
||||
{ name = "pandas-stubs", specifier = ">=2.2.2.240807" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "redis" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint-postgres"
|
||||
version = "2.0.25"
|
||||
version = "3.0.1"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "langgraph-checkpoint" },
|
||||
@@ -287,6 +303,20 @@ dev = [
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "anyio" },
|
||||
{ name = "langgraph-checkpoint" },
|
||||
{ name = "psycopg", extra = ["binary"] },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
@@ -309,6 +339,20 @@ dev = [
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "anyio" },
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
{ name = "psycopg", extras = ["binary"] },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
@@ -461,42 +505,57 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ormsgpack"
|
||||
version = "1.10.0"
|
||||
version = "1.12.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/92/36/44eed5ef8ce93cded76a576780bab16425ce7876f10d3e2e6265e46c21ea/ormsgpack-1.10.0.tar.gz", hash = "sha256:7f7a27efd67ef22d7182ec3b7fa7e9d147c3ad9be2a24656b23c989077e08b16", size = 58629, upload-time = "2025-05-24T19:07:53.944Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/67/d5ef41c3b4a94400be801984ef7c7fc9623e1a82b643e74eeec367e7462b/ormsgpack-1.12.0.tar.gz", hash = "sha256:94be818fdbb0285945839b88763b269987787cb2f7ef280cad5d6ec815b7e608", size = 49959, upload-time = "2025-11-04T18:30:10.083Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/74/c2dd5daf069e3798d09d5746000f9b210de04df83834e5cb47f0ace51892/ormsgpack-1.10.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8a52c7ce7659459f3dc8dec9fd6a6c76f855a0a7e2b61f26090982ac10b95216", size = 376280, upload-time = "2025-05-24T19:06:51.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/7b/30ff4bffb709e8a242005a8c4d65714fd96308ad640d31cff1b85c0d8cc4/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:060f67fe927582f4f63a1260726d019204b72f460cf20930e6c925a1d129f373", size = 204335, upload-time = "2025-05-24T19:06:53.442Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/3f/c95b7d142819f801a0acdbd04280e8132e43b6e5a8920173e8eb92ea0e6a/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7058ef6092f995561bf9f71d6c9a4da867b6cc69d2e94cb80184f579a3ceed5", size = 215373, upload-time = "2025-05-24T19:06:55.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/1a/e30f4bcf386db2015d1686d1da6110c95110294d8ea04f86091dd5eb3361/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6f3509c1b0e51b15552d314b1d409321718122e90653122ce4b997f01453a", size = 216469, upload-time = "2025-05-24T19:06:56.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/fc/7e44aeade22b91883586f45b7278c118fd210834c069774891447f444fc9/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c1edafd5c72b863b1f875ec31c529f09c872a5ff6fe473b9dfaf188ccc3227", size = 384590, upload-time = "2025-05-24T19:06:58.286Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/78/f92c24e8446697caa83c122f10b6cf5e155eddf81ce63905c8223a260482/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c780b44107a547a9e9327270f802fa4d6b0f6667c9c03c3338c0ce812259a0f7", size = 478891, upload-time = "2025-05-24T19:07:00.126Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/75/87449690253c64bea2b663c7c8f2dbc9ad39d73d0b38db74bdb0f3947b16/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:137aab0d5cdb6df702da950a80405eb2b7038509585e32b4e16289604ac7cb84", size = 390121, upload-time = "2025-05-24T19:07:01.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/cc/c83257faf3a5169ec29dd87121317a25711da9412ee8c1e82f2e1a00c0be/ormsgpack-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:3e666cb63030538fa5cd74b1e40cb55b6fdb6e2981f024997a288bf138ebad07", size = 121196, upload-time = "2025-05-24T19:07:03.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/27/7da748bc0d7d567950a378dee5a32477ed5d15462ab186918b5f25cac1ad/ormsgpack-1.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4bb7df307e17b36cbf7959cd642c47a7f2046ae19408c564e437f0ec323a7775", size = 376275, upload-time = "2025-05-24T19:07:05.128Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/65/c082cc8c74a914dbd05af0341c761c73c3d9960b7432bbf9b8e1e20811af/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8817ae439c671779e1127ee62f0ac67afdeaeeacb5f0db45703168aa74a2e4af", size = 204335, upload-time = "2025-05-24T19:07:06.423Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/62/17ef7e5d9766c79355b9c594cc9328c204f1677bc35da0595cc4e46449f0/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f345f81e852035d80232e64374d3a104139d60f8f43c6c5eade35c4bac5590e", size = 215372, upload-time = "2025-05-24T19:07:08.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/92/7c91e8115fc37e88d1a35e13200fda3054ff5d2e5adf017345e58cea4834/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21de648a1c7ef692bdd287fb08f047bd5371d7462504c0a7ae1553c39fee35e3", size = 216470, upload-time = "2025-05-24T19:07:09.903Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/86/ce053c52e2517b90e390792d83e926a7a523c1bce5cc63d0a7cd05ce6cf6/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3a7d844ae9cbf2112c16086dd931b2acefce14cefd163c57db161170c2bfa22b", size = 384591, upload-time = "2025-05-24T19:07:11.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/e8/2ad59f2ab222c6029e500bc966bfd2fe5cb099f8ab6b7ebeb50ddb1a6fe5/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4d80585403d86d7f800cf3d0aafac1189b403941e84e90dd5102bb2b92bf9d5", size = 478892, upload-time = "2025-05-24T19:07:13.147Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/73/f55e4b47b7b18fd8e7789680051bf830f1e39c03f1d9ed993cd0c3e97215/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da1de515a87e339e78a3ccf60e39f5fb740edac3e9e82d3c3d209e217a13ac08", size = 390122, upload-time = "2025-05-24T19:07:14.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/87/073251cdb93d4c6241748568b3ad1b2a76281fb2002eed16a3a4043d61cf/ormsgpack-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:57c4601812684024132cbb32c17a7d4bb46ffc7daf2fddf5b697391c2c4f142a", size = 121197, upload-time = "2025-05-24T19:07:15.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/95/f3ab1a7638f6aa9362e87916bb96087fbbc5909db57e19f12ad127560e1e/ormsgpack-1.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4e159d50cd4064d7540e2bc6a0ab66eab70b0cc40c618b485324ee17037527c0", size = 376806, upload-time = "2025-05-24T19:07:17.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/2b/42f559f13c0b0f647b09d749682851d47c1a7e48308c43612ae6833499c8/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb47c85f3a866e29279d801115b554af0fefc409e2ed8aa90aabfa77efe5cc6", size = 204433, upload-time = "2025-05-24T19:07:18.569Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/42/1ca0cb4d8c80340a89a4af9e6d8951fb8ba0d076a899d2084eadf536f677/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c28249574934534c9bd5dce5485c52f21bcea0ee44d13ece3def6e3d2c3798b5", size = 215547, upload-time = "2025-05-24T19:07:20.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/38/184a570d7c44c0260bc576d1daaac35b2bfd465a50a08189518505748b9a/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1957dcadbb16e6a981cd3f9caef9faf4c2df1125e2a1b702ee8236a55837ce07", size = 216746, upload-time = "2025-05-24T19:07:21.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/2f/1aaffd08f6b7fdc2a57336a80bdfb8df24e6a65ada5aa769afecfcbc6cc6/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b29412558c740bf6bac156727aa85ac67f9952cd6f071318f29ee72e1a76044", size = 384783, upload-time = "2025-05-24T19:07:23.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/63/3e53d6f43bb35e00c98f2b8ab2006d5138089ad254bc405614fbf0213502/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6933f350c2041ec189fe739f0ba7d6117c8772f5bc81f45b97697a84d03020dd", size = 479076, upload-time = "2025-05-24T19:07:25.047Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/19/fa1121b03b61402bb4d04e35d164e2320ef73dfb001b57748110319dd014/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a86de06d368fcc2e58b79dece527dc8ca831e0e8b9cec5d6e633d2777ec93d0", size = 390447, upload-time = "2025-05-24T19:07:26.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/0d/73143ecb94ac4a5dcba223402139240a75dee0cc6ba8a543788a5646407a/ormsgpack-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:35fa9f81e5b9a0dab42e09a73f7339ecffdb978d6dbf9deb2ecf1e9fc7808722", size = 121401, upload-time = "2025-05-24T19:07:28.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/f8/ec5f4e03268d0097545efaab2893aa63f171cf2959cb0ea678a5690e16a1/ormsgpack-1.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d816d45175a878993b7372bd5408e0f3ec5a40f48e2d5b9d8f1cc5d31b61f1f", size = 376806, upload-time = "2025-05-24T19:07:29.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/19/b3c53284aad1e90d4d7ed8c881a373d218e16675b8b38e3569d5b40cc9b8/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90345ccb058de0f35262893751c603b6376b05f02be2b6f6b7e05d9dd6d5643", size = 204433, upload-time = "2025-05-24T19:07:30.977Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/0b/845c258f59df974a20a536c06cace593698491defdd3d026a8a5f9b6e745/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144b5e88f1999433e54db9d637bae6fe21e935888be4e3ac3daecd8260bd454e", size = 215549, upload-time = "2025-05-24T19:07:32.345Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/56/57fce8fb34ca6c9543c026ebebf08344c64dbb7b6643d6ddd5355d37e724/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2190b352509d012915921cca76267db136cd026ddee42f1b0d9624613cc7058c", size = 216747, upload-time = "2025-05-24T19:07:34.075Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/3f/655b5f6a2475c8d209f5348cfbaaf73ce26237b92d79ef2ad439407dd0fa/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:86fd9c1737eaba43d3bb2730add9c9e8b5fbed85282433705dd1b1e88ea7e6fb", size = 384785, upload-time = "2025-05-24T19:07:35.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/94/687a0ad8afd17e4bce1892145d6a1111e58987ddb176810d02a1f3f18686/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:33afe143a7b61ad21bb60109a86bb4e87fec70ef35db76b89c65b17e32da7935", size = 479076, upload-time = "2025-05-24T19:07:37.533Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/34/68925232e81e0e062a2f0ac678f62aa3b6f7009d6a759e19324dbbaebae7/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f23d45080846a7b90feabec0d330a9cc1863dc956728412e4f7986c80ab3a668", size = 390446, upload-time = "2025-05-24T19:07:39.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/ad/f4e1a36a6d1714afb7ffb74b3ababdcb96529cf4e7a216f9f7c8eda837b6/ormsgpack-1.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:534d18acb805c75e5fba09598bf40abe1851c853247e61dda0c01f772234da69", size = 121399, upload-time = "2025-05-24T19:07:40.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/0c/8f45fcd22c95190b05d4fba71375d8f783a9e3b0b6aaf476812b693e3868/ormsgpack-1.12.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e08904c232358b94a682ccfbb680bc47d3fd5c424bb7dccb65974dd20c95e8e1", size = 369156, upload-time = "2025-11-04T18:29:17.629Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/f8/c7adc093d4ceb05e38786906815f868210f808326c27f8124b4d9466a26b/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9ed7a4b0037d69c8ba7e670e03ee65ae8d5c5114a409e73c5770d7fb5e4b895", size = 195743, upload-time = "2025-11-04T18:29:18.964Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/b8/bf002648fa6c150ed6157837b00303edafb35f65c352429463f83214de18/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:db2928525b684f3f2af0367aef7ae8d20cde37fc5349c700017129d493a755aa", size = 206472, upload-time = "2025-11-04T18:29:19.951Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/d6/1f445947c95a931bb189b7864a3f9dcbeebe7dcbc1b3c7387427b3779228/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45f911d9c5b23d11e49ff03fc8f9566745a2b1a7d9033733a1c0a2fa9301cd60", size = 207959, upload-time = "2025-11-04T18:29:21.282Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/9c/dd8ccd7553a5c1d0b4b69a0541611983a2f9bc2e8c5708a4bfffc0100468/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:98c54ae6fd682b2aceb264505af9b2255f3df9d84e6e4369bc44d2110f1f311d", size = 377659, upload-time = "2025-11-04T18:29:22.561Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/08/3282d8f6330e742d4cdbcfbe2c100b403ae5526ae82a1c1b6a11b7967e37/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:857ab987c3502de08258cc4baf0e87267cb2c80931601084e13df3c355b1ab9d", size = 471391, upload-time = "2025-11-04T18:29:23.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/d4/94a2fbfd4837754bda7a099b6a23b9d40aba9e76e1af8b8fb8133612eb54/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:27579d45dc502ee736238e1024559cb0a01aa72a3b68827448b8edf6a2dcdc9c", size = 381501, upload-time = "2025-11-04T18:29:24.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/c6/1a9fa122cb5deb10b067bbaa43165b12291a914cc0ce364988ff17bbf405/ormsgpack-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:c78379d054760875540cf2e81f28da1bb78d09fda3eabdbeb6c53b3e297158cb", size = 112715, upload-time = "2025-11-04T18:29:26.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/ba/3cae83cf36420c1c8dd294f16c852c03313aafe2439a165c4c6ac611b1d0/ormsgpack-1.12.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c40d86d77391b18dd34de5295e3de2b8ad818bcab9c9def4121c8ec5c9714ae4", size = 369159, upload-time = "2025-11-04T18:29:27.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/d4/5e176309e01a8b9098d80201aac1eb7db9336c3b5b4fa6254a2bbb0d0fa0/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:777b7fab364dc0f200bb382a98a385c8222ffa6a2333d627d763797326202c86", size = 195744, upload-time = "2025-11-04T18:29:28.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/83/6d80c8c5571639c000a39f38f77752dfaf9d9e552d775331e8d280f66a4e/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b5089ad9dd5b3d3013b245a55e4abaea2f8ad70f4a78e1b002127b02340004", size = 206474, upload-time = "2025-11-04T18:29:29.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/e6/940311e48dc0cfc3e212bd7007a21ed0825158638057687d804f2c5c2cca/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deaf0c87cace7bc08fbf68c5cc66605b593df6427e9f4de235b2da358787e008", size = 207959, upload-time = "2025-11-04T18:29:30.315Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/e3/fbe94b0a311815343b86a95a0627e4901b11ff6fd522679ca29a2a88c99b/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f62d476fe28bc5675d9aff30341bfa9f41d7de332c5b63fbbe9aaf6bb7ec74d4", size = 377666, upload-time = "2025-11-04T18:29:31.38Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/3b/229cfa28076798ffb619aaa854b842de3f2ed5ea4e6509bf34d14c038c4d/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ded7810095b887e28434f32f5a345d354e88cf851bab3c5435aeb86a718618d2", size = 471394, upload-time = "2025-11-04T18:29:32.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/bd/4eae4ab35586e4175c07acb5f98aec83aa9d8987f71ea0443aa900191bdf/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f72a1dea0c4ae7c4101dcfbe8133f274a9d769d0b87fe5188db4fab07ffabaee", size = 381506, upload-time = "2025-11-04T18:29:33.533Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/51/f9d56d6d015cbfa1ce9a4358ca30a41744644f0cf606e060d7203efe5af8/ormsgpack-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:8f479bfef847255d7d0b12c7a198f6a21490155da2da3062e082ba370893d4a1", size = 112707, upload-time = "2025-11-04T18:29:34.898Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/07/bb189ef7072979f2f96e8716e952172efdce9c54930aa0814bec73aee19b/ormsgpack-1.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:3583ca410e4502144b2594170542e4bbef7b15643fd1208703ae820f11029036", size = 106533, upload-time = "2025-11-04T18:29:36.112Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/f2/c1036b2775fcc0cfa5fd618c53bcd3b862ee07298fb627f03af4c7982f84/ormsgpack-1.12.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e0c1e08b64d99076fee155276097489b82cc56e8d5951c03c721a65a32f44494", size = 369538, upload-time = "2025-11-04T18:29:37.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/ca/526c4ae02f3cb34621af91bf8282a10d666757c2e0c6ff391ff5d403d607/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fd43bcb299131690b8e0677af172020b2ada8e625169034b42ac0c13adf84aa", size = 195872, upload-time = "2025-11-04T18:29:38.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/0f/83bb7968e9715f6a85be53d041b1e6324a05428f56b8b980dac866886871/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0149d595341e22ead340bf281b2995c4cc7dc8d522a6b5f575fe17aa407604", size = 206469, upload-time = "2025-11-04T18:29:39.749Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/e3/9e93ca1065f2d4af035804a842b1ff3025bab580c7918239bb225cd1fee2/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f19a1b27d169deb553c80fd10b589fc2be1fc14cee779fae79fcaf40db04de2b", size = 208273, upload-time = "2025-11-04T18:29:40.769Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d8/6d6ef901b3a8b8f3ab8836b135a56eb7f66c559003e251d9530bedb12627/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f28896942d655064940dfe06118b7ce1e3468d051483148bf02c99ec157483a", size = 377839, upload-time = "2025-11-04T18:29:42.092Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/72/fcb704bfa4c2c3a37b647d597cc45a13cffc9d50baac635a9ad620731d29/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9396efcfa48b4abbc06e44c5dbc3c4574a8381a80cb4cd01eea15d28b38c554e", size = 471446, upload-time = "2025-11-04T18:29:43.133Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/f8/402e4e3eb997c2ee534c99bec4b5bb359c2a1f9edadf043e254a71e11378/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:96586ed537a5fb386a162c4f9f7d8e6f76e07b38a990d50c73f11131e00ff040", size = 381783, upload-time = "2025-11-04T18:29:44.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/8d/5897b700360bc00911b70ae5ef1134ee7abf5baa81a92a4be005917d3dfd/ormsgpack-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e70387112fb3870e4844de090014212cdcf1342f5022047aecca01ec7de05d7a", size = 112943, upload-time = "2025-11-04T18:29:45.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/44/1e73649f79bb96d6cf9e5bcbac68b6216d238bba80af351c4c0cbcf7ee15/ormsgpack-1.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:d71290a23de5d4829610c42665d816c661ecad8979883f3f06b2e3ab9639962e", size = 106688, upload-time = "2025-11-04T18:29:46.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/e8/35f11ce9313111488b26b3035e4cbe55caa27909c0b6c8b5b5cd59f9661e/ormsgpack-1.12.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:766f2f3b512d85cd375b26a8b1329b99843560b50b93d3880718e634ad4a5de5", size = 369574, upload-time = "2025-11-04T18:29:47.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/b0/77461587f412d4e598d3687bafe23455ed0f26269f44be20252eddaa624e/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84b285b1f3f185aad7da45641b873b30acfd13084cf829cf668c4c6480a81583", size = 195893, upload-time = "2025-11-04T18:29:48.735Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/67/e197ceb04c3b550589e5407fc9fdae10f4e2e2eba5fdac921a269e02e974/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e23604fc79fe110292cb365f4c8232e64e63a34f470538be320feae3921f271b", size = 206503, upload-time = "2025-11-04T18:29:49.99Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/b1/7fa8ba82a25cef678983c7976f85edeef5014f5c26495f338258e6a3cf1c/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc32b156c113a0fae2975051417d8d9a7a5247c34b2d7239410c46b75ce9348a", size = 208257, upload-time = "2025-11-04T18:29:51.007Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/b1/759e999390000d2589e6d0797f7265e6ec28378547075d28d3736248ab63/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:94ac500dd10c20fa8b8a23bc55606250bfe711bf9716828d9f3d44dfd1f25668", size = 377852, upload-time = "2025-11-04T18:29:52.103Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/e7/0af737c94272494d9d84a3c29cc42c973ef7fd2342917020906596db863c/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:c5201ff7ec24f721f813a182885a17064cffdbe46b2412685a52e6374a872c8f", size = 471456, upload-time = "2025-11-04T18:29:53.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/ba/c81f0aa4f19fbf457213395945b672e6fde3ce777e3587456e7f0fca2147/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a9740bb3839c9368aacae1cbcfc474ee6976458f41cc135372b7255d5206c953", size = 381813, upload-time = "2025-11-04T18:29:54.394Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/15/429c72d64323503fd42cc4ca8398930ded8aa8b3470df8a86b3bbae7a35c/ormsgpack-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ed37f29772432048b58174e920a1d4c4cde0404a5d448d3d8bbcc95d86a6918", size = 112949, upload-time = "2025-11-04T18:29:55.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/b9/e72c451a40f8c57bfc229e0b8e536ecea7203c8f0a839676df2ffb605c62/ormsgpack-1.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:b03994bbec5d6d42e03d6604e327863f885bde67aa61e06107ce1fa5bdd3e71d", size = 106689, upload-time = "2025-11-04T18:29:56.262Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/16/13eab1a75da531b359105fdee90dda0b6bd1ca0a09880250cf91d8bdfdea/ormsgpack-1.12.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0f3981ba3cba80656012090337e548e597799e14b41e3d0b595ab5ab05a23d7f", size = 369620, upload-time = "2025-11-04T18:29:57.255Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/c1/cbcc38b7af4ce58d8893e56d3595c0c8dcd117093bf048f889cf351bdba0/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:901f6f55184d6776dbd5183cbce14caf05bf7f467eef52faf9b094686980bf71", size = 195925, upload-time = "2025-11-04T18:29:58.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/59/4fa4dc0681490e12b75333440a1c0fd9741b0ebff272b1db4a29d35c2021/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e13b15412571422b711b40f45e3fe6d993ea3314b5e97d1a853fe99226c5effc", size = 206594, upload-time = "2025-11-04T18:29:59.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/67/249770896bc32bb91b22c30256961f935d0915cbcf6e289a7fc961d9b14c/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91fa8a452553a62e5fb3fbab471e7faf7b3bec3c87a2f355ebf3d7aab290fe4f", size = 208307, upload-time = "2025-11-04T18:30:00.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/0a/e041a248cd72f2f4c07e155913e0a3ede4c86cf21a40ae6cd79f135f2847/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74ec101f69624695eec4ce7c953192d97748254abe78fb01b591f06d529e1952", size = 377844, upload-time = "2025-11-04T18:30:01.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/71/6f7773e4ffda73a358ce4bba69b3e8bee9d40a7a06315e4c1cd7a3ea9d02/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9bbf7896580848326c1f9bd7531f264e561f98db7e08e15aa75963d83832c717", size = 471572, upload-time = "2025-11-04T18:30:02.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/29/af6769a4289c07acc71e7bda1d64fb31800563147d73142686e185e82348/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7567917da613b8f8d591c1674e411fd3404bea41ef2b9a0e0a1e049c0f9406d7", size = 381842, upload-time = "2025-11-04T18:30:03.799Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/dd/0a86195ee7a1a96c088aefc8504385e881cf56f4563ed81bafe21cbf1fb0/ormsgpack-1.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e418256c5d8622b8bc92861936f7c6a0131355e7bcad88a42102ae8227f8a1c", size = 113008, upload-time = "2025-11-04T18:30:04.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/57/fafc79e32f3087f6f26f509d80b8167516326bfea38d30502627c01617e0/ormsgpack-1.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:433ace29aa02713554f714c62a4e4dcad0c9e32674ba4f66742c91a4c3b1b969", size = 106648, upload-time = "2025-11-04T18:30:05.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/cf/5d58d9b132128d2fe5d586355dde76af386554abef00d608f66b913bff1f/ormsgpack-1.12.0-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e57164be4ca34b64e210ec515059193280ac84df4d6f31a6fcbfb2fc8436de55", size = 369803, upload-time = "2025-11-04T18:30:06.728Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/42/968a2da361eaff2e4cbb17c82c7599787babf16684110ad70409646cc1e4/ormsgpack-1.12.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:904f96289deaa92fc6440b122edc27c5bdc28234edd63717f6d853d88c823a83", size = 195991, upload-time = "2025-11-04T18:30:07.713Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/f0/9696c6c6cf8ad35170f0be8d0ef3523cc258083535f6c8071cb8235ebb8b/ormsgpack-1.12.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b291d086e524a1062d57d1b7b5a8bcaaf29caebf0212fec12fd86240bd33633", size = 208316, upload-time = "2025-11-04T18:30:08.663Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -610,7 +669,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.11.9"
|
||||
version = "2.12.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
@@ -618,96 +677,123 @@ dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ff/5d/09a551ba512d7ca404d785072700d3f6727a02f6f3c24ecfd081c7cf0aa8/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2", size = 788495, upload-time = "2025-09-13T11:26:39.325Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8d/35/d319ed522433215526689bad428a94058b6dd12190ce7ddd78618ac14b28/pydantic-2.12.2.tar.gz", hash = "sha256:7b8fa15b831a4bbde9d5b84028641ac3080a4ca2cbd4a621a661687e741624fd", size = 816358, upload-time = "2025-10-14T15:02:21.842Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/d3/108f2006987c58e76691d5ae5d200dd3e0f532cb4e5fa3560751c3a1feba/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2", size = 444855, upload-time = "2025-09-13T11:26:36.909Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/98/468cb649f208a6f1279448e6e5247b37ae79cf5e4041186f1e2ef3d16345/pydantic-2.12.2-py3-none-any.whl", hash = "sha256:25ff718ee909acd82f1ff9b1a4acfd781bb23ab3739adaa7144f19a6a4e231ae", size = 460628, upload-time = "2025-10-14T15:02:19.623Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.33.2"
|
||||
version = "2.41.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/18/d0944e8eaaa3efd0a91b0f1fc537d3be55ad35091b6a87638211ba691964/pydantic_core-2.41.4.tar.gz", hash = "sha256:70e47929a9d4a1905a67e4b687d5946026390568a8e952b92824118063cee4d5", size = 457557, upload-time = "2025-10-14T10:23:47.909Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/3d/9b8ca77b0f76fcdbf8bc6b72474e264283f461284ca84ac3fde570c6c49a/pydantic_core-2.41.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2442d9a4d38f3411f22eb9dd0912b7cbf4b7d5b6c92c4173b75d3e1ccd84e36e", size = 2111197, upload-time = "2025-10-14T10:19:43.303Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/92/b7b0fe6ed4781642232755cb7e56a86e2041e1292f16d9ae410a0ccee5ac/pydantic_core-2.41.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30a9876226dda131a741afeab2702e2d127209bde3c65a2b8133f428bc5d006b", size = 1917909, upload-time = "2025-10-14T10:19:45.194Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/8c/3eb872009274ffa4fb6a9585114e161aa1a0915af2896e2d441642929fe4/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d55bbac04711e2980645af68b97d445cdbcce70e5216de444a6c4b6943ebcccd", size = 1969905, upload-time = "2025-10-14T10:19:46.567Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/21/35adf4a753bcfaea22d925214a0c5b880792e3244731b3f3e6fec0d124f7/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1d778fb7849a42d0ee5927ab0f7453bf9f85eef8887a546ec87db5ddb178945", size = 2051938, upload-time = "2025-10-14T10:19:48.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/d0/cdf7d126825e36d6e3f1eccf257da8954452934ede275a8f390eac775e89/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b65077a4693a98b90ec5ad8f203ad65802a1b9b6d4a7e48066925a7e1606706", size = 2250710, upload-time = "2025-10-14T10:19:49.619Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/1c/af1e6fd5ea596327308f9c8d1654e1285cc3d8de0d584a3c9d7705bf8a7c/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62637c769dee16eddb7686bf421be48dfc2fae93832c25e25bc7242e698361ba", size = 2367445, upload-time = "2025-10-14T10:19:51.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/81/8cece29a6ef1b3a92f956ea6da6250d5b2d2e7e4d513dd3b4f0c7a83dfea/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfe3aa529c8f501babf6e502936b9e8d4698502b2cfab41e17a028d91b1ac7b", size = 2072875, upload-time = "2025-10-14T10:19:52.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/37/a6a579f5fc2cd4d5521284a0ab6a426cc6463a7b3897aeb95b12f1ba607b/pydantic_core-2.41.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca2322da745bf2eeb581fc9ea3bbb31147702163ccbcbf12a3bb630e4bf05e1d", size = 2191329, upload-time = "2025-10-14T10:19:54.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/03/505020dc5c54ec75ecba9f41119fd1e48f9e41e4629942494c4a8734ded1/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e8cd3577c796be7231dcf80badcf2e0835a46665eaafd8ace124d886bab4d700", size = 2151658, upload-time = "2025-10-14T10:19:55.843Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/5d/2c0d09fb53aa03bbd2a214d89ebfa6304be7df9ed86ee3dc7770257f41ee/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1cae8851e174c83633f0833e90636832857297900133705ee158cf79d40f03e6", size = 2316777, upload-time = "2025-10-14T10:19:57.607Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/4b/c2c9c8f5e1f9c864b57d08539d9d3db160e00491c9f5ee90e1bfd905e644/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a26d950449aae348afe1ac8be5525a00ae4235309b729ad4d3399623125b43c9", size = 2320705, upload-time = "2025-10-14T10:19:59.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/c3/a74c1c37f49c0a02c89c7340fafc0ba816b29bd495d1a31ce1bdeacc6085/pydantic_core-2.41.4-cp310-cp310-win32.whl", hash = "sha256:0cf2a1f599efe57fa0051312774280ee0f650e11152325e41dfd3018ef2c1b57", size = 1975464, upload-time = "2025-10-14T10:20:00.581Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/23/5dd5c1324ba80303368f7569e2e2e1a721c7d9eb16acb7eb7b7f85cb1be2/pydantic_core-2.41.4-cp310-cp310-win_amd64.whl", hash = "sha256:a8c2e340d7e454dc3340d3d2e8f23558ebe78c98aa8f68851b04dcb7bc37abdc", size = 2024497, upload-time = "2025-10-14T10:20:03.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/4c/f6cbfa1e8efacd00b846764e8484fe173d25b8dab881e277a619177f3384/pydantic_core-2.41.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:28ff11666443a1a8cf2a044d6a545ebffa8382b5f7973f22c36109205e65dc80", size = 2109062, upload-time = "2025-10-14T10:20:04.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/f8/40b72d3868896bfcd410e1bd7e516e762d326201c48e5b4a06446f6cf9e8/pydantic_core-2.41.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:61760c3925d4633290292bad462e0f737b840508b4f722247d8729684f6539ae", size = 1916301, upload-time = "2025-10-14T10:20:06.857Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/4d/d203dce8bee7faeca791671c88519969d98d3b4e8f225da5b96dad226fc8/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eae547b7315d055b0de2ec3965643b0ab82ad0106a7ffd29615ee9f266a02827", size = 1968728, upload-time = "2025-10-14T10:20:08.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/f5/6a66187775df87c24d526985b3a5d78d861580ca466fbd9d4d0e792fcf6c/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef9ee5471edd58d1fcce1c80ffc8783a650e3e3a193fe90d52e43bb4d87bff1f", size = 2050238, upload-time = "2025-10-14T10:20:09.766Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/b9/78336345de97298cf53236b2f271912ce11f32c1e59de25a374ce12f9cce/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15dd504af121caaf2c95cb90c0ebf71603c53de98305621b94da0f967e572def", size = 2249424, upload-time = "2025-10-14T10:20:11.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/bb/a4584888b70ee594c3d374a71af5075a68654d6c780369df269118af7402/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a926768ea49a8af4d36abd6a8968b8790f7f76dd7cbd5a4c180db2b4ac9a3a2", size = 2366047, upload-time = "2025-10-14T10:20:13.647Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/8d/17fc5de9d6418e4d2ae8c675f905cdafdc59d3bf3bf9c946b7ab796a992a/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916b9b7d134bff5440098a4deb80e4cb623e68974a87883299de9124126c2a8", size = 2071163, upload-time = "2025-10-14T10:20:15.307Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/e7/03d2c5c0b8ed37a4617430db68ec5e7dbba66358b629cd69e11b4d564367/pydantic_core-2.41.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cf90535979089df02e6f17ffd076f07237efa55b7343d98760bde8743c4b265", size = 2190585, upload-time = "2025-10-14T10:20:17.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/fc/15d1c9fe5ad9266a5897d9b932b7f53d7e5cfc800573917a2c5d6eea56ec/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7533c76fa647fade2d7ec75ac5cc079ab3f34879626dae5689b27790a6cf5a5c", size = 2150109, upload-time = "2025-10-14T10:20:19.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/ef/e735dd008808226c83ba56972566138665b71477ad580fa5a21f0851df48/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:37e516bca9264cbf29612539801ca3cd5d1be465f940417b002905e6ed79d38a", size = 2315078, upload-time = "2025-10-14T10:20:20.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/00/806efdcf35ff2ac0f938362350cd9827b8afb116cc814b6b75cf23738c7c/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c19cb355224037c83642429b8ce261ae108e1c5fbf5c028bac63c77b0f8646e", size = 2318737, upload-time = "2025-10-14T10:20:22.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/7e/6ac90673fe6cb36621a2283552897838c020db343fa86e513d3f563b196f/pydantic_core-2.41.4-cp311-cp311-win32.whl", hash = "sha256:09c2a60e55b357284b5f31f5ab275ba9f7f70b7525e18a132ec1f9160b4f1f03", size = 1974160, upload-time = "2025-10-14T10:20:23.817Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/9d/7c5e24ee585c1f8b6356e1d11d40ab807ffde44d2db3b7dfd6d20b09720e/pydantic_core-2.41.4-cp311-cp311-win_amd64.whl", hash = "sha256:711156b6afb5cb1cb7c14a2cc2c4a8b4c717b69046f13c6b332d8a0a8f41ca3e", size = 2021883, upload-time = "2025-10-14T10:20:25.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/90/5c172357460fc28b2871eb4a0fb3843b136b429c6fa827e4b588877bf115/pydantic_core-2.41.4-cp311-cp311-win_arm64.whl", hash = "sha256:6cb9cf7e761f4f8a8589a45e49ed3c0d92d1d696a45a6feaee8c904b26efc2db", size = 1968026, upload-time = "2025-10-14T10:20:27.039Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/81/d3b3e95929c4369d30b2a66a91db63c8ed0a98381ae55a45da2cd1cc1288/pydantic_core-2.41.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ab06d77e053d660a6faaf04894446df7b0a7e7aba70c2797465a0a1af00fc887", size = 2099043, upload-time = "2025-10-14T10:20:28.561Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/da/46fdac49e6717e3a94fc9201403e08d9d61aa7a770fab6190b8740749047/pydantic_core-2.41.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c53ff33e603a9c1179a9364b0a24694f183717b2e0da2b5ad43c316c956901b2", size = 1910699, upload-time = "2025-10-14T10:20:30.217Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/63/4d948f1b9dd8e991a5a98b77dd66c74641f5f2e5225fee37994b2e07d391/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:304c54176af2c143bd181d82e77c15c41cbacea8872a2225dd37e6544dce9999", size = 1952121, upload-time = "2025-10-14T10:20:32.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/a7/e5fc60a6f781fc634ecaa9ecc3c20171d238794cef69ae0af79ac11b89d7/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025ba34a4cf4fb32f917d5d188ab5e702223d3ba603be4d8aca2f82bede432a4", size = 2041590, upload-time = "2025-10-14T10:20:34.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/69/dce747b1d21d59e85af433428978a1893c6f8a7068fa2bb4a927fba7a5ff/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9f5f30c402ed58f90c70e12eff65547d3ab74685ffe8283c719e6bead8ef53f", size = 2219869, upload-time = "2025-10-14T10:20:35.965Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/6a/c070e30e295403bf29c4df1cb781317b6a9bac7cd07b8d3acc94d501a63c/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd96e5d15385d301733113bcaa324c8bcf111275b7675a9c6e88bfb19fc05e3b", size = 2345169, upload-time = "2025-10-14T10:20:37.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/83/06d001f8043c336baea7fd202a9ac7ad71f87e1c55d8112c50b745c40324/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f348cbb44fae6e9653c1055db7e29de67ea6a9ca03a5fa2c2e11a47cff0e47", size = 2070165, upload-time = "2025-10-14T10:20:39.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/0a/e567c2883588dd12bcbc110232d892cf385356f7c8a9910311ac997ab715/pydantic_core-2.41.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec22626a2d14620a83ca583c6f5a4080fa3155282718b6055c2ea48d3ef35970", size = 2189067, upload-time = "2025-10-14T10:20:41.015Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/1d/3d9fca34273ba03c9b1c5289f7618bc4bd09c3ad2289b5420481aa051a99/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a95d4590b1f1a43bf33ca6d647b990a88f4a3824a8c4572c708f0b45a5290ed", size = 2132997, upload-time = "2025-10-14T10:20:43.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/70/d702ef7a6cd41a8afc61f3554922b3ed8d19dd54c3bd4bdbfe332e610827/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:f9672ab4d398e1b602feadcffcdd3af44d5f5e6ddc15bc7d15d376d47e8e19f8", size = 2307187, upload-time = "2025-10-14T10:20:44.849Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/4c/c06be6e27545d08b802127914156f38d10ca287a9e8489342793de8aae3c/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:84d8854db5f55fead3b579f04bda9a36461dab0730c5d570e1526483e7bb8431", size = 2305204, upload-time = "2025-10-14T10:20:46.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/e5/35ae4919bcd9f18603419e23c5eaf32750224a89d41a8df1a3704b69f77e/pydantic_core-2.41.4-cp312-cp312-win32.whl", hash = "sha256:9be1c01adb2ecc4e464392c36d17f97e9110fbbc906bcbe1c943b5b87a74aabd", size = 1972536, upload-time = "2025-10-14T10:20:48.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/c2/49c5bb6d2a49eb2ee3647a93e3dae7080c6409a8a7558b075027644e879c/pydantic_core-2.41.4-cp312-cp312-win_amd64.whl", hash = "sha256:d682cf1d22bab22a5be08539dca3d1593488a99998f9f412137bc323179067ff", size = 2031132, upload-time = "2025-10-14T10:20:50.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/23/936343dbcba6eec93f73e95eb346810fc732f71ba27967b287b66f7b7097/pydantic_core-2.41.4-cp312-cp312-win_arm64.whl", hash = "sha256:833eebfd75a26d17470b58768c1834dfc90141b7afc6eb0429c21fc5a21dcfb8", size = 1969483, upload-time = "2025-10-14T10:20:52.35Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/d0/c20adabd181a029a970738dfe23710b52a31f1258f591874fcdec7359845/pydantic_core-2.41.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:85e050ad9e5f6fe1004eec65c914332e52f429bc0ae12d6fa2092407a462c746", size = 2105688, upload-time = "2025-10-14T10:20:54.448Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/b6/0ce5c03cec5ae94cca220dfecddc453c077d71363b98a4bbdb3c0b22c783/pydantic_core-2.41.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7393f1d64792763a48924ba31d1e44c2cfbc05e3b1c2c9abb4ceeadd912cced", size = 1910807, upload-time = "2025-10-14T10:20:56.115Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/3e/800d3d02c8beb0b5c069c870cbb83799d085debf43499c897bb4b4aaff0d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94dab0940b0d1fb28bcab847adf887c66a27a40291eedf0b473be58761c9799a", size = 1956669, upload-time = "2025-10-14T10:20:57.874Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/a4/24271cc71a17f64589be49ab8bd0751f6a0a03046c690df60989f2f95c2c/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de7c42f897e689ee6f9e93c4bec72b99ae3b32a2ade1c7e4798e690ff5246e02", size = 2051629, upload-time = "2025-10-14T10:21:00.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/de/45af3ca2f175d91b96bfb62e1f2d2f1f9f3b14a734afe0bfeff079f78181/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:664b3199193262277b8b3cd1e754fb07f2c6023289c815a1e1e8fb415cb247b1", size = 2224049, upload-time = "2025-10-14T10:21:01.801Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/8f/ae4e1ff84672bf869d0a77af24fd78387850e9497753c432875066b5d622/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95b253b88f7d308b1c0b417c4624f44553ba4762816f94e6986819b9c273fb2", size = 2342409, upload-time = "2025-10-14T10:21:03.556Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/62/273dd70b0026a085c7b74b000394e1ef95719ea579c76ea2f0cc8893736d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1351f5bbdbbabc689727cb91649a00cb9ee7203e0a6e54e9f5ba9e22e384b84", size = 2069635, upload-time = "2025-10-14T10:21:05.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/03/cf485fff699b4cdaea469bc481719d3e49f023241b4abb656f8d422189fc/pydantic_core-2.41.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1affa4798520b148d7182da0615d648e752de4ab1a9566b7471bc803d88a062d", size = 2194284, upload-time = "2025-10-14T10:21:07.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/7e/c8e713db32405dfd97211f2fc0a15d6bf8adb7640f3d18544c1f39526619/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7b74e18052fea4aa8dea2fb7dbc23d15439695da6cbe6cfc1b694af1115df09d", size = 2137566, upload-time = "2025-10-14T10:21:08.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/f7/db71fd4cdccc8b75990f79ccafbbd66757e19f6d5ee724a6252414483fb4/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:285b643d75c0e30abda9dc1077395624f314a37e3c09ca402d4015ef5979f1a2", size = 2316809, upload-time = "2025-10-14T10:21:10.805Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/63/a54973ddb945f1bca56742b48b144d85c9fc22f819ddeb9f861c249d5464/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f52679ff4218d713b3b33f88c89ccbf3a5c2c12ba665fb80ccc4192b4608dbab", size = 2311119, upload-time = "2025-10-14T10:21:12.583Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/03/5d12891e93c19218af74843a27e32b94922195ded2386f7b55382f904d2f/pydantic_core-2.41.4-cp313-cp313-win32.whl", hash = "sha256:ecde6dedd6fff127c273c76821bb754d793be1024bc33314a120f83a3c69460c", size = 1981398, upload-time = "2025-10-14T10:21:14.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/d8/fd0de71f39db91135b7a26996160de71c073d8635edfce8b3c3681be0d6d/pydantic_core-2.41.4-cp313-cp313-win_amd64.whl", hash = "sha256:d081a1f3800f05409ed868ebb2d74ac39dd0c1ff6c035b5162356d76030736d4", size = 2030735, upload-time = "2025-10-14T10:21:16.432Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/86/c99921c1cf6650023c08bfab6fe2d7057a5142628ef7ccfa9921f2dda1d5/pydantic_core-2.41.4-cp313-cp313-win_arm64.whl", hash = "sha256:f8e49c9c364a7edcbe2a310f12733aad95b022495ef2a8d653f645e5d20c1564", size = 1973209, upload-time = "2025-10-14T10:21:18.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/0d/b5706cacb70a8414396efdda3d72ae0542e050b591119e458e2490baf035/pydantic_core-2.41.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ed97fd56a561f5eb5706cebe94f1ad7c13b84d98312a05546f2ad036bafe87f4", size = 1877324, upload-time = "2025-10-14T10:21:20.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/2d/cba1fa02cfdea72dfb3a9babb067c83b9dff0bbcb198368e000a6b756ea7/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a870c307bf1ee91fc58a9a61338ff780d01bfae45922624816878dce784095d2", size = 1884515, upload-time = "2025-10-14T10:21:22.339Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/ea/3df927c4384ed9b503c9cc2d076cf983b4f2adb0c754578dfb1245c51e46/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25e97bc1f5f8f7985bdc2335ef9e73843bb561eb1fa6831fdfc295c1c2061cf", size = 2042819, upload-time = "2025-10-14T10:21:26.683Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/ee/df8e871f07074250270a3b1b82aad4cd0026b588acd5d7d3eb2fcb1471a3/pydantic_core-2.41.4-cp313-cp313t-win_amd64.whl", hash = "sha256:d405d14bea042f166512add3091c1af40437c2e7f86988f3915fabd27b1e9cd2", size = 1995866, upload-time = "2025-10-14T10:21:28.951Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/de/b20f4ab954d6d399499c33ec4fafc46d9551e11dc1858fb7f5dca0748ceb/pydantic_core-2.41.4-cp313-cp313t-win_arm64.whl", hash = "sha256:19f3684868309db5263a11bace3c45d93f6f24afa2ffe75a647583df22a2ff89", size = 1970034, upload-time = "2025-10-14T10:21:30.869Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/28/d3325da57d413b9819365546eb9a6e8b7cbd9373d9380efd5f74326143e6/pydantic_core-2.41.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e9205d97ed08a82ebb9a307e92914bb30e18cdf6f6b12ca4bedadb1588a0bfe1", size = 2102022, upload-time = "2025-10-14T10:21:32.809Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/24/b58a1bc0d834bf1acc4361e61233ee217169a42efbdc15a60296e13ce438/pydantic_core-2.41.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:82df1f432b37d832709fbcc0e24394bba04a01b6ecf1ee87578145c19cde12ac", size = 1905495, upload-time = "2025-10-14T10:21:34.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/a4/71f759cc41b7043e8ecdaab81b985a9b6cad7cec077e0b92cff8b71ecf6b/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3b4cc4539e055cfa39a3763c939f9d409eb40e85813257dcd761985a108554", size = 1956131, upload-time = "2025-10-14T10:21:36.924Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/64/1e79ac7aa51f1eec7c4cda8cbe456d5d09f05fdd68b32776d72168d54275/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1eb1754fce47c63d2ff57fdb88c351a6c0150995890088b33767a10218eaa4e", size = 2052236, upload-time = "2025-10-14T10:21:38.927Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/e3/a3ffc363bd4287b80f1d43dc1c28ba64831f8dfc237d6fec8f2661138d48/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6ab5ab30ef325b443f379ddb575a34969c333004fca5a1daa0133a6ffaad616", size = 2223573, upload-time = "2025-10-14T10:21:41.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/27/78814089b4d2e684a9088ede3790763c64693c3d1408ddc0a248bc789126/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31a41030b1d9ca497634092b46481b937ff9397a86f9f51bd41c4767b6fc04af", size = 2342467, upload-time = "2025-10-14T10:21:44.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/97/4de0e2a1159cb85ad737e03306717637842c88c7fd6d97973172fb183149/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a44ac1738591472c3d020f61c6df1e4015180d6262ebd39bf2aeb52571b60f12", size = 2063754, upload-time = "2025-10-14T10:21:46.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/50/8cb90ce4b9efcf7ae78130afeb99fd1c86125ccdf9906ef64b9d42f37c25/pydantic_core-2.41.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d72f2b5e6e82ab8f94ea7d0d42f83c487dc159c5240d8f83beae684472864e2d", size = 2196754, upload-time = "2025-10-14T10:21:48.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/3b/ccdc77af9cd5082723574a1cc1bcae7a6acacc829d7c0a06201f7886a109/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c4d1e854aaf044487d31143f541f7aafe7b482ae72a022c664b2de2e466ed0ad", size = 2137115, upload-time = "2025-10-14T10:21:50.63Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/ba/e7c7a02651a8f7c52dc2cff2b64a30c313e3b57c7d93703cecea76c09b71/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b568af94267729d76e6ee5ececda4e283d07bbb28e8148bb17adad93d025d25a", size = 2317400, upload-time = "2025-10-14T10:21:52.959Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/ba/6c533a4ee8aec6b812c643c49bb3bd88d3f01e3cebe451bb85512d37f00f/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6d55fb8b1e8929b341cc313a81a26e0d48aa3b519c1dbaadec3a6a2b4fcad025", size = 2312070, upload-time = "2025-10-14T10:21:55.419Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/ae/f10524fcc0ab8d7f96cf9a74c880243576fd3e72bd8ce4f81e43d22bcab7/pydantic_core-2.41.4-cp314-cp314-win32.whl", hash = "sha256:5b66584e549e2e32a1398df11da2e0a7eff45d5c2d9db9d5667c5e6ac764d77e", size = 1982277, upload-time = "2025-10-14T10:21:57.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/dc/e5aa27aea1ad4638f0c3fb41132f7eb583bd7420ee63204e2d4333a3bbf9/pydantic_core-2.41.4-cp314-cp314-win_amd64.whl", hash = "sha256:557a0aab88664cc552285316809cab897716a372afaf8efdbef756f8b890e894", size = 2024608, upload-time = "2025-10-14T10:21:59.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/61/51d89cc2612bd147198e120a13f150afbf0bcb4615cddb049ab10b81b79e/pydantic_core-2.41.4-cp314-cp314-win_arm64.whl", hash = "sha256:3f1ea6f48a045745d0d9f325989d8abd3f1eaf47dd00485912d1a3a63c623a8d", size = 1967614, upload-time = "2025-10-14T10:22:01.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/c2/472f2e31b95eff099961fa050c376ab7156a81da194f9edb9f710f68787b/pydantic_core-2.41.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6c1fe4c5404c448b13188dd8bd2ebc2bdd7e6727fa61ff481bcc2cca894018da", size = 1876904, upload-time = "2025-10-14T10:22:04.062Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/07/ea8eeb91173807ecdae4f4a5f4b150a520085b35454350fc219ba79e66a3/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:523e7da4d43b113bf8e7b49fa4ec0c35bf4fe66b2230bfc5c13cc498f12c6c3e", size = 1882538, upload-time = "2025-10-14T10:22:06.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/29/b53a9ca6cd366bfc928823679c6a76c7a4c69f8201c0ba7903ad18ebae2f/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5729225de81fb65b70fdb1907fcf08c75d498f4a6f15af005aabb1fdadc19dfa", size = 2041183, upload-time = "2025-10-14T10:22:08.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/3d/f8c1a371ceebcaf94d6dd2d77c6cf4b1c078e13a5837aee83f760b4f7cfd/pydantic_core-2.41.4-cp314-cp314t-win_amd64.whl", hash = "sha256:de2cfbb09e88f0f795fd90cf955858fc2c691df65b1f21f0aa00b99f3fbc661d", size = 1993542, upload-time = "2025-10-14T10:22:11.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/ac/9fc61b4f9d079482a290afe8d206b8f490e9fd32d4fc03ed4fc698214e01/pydantic_core-2.41.4-cp314-cp314t-win_arm64.whl", hash = "sha256:d34f950ae05a83e0ede899c595f312ca976023ea1db100cd5aa188f7005e3ab0", size = 1973897, upload-time = "2025-10-14T10:22:13.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/12/5ba58daa7f453454464f92b3ca7b9d7c657d8641c48e370c3ebc9a82dd78/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a1b2cfec3879afb742a7b0bcfa53e4f22ba96571c9e54d6a3afe1052d17d843b", size = 2122139, upload-time = "2025-10-14T10:22:47.288Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/fb/6860126a77725c3108baecd10fd3d75fec25191d6381b6eb2ac660228eac/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:d175600d975b7c244af6eb9c9041f10059f20b8bbffec9e33fdd5ee3f67cdc42", size = 1936674, upload-time = "2025-10-14T10:22:49.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/be/57dcaa3ed595d81f8757e2b44a38240ac5d37628bce25fb20d02c7018776/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f184d657fa4947ae5ec9c47bd7e917730fa1cbb78195037e32dcbab50aca5ee", size = 1956398, upload-time = "2025-10-14T10:22:52.19Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/1d/679a344fadb9695f1a6a294d739fbd21d71fa023286daeea8c0ed49e7c2b/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed810568aeffed3edc78910af32af911c835cc39ebbfacd1f0ab5dd53028e5c", size = 2138674, upload-time = "2025-10-14T10:22:54.499Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/48/ae937e5a831b7c0dc646b2ef788c27cd003894882415300ed21927c21efa/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:4f5d640aeebb438517150fdeec097739614421900e4a08db4a3ef38898798537", size = 2112087, upload-time = "2025-10-14T10:22:56.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/db/6db8073e3d32dae017da7e0d16a9ecb897d0a4d92e00634916e486097961/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:4a9ab037b71927babc6d9e7fc01aea9e66dc2a4a34dff06ef0724a4049629f94", size = 1920387, upload-time = "2025-10-14T10:22:59.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/c1/dd3542d072fcc336030d66834872f0328727e3b8de289c662faa04aa270e/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4dab9484ec605c3016df9ad4fd4f9a390bc5d816a3b10c6550f8424bb80b18c", size = 1951495, upload-time = "2025-10-14T10:23:02.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/c6/db8d13a1f8ab3f1eb08c88bd00fd62d44311e3456d1e85c0e59e0a0376e7/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8a5028425820731d8c6c098ab642d7b8b999758e24acae03ed38a66eca8335", size = 2139008, upload-time = "2025-10-14T10:23:04.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/d4/912e976a2dd0b49f31c98a060ca90b353f3b73ee3ea2fd0030412f6ac5ec/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e5ab4fc177dd41536b3c32b2ea11380dd3d4619a385860621478ac2d25ceb00", size = 2106739, upload-time = "2025-10-14T10:23:06.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/f0/66ec5a626c81eba326072d6ee2b127f8c139543f1bf609b4842978d37833/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3d88d0054d3fa11ce936184896bed3c1c5441d6fa483b498fac6a5d0dd6f64a9", size = 1932549, upload-time = "2025-10-14T10:23:09.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/af/625626278ca801ea0a658c2dcf290dc9f21bb383098e99e7c6a029fccfc0/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2a054a8725f05b4b6503357e0ac1c4e8234ad3b0c2ac130d6ffc66f0e170e2", size = 2135093, upload-time = "2025-10-14T10:23:11.626Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/f6/2fba049f54e0f4975fef66be654c597a1d005320fa141863699180c7697d/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0d9db5a161c99375a0c68c058e227bee1d89303300802601d76a3d01f74e258", size = 2187971, upload-time = "2025-10-14T10:23:14.437Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/80/65ab839a2dfcd3b949202f9d920c34f9de5a537c3646662bdf2f7d999680/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6273ea2c8ffdac7b7fda2653c49682db815aebf4a89243a6feccf5e36c18c347", size = 2147939, upload-time = "2025-10-14T10:23:16.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/58/627565d3d182ce6dfda18b8e1c841eede3629d59c9d7cbc1e12a03aeb328/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:4c973add636efc61de22530b2ef83a65f39b6d6f656df97f678720e20de26caa", size = 2311400, upload-time = "2025-10-14T10:23:19.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/06/8a84711162ad5a5f19a88cead37cca81b4b1f294f46260ef7334ae4f24d3/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b69d1973354758007f46cf2d44a4f3d0933f10b6dc9bf15cf1356e037f6f731a", size = 2316840, upload-time = "2025-10-14T10:23:21.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/8b/b7bb512a4682a2f7fbfae152a755d37351743900226d29bd953aaf870eaa/pydantic_core-2.41.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3619320641fd212aaf5997b6ca505e97540b7e16418f4a241f44cdf108ffb50d", size = 2149135, upload-time = "2025-10-14T10:23:24.379Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/7d/138e902ed6399b866f7cfe4435d22445e16fff888a1c00560d9dc79a780f/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:491535d45cd7ad7e4a2af4a5169b0d07bebf1adfd164b0368da8aa41e19907a5", size = 2104721, upload-time = "2025-10-14T10:23:26.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/13/0525623cf94627f7b53b4c2034c81edc8491cbfc7c28d5447fa318791479/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:54d86c0cada6aba4ec4c047d0e348cbad7063b87ae0f005d9f8c9ad04d4a92a2", size = 1931608, upload-time = "2025-10-14T10:23:29.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/f9/744bc98137d6ef0a233f808bfc9b18cf94624bf30836a18d3b05d08bf418/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca1124aced216b2500dc2609eade086d718e8249cb9696660ab447d50a758bd", size = 2132986, upload-time = "2025-10-14T10:23:32.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/c8/629e88920171173f6049386cc71f893dff03209a9ef32b4d2f7e7c264bcf/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c9024169becccf0cb470ada03ee578d7348c119a0d42af3dcf9eda96e3a247c", size = 2187516, upload-time = "2025-10-14T10:23:34.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/0f/4f2734688d98488782218ca61bcc118329bf5de05bb7fe3adc7dd79b0b86/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:26895a4268ae5a2849269f4991cdc97236e4b9c010e51137becf25182daac405", size = 2146146, upload-time = "2025-10-14T10:23:37.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/f2/ab385dbd94a052c62224b99cf99002eee99dbec40e10006c78575aead256/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:ca4df25762cf71308c446e33c9b1fdca2923a3f13de616e2a949f38bf21ff5a8", size = 2311296, upload-time = "2025-10-14T10:23:40.145Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/8e/e4f12afe1beeb9823bba5375f8f258df0cc61b056b0195fb1cf9f62a1a58/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5a28fcedd762349519276c36634e71853b4541079cab4acaaac60c4421827308", size = 2315386, upload-time = "2025-10-14T10:23:42.624Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/f7/925f65d930802e3ea2eb4d5afa4cb8730c8dc0d2cb89a59dc4ed2fcb2d74/pydantic_core-2.41.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c173ddcd86afd2535e2b695217e82191580663a1d1928239f877f5a1649ef39f", size = 2147775, upload-time = "2025-10-14T10:23:45.406Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -961,14 +1047,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 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.
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import random
|
||||
import sqlite3
|
||||
import threading
|
||||
@@ -265,9 +266,7 @@ class SqliteSaver(BaseCheckpointSaver[str]):
|
||||
self.serde.loads_typed((type, checkpoint)),
|
||||
cast(
|
||||
CheckpointMetadata,
|
||||
self.jsonplus_serde.loads(metadata)
|
||||
if metadata is not None
|
||||
else {},
|
||||
json.loads(metadata) if metadata is not None else {},
|
||||
),
|
||||
(
|
||||
{
|
||||
@@ -358,9 +357,7 @@ class SqliteSaver(BaseCheckpointSaver[str]):
|
||||
self.serde.loads_typed((type, checkpoint)),
|
||||
cast(
|
||||
CheckpointMetadata,
|
||||
self.jsonplus_serde.loads(metadata)
|
||||
if metadata is not None
|
||||
else {},
|
||||
json.loads(metadata) if metadata is not None else {},
|
||||
),
|
||||
(
|
||||
{
|
||||
@@ -413,9 +410,9 @@ class SqliteSaver(BaseCheckpointSaver[str]):
|
||||
thread_id = config["configurable"]["thread_id"]
|
||||
checkpoint_ns = config["configurable"]["checkpoint_ns"]
|
||||
type_, serialized_checkpoint = self.serde.dumps_typed(checkpoint)
|
||||
serialized_metadata = self.jsonplus_serde.dumps(
|
||||
get_checkpoint_metadata(config, metadata)
|
||||
)
|
||||
serialized_metadata = json.dumps(
|
||||
get_checkpoint_metadata(config, metadata), ensure_ascii=False
|
||||
).encode("utf-8", "ignore")
|
||||
with self.cursor() as cur:
|
||||
cur.execute(
|
||||
"INSERT OR REPLACE INTO checkpoints (thread_id, checkpoint_ns, checkpoint_id, parent_checkpoint_id, type, checkpoint, metadata) VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import random
|
||||
from collections.abc import AsyncIterator, Callable, Iterator, Sequence
|
||||
from contextlib import asynccontextmanager
|
||||
@@ -377,9 +378,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
|
||||
self.serde.loads_typed((type, checkpoint)),
|
||||
cast(
|
||||
CheckpointMetadata,
|
||||
self.jsonplus_serde.loads(metadata)
|
||||
if metadata is not None
|
||||
else {},
|
||||
(json.loads(metadata) if metadata is not None else {}),
|
||||
),
|
||||
(
|
||||
{
|
||||
@@ -457,9 +456,7 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
|
||||
self.serde.loads_typed((type, checkpoint)),
|
||||
cast(
|
||||
CheckpointMetadata,
|
||||
self.jsonplus_serde.loads(metadata)
|
||||
if metadata is not None
|
||||
else {},
|
||||
(json.loads(metadata) if metadata is not None else {}),
|
||||
),
|
||||
(
|
||||
{
|
||||
@@ -503,9 +500,9 @@ class AsyncSqliteSaver(BaseCheckpointSaver[str]):
|
||||
thread_id = config["configurable"]["thread_id"]
|
||||
checkpoint_ns = config["configurable"]["checkpoint_ns"]
|
||||
type_, serialized_checkpoint = self.serde.dumps_typed(checkpoint)
|
||||
serialized_metadata = self.jsonplus_serde.dumps(
|
||||
get_checkpoint_metadata(config, metadata)
|
||||
)
|
||||
serialized_metadata = json.dumps(
|
||||
get_checkpoint_metadata(config, metadata), ensure_ascii=False
|
||||
).encode("utf-8", "ignore")
|
||||
async with (
|
||||
self.lock,
|
||||
self.conn.execute(
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "langgraph-checkpoint-sqlite"
|
||||
version = "2.0.11"
|
||||
version = "3.0.0"
|
||||
description = "Library with a SQLite implementation of LangGraph checkpoint saver."
|
||||
authors = []
|
||||
requires-python = ">=3.10"
|
||||
@@ -12,26 +12,35 @@ readme = "README.md"
|
||||
license = "MIT"
|
||||
license-files = ['LICENSE']
|
||||
dependencies = [
|
||||
"langgraph-checkpoint>=2.0.21,<3.0.0",
|
||||
"langgraph-checkpoint>=3,<4.0.0",
|
||||
"aiosqlite>=0.20",
|
||||
"sqlite-vec>=0.1.6",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint-sqlite"
|
||||
Twitter = "https://x.com/LangChainAI"
|
||||
Slack = "https://www.langchain.com/join-community"
|
||||
Reddit = "https://www.reddit.com/r/LangChain/"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
test = [
|
||||
"pytest",
|
||||
"pytest-asyncio",
|
||||
"pytest-mock",
|
||||
"pytest-watcher",
|
||||
"mypy",
|
||||
"langgraph-checkpoint",
|
||||
"pytest-retry>=1.7.0",
|
||||
]
|
||||
lint = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
"mypy",
|
||||
]
|
||||
dev = [
|
||||
{include-group = "test"},
|
||||
{include-group = "lint"},
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
default-groups = ['dev']
|
||||
|
||||
Generated
+206
-122
@@ -1,5 +1,5 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
revision = 3
|
||||
requires-python = ">=3.10"
|
||||
|
||||
[[package]]
|
||||
@@ -246,7 +246,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint"
|
||||
version = "2.1.2"
|
||||
version = "3.0.1"
|
||||
source = { editable = "../checkpoint" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
@@ -256,7 +256,7 @@ dependencies = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "langchain-core", specifier = ">=0.2.38" },
|
||||
{ name = "ormsgpack", specifier = ">=1.10.0" },
|
||||
{ name = "ormsgpack", specifier = ">=1.12.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
@@ -274,10 +274,26 @@ dev = [
|
||||
{ name = "redis" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "dataclasses-json" },
|
||||
{ name = "numpy" },
|
||||
{ name = "pandas" },
|
||||
{ name = "pandas-stubs", specifier = ">=2.2.2.240807" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "redis" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint-sqlite"
|
||||
version = "2.0.11"
|
||||
version = "3.0.0"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "aiosqlite" },
|
||||
@@ -297,6 +313,19 @@ dev = [
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "langgraph-checkpoint" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-retry" },
|
||||
{ name = "pytest-watcher" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
@@ -317,6 +346,19 @@ dev = [
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-retry", specifier = ">=1.7.0" },
|
||||
{ name = "pytest-watcher" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
@@ -469,42 +511,57 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ormsgpack"
|
||||
version = "1.10.0"
|
||||
version = "1.12.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/92/36/44eed5ef8ce93cded76a576780bab16425ce7876f10d3e2e6265e46c21ea/ormsgpack-1.10.0.tar.gz", hash = "sha256:7f7a27efd67ef22d7182ec3b7fa7e9d147c3ad9be2a24656b23c989077e08b16", size = 58629, upload-time = "2025-05-24T19:07:53.944Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/67/d5ef41c3b4a94400be801984ef7c7fc9623e1a82b643e74eeec367e7462b/ormsgpack-1.12.0.tar.gz", hash = "sha256:94be818fdbb0285945839b88763b269987787cb2f7ef280cad5d6ec815b7e608", size = 49959, upload-time = "2025-11-04T18:30:10.083Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/74/c2dd5daf069e3798d09d5746000f9b210de04df83834e5cb47f0ace51892/ormsgpack-1.10.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8a52c7ce7659459f3dc8dec9fd6a6c76f855a0a7e2b61f26090982ac10b95216", size = 376280, upload-time = "2025-05-24T19:06:51.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/7b/30ff4bffb709e8a242005a8c4d65714fd96308ad640d31cff1b85c0d8cc4/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:060f67fe927582f4f63a1260726d019204b72f460cf20930e6c925a1d129f373", size = 204335, upload-time = "2025-05-24T19:06:53.442Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/3f/c95b7d142819f801a0acdbd04280e8132e43b6e5a8920173e8eb92ea0e6a/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7058ef6092f995561bf9f71d6c9a4da867b6cc69d2e94cb80184f579a3ceed5", size = 215373, upload-time = "2025-05-24T19:06:55.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/1a/e30f4bcf386db2015d1686d1da6110c95110294d8ea04f86091dd5eb3361/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6f3509c1b0e51b15552d314b1d409321718122e90653122ce4b997f01453a", size = 216469, upload-time = "2025-05-24T19:06:56.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/fc/7e44aeade22b91883586f45b7278c118fd210834c069774891447f444fc9/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c1edafd5c72b863b1f875ec31c529f09c872a5ff6fe473b9dfaf188ccc3227", size = 384590, upload-time = "2025-05-24T19:06:58.286Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/78/f92c24e8446697caa83c122f10b6cf5e155eddf81ce63905c8223a260482/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c780b44107a547a9e9327270f802fa4d6b0f6667c9c03c3338c0ce812259a0f7", size = 478891, upload-time = "2025-05-24T19:07:00.126Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/75/87449690253c64bea2b663c7c8f2dbc9ad39d73d0b38db74bdb0f3947b16/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:137aab0d5cdb6df702da950a80405eb2b7038509585e32b4e16289604ac7cb84", size = 390121, upload-time = "2025-05-24T19:07:01.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/cc/c83257faf3a5169ec29dd87121317a25711da9412ee8c1e82f2e1a00c0be/ormsgpack-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:3e666cb63030538fa5cd74b1e40cb55b6fdb6e2981f024997a288bf138ebad07", size = 121196, upload-time = "2025-05-24T19:07:03.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/27/7da748bc0d7d567950a378dee5a32477ed5d15462ab186918b5f25cac1ad/ormsgpack-1.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4bb7df307e17b36cbf7959cd642c47a7f2046ae19408c564e437f0ec323a7775", size = 376275, upload-time = "2025-05-24T19:07:05.128Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/65/c082cc8c74a914dbd05af0341c761c73c3d9960b7432bbf9b8e1e20811af/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8817ae439c671779e1127ee62f0ac67afdeaeeacb5f0db45703168aa74a2e4af", size = 204335, upload-time = "2025-05-24T19:07:06.423Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/62/17ef7e5d9766c79355b9c594cc9328c204f1677bc35da0595cc4e46449f0/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f345f81e852035d80232e64374d3a104139d60f8f43c6c5eade35c4bac5590e", size = 215372, upload-time = "2025-05-24T19:07:08.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/92/7c91e8115fc37e88d1a35e13200fda3054ff5d2e5adf017345e58cea4834/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21de648a1c7ef692bdd287fb08f047bd5371d7462504c0a7ae1553c39fee35e3", size = 216470, upload-time = "2025-05-24T19:07:09.903Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/86/ce053c52e2517b90e390792d83e926a7a523c1bce5cc63d0a7cd05ce6cf6/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3a7d844ae9cbf2112c16086dd931b2acefce14cefd163c57db161170c2bfa22b", size = 384591, upload-time = "2025-05-24T19:07:11.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/e8/2ad59f2ab222c6029e500bc966bfd2fe5cb099f8ab6b7ebeb50ddb1a6fe5/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4d80585403d86d7f800cf3d0aafac1189b403941e84e90dd5102bb2b92bf9d5", size = 478892, upload-time = "2025-05-24T19:07:13.147Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/73/f55e4b47b7b18fd8e7789680051bf830f1e39c03f1d9ed993cd0c3e97215/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da1de515a87e339e78a3ccf60e39f5fb740edac3e9e82d3c3d209e217a13ac08", size = 390122, upload-time = "2025-05-24T19:07:14.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/87/073251cdb93d4c6241748568b3ad1b2a76281fb2002eed16a3a4043d61cf/ormsgpack-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:57c4601812684024132cbb32c17a7d4bb46ffc7daf2fddf5b697391c2c4f142a", size = 121197, upload-time = "2025-05-24T19:07:15.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/95/f3ab1a7638f6aa9362e87916bb96087fbbc5909db57e19f12ad127560e1e/ormsgpack-1.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4e159d50cd4064d7540e2bc6a0ab66eab70b0cc40c618b485324ee17037527c0", size = 376806, upload-time = "2025-05-24T19:07:17.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/2b/42f559f13c0b0f647b09d749682851d47c1a7e48308c43612ae6833499c8/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb47c85f3a866e29279d801115b554af0fefc409e2ed8aa90aabfa77efe5cc6", size = 204433, upload-time = "2025-05-24T19:07:18.569Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/42/1ca0cb4d8c80340a89a4af9e6d8951fb8ba0d076a899d2084eadf536f677/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c28249574934534c9bd5dce5485c52f21bcea0ee44d13ece3def6e3d2c3798b5", size = 215547, upload-time = "2025-05-24T19:07:20.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/38/184a570d7c44c0260bc576d1daaac35b2bfd465a50a08189518505748b9a/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1957dcadbb16e6a981cd3f9caef9faf4c2df1125e2a1b702ee8236a55837ce07", size = 216746, upload-time = "2025-05-24T19:07:21.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/2f/1aaffd08f6b7fdc2a57336a80bdfb8df24e6a65ada5aa769afecfcbc6cc6/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b29412558c740bf6bac156727aa85ac67f9952cd6f071318f29ee72e1a76044", size = 384783, upload-time = "2025-05-24T19:07:23.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/63/3e53d6f43bb35e00c98f2b8ab2006d5138089ad254bc405614fbf0213502/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6933f350c2041ec189fe739f0ba7d6117c8772f5bc81f45b97697a84d03020dd", size = 479076, upload-time = "2025-05-24T19:07:25.047Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/19/fa1121b03b61402bb4d04e35d164e2320ef73dfb001b57748110319dd014/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a86de06d368fcc2e58b79dece527dc8ca831e0e8b9cec5d6e633d2777ec93d0", size = 390447, upload-time = "2025-05-24T19:07:26.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/0d/73143ecb94ac4a5dcba223402139240a75dee0cc6ba8a543788a5646407a/ormsgpack-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:35fa9f81e5b9a0dab42e09a73f7339ecffdb978d6dbf9deb2ecf1e9fc7808722", size = 121401, upload-time = "2025-05-24T19:07:28.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/f8/ec5f4e03268d0097545efaab2893aa63f171cf2959cb0ea678a5690e16a1/ormsgpack-1.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d816d45175a878993b7372bd5408e0f3ec5a40f48e2d5b9d8f1cc5d31b61f1f", size = 376806, upload-time = "2025-05-24T19:07:29.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/19/b3c53284aad1e90d4d7ed8c881a373d218e16675b8b38e3569d5b40cc9b8/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90345ccb058de0f35262893751c603b6376b05f02be2b6f6b7e05d9dd6d5643", size = 204433, upload-time = "2025-05-24T19:07:30.977Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/0b/845c258f59df974a20a536c06cace593698491defdd3d026a8a5f9b6e745/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144b5e88f1999433e54db9d637bae6fe21e935888be4e3ac3daecd8260bd454e", size = 215549, upload-time = "2025-05-24T19:07:32.345Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/56/57fce8fb34ca6c9543c026ebebf08344c64dbb7b6643d6ddd5355d37e724/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2190b352509d012915921cca76267db136cd026ddee42f1b0d9624613cc7058c", size = 216747, upload-time = "2025-05-24T19:07:34.075Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/3f/655b5f6a2475c8d209f5348cfbaaf73ce26237b92d79ef2ad439407dd0fa/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:86fd9c1737eaba43d3bb2730add9c9e8b5fbed85282433705dd1b1e88ea7e6fb", size = 384785, upload-time = "2025-05-24T19:07:35.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/94/687a0ad8afd17e4bce1892145d6a1111e58987ddb176810d02a1f3f18686/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:33afe143a7b61ad21bb60109a86bb4e87fec70ef35db76b89c65b17e32da7935", size = 479076, upload-time = "2025-05-24T19:07:37.533Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/34/68925232e81e0e062a2f0ac678f62aa3b6f7009d6a759e19324dbbaebae7/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f23d45080846a7b90feabec0d330a9cc1863dc956728412e4f7986c80ab3a668", size = 390446, upload-time = "2025-05-24T19:07:39.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/ad/f4e1a36a6d1714afb7ffb74b3ababdcb96529cf4e7a216f9f7c8eda837b6/ormsgpack-1.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:534d18acb805c75e5fba09598bf40abe1851c853247e61dda0c01f772234da69", size = 121399, upload-time = "2025-05-24T19:07:40.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/0c/8f45fcd22c95190b05d4fba71375d8f783a9e3b0b6aaf476812b693e3868/ormsgpack-1.12.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e08904c232358b94a682ccfbb680bc47d3fd5c424bb7dccb65974dd20c95e8e1", size = 369156, upload-time = "2025-11-04T18:29:17.629Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/f8/c7adc093d4ceb05e38786906815f868210f808326c27f8124b4d9466a26b/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9ed7a4b0037d69c8ba7e670e03ee65ae8d5c5114a409e73c5770d7fb5e4b895", size = 195743, upload-time = "2025-11-04T18:29:18.964Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/b8/bf002648fa6c150ed6157837b00303edafb35f65c352429463f83214de18/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:db2928525b684f3f2af0367aef7ae8d20cde37fc5349c700017129d493a755aa", size = 206472, upload-time = "2025-11-04T18:29:19.951Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/d6/1f445947c95a931bb189b7864a3f9dcbeebe7dcbc1b3c7387427b3779228/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45f911d9c5b23d11e49ff03fc8f9566745a2b1a7d9033733a1c0a2fa9301cd60", size = 207959, upload-time = "2025-11-04T18:29:21.282Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/9c/dd8ccd7553a5c1d0b4b69a0541611983a2f9bc2e8c5708a4bfffc0100468/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:98c54ae6fd682b2aceb264505af9b2255f3df9d84e6e4369bc44d2110f1f311d", size = 377659, upload-time = "2025-11-04T18:29:22.561Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/08/3282d8f6330e742d4cdbcfbe2c100b403ae5526ae82a1c1b6a11b7967e37/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:857ab987c3502de08258cc4baf0e87267cb2c80931601084e13df3c355b1ab9d", size = 471391, upload-time = "2025-11-04T18:29:23.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/d4/94a2fbfd4837754bda7a099b6a23b9d40aba9e76e1af8b8fb8133612eb54/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:27579d45dc502ee736238e1024559cb0a01aa72a3b68827448b8edf6a2dcdc9c", size = 381501, upload-time = "2025-11-04T18:29:24.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/c6/1a9fa122cb5deb10b067bbaa43165b12291a914cc0ce364988ff17bbf405/ormsgpack-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:c78379d054760875540cf2e81f28da1bb78d09fda3eabdbeb6c53b3e297158cb", size = 112715, upload-time = "2025-11-04T18:29:26.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/ba/3cae83cf36420c1c8dd294f16c852c03313aafe2439a165c4c6ac611b1d0/ormsgpack-1.12.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c40d86d77391b18dd34de5295e3de2b8ad818bcab9c9def4121c8ec5c9714ae4", size = 369159, upload-time = "2025-11-04T18:29:27.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/d4/5e176309e01a8b9098d80201aac1eb7db9336c3b5b4fa6254a2bbb0d0fa0/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:777b7fab364dc0f200bb382a98a385c8222ffa6a2333d627d763797326202c86", size = 195744, upload-time = "2025-11-04T18:29:28.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/83/6d80c8c5571639c000a39f38f77752dfaf9d9e552d775331e8d280f66a4e/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b5089ad9dd5b3d3013b245a55e4abaea2f8ad70f4a78e1b002127b02340004", size = 206474, upload-time = "2025-11-04T18:29:29.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/e6/940311e48dc0cfc3e212bd7007a21ed0825158638057687d804f2c5c2cca/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deaf0c87cace7bc08fbf68c5cc66605b593df6427e9f4de235b2da358787e008", size = 207959, upload-time = "2025-11-04T18:29:30.315Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/e3/fbe94b0a311815343b86a95a0627e4901b11ff6fd522679ca29a2a88c99b/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f62d476fe28bc5675d9aff30341bfa9f41d7de332c5b63fbbe9aaf6bb7ec74d4", size = 377666, upload-time = "2025-11-04T18:29:31.38Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/3b/229cfa28076798ffb619aaa854b842de3f2ed5ea4e6509bf34d14c038c4d/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ded7810095b887e28434f32f5a345d354e88cf851bab3c5435aeb86a718618d2", size = 471394, upload-time = "2025-11-04T18:29:32.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/bd/4eae4ab35586e4175c07acb5f98aec83aa9d8987f71ea0443aa900191bdf/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f72a1dea0c4ae7c4101dcfbe8133f274a9d769d0b87fe5188db4fab07ffabaee", size = 381506, upload-time = "2025-11-04T18:29:33.533Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/51/f9d56d6d015cbfa1ce9a4358ca30a41744644f0cf606e060d7203efe5af8/ormsgpack-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:8f479bfef847255d7d0b12c7a198f6a21490155da2da3062e082ba370893d4a1", size = 112707, upload-time = "2025-11-04T18:29:34.898Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/07/bb189ef7072979f2f96e8716e952172efdce9c54930aa0814bec73aee19b/ormsgpack-1.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:3583ca410e4502144b2594170542e4bbef7b15643fd1208703ae820f11029036", size = 106533, upload-time = "2025-11-04T18:29:36.112Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/f2/c1036b2775fcc0cfa5fd618c53bcd3b862ee07298fb627f03af4c7982f84/ormsgpack-1.12.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e0c1e08b64d99076fee155276097489b82cc56e8d5951c03c721a65a32f44494", size = 369538, upload-time = "2025-11-04T18:29:37.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/ca/526c4ae02f3cb34621af91bf8282a10d666757c2e0c6ff391ff5d403d607/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fd43bcb299131690b8e0677af172020b2ada8e625169034b42ac0c13adf84aa", size = 195872, upload-time = "2025-11-04T18:29:38.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/0f/83bb7968e9715f6a85be53d041b1e6324a05428f56b8b980dac866886871/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0149d595341e22ead340bf281b2995c4cc7dc8d522a6b5f575fe17aa407604", size = 206469, upload-time = "2025-11-04T18:29:39.749Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/e3/9e93ca1065f2d4af035804a842b1ff3025bab580c7918239bb225cd1fee2/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f19a1b27d169deb553c80fd10b589fc2be1fc14cee779fae79fcaf40db04de2b", size = 208273, upload-time = "2025-11-04T18:29:40.769Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d8/6d6ef901b3a8b8f3ab8836b135a56eb7f66c559003e251d9530bedb12627/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f28896942d655064940dfe06118b7ce1e3468d051483148bf02c99ec157483a", size = 377839, upload-time = "2025-11-04T18:29:42.092Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/72/fcb704bfa4c2c3a37b647d597cc45a13cffc9d50baac635a9ad620731d29/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9396efcfa48b4abbc06e44c5dbc3c4574a8381a80cb4cd01eea15d28b38c554e", size = 471446, upload-time = "2025-11-04T18:29:43.133Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/f8/402e4e3eb997c2ee534c99bec4b5bb359c2a1f9edadf043e254a71e11378/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:96586ed537a5fb386a162c4f9f7d8e6f76e07b38a990d50c73f11131e00ff040", size = 381783, upload-time = "2025-11-04T18:29:44.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/8d/5897b700360bc00911b70ae5ef1134ee7abf5baa81a92a4be005917d3dfd/ormsgpack-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e70387112fb3870e4844de090014212cdcf1342f5022047aecca01ec7de05d7a", size = 112943, upload-time = "2025-11-04T18:29:45.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/44/1e73649f79bb96d6cf9e5bcbac68b6216d238bba80af351c4c0cbcf7ee15/ormsgpack-1.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:d71290a23de5d4829610c42665d816c661ecad8979883f3f06b2e3ab9639962e", size = 106688, upload-time = "2025-11-04T18:29:46.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/e8/35f11ce9313111488b26b3035e4cbe55caa27909c0b6c8b5b5cd59f9661e/ormsgpack-1.12.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:766f2f3b512d85cd375b26a8b1329b99843560b50b93d3880718e634ad4a5de5", size = 369574, upload-time = "2025-11-04T18:29:47.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/b0/77461587f412d4e598d3687bafe23455ed0f26269f44be20252eddaa624e/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84b285b1f3f185aad7da45641b873b30acfd13084cf829cf668c4c6480a81583", size = 195893, upload-time = "2025-11-04T18:29:48.735Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/67/e197ceb04c3b550589e5407fc9fdae10f4e2e2eba5fdac921a269e02e974/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e23604fc79fe110292cb365f4c8232e64e63a34f470538be320feae3921f271b", size = 206503, upload-time = "2025-11-04T18:29:49.99Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/b1/7fa8ba82a25cef678983c7976f85edeef5014f5c26495f338258e6a3cf1c/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc32b156c113a0fae2975051417d8d9a7a5247c34b2d7239410c46b75ce9348a", size = 208257, upload-time = "2025-11-04T18:29:51.007Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/b1/759e999390000d2589e6d0797f7265e6ec28378547075d28d3736248ab63/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:94ac500dd10c20fa8b8a23bc55606250bfe711bf9716828d9f3d44dfd1f25668", size = 377852, upload-time = "2025-11-04T18:29:52.103Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/e7/0af737c94272494d9d84a3c29cc42c973ef7fd2342917020906596db863c/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:c5201ff7ec24f721f813a182885a17064cffdbe46b2412685a52e6374a872c8f", size = 471456, upload-time = "2025-11-04T18:29:53.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/ba/c81f0aa4f19fbf457213395945b672e6fde3ce777e3587456e7f0fca2147/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a9740bb3839c9368aacae1cbcfc474ee6976458f41cc135372b7255d5206c953", size = 381813, upload-time = "2025-11-04T18:29:54.394Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/15/429c72d64323503fd42cc4ca8398930ded8aa8b3470df8a86b3bbae7a35c/ormsgpack-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ed37f29772432048b58174e920a1d4c4cde0404a5d448d3d8bbcc95d86a6918", size = 112949, upload-time = "2025-11-04T18:29:55.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/b9/e72c451a40f8c57bfc229e0b8e536ecea7203c8f0a839676df2ffb605c62/ormsgpack-1.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:b03994bbec5d6d42e03d6604e327863f885bde67aa61e06107ce1fa5bdd3e71d", size = 106689, upload-time = "2025-11-04T18:29:56.262Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/16/13eab1a75da531b359105fdee90dda0b6bd1ca0a09880250cf91d8bdfdea/ormsgpack-1.12.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0f3981ba3cba80656012090337e548e597799e14b41e3d0b595ab5ab05a23d7f", size = 369620, upload-time = "2025-11-04T18:29:57.255Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/c1/cbcc38b7af4ce58d8893e56d3595c0c8dcd117093bf048f889cf351bdba0/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:901f6f55184d6776dbd5183cbce14caf05bf7f467eef52faf9b094686980bf71", size = 195925, upload-time = "2025-11-04T18:29:58.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/59/4fa4dc0681490e12b75333440a1c0fd9741b0ebff272b1db4a29d35c2021/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e13b15412571422b711b40f45e3fe6d993ea3314b5e97d1a853fe99226c5effc", size = 206594, upload-time = "2025-11-04T18:29:59.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/67/249770896bc32bb91b22c30256961f935d0915cbcf6e289a7fc961d9b14c/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91fa8a452553a62e5fb3fbab471e7faf7b3bec3c87a2f355ebf3d7aab290fe4f", size = 208307, upload-time = "2025-11-04T18:30:00.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/0a/e041a248cd72f2f4c07e155913e0a3ede4c86cf21a40ae6cd79f135f2847/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74ec101f69624695eec4ce7c953192d97748254abe78fb01b591f06d529e1952", size = 377844, upload-time = "2025-11-04T18:30:01.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/71/6f7773e4ffda73a358ce4bba69b3e8bee9d40a7a06315e4c1cd7a3ea9d02/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9bbf7896580848326c1f9bd7531f264e561f98db7e08e15aa75963d83832c717", size = 471572, upload-time = "2025-11-04T18:30:02.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/29/af6769a4289c07acc71e7bda1d64fb31800563147d73142686e185e82348/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7567917da613b8f8d591c1674e411fd3404bea41ef2b9a0e0a1e049c0f9406d7", size = 381842, upload-time = "2025-11-04T18:30:03.799Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/dd/0a86195ee7a1a96c088aefc8504385e881cf56f4563ed81bafe21cbf1fb0/ormsgpack-1.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e418256c5d8622b8bc92861936f7c6a0131355e7bcad88a42102ae8227f8a1c", size = 113008, upload-time = "2025-11-04T18:30:04.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/57/fafc79e32f3087f6f26f509d80b8167516326bfea38d30502627c01617e0/ormsgpack-1.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:433ace29aa02713554f714c62a4e4dcad0c9e32674ba4f66742c91a4c3b1b969", size = 106648, upload-time = "2025-11-04T18:30:05.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/cf/5d58d9b132128d2fe5d586355dde76af386554abef00d608f66b913bff1f/ormsgpack-1.12.0-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e57164be4ca34b64e210ec515059193280ac84df4d6f31a6fcbfb2fc8436de55", size = 369803, upload-time = "2025-11-04T18:30:06.728Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/42/968a2da361eaff2e4cbb17c82c7599787babf16684110ad70409646cc1e4/ormsgpack-1.12.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:904f96289deaa92fc6440b122edc27c5bdc28234edd63717f6d853d88c823a83", size = 195991, upload-time = "2025-11-04T18:30:07.713Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/f0/9696c6c6cf8ad35170f0be8d0ef3523cc258083535f6c8071cb8235ebb8b/ormsgpack-1.12.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b291d086e524a1062d57d1b7b5a8bcaaf29caebf0212fec12fd86240bd33633", size = 208316, upload-time = "2025-11-04T18:30:08.663Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -536,7 +593,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.11.9"
|
||||
version = "2.12.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
@@ -544,96 +601,123 @@ dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ff/5d/09a551ba512d7ca404d785072700d3f6727a02f6f3c24ecfd081c7cf0aa8/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2", size = 788495, upload-time = "2025-09-13T11:26:39.325Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8d/35/d319ed522433215526689bad428a94058b6dd12190ce7ddd78618ac14b28/pydantic-2.12.2.tar.gz", hash = "sha256:7b8fa15b831a4bbde9d5b84028641ac3080a4ca2cbd4a621a661687e741624fd", size = 816358, upload-time = "2025-10-14T15:02:21.842Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/d3/108f2006987c58e76691d5ae5d200dd3e0f532cb4e5fa3560751c3a1feba/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2", size = 444855, upload-time = "2025-09-13T11:26:36.909Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/98/468cb649f208a6f1279448e6e5247b37ae79cf5e4041186f1e2ef3d16345/pydantic-2.12.2-py3-none-any.whl", hash = "sha256:25ff718ee909acd82f1ff9b1a4acfd781bb23ab3739adaa7144f19a6a4e231ae", size = 460628, upload-time = "2025-10-14T15:02:19.623Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.33.2"
|
||||
version = "2.41.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/18/d0944e8eaaa3efd0a91b0f1fc537d3be55ad35091b6a87638211ba691964/pydantic_core-2.41.4.tar.gz", hash = "sha256:70e47929a9d4a1905a67e4b687d5946026390568a8e952b92824118063cee4d5", size = 457557, upload-time = "2025-10-14T10:23:47.909Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/3d/9b8ca77b0f76fcdbf8bc6b72474e264283f461284ca84ac3fde570c6c49a/pydantic_core-2.41.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2442d9a4d38f3411f22eb9dd0912b7cbf4b7d5b6c92c4173b75d3e1ccd84e36e", size = 2111197, upload-time = "2025-10-14T10:19:43.303Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/92/b7b0fe6ed4781642232755cb7e56a86e2041e1292f16d9ae410a0ccee5ac/pydantic_core-2.41.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30a9876226dda131a741afeab2702e2d127209bde3c65a2b8133f428bc5d006b", size = 1917909, upload-time = "2025-10-14T10:19:45.194Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/8c/3eb872009274ffa4fb6a9585114e161aa1a0915af2896e2d441642929fe4/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d55bbac04711e2980645af68b97d445cdbcce70e5216de444a6c4b6943ebcccd", size = 1969905, upload-time = "2025-10-14T10:19:46.567Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/21/35adf4a753bcfaea22d925214a0c5b880792e3244731b3f3e6fec0d124f7/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1d778fb7849a42d0ee5927ab0f7453bf9f85eef8887a546ec87db5ddb178945", size = 2051938, upload-time = "2025-10-14T10:19:48.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/d0/cdf7d126825e36d6e3f1eccf257da8954452934ede275a8f390eac775e89/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b65077a4693a98b90ec5ad8f203ad65802a1b9b6d4a7e48066925a7e1606706", size = 2250710, upload-time = "2025-10-14T10:19:49.619Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/1c/af1e6fd5ea596327308f9c8d1654e1285cc3d8de0d584a3c9d7705bf8a7c/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62637c769dee16eddb7686bf421be48dfc2fae93832c25e25bc7242e698361ba", size = 2367445, upload-time = "2025-10-14T10:19:51.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/81/8cece29a6ef1b3a92f956ea6da6250d5b2d2e7e4d513dd3b4f0c7a83dfea/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfe3aa529c8f501babf6e502936b9e8d4698502b2cfab41e17a028d91b1ac7b", size = 2072875, upload-time = "2025-10-14T10:19:52.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/37/a6a579f5fc2cd4d5521284a0ab6a426cc6463a7b3897aeb95b12f1ba607b/pydantic_core-2.41.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca2322da745bf2eeb581fc9ea3bbb31147702163ccbcbf12a3bb630e4bf05e1d", size = 2191329, upload-time = "2025-10-14T10:19:54.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/03/505020dc5c54ec75ecba9f41119fd1e48f9e41e4629942494c4a8734ded1/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e8cd3577c796be7231dcf80badcf2e0835a46665eaafd8ace124d886bab4d700", size = 2151658, upload-time = "2025-10-14T10:19:55.843Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/5d/2c0d09fb53aa03bbd2a214d89ebfa6304be7df9ed86ee3dc7770257f41ee/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1cae8851e174c83633f0833e90636832857297900133705ee158cf79d40f03e6", size = 2316777, upload-time = "2025-10-14T10:19:57.607Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/4b/c2c9c8f5e1f9c864b57d08539d9d3db160e00491c9f5ee90e1bfd905e644/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a26d950449aae348afe1ac8be5525a00ae4235309b729ad4d3399623125b43c9", size = 2320705, upload-time = "2025-10-14T10:19:59.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/c3/a74c1c37f49c0a02c89c7340fafc0ba816b29bd495d1a31ce1bdeacc6085/pydantic_core-2.41.4-cp310-cp310-win32.whl", hash = "sha256:0cf2a1f599efe57fa0051312774280ee0f650e11152325e41dfd3018ef2c1b57", size = 1975464, upload-time = "2025-10-14T10:20:00.581Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/23/5dd5c1324ba80303368f7569e2e2e1a721c7d9eb16acb7eb7b7f85cb1be2/pydantic_core-2.41.4-cp310-cp310-win_amd64.whl", hash = "sha256:a8c2e340d7e454dc3340d3d2e8f23558ebe78c98aa8f68851b04dcb7bc37abdc", size = 2024497, upload-time = "2025-10-14T10:20:03.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/4c/f6cbfa1e8efacd00b846764e8484fe173d25b8dab881e277a619177f3384/pydantic_core-2.41.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:28ff11666443a1a8cf2a044d6a545ebffa8382b5f7973f22c36109205e65dc80", size = 2109062, upload-time = "2025-10-14T10:20:04.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/f8/40b72d3868896bfcd410e1bd7e516e762d326201c48e5b4a06446f6cf9e8/pydantic_core-2.41.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:61760c3925d4633290292bad462e0f737b840508b4f722247d8729684f6539ae", size = 1916301, upload-time = "2025-10-14T10:20:06.857Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/4d/d203dce8bee7faeca791671c88519969d98d3b4e8f225da5b96dad226fc8/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eae547b7315d055b0de2ec3965643b0ab82ad0106a7ffd29615ee9f266a02827", size = 1968728, upload-time = "2025-10-14T10:20:08.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/f5/6a66187775df87c24d526985b3a5d78d861580ca466fbd9d4d0e792fcf6c/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef9ee5471edd58d1fcce1c80ffc8783a650e3e3a193fe90d52e43bb4d87bff1f", size = 2050238, upload-time = "2025-10-14T10:20:09.766Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/b9/78336345de97298cf53236b2f271912ce11f32c1e59de25a374ce12f9cce/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15dd504af121caaf2c95cb90c0ebf71603c53de98305621b94da0f967e572def", size = 2249424, upload-time = "2025-10-14T10:20:11.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/bb/a4584888b70ee594c3d374a71af5075a68654d6c780369df269118af7402/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a926768ea49a8af4d36abd6a8968b8790f7f76dd7cbd5a4c180db2b4ac9a3a2", size = 2366047, upload-time = "2025-10-14T10:20:13.647Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/8d/17fc5de9d6418e4d2ae8c675f905cdafdc59d3bf3bf9c946b7ab796a992a/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916b9b7d134bff5440098a4deb80e4cb623e68974a87883299de9124126c2a8", size = 2071163, upload-time = "2025-10-14T10:20:15.307Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/e7/03d2c5c0b8ed37a4617430db68ec5e7dbba66358b629cd69e11b4d564367/pydantic_core-2.41.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cf90535979089df02e6f17ffd076f07237efa55b7343d98760bde8743c4b265", size = 2190585, upload-time = "2025-10-14T10:20:17.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/fc/15d1c9fe5ad9266a5897d9b932b7f53d7e5cfc800573917a2c5d6eea56ec/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7533c76fa647fade2d7ec75ac5cc079ab3f34879626dae5689b27790a6cf5a5c", size = 2150109, upload-time = "2025-10-14T10:20:19.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/ef/e735dd008808226c83ba56972566138665b71477ad580fa5a21f0851df48/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:37e516bca9264cbf29612539801ca3cd5d1be465f940417b002905e6ed79d38a", size = 2315078, upload-time = "2025-10-14T10:20:20.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/00/806efdcf35ff2ac0f938362350cd9827b8afb116cc814b6b75cf23738c7c/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c19cb355224037c83642429b8ce261ae108e1c5fbf5c028bac63c77b0f8646e", size = 2318737, upload-time = "2025-10-14T10:20:22.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/7e/6ac90673fe6cb36621a2283552897838c020db343fa86e513d3f563b196f/pydantic_core-2.41.4-cp311-cp311-win32.whl", hash = "sha256:09c2a60e55b357284b5f31f5ab275ba9f7f70b7525e18a132ec1f9160b4f1f03", size = 1974160, upload-time = "2025-10-14T10:20:23.817Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/9d/7c5e24ee585c1f8b6356e1d11d40ab807ffde44d2db3b7dfd6d20b09720e/pydantic_core-2.41.4-cp311-cp311-win_amd64.whl", hash = "sha256:711156b6afb5cb1cb7c14a2cc2c4a8b4c717b69046f13c6b332d8a0a8f41ca3e", size = 2021883, upload-time = "2025-10-14T10:20:25.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/90/5c172357460fc28b2871eb4a0fb3843b136b429c6fa827e4b588877bf115/pydantic_core-2.41.4-cp311-cp311-win_arm64.whl", hash = "sha256:6cb9cf7e761f4f8a8589a45e49ed3c0d92d1d696a45a6feaee8c904b26efc2db", size = 1968026, upload-time = "2025-10-14T10:20:27.039Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/81/d3b3e95929c4369d30b2a66a91db63c8ed0a98381ae55a45da2cd1cc1288/pydantic_core-2.41.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ab06d77e053d660a6faaf04894446df7b0a7e7aba70c2797465a0a1af00fc887", size = 2099043, upload-time = "2025-10-14T10:20:28.561Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/da/46fdac49e6717e3a94fc9201403e08d9d61aa7a770fab6190b8740749047/pydantic_core-2.41.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c53ff33e603a9c1179a9364b0a24694f183717b2e0da2b5ad43c316c956901b2", size = 1910699, upload-time = "2025-10-14T10:20:30.217Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/63/4d948f1b9dd8e991a5a98b77dd66c74641f5f2e5225fee37994b2e07d391/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:304c54176af2c143bd181d82e77c15c41cbacea8872a2225dd37e6544dce9999", size = 1952121, upload-time = "2025-10-14T10:20:32.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/a7/e5fc60a6f781fc634ecaa9ecc3c20171d238794cef69ae0af79ac11b89d7/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025ba34a4cf4fb32f917d5d188ab5e702223d3ba603be4d8aca2f82bede432a4", size = 2041590, upload-time = "2025-10-14T10:20:34.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/69/dce747b1d21d59e85af433428978a1893c6f8a7068fa2bb4a927fba7a5ff/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9f5f30c402ed58f90c70e12eff65547d3ab74685ffe8283c719e6bead8ef53f", size = 2219869, upload-time = "2025-10-14T10:20:35.965Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/6a/c070e30e295403bf29c4df1cb781317b6a9bac7cd07b8d3acc94d501a63c/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd96e5d15385d301733113bcaa324c8bcf111275b7675a9c6e88bfb19fc05e3b", size = 2345169, upload-time = "2025-10-14T10:20:37.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/83/06d001f8043c336baea7fd202a9ac7ad71f87e1c55d8112c50b745c40324/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f348cbb44fae6e9653c1055db7e29de67ea6a9ca03a5fa2c2e11a47cff0e47", size = 2070165, upload-time = "2025-10-14T10:20:39.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/0a/e567c2883588dd12bcbc110232d892cf385356f7c8a9910311ac997ab715/pydantic_core-2.41.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec22626a2d14620a83ca583c6f5a4080fa3155282718b6055c2ea48d3ef35970", size = 2189067, upload-time = "2025-10-14T10:20:41.015Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/1d/3d9fca34273ba03c9b1c5289f7618bc4bd09c3ad2289b5420481aa051a99/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a95d4590b1f1a43bf33ca6d647b990a88f4a3824a8c4572c708f0b45a5290ed", size = 2132997, upload-time = "2025-10-14T10:20:43.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/70/d702ef7a6cd41a8afc61f3554922b3ed8d19dd54c3bd4bdbfe332e610827/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:f9672ab4d398e1b602feadcffcdd3af44d5f5e6ddc15bc7d15d376d47e8e19f8", size = 2307187, upload-time = "2025-10-14T10:20:44.849Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/4c/c06be6e27545d08b802127914156f38d10ca287a9e8489342793de8aae3c/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:84d8854db5f55fead3b579f04bda9a36461dab0730c5d570e1526483e7bb8431", size = 2305204, upload-time = "2025-10-14T10:20:46.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/e5/35ae4919bcd9f18603419e23c5eaf32750224a89d41a8df1a3704b69f77e/pydantic_core-2.41.4-cp312-cp312-win32.whl", hash = "sha256:9be1c01adb2ecc4e464392c36d17f97e9110fbbc906bcbe1c943b5b87a74aabd", size = 1972536, upload-time = "2025-10-14T10:20:48.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/c2/49c5bb6d2a49eb2ee3647a93e3dae7080c6409a8a7558b075027644e879c/pydantic_core-2.41.4-cp312-cp312-win_amd64.whl", hash = "sha256:d682cf1d22bab22a5be08539dca3d1593488a99998f9f412137bc323179067ff", size = 2031132, upload-time = "2025-10-14T10:20:50.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/23/936343dbcba6eec93f73e95eb346810fc732f71ba27967b287b66f7b7097/pydantic_core-2.41.4-cp312-cp312-win_arm64.whl", hash = "sha256:833eebfd75a26d17470b58768c1834dfc90141b7afc6eb0429c21fc5a21dcfb8", size = 1969483, upload-time = "2025-10-14T10:20:52.35Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/d0/c20adabd181a029a970738dfe23710b52a31f1258f591874fcdec7359845/pydantic_core-2.41.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:85e050ad9e5f6fe1004eec65c914332e52f429bc0ae12d6fa2092407a462c746", size = 2105688, upload-time = "2025-10-14T10:20:54.448Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/b6/0ce5c03cec5ae94cca220dfecddc453c077d71363b98a4bbdb3c0b22c783/pydantic_core-2.41.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7393f1d64792763a48924ba31d1e44c2cfbc05e3b1c2c9abb4ceeadd912cced", size = 1910807, upload-time = "2025-10-14T10:20:56.115Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/3e/800d3d02c8beb0b5c069c870cbb83799d085debf43499c897bb4b4aaff0d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94dab0940b0d1fb28bcab847adf887c66a27a40291eedf0b473be58761c9799a", size = 1956669, upload-time = "2025-10-14T10:20:57.874Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/a4/24271cc71a17f64589be49ab8bd0751f6a0a03046c690df60989f2f95c2c/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de7c42f897e689ee6f9e93c4bec72b99ae3b32a2ade1c7e4798e690ff5246e02", size = 2051629, upload-time = "2025-10-14T10:21:00.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/de/45af3ca2f175d91b96bfb62e1f2d2f1f9f3b14a734afe0bfeff079f78181/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:664b3199193262277b8b3cd1e754fb07f2c6023289c815a1e1e8fb415cb247b1", size = 2224049, upload-time = "2025-10-14T10:21:01.801Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/8f/ae4e1ff84672bf869d0a77af24fd78387850e9497753c432875066b5d622/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95b253b88f7d308b1c0b417c4624f44553ba4762816f94e6986819b9c273fb2", size = 2342409, upload-time = "2025-10-14T10:21:03.556Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/62/273dd70b0026a085c7b74b000394e1ef95719ea579c76ea2f0cc8893736d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1351f5bbdbbabc689727cb91649a00cb9ee7203e0a6e54e9f5ba9e22e384b84", size = 2069635, upload-time = "2025-10-14T10:21:05.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/03/cf485fff699b4cdaea469bc481719d3e49f023241b4abb656f8d422189fc/pydantic_core-2.41.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1affa4798520b148d7182da0615d648e752de4ab1a9566b7471bc803d88a062d", size = 2194284, upload-time = "2025-10-14T10:21:07.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/7e/c8e713db32405dfd97211f2fc0a15d6bf8adb7640f3d18544c1f39526619/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7b74e18052fea4aa8dea2fb7dbc23d15439695da6cbe6cfc1b694af1115df09d", size = 2137566, upload-time = "2025-10-14T10:21:08.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/f7/db71fd4cdccc8b75990f79ccafbbd66757e19f6d5ee724a6252414483fb4/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:285b643d75c0e30abda9dc1077395624f314a37e3c09ca402d4015ef5979f1a2", size = 2316809, upload-time = "2025-10-14T10:21:10.805Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/63/a54973ddb945f1bca56742b48b144d85c9fc22f819ddeb9f861c249d5464/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f52679ff4218d713b3b33f88c89ccbf3a5c2c12ba665fb80ccc4192b4608dbab", size = 2311119, upload-time = "2025-10-14T10:21:12.583Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/03/5d12891e93c19218af74843a27e32b94922195ded2386f7b55382f904d2f/pydantic_core-2.41.4-cp313-cp313-win32.whl", hash = "sha256:ecde6dedd6fff127c273c76821bb754d793be1024bc33314a120f83a3c69460c", size = 1981398, upload-time = "2025-10-14T10:21:14.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/d8/fd0de71f39db91135b7a26996160de71c073d8635edfce8b3c3681be0d6d/pydantic_core-2.41.4-cp313-cp313-win_amd64.whl", hash = "sha256:d081a1f3800f05409ed868ebb2d74ac39dd0c1ff6c035b5162356d76030736d4", size = 2030735, upload-time = "2025-10-14T10:21:16.432Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/86/c99921c1cf6650023c08bfab6fe2d7057a5142628ef7ccfa9921f2dda1d5/pydantic_core-2.41.4-cp313-cp313-win_arm64.whl", hash = "sha256:f8e49c9c364a7edcbe2a310f12733aad95b022495ef2a8d653f645e5d20c1564", size = 1973209, upload-time = "2025-10-14T10:21:18.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/0d/b5706cacb70a8414396efdda3d72ae0542e050b591119e458e2490baf035/pydantic_core-2.41.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ed97fd56a561f5eb5706cebe94f1ad7c13b84d98312a05546f2ad036bafe87f4", size = 1877324, upload-time = "2025-10-14T10:21:20.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/2d/cba1fa02cfdea72dfb3a9babb067c83b9dff0bbcb198368e000a6b756ea7/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a870c307bf1ee91fc58a9a61338ff780d01bfae45922624816878dce784095d2", size = 1884515, upload-time = "2025-10-14T10:21:22.339Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/ea/3df927c4384ed9b503c9cc2d076cf983b4f2adb0c754578dfb1245c51e46/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25e97bc1f5f8f7985bdc2335ef9e73843bb561eb1fa6831fdfc295c1c2061cf", size = 2042819, upload-time = "2025-10-14T10:21:26.683Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/ee/df8e871f07074250270a3b1b82aad4cd0026b588acd5d7d3eb2fcb1471a3/pydantic_core-2.41.4-cp313-cp313t-win_amd64.whl", hash = "sha256:d405d14bea042f166512add3091c1af40437c2e7f86988f3915fabd27b1e9cd2", size = 1995866, upload-time = "2025-10-14T10:21:28.951Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/de/b20f4ab954d6d399499c33ec4fafc46d9551e11dc1858fb7f5dca0748ceb/pydantic_core-2.41.4-cp313-cp313t-win_arm64.whl", hash = "sha256:19f3684868309db5263a11bace3c45d93f6f24afa2ffe75a647583df22a2ff89", size = 1970034, upload-time = "2025-10-14T10:21:30.869Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/28/d3325da57d413b9819365546eb9a6e8b7cbd9373d9380efd5f74326143e6/pydantic_core-2.41.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e9205d97ed08a82ebb9a307e92914bb30e18cdf6f6b12ca4bedadb1588a0bfe1", size = 2102022, upload-time = "2025-10-14T10:21:32.809Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/24/b58a1bc0d834bf1acc4361e61233ee217169a42efbdc15a60296e13ce438/pydantic_core-2.41.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:82df1f432b37d832709fbcc0e24394bba04a01b6ecf1ee87578145c19cde12ac", size = 1905495, upload-time = "2025-10-14T10:21:34.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/a4/71f759cc41b7043e8ecdaab81b985a9b6cad7cec077e0b92cff8b71ecf6b/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3b4cc4539e055cfa39a3763c939f9d409eb40e85813257dcd761985a108554", size = 1956131, upload-time = "2025-10-14T10:21:36.924Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/64/1e79ac7aa51f1eec7c4cda8cbe456d5d09f05fdd68b32776d72168d54275/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1eb1754fce47c63d2ff57fdb88c351a6c0150995890088b33767a10218eaa4e", size = 2052236, upload-time = "2025-10-14T10:21:38.927Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/e3/a3ffc363bd4287b80f1d43dc1c28ba64831f8dfc237d6fec8f2661138d48/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6ab5ab30ef325b443f379ddb575a34969c333004fca5a1daa0133a6ffaad616", size = 2223573, upload-time = "2025-10-14T10:21:41.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/27/78814089b4d2e684a9088ede3790763c64693c3d1408ddc0a248bc789126/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31a41030b1d9ca497634092b46481b937ff9397a86f9f51bd41c4767b6fc04af", size = 2342467, upload-time = "2025-10-14T10:21:44.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/97/4de0e2a1159cb85ad737e03306717637842c88c7fd6d97973172fb183149/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a44ac1738591472c3d020f61c6df1e4015180d6262ebd39bf2aeb52571b60f12", size = 2063754, upload-time = "2025-10-14T10:21:46.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/50/8cb90ce4b9efcf7ae78130afeb99fd1c86125ccdf9906ef64b9d42f37c25/pydantic_core-2.41.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d72f2b5e6e82ab8f94ea7d0d42f83c487dc159c5240d8f83beae684472864e2d", size = 2196754, upload-time = "2025-10-14T10:21:48.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/3b/ccdc77af9cd5082723574a1cc1bcae7a6acacc829d7c0a06201f7886a109/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c4d1e854aaf044487d31143f541f7aafe7b482ae72a022c664b2de2e466ed0ad", size = 2137115, upload-time = "2025-10-14T10:21:50.63Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/ba/e7c7a02651a8f7c52dc2cff2b64a30c313e3b57c7d93703cecea76c09b71/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b568af94267729d76e6ee5ececda4e283d07bbb28e8148bb17adad93d025d25a", size = 2317400, upload-time = "2025-10-14T10:21:52.959Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/ba/6c533a4ee8aec6b812c643c49bb3bd88d3f01e3cebe451bb85512d37f00f/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6d55fb8b1e8929b341cc313a81a26e0d48aa3b519c1dbaadec3a6a2b4fcad025", size = 2312070, upload-time = "2025-10-14T10:21:55.419Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/ae/f10524fcc0ab8d7f96cf9a74c880243576fd3e72bd8ce4f81e43d22bcab7/pydantic_core-2.41.4-cp314-cp314-win32.whl", hash = "sha256:5b66584e549e2e32a1398df11da2e0a7eff45d5c2d9db9d5667c5e6ac764d77e", size = 1982277, upload-time = "2025-10-14T10:21:57.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/dc/e5aa27aea1ad4638f0c3fb41132f7eb583bd7420ee63204e2d4333a3bbf9/pydantic_core-2.41.4-cp314-cp314-win_amd64.whl", hash = "sha256:557a0aab88664cc552285316809cab897716a372afaf8efdbef756f8b890e894", size = 2024608, upload-time = "2025-10-14T10:21:59.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/61/51d89cc2612bd147198e120a13f150afbf0bcb4615cddb049ab10b81b79e/pydantic_core-2.41.4-cp314-cp314-win_arm64.whl", hash = "sha256:3f1ea6f48a045745d0d9f325989d8abd3f1eaf47dd00485912d1a3a63c623a8d", size = 1967614, upload-time = "2025-10-14T10:22:01.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/c2/472f2e31b95eff099961fa050c376ab7156a81da194f9edb9f710f68787b/pydantic_core-2.41.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6c1fe4c5404c448b13188dd8bd2ebc2bdd7e6727fa61ff481bcc2cca894018da", size = 1876904, upload-time = "2025-10-14T10:22:04.062Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/07/ea8eeb91173807ecdae4f4a5f4b150a520085b35454350fc219ba79e66a3/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:523e7da4d43b113bf8e7b49fa4ec0c35bf4fe66b2230bfc5c13cc498f12c6c3e", size = 1882538, upload-time = "2025-10-14T10:22:06.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/29/b53a9ca6cd366bfc928823679c6a76c7a4c69f8201c0ba7903ad18ebae2f/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5729225de81fb65b70fdb1907fcf08c75d498f4a6f15af005aabb1fdadc19dfa", size = 2041183, upload-time = "2025-10-14T10:22:08.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/3d/f8c1a371ceebcaf94d6dd2d77c6cf4b1c078e13a5837aee83f760b4f7cfd/pydantic_core-2.41.4-cp314-cp314t-win_amd64.whl", hash = "sha256:de2cfbb09e88f0f795fd90cf955858fc2c691df65b1f21f0aa00b99f3fbc661d", size = 1993542, upload-time = "2025-10-14T10:22:11.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/ac/9fc61b4f9d079482a290afe8d206b8f490e9fd32d4fc03ed4fc698214e01/pydantic_core-2.41.4-cp314-cp314t-win_arm64.whl", hash = "sha256:d34f950ae05a83e0ede899c595f312ca976023ea1db100cd5aa188f7005e3ab0", size = 1973897, upload-time = "2025-10-14T10:22:13.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/12/5ba58daa7f453454464f92b3ca7b9d7c657d8641c48e370c3ebc9a82dd78/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a1b2cfec3879afb742a7b0bcfa53e4f22ba96571c9e54d6a3afe1052d17d843b", size = 2122139, upload-time = "2025-10-14T10:22:47.288Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/fb/6860126a77725c3108baecd10fd3d75fec25191d6381b6eb2ac660228eac/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:d175600d975b7c244af6eb9c9041f10059f20b8bbffec9e33fdd5ee3f67cdc42", size = 1936674, upload-time = "2025-10-14T10:22:49.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/be/57dcaa3ed595d81f8757e2b44a38240ac5d37628bce25fb20d02c7018776/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f184d657fa4947ae5ec9c47bd7e917730fa1cbb78195037e32dcbab50aca5ee", size = 1956398, upload-time = "2025-10-14T10:22:52.19Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/1d/679a344fadb9695f1a6a294d739fbd21d71fa023286daeea8c0ed49e7c2b/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed810568aeffed3edc78910af32af911c835cc39ebbfacd1f0ab5dd53028e5c", size = 2138674, upload-time = "2025-10-14T10:22:54.499Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/48/ae937e5a831b7c0dc646b2ef788c27cd003894882415300ed21927c21efa/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:4f5d640aeebb438517150fdeec097739614421900e4a08db4a3ef38898798537", size = 2112087, upload-time = "2025-10-14T10:22:56.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/db/6db8073e3d32dae017da7e0d16a9ecb897d0a4d92e00634916e486097961/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:4a9ab037b71927babc6d9e7fc01aea9e66dc2a4a34dff06ef0724a4049629f94", size = 1920387, upload-time = "2025-10-14T10:22:59.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/c1/dd3542d072fcc336030d66834872f0328727e3b8de289c662faa04aa270e/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4dab9484ec605c3016df9ad4fd4f9a390bc5d816a3b10c6550f8424bb80b18c", size = 1951495, upload-time = "2025-10-14T10:23:02.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/c6/db8d13a1f8ab3f1eb08c88bd00fd62d44311e3456d1e85c0e59e0a0376e7/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8a5028425820731d8c6c098ab642d7b8b999758e24acae03ed38a66eca8335", size = 2139008, upload-time = "2025-10-14T10:23:04.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/d4/912e976a2dd0b49f31c98a060ca90b353f3b73ee3ea2fd0030412f6ac5ec/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e5ab4fc177dd41536b3c32b2ea11380dd3d4619a385860621478ac2d25ceb00", size = 2106739, upload-time = "2025-10-14T10:23:06.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/f0/66ec5a626c81eba326072d6ee2b127f8c139543f1bf609b4842978d37833/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3d88d0054d3fa11ce936184896bed3c1c5441d6fa483b498fac6a5d0dd6f64a9", size = 1932549, upload-time = "2025-10-14T10:23:09.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/af/625626278ca801ea0a658c2dcf290dc9f21bb383098e99e7c6a029fccfc0/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2a054a8725f05b4b6503357e0ac1c4e8234ad3b0c2ac130d6ffc66f0e170e2", size = 2135093, upload-time = "2025-10-14T10:23:11.626Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/f6/2fba049f54e0f4975fef66be654c597a1d005320fa141863699180c7697d/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0d9db5a161c99375a0c68c058e227bee1d89303300802601d76a3d01f74e258", size = 2187971, upload-time = "2025-10-14T10:23:14.437Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/80/65ab839a2dfcd3b949202f9d920c34f9de5a537c3646662bdf2f7d999680/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6273ea2c8ffdac7b7fda2653c49682db815aebf4a89243a6feccf5e36c18c347", size = 2147939, upload-time = "2025-10-14T10:23:16.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/58/627565d3d182ce6dfda18b8e1c841eede3629d59c9d7cbc1e12a03aeb328/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:4c973add636efc61de22530b2ef83a65f39b6d6f656df97f678720e20de26caa", size = 2311400, upload-time = "2025-10-14T10:23:19.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/06/8a84711162ad5a5f19a88cead37cca81b4b1f294f46260ef7334ae4f24d3/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b69d1973354758007f46cf2d44a4f3d0933f10b6dc9bf15cf1356e037f6f731a", size = 2316840, upload-time = "2025-10-14T10:23:21.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/8b/b7bb512a4682a2f7fbfae152a755d37351743900226d29bd953aaf870eaa/pydantic_core-2.41.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3619320641fd212aaf5997b6ca505e97540b7e16418f4a241f44cdf108ffb50d", size = 2149135, upload-time = "2025-10-14T10:23:24.379Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/7d/138e902ed6399b866f7cfe4435d22445e16fff888a1c00560d9dc79a780f/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:491535d45cd7ad7e4a2af4a5169b0d07bebf1adfd164b0368da8aa41e19907a5", size = 2104721, upload-time = "2025-10-14T10:23:26.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/13/0525623cf94627f7b53b4c2034c81edc8491cbfc7c28d5447fa318791479/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:54d86c0cada6aba4ec4c047d0e348cbad7063b87ae0f005d9f8c9ad04d4a92a2", size = 1931608, upload-time = "2025-10-14T10:23:29.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/f9/744bc98137d6ef0a233f808bfc9b18cf94624bf30836a18d3b05d08bf418/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca1124aced216b2500dc2609eade086d718e8249cb9696660ab447d50a758bd", size = 2132986, upload-time = "2025-10-14T10:23:32.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/c8/629e88920171173f6049386cc71f893dff03209a9ef32b4d2f7e7c264bcf/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c9024169becccf0cb470ada03ee578d7348c119a0d42af3dcf9eda96e3a247c", size = 2187516, upload-time = "2025-10-14T10:23:34.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/0f/4f2734688d98488782218ca61bcc118329bf5de05bb7fe3adc7dd79b0b86/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:26895a4268ae5a2849269f4991cdc97236e4b9c010e51137becf25182daac405", size = 2146146, upload-time = "2025-10-14T10:23:37.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/f2/ab385dbd94a052c62224b99cf99002eee99dbec40e10006c78575aead256/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:ca4df25762cf71308c446e33c9b1fdca2923a3f13de616e2a949f38bf21ff5a8", size = 2311296, upload-time = "2025-10-14T10:23:40.145Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/8e/e4f12afe1beeb9823bba5375f8f258df0cc61b056b0195fb1cf9f62a1a58/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5a28fcedd762349519276c36634e71853b4541079cab4acaaac60c4421827308", size = 2315386, upload-time = "2025-10-14T10:23:42.624Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/f7/925f65d930802e3ea2eb4d5afa4cb8730c8dc0d2cb89a59dc4ed2fcb2d74/pydantic_core-2.41.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c173ddcd86afd2535e2b695217e82191580663a1d1928239f877f5a1649ef39f", size = 2147775, upload-time = "2025-10-14T10:23:45.406Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -911,14 +995,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -38,8 +38,10 @@ Each checkpointer should conform to `langgraph.checkpoint.base.BaseCheckpointSav
|
||||
- `.put_writes` - Store intermediate writes linked to a checkpoint (i.e. pending writes).
|
||||
- `.get_tuple` - Fetch a checkpoint tuple using for a given configuration (`thread_id` and `checkpoint_id`).
|
||||
- `.list` - List checkpoints that match a given configuration and filter criteria.
|
||||
- `.delete_thread()` - Delete all checkpoints and writes associated with a thread.
|
||||
- `.get_next_version()` - Generate the next version ID for a channel.
|
||||
|
||||
If the checkpointer will be used with asynchronous graph execution (i.e. executing the graph via `.ainvoke`, `.astream`, `.abatch`), checkpointer must implement asynchronous versions of the above methods (`.aput`, `.aput_writes`, `.aget_tuple`, `.alist`).
|
||||
If the checkpointer will be used with asynchronous graph execution (i.e. executing the graph via `.ainvoke`, `.astream`, `.abatch`), checkpointer must implement asynchronous versions of the above methods (`.aput`, `.aput_writes`, `.aget_tuple`, `.alist`). Similarly, the checkpointer must implement `.adelete_thread()` if asynchronous thread cleanup is desired. The base class provides a default implementation of `.get_next_version()` that generates an integer sequence starting from 1, but this method should be overridden for custom versioning schemes.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
@@ -352,11 +352,11 @@ class BaseCheckpointSaver(Generic[V]):
|
||||
def get_next_version(self, current: V | None, channel: None) -> V:
|
||||
"""Generate the next version ID for a channel.
|
||||
|
||||
Default is to use integer versions, incrementing by 1. If you override, you can use str/int/float versions,
|
||||
as long as they are monotonically increasing.
|
||||
Default is to use integer versions, incrementing by `1`. If you override, you can use `str`/`int`/`float`
|
||||
versions, as long as they are monotonically increasing.
|
||||
|
||||
Args:
|
||||
current: The current version identifier (int, float, or str).
|
||||
current: The current version identifier (`int`, `float`, or `str`).
|
||||
channel: Deprecated argument, kept for backwards compatibility.
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -42,7 +42,7 @@ class InMemorySaver(
|
||||
If you are using LangSmith Deployment, no checkpointer needs to be specified. The correct managed checkpointer will be used automatically.
|
||||
|
||||
Args:
|
||||
serde: The serializer to use for serializing and deserializing checkpoints. Defaults to None.
|
||||
serde: The serializer to use for serializing and deserializing checkpoints.
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Protocol
|
||||
from typing import Any, Protocol, runtime_checkable
|
||||
|
||||
|
||||
class UntypedSerializerProtocol(Protocol):
|
||||
@@ -11,13 +11,14 @@ class UntypedSerializerProtocol(Protocol):
|
||||
def loads(self, data: bytes) -> Any: ...
|
||||
|
||||
|
||||
class SerializerProtocol(UntypedSerializerProtocol, Protocol):
|
||||
@runtime_checkable
|
||||
class SerializerProtocol(Protocol):
|
||||
"""Protocol for serialization and deserialization of objects.
|
||||
|
||||
- `dumps`: Serialize an object to bytes.
|
||||
- `dumps_typed`: Serialize an object to a tuple (type, bytes).
|
||||
- `dumps_typed`: Serialize an object to a tuple `(type, bytes)`.
|
||||
- `loads`: Deserialize an object from bytes.
|
||||
- `loads_typed`: Deserialize an object from a tuple (type, bytes).
|
||||
- `loads_typed`: Deserialize an object from a tuple `(type, bytes)`.
|
||||
|
||||
Valid implementations include the `pickle`, `json` and `orjson` modules.
|
||||
"""
|
||||
@@ -31,12 +32,6 @@ class SerializerCompat(SerializerProtocol):
|
||||
def __init__(self, serde: UntypedSerializerProtocol) -> None:
|
||||
self.serde = serde
|
||||
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
return self.serde.dumps(obj)
|
||||
|
||||
def loads(self, data: bytes) -> Any:
|
||||
return self.serde.loads(data)
|
||||
|
||||
def dumps_typed(self, obj: Any) -> tuple[str, bytes]:
|
||||
return type(obj).__name__, self.serde.dumps(obj)
|
||||
|
||||
@@ -49,7 +44,7 @@ def maybe_add_typed_methods(
|
||||
) -> SerializerProtocol:
|
||||
"""Wrap serde old serde implementations in a class with loads_typed and dumps_typed for backwards compatibility."""
|
||||
|
||||
if not hasattr(serde, "loads_typed") or not hasattr(serde, "dumps_typed"):
|
||||
if not isinstance(serde, SerializerProtocol):
|
||||
return SerializerCompat(serde)
|
||||
|
||||
return serde
|
||||
|
||||
@@ -14,14 +14,8 @@ class EncryptedSerializer(SerializerProtocol):
|
||||
self.cipher = cipher
|
||||
self.serde = serde
|
||||
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
return self.serde.dumps(obj)
|
||||
|
||||
def loads(self, data: bytes) -> Any:
|
||||
return self.serde.loads(data)
|
||||
|
||||
def dumps_typed(self, obj: Any) -> tuple[str, bytes]:
|
||||
"""Serialize an object to a tuple (type, bytes) and encrypt the bytes."""
|
||||
"""Serialize an object to a tuple `(type, bytes)` and encrypt the bytes."""
|
||||
# serialize data
|
||||
typ, data = self.serde.dumps_typed(obj)
|
||||
# encrypt data
|
||||
@@ -45,7 +39,7 @@ class EncryptedSerializer(SerializerProtocol):
|
||||
def from_pycryptodome_aes(
|
||||
cls, serde: SerializerProtocol = JsonPlusSerializer(), **kwargs: Any
|
||||
) -> "EncryptedSerializer":
|
||||
"""Create an EncryptedSerializer using AES encryption."""
|
||||
"""Create an `EncryptedSerializer` using AES encryption."""
|
||||
try:
|
||||
from Crypto.Cipher import AES # type: ignore
|
||||
except ImportError:
|
||||
|
||||
@@ -4,6 +4,7 @@ import dataclasses
|
||||
import decimal
|
||||
import importlib
|
||||
import json
|
||||
import logging
|
||||
import pathlib
|
||||
import pickle
|
||||
import re
|
||||
@@ -21,13 +22,12 @@ from ipaddress import (
|
||||
IPv6Interface,
|
||||
IPv6Network,
|
||||
)
|
||||
from typing import Any, cast
|
||||
from typing import Any, Literal
|
||||
from uuid import UUID
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import ormsgpack
|
||||
from langchain_core.load.load import Reviver
|
||||
from langchain_core.load.serializable import Serializable
|
||||
|
||||
from langgraph.checkpoint.serde.base import SerializerProtocol
|
||||
from langgraph.checkpoint.serde.types import SendProtocol
|
||||
@@ -35,18 +35,31 @@ from langgraph.store.base import Item
|
||||
|
||||
LC_REVIVER = Reviver()
|
||||
EMPTY_BYTES = b""
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class JsonPlusSerializer(SerializerProtocol):
|
||||
"""Serializer that uses ormsgpack, with a fallback to extended JSON serializer."""
|
||||
"""Serializer that uses ormsgpack, with optional fallbacks.
|
||||
|
||||
Security note: this serializer is intended for use within the BaseCheckpointSaver
|
||||
class and called within the Pregel loop. It should not be used on untrusted
|
||||
python objects. If an attacker can write directly to your checkpoint database,
|
||||
they may be able to trigger code execution when data is deserialized.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
pickle_fallback: bool = False,
|
||||
allowed_json_modules: Sequence[tuple[str, ...]] | Literal[True] | None = None,
|
||||
__unpack_ext_hook__: Callable[[int, bytes], Any] | None = None,
|
||||
) -> None:
|
||||
self.pickle_fallback = pickle_fallback
|
||||
self._allowed_modules = (
|
||||
{mod_and_name for mod_and_name in allowed_json_modules}
|
||||
if allowed_json_modules and allowed_json_modules is not True
|
||||
else (allowed_json_modules if allowed_json_modules is True else None)
|
||||
)
|
||||
self._unpack_ext_hook = (
|
||||
__unpack_ext_hook__
|
||||
if __unpack_ext_hook__ is not None
|
||||
@@ -74,134 +87,90 @@ class JsonPlusSerializer(SerializerProtocol):
|
||||
out["kwargs"] = kwargs
|
||||
return out
|
||||
|
||||
def _default(self, obj: Any) -> str | dict[str, Any]:
|
||||
if isinstance(obj, Serializable):
|
||||
return cast(dict[str, Any], obj.to_json())
|
||||
elif hasattr(obj, "model_dump") and callable(obj.model_dump):
|
||||
return self._encode_constructor_args(
|
||||
obj.__class__, method=(None, "model_construct"), kwargs=obj.model_dump()
|
||||
)
|
||||
elif hasattr(obj, "dict") and callable(obj.dict):
|
||||
return self._encode_constructor_args(
|
||||
obj.__class__, method=(None, "construct"), kwargs=obj.dict()
|
||||
)
|
||||
elif hasattr(obj, "_asdict") and callable(obj._asdict):
|
||||
return self._encode_constructor_args(obj.__class__, kwargs=obj._asdict())
|
||||
elif isinstance(obj, pathlib.Path):
|
||||
return self._encode_constructor_args(pathlib.Path, args=obj.parts)
|
||||
elif isinstance(obj, re.Pattern):
|
||||
return self._encode_constructor_args(
|
||||
re.compile, args=(obj.pattern, obj.flags)
|
||||
)
|
||||
elif isinstance(obj, UUID):
|
||||
return self._encode_constructor_args(UUID, args=(obj.hex,))
|
||||
elif isinstance(obj, decimal.Decimal):
|
||||
return self._encode_constructor_args(decimal.Decimal, args=(str(obj),))
|
||||
elif isinstance(obj, (set, frozenset, deque)):
|
||||
return self._encode_constructor_args(type(obj), args=(tuple(obj),))
|
||||
elif isinstance(obj, (IPv4Address, IPv4Interface, IPv4Network)):
|
||||
return self._encode_constructor_args(obj.__class__, args=(str(obj),))
|
||||
elif isinstance(obj, (IPv6Address, IPv6Interface, IPv6Network)):
|
||||
return self._encode_constructor_args(obj.__class__, args=(str(obj),))
|
||||
|
||||
elif isinstance(obj, datetime):
|
||||
return self._encode_constructor_args(
|
||||
datetime, method="fromisoformat", args=(obj.isoformat(),)
|
||||
)
|
||||
elif isinstance(obj, timezone):
|
||||
return self._encode_constructor_args(
|
||||
timezone,
|
||||
args=obj.__getinitargs__(), # type: ignore[attr-defined]
|
||||
)
|
||||
elif isinstance(obj, ZoneInfo):
|
||||
return self._encode_constructor_args(ZoneInfo, args=(obj.key,))
|
||||
elif isinstance(obj, timedelta):
|
||||
return self._encode_constructor_args(
|
||||
timedelta, args=(obj.days, obj.seconds, obj.microseconds)
|
||||
)
|
||||
elif isinstance(obj, date):
|
||||
return self._encode_constructor_args(
|
||||
date, args=(obj.year, obj.month, obj.day)
|
||||
)
|
||||
elif isinstance(obj, time):
|
||||
return self._encode_constructor_args(
|
||||
time,
|
||||
args=(obj.hour, obj.minute, obj.second, obj.microsecond, obj.tzinfo),
|
||||
kwargs={"fold": obj.fold},
|
||||
)
|
||||
elif dataclasses.is_dataclass(obj):
|
||||
return self._encode_constructor_args(
|
||||
obj.__class__,
|
||||
kwargs={
|
||||
field.name: getattr(obj, field.name)
|
||||
for field in dataclasses.fields(obj)
|
||||
},
|
||||
)
|
||||
elif isinstance(obj, Enum):
|
||||
return self._encode_constructor_args(obj.__class__, args=(obj.value,))
|
||||
elif isinstance(obj, SendProtocol):
|
||||
return self._encode_constructor_args(
|
||||
obj.__class__, kwargs={"node": obj.node, "arg": obj.arg}
|
||||
)
|
||||
elif isinstance(obj, (bytes, bytearray)):
|
||||
return self._encode_constructor_args(
|
||||
obj.__class__, method="fromhex", args=(obj.hex(),)
|
||||
)
|
||||
elif isinstance(obj, BaseException):
|
||||
return repr(obj)
|
||||
else:
|
||||
raise TypeError(
|
||||
f"Object of type {obj.__class__.__name__} is not JSON serializable"
|
||||
)
|
||||
|
||||
def _reviver(self, value: dict[str, Any]) -> Any:
|
||||
if (
|
||||
if self._allowed_modules and (
|
||||
value.get("lc", None) == 2
|
||||
and value.get("type", None) == "constructor"
|
||||
and value.get("id", None) is not None
|
||||
):
|
||||
try:
|
||||
# Get module and class name
|
||||
[*module, name] = value["id"]
|
||||
# Import module
|
||||
mod = importlib.import_module(".".join(module))
|
||||
# Import class
|
||||
cls = getattr(mod, name)
|
||||
# Instantiate class
|
||||
method = value.get("method")
|
||||
if isinstance(method, str):
|
||||
methods = [getattr(cls, method)]
|
||||
elif isinstance(method, list):
|
||||
methods = [
|
||||
cls if method is None else getattr(cls, method)
|
||||
for method in method
|
||||
]
|
||||
else:
|
||||
methods = [cls]
|
||||
args = value.get("args")
|
||||
kwargs = value.get("kwargs")
|
||||
for method in methods:
|
||||
try:
|
||||
if isclass(method) and issubclass(method, BaseException):
|
||||
return None
|
||||
if args and kwargs:
|
||||
return method(*args, **kwargs)
|
||||
elif args:
|
||||
return method(*args)
|
||||
elif kwargs:
|
||||
return method(**kwargs)
|
||||
else:
|
||||
return method()
|
||||
except Exception:
|
||||
continue
|
||||
except Exception:
|
||||
return None
|
||||
return self._revive_lc2(value)
|
||||
except InvalidModuleError as e:
|
||||
logger.warning(
|
||||
"Object %s is not in the deserialization allowlist.\n%s",
|
||||
value["id"],
|
||||
e.message,
|
||||
)
|
||||
|
||||
return LC_REVIVER(value)
|
||||
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
return json.dumps(obj, default=self._default, ensure_ascii=False).encode(
|
||||
"utf-8", "ignore"
|
||||
def _revive_lc2(self, value: dict[str, Any]) -> Any:
|
||||
self._check_allowed_modules(value)
|
||||
|
||||
[*module, name] = value["id"]
|
||||
try:
|
||||
mod = importlib.import_module(".".join(module))
|
||||
cls = getattr(mod, name)
|
||||
method = value.get("method")
|
||||
if isinstance(method, str):
|
||||
methods = [getattr(cls, method)]
|
||||
elif isinstance(method, list):
|
||||
methods = [cls if m is None else getattr(cls, m) for m in method]
|
||||
else:
|
||||
methods = [cls]
|
||||
args = value.get("args")
|
||||
kwargs = value.get("kwargs")
|
||||
for method in methods:
|
||||
try:
|
||||
if isclass(method) and issubclass(method, BaseException):
|
||||
return None
|
||||
if args and kwargs:
|
||||
return method(*args, **kwargs)
|
||||
elif args:
|
||||
return method(*args)
|
||||
elif kwargs:
|
||||
return method(**kwargs)
|
||||
else:
|
||||
return method()
|
||||
except Exception:
|
||||
continue
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
def _check_allowed_modules(self, value: dict[str, Any]) -> None:
|
||||
needed = tuple(value["id"])
|
||||
method = value.get("method")
|
||||
if isinstance(method, list):
|
||||
method_display = ",".join(m or "<init>" for m in method)
|
||||
elif isinstance(method, str):
|
||||
method_display = method
|
||||
else:
|
||||
method_display = "<init>"
|
||||
|
||||
dotted = ".".join(needed)
|
||||
if not self._allowed_modules:
|
||||
raise InvalidModuleError(
|
||||
f"Refused to deserialize JSON constructor: {dotted} (method: {method_display}). "
|
||||
"No allowed_json_modules configured.\n\n"
|
||||
"Unblock with ONE of:\n"
|
||||
f" • JsonPlusSerializer(allowed_json_modules=[{needed!r}, ...])\n"
|
||||
" • (DANGEROUS) JsonPlusSerializer(allowed_json_modules=True)\n\n"
|
||||
"Note: Prefix allowlists are intentionally unsupported; prefer exact symbols "
|
||||
"or plain-JSON representations revived without import-time side effects."
|
||||
)
|
||||
|
||||
if self._allowed_modules is True:
|
||||
return
|
||||
if needed in self._allowed_modules:
|
||||
return
|
||||
|
||||
raise InvalidModuleError(
|
||||
f"Refused to deserialize JSON constructor: {dotted} (method: {method_display}). "
|
||||
"Symbol is not in the deserialization allowlist.\n\n"
|
||||
"Add exactly this symbol to unblock:\n"
|
||||
f" JsonPlusSerializer(allowed_json_modules=[{needed!r}, ...])\n"
|
||||
"Or, as a last resort (DANGEROUS):\n"
|
||||
" JsonPlusSerializer(allowed_json_modules=True)"
|
||||
)
|
||||
|
||||
def dumps_typed(self, obj: Any) -> tuple[str, bytes]:
|
||||
@@ -215,15 +184,10 @@ class JsonPlusSerializer(SerializerProtocol):
|
||||
try:
|
||||
return "msgpack", _msgpack_enc(obj)
|
||||
except ormsgpack.MsgpackEncodeError as exc:
|
||||
if "valid UTF-8" in str(exc):
|
||||
return "json", self.dumps(obj)
|
||||
elif self.pickle_fallback:
|
||||
if self.pickle_fallback:
|
||||
return "pickle", pickle.dumps(obj)
|
||||
raise exc
|
||||
|
||||
def loads(self, data: bytes) -> Any:
|
||||
return json.loads(data, object_hook=self._reviver)
|
||||
|
||||
def loads_typed(self, data: tuple[str, bytes]) -> Any:
|
||||
type_, data_ = data
|
||||
if type_ == "null":
|
||||
@@ -233,7 +197,7 @@ class JsonPlusSerializer(SerializerProtocol):
|
||||
elif type_ == "bytearray":
|
||||
return bytearray(data_)
|
||||
elif type_ == "json":
|
||||
return self.loads(data_)
|
||||
return json.loads(data_, object_hook=self._reviver)
|
||||
elif type_ == "msgpack":
|
||||
return ormsgpack.unpackb(
|
||||
data_, ext_hook=self._unpack_ext_hook, option=ormsgpack.OPT_NON_STR_KEYS
|
||||
@@ -663,12 +627,20 @@ def _msgpack_ext_hook_to_json(code: int, data: bytes) -> Any:
|
||||
return
|
||||
|
||||
|
||||
class InvalidModuleError(Exception):
|
||||
"""Exception raised when a module is not in the allowlist."""
|
||||
|
||||
def __init__(self, message: str):
|
||||
self.message = message
|
||||
|
||||
|
||||
_option = (
|
||||
ormsgpack.OPT_NON_STR_KEYS
|
||||
| ormsgpack.OPT_PASSTHROUGH_DATACLASS
|
||||
| ormsgpack.OPT_PASSTHROUGH_DATETIME
|
||||
| ormsgpack.OPT_PASSTHROUGH_ENUM
|
||||
| ormsgpack.OPT_PASSTHROUGH_UUID
|
||||
| ormsgpack.OPT_REPLACE_SURROGATES
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ Stores provide long-term memory that persists across threads and conversations.
|
||||
Supports hierarchical namespaces, key-value storage, and optional vector search.
|
||||
|
||||
Core types:
|
||||
- BaseStore: Store interface with sync/async operations
|
||||
- Item: Stored key-value pairs with metadata
|
||||
- Op: Get/Put/Search/List operations
|
||||
- `BaseStore`: Store interface with sync/async operations
|
||||
- `Item`: Stored key-value pairs with metadata
|
||||
- `Op`: Get/Put/Search/List operations
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -163,6 +163,7 @@ class GetOp(NamedTuple):
|
||||
???+ example "Examples"
|
||||
|
||||
Basic item retrieval:
|
||||
|
||||
```python
|
||||
GetOp(namespace=("users", "profiles"), key="user123")
|
||||
GetOp(namespace=("cache", "embeddings"), key="doc456")
|
||||
@@ -206,11 +207,14 @@ class SearchOp(NamedTuple):
|
||||
within a given namespace prefix. It provides pagination through limit and offset
|
||||
parameters.
|
||||
|
||||
Note:
|
||||
!!! note
|
||||
|
||||
Natural language search support depends on your store implementation.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Search with filters and pagination:
|
||||
|
||||
```python
|
||||
SearchOp(
|
||||
namespace_prefix=("documents",),
|
||||
@@ -221,6 +225,7 @@ class SearchOp(NamedTuple):
|
||||
```
|
||||
|
||||
Natural language search:
|
||||
|
||||
```python
|
||||
SearchOp(
|
||||
namespace_prefix=("users", "content"),
|
||||
@@ -256,6 +261,7 @@ class SearchOp(NamedTuple):
|
||||
- `$lte`: Less than or equal to
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Simple exact match:
|
||||
|
||||
```python
|
||||
@@ -288,6 +294,7 @@ class SearchOp(NamedTuple):
|
||||
"""Natural language search query for semantic search capabilities.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
- "technical documentation about REST APIs"
|
||||
- "machine learning papers from 2023"
|
||||
"""
|
||||
@@ -305,6 +312,7 @@ NamespacePath = tuple[str | Literal["*"], ...]
|
||||
"""A tuple representing a namespace path that can include wildcards.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
("users",) # Exact users namespace
|
||||
("documents", "*") # Any sub-namespace under documents
|
||||
@@ -330,17 +338,21 @@ class MatchCondition(NamedTuple):
|
||||
hierarchies.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Prefix matching:
|
||||
|
||||
```python
|
||||
MatchCondition(match_type="prefix", path=("users", "profiles"))
|
||||
```
|
||||
|
||||
Suffix matching with wildcard:
|
||||
|
||||
```python
|
||||
MatchCondition(match_type="suffix", path=("cache", "*"))
|
||||
```
|
||||
|
||||
Simple suffix matching:
|
||||
|
||||
```python
|
||||
MatchCondition(match_type="suffix", path=("v1",))
|
||||
```
|
||||
@@ -361,7 +373,8 @@ class ListNamespacesOp(NamedTuple):
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
List all namespaces under the "documents" path:
|
||||
List all namespaces under the `"documents"` path:
|
||||
|
||||
```python
|
||||
ListNamespacesOp(
|
||||
match_conditions=(MatchCondition(match_type="prefix", path=("documents",)),),
|
||||
@@ -369,7 +382,8 @@ class ListNamespacesOp(NamedTuple):
|
||||
)
|
||||
```
|
||||
|
||||
List all namespaces that end with "v1":
|
||||
List all namespaces that end with `"v1"`:
|
||||
|
||||
```python
|
||||
ListNamespacesOp(
|
||||
match_conditions=(MatchCondition(match_type="suffix", path=("v1",)),),
|
||||
@@ -383,12 +397,15 @@ class ListNamespacesOp(NamedTuple):
|
||||
"""Optional conditions for filtering namespaces.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
All user namespaces:
|
||||
|
||||
```python
|
||||
(MatchCondition(match_type="prefix", path=("users",)),)
|
||||
```
|
||||
|
||||
All namespaces that start with "docs" and end with "draft":
|
||||
All namespaces that start with `"docs"` and end with `"draft"`:
|
||||
|
||||
```python
|
||||
(
|
||||
MatchCondition(match_type="prefix", path=("docs",)),
|
||||
@@ -425,17 +442,21 @@ class PutOp(NamedTuple):
|
||||
Each element in the tuple represents one level in the hierarchy.
|
||||
|
||||
???+ example "Examples"
|
||||
Root level documents
|
||||
|
||||
Root level documents:
|
||||
|
||||
```python
|
||||
("documents",)
|
||||
```
|
||||
|
||||
User-specific documents
|
||||
User-specific documents:
|
||||
|
||||
```python
|
||||
("documents", "user123")
|
||||
```
|
||||
|
||||
Nested cache structure
|
||||
Nested cache structure:
|
||||
|
||||
```python
|
||||
("cache", "embeddings", "v1")
|
||||
```
|
||||
@@ -448,15 +469,15 @@ class PutOp(NamedTuple):
|
||||
Together with the namespace, it forms a complete path to the item.
|
||||
|
||||
Example:
|
||||
If namespace is ("documents", "user123") and key is "report1",
|
||||
the full path would effectively be "documents/user123/report1"
|
||||
If namespace is `("documents", "user123")` and key is `"report1"`,
|
||||
the full path would effectively be `"documents/user123/report1"`
|
||||
"""
|
||||
|
||||
value: dict[str, Any] | None
|
||||
"""The data to store, or None to mark the item for deletion.
|
||||
"""The data to store, or `None` to mark the item for deletion.
|
||||
|
||||
The value must be a dictionary with string keys and JSON-serializable values.
|
||||
Setting this to None signals that the item should be deleted.
|
||||
Setting this to `None` signals that the item should be deleted.
|
||||
|
||||
Example:
|
||||
{
|
||||
@@ -470,9 +491,9 @@ class PutOp(NamedTuple):
|
||||
"""Controls how the item's fields are indexed for search operations.
|
||||
|
||||
Indexing configuration determines how the item can be found through search:
|
||||
- None (default): Uses the store's default indexing configuration (if provided)
|
||||
- False: Disables indexing for this item
|
||||
- list[str]: Specifies which json path fields to index for search
|
||||
- `None` (default): Uses the store's default indexing configuration (if provided)
|
||||
- `False`: Disables indexing for this item
|
||||
- `list[str]`: Specifies which json path fields to index for search
|
||||
|
||||
The item remains accessible through direct get() operations regardless of indexing.
|
||||
When indexed, fields can be searched using natural language queries through
|
||||
@@ -487,8 +508,9 @@ class PutOp(NamedTuple):
|
||||
- All elements (each individually): `"array[*]"`
|
||||
|
||||
???+ example "Examples"
|
||||
- None - Use store defaults (whole item)
|
||||
- list[str] - List of fields to index
|
||||
|
||||
- `None` - Use store defaults (whole item)
|
||||
- `list[str]` - List of fields to index
|
||||
|
||||
```python
|
||||
[
|
||||
@@ -569,13 +591,15 @@ class IndexConfig(TypedDict, total=False):
|
||||
"""Optional function to generate embeddings from text.
|
||||
|
||||
Can be specified in three ways:
|
||||
1. A LangChain Embeddings instance
|
||||
1. A LangChain `Embeddings` instance
|
||||
2. A synchronous embedding function (`EmbeddingsFunc`)
|
||||
3. An asynchronous embedding function (`AEmbeddingsFunc`)
|
||||
4. A provider string (e.g., `"openai:text-embedding-3-small"`)
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Using LangChain's initialization with `InMemoryStore`:
|
||||
|
||||
```python
|
||||
from langchain.embeddings import init_embeddings
|
||||
from langgraph.store.memory import InMemoryStore
|
||||
@@ -589,6 +613,7 @@ class IndexConfig(TypedDict, total=False):
|
||||
```
|
||||
|
||||
Using a custom embedding function with `InMemoryStore`:
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from langgraph.store.memory import InMemoryStore
|
||||
@@ -611,6 +636,7 @@ class IndexConfig(TypedDict, total=False):
|
||||
```
|
||||
|
||||
Using an asynchronous embedding function with `InMemoryStore`:
|
||||
|
||||
```python
|
||||
from openai import AsyncOpenAI
|
||||
from langgraph.store.memory import InMemoryStore
|
||||
@@ -648,6 +674,7 @@ class IndexConfig(TypedDict, total=False):
|
||||
`index` parameter in the `put` or `aput` operations.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
# Embed entire document (default)
|
||||
fields=["$"]
|
||||
@@ -731,7 +758,7 @@ class BaseStore(ABC):
|
||||
namespace: Hierarchical path for the item.
|
||||
key: Unique identifier within the namespace.
|
||||
refresh_ttl: Whether to refresh TTLs for the returned item.
|
||||
If `None`, uses the store's default refresh_ttl setting.
|
||||
If `None`, uses the store's default `refresh_ttl` setting.
|
||||
If no TTL is specified, this argument is ignored.
|
||||
|
||||
Returns:
|
||||
@@ -767,7 +794,9 @@ class BaseStore(ABC):
|
||||
List of items matching the search criteria.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Basic filtering:
|
||||
|
||||
```python
|
||||
# Search for documents with specific metadata
|
||||
results = store.search(
|
||||
@@ -777,6 +806,7 @@ class BaseStore(ABC):
|
||||
```
|
||||
|
||||
Natural language search (requires vector store implementation):
|
||||
|
||||
```python
|
||||
# Initialize store with embedding configuration
|
||||
store = YourStore( # e.g., InMemoryStore, AsyncPostgresStore
|
||||
@@ -788,6 +818,7 @@ class BaseStore(ABC):
|
||||
)
|
||||
|
||||
# Search for semantically similar documents
|
||||
|
||||
results = store.search(
|
||||
("docs",),
|
||||
query="machine learning applications in healthcare",
|
||||
@@ -796,8 +827,10 @@ class BaseStore(ABC):
|
||||
)
|
||||
```
|
||||
|
||||
Note: Natural language search support depends on your store implementation
|
||||
and requires proper embedding configuration.
|
||||
!!! note
|
||||
|
||||
Natural language search support depends on your store implementation
|
||||
and requires proper embedding configuration.
|
||||
"""
|
||||
return self.batch(
|
||||
[
|
||||
@@ -825,7 +858,7 @@ class BaseStore(ABC):
|
||||
|
||||
Args:
|
||||
namespace: Hierarchical path for the item, represented as a tuple of strings.
|
||||
Example: ("documents", "user123")
|
||||
Example: `("documents", "user123")`
|
||||
key: Unique identifier within the namespace. Together with namespace forms
|
||||
the complete path to the item.
|
||||
value: Dictionary containing the item's data. Must contain string keys
|
||||
@@ -836,10 +869,10 @@ class BaseStore(ABC):
|
||||
If you do not initialize the store with indexing capabilities,
|
||||
the `index` parameter will be ignored
|
||||
- False: Disable indexing for this item
|
||||
- list[str]: List of field paths to index, supporting:
|
||||
- Nested fields: "metadata.title"
|
||||
- Array access: "chapters[*].content" (each indexed separately)
|
||||
- Specific indices: "authors[0].name"
|
||||
- `list[str]`: List of field paths to index, supporting:
|
||||
- Nested fields: `"metadata.title"`
|
||||
- Array access: `"chapters[*].content"` (each indexed separately)
|
||||
- Specific indices: `"authors[0].name"`
|
||||
ttl: Time to live in minutes. Support for this argument depends on your store adapter.
|
||||
If specified, the item will expire after this many minutes from when it was last accessed.
|
||||
None means no expiration. Expired runs will be deleted opportunistically.
|
||||
@@ -855,18 +888,22 @@ class BaseStore(ABC):
|
||||
Some implementations may not support expiration of items.
|
||||
|
||||
???+ example "Examples"
|
||||
Store item. Indexing depends on how you configure the store.
|
||||
|
||||
Store item. Indexing depends on how you configure the store:
|
||||
|
||||
```python
|
||||
store.put(("docs",), "report", {"memory": "Will likes ai"})
|
||||
```
|
||||
|
||||
Do not index item for semantic search. Still accessible through get()
|
||||
and search() operations but won't have a vector representation.
|
||||
Do not index item for semantic search. Still accessible through `get()`
|
||||
and `search()` operations but won't have a vector representation.
|
||||
|
||||
```python
|
||||
store.put(("docs",), "report", {"memory": "Will likes ai"}, index=False)
|
||||
```
|
||||
|
||||
Index specific fields for search.
|
||||
Index specific fields for search:
|
||||
|
||||
```python
|
||||
store.put(("docs",), "report", {"memory": "Will likes ai"}, index=["memory"])
|
||||
```
|
||||
@@ -917,15 +954,17 @@ class BaseStore(ABC):
|
||||
suffix: Filter namespaces that end with this path.
|
||||
max_depth: Return namespaces up to this depth in the hierarchy.
|
||||
Namespaces deeper than this level will be truncated.
|
||||
limit: Maximum number of namespaces to return (default 100).
|
||||
offset: Number of namespaces to skip for pagination (default 0).
|
||||
limit: Maximum number of namespaces to return.
|
||||
offset: Number of namespaces to skip for pagination.
|
||||
|
||||
Returns:
|
||||
List[Tuple[str, ...]]: A list of namespace tuples that match the criteria.
|
||||
Each tuple represents a full namespace path up to `max_depth`.
|
||||
A list of namespace tuples that match the criteria. Each tuple represents a
|
||||
full namespace path up to `max_depth`.
|
||||
|
||||
???+ example "Examples":
|
||||
Setting max_depth=3. Given the namespaces:
|
||||
|
||||
Setting `max_depth=3`. Given the namespaces:
|
||||
|
||||
```python
|
||||
# Example if you have the following namespaces:
|
||||
# ("a", "b", "c")
|
||||
@@ -999,14 +1038,16 @@ class BaseStore(ABC):
|
||||
limit: Maximum number of items to return.
|
||||
offset: Number of items to skip before returning results.
|
||||
refresh_ttl: Whether to refresh TTLs for the returned items.
|
||||
If `None`, uses the store's TTLConfig.refresh_default setting.
|
||||
If TTLConfig is not provided or no TTL is specified, this argument is ignored.
|
||||
If `None`, uses the store's `TTLConfig.refresh_default` setting.
|
||||
If `TTLConfig` is not provided or no TTL is specified, this argument is ignored.
|
||||
|
||||
Returns:
|
||||
List of items matching the search criteria.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Basic filtering:
|
||||
|
||||
```python
|
||||
# Search for documents with specific metadata
|
||||
results = await store.asearch(
|
||||
@@ -1016,6 +1057,7 @@ class BaseStore(ABC):
|
||||
```
|
||||
|
||||
Natural language search (requires vector store implementation):
|
||||
|
||||
```python
|
||||
# Initialize store with embedding configuration
|
||||
store = YourStore( # e.g., InMemoryStore, AsyncPostgresStore
|
||||
@@ -1027,6 +1069,7 @@ class BaseStore(ABC):
|
||||
)
|
||||
|
||||
# Search for semantically similar documents
|
||||
|
||||
results = await store.asearch(
|
||||
("docs",),
|
||||
query="machine learning applications in healthcare",
|
||||
@@ -1035,8 +1078,10 @@ class BaseStore(ABC):
|
||||
)
|
||||
```
|
||||
|
||||
Note: Natural language search support depends on your store implementation
|
||||
and requires proper embedding configuration.
|
||||
!!! note
|
||||
|
||||
Natural language search support depends on your store implementation
|
||||
and requires proper embedding configuration.
|
||||
"""
|
||||
return (
|
||||
await self.abatch(
|
||||
@@ -1066,7 +1111,7 @@ class BaseStore(ABC):
|
||||
|
||||
Args:
|
||||
namespace: Hierarchical path for the item, represented as a tuple of strings.
|
||||
Example: ("documents", "user123")
|
||||
Example: `("documents", "user123")`
|
||||
key: Unique identifier within the namespace. Together with namespace forms
|
||||
the complete path to the item.
|
||||
value: Dictionary containing the item's data. Must contain string keys
|
||||
@@ -1077,10 +1122,10 @@ class BaseStore(ABC):
|
||||
If you do not initialize the store with indexing capabilities,
|
||||
the `index` parameter will be ignored
|
||||
- False: Disable indexing for this item
|
||||
- list[str]: List of field paths to index, supporting:
|
||||
- Nested fields: "metadata.title"
|
||||
- Array access: "chapters[*].content" (each indexed separately)
|
||||
- Specific indices: "authors[0].name"
|
||||
- `list[str]`: List of field paths to index, supporting:
|
||||
- Nested fields: `"metadata.title"`
|
||||
- Array access: `"chapters[*].content"` (each indexed separately)
|
||||
- Specific indices: `"authors[0].name"`
|
||||
ttl: Time to live in minutes. Support for this argument depends on your store adapter.
|
||||
If specified, the item will expire after this many minutes from when it was last accessed.
|
||||
None means no expiration. Expired runs will be deleted opportunistically.
|
||||
@@ -1096,18 +1141,22 @@ class BaseStore(ABC):
|
||||
Some implementations may not support expiration of items.
|
||||
|
||||
???+ example "Examples"
|
||||
Store item. Indexing depends on how you configure the store.
|
||||
|
||||
Store item. Indexing depends on how you configure the store:
|
||||
|
||||
```python
|
||||
await store.aput(("docs",), "report", {"memory": "Will likes ai"})
|
||||
```
|
||||
|
||||
Do not index item for semantic search. Still accessible through get()
|
||||
and search() operations but won't have a vector representation.
|
||||
Do not index item for semantic search. Still accessible through `get()`
|
||||
and `search()` operations but won't have a vector representation.
|
||||
|
||||
```python
|
||||
await store.aput(("docs",), "report", {"memory": "Will likes ai"}, index=False)
|
||||
```
|
||||
|
||||
Index specific fields for search (if store configured to index items):
|
||||
|
||||
```python
|
||||
await store.aput(
|
||||
("docs",),
|
||||
@@ -1166,15 +1215,16 @@ class BaseStore(ABC):
|
||||
suffix: Filter namespaces that end with this path.
|
||||
max_depth: Return namespaces up to this depth in the hierarchy.
|
||||
Namespaces deeper than this level will be truncated to this depth.
|
||||
limit: Maximum number of namespaces to return (default 100).
|
||||
offset: Number of namespaces to skip for pagination (default 0).
|
||||
limit: Maximum number of namespaces to return.
|
||||
offset: Number of namespaces to skip for pagination.
|
||||
|
||||
Returns:
|
||||
List[Tuple[str, ...]]: A list of namespace tuples that match the criteria.
|
||||
Each tuple represents a full namespace path up to `max_depth`.
|
||||
A list of namespace tuples that match the criteria. Each tuple represents a
|
||||
full namespace path up to `max_depth`.
|
||||
|
||||
???+ example "Examples"
|
||||
Setting max_depth=3 with existing namespaces:
|
||||
|
||||
Setting `max_depth=3` with existing namespaces:
|
||||
```python
|
||||
# Given the following namespaces:
|
||||
# ("a", "b", "c")
|
||||
|
||||
@@ -49,7 +49,9 @@ def ensure_embeddings(
|
||||
An Embeddings instance that wraps the provided function(s).
|
||||
|
||||
??? example "Examples"
|
||||
|
||||
Wrap a synchronous embedding function:
|
||||
|
||||
```python
|
||||
def my_embed_fn(texts):
|
||||
return [[0.1, 0.2] for _ in texts]
|
||||
@@ -59,6 +61,7 @@ def ensure_embeddings(
|
||||
```
|
||||
|
||||
Wrap an asynchronous embedding function:
|
||||
|
||||
```python
|
||||
async def my_async_fn(texts):
|
||||
return [[0.1, 0.2] for _ in texts]
|
||||
@@ -68,6 +71,7 @@ def ensure_embeddings(
|
||||
```
|
||||
|
||||
Initialize embeddings using a provider string:
|
||||
|
||||
```python
|
||||
# Requires langchain>=0.3.9 and langgraph-checkpoint>=2.0.11
|
||||
embeddings = ensure_embeddings("openai:text-embedding-3-small")
|
||||
@@ -119,7 +123,9 @@ class EmbeddingsLambda(Embeddings):
|
||||
will raise an error. If sync, it will be used for both sync and async operations.
|
||||
|
||||
??? example "Examples"
|
||||
|
||||
With a sync function:
|
||||
|
||||
```python
|
||||
def my_embed_fn(texts):
|
||||
# Return 2D embeddings for each text
|
||||
@@ -131,6 +137,7 @@ class EmbeddingsLambda(Embeddings):
|
||||
```
|
||||
|
||||
With an async function:
|
||||
|
||||
```python
|
||||
async def my_async_fn(texts):
|
||||
return [[0.1, 0.2] for _ in texts]
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "langgraph-checkpoint"
|
||||
version = "2.1.2"
|
||||
version = "3.0.1"
|
||||
description = "Library with base interfaces for LangGraph checkpoint savers."
|
||||
authors = []
|
||||
requires-python = ">=3.10"
|
||||
@@ -13,27 +13,36 @@ license = "MIT"
|
||||
license-files = ['LICENSE']
|
||||
dependencies = [
|
||||
"langchain-core>=0.2.38",
|
||||
"ormsgpack>=1.10.0",
|
||||
"ormsgpack>=1.12.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/checkpoint"
|
||||
Twitter = "https://x.com/LangChainAI"
|
||||
Slack = "https://www.langchain.com/join-community"
|
||||
Reddit = "https://www.reddit.com/r/LangChain/"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
test = [
|
||||
"pytest",
|
||||
"pytest-asyncio",
|
||||
"pytest-mock",
|
||||
"pytest-watcher",
|
||||
"mypy",
|
||||
"dataclasses-json",
|
||||
"numpy",
|
||||
"pandas",
|
||||
"pandas-stubs>=2.2.2.240807",
|
||||
"redis",
|
||||
]
|
||||
lint = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
"mypy",
|
||||
]
|
||||
dev = [
|
||||
{include-group = "test"},
|
||||
{include-group = "lint"},
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
include = ["langgraph"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import dataclasses
|
||||
import json
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
@@ -19,6 +20,7 @@ from pydantic.v1 import BaseModel as BaseModelV1
|
||||
from pydantic.v1 import SecretStr as SecretStrV1
|
||||
|
||||
from langgraph.checkpoint.serde.jsonplus import (
|
||||
InvalidModuleError,
|
||||
JsonPlusSerializer,
|
||||
_msgpack_ext_hook_to_json,
|
||||
)
|
||||
@@ -108,11 +110,7 @@ def test_serde_jsonplus() -> None:
|
||||
"my_dataclass": MyDataclass("foo", 1, InnerDataclass("hello")),
|
||||
"my_enum": MyEnum.FOO,
|
||||
"my_pydantic": MyPydantic(foo="foo", bar=1, inner=InnerPydantic(hello="hello")),
|
||||
"my_pydantic_v1": MyPydanticV1(
|
||||
foo="foo", bar=1, inner=InnerPydanticV1(hello="hello")
|
||||
),
|
||||
"my_secret_str": SecretStr("meow"),
|
||||
"my_secret_str_v1": SecretStrV1("meow"),
|
||||
"person": Person(name="foo"),
|
||||
"a_bool": True,
|
||||
"a_none": None,
|
||||
@@ -134,6 +132,12 @@ def test_serde_jsonplus() -> None:
|
||||
),
|
||||
}
|
||||
|
||||
if sys.version_info < (3, 14):
|
||||
to_serialize["my_pydantic_v1"] = MyPydanticV1(
|
||||
foo="foo", bar=1, inner=InnerPydanticV1(hello="hello")
|
||||
)
|
||||
to_serialize["my_secret_str_v1"] = SecretStrV1("meow")
|
||||
|
||||
serde = JsonPlusSerializer()
|
||||
|
||||
dumped = serde.dumps_typed(to_serialize)
|
||||
@@ -145,23 +149,22 @@ def test_serde_jsonplus() -> None:
|
||||
assert serde.loads_typed(serde.dumps_typed(value)) == value
|
||||
|
||||
surrogates = [
|
||||
"Hello\ud83d\ude00",
|
||||
"Python\ud83d\udc0d",
|
||||
"Surrogate\ud834\udd1e",
|
||||
"Example\ud83c\udf89",
|
||||
"String\ud83c\udfa7",
|
||||
"With\ud83c\udf08",
|
||||
"Surrogates\ud83d\ude0e",
|
||||
"Embedded\ud83d\udcbb",
|
||||
"In\ud83c\udf0e",
|
||||
"The\ud83d\udcd6",
|
||||
"Text\ud83d\udcac",
|
||||
"Hello??",
|
||||
"Python??",
|
||||
"Surrogate??",
|
||||
"Example??",
|
||||
"String??",
|
||||
"With??",
|
||||
"Surrogates??",
|
||||
"Embedded??",
|
||||
"In??",
|
||||
"The??",
|
||||
"Text??",
|
||||
"收花🙄·到",
|
||||
]
|
||||
serde = JsonPlusSerializer(pickle_fallback=False)
|
||||
|
||||
assert serde.loads_typed(serde.dumps_typed(surrogates)) == [
|
||||
v.encode("utf-8", "ignore").decode() for v in surrogates
|
||||
]
|
||||
assert serde.loads_typed(serde.dumps_typed(surrogates)) == surrogates
|
||||
|
||||
|
||||
def test_serde_jsonplus_json_mode() -> None:
|
||||
@@ -190,11 +193,7 @@ def test_serde_jsonplus_json_mode() -> None:
|
||||
"my_dataclass": MyDataclass("foo", 1, InnerDataclass("hello")),
|
||||
"my_enum": MyEnum.FOO,
|
||||
"my_pydantic": MyPydantic(foo="foo", bar=1, inner=InnerPydantic(hello="hello")),
|
||||
"my_pydantic_v1": MyPydanticV1(
|
||||
foo="foo", bar=1, inner=InnerPydanticV1(hello="hello")
|
||||
),
|
||||
"my_secret_str": SecretStr("meow"),
|
||||
"my_secret_str_v1": SecretStrV1("meow"),
|
||||
"person": Person(name="foo"),
|
||||
"a_bool": True,
|
||||
"a_none": None,
|
||||
@@ -216,13 +215,20 @@ def test_serde_jsonplus_json_mode() -> None:
|
||||
),
|
||||
}
|
||||
|
||||
if sys.version_info < (3, 14):
|
||||
to_serialize["my_pydantic_v1"] = MyPydanticV1(
|
||||
foo="foo", bar=1, inner=InnerPydanticV1(hello="hello")
|
||||
)
|
||||
to_serialize["my_secret_str_v1"] = SecretStrV1("meow")
|
||||
|
||||
serde = JsonPlusSerializer(__unpack_ext_hook__=_msgpack_ext_hook_to_json)
|
||||
|
||||
dumped = serde.dumps_typed(to_serialize)
|
||||
|
||||
assert dumped[0] == "msgpack"
|
||||
result = serde.loads_typed(dumped)
|
||||
assert result == {
|
||||
|
||||
expected_result = {
|
||||
"path": ["foo", "bar"],
|
||||
"re": ["foo", 48],
|
||||
"decimal": "1.10101",
|
||||
@@ -246,9 +252,7 @@ def test_serde_jsonplus_json_mode() -> None:
|
||||
"my_dataclass": {"foo": "foo", "bar": 1, "inner": {"hello": "hello"}},
|
||||
"my_enum": "foo",
|
||||
"my_pydantic": {"foo": "foo", "bar": 1, "inner": {"hello": "hello"}},
|
||||
"my_pydantic_v1": {"foo": "foo", "bar": 1, "inner": {"hello": "hello"}},
|
||||
"my_secret_str": "meow",
|
||||
"my_secret_str_v1": "meow",
|
||||
"person": {"name": "foo"},
|
||||
"a_bool": True,
|
||||
"a_none": None,
|
||||
@@ -270,6 +274,16 @@ def test_serde_jsonplus_json_mode() -> None:
|
||||
},
|
||||
}
|
||||
|
||||
if sys.version_info < (3, 14):
|
||||
expected_result["my_pydantic_v1"] = {
|
||||
"foo": "foo",
|
||||
"bar": 1,
|
||||
"inner": {"hello": "hello"},
|
||||
}
|
||||
expected_result["my_secret_str_v1"] = "meow"
|
||||
|
||||
assert result == expected_result
|
||||
|
||||
|
||||
def test_serde_jsonplus_bytes() -> None:
|
||||
serde = JsonPlusSerializer()
|
||||
@@ -281,6 +295,20 @@ def test_serde_jsonplus_bytes() -> None:
|
||||
assert serde.loads_typed(dumped) == some_bytes
|
||||
|
||||
|
||||
def test_deserde_invalid_module() -> None:
|
||||
serde = JsonPlusSerializer()
|
||||
load = {
|
||||
"lc": 2,
|
||||
"type": "constructor",
|
||||
"id": ["pprint", "pprint"],
|
||||
"kwargs": {"object": "HELLO"},
|
||||
}
|
||||
with pytest.raises(InvalidModuleError):
|
||||
serde._revive_lc2(load)
|
||||
serde = JsonPlusSerializer(allowed_json_modules=[("pprint", "pprint")])
|
||||
serde.loads_typed(("json", json.dumps(load).encode("utf-8")))
|
||||
|
||||
|
||||
def test_serde_jsonplus_bytearray() -> None:
|
||||
serde = JsonPlusSerializer()
|
||||
|
||||
@@ -357,7 +385,12 @@ def test_serde_jsonplus_numpy_array_json_hook(arr: np.ndarray) -> None:
|
||||
"str_col": ["a", None, "c"],
|
||||
}
|
||||
),
|
||||
pd.DataFrame({"cat_col": pd.Categorical(["a", "b", "a", "c"])}),
|
||||
pytest.param(
|
||||
pd.DataFrame({"cat_col": pd.Categorical(["a", "b", "a", "c"])}),
|
||||
marks=pytest.mark.skipif(
|
||||
sys.version_info >= (3, 14), reason="NotImplementedError on Python 3.14"
|
||||
),
|
||||
),
|
||||
pd.DataFrame(
|
||||
{
|
||||
"int8": pd.array([1, 2, 3], dtype="int8"),
|
||||
@@ -385,11 +418,25 @@ def test_serde_jsonplus_numpy_array_json_hook(arr: np.ndarray) -> None:
|
||||
"col3": np.random.rand(1000),
|
||||
}
|
||||
),
|
||||
pd.DataFrame(
|
||||
{"tz_datetime": pd.date_range("2024-01-01", periods=3, freq="D", tz="UTC")}
|
||||
pytest.param(
|
||||
pd.DataFrame(
|
||||
{
|
||||
"tz_datetime": pd.date_range(
|
||||
"2024-01-01", periods=3, freq="D", tz="UTC"
|
||||
)
|
||||
}
|
||||
),
|
||||
marks=pytest.mark.skipif(
|
||||
sys.version_info >= (3, 14), reason="NotImplementedError on Python 3.14"
|
||||
),
|
||||
),
|
||||
pd.DataFrame({"timedelta": pd.to_timedelta([1, 2, 3], unit="D")}),
|
||||
pd.DataFrame({"period": pd.period_range("2024-01", periods=3, freq="M")}),
|
||||
pytest.param(
|
||||
pd.DataFrame({"period": pd.period_range("2024-01", periods=3, freq="M")}),
|
||||
marks=pytest.mark.skipif(
|
||||
sys.version_info >= (3, 14), reason="NotImplementedError on Python 3.14"
|
||||
),
|
||||
),
|
||||
pd.DataFrame({"interval": pd.interval_range(start=0, end=3, periods=3)}),
|
||||
pd.DataFrame({"unicode": ["Hello 🌍", "Python 🐍", "Data 📊"]}),
|
||||
pd.DataFrame({"mixed": [1, "string", [1, 2, 3], {"key": "value"}]}),
|
||||
@@ -426,7 +473,12 @@ def test_serde_jsonplus_pandas_dataframe(df: pd.DataFrame) -> None:
|
||||
pd.Series([1, 2, None]),
|
||||
pd.Series([1.1, None, 3.3]),
|
||||
pd.Series(["a", None, "c"]),
|
||||
pd.Series(pd.Categorical(["a", "b", "a", "c"])),
|
||||
pytest.param(
|
||||
pd.Series(pd.Categorical(["a", "b", "a", "c"])),
|
||||
marks=pytest.mark.skipif(
|
||||
sys.version_info >= (3, 14), reason="NotImplementedError on Python 3.14"
|
||||
),
|
||||
),
|
||||
pd.Series([1, 2, 3], dtype="int8"),
|
||||
pd.Series([10, 20, 30], dtype="int16"),
|
||||
pd.Series([100, 200, 300], dtype="int32"),
|
||||
|
||||
Generated
+562
-435
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,12 @@
|
||||
from collections.abc import Sequence
|
||||
from typing import Annotated, Literal, TypedDict
|
||||
|
||||
from langchain_community.tools.tavily_search import TavilySearchResults
|
||||
from langchain_core.messages import BaseMessage
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langgraph.graph import END, StateGraph, add_messages
|
||||
from langgraph.prebuilt import ToolNode
|
||||
|
||||
tools = [TavilySearchResults(max_results=1)]
|
||||
tools = []
|
||||
|
||||
model_oai = ChatOpenAI(temperature=0)
|
||||
|
||||
|
||||
@@ -5,5 +5,5 @@ description = "Test for prerelease stuff"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"langgraph==0.6.0"
|
||||
"langgraph==1.0.2"
|
||||
]
|
||||
@@ -5,5 +5,5 @@ description = "Test for prerelease stuff"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"langchain-openai==0.3.0"
|
||||
"langchain-openai==1.0.1"
|
||||
]
|
||||
@@ -6,9 +6,9 @@ readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
"langchain-openai==1.0.0a2",
|
||||
"langgraph==1.0.0a2",
|
||||
"langchain_community>=0.3.0",
|
||||
"langchain-anthropic==1.0.0a5",
|
||||
"langgraph==1.0.2"
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
prerelease = "allow"
|
||||
prerelease = "allow"
|
||||
|
||||
@@ -13,7 +13,7 @@ from pathlib import Path
|
||||
|
||||
import msgspec
|
||||
|
||||
from langgraph_cli.config import (
|
||||
from langgraph_cli.schemas import (
|
||||
AuthConfig,
|
||||
CheckpointerConfig,
|
||||
Config,
|
||||
@@ -22,6 +22,7 @@ from langgraph_cli.config import (
|
||||
HttpConfig,
|
||||
IndexConfig,
|
||||
SecurityConfig,
|
||||
SerdeConfig,
|
||||
StoreConfig,
|
||||
ThreadTTLConfig,
|
||||
TTLConfig,
|
||||
@@ -112,6 +113,7 @@ def add_descriptions_to_schema(schema, cls):
|
||||
CorsConfig,
|
||||
ThreadTTLConfig,
|
||||
CheckpointerConfig,
|
||||
SerdeConfig,
|
||||
TTLConfig,
|
||||
ConfigurableHeaderConfig,
|
||||
]:
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "0.4.4"
|
||||
__version__ = "0.4.7"
|
||||
|
||||
@@ -4,10 +4,12 @@ import pathlib
|
||||
import re
|
||||
import textwrap
|
||||
from collections import Counter
|
||||
from typing import Any, Literal, NamedTuple, TypedDict
|
||||
from typing import Literal, NamedTuple
|
||||
|
||||
import click
|
||||
|
||||
from langgraph_cli.schemas import Config, Distros
|
||||
|
||||
MIN_NODE_VERSION = "20"
|
||||
DEFAULT_NODE_VERSION = "20"
|
||||
|
||||
@@ -17,504 +19,6 @@ DEFAULT_PYTHON_VERSION = "3.11"
|
||||
DEFAULT_IMAGE_DISTRO = "debian"
|
||||
|
||||
|
||||
Distros = Literal["debian", "wolfi", "bullseye", "bookworm"]
|
||||
MiddlewareOrders = Literal["auth_first", "middleware_first"]
|
||||
|
||||
|
||||
class TTLConfig(TypedDict, total=False):
|
||||
"""Configuration for TTL (time-to-live) behavior in the store."""
|
||||
|
||||
refresh_on_read: bool
|
||||
"""Default behavior for refreshing TTLs on read operations (`GET` and `SEARCH`).
|
||||
|
||||
If `True`, TTLs will be refreshed on read operations (get/search) by default.
|
||||
This can be overridden per-operation by explicitly setting `refresh_ttl`.
|
||||
Defaults to `True` if not configured.
|
||||
"""
|
||||
default_ttl: float | None
|
||||
"""Optional. Default TTL (time-to-live) in minutes for new items.
|
||||
|
||||
If provided, all new items will have this TTL unless explicitly overridden.
|
||||
If omitted, items will have no TTL by default.
|
||||
"""
|
||||
sweep_interval_minutes: int | None
|
||||
"""Optional. Interval in minutes between TTL sweep iterations.
|
||||
|
||||
If provided, the store will periodically delete expired items based on the TTL.
|
||||
If omitted, no automatic sweeping will occur.
|
||||
"""
|
||||
|
||||
|
||||
class IndexConfig(TypedDict, total=False):
|
||||
"""Configuration for indexing documents for semantic search in the store.
|
||||
|
||||
This governs how text is converted into embeddings and stored for vector-based lookups.
|
||||
"""
|
||||
|
||||
dims: int
|
||||
"""Required. Dimensionality of the embedding vectors you will store.
|
||||
|
||||
Must match the output dimension of your selected embedding model or custom embed function.
|
||||
If mismatched, you will likely encounter shape/size errors when inserting or querying vectors.
|
||||
|
||||
Common embedding model output dimensions:
|
||||
- openai:text-embedding-3-large: 3072
|
||||
- openai:text-embedding-3-small: 1536
|
||||
- openai:text-embedding-ada-002: 1536
|
||||
- cohere:embed-english-v3.0: 1024
|
||||
- cohere:embed-english-light-v3.0: 384
|
||||
- cohere:embed-multilingual-v3.0: 1024
|
||||
- cohere:embed-multilingual-light-v3.0: 384
|
||||
"""
|
||||
|
||||
embed: str
|
||||
"""Required. Identifier or reference to the embedding model or a custom embedding function.
|
||||
|
||||
The format can vary:
|
||||
- "<provider>:<model_name>" for recognized providers (e.g., "openai:text-embedding-3-large")
|
||||
- "path/to/module.py:function_name" for your own local embedding function
|
||||
- "my_custom_embed" if it's a known alias in your system
|
||||
|
||||
Examples:
|
||||
- "openai:text-embedding-3-large"
|
||||
- "cohere:embed-multilingual-v3.0"
|
||||
- "src/app.py:embeddings"
|
||||
|
||||
Note: Must return embeddings of dimension `dims`.
|
||||
"""
|
||||
|
||||
fields: list[str] | None
|
||||
"""Optional. List of JSON fields to extract before generating embeddings.
|
||||
|
||||
Defaults to ["$"], which means the entire JSON object is embedded as one piece of text.
|
||||
If you provide multiple fields (e.g. ["title", "content"]), each is extracted and embedded separately,
|
||||
often saving token usage if you only care about certain parts of the data.
|
||||
|
||||
Example:
|
||||
fields=["title", "abstract", "author.biography"]
|
||||
"""
|
||||
|
||||
|
||||
class StoreConfig(TypedDict, total=False):
|
||||
"""Configuration for the built-in long-term memory store.
|
||||
|
||||
This store can optionally perform semantic search. If you omit `index`,
|
||||
the store will just handle traditional (non-embedded) data without vector lookups.
|
||||
"""
|
||||
|
||||
index: IndexConfig | None
|
||||
"""Optional. Defines the vector-based semantic search configuration.
|
||||
|
||||
If provided, the store will:
|
||||
- Generate embeddings according to `index.embed`
|
||||
- Enforce the embedding dimension given by `index.dims`
|
||||
- Embed only specified JSON fields (if any) from `index.fields`
|
||||
|
||||
If omitted, no vector index is initialized.
|
||||
"""
|
||||
|
||||
ttl: TTLConfig | None
|
||||
"""Optional. Defines the TTL (time-to-live) behavior configuration.
|
||||
|
||||
If provided, the store will apply TTL settings according to the configuration.
|
||||
If omitted, no TTL behavior is configured.
|
||||
"""
|
||||
|
||||
|
||||
class ThreadTTLConfig(TypedDict, total=False):
|
||||
"""Configure a default TTL for checkpointed data within threads."""
|
||||
|
||||
strategy: Literal["delete"]
|
||||
"""Strategy to use for deleting checkpointed data.
|
||||
|
||||
Choices:
|
||||
- "delete": Delete all checkpoints for a thread after TTL expires.
|
||||
"""
|
||||
default_ttl: float | None
|
||||
"""Default TTL (time-to-live) in minutes for checkpointed data."""
|
||||
sweep_interval_minutes: int | None
|
||||
"""Interval in minutes between sweep iterations.
|
||||
If omitted, a default interval will be used (typically ~ 5 minutes)."""
|
||||
|
||||
|
||||
class CheckpointerConfig(TypedDict, total=False):
|
||||
"""Configuration for the built-in checkpointer, which handles checkpointing of state.
|
||||
|
||||
If omitted, no checkpointer is set up (the object store will still be present, however).
|
||||
"""
|
||||
|
||||
ttl: ThreadTTLConfig | None
|
||||
"""Optional. Defines the TTL (time-to-live) behavior configuration.
|
||||
|
||||
If provided, the checkpointer will apply TTL settings according to the configuration.
|
||||
If omitted, no TTL behavior is configured.
|
||||
"""
|
||||
|
||||
|
||||
class SecurityConfig(TypedDict, total=False):
|
||||
"""Configuration for OpenAPI security definitions and requirements.
|
||||
|
||||
Useful for specifying global or path-level authentication and authorization flows
|
||||
(e.g., OAuth2, API key headers, etc.).
|
||||
"""
|
||||
|
||||
securitySchemes: dict[str, dict[str, Any]]
|
||||
"""Describe each security scheme recognized by your OpenAPI spec.
|
||||
|
||||
Keys are scheme names (e.g. "OAuth2", "ApiKeyAuth") and values are their definitions.
|
||||
Example:
|
||||
{
|
||||
"OAuth2": {
|
||||
"type": "oauth2",
|
||||
"flows": {
|
||||
"password": {
|
||||
"tokenUrl": "/token",
|
||||
"scopes": {"read": "Read data", "write": "Write data"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
security: list[dict[str, list[str]]]
|
||||
"""Global security requirements across all endpoints.
|
||||
|
||||
Each element in the list maps a security scheme (e.g. "OAuth2") to a list of scopes (e.g. ["read", "write"]).
|
||||
Example:
|
||||
[
|
||||
{"OAuth2": ["read", "write"]},
|
||||
{"ApiKeyAuth": []}
|
||||
]
|
||||
"""
|
||||
# path => {method => security}
|
||||
paths: dict[str, dict[str, list[dict[str, list[str]]]]]
|
||||
"""Path-specific security overrides.
|
||||
|
||||
Keys are path templates (e.g., "/items/{item_id}"), mapping to:
|
||||
- Keys that are HTTP methods (e.g., "GET", "POST"),
|
||||
- Values are lists of security definitions (just like `security`) for that method.
|
||||
|
||||
Example:
|
||||
{
|
||||
"/private_data": {
|
||||
"GET": [{"OAuth2": ["read"]}],
|
||||
"POST": [{"OAuth2": ["write"]}]
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class AuthConfig(TypedDict, total=False):
|
||||
"""Configuration for custom authentication logic and how it integrates into the OpenAPI spec."""
|
||||
|
||||
path: str
|
||||
"""Required. Path to an instance of the Auth() class that implements custom authentication.
|
||||
|
||||
Format: "path/to/file.py:my_auth"
|
||||
"""
|
||||
disable_studio_auth: bool
|
||||
"""Optional. Whether to disable LangSmith API-key authentication for requests originating the Studio.
|
||||
|
||||
Defaults to False, meaning that if a particular header is set, the server will verify the `x-api-key` header
|
||||
value is a valid API key for the deployment's workspace. If `True`, all requests will go through your custom
|
||||
authentication logic, regardless of origin of the request.
|
||||
"""
|
||||
openapi: SecurityConfig
|
||||
"""The security configuration to include in your server's OpenAPI spec.
|
||||
|
||||
Example (OAuth2):
|
||||
{
|
||||
"securitySchemes": {
|
||||
"OAuth2": {
|
||||
"type": "oauth2",
|
||||
"flows": {
|
||||
"password": {
|
||||
"tokenUrl": "/token",
|
||||
"scopes": {"me": "Read user info", "items": "Manage items"}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{"OAuth2": ["me"]}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class CorsConfig(TypedDict, total=False):
|
||||
"""Specifies Cross-Origin Resource Sharing (CORS) rules for your server.
|
||||
|
||||
If omitted, defaults are typically very restrictive (often no cross-origin requests).
|
||||
Configure carefully if you want to allow usage from browsers hosted on other domains.
|
||||
"""
|
||||
|
||||
allow_origins: list[str]
|
||||
"""Optional. List of allowed origins (e.g., "https://example.com").
|
||||
|
||||
Default is often an empty list (no external origins).
|
||||
Use "*" only if you trust all origins, as that bypasses most restrictions.
|
||||
"""
|
||||
allow_methods: list[str]
|
||||
"""Optional. HTTP methods permitted for cross-origin requests (e.g. ["GET", "POST"]).
|
||||
|
||||
Default might be ["GET", "POST", "OPTIONS"] depending on your server framework.
|
||||
"""
|
||||
allow_headers: list[str]
|
||||
"""Optional. HTTP headers that can be used in cross-origin requests (e.g. ["Content-Type", "Authorization"])."""
|
||||
allow_credentials: bool
|
||||
"""Optional. If `True`, cross-origin requests can include credentials (cookies, auth headers).
|
||||
|
||||
Default False to avoid accidentally exposing secured endpoints to untrusted sites.
|
||||
"""
|
||||
allow_origin_regex: str
|
||||
"""Optional. A regex pattern for matching allowed origins, used if you have dynamic subdomains.
|
||||
|
||||
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."""
|
||||
max_age: int
|
||||
"""Optional. How many seconds the browser may cache preflight responses.
|
||||
|
||||
Default might be 600 (10 minutes). Larger values reduce preflight requests but can cause stale configurations.
|
||||
"""
|
||||
|
||||
|
||||
class ConfigurableHeaderConfig(TypedDict):
|
||||
"""Customize which headers to include as configurable values in your runs.
|
||||
|
||||
By default, omits x-api-key, x-tenant-id, and x-service-key.
|
||||
|
||||
Exclusions (if provided) take precedence.
|
||||
|
||||
Each value can be a raw string with an optional wildcard.
|
||||
"""
|
||||
|
||||
includes: list[str] | None
|
||||
"""Headers to include (if not also matches against an 'exludes' pattern.
|
||||
|
||||
Examples:
|
||||
- 'user-agent'
|
||||
- 'x-configurable-*'
|
||||
"""
|
||||
excludes: list[str] | None
|
||||
"""Headers to exclude. Applied before the 'includes' checks.
|
||||
|
||||
Examples:
|
||||
- 'x-api-key'
|
||||
- '*key*'
|
||||
- '*token*'
|
||||
"""
|
||||
|
||||
|
||||
class HttpConfig(TypedDict, total=False):
|
||||
"""Configuration for the built-in HTTP server that powers your deployment's routes and endpoints."""
|
||||
|
||||
app: str
|
||||
"""Optional. Import path to a custom Starlette/FastAPI application to mount.
|
||||
|
||||
Format: "path/to/module.py:app_var"
|
||||
If provided, it can override or extend the default routes.
|
||||
"""
|
||||
disable_assistants: bool
|
||||
"""Optional. If `True`, /assistants routes are removed from the server.
|
||||
|
||||
Default is False (meaning /assistants is enabled).
|
||||
"""
|
||||
disable_threads: bool
|
||||
"""Optional. If `True`, /threads routes are removed.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_runs: bool
|
||||
"""Optional. If `True`, /runs routes are removed.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_store: bool
|
||||
"""Optional. If `True`, /store routes are removed, disabling direct store interactions via HTTP.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_mcp: bool
|
||||
"""Optional. If `True`, /mcp routes are removed, disabling the MCP server.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_meta: bool
|
||||
"""Optional. Remove meta endpoints.
|
||||
|
||||
Set to True to disable the following endpoints: /openapi.json, /info, /metrics, /docs.
|
||||
This will also make the /ok endpoint skip any DB or other checks, always returning {"ok": True}.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
cors: CorsConfig | None
|
||||
"""Optional. Defines CORS restrictions. If omitted, no special rules are set and
|
||||
cross-origin behavior depends on default server settings.
|
||||
"""
|
||||
configurable_headers: ConfigurableHeaderConfig | None
|
||||
"""Optional. Defines how headers are treated for a run's configuration.
|
||||
|
||||
You can include or exclude headers as configurable values to condition your
|
||||
agent's behavior or permissions on a request's headers."""
|
||||
logging_headers: ConfigurableHeaderConfig | None
|
||||
"""Optional. Defines which headers are excluded from logging."""
|
||||
middleware_order: MiddlewareOrders | None
|
||||
"""Optional. Defines the order in which to apply server customizations.
|
||||
|
||||
Choices:
|
||||
- "auth_first": Authentication hooks (custom or default) are evaluated
|
||||
before custom middleware.
|
||||
- "middleware_first": Custom middleware is evaluated
|
||||
before authentication hooks (custom or default).
|
||||
|
||||
Default is `middleware_first`.
|
||||
"""
|
||||
enable_custom_route_auth: bool
|
||||
"""Optional. If `True`, authentication is enabled for custom routes,
|
||||
not just the routes that are protected by default.
|
||||
(Routes protected by default include /assistants, /threads, and /runs).
|
||||
|
||||
Default is False. This flag only affects authentication behavior
|
||||
if `app` is provided and contains custom routes.
|
||||
"""
|
||||
|
||||
|
||||
class Config(TypedDict, total=False):
|
||||
"""Top-level config for langgraph-cli or similar deployment tooling."""
|
||||
|
||||
python_version: str
|
||||
"""Optional. Python version in 'major.minor' format (e.g. '3.11').
|
||||
Must be at least 3.11 or greater for this deployment to function properly.
|
||||
"""
|
||||
|
||||
node_version: str | None
|
||||
"""Optional. Node.js version as a major version (e.g. '20'), if your deployment needs Node.
|
||||
Must be >= 20 if provided.
|
||||
"""
|
||||
|
||||
api_version: str | None
|
||||
"""Optional. Which semantic version of the LangGraph API server to use.
|
||||
|
||||
Defaults to latest. Check the
|
||||
[changelog](https://docs.langchain.com/langgraph-platform/langgraph-server-changelog)
|
||||
for more information."""
|
||||
|
||||
_INTERNAL_docker_tag: str | None
|
||||
"""Optional. Internal use only.
|
||||
"""
|
||||
|
||||
base_image: str | None
|
||||
"""Optional. Base image to use for the LangGraph API server.
|
||||
|
||||
Defaults to langchain/langgraph-api or langchain/langgraphjs-api."""
|
||||
|
||||
image_distro: Distros | None
|
||||
"""Optional. Linux distribution for the base image.
|
||||
|
||||
Must be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.
|
||||
If omitted, defaults to 'debian' ('latest').
|
||||
"""
|
||||
|
||||
pip_config_file: str | None
|
||||
"""Optional. Path to a pip config file (e.g., "/etc/pip.conf" or "pip.ini") for controlling
|
||||
package installation (custom indices, credentials, etc.).
|
||||
|
||||
Only relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.
|
||||
"""
|
||||
|
||||
pip_installer: str | None
|
||||
"""Optional. Python package installer to use ('auto', 'pip', 'uv').
|
||||
|
||||
- 'auto' (default): Use uv for supported base images, otherwise pip
|
||||
- 'pip': Force use of pip regardless of base image support
|
||||
- 'uv': Force use of uv (will fail if base image doesn't support it)
|
||||
"""
|
||||
|
||||
dockerfile_lines: list[str]
|
||||
"""Optional. Additional Docker instructions that will be appended to your base Dockerfile.
|
||||
|
||||
Useful for installing OS packages, setting environment variables, etc.
|
||||
Example:
|
||||
dockerfile_lines=[
|
||||
"RUN apt-get update && apt-get install -y libmagic-dev",
|
||||
"ENV MY_CUSTOM_VAR=hello_world"
|
||||
]
|
||||
"""
|
||||
|
||||
dependencies: list[str]
|
||||
"""List of Python dependencies to install, either from PyPI or local paths.
|
||||
|
||||
Examples:
|
||||
- "." or "./src" if you have a local Python package
|
||||
- str (aka "anthropic") for a PyPI package
|
||||
- "git+https://github.com/org/repo.git@main" for a Git-based package
|
||||
Defaults to an empty list, meaning no additional packages installed beyond your base environment.
|
||||
"""
|
||||
|
||||
graphs: dict[str, str]
|
||||
"""Optional. Named definitions of graphs, each pointing to a Python object.
|
||||
|
||||
|
||||
Graphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context
|
||||
managers that accept a single configuration argument (of type RunnableConfig) and return a pregel object
|
||||
(instance of Stategraph, etc.).
|
||||
|
||||
Keys are graph names, values are "path/to/file.py:object_name".
|
||||
Example:
|
||||
{
|
||||
"mygraph": "graphs/my_graph.py:graph_definition",
|
||||
"anothergraph": "graphs/another.py:get_graph"
|
||||
}
|
||||
"""
|
||||
|
||||
env: dict[str, str] | str
|
||||
"""Optional. Environment variables to set for your deployment.
|
||||
|
||||
- If given as a dict, keys are variable names and values are their values.
|
||||
- If given as a string, it must be a path to a file containing lines in KEY=VALUE format.
|
||||
|
||||
Example as a dict:
|
||||
env={"API_TOKEN": "abc123", "DEBUG": "true"}
|
||||
Example as a file path:
|
||||
env=".env"
|
||||
"""
|
||||
|
||||
store: StoreConfig | None
|
||||
"""Optional. Configuration for the built-in long-term memory store, including semantic search indexing.
|
||||
|
||||
If omitted, no vector index is set up (the object store will still be present, however).
|
||||
"""
|
||||
|
||||
checkpointer: CheckpointerConfig | None
|
||||
"""Optional. Configuration for the built-in checkpointer, which handles checkpointing of state.
|
||||
|
||||
If omitted, no checkpointer is set up (the object store will still be present, however).
|
||||
"""
|
||||
|
||||
auth: AuthConfig | None
|
||||
"""Optional. Custom authentication config, including the path to your Python auth logic and
|
||||
the OpenAPI security definitions it uses.
|
||||
"""
|
||||
|
||||
http: HttpConfig | None
|
||||
"""Optional. Configuration for the built-in HTTP server, controlling which custom routes are exposed
|
||||
and how cross-origin requests are handled.
|
||||
"""
|
||||
|
||||
ui: dict[str, str] | None
|
||||
"""Optional. Named definitions of UI components emitted by the agent, each pointing to a JS/TS file.
|
||||
"""
|
||||
|
||||
keep_pkg_tools: bool | list[str] | None
|
||||
"""Optional. Control whether to retain Python packaging tools in the final image.
|
||||
|
||||
Allowed tools are: "pip", "setuptools", "wheel".
|
||||
You can also set to true to include all packaging tools.
|
||||
"""
|
||||
|
||||
|
||||
_BUILD_TOOLS = ("pip", "setuptools", "wheel")
|
||||
|
||||
|
||||
@@ -1422,35 +926,51 @@ ADD {relpath} /deps/{name}
|
||||
]
|
||||
)
|
||||
image_str = docker_tag(config, base_image, api_version)
|
||||
docker_file_contents = [
|
||||
f"FROM {image_str}",
|
||||
"",
|
||||
os.linesep.join(config["dockerfile_lines"]),
|
||||
"",
|
||||
installs,
|
||||
"",
|
||||
"# -- Installing all local dependencies --",
|
||||
f"""RUN for dep in /deps/*; do \
|
||||
|
||||
# Prepare docker file contents
|
||||
docker_file_contents = []
|
||||
|
||||
# Add syntax directive if we have additional contexts (requires BuildKit frontend.contexts capability)
|
||||
if local_deps.additional_contexts:
|
||||
docker_file_contents.extend(
|
||||
[
|
||||
"# syntax=docker/dockerfile:1.4",
|
||||
"",
|
||||
]
|
||||
)
|
||||
|
||||
# Add main dockerfile content
|
||||
docker_file_contents.extend(
|
||||
[
|
||||
f"FROM {image_str}",
|
||||
"",
|
||||
os.linesep.join(config["dockerfile_lines"]),
|
||||
"",
|
||||
installs,
|
||||
"",
|
||||
"# -- Installing all local dependencies --",
|
||||
f"""RUN for dep in /deps/*; do \
|
||||
echo "Installing $dep"; \
|
||||
if [ -d "$dep" ]; then \
|
||||
echo "Installing $dep"; \
|
||||
(cd "$dep" && {global_reqs_pip_install} -e .); \
|
||||
fi; \
|
||||
done""",
|
||||
"# -- End of local dependencies install --",
|
||||
os.linesep.join(env_vars),
|
||||
"",
|
||||
js_inst_str,
|
||||
"",
|
||||
# Add pip cleanup after all installations are complete
|
||||
_get_pip_cleanup_lines(
|
||||
install_cmd=install_cmd,
|
||||
to_uninstall=build_tools_to_uninstall,
|
||||
pip_installer=pip_installer,
|
||||
),
|
||||
"",
|
||||
f"WORKDIR {local_deps.working_dir}" if local_deps.working_dir else "",
|
||||
]
|
||||
"# -- End of local dependencies install --",
|
||||
os.linesep.join(env_vars),
|
||||
"",
|
||||
js_inst_str,
|
||||
"",
|
||||
# Add pip cleanup after all installations are complete
|
||||
_get_pip_cleanup_lines(
|
||||
install_cmd=install_cmd,
|
||||
to_uninstall=build_tools_to_uninstall,
|
||||
pip_installer=pip_installer,
|
||||
),
|
||||
"",
|
||||
f"WORKDIR {local_deps.working_dir}" if local_deps.working_dir else "",
|
||||
]
|
||||
)
|
||||
|
||||
additional_contexts: dict[str, str] = {}
|
||||
for p in local_deps.additional_contexts:
|
||||
|
||||
@@ -0,0 +1,558 @@
|
||||
from typing import Any, Literal, TypedDict
|
||||
|
||||
Distros = Literal["debian", "wolfi", "bullseye", "bookworm"]
|
||||
MiddlewareOrders = Literal["auth_first", "middleware_first"]
|
||||
|
||||
|
||||
class TTLConfig(TypedDict, total=False):
|
||||
"""Configuration for TTL (time-to-live) behavior in the store."""
|
||||
|
||||
refresh_on_read: bool
|
||||
"""Default behavior for refreshing TTLs on read operations (`GET` and `SEARCH`).
|
||||
|
||||
If `True`, TTLs will be refreshed on read operations (get/search) by default.
|
||||
This can be overridden per-operation by explicitly setting `refresh_ttl`.
|
||||
Defaults to `True` if not configured.
|
||||
"""
|
||||
default_ttl: float | None
|
||||
"""Optional. Default TTL (time-to-live) in minutes for new items.
|
||||
|
||||
If provided, all new items will have this TTL unless explicitly overridden.
|
||||
If omitted, items will have no TTL by default.
|
||||
"""
|
||||
sweep_interval_minutes: int | None
|
||||
"""Optional. Interval in minutes between TTL sweep iterations.
|
||||
|
||||
If provided, the store will periodically delete expired items based on the TTL.
|
||||
If omitted, no automatic sweeping will occur.
|
||||
"""
|
||||
|
||||
|
||||
class IndexConfig(TypedDict, total=False):
|
||||
"""Configuration for indexing documents for semantic search in the store.
|
||||
|
||||
This governs how text is converted into embeddings and stored for vector-based lookups.
|
||||
"""
|
||||
|
||||
dims: int
|
||||
"""Required. Dimensionality of the embedding vectors you will store.
|
||||
|
||||
Must match the output dimension of your selected embedding model or custom embed function.
|
||||
If mismatched, you will likely encounter shape/size errors when inserting or querying vectors.
|
||||
|
||||
Common embedding model output dimensions:
|
||||
- openai:text-embedding-3-large: 3072
|
||||
- openai:text-embedding-3-small: 1536
|
||||
- openai:text-embedding-ada-002: 1536
|
||||
- cohere:embed-english-v3.0: 1024
|
||||
- cohere:embed-english-light-v3.0: 384
|
||||
- cohere:embed-multilingual-v3.0: 1024
|
||||
- cohere:embed-multilingual-light-v3.0: 384
|
||||
"""
|
||||
|
||||
embed: str
|
||||
"""Required. Identifier or reference to the embedding model or a custom embedding function.
|
||||
|
||||
The format can vary:
|
||||
- "<provider>:<model_name>" for recognized providers (e.g., "openai:text-embedding-3-large")
|
||||
- "path/to/module.py:function_name" for your own local embedding function
|
||||
- "my_custom_embed" if it's a known alias in your system
|
||||
|
||||
Examples:
|
||||
- "openai:text-embedding-3-large"
|
||||
- "cohere:embed-multilingual-v3.0"
|
||||
- "src/app.py:embeddings"
|
||||
|
||||
Note: Must return embeddings of dimension `dims`.
|
||||
"""
|
||||
|
||||
fields: list[str] | None
|
||||
"""Optional. List of JSON fields to extract before generating embeddings.
|
||||
|
||||
Defaults to ["$"], which means the entire JSON object is embedded as one piece of text.
|
||||
If you provide multiple fields (e.g. ["title", "content"]), each is extracted and embedded separately,
|
||||
often saving token usage if you only care about certain parts of the data.
|
||||
|
||||
Example:
|
||||
fields=["title", "abstract", "author.biography"]
|
||||
"""
|
||||
|
||||
|
||||
class StoreConfig(TypedDict, total=False):
|
||||
"""Configuration for the built-in long-term memory store.
|
||||
|
||||
This store can optionally perform semantic search. If you omit `index`,
|
||||
the store will just handle traditional (non-embedded) data without vector lookups.
|
||||
"""
|
||||
|
||||
index: IndexConfig | None
|
||||
"""Optional. Defines the vector-based semantic search configuration.
|
||||
|
||||
If provided, the store will:
|
||||
- Generate embeddings according to `index.embed`
|
||||
- Enforce the embedding dimension given by `index.dims`
|
||||
- Embed only specified JSON fields (if any) from `index.fields`
|
||||
|
||||
If omitted, no vector index is initialized.
|
||||
"""
|
||||
|
||||
ttl: TTLConfig | None
|
||||
"""Optional. Defines the TTL (time-to-live) behavior configuration.
|
||||
|
||||
If provided, the store will apply TTL settings according to the configuration.
|
||||
If omitted, no TTL behavior is configured.
|
||||
"""
|
||||
|
||||
|
||||
class ThreadTTLConfig(TypedDict, total=False):
|
||||
"""Configure a default TTL for checkpointed data within threads."""
|
||||
|
||||
strategy: Literal["delete"]
|
||||
"""Strategy to use for deleting checkpointed data.
|
||||
|
||||
Choices:
|
||||
- "delete": Delete all checkpoints for a thread after TTL expires.
|
||||
"""
|
||||
default_ttl: float | None
|
||||
"""Default TTL (time-to-live) in minutes for checkpointed data."""
|
||||
sweep_interval_minutes: int | None
|
||||
"""Interval in minutes between sweep iterations.
|
||||
If omitted, a default interval will be used (typically ~ 5 minutes)."""
|
||||
|
||||
|
||||
class SerdeConfig(TypedDict, total=False):
|
||||
"""Configuration for the built-in serde, which handles checkpointing of state.
|
||||
|
||||
If omitted, no serde is set up (the object store will still be present, however)."""
|
||||
|
||||
allowed_json_modules: list[list[str]] | bool | None
|
||||
"""Optional. List of allowed python modules to de-serialize custom objects from.
|
||||
|
||||
If provided, only the specified modules will be allowed to be deserialized.
|
||||
If omitted, no modules are allowed, and the object returned will simply be a json object OR
|
||||
a deserialized langchain object.
|
||||
|
||||
Example:
|
||||
{...
|
||||
"serde": {
|
||||
"allowed_json_modules": [
|
||||
["my_agent", "my_file", "SomeType"],
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
If you set this to True, any module will be allowed to be deserialized.
|
||||
|
||||
Example:
|
||||
{...
|
||||
"serde": {
|
||||
"allowed_json_modules": true
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
pickle_fallback: bool
|
||||
"""Optional. Whether to allow pickling as a fallback for deserialization.
|
||||
|
||||
If True, pickling will be allowed as a fallback for deserialization.
|
||||
If False, pickling will not be allowed as a fallback for deserialization.
|
||||
Defaults to True if not configured."""
|
||||
|
||||
|
||||
class CheckpointerConfig(TypedDict, total=False):
|
||||
"""Configuration for the built-in checkpointer, which handles checkpointing of state.
|
||||
|
||||
If omitted, no checkpointer is set up (the object store will still be present, however).
|
||||
"""
|
||||
|
||||
ttl: ThreadTTLConfig | None
|
||||
"""Optional. Defines the TTL (time-to-live) behavior configuration.
|
||||
|
||||
If provided, the checkpointer will apply TTL settings according to the configuration.
|
||||
If omitted, no TTL behavior is configured.
|
||||
"""
|
||||
serde: SerdeConfig | None
|
||||
"""Optional. Defines the serde configuration.
|
||||
|
||||
If provided, the checkpointer will apply serde settings according to the configuration.
|
||||
If omitted, no serde behavior is configured.
|
||||
|
||||
This configuration requires server version 0.5 or later to take effect.
|
||||
"""
|
||||
|
||||
|
||||
class SecurityConfig(TypedDict, total=False):
|
||||
"""Configuration for OpenAPI security definitions and requirements.
|
||||
|
||||
Useful for specifying global or path-level authentication and authorization flows
|
||||
(e.g., OAuth2, API key headers, etc.).
|
||||
"""
|
||||
|
||||
securitySchemes: dict[str, dict[str, Any]]
|
||||
"""Describe each security scheme recognized by your OpenAPI spec.
|
||||
|
||||
Keys are scheme names (e.g. "OAuth2", "ApiKeyAuth") and values are their definitions.
|
||||
Example:
|
||||
{
|
||||
"OAuth2": {
|
||||
"type": "oauth2",
|
||||
"flows": {
|
||||
"password": {
|
||||
"tokenUrl": "/token",
|
||||
"scopes": {"read": "Read data", "write": "Write data"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
security: list[dict[str, list[str]]]
|
||||
"""Global security requirements across all endpoints.
|
||||
|
||||
Each element in the list maps a security scheme (e.g. "OAuth2") to a list of scopes (e.g. ["read", "write"]).
|
||||
Example:
|
||||
[
|
||||
{"OAuth2": ["read", "write"]},
|
||||
{"ApiKeyAuth": []}
|
||||
]
|
||||
"""
|
||||
# path => {method => security}
|
||||
paths: dict[str, dict[str, list[dict[str, list[str]]]]]
|
||||
"""Path-specific security overrides.
|
||||
|
||||
Keys are path templates (e.g., "/items/{item_id}"), mapping to:
|
||||
- Keys that are HTTP methods (e.g., "GET", "POST"),
|
||||
- Values are lists of security definitions (just like `security`) for that method.
|
||||
|
||||
Example:
|
||||
{
|
||||
"/private_data": {
|
||||
"GET": [{"OAuth2": ["read"]}],
|
||||
"POST": [{"OAuth2": ["write"]}]
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class AuthConfig(TypedDict, total=False):
|
||||
"""Configuration for custom authentication logic and how it integrates into the OpenAPI spec."""
|
||||
|
||||
path: str
|
||||
"""Required. Path to an instance of the Auth() class that implements custom authentication.
|
||||
|
||||
Format: "path/to/file.py:my_auth"
|
||||
"""
|
||||
disable_studio_auth: bool
|
||||
"""Optional. Whether to disable LangSmith API-key authentication for requests originating the Studio.
|
||||
|
||||
Defaults to False, meaning that if a particular header is set, the server will verify the `x-api-key` header
|
||||
value is a valid API key for the deployment's workspace. If `True`, all requests will go through your custom
|
||||
authentication logic, regardless of origin of the request.
|
||||
"""
|
||||
openapi: SecurityConfig
|
||||
"""The security configuration to include in your server's OpenAPI spec.
|
||||
|
||||
Example (OAuth2):
|
||||
{
|
||||
"securitySchemes": {
|
||||
"OAuth2": {
|
||||
"type": "oauth2",
|
||||
"flows": {
|
||||
"password": {
|
||||
"tokenUrl": "/token",
|
||||
"scopes": {"me": "Read user info", "items": "Manage items"}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{"OAuth2": ["me"]}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class CorsConfig(TypedDict, total=False):
|
||||
"""Specifies Cross-Origin Resource Sharing (CORS) rules for your server.
|
||||
|
||||
If omitted, defaults are typically very restrictive (often no cross-origin requests).
|
||||
Configure carefully if you want to allow usage from browsers hosted on other domains.
|
||||
"""
|
||||
|
||||
allow_origins: list[str]
|
||||
"""Optional. List of allowed origins (e.g., "https://example.com").
|
||||
|
||||
Default is often an empty list (no external origins).
|
||||
Use "*" only if you trust all origins, as that bypasses most restrictions.
|
||||
"""
|
||||
allow_methods: list[str]
|
||||
"""Optional. HTTP methods permitted for cross-origin requests (e.g. ["GET", "POST"]).
|
||||
|
||||
Default might be ["GET", "POST", "OPTIONS"] depending on your server framework.
|
||||
"""
|
||||
allow_headers: list[str]
|
||||
"""Optional. HTTP headers that can be used in cross-origin requests (e.g. ["Content-Type", "Authorization"])."""
|
||||
allow_credentials: bool
|
||||
"""Optional. If `True`, cross-origin requests can include credentials (cookies, auth headers).
|
||||
|
||||
Default False to avoid accidentally exposing secured endpoints to untrusted sites.
|
||||
"""
|
||||
allow_origin_regex: str
|
||||
"""Optional. A regex pattern for matching allowed origins, used if you have dynamic subdomains.
|
||||
|
||||
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."""
|
||||
max_age: int
|
||||
"""Optional. How many seconds the browser may cache preflight responses.
|
||||
|
||||
Default might be 600 (10 minutes). Larger values reduce preflight requests but can cause stale configurations.
|
||||
"""
|
||||
|
||||
|
||||
class ConfigurableHeaderConfig(TypedDict):
|
||||
"""Customize which headers to include as configurable values in your runs.
|
||||
|
||||
By default, omits x-api-key, x-tenant-id, and x-service-key.
|
||||
|
||||
Exclusions (if provided) take precedence.
|
||||
|
||||
Each value can be a raw string with an optional wildcard.
|
||||
"""
|
||||
|
||||
includes: list[str] | None
|
||||
"""Headers to include (if not also matches against an 'exludes' pattern.
|
||||
|
||||
Examples:
|
||||
- 'user-agent'
|
||||
- 'x-configurable-*'
|
||||
"""
|
||||
excludes: list[str] | None
|
||||
"""Headers to exclude. Applied before the 'includes' checks.
|
||||
|
||||
Examples:
|
||||
- 'x-api-key'
|
||||
- '*key*'
|
||||
- '*token*'
|
||||
"""
|
||||
|
||||
|
||||
class HttpConfig(TypedDict, total=False):
|
||||
"""Configuration for the built-in HTTP server that powers your deployment's routes and endpoints."""
|
||||
|
||||
app: str
|
||||
"""Optional. Import path to a custom Starlette/FastAPI application to mount.
|
||||
|
||||
Format: "path/to/module.py:app_var"
|
||||
If provided, it can override or extend the default routes.
|
||||
"""
|
||||
disable_assistants: bool
|
||||
"""Optional. If `True`, /assistants routes are removed from the server.
|
||||
|
||||
Default is False (meaning /assistants is enabled).
|
||||
"""
|
||||
disable_threads: bool
|
||||
"""Optional. If `True`, /threads routes are removed.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_runs: bool
|
||||
"""Optional. If `True`, /runs routes are removed.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_store: bool
|
||||
"""Optional. If `True`, /store routes are removed, disabling direct store interactions via HTTP.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_mcp: bool
|
||||
"""Optional. If `True`, /mcp routes are removed, disabling the MCP server.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
disable_meta: bool
|
||||
"""Optional. Remove meta endpoints.
|
||||
|
||||
Set to True to disable the following endpoints: /openapi.json, /info, /metrics, /docs.
|
||||
This will also make the /ok endpoint skip any DB or other checks, always returning {"ok": True}.
|
||||
|
||||
Default is False.
|
||||
"""
|
||||
cors: CorsConfig | None
|
||||
"""Optional. Defines CORS restrictions. If omitted, no special rules are set and
|
||||
cross-origin behavior depends on default server settings.
|
||||
"""
|
||||
configurable_headers: ConfigurableHeaderConfig | None
|
||||
"""Optional. Defines how headers are treated for a run's configuration.
|
||||
|
||||
You can include or exclude headers as configurable values to condition your
|
||||
agent's behavior or permissions on a request's headers."""
|
||||
logging_headers: ConfigurableHeaderConfig | None
|
||||
"""Optional. Defines which headers are excluded from logging."""
|
||||
middleware_order: MiddlewareOrders | None
|
||||
"""Optional. Defines the order in which to apply server customizations.
|
||||
|
||||
Choices:
|
||||
- "auth_first": Authentication hooks (custom or default) are evaluated
|
||||
before custom middleware.
|
||||
- "middleware_first": Custom middleware is evaluated
|
||||
before authentication hooks (custom or default).
|
||||
|
||||
Default is `middleware_first`.
|
||||
"""
|
||||
enable_custom_route_auth: bool
|
||||
"""Optional. If `True`, authentication is enabled for custom routes,
|
||||
not just the routes that are protected by default.
|
||||
(Routes protected by default include /assistants, /threads, and /runs).
|
||||
|
||||
Default is False. This flag only affects authentication behavior
|
||||
if `app` is provided and contains custom routes.
|
||||
"""
|
||||
|
||||
|
||||
class Config(TypedDict, total=False):
|
||||
"""Top-level config for langgraph-cli or similar deployment tooling."""
|
||||
|
||||
python_version: str
|
||||
"""Optional. Python version in 'major.minor' format (e.g. '3.11').
|
||||
Must be at least 3.11 or greater for this deployment to function properly.
|
||||
"""
|
||||
|
||||
node_version: str | None
|
||||
"""Optional. Node.js version as a major version (e.g. '20'), if your deployment needs Node.
|
||||
Must be >= 20 if provided.
|
||||
"""
|
||||
|
||||
api_version: str | None
|
||||
"""Optional. Which semantic version of the LangGraph API server to use.
|
||||
|
||||
Defaults to latest. Check the
|
||||
[changelog](https://docs.langchain.com/langgraph-platform/langgraph-server-changelog)
|
||||
for more information."""
|
||||
|
||||
_INTERNAL_docker_tag: str | None
|
||||
"""Optional. Internal use only.
|
||||
"""
|
||||
|
||||
base_image: str | None
|
||||
"""Optional. Base image to use for the LangGraph API server.
|
||||
|
||||
Defaults to langchain/langgraph-api or langchain/langgraphjs-api."""
|
||||
|
||||
image_distro: Distros | None
|
||||
"""Optional. Linux distribution for the base image.
|
||||
|
||||
Must be one of 'wolfi', 'debian', 'bullseye', or 'bookworm'.
|
||||
If omitted, defaults to 'debian' ('latest').
|
||||
"""
|
||||
|
||||
pip_config_file: str | None
|
||||
"""Optional. Path to a pip config file (e.g., "/etc/pip.conf" or "pip.ini") for controlling
|
||||
package installation (custom indices, credentials, etc.).
|
||||
|
||||
Only relevant if Python dependencies are installed via pip. If omitted, default pip settings are used.
|
||||
"""
|
||||
|
||||
pip_installer: str | None
|
||||
"""Optional. Python package installer to use ('auto', 'pip', 'uv').
|
||||
|
||||
- 'auto' (default): Use uv for supported base images, otherwise pip
|
||||
- 'pip': Force use of pip regardless of base image support
|
||||
- 'uv': Force use of uv (will fail if base image doesn't support it)
|
||||
"""
|
||||
|
||||
dockerfile_lines: list[str]
|
||||
"""Optional. Additional Docker instructions that will be appended to your base Dockerfile.
|
||||
|
||||
Useful for installing OS packages, setting environment variables, etc.
|
||||
Example:
|
||||
dockerfile_lines=[
|
||||
"RUN apt-get update && apt-get install -y libmagic-dev",
|
||||
"ENV MY_CUSTOM_VAR=hello_world"
|
||||
]
|
||||
"""
|
||||
|
||||
dependencies: list[str]
|
||||
"""List of Python dependencies to install, either from PyPI or local paths.
|
||||
|
||||
Examples:
|
||||
- "." or "./src" if you have a local Python package
|
||||
- str (aka "anthropic") for a PyPI package
|
||||
- "git+https://github.com/org/repo.git@main" for a Git-based package
|
||||
Defaults to an empty list, meaning no additional packages installed beyond your base environment.
|
||||
"""
|
||||
|
||||
graphs: dict[str, str]
|
||||
"""Optional. Named definitions of graphs, each pointing to a Python object.
|
||||
|
||||
|
||||
Graphs can be StateGraph, @entrypoint, or any other Pregel object OR they can point to (async) context
|
||||
managers that accept a single configuration argument (of type RunnableConfig) and return a pregel object
|
||||
(instance of Stategraph, etc.).
|
||||
|
||||
Keys are graph names, values are "path/to/file.py:object_name".
|
||||
Example:
|
||||
{
|
||||
"mygraph": "graphs/my_graph.py:graph_definition",
|
||||
"anothergraph": "graphs/another.py:get_graph"
|
||||
}
|
||||
"""
|
||||
|
||||
env: dict[str, str] | str
|
||||
"""Optional. Environment variables to set for your deployment.
|
||||
|
||||
- If given as a dict, keys are variable names and values are their values.
|
||||
- If given as a string, it must be a path to a file containing lines in KEY=VALUE format.
|
||||
|
||||
Example as a dict:
|
||||
env={"API_TOKEN": "abc123", "DEBUG": "true"}
|
||||
Example as a file path:
|
||||
env=".env"
|
||||
"""
|
||||
|
||||
store: StoreConfig | None
|
||||
"""Optional. Configuration for the built-in long-term memory store, including semantic search indexing.
|
||||
|
||||
If omitted, no vector index is set up (the object store will still be present, however).
|
||||
"""
|
||||
|
||||
checkpointer: CheckpointerConfig | None
|
||||
"""Optional. Configuration for the built-in checkpointer, which handles checkpointing of state.
|
||||
|
||||
If omitted, no checkpointer is set up (the object store will still be present, however).
|
||||
"""
|
||||
|
||||
auth: AuthConfig | None
|
||||
"""Optional. Custom authentication config, including the path to your Python auth logic and
|
||||
the OpenAPI security definitions it uses.
|
||||
"""
|
||||
|
||||
http: HttpConfig | None
|
||||
"""Optional. Configuration for the built-in HTTP server, controlling which custom routes are exposed
|
||||
and how cross-origin requests are handled.
|
||||
"""
|
||||
|
||||
ui: dict[str, str] | None
|
||||
"""Optional. Named definitions of UI components emitted by the agent, each pointing to a JS/TS file.
|
||||
"""
|
||||
|
||||
keep_pkg_tools: bool | list[str] | None
|
||||
"""Optional. Control whether to retain Python packaging tools in the final image.
|
||||
|
||||
Allowed tools are: "pip", "setuptools", "wheel".
|
||||
You can also set to true to include all packaging tools.
|
||||
"""
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Config",
|
||||
"StoreConfig",
|
||||
"CheckpointerConfig",
|
||||
"AuthConfig",
|
||||
"HttpConfig",
|
||||
"MiddlewareOrders",
|
||||
"Distros",
|
||||
"TTLConfig",
|
||||
"IndexConfig",
|
||||
]
|
||||
+16
-7
@@ -19,28 +19,37 @@ dependencies = [
|
||||
path = "langgraph_cli/__init__.py"
|
||||
[project.optional-dependencies]
|
||||
inmem = [
|
||||
"langgraph-api>=0.3,<0.5.0 ; python_version >= '3.11'",
|
||||
"langgraph-api>=0.4,<0.6.0 ; python_version >= '3.11'",
|
||||
"langgraph-runtime-inmem>=0.7 ; python_version >= '3.11'",
|
||||
"python-dotenv>=0.8.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/cli"
|
||||
Twitter = "https://x.com/LangChainAI"
|
||||
Slack = "https://www.langchain.com/join-community"
|
||||
Reddit = "https://www.reddit.com/r/LangChain/"
|
||||
|
||||
[project.scripts]
|
||||
langgraph = "langgraph_cli.cli:cli"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
test = [
|
||||
"pytest",
|
||||
"pytest-asyncio",
|
||||
"pytest-mock",
|
||||
"pytest-watch",
|
||||
"mypy",
|
||||
"msgspec",
|
||||
]
|
||||
lint = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
"mypy",
|
||||
]
|
||||
dev = [
|
||||
{include-group = "test"},
|
||||
{include-group = "lint"},
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
default-groups = ['dev']
|
||||
@@ -62,4 +71,4 @@ lint.select = [
|
||||
"UP", # pyupgrade
|
||||
]
|
||||
lint.ignore = ["E501", "B008"]
|
||||
target-version = "py310"
|
||||
target-version = "py310"
|
||||
|
||||
@@ -8,7 +8,7 @@ authors = [
|
||||
license = { text = "MIT" }
|
||||
requires-python = ">=3.11,<4.0"
|
||||
dependencies = [
|
||||
"langgraph>=0.6.0,<0.7.0",
|
||||
"langgraph>=0.6.0,<2",
|
||||
"langchain-core>=0.2.14",
|
||||
]
|
||||
|
||||
|
||||
@@ -472,6 +472,17 @@
|
||||
"description": "Configuration for the built-in checkpointer, which handles checkpointing of state.\n\nIf omitted, no checkpointer is set up (the object store will still be present, however).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"serde": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/$defs/SerdeConfig"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional. Defines the serde configuration.\n\nIf provided, the checkpointer will apply serde settings according to the configuration.\nIf omitted, no serde behavior is configured.\n\nThis configuration requires server version 0.5 or later to take effect.\n"
|
||||
},
|
||||
"ttl": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -486,6 +497,38 @@
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"SerdeConfig": {
|
||||
"title": "SerdeConfig",
|
||||
"description": "Configuration for the built-in serde, which handles checkpointing of state.\n\nIf omitted, no serde is set up (the object store will still be present, however).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allowed_json_modules": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional. List of allowed python modules to de-serialize custom objects from.\n\nIf provided, only the specified modules will be allowed to be deserialized.\nIf omitted, no modules are allowed, and the object returned will simply be a json object OR\na deserialized langchain object.\n"
|
||||
},
|
||||
"pickle_fallback": {
|
||||
"type": "boolean",
|
||||
"description": "Optional. Whether to allow pickling as a fallback for deserialization.\n\nIf True, pickling will be allowed as a fallback for deserialization.\nIf False, pickling will not be allowed as a fallback for deserialization.\nDefaults to True if not configured."
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"ThreadTTLConfig": {
|
||||
"title": "ThreadTTLConfig",
|
||||
"description": "Configure a default TTL for checkpointed data within threads.",
|
||||
|
||||
@@ -472,6 +472,17 @@
|
||||
"description": "Configuration for the built-in checkpointer, which handles checkpointing of state.\n\nIf omitted, no checkpointer is set up (the object store will still be present, however).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"serde": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/$defs/SerdeConfig"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional. Defines the serde configuration.\n\nIf provided, the checkpointer will apply serde settings according to the configuration.\nIf omitted, no serde behavior is configured.\n\nThis configuration requires server version 0.5 or later to take effect.\n"
|
||||
},
|
||||
"ttl": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -486,6 +497,38 @@
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"SerdeConfig": {
|
||||
"title": "SerdeConfig",
|
||||
"description": "Configuration for the built-in serde, which handles checkpointing of state.\n\nIf omitted, no serde is set up (the object store will still be present, however).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allowed_json_modules": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"description": "Optional. List of allowed python modules to de-serialize custom objects from.\n\nIf provided, only the specified modules will be allowed to be deserialized.\nIf omitted, no modules are allowed, and the object returned will simply be a json object OR\na deserialized langchain object.\n"
|
||||
},
|
||||
"pickle_fallback": {
|
||||
"type": "boolean",
|
||||
"description": "Optional. Whether to allow pickling as a fallback for deserialization.\n\nIf True, pickling will be allowed as a fallback for deserialization.\nIf False, pickling will not be allowed as a fallback for deserialization.\nDefaults to True if not configured."
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"ThreadTTLConfig": {
|
||||
"title": "ThreadTTLConfig",
|
||||
"description": "Configure a default TTL for checkpointed data within threads.",
|
||||
|
||||
@@ -141,6 +141,7 @@ services:
|
||||
additional_contexts:
|
||||
- cli_1: {str(pathlib.Path(__file__).parent.parent.parent.parent.absolute())}
|
||||
dockerfile_inline: |
|
||||
# syntax=docker/dockerfile:1.4
|
||||
FROM langchain/langgraph-api:3.11
|
||||
# -- Adding local package . --
|
||||
ADD . /deps/cli
|
||||
|
||||
@@ -419,6 +419,7 @@ def test_config_to_docker_simple():
|
||||
"langchain/langgraph-api",
|
||||
)
|
||||
expected_docker_stdin = f"""\
|
||||
# syntax=docker/dockerfile:1.4
|
||||
FROM langchain/langgraph-api:3.11
|
||||
# -- Installing local requirements --
|
||||
COPY --from=outer-requirements.txt requirements.txt /deps/outer-graphs_reqs_a/graphs_reqs_a/requirements.txt
|
||||
@@ -482,6 +483,7 @@ def test_config_to_docker_outside_path():
|
||||
)
|
||||
expected_docker_stdin = (
|
||||
"""\
|
||||
# syntax=docker/dockerfile:1.4
|
||||
FROM langchain/langgraph-api:3.11
|
||||
# -- Adding non-package dependency unit_tests --
|
||||
ADD . /deps/outer-unit_tests/unit_tests
|
||||
|
||||
Generated
+838
-566
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(rg:*)",
|
||||
"Bash(python:*)",
|
||||
"Bash(grep:*)",
|
||||
"Bash(sed:*)",
|
||||
"Bash(awk:*)",
|
||||
"Bash(uv run mypy:*)",
|
||||
"Bash(uv run:*)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ While LangGraph can be used standalone, it also integrates seamlessly with any L
|
||||
|
||||
- [LangSmith](http://www.langchain.com/langsmith) — Helpful for agent evals and observability. Debug poor-performing LLM app runs, evaluate agent trajectories, gain visibility in production, and improve performance over time.
|
||||
- [LangSmith Deployment](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/) — Deploy and scale agents effortlessly with a purpose-built deployment platform for long running, stateful workflows. Discover, reuse, configure, and share agents across teams — and iterate quickly with visual prototyping in [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/).
|
||||
- [LangChain](https://python.langchain.com/docs/introduction/) – Provides integrations and composable components to streamline LLM application development.
|
||||
- [LangChain](https://docs.langchain.com/oss/python/langchain/overview) – Provides integrations and composable components to streamline LLM application development.
|
||||
|
||||
> [!NOTE]
|
||||
> Looking for the JS version of LangGraph? See the [JS repo](https://github.com/langchain-ai/langgraphjs) and the [JS docs](https://langchain-ai.github.io/langgraphjs/).
|
||||
@@ -81,4 +81,4 @@ While LangGraph can be used standalone, it also integrates seamlessly with any L
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
|
||||
LangGraph is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The public interface draws inspiration from [NetworkX](https://networkx.org/documentation/latest/). LangGraph is built by LangChain Inc, the creators of LangChain, but can be used without LangChain.
|
||||
|
||||
@@ -77,6 +77,8 @@ CONF = cast(Literal["configurable"], sys.intern("configurable"))
|
||||
# key for the configurable dict in RunnableConfig
|
||||
NULL_TASK_ID = sys.intern("00000000-0000-0000-0000-000000000000")
|
||||
# the task_id to use for writes that are not associated with a task
|
||||
OVERWRITE = sys.intern("__overwrite__")
|
||||
# dict key for the overwrite value, used as `{'__overwrite__': value}`
|
||||
|
||||
# redefined to avoid circular import with langgraph.constants
|
||||
_TAG_HIDDEN = sys.intern("langsmith:hidden")
|
||||
|
||||
@@ -201,6 +201,10 @@ def get_cached_annotated_keys(obj: type[Any]) -> tuple[str, ...]:
|
||||
keys: list[str] = []
|
||||
for base in reversed(obj.__mro__):
|
||||
ann = base.__dict__.get("__annotations__")
|
||||
# In Python 3.14+, Pydantic models use descriptors for __annotations__
|
||||
# so we need to fall back to getattr if __dict__.get returns None
|
||||
if ann is None:
|
||||
ann = getattr(base, "__annotations__", None)
|
||||
if ann is None or isinstance(ann, types.GetSetDescriptorType):
|
||||
continue
|
||||
keys.extend(ann.keys())
|
||||
|
||||
@@ -481,9 +481,9 @@ def is_async_callable(
|
||||
) -> TypeGuard[Callable[..., Awaitable]]:
|
||||
"""Check if a function is async."""
|
||||
return (
|
||||
asyncio.iscoroutinefunction(func)
|
||||
inspect.iscoroutinefunction(func)
|
||||
or hasattr(func, "__call__")
|
||||
and asyncio.iscoroutinefunction(func.__call__)
|
||||
and inspect.iscoroutinefunction(func.__call__)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class BaseChannel(Generic[Value, Update, Checkpoint], ABC):
|
||||
def is_available(self) -> bool:
|
||||
"""Return `True` if the channel is available (not empty), `False` otherwise.
|
||||
Subclasses should override this method to provide a more efficient
|
||||
implementation than calling get() and catching `EmptyChannelError`.
|
||||
implementation than calling `get()` and catching `EmptyChannelError`.
|
||||
"""
|
||||
try:
|
||||
self.get()
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
import collections.abc
|
||||
from collections.abc import Callable, Sequence
|
||||
from typing import Generic
|
||||
from typing import Any, Generic
|
||||
|
||||
from typing_extensions import NotRequired, Required, Self
|
||||
|
||||
from langgraph._internal._constants import OVERWRITE
|
||||
from langgraph._internal._typing import MISSING
|
||||
from langgraph.channels.base import BaseChannel, Value
|
||||
from langgraph.errors import EmptyChannelError
|
||||
from langgraph.errors import (
|
||||
EmptyChannelError,
|
||||
ErrorCode,
|
||||
InvalidUpdateError,
|
||||
create_error_message,
|
||||
)
|
||||
from langgraph.types import Overwrite
|
||||
|
||||
__all__ = ("BinaryOperatorAggregate",)
|
||||
|
||||
@@ -22,6 +29,15 @@ def _strip_extras(t): # type: ignore[no-untyped-def]
|
||||
return t
|
||||
|
||||
|
||||
def _get_overwrite(value: Any) -> tuple[bool, Any]:
|
||||
"""Inspects the given value and returns (is_overwrite, overwrite_value)."""
|
||||
if isinstance(value, Overwrite):
|
||||
return True, value.value
|
||||
if isinstance(value, dict) and set(value.keys()) == {OVERWRITE}:
|
||||
return True, value[OVERWRITE]
|
||||
return False, None
|
||||
|
||||
|
||||
class BinaryOperatorAggregate(Generic[Value], BaseChannel[Value, Value, Value]):
|
||||
"""Stores the result of applying a binary operator to the current value and each new value.
|
||||
|
||||
@@ -89,8 +105,21 @@ class BinaryOperatorAggregate(Generic[Value], BaseChannel[Value, Value, Value]):
|
||||
if self.value is MISSING:
|
||||
self.value = values[0]
|
||||
values = values[1:]
|
||||
seen_overwrite: bool = False
|
||||
for value in values:
|
||||
self.value = self.operator(self.value, value)
|
||||
is_overwrite, overwrite_value = _get_overwrite(value)
|
||||
if is_overwrite:
|
||||
if seen_overwrite:
|
||||
msg = create_error_message(
|
||||
message="Can receive only one Overwrite value per super-step.",
|
||||
error_code=ErrorCode.INVALID_CONCURRENT_GRAPH_UPDATE,
|
||||
)
|
||||
raise InvalidUpdateError(msg)
|
||||
self.value = overwrite_value
|
||||
seen_overwrite = True
|
||||
continue
|
||||
if not seen_overwrite:
|
||||
self.value = self.operator(self.value, value)
|
||||
return True
|
||||
|
||||
def get(self) -> Value:
|
||||
|
||||
@@ -37,8 +37,8 @@ class ErrorCode(Enum):
|
||||
def create_error_message(*, message: str, error_code: ErrorCode) -> str:
|
||||
return (
|
||||
f"{message}\n"
|
||||
"For troubleshooting, visit: https://python.langchain.com/docs/"
|
||||
f"troubleshooting/errors/{error_code.value}"
|
||||
"For troubleshooting, visit: https://docs.langchain.com/oss/python/langgraph/"
|
||||
f"errors/{error_code.value}"
|
||||
)
|
||||
|
||||
|
||||
@@ -48,9 +48,9 @@ class GraphRecursionError(RecursionError):
|
||||
This prevents infinite loops. To increase the maximum number of steps,
|
||||
run your graph with a config specifying a higher `recursion_limit`.
|
||||
|
||||
Troubleshooting Guides:
|
||||
Troubleshooting guides:
|
||||
|
||||
- [GRAPH_RECURSION_LIMIT](https://docs.langchain.com/oss/python/langgraph/GRAPH_RECURSION_LIMIT)
|
||||
- [`GRAPH_RECURSION_LIMIT`](https://docs.langchain.com/oss/python/langgraph/GRAPH_RECURSION_LIMIT)
|
||||
|
||||
Examples:
|
||||
|
||||
@@ -68,10 +68,10 @@ class GraphRecursionError(RecursionError):
|
||||
class InvalidUpdateError(Exception):
|
||||
"""Raised when attempting to update a channel with an invalid set of updates.
|
||||
|
||||
Troubleshooting Guides:
|
||||
Troubleshooting guides:
|
||||
|
||||
- [INVALID_CONCURRENT_GRAPH_UPDATE](https://docs.langchain.com/oss/python/langgraph/INVALID_CONCURRENT_GRAPH_UPDATE)
|
||||
- [INVALID_GRAPH_NODE_RETURN_VALUE](https://docs.langchain.com/oss/python/langgraph/INVALID_GRAPH_NODE_RETURN_VALUE)
|
||||
- [`INVALID_CONCURRENT_GRAPH_UPDATE`](https://docs.langchain.com/oss/python/langgraph/INVALID_CONCURRENT_GRAPH_UPDATE)
|
||||
- [`INVALID_GRAPH_NODE_RETURN_VALUE`](https://docs.langchain.com/oss/python/langgraph/INVALID_GRAPH_NODE_RETURN_VALUE)
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
@@ -151,13 +151,13 @@ def task(
|
||||
|
||||
|
||||
@task
|
||||
def add_one(a: int) -> int:
|
||||
def add_one_task(a: int) -> int:
|
||||
return a + 1
|
||||
|
||||
|
||||
@entrypoint()
|
||||
def add_one(numbers: list[int]) -> list[int]:
|
||||
futures = [add_one(n) for n in numbers]
|
||||
futures = [add_one_task(n) for n in numbers]
|
||||
results = [f.result() for f in futures]
|
||||
return results
|
||||
|
||||
@@ -173,13 +173,13 @@ def task(
|
||||
|
||||
|
||||
@task
|
||||
async def add_one(a: int) -> int:
|
||||
async def add_one_task(a: int) -> int:
|
||||
return a + 1
|
||||
|
||||
|
||||
@entrypoint()
|
||||
async def add_one(numbers: list[int]) -> list[int]:
|
||||
futures = [add_one(n) for n in numbers]
|
||||
futures = [add_one_task(n) for n in numbers]
|
||||
return asyncio.gather(*futures)
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ __all__ = (
|
||||
"add_messages",
|
||||
"MessagesState",
|
||||
"MessageGraph",
|
||||
"REMOVE_ALL_MESSAGES",
|
||||
)
|
||||
|
||||
Messages = list[MessageLikeRepresentation] | MessageLikeRepresentation
|
||||
@@ -69,11 +70,11 @@ def add_messages(
|
||||
new message has the same ID as an existing message.
|
||||
|
||||
Args:
|
||||
left: The base list of messages.
|
||||
right: The list of messages (or single message) to merge
|
||||
left: The base list of `Messages`.
|
||||
right: The list of `Messages` (or single `Message`) to merge
|
||||
into the base list.
|
||||
format: The format to return messages in. If `None` then messages will be
|
||||
returned as is. If `langchain-openai` then messages will be returned as
|
||||
format: The format to return messages in. If `None` then `Messages` will be
|
||||
returned as is. If `langchain-openai` then `Messages` will be returned as
|
||||
`BaseMessage` objects with their contents formatted to match OpenAI message
|
||||
format, meaning contents can be string, `'text'` blocks, or `'image_url'` blocks
|
||||
and tool responses are returned as their own `ToolMessage` objects.
|
||||
@@ -85,7 +86,7 @@ def add_messages(
|
||||
Returns:
|
||||
A new list of messages with the messages from `right` merged into `left`.
|
||||
If a message in `right` has the same ID as a message in `left`, the
|
||||
message from `right` will replace the message from `left`.
|
||||
message from `right` will replace the message from `left`.
|
||||
|
||||
Example:
|
||||
```python title="Basic usage"
|
||||
|
||||
@@ -110,11 +110,19 @@ def _get_node_name(node: StateNode[Any, ContextT]) -> str:
|
||||
|
||||
class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
"""A graph whose nodes communicate by reading and writing to a shared state.
|
||||
The signature of each node is State -> Partial<State>.
|
||||
|
||||
The signature of each node is `State -> Partial<State>`.
|
||||
|
||||
Each state key can optionally be annotated with a reducer function that
|
||||
will be used to aggregate the values of that key received from multiple nodes.
|
||||
The signature of a reducer function is (Value, Value) -> Value.
|
||||
The signature of a reducer function is `(Value, Value) -> Value`.
|
||||
|
||||
!!! warning
|
||||
|
||||
`StateGraph` is a builder class and cannot be used directly for execution.
|
||||
You must first call `.compile()` to create an executable graph that supports
|
||||
methods like `invoke()`, `stream()`, `astream()`, and `ainvoke()`. See the
|
||||
`CompiledStateGraph` documentation for more details.
|
||||
|
||||
Args:
|
||||
state_schema: The schema class that defines the state.
|
||||
@@ -289,7 +297,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
destinations: dict[str, str] | tuple[str, ...] | None = None,
|
||||
**kwargs: Unpack[DeprecatedKwargs],
|
||||
) -> Self:
|
||||
"""Add a new node to the state graph, input schema is inferred as the state schema.
|
||||
"""Add a new node to the `StateGraph`, input schema is inferred as the state schema.
|
||||
Will take the name of the function/runnable as the node name.
|
||||
"""
|
||||
...
|
||||
@@ -307,7 +315,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
destinations: dict[str, str] | tuple[str, ...] | None = None,
|
||||
**kwargs: Unpack[DeprecatedKwargs],
|
||||
) -> Self:
|
||||
"""Add a new node to the state graph, input schema is specified.
|
||||
"""Add a new node to the `StateGraph`, input schema is specified.
|
||||
Will take the name of the function/runnable as the node name.
|
||||
"""
|
||||
...
|
||||
@@ -326,7 +334,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
destinations: dict[str, str] | tuple[str, ...] | None = None,
|
||||
**kwargs: Unpack[DeprecatedKwargs],
|
||||
) -> Self:
|
||||
"""Add a new node to the state graph, input schema is inferred as the state schema."""
|
||||
"""Add a new node to the `StateGraph`, input schema is inferred as the state schema."""
|
||||
...
|
||||
|
||||
@overload
|
||||
@@ -343,7 +351,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
destinations: dict[str, str] | tuple[str, ...] | None = None,
|
||||
**kwargs: Unpack[DeprecatedKwargs],
|
||||
) -> Self:
|
||||
"""Add a new node to the state graph, input schema is specified."""
|
||||
"""Add a new node to the `StateGraph`, input schema is specified."""
|
||||
...
|
||||
|
||||
def add_node(
|
||||
@@ -359,7 +367,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
destinations: dict[str, str] | tuple[str, ...] | None = None,
|
||||
**kwargs: Unpack[DeprecatedKwargs],
|
||||
) -> Self:
|
||||
"""Add a new node to the state graph.
|
||||
"""Add a new node to the `StateGraph`.
|
||||
|
||||
Args:
|
||||
node: The function or runnable this node will run.
|
||||
@@ -374,10 +382,11 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
cache_policy: The cache policy for the node.
|
||||
destinations: Destinations that indicate where a node can route to.
|
||||
This is useful for edgeless graphs with nodes that return `Command` objects.
|
||||
If a dict is provided, the keys will be used as the target node names and the values will be used as the labels for the edges.
|
||||
If a tuple is provided, the values will be used as the target node names.
|
||||
If a `dict` is provided, the keys will be used as the target node names and the values will be used as the labels for the edges.
|
||||
If a `tuple` is provided, the values will be used as the target node names.
|
||||
|
||||
!!! note
|
||||
|
||||
This is only used for graph rendering and doesn't have any effect on the graph execution.
|
||||
|
||||
Example:
|
||||
@@ -415,7 +424,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
```
|
||||
|
||||
Returns:
|
||||
Self: The instance of the state graph, allowing for method chaining.
|
||||
Self: The instance of the `StateGraph`, allowing for method chaining.
|
||||
"""
|
||||
if (retry := kwargs.get("retry", MISSING)) is not MISSING:
|
||||
warnings.warn(
|
||||
@@ -570,7 +579,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
ValueError: If the start key is `'END'` or if the start key or end key is not present in the graph.
|
||||
|
||||
Returns:
|
||||
Self: The instance of the state graph, allowing for method chaining.
|
||||
Self: The instance of the `StateGraph`, allowing for method chaining.
|
||||
"""
|
||||
if self.compiled:
|
||||
logger.warning(
|
||||
@@ -632,7 +641,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
Self: The instance of the graph, allowing for method chaining.
|
||||
|
||||
!!! warning
|
||||
Without typehints on the `path` function's return value (e.g., `-> Literal["foo", "__end__"]:`)
|
||||
Without type hints on the `path` function's return value (e.g., `-> Literal["foo", "__end__"]:`)
|
||||
or a path_map, the graph visualization assumes the edge could transition to any node in the graph.
|
||||
|
||||
""" # noqa: E501
|
||||
@@ -675,7 +684,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
ValueError: If the sequence contains duplicate node names.
|
||||
|
||||
Returns:
|
||||
Self: The instance of the state graph, allowing for method chaining.
|
||||
Self: The instance of the `StateGraph`, allowing for method chaining.
|
||||
"""
|
||||
if len(nodes) < 1:
|
||||
raise ValueError("Sequence requires at least one node.")
|
||||
@@ -808,7 +817,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
debug: bool = False,
|
||||
name: str | None = None,
|
||||
) -> CompiledStateGraph[StateT, ContextT, InputT, OutputT]:
|
||||
"""Compiles the state graph into a `CompiledStateGraph` object.
|
||||
"""Compiles the `StateGraph` into a `CompiledStateGraph` object.
|
||||
|
||||
The compiled graph implements the `Runnable` interface and can be invoked,
|
||||
streamed, batched, and run asynchronously.
|
||||
@@ -825,7 +834,7 @@ class StateGraph(Generic[StateT, ContextT, InputT, OutputT]):
|
||||
name: The name to use for the compiled graph.
|
||||
|
||||
Returns:
|
||||
CompiledStateGraph: The compiled state graph.
|
||||
CompiledStateGraph: The compiled `StateGraph`.
|
||||
"""
|
||||
# assign default values
|
||||
interrupt_before = interrupt_before or []
|
||||
|
||||
@@ -81,9 +81,8 @@ def push_ui_message(
|
||||
metadata: Optional additional metadata about the UI message.
|
||||
message: Optional message object to associate with the UI message.
|
||||
state_key: Key in the graph state where the UI messages are stored.
|
||||
Defaults to "ui".
|
||||
merge: Whether to merge props with existing UI message (True) or replace
|
||||
them (False). Defaults to False.
|
||||
them (False).
|
||||
|
||||
Returns:
|
||||
The created UI message.
|
||||
|
||||
@@ -63,6 +63,7 @@ from langgraph._internal._scratchpad import PregelScratchpad
|
||||
from langgraph._internal._typing import EMPTY_SEQ, MISSING
|
||||
from langgraph.channels.base import BaseChannel
|
||||
from langgraph.channels.topic import Topic
|
||||
from langgraph.channels.untracked_value import UntrackedValue
|
||||
from langgraph.constants import TAG_HIDDEN
|
||||
from langgraph.managed.base import ManagedValueMapping
|
||||
from langgraph.pregel._call import get_runnable_for_task, identifier
|
||||
@@ -257,9 +258,11 @@ def apply_writes(
|
||||
next_version = None
|
||||
else:
|
||||
next_version = get_next_version(
|
||||
max(checkpoint["channel_versions"].values())
|
||||
if checkpoint["channel_versions"]
|
||||
else None,
|
||||
(
|
||||
max(checkpoint["channel_versions"].values())
|
||||
if checkpoint["channel_versions"]
|
||||
else None
|
||||
),
|
||||
None,
|
||||
)
|
||||
|
||||
@@ -490,6 +493,11 @@ def prepare_next_tasks(
|
||||
PUSH_TRIGGER = (PUSH,)
|
||||
|
||||
|
||||
class _TaskIDFn(Protocol):
|
||||
def __call__(self, namespace: bytes, *parts: str | bytes) -> str:
|
||||
pass
|
||||
|
||||
|
||||
def prepare_single_task(
|
||||
task_path: tuple[Any, ...],
|
||||
task_id_checksum: str | None,
|
||||
@@ -519,249 +527,50 @@ def prepare_single_task(
|
||||
task_id_func = _xxhash_str if checkpoint["v"] > 1 else _uuid5_str
|
||||
|
||||
if task_path[0] == PUSH and isinstance(task_path[-1], Call):
|
||||
# (PUSH, parent task path, idx of PUSH write, id of parent task, Call)
|
||||
task_path_t = cast(tuple[str, tuple, int, str, Call], task_path)
|
||||
call = task_path_t[-1]
|
||||
proc_ = get_runnable_for_task(call.func)
|
||||
name = proc_.name
|
||||
if name is None:
|
||||
raise ValueError("`call` functions must have a `__name__` attribute")
|
||||
# create task id
|
||||
triggers: Sequence[str] = PUSH_TRIGGER
|
||||
checkpoint_ns = f"{parent_ns}{NS_SEP}{name}" if parent_ns else name
|
||||
task_id = task_id_func(
|
||||
checkpoint_id_bytes,
|
||||
checkpoint_ns,
|
||||
str(step),
|
||||
name,
|
||||
PUSH,
|
||||
task_path_str(task_path[1]),
|
||||
str(task_path[2]),
|
||||
return prepare_push_task_functional(
|
||||
cast(tuple[str, tuple, int, str, Call], task_path),
|
||||
task_id_checksum,
|
||||
checkpoint=checkpoint,
|
||||
checkpoint_id_bytes=checkpoint_id_bytes,
|
||||
pending_writes=pending_writes,
|
||||
channels=channels,
|
||||
managed=managed,
|
||||
config=config,
|
||||
step=step,
|
||||
stop=stop,
|
||||
for_execution=for_execution,
|
||||
store=store,
|
||||
checkpointer=checkpointer,
|
||||
manager=manager,
|
||||
cache_policy=cache_policy,
|
||||
retry_policy=retry_policy,
|
||||
parent_ns=parent_ns,
|
||||
task_id_func=task_id_func,
|
||||
)
|
||||
task_checkpoint_ns = f"{checkpoint_ns}:{task_id}"
|
||||
# we append True to the task path to indicate that a call is being
|
||||
# made, so we should not return interrupts from this task (responsibility lies with the parent)
|
||||
task_path = (*task_path[:3], True)
|
||||
metadata = {
|
||||
"langgraph_step": step,
|
||||
"langgraph_node": name,
|
||||
"langgraph_triggers": triggers,
|
||||
"langgraph_path": task_path,
|
||||
"langgraph_checkpoint_ns": task_checkpoint_ns,
|
||||
}
|
||||
if task_id_checksum is not None:
|
||||
assert task_id == task_id_checksum, f"{task_id} != {task_id_checksum}"
|
||||
if for_execution:
|
||||
writes: deque[tuple[str, Any]] = deque()
|
||||
cache_policy = call.cache_policy or cache_policy
|
||||
if cache_policy:
|
||||
args_key = cache_policy.key_func(*call.input[0], **call.input[1])
|
||||
cache_key: CacheKey | None = CacheKey(
|
||||
(
|
||||
CACHE_NS_WRITES,
|
||||
(identifier(call.func) or "__dynamic__"),
|
||||
),
|
||||
xxh3_128_hexdigest(
|
||||
args_key.encode() if isinstance(args_key, str) else args_key,
|
||||
),
|
||||
cache_policy.ttl,
|
||||
)
|
||||
else:
|
||||
cache_key = None
|
||||
scratchpad = _scratchpad(
|
||||
config[CONF].get(CONFIG_KEY_SCRATCHPAD),
|
||||
pending_writes,
|
||||
task_id,
|
||||
xxh3_128_hexdigest(task_checkpoint_ns.encode()),
|
||||
config[CONF].get(CONFIG_KEY_RESUME_MAP),
|
||||
step,
|
||||
stop,
|
||||
)
|
||||
runtime = cast(
|
||||
Runtime, configurable.get(CONFIG_KEY_RUNTIME, DEFAULT_RUNTIME)
|
||||
)
|
||||
runtime = runtime.override(store=store)
|
||||
return PregelExecutableTask(
|
||||
name,
|
||||
call.input,
|
||||
proc_,
|
||||
writes,
|
||||
patch_config(
|
||||
merge_configs(config, {"metadata": metadata}),
|
||||
run_name=name,
|
||||
callbacks=call.callbacks
|
||||
or (manager.get_child(f"graph:step:{step}") if manager else None),
|
||||
configurable={
|
||||
CONFIG_KEY_TASK_ID: task_id,
|
||||
# deque.extend is thread-safe
|
||||
CONFIG_KEY_SEND: writes.extend,
|
||||
CONFIG_KEY_READ: partial(
|
||||
local_read,
|
||||
scratchpad,
|
||||
channels,
|
||||
managed,
|
||||
PregelTaskWrites(task_path, name, writes, triggers),
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINTER: (
|
||||
checkpointer or configurable.get(CONFIG_KEY_CHECKPOINTER)
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINT_MAP: {
|
||||
**configurable.get(CONFIG_KEY_CHECKPOINT_MAP, {}),
|
||||
parent_ns: checkpoint["id"],
|
||||
},
|
||||
CONFIG_KEY_CHECKPOINT_ID: None,
|
||||
CONFIG_KEY_CHECKPOINT_NS: task_checkpoint_ns,
|
||||
CONFIG_KEY_SCRATCHPAD: scratchpad,
|
||||
CONFIG_KEY_RUNTIME: runtime,
|
||||
},
|
||||
),
|
||||
triggers,
|
||||
call.retry_policy or retry_policy,
|
||||
cache_key,
|
||||
task_id,
|
||||
task_path,
|
||||
)
|
||||
else:
|
||||
return PregelTask(task_id, name, task_path)
|
||||
|
||||
elif task_path[0] == PUSH:
|
||||
if len(task_path) == 2:
|
||||
# SEND tasks, executed in superstep n+1
|
||||
# (PUSH, idx of pending send)
|
||||
idx = cast(int, task_path[1])
|
||||
if not channels[TASKS].is_available():
|
||||
return
|
||||
sends: Sequence[Send] = channels[TASKS].get()
|
||||
if idx < 0 or idx >= len(sends):
|
||||
return
|
||||
packet = sends[idx]
|
||||
if not isinstance(packet, Send):
|
||||
logger.warning(
|
||||
f"Ignoring invalid packet type {type(packet)} in pending sends"
|
||||
)
|
||||
return
|
||||
if packet.node not in processes:
|
||||
logger.warning(
|
||||
f"Ignoring unknown node name {packet.node} in pending sends"
|
||||
)
|
||||
return
|
||||
# find process
|
||||
proc = processes[packet.node]
|
||||
proc_node = proc.node
|
||||
if proc_node is None:
|
||||
return
|
||||
# create task id
|
||||
triggers = PUSH_TRIGGER
|
||||
checkpoint_ns = (
|
||||
f"{parent_ns}{NS_SEP}{packet.node}" if parent_ns else packet.node
|
||||
)
|
||||
task_id = task_id_func(
|
||||
checkpoint_id_bytes,
|
||||
checkpoint_ns,
|
||||
str(step),
|
||||
packet.node,
|
||||
PUSH,
|
||||
str(idx),
|
||||
)
|
||||
else:
|
||||
logger.warning(f"Ignoring invalid PUSH task path {task_path}")
|
||||
return
|
||||
task_checkpoint_ns = f"{checkpoint_ns}:{task_id}"
|
||||
# we append False to the task path to indicate that a call is not being made
|
||||
# so we should return interrupts from this task
|
||||
task_path = (*task_path[:3], False)
|
||||
metadata = {
|
||||
"langgraph_step": step,
|
||||
"langgraph_node": packet.node,
|
||||
"langgraph_triggers": triggers,
|
||||
"langgraph_path": task_path,
|
||||
"langgraph_checkpoint_ns": task_checkpoint_ns,
|
||||
}
|
||||
if task_id_checksum is not None:
|
||||
assert task_id == task_id_checksum, f"{task_id} != {task_id_checksum}"
|
||||
if for_execution:
|
||||
if proc.metadata:
|
||||
metadata.update(proc.metadata)
|
||||
writes = deque()
|
||||
cache_policy = proc.cache_policy or cache_policy
|
||||
if cache_policy:
|
||||
args_key = cache_policy.key_func(packet.arg)
|
||||
cache_key = CacheKey(
|
||||
(
|
||||
CACHE_NS_WRITES,
|
||||
(identifier(proc) or "__dynamic__"),
|
||||
packet.node,
|
||||
),
|
||||
xxh3_128_hexdigest(
|
||||
args_key.encode() if isinstance(args_key, str) else args_key,
|
||||
),
|
||||
cache_policy.ttl,
|
||||
)
|
||||
else:
|
||||
cache_key = None
|
||||
scratchpad = _scratchpad(
|
||||
config[CONF].get(CONFIG_KEY_SCRATCHPAD),
|
||||
pending_writes,
|
||||
task_id,
|
||||
xxh3_128_hexdigest(task_checkpoint_ns.encode()),
|
||||
config[CONF].get(CONFIG_KEY_RESUME_MAP),
|
||||
step,
|
||||
stop,
|
||||
)
|
||||
runtime = cast(
|
||||
Runtime, configurable.get(CONFIG_KEY_RUNTIME, DEFAULT_RUNTIME)
|
||||
)
|
||||
runtime = runtime.override(
|
||||
store=store, previous=checkpoint["channel_values"].get(PREVIOUS, None)
|
||||
)
|
||||
additional_config: RunnableConfig = {
|
||||
"metadata": metadata,
|
||||
"tags": proc.tags,
|
||||
}
|
||||
return PregelExecutableTask(
|
||||
packet.node,
|
||||
packet.arg,
|
||||
proc_node,
|
||||
writes,
|
||||
patch_config(
|
||||
merge_configs(config, additional_config),
|
||||
run_name=packet.node,
|
||||
callbacks=(
|
||||
manager.get_child(f"graph:step:{step}") if manager else None
|
||||
),
|
||||
configurable={
|
||||
CONFIG_KEY_TASK_ID: task_id,
|
||||
# deque.extend is thread-safe
|
||||
CONFIG_KEY_SEND: writes.extend,
|
||||
CONFIG_KEY_READ: partial(
|
||||
local_read,
|
||||
scratchpad,
|
||||
channels,
|
||||
managed,
|
||||
PregelTaskWrites(task_path, packet.node, writes, triggers),
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINTER: (
|
||||
checkpointer or configurable.get(CONFIG_KEY_CHECKPOINTER)
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINT_MAP: {
|
||||
**configurable.get(CONFIG_KEY_CHECKPOINT_MAP, {}),
|
||||
parent_ns: checkpoint["id"],
|
||||
},
|
||||
CONFIG_KEY_CHECKPOINT_ID: None,
|
||||
CONFIG_KEY_CHECKPOINT_NS: task_checkpoint_ns,
|
||||
CONFIG_KEY_SCRATCHPAD: scratchpad,
|
||||
CONFIG_KEY_RUNTIME: runtime,
|
||||
},
|
||||
),
|
||||
triggers,
|
||||
proc.retry_policy or retry_policy,
|
||||
cache_key,
|
||||
task_id,
|
||||
task_path,
|
||||
writers=proc.flat_writers,
|
||||
subgraphs=proc.subgraphs,
|
||||
)
|
||||
else:
|
||||
return PregelTask(task_id, packet.node, task_path)
|
||||
return prepare_push_task_send(
|
||||
cast(tuple[str, tuple], task_path),
|
||||
task_id_checksum,
|
||||
checkpoint=checkpoint,
|
||||
checkpoint_id_bytes=checkpoint_id_bytes,
|
||||
pending_writes=pending_writes,
|
||||
channels=channels,
|
||||
managed=managed,
|
||||
config=config,
|
||||
step=step,
|
||||
processes=processes,
|
||||
stop=stop,
|
||||
for_execution=for_execution,
|
||||
store=store,
|
||||
checkpointer=checkpointer,
|
||||
manager=manager,
|
||||
cache_policy=cache_policy,
|
||||
retry_policy=retry_policy,
|
||||
parent_ns=parent_ns,
|
||||
task_id_func=task_id_func,
|
||||
)
|
||||
|
||||
elif task_path[0] == PULL:
|
||||
# (PULL, node name)
|
||||
name = cast(str, task_path[1])
|
||||
@@ -832,7 +641,7 @@ def prepare_single_task(
|
||||
if node := proc.node:
|
||||
if proc.metadata:
|
||||
metadata.update(proc.metadata)
|
||||
writes = deque()
|
||||
writes: deque[tuple[str, Any]] = deque()
|
||||
cache_policy = proc.cache_policy or cache_policy
|
||||
if cache_policy:
|
||||
args_key = cache_policy.key_func(val)
|
||||
@@ -843,9 +652,11 @@ def prepare_single_task(
|
||||
name,
|
||||
),
|
||||
xxh3_128_hexdigest(
|
||||
args_key.encode()
|
||||
if isinstance(args_key, str)
|
||||
else args_key,
|
||||
(
|
||||
args_key.encode()
|
||||
if isinstance(args_key, str)
|
||||
else args_key
|
||||
),
|
||||
),
|
||||
cache_policy.ttl,
|
||||
)
|
||||
@@ -868,7 +679,9 @@ def prepare_single_task(
|
||||
node,
|
||||
writes,
|
||||
patch_config(
|
||||
merge_configs(config, additional_config),
|
||||
merge_configs(
|
||||
config, cast(RunnableConfig, additional_config)
|
||||
),
|
||||
run_name=name,
|
||||
callbacks=(
|
||||
manager.get_child(f"graph:step:{step}")
|
||||
@@ -917,6 +730,297 @@ def prepare_single_task(
|
||||
return PregelTask(task_id, name, task_path[:3])
|
||||
|
||||
|
||||
def prepare_push_task_functional(
|
||||
task_path: tuple[str, tuple, int, str, Call],
|
||||
# (PUSH, parent task path, idx of PUSH write, id of parent task, Call)
|
||||
task_id_checksum: str | None,
|
||||
*,
|
||||
checkpoint: Checkpoint,
|
||||
checkpoint_id_bytes: bytes,
|
||||
pending_writes: list[PendingWrite],
|
||||
channels: Mapping[str, BaseChannel],
|
||||
managed: ManagedValueMapping,
|
||||
config: RunnableConfig,
|
||||
step: int,
|
||||
stop: int,
|
||||
for_execution: bool,
|
||||
store: BaseStore | None = None,
|
||||
checkpointer: BaseCheckpointSaver | None = None,
|
||||
manager: None | ParentRunManager | AsyncParentRunManager = None,
|
||||
cache_policy: CachePolicy | None = None,
|
||||
retry_policy: Sequence[RetryPolicy] = (),
|
||||
parent_ns: str,
|
||||
# namespace: bytes, *parts: str | bytes
|
||||
task_id_func: _TaskIDFn,
|
||||
) -> PregelTask | PregelExecutableTask:
|
||||
"""Prepare a push task with an attached caller. Used for the functional API."""
|
||||
configurable = config.get(CONF, {})
|
||||
|
||||
call = task_path[-1]
|
||||
proc_ = get_runnable_for_task(call.func)
|
||||
name = proc_.name
|
||||
if name is None:
|
||||
raise ValueError("`call` functions must have a `__name__` attribute")
|
||||
# create task id
|
||||
triggers: Sequence[str] = PUSH_TRIGGER
|
||||
checkpoint_ns = f"{parent_ns}{NS_SEP}{name}" if parent_ns else name
|
||||
task_id = task_id_func(
|
||||
checkpoint_id_bytes,
|
||||
checkpoint_ns,
|
||||
str(step),
|
||||
name,
|
||||
PUSH,
|
||||
task_path_str(task_path[1]),
|
||||
str(task_path[2]),
|
||||
)
|
||||
task_checkpoint_ns = f"{checkpoint_ns}:{task_id}"
|
||||
# we append True to the task path to indicate that a call is being
|
||||
# made, so we should not return interrupts from this task (responsibility lies with the parent)
|
||||
in_progress_task_path = (*task_path[:3], True)
|
||||
metadata = {
|
||||
"langgraph_step": step,
|
||||
"langgraph_node": name,
|
||||
"langgraph_triggers": triggers,
|
||||
"langgraph_path": in_progress_task_path,
|
||||
"langgraph_checkpoint_ns": task_checkpoint_ns,
|
||||
}
|
||||
if task_id_checksum is not None:
|
||||
assert task_id == task_id_checksum, f"{task_id} != {task_id_checksum}"
|
||||
if for_execution:
|
||||
writes: deque[tuple[str, Any]] = deque()
|
||||
cache_policy = call.cache_policy or cache_policy
|
||||
if cache_policy:
|
||||
args_key = cache_policy.key_func(*call.input[0], **call.input[1])
|
||||
cache_key: CacheKey | None = CacheKey(
|
||||
(
|
||||
CACHE_NS_WRITES,
|
||||
(identifier(call.func) or "__dynamic__"),
|
||||
),
|
||||
xxh3_128_hexdigest(
|
||||
args_key.encode() if isinstance(args_key, str) else args_key,
|
||||
),
|
||||
cache_policy.ttl,
|
||||
)
|
||||
else:
|
||||
cache_key = None
|
||||
scratchpad = _scratchpad(
|
||||
configurable.get(CONFIG_KEY_SCRATCHPAD),
|
||||
pending_writes,
|
||||
task_id,
|
||||
xxh3_128_hexdigest(task_checkpoint_ns.encode()),
|
||||
configurable.get(CONFIG_KEY_RESUME_MAP),
|
||||
step,
|
||||
stop,
|
||||
)
|
||||
runtime = cast(Runtime, configurable.get(CONFIG_KEY_RUNTIME, DEFAULT_RUNTIME))
|
||||
runtime = runtime.override(store=store)
|
||||
return PregelExecutableTask(
|
||||
name,
|
||||
call.input,
|
||||
proc_,
|
||||
writes,
|
||||
patch_config(
|
||||
merge_configs(config, {"metadata": metadata}),
|
||||
run_name=name,
|
||||
callbacks=call.callbacks
|
||||
or (manager.get_child(f"graph:step:{step}") if manager else None),
|
||||
configurable={
|
||||
CONFIG_KEY_TASK_ID: task_id,
|
||||
# deque.extend is thread-safe
|
||||
CONFIG_KEY_SEND: writes.extend,
|
||||
CONFIG_KEY_READ: partial(
|
||||
local_read,
|
||||
scratchpad,
|
||||
channels,
|
||||
managed,
|
||||
PregelTaskWrites(in_progress_task_path, name, writes, triggers),
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINTER: (
|
||||
checkpointer or configurable.get(CONFIG_KEY_CHECKPOINTER)
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINT_MAP: {
|
||||
**configurable.get(CONFIG_KEY_CHECKPOINT_MAP, {}),
|
||||
parent_ns: checkpoint["id"],
|
||||
},
|
||||
CONFIG_KEY_CHECKPOINT_ID: None,
|
||||
CONFIG_KEY_CHECKPOINT_NS: task_checkpoint_ns,
|
||||
CONFIG_KEY_SCRATCHPAD: scratchpad,
|
||||
CONFIG_KEY_RUNTIME: runtime,
|
||||
},
|
||||
),
|
||||
triggers,
|
||||
call.retry_policy or retry_policy,
|
||||
cache_key,
|
||||
task_id,
|
||||
in_progress_task_path,
|
||||
)
|
||||
else:
|
||||
return PregelTask(task_id, name, in_progress_task_path)
|
||||
|
||||
|
||||
def prepare_push_task_send(
|
||||
task_path: tuple[str, tuple],
|
||||
# (PUSH, parent task path)
|
||||
task_id_checksum: str | None,
|
||||
*,
|
||||
checkpoint: Checkpoint,
|
||||
checkpoint_id_bytes: bytes,
|
||||
pending_writes: list[PendingWrite],
|
||||
channels: Mapping[str, BaseChannel],
|
||||
managed: ManagedValueMapping,
|
||||
config: RunnableConfig,
|
||||
step: int,
|
||||
stop: int,
|
||||
for_execution: bool,
|
||||
store: BaseStore | None = None,
|
||||
checkpointer: BaseCheckpointSaver | None = None,
|
||||
manager: None | ParentRunManager | AsyncParentRunManager = None,
|
||||
cache_policy: CachePolicy | None = None,
|
||||
retry_policy: Sequence[RetryPolicy] = (),
|
||||
parent_ns: str,
|
||||
task_id_func: _TaskIDFn,
|
||||
processes: Mapping[str, PregelNode],
|
||||
) -> PregelTask | PregelExecutableTask | None:
|
||||
if len(task_path) == 2:
|
||||
# SEND tasks, executed in superstep n+1
|
||||
# (PUSH, idx of pending send)
|
||||
idx = cast(int, task_path[1])
|
||||
if not channels[TASKS].is_available():
|
||||
return
|
||||
sends: Sequence[Send] = channels[TASKS].get()
|
||||
if idx < 0 or idx >= len(sends):
|
||||
return
|
||||
packet = sends[idx]
|
||||
if not isinstance(packet, Send):
|
||||
logger.warning(
|
||||
f"Ignoring invalid packet type {type(packet)} in pending sends"
|
||||
)
|
||||
return
|
||||
|
||||
if packet.node not in processes:
|
||||
logger.warning(f"Ignoring unknown node name {packet.node} in pending sends")
|
||||
return
|
||||
# find process
|
||||
proc = processes[packet.node]
|
||||
proc_node = proc.node
|
||||
if proc_node is None:
|
||||
return
|
||||
# create task id
|
||||
triggers = PUSH_TRIGGER
|
||||
checkpoint_ns = (
|
||||
f"{parent_ns}{NS_SEP}{packet.node}" if parent_ns else packet.node
|
||||
)
|
||||
task_id = task_id_func(
|
||||
checkpoint_id_bytes,
|
||||
checkpoint_ns,
|
||||
str(step),
|
||||
packet.node,
|
||||
PUSH,
|
||||
str(idx),
|
||||
)
|
||||
else:
|
||||
logger.warning(f"Ignoring invalid PUSH task path {task_path}")
|
||||
return
|
||||
configurable = config.get(CONF, {})
|
||||
task_checkpoint_ns = f"{checkpoint_ns}:{task_id}"
|
||||
# we append False to the task path to indicate that a call is not being made
|
||||
# so we should return interrupts from this task
|
||||
translated_task_path = (*task_path[:3], False)
|
||||
metadata = {
|
||||
"langgraph_step": step,
|
||||
"langgraph_node": packet.node,
|
||||
"langgraph_triggers": triggers,
|
||||
"langgraph_path": translated_task_path,
|
||||
"langgraph_checkpoint_ns": task_checkpoint_ns,
|
||||
}
|
||||
if task_id_checksum is not None:
|
||||
assert task_id == task_id_checksum, f"{task_id} != {task_id_checksum}"
|
||||
if for_execution:
|
||||
if proc.metadata:
|
||||
metadata.update(proc.metadata)
|
||||
writes: deque[tuple[str, Any]] = deque()
|
||||
cache_policy = proc.cache_policy or cache_policy
|
||||
if cache_policy:
|
||||
args_key = cache_policy.key_func(packet.arg)
|
||||
cache_key = CacheKey(
|
||||
(
|
||||
CACHE_NS_WRITES,
|
||||
(identifier(proc) or "__dynamic__"),
|
||||
packet.node,
|
||||
),
|
||||
xxh3_128_hexdigest(
|
||||
args_key.encode() if isinstance(args_key, str) else args_key,
|
||||
),
|
||||
cache_policy.ttl,
|
||||
)
|
||||
else:
|
||||
cache_key = None
|
||||
scratchpad = _scratchpad(
|
||||
config[CONF].get(CONFIG_KEY_SCRATCHPAD),
|
||||
pending_writes,
|
||||
task_id,
|
||||
xxh3_128_hexdigest(task_checkpoint_ns.encode()),
|
||||
config[CONF].get(CONFIG_KEY_RESUME_MAP),
|
||||
step,
|
||||
stop,
|
||||
)
|
||||
runtime = cast(Runtime, configurable.get(CONFIG_KEY_RUNTIME, DEFAULT_RUNTIME))
|
||||
runtime = runtime.override(
|
||||
store=store, previous=checkpoint["channel_values"].get(PREVIOUS, None)
|
||||
)
|
||||
additional_config: RunnableConfig = {
|
||||
"metadata": metadata,
|
||||
"tags": proc.tags,
|
||||
}
|
||||
return PregelExecutableTask(
|
||||
packet.node,
|
||||
packet.arg,
|
||||
proc_node,
|
||||
writes,
|
||||
patch_config(
|
||||
merge_configs(config, additional_config),
|
||||
run_name=packet.node,
|
||||
callbacks=(
|
||||
manager.get_child(f"graph:step:{step}") if manager else None
|
||||
),
|
||||
configurable={
|
||||
CONFIG_KEY_TASK_ID: task_id,
|
||||
# deque.extend is thread-safe
|
||||
CONFIG_KEY_SEND: writes.extend,
|
||||
CONFIG_KEY_READ: partial(
|
||||
local_read,
|
||||
scratchpad,
|
||||
channels,
|
||||
managed,
|
||||
PregelTaskWrites(
|
||||
translated_task_path, packet.node, writes, triggers
|
||||
),
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINTER: (
|
||||
checkpointer or configurable.get(CONFIG_KEY_CHECKPOINTER)
|
||||
),
|
||||
CONFIG_KEY_CHECKPOINT_MAP: {
|
||||
**configurable.get(CONFIG_KEY_CHECKPOINT_MAP, {}),
|
||||
parent_ns: checkpoint["id"],
|
||||
},
|
||||
CONFIG_KEY_CHECKPOINT_ID: None,
|
||||
CONFIG_KEY_CHECKPOINT_NS: task_checkpoint_ns,
|
||||
CONFIG_KEY_SCRATCHPAD: scratchpad,
|
||||
CONFIG_KEY_RUNTIME: runtime,
|
||||
},
|
||||
),
|
||||
triggers,
|
||||
proc.retry_policy or retry_policy,
|
||||
cache_key,
|
||||
task_id,
|
||||
translated_task_path,
|
||||
writers=proc.flat_writers,
|
||||
subgraphs=proc.subgraphs,
|
||||
)
|
||||
else:
|
||||
return PregelTask(task_id, packet.node, translated_task_path)
|
||||
|
||||
|
||||
def checkpoint_null_version(
|
||||
checkpoint: Checkpoint,
|
||||
) -> V | None:
|
||||
@@ -1106,3 +1210,24 @@ class LazyAtomicCounter:
|
||||
if self._counter is None:
|
||||
self._counter = itertools.count(0).__next__
|
||||
return self._counter()
|
||||
|
||||
|
||||
def sanitize_untracked_values_in_send(
|
||||
packet: Send, channels: Mapping[str, BaseChannel]
|
||||
) -> Send:
|
||||
"""Pop any values belonging to UntrackedValue channels in Send.arg for safe checkpointing.
|
||||
|
||||
Send is often called with state to be passed to the dest node, which may contain
|
||||
UntrackedValues at the top level. Send is not typed and arg may be a nested dict."""
|
||||
|
||||
if not isinstance(packet.arg, dict):
|
||||
# Command
|
||||
return packet
|
||||
|
||||
# top level keys should be the channel names
|
||||
sanitized_arg = {
|
||||
k: v
|
||||
for k, v in packet.arg.items()
|
||||
if not isinstance(channels.get(k), UntrackedValue)
|
||||
}
|
||||
return Send(node=packet.node, arg=sanitized_arg)
|
||||
|
||||
@@ -56,10 +56,12 @@ from langgraph._internal._constants import (
|
||||
NULL_TASK_ID,
|
||||
PUSH,
|
||||
RESUME,
|
||||
TASKS,
|
||||
)
|
||||
from langgraph._internal._scratchpad import PregelScratchpad
|
||||
from langgraph._internal._typing import EMPTY_SEQ, MISSING
|
||||
from langgraph.channels.base import BaseChannel
|
||||
from langgraph.channels.untracked_value import UntrackedValue
|
||||
from langgraph.constants import TAG_HIDDEN
|
||||
from langgraph.errors import (
|
||||
EmptyInputError,
|
||||
@@ -78,6 +80,7 @@ from langgraph.pregel._algo import (
|
||||
increment,
|
||||
prepare_next_tasks,
|
||||
prepare_single_task,
|
||||
sanitize_untracked_values_in_send,
|
||||
should_interrupt,
|
||||
task_path_str,
|
||||
)
|
||||
@@ -114,6 +117,7 @@ from langgraph.types import (
|
||||
Durability,
|
||||
PregelExecutableTask,
|
||||
RetryPolicy,
|
||||
Send,
|
||||
StreamMode,
|
||||
)
|
||||
|
||||
@@ -320,6 +324,24 @@ class PregelLoop:
|
||||
w for w in self.checkpoint_pending_writes if w[0] != task_id
|
||||
]
|
||||
writes_to_save = writes
|
||||
|
||||
# check if any writes are to an UntrackedValue channel
|
||||
if any(
|
||||
isinstance(channel, UntrackedValue) for channel in self.channels.values()
|
||||
):
|
||||
# we do not persist untracked values in checkpoints
|
||||
writes_to_save = [
|
||||
# sanitize UntrackedValues that are nested within Send packets
|
||||
(
|
||||
(c, sanitize_untracked_values_in_send(v, self.channels))
|
||||
if c == TASKS and isinstance(v, Send)
|
||||
else (c, v)
|
||||
)
|
||||
for c, v in writes_to_save
|
||||
# dont persist UntrackedValue channel writes
|
||||
if not isinstance(self.specs.get(c), UntrackedValue)
|
||||
]
|
||||
|
||||
# save writes
|
||||
self.checkpoint_pending_writes.extend((task_id, c, v) for c, v in writes)
|
||||
if self.durability != "exit" and self.checkpointer_put_writes is not None:
|
||||
@@ -437,9 +459,6 @@ class PregelLoop:
|
||||
def tick(self) -> bool:
|
||||
"""Execute a single iteration of the Pregel loop.
|
||||
|
||||
Args:
|
||||
input_keys: The key(s) to read input from.
|
||||
|
||||
Returns:
|
||||
True if more iterations are needed.
|
||||
"""
|
||||
@@ -735,6 +754,17 @@ class PregelLoop:
|
||||
id=self.checkpoint["id"] if exiting else None,
|
||||
updated_channels=self.updated_channels,
|
||||
)
|
||||
# sanitize TASK channel in the checkpoint before saving (durability=="exit")
|
||||
if TASKS in self.checkpoint["channel_values"] and any(
|
||||
isinstance(channel, UntrackedValue) for channel in self.channels.values()
|
||||
):
|
||||
sanitized_tasks = [
|
||||
sanitize_untracked_values_in_send(value, self.channels)
|
||||
if isinstance(value, Send)
|
||||
else value
|
||||
for value in self.checkpoint["channel_values"][TASKS]
|
||||
]
|
||||
self.checkpoint["channel_values"][TASKS] = sanitized_tasks
|
||||
# bail if no checkpointer
|
||||
if do_checkpoint and self._checkpointer_put_after_previous is not None:
|
||||
self.prev_checkpoint_config = (
|
||||
|
||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import concurrent.futures
|
||||
import inspect
|
||||
import threading
|
||||
import time
|
||||
import weakref
|
||||
@@ -281,7 +282,11 @@ class PregelRunner:
|
||||
Awaitable[PregelExecutableTask | None],
|
||||
],
|
||||
) -> AsyncIterator[None]:
|
||||
loop = asyncio.get_event_loop()
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
tasks = tuple(tasks)
|
||||
futures = FuturesDict(
|
||||
callback=weakref.WeakMethod(self.commit),
|
||||
@@ -539,7 +544,7 @@ def _call(
|
||||
],
|
||||
submit: weakref.ref[Submit],
|
||||
) -> concurrent.futures.Future[Any]:
|
||||
if asyncio.iscoroutinefunction(func):
|
||||
if inspect.iscoroutinefunction(func):
|
||||
raise RuntimeError("In an sync context async tasks cannot be called")
|
||||
|
||||
fut: concurrent.futures.Future | None = None
|
||||
|
||||
@@ -934,7 +934,7 @@ class Pregel(
|
||||
If `False`, only the immediate subgraphs will be returned.
|
||||
|
||||
Returns:
|
||||
An iterator of the (namespace, subgraph) pairs.
|
||||
An iterator of the `(namespace, subgraph)` pairs.
|
||||
"""
|
||||
for name, node in self.nodes.items():
|
||||
# filter by prefix
|
||||
@@ -973,7 +973,7 @@ class Pregel(
|
||||
If `False`, only the immediate subgraphs will be returned.
|
||||
|
||||
Returns:
|
||||
An iterator of the (namespace, subgraph) pairs.
|
||||
An iterator of the `(namespace, subgraph)` pairs.
|
||||
"""
|
||||
for name, node in self.get_subgraphs(namespace=namespace, recurse=recurse):
|
||||
yield name, node
|
||||
@@ -1702,7 +1702,9 @@ class Pregel(
|
||||
# we use the task id generated by prepare_next_tasks
|
||||
node_to_task_ids: dict[str, deque[str]] = defaultdict(deque)
|
||||
if saved is not None and saved.pending_writes is not None:
|
||||
# tasks for this checkpoint
|
||||
# we call prepare_next_tasks to discover the task IDs that
|
||||
# would have been generated, so we can reuse them and
|
||||
# properly populate task.result in state history
|
||||
next_tasks = prepare_next_tasks(
|
||||
checkpoint,
|
||||
saved.pending_writes,
|
||||
@@ -1721,32 +1723,6 @@ class Pregel(
|
||||
for t in next_tasks.values():
|
||||
node_to_task_ids[t.name].append(t.id)
|
||||
|
||||
# apply null writes
|
||||
if null_writes := [
|
||||
w[1:] for w in saved.pending_writes or [] if w[0] == NULL_TASK_ID
|
||||
]:
|
||||
apply_writes(
|
||||
checkpoint,
|
||||
channels,
|
||||
[PregelTaskWrites((), INPUT, null_writes, [])],
|
||||
checkpointer.get_next_version,
|
||||
self.trigger_to_nodes,
|
||||
)
|
||||
# apply writes
|
||||
for tid, k, v in saved.pending_writes:
|
||||
if k in (ERROR, INTERRUPT):
|
||||
continue
|
||||
if tid not in next_tasks:
|
||||
continue
|
||||
next_tasks[tid].writes.append((k, v))
|
||||
if tasks := [t for t in next_tasks.values() if t.writes]:
|
||||
apply_writes(
|
||||
checkpoint,
|
||||
channels,
|
||||
tasks,
|
||||
checkpointer.get_next_version,
|
||||
self.trigger_to_nodes,
|
||||
)
|
||||
valid_updates: list[tuple[str, dict[str, Any] | None, str | None]] = []
|
||||
if len(updates) == 1:
|
||||
values, as_node, task_id = updates[0]
|
||||
@@ -2167,7 +2143,9 @@ class Pregel(
|
||||
# we use the task id generated by prepare_next_tasks
|
||||
node_to_task_ids: dict[str, deque[str]] = defaultdict(deque)
|
||||
if saved is not None and saved.pending_writes is not None:
|
||||
# tasks for this checkpoint
|
||||
# we call prepare_next_tasks to discover the task IDs that
|
||||
# would have been generated, so we can reuse them and
|
||||
# properly populate task.result in state history
|
||||
next_tasks = prepare_next_tasks(
|
||||
checkpoint,
|
||||
saved.pending_writes,
|
||||
@@ -2186,31 +2164,6 @@ class Pregel(
|
||||
for t in next_tasks.values():
|
||||
node_to_task_ids[t.name].append(t.id)
|
||||
|
||||
# apply null writes
|
||||
if null_writes := [
|
||||
w[1:] for w in saved.pending_writes or [] if w[0] == NULL_TASK_ID
|
||||
]:
|
||||
apply_writes(
|
||||
checkpoint,
|
||||
channels,
|
||||
[PregelTaskWrites((), INPUT, null_writes, [])],
|
||||
checkpointer.get_next_version,
|
||||
self.trigger_to_nodes,
|
||||
)
|
||||
for tid, k, v in saved.pending_writes:
|
||||
if k in (ERROR, INTERRUPT):
|
||||
continue
|
||||
if tid not in next_tasks:
|
||||
continue
|
||||
next_tasks[tid].writes.append((k, v))
|
||||
if tasks := [t for t in next_tasks.values() if t.writes]:
|
||||
apply_writes(
|
||||
checkpoint,
|
||||
channels,
|
||||
tasks,
|
||||
checkpointer.get_next_version,
|
||||
self.trigger_to_nodes,
|
||||
)
|
||||
valid_updates: list[tuple[str, dict[str, Any] | None, str | None]] = []
|
||||
if len(updates) == 1:
|
||||
values, as_node, task_id = updates[0]
|
||||
@@ -2401,7 +2354,7 @@ class Pregel(
|
||||
validate_keys(output_keys, self.channels)
|
||||
interrupt_before = interrupt_before or self.interrupt_before_nodes
|
||||
interrupt_after = interrupt_after or self.interrupt_after_nodes
|
||||
if not isinstance(stream_mode, list):
|
||||
if isinstance(stream_mode, str):
|
||||
stream_modes = {stream_mode}
|
||||
else:
|
||||
stream_modes = set(stream_mode)
|
||||
@@ -2478,16 +2431,19 @@ class Pregel(
|
||||
Will be emitted as 2-tuples `(LLM token, metadata)`.
|
||||
- `"checkpoints"`: Emit an event when a checkpoint is created, in the same format as returned by `get_state()`.
|
||||
- `"tasks"`: Emit events when tasks start and finish, including their results and errors.
|
||||
- `"debug"`: Emit debug events with as much information as possible for each step.
|
||||
|
||||
You can pass a list as the `stream_mode` parameter to stream multiple modes at once.
|
||||
The streamed outputs will be tuples of `(mode, data)`.
|
||||
|
||||
See [LangGraph streaming guide](https://langchain-ai.github.io/langgraph/how-tos/streaming/) for more details.
|
||||
See [LangGraph streaming guide](https://docs.langchain.com/oss/python/langgraph/streaming) for more details.
|
||||
print_mode: Accepts the same values as `stream_mode`, but only prints the output to the console, for debugging purposes. Does not affect the output of the graph in any way.
|
||||
output_keys: The keys to stream, defaults to all non-context channels.
|
||||
interrupt_before: Nodes to interrupt before, defaults to all nodes in the graph.
|
||||
interrupt_after: Nodes to interrupt after, defaults to all nodes in the graph.
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`. Options are:
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`.
|
||||
Options are:
|
||||
|
||||
- `"sync"`: Changes are persisted synchronously before the next step starts.
|
||||
- `"async"`: Changes are persisted asynchronously while the next step executes.
|
||||
- `"exit"`: Changes are persisted only when the graph exits.
|
||||
@@ -2497,7 +2453,7 @@ class Pregel(
|
||||
where `namespace` is a tuple with the path to the node where a subgraph is invoked,
|
||||
e.g. `("parent_node:<task_id>", "child_node:<task_id>")`.
|
||||
|
||||
See [LangGraph streaming guide](https://langchain-ai.github.io/langgraph/how-tos/streaming/) for more details.
|
||||
See [LangGraph streaming guide](https://docs.langchain.com/oss/python/langgraph/streaming) for more details.
|
||||
|
||||
Yields:
|
||||
The output of each step in the graph. The output shape depends on the `stream_mode`.
|
||||
@@ -2742,17 +2698,21 @@ class Pregel(
|
||||
- `"custom"`: Emit custom data from inside nodes or tasks using `StreamWriter`.
|
||||
- `"messages"`: Emit LLM messages token-by-token together with metadata for any LLM invocations inside nodes or tasks.
|
||||
Will be emitted as 2-tuples `(LLM token, metadata)`.
|
||||
- `"checkpoints"`: Emit an event when a checkpoint is created, in the same format as returned by `get_state()`.
|
||||
- `"tasks"`: Emit events when tasks start and finish, including their results and errors.
|
||||
- `"debug"`: Emit debug events with as much information as possible for each step.
|
||||
|
||||
You can pass a list as the `stream_mode` parameter to stream multiple modes at once.
|
||||
The streamed outputs will be tuples of `(mode, data)`.
|
||||
|
||||
See [LangGraph streaming guide](https://langchain-ai.github.io/langgraph/how-tos/streaming/) for more details.
|
||||
See [LangGraph streaming guide](https://docs.langchain.com/oss/python/langgraph/streaming) for more details.
|
||||
print_mode: Accepts the same values as `stream_mode`, but only prints the output to the console, for debugging purposes. Does not affect the output of the graph in any way.
|
||||
output_keys: The keys to stream, defaults to all non-context channels.
|
||||
interrupt_before: Nodes to interrupt before, defaults to all nodes in the graph.
|
||||
interrupt_after: Nodes to interrupt after, defaults to all nodes in the graph.
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`. Options are:
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`.
|
||||
Options are:
|
||||
|
||||
- `"sync"`: Changes are persisted synchronously before the next step starts.
|
||||
- `"async"`: Changes are persisted asynchronously while the next step executes.
|
||||
- `"exit"`: Changes are persisted only when the graph exits.
|
||||
@@ -2762,7 +2722,7 @@ class Pregel(
|
||||
where `namespace` is a tuple with the path to the node where a subgraph is invoked,
|
||||
e.g. `("parent_node:<task_id>", "child_node:<task_id>")`.
|
||||
|
||||
See [LangGraph streaming guide](https://langchain-ai.github.io/langgraph/how-tos/streaming/) for more details.
|
||||
See [LangGraph streaming guide](https://docs.langchain.com/oss/python/langgraph/streaming) for more details.
|
||||
|
||||
Yields:
|
||||
The output of each step in the graph. The output shape depends on the `stream_mode`.
|
||||
@@ -3069,7 +3029,9 @@ class Pregel(
|
||||
output_keys: The output keys to retrieve from the graph run.
|
||||
interrupt_before: The nodes to interrupt the graph run before.
|
||||
interrupt_after: The nodes to interrupt the graph run after.
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`. Options are:
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`.
|
||||
Options are:
|
||||
|
||||
- `"sync"`: Changes are persisted synchronously before the next step starts.
|
||||
- `"async"`: Changes are persisted asynchronously while the next step executes.
|
||||
- `"exit"`: Changes are persisted only when the graph exits.
|
||||
@@ -3142,29 +3104,30 @@ class Pregel(
|
||||
durability: Durability | None = None,
|
||||
**kwargs: Any,
|
||||
) -> dict[str, Any] | Any:
|
||||
"""Asynchronously invoke the graph on a single input.
|
||||
"""Asynchronously run the graph with a single input and config.
|
||||
|
||||
Args:
|
||||
input: The input data for the computation. It can be a dictionary or any other type.
|
||||
config: The configuration for the computation.
|
||||
input: The input data for the graph. It can be a dictionary or any other type.
|
||||
config: The configuration for the graph run.
|
||||
context: The static context to use for the run.
|
||||
!!! version-added "Added in version 0.6.0"
|
||||
stream_mode: The stream mode for the computation.
|
||||
stream_mode: The stream mode for the graph run.
|
||||
print_mode: Accepts the same values as `stream_mode`, but only prints the output to the console, for debugging purposes. Does not affect the output of the graph in any way.
|
||||
output_keys: The output keys to include in the result.
|
||||
interrupt_before: The nodes to interrupt before.
|
||||
interrupt_after: The nodes to interrupt after.
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`. Options are:
|
||||
output_keys: The output keys to retrieve from the graph run.
|
||||
interrupt_before: The nodes to interrupt the graph run before.
|
||||
interrupt_after: The nodes to interrupt the graph run after.
|
||||
durability: The durability mode for the graph execution, defaults to `"async"`.
|
||||
Options are:
|
||||
|
||||
- `"sync"`: Changes are persisted synchronously before the next step starts.
|
||||
- `"async"`: Changes are persisted asynchronously while the next step executes.
|
||||
- `"exit"`: Changes are persisted only when the graph exits.
|
||||
**kwargs: Additional keyword arguments.
|
||||
**kwargs: Additional keyword arguments to pass to the graph run.
|
||||
|
||||
Returns:
|
||||
The result of the computation. If `stream_mode` is `"values"`, it returns the latest value.
|
||||
If `stream_mode` is `"chunks"`, it returns a list of chunks.
|
||||
The output of the graph run. If `stream_mode` is `"values"`, it returns the latest output.
|
||||
If `stream_mode` is not `"values"`, it returns a list of output chunks.
|
||||
"""
|
||||
|
||||
output_keys = output_keys if output_keys is not None else self.output_channels
|
||||
|
||||
latest: dict[str, Any] | Any = None
|
||||
|
||||
@@ -111,7 +111,7 @@ class Runtime(Generic[ContextT]):
|
||||
stream_writer=other.stream_writer
|
||||
if other.stream_writer is not _no_op_stream_writer
|
||||
else self.stream_writer,
|
||||
previous=other.previous or self.previous,
|
||||
previous=self.previous if other.previous is None else other.previous,
|
||||
)
|
||||
|
||||
def override(
|
||||
|
||||
@@ -55,6 +55,7 @@ __all__ = (
|
||||
"Command",
|
||||
"Durability",
|
||||
"interrupt",
|
||||
"Overwrite",
|
||||
)
|
||||
|
||||
Durability = Literal["sync", "async", "exit"]
|
||||
@@ -85,11 +86,11 @@ StreamMode = Literal[
|
||||
- `"messages"`: Emit LLM messages token-by-token together with metadata for any LLM invocations inside nodes or tasks.
|
||||
- `"checkpoints"`: Emit an event when a checkpoint is created, in the same format as returned by `get_state()`.
|
||||
- `"tasks"`: Emit events when tasks start and finish, including their results and errors.
|
||||
- `"debug"`: Emit "checkpoints" and "tasks" events, for debugging purposes.
|
||||
- `"debug"`: Emit `"checkpoints"` and `"tasks"` events for debugging purposes.
|
||||
"""
|
||||
|
||||
StreamWriter = Callable[[Any], None]
|
||||
"""Callable that accepts a single argument and writes it to the output stream.
|
||||
"""`Callable` that accepts a single argument and writes it to the output stream.
|
||||
Always injected into nodes if requested as a keyword argument, but it's a no-op
|
||||
when not using `stream_mode="custom"`."""
|
||||
|
||||
@@ -115,7 +116,7 @@ class RetryPolicy(NamedTuple):
|
||||
retry_on: (
|
||||
type[Exception] | Sequence[type[Exception]] | Callable[[Exception], bool]
|
||||
) = default_retry_on
|
||||
"""List of exception classes that should trigger a retry, or a callable that returns True for exceptions that should trigger a retry."""
|
||||
"""List of exception classes that should trigger a retry, or a callable that returns `True` for exceptions that should trigger a retry."""
|
||||
|
||||
|
||||
KeyFuncT = TypeVar("KeyFuncT", bound=Callable[..., str | bytes])
|
||||
@@ -283,26 +284,32 @@ class Send:
|
||||
node (str): The name of the target node to send the message to.
|
||||
arg (Any): The state or message to send to the target node.
|
||||
|
||||
Examples:
|
||||
>>> from typing import Annotated
|
||||
>>> import operator
|
||||
>>> class OverallState(TypedDict):
|
||||
... subjects: list[str]
|
||||
... jokes: Annotated[list[str], operator.add]
|
||||
>>> from langgraph.types import Send
|
||||
>>> from langgraph.graph import END, START
|
||||
>>> def continue_to_jokes(state: OverallState):
|
||||
... return [Send("generate_joke", {"subject": s}) for s in state["subjects"]]
|
||||
>>> from langgraph.graph import StateGraph
|
||||
>>> builder = StateGraph(OverallState)
|
||||
>>> builder.add_node("generate_joke", lambda state: {"jokes": [f"Joke about {state['subject']}"]})
|
||||
>>> builder.add_conditional_edges(START, continue_to_jokes)
|
||||
>>> builder.add_edge("generate_joke", END)
|
||||
>>> graph = builder.compile()
|
||||
>>>
|
||||
>>> # Invoking with two subjects results in a generated joke for each
|
||||
>>> graph.invoke({"subjects": ["cats", "dogs"]})
|
||||
{'subjects': ['cats', 'dogs'], 'jokes': ['Joke about cats', 'Joke about dogs']}
|
||||
!!! example
|
||||
|
||||
```python
|
||||
from typing import Annotated
|
||||
from langgraph.types import Send
|
||||
from langgraph.graph import END, START
|
||||
from langgraph.graph import StateGraph
|
||||
import operator
|
||||
|
||||
class OverallState(TypedDict):
|
||||
subjects: list[str]
|
||||
jokes: Annotated[list[str], operator.add]
|
||||
|
||||
def continue_to_jokes(state: OverallState):
|
||||
return [Send("generate_joke", {"subject": s}) for s in state["subjects"]]
|
||||
|
||||
builder = StateGraph(OverallState)
|
||||
builder.add_node("generate_joke", lambda state: {"jokes": [f"Joke about {state['subject']}"]})
|
||||
builder.add_conditional_edges(START, continue_to_jokes)
|
||||
builder.add_edge("generate_joke", END)
|
||||
graph = builder.compile()
|
||||
|
||||
# Invoking with two subjects results in a generated joke for each
|
||||
graph.invoke({"subjects": ["cats", "dogs"]})
|
||||
# {'subjects': ['cats', 'dogs'], 'jokes': ['Joke about cats', 'Joke about dogs']}
|
||||
```
|
||||
"""
|
||||
|
||||
__slots__ = ("node", "arg")
|
||||
@@ -312,7 +319,7 @@ class Send:
|
||||
|
||||
def __init__(self, /, node: str, arg: Any) -> None:
|
||||
"""
|
||||
Initialize a new instance of the Send class.
|
||||
Initialize a new instance of the `Send` class.
|
||||
|
||||
Args:
|
||||
node: The name of the target node to send the message to.
|
||||
@@ -342,10 +349,8 @@ N = TypeVar("N", bound=Hashable)
|
||||
class Command(Generic[N], ToolOutputMixin):
|
||||
"""One or more commands to update the graph's state and send messages to nodes.
|
||||
|
||||
!!! version-added "Added in version 0.2.24"
|
||||
|
||||
Args:
|
||||
graph: graph to send the command to. Supported values are:
|
||||
graph: Graph to send the command to. Supported values are:
|
||||
|
||||
- `None`: the current graph
|
||||
- `Command.PARENT`: closest parent graph
|
||||
@@ -415,7 +420,8 @@ def interrupt(value: Any) -> Any:
|
||||
To use an `interrupt`, you must enable a checkpointer, as the feature relies
|
||||
on persisting the graph state.
|
||||
|
||||
Example:
|
||||
!!! example
|
||||
|
||||
```python
|
||||
import uuid
|
||||
from typing import Optional
|
||||
@@ -516,3 +522,47 @@ def interrupt(value: Any) -> Any:
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class Overwrite:
|
||||
"""Bypass a reducer and write the wrapped value directly to a `BinaryOperatorAggregate` channel.
|
||||
|
||||
Receiving multiple `Overwrite` values for the same channel in a single super-step
|
||||
will raise an `InvalidUpdateError`.
|
||||
|
||||
!!! example
|
||||
|
||||
```python
|
||||
from typing import Annotated
|
||||
import operator
|
||||
from langgraph.graph import StateGraph
|
||||
from langgraph.types import Overwrite
|
||||
|
||||
class State(TypedDict):
|
||||
messages: Annotated[list, operator.add]
|
||||
|
||||
def node_a(state: TypedDict):
|
||||
# Normal update: uses the reducer (operator.add)
|
||||
return {"messages": ["a"]}
|
||||
|
||||
def node_b(state: State):
|
||||
# Overwrite: bypasses the reducer and replaces the entire value
|
||||
return {"messages": Overwrite(value=["b"])}
|
||||
|
||||
builder = StateGraph(State)
|
||||
builder.add_node("node_a", node_a)
|
||||
builder.add_node("node_b", node_b)
|
||||
builder.set_entry_point("node_a")
|
||||
builder.add_edge("node_a", "node_b")
|
||||
graph = builder.compile()
|
||||
|
||||
# Without Overwrite in node_b, messages would be ["START", "a", "b"]
|
||||
# With Overwrite, messages is just ["b"]
|
||||
result = graph.invoke({"messages": ["START"]})
|
||||
assert result == {"messages": ["b"]}
|
||||
```
|
||||
"""
|
||||
|
||||
value: Any
|
||||
"""The value to write directly to the channel, bypassing any reducer."""
|
||||
|
||||
@@ -31,13 +31,13 @@ ContextT_contra = TypeVar(
|
||||
)
|
||||
|
||||
InputT = TypeVar("InputT", bound=StateLike, default=StateT)
|
||||
"""Type variable used to represent the input to a state graph.
|
||||
"""Type variable used to represent the input to a `StateGraph`.
|
||||
|
||||
Defaults to `StateT`.
|
||||
"""
|
||||
|
||||
OutputT = TypeVar("OutputT", bound=StateLike, default=StateT)
|
||||
"""Type variable used to represent the output of a state graph.
|
||||
"""Type variable used to represent the output of a `StateGraph`.
|
||||
|
||||
Defaults to `StateT`.
|
||||
"""
|
||||
|
||||
@@ -4,27 +4,46 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "langgraph"
|
||||
version = "1.0.0rc1"
|
||||
version = "1.0.3"
|
||||
description = "Building stateful, multi-actor applications with LLMs"
|
||||
authors = []
|
||||
requires-python = ">=3.10"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
license-files = ['LICENSE']
|
||||
classifiers = [
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3 :: Only',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Programming Language :: Python :: 3.11',
|
||||
'Programming Language :: Python :: 3.12',
|
||||
'Programming Language :: Python :: 3.13',
|
||||
]
|
||||
dependencies = [
|
||||
"langchain-core>=0.1",
|
||||
"langgraph-checkpoint>=2.1.0,<3.0.0",
|
||||
"langgraph-checkpoint>=2.1.0,<4.0.0",
|
||||
"langgraph-sdk>=0.2.2,<0.3.0",
|
||||
"langgraph-prebuilt==0.7.0rc1",
|
||||
"langgraph-prebuilt>=1.0.2,<1.1.0",
|
||||
"xxhash>=3.5.0",
|
||||
"pydantic>=2.7.4",
|
||||
]
|
||||
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
Homepage = "https://docs.langchain.com/oss/python/langgraph/overview"
|
||||
Documentation = "https://reference.langchain.com/python/langgraph/"
|
||||
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/langgraph"
|
||||
Changelog = "https://github.com/langchain-ai/langgraph/releases"
|
||||
Twitter = "https://x.com/LangChainAI"
|
||||
Slack = "https://www.langchain.com/join-community"
|
||||
Reddit = "https://www.reddit.com/r/LangChain/"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
test = [
|
||||
"pytest",
|
||||
"pytest-cov",
|
||||
"pytest-dotenv",
|
||||
@@ -32,12 +51,9 @@ dev = [
|
||||
"syrupy",
|
||||
"httpx",
|
||||
"pytest-watcher",
|
||||
"mypy",
|
||||
"ruff",
|
||||
"jupyter",
|
||||
"pytest-xdist[psutil]",
|
||||
"pytest-repeat",
|
||||
"langchain-core==1.0.0a1",
|
||||
"langchain-core>=1.0.0",
|
||||
"langgraph-prebuilt",
|
||||
"langgraph-checkpoint",
|
||||
"langgraph-checkpoint-sqlite",
|
||||
@@ -47,14 +63,22 @@ dev = [
|
||||
"uvloop==0.21.0beta1",
|
||||
"pyperf",
|
||||
"py-spy",
|
||||
"types-requests",
|
||||
"pycryptodome",
|
||||
"langgraph-cli[inmem]",
|
||||
"langgraph-cli; python_version < '3.14'",
|
||||
"langgraph-cli[inmem]; python_version < '3.14'",
|
||||
"redis",
|
||||
]
|
||||
lint = [
|
||||
"mypy",
|
||||
"ruff",
|
||||
"types-requests",
|
||||
]
|
||||
dev = [
|
||||
{include-group = "test"},
|
||||
{include-group = "lint"},
|
||||
"jupyter",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
default-groups = ['dev']
|
||||
|
||||
[tool.uv.sources]
|
||||
langgraph-prebuilt = { path = "../prebuilt", editable = true }
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -666,18 +666,18 @@
|
||||
__end__([<p>__end__</p>]):::last
|
||||
__start__ --> uno;
|
||||
uno -.-> dos;
|
||||
uno -.-> subgraph_one;
|
||||
uno -.-> subgraph\3aone;
|
||||
dos --> __end__;
|
||||
subgraph___end__ --> __end__;
|
||||
subgraph\3a__end__ --> __end__;
|
||||
subgraph subgraph
|
||||
subgraph_one(one)
|
||||
subgraph_two(two)
|
||||
subgraph_three(three)
|
||||
subgraph___end__(<p>__end__</p>)
|
||||
subgraph_one -.-> subgraph_three;
|
||||
subgraph_one -.-> subgraph_two;
|
||||
subgraph_three --> subgraph___end__;
|
||||
subgraph_two --> subgraph___end__;
|
||||
subgraph\3aone(one)
|
||||
subgraph\3atwo(two)
|
||||
subgraph\3athree(three)
|
||||
subgraph\3a__end__(<p>__end__</p>)
|
||||
subgraph\3aone -.-> subgraph\3athree;
|
||||
subgraph\3aone -.-> subgraph\3atwo;
|
||||
subgraph\3athree --> subgraph\3a__end__;
|
||||
subgraph\3atwo --> subgraph\3a__end__;
|
||||
end
|
||||
classDef default fill:#f2f0ff,line-height:1.2
|
||||
classDef first fill-opacity:0
|
||||
@@ -705,11 +705,11 @@
|
||||
__start__([<p>__start__</p>]):::first
|
||||
side(side)
|
||||
__end__([<p>__end__</p>]):::last
|
||||
__start__ --> inner_up;
|
||||
inner_up --> side;
|
||||
__start__ --> inner\3aup;
|
||||
inner\3aup --> side;
|
||||
side --> __end__;
|
||||
subgraph inner
|
||||
inner_up(up)
|
||||
inner\3aup(up)
|
||||
end
|
||||
classDef default fill:#f2f0ff,line-height:1.2
|
||||
classDef first fill-opacity:0
|
||||
@@ -868,19 +868,19 @@
|
||||
__end__([<p>__end__</p>]):::last
|
||||
__start__ -.-> tool_one;
|
||||
__start__ -.-> tool_three;
|
||||
__start__ -.-> tool_two___start__;
|
||||
__start__ -.-> tool_two\3a__start__;
|
||||
tool_one --> __end__;
|
||||
tool_three --> __end__;
|
||||
tool_two___end__ --> __end__;
|
||||
tool_two\3a__end__ --> __end__;
|
||||
subgraph tool_two
|
||||
tool_two___start__(<p>__start__</p>)
|
||||
tool_two_tool_two_slow(tool_two_slow)
|
||||
tool_two_tool_two_fast(tool_two_fast)
|
||||
tool_two___end__(<p>__end__</p>)
|
||||
tool_two___start__ -.-> tool_two_tool_two_fast;
|
||||
tool_two___start__ -.-> tool_two_tool_two_slow;
|
||||
tool_two_tool_two_fast --> tool_two___end__;
|
||||
tool_two_tool_two_slow --> tool_two___end__;
|
||||
tool_two\3a__start__(<p>__start__</p>)
|
||||
tool_two\3atool_two_slow(tool_two_slow)
|
||||
tool_two\3atool_two_fast(tool_two_fast)
|
||||
tool_two\3a__end__(<p>__end__</p>)
|
||||
tool_two\3a__start__ -.-> tool_two\3atool_two_fast;
|
||||
tool_two\3a__start__ -.-> tool_two\3atool_two_slow;
|
||||
tool_two\3atool_two_fast --> tool_two\3a__end__;
|
||||
tool_two\3atool_two_slow --> tool_two\3a__end__;
|
||||
end
|
||||
classDef default fill:#f2f0ff,line-height:1.2
|
||||
classDef first fill-opacity:0
|
||||
@@ -891,13 +891,13 @@
|
||||
# name: test_repeat_condition
|
||||
'''
|
||||
graph TD;
|
||||
Call_Tool -.-> Chart_Generator;
|
||||
Call_Tool -.-> Researcher;
|
||||
Chart_Generator -. call_tool .-> Call_Tool;
|
||||
Chart_Generator -. continue .-> Researcher;
|
||||
Chart_Generator -. end .-> __end__;
|
||||
Researcher -. call_tool .-> Call_Tool;
|
||||
Researcher -. continue .-> Chart_Generator;
|
||||
Call\20Tool -.-> Chart\20Generator;
|
||||
Call\20Tool -.-> Researcher;
|
||||
Chart\20Generator -. call_tool .-> Call\20Tool;
|
||||
Chart\20Generator -. continue .-> Researcher;
|
||||
Chart\20Generator -. end .-> __end__;
|
||||
Researcher -. call_tool .-> Call\20Tool;
|
||||
Researcher -. continue .-> Chart\20Generator;
|
||||
Researcher -. end .-> __end__;
|
||||
__start__ --> Researcher;
|
||||
Researcher -. redo .-> Researcher;
|
||||
@@ -939,25 +939,25 @@
|
||||
__end__([<p>__end__</p>]):::last
|
||||
__start__ --> gp_one;
|
||||
gp_one -. 1 .-> __end__;
|
||||
gp_one -. 0 .-> gp_two___start__;
|
||||
gp_two___end__ --> gp_one;
|
||||
gp_one -. 0 .-> gp_two\3a__start__;
|
||||
gp_two\3a__end__ --> gp_one;
|
||||
subgraph gp_two
|
||||
gp_two___start__(<p>__start__</p>)
|
||||
gp_two_p_one(p_one)
|
||||
gp_two___end__(<p>__end__</p>)
|
||||
gp_two___start__ --> gp_two_p_one;
|
||||
gp_two_p_one -. 1 .-> gp_two___end__;
|
||||
gp_two_p_one -. 0 .-> gp_two_p_two___start__;
|
||||
gp_two_p_two___end__ --> gp_two_p_one;
|
||||
gp_two\3a__start__(<p>__start__</p>)
|
||||
gp_two\3ap_one(p_one)
|
||||
gp_two\3a__end__(<p>__end__</p>)
|
||||
gp_two\3a__start__ --> gp_two\3ap_one;
|
||||
gp_two\3ap_one -. 1 .-> gp_two\3a__end__;
|
||||
gp_two\3ap_one -. 0 .-> gp_two\3ap_two\3a__start__;
|
||||
gp_two\3ap_two\3a__end__ --> gp_two\3ap_one;
|
||||
subgraph p_two
|
||||
gp_two_p_two___start__(<p>__start__</p>)
|
||||
gp_two_p_two_c_one(c_one)
|
||||
gp_two_p_two_c_two(c_two)
|
||||
gp_two_p_two___end__(<p>__end__</p>)
|
||||
gp_two_p_two___start__ --> gp_two_p_two_c_one;
|
||||
gp_two_p_two_c_one -. 1 .-> gp_two_p_two___end__;
|
||||
gp_two_p_two_c_one -. 0 .-> gp_two_p_two_c_two;
|
||||
gp_two_p_two_c_two --> gp_two_p_two_c_one;
|
||||
gp_two\3ap_two\3a__start__(<p>__start__</p>)
|
||||
gp_two\3ap_two\3ac_one(c_one)
|
||||
gp_two\3ap_two\3ac_two(c_two)
|
||||
gp_two\3ap_two\3a__end__(<p>__end__</p>)
|
||||
gp_two\3ap_two\3a__start__ --> gp_two\3ap_two\3ac_one;
|
||||
gp_two\3ap_two\3ac_one -. 1 .-> gp_two\3ap_two\3a__end__;
|
||||
gp_two\3ap_two\3ac_one -. 0 .-> gp_two\3ap_two\3ac_two;
|
||||
gp_two\3ap_two\3ac_two --> gp_two\3ap_two\3ac_one;
|
||||
end
|
||||
end
|
||||
classDef default fill:#f2f0ff,line-height:1.2
|
||||
@@ -979,17 +979,17 @@
|
||||
__end__([<p>__end__</p>]):::last
|
||||
__start__ --> p_one;
|
||||
p_one -. 1 .-> __end__;
|
||||
p_one -. 0 .-> p_two___start__;
|
||||
p_two___end__ --> p_one;
|
||||
p_one -. 0 .-> p_two\3a__start__;
|
||||
p_two\3a__end__ --> p_one;
|
||||
subgraph p_two
|
||||
p_two___start__(<p>__start__</p>)
|
||||
p_two_c_one(c_one)
|
||||
p_two_c_two(c_two)
|
||||
p_two___end__(<p>__end__</p>)
|
||||
p_two___start__ --> p_two_c_one;
|
||||
p_two_c_one -. 1 .-> p_two___end__;
|
||||
p_two_c_one -. 0 .-> p_two_c_two;
|
||||
p_two_c_two --> p_two_c_one;
|
||||
p_two\3a__start__(<p>__start__</p>)
|
||||
p_two\3ac_one(c_one)
|
||||
p_two\3ac_two(c_two)
|
||||
p_two\3a__end__(<p>__end__</p>)
|
||||
p_two\3a__start__ --> p_two\3ac_one;
|
||||
p_two\3ac_one -. 1 .-> p_two\3a__end__;
|
||||
p_two\3ac_one -. 0 .-> p_two\3ac_two;
|
||||
p_two\3ac_two --> p_two\3ac_one;
|
||||
end
|
||||
classDef default fill:#f2f0ff,line-height:1.2
|
||||
classDef first fill-opacity:0
|
||||
|
||||
@@ -7,6 +7,7 @@ from langgraph._internal._typing import MISSING
|
||||
from langgraph.channels.binop import BinaryOperatorAggregate
|
||||
from langgraph.channels.last_value import LastValue
|
||||
from langgraph.channels.topic import Topic
|
||||
from langgraph.channels.untracked_value import UntrackedValue
|
||||
from langgraph.errors import EmptyChannelError, InvalidUpdateError
|
||||
|
||||
pytestmark = pytest.mark.anyio
|
||||
@@ -87,3 +88,32 @@ def test_binop() -> None:
|
||||
checkpoint = channel.checkpoint()
|
||||
channel = BinaryOperatorAggregate(int, operator.add).from_checkpoint(checkpoint)
|
||||
assert channel.get() == 10
|
||||
|
||||
|
||||
def test_untracked_value() -> None:
|
||||
channel = UntrackedValue(dict).from_checkpoint(MISSING)
|
||||
assert channel.ValueType is dict
|
||||
assert channel.UpdateType is dict
|
||||
|
||||
# UntrackedValue should start empty
|
||||
with pytest.raises(EmptyChannelError):
|
||||
channel.get()
|
||||
|
||||
# Should be able to update with a value
|
||||
test_data = {"session": "test", "temp": "dir"}
|
||||
channel.update([test_data])
|
||||
assert channel.get() == test_data
|
||||
|
||||
# Update with new value
|
||||
new_data = {"session": "updated", "temp": "newdir"}
|
||||
channel.update([new_data])
|
||||
assert channel.get() == new_data
|
||||
|
||||
# On checkpoint, UntrackedValue should return MISSING
|
||||
checkpoint = channel.checkpoint()
|
||||
assert checkpoint is MISSING
|
||||
|
||||
# Creating from checkpoint with MISSING should start empty
|
||||
new_channel = UntrackedValue(dict).from_checkpoint(checkpoint)
|
||||
with pytest.raises(EmptyChannelError):
|
||||
new_channel.get()
|
||||
|
||||
@@ -21,18 +21,18 @@ def test_interrupt_legacy_ns() -> None:
|
||||
assert new_interrupt.id == old_interrupt.id
|
||||
|
||||
|
||||
serializer = JsonPlusSerializer()
|
||||
serializer = JsonPlusSerializer(allowed_json_modules=True)
|
||||
|
||||
|
||||
def test_serialization_roundtrip() -> None:
|
||||
"""Test that the legacy interrupt (pre v1) can be reserialized as the modern interrupt without id corruption."""
|
||||
|
||||
# generated with:
|
||||
# JsonPlusSerializer().dumps(Interrupt(value="legacy_test", ns=["legacy_test"], resumable=True, when="during"))
|
||||
# JsonPlusSerializer().dumps_typed(Interrupt(value="legacy_test", ns=["legacy_test"], resumable=True, when="during"))
|
||||
legacy_interrupt_bytes = b'{"lc": 2, "type": "constructor", "id": ["langgraph", "types", "Interrupt"], "kwargs": {"value": "legacy_test", "resumable": true, "ns": ["legacy_test"], "when": "during"}}'
|
||||
legacy_interrupt_id = "f1fa625689ec006a5b32b76863e22a6c"
|
||||
|
||||
interrupt = serializer.loads(legacy_interrupt_bytes)
|
||||
interrupt = serializer.loads_typed(("json", legacy_interrupt_bytes))
|
||||
assert interrupt.id == legacy_interrupt_id
|
||||
assert interrupt.value == "legacy_test"
|
||||
|
||||
@@ -41,10 +41,10 @@ def test_serialization_roundtrip_complex_ns() -> None:
|
||||
"""Test that the legacy interrupt (pre v1), with a more complex ns can be reserialized as the modern interrupt without id corruption."""
|
||||
|
||||
# generated with:
|
||||
# JsonPlusSerializer().dumps(Interrupt(value="legacy_test", ns=["legacy:test", "with:complex", "name:space"], resumable=True, when="during"))
|
||||
# JsonPlusSerializer().dumps_typed(Interrupt(value="legacy_test", ns=["legacy:test", "with:complex", "name:space"], resumable=True, when="during"))
|
||||
legacy_interrupt_bytes = b'{"lc": 2, "type": "constructor", "id": ["langgraph", "types", "Interrupt"], "kwargs": {"value": "legacy_test", "resumable": true, "ns": ["legacy:test", "with:complex", "name:space"], "when": "during"}}'
|
||||
legacy_interrupt_id = "e69356a9ee3630ee7f4f597f2693000c"
|
||||
|
||||
interrupt = serializer.loads(legacy_interrupt_bytes)
|
||||
interrupt = serializer.loads_typed(("json", legacy_interrupt_bytes))
|
||||
assert interrupt.id == legacy_interrupt_id
|
||||
assert interrupt.value == "legacy_test"
|
||||
|
||||
@@ -44,6 +44,7 @@ from langgraph.channels.binop import BinaryOperatorAggregate
|
||||
from langgraph.channels.ephemeral_value import EphemeralValue
|
||||
from langgraph.channels.last_value import LastValue
|
||||
from langgraph.channels.topic import Topic
|
||||
from langgraph.channels.untracked_value import UntrackedValue
|
||||
from langgraph.config import get_stream_writer
|
||||
from langgraph.errors import GraphRecursionError, InvalidUpdateError, ParentCommand
|
||||
from langgraph.func import entrypoint, task
|
||||
@@ -60,6 +61,7 @@ from langgraph.types import (
|
||||
Command,
|
||||
Durability,
|
||||
Interrupt,
|
||||
Overwrite,
|
||||
PregelTask,
|
||||
RetryPolicy,
|
||||
Send,
|
||||
@@ -8597,3 +8599,249 @@ def test_multiple_writes_same_channel_from_same_node(
|
||||
"values": {"foo": ""},
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def test_send_with_untracked_value(sync_checkpointer: BaseCheckpointSaver):
|
||||
"""Test that Send objects work correctly with untracked values in state."""
|
||||
|
||||
class UnserializableResource:
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
self.lock = threading.Lock()
|
||||
|
||||
class State(TypedDict):
|
||||
messages: Annotated[list[str], operator.add]
|
||||
session_resource: Annotated[UnserializableResource, UntrackedValue]
|
||||
|
||||
def setup_node(state: State) -> State:
|
||||
resource = UnserializableResource("test_session")
|
||||
return {"messages": ["setup complete"], "session_resource": resource}
|
||||
|
||||
def send_to_tool(state: State):
|
||||
return [Send("tool_node", state)]
|
||||
|
||||
def tool_node(state: State) -> State:
|
||||
resource = state["session_resource"]
|
||||
assert isinstance(resource, UnserializableResource)
|
||||
assert resource.name == "test_session"
|
||||
|
||||
new_resource = UnserializableResource("new_session")
|
||||
|
||||
return {
|
||||
"messages": [f"tool used resource: {resource.name}"],
|
||||
"session_resource": new_resource,
|
||||
}
|
||||
|
||||
graph = StateGraph(State)
|
||||
graph.add_node("setup", setup_node)
|
||||
graph.add_node("tool_node", tool_node)
|
||||
graph.add_edge(START, "setup")
|
||||
graph.add_conditional_edges("setup", send_to_tool)
|
||||
|
||||
app = graph.compile(checkpointer=sync_checkpointer)
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
result = app.invoke({}, config)
|
||||
|
||||
assert len(result["messages"]) == 2
|
||||
assert result["messages"][0] == "setup complete"
|
||||
assert result["messages"][1] == "tool used resource: test_session"
|
||||
assert result["session_resource"].name == "new_session"
|
||||
|
||||
state = app.get_state(config)
|
||||
assert "session_resource" not in state.values
|
||||
|
||||
|
||||
def test_send_with_untracked_value_overlapping_keys(
|
||||
sync_checkpointer: BaseCheckpointSaver,
|
||||
):
|
||||
"""Test that Send objects work correctly with untracked values in state."""
|
||||
|
||||
class State(TypedDict):
|
||||
dictionary: dict
|
||||
session_resource: Annotated[str, UntrackedValue]
|
||||
|
||||
def setup_node(state: State) -> State:
|
||||
return {}
|
||||
|
||||
def send_to_tool(state: State):
|
||||
return [
|
||||
Send(
|
||||
"tool_node",
|
||||
{
|
||||
"dictionary": {"session_resource": "legal_value"},
|
||||
"session_resource": "illegal_value",
|
||||
},
|
||||
)
|
||||
]
|
||||
|
||||
def tool_node(state: State) -> State:
|
||||
print(f"STATE: {state}")
|
||||
assert state["dictionary"] == {"session_resource": "legal_value"}
|
||||
assert state["session_resource"] == "illegal_value"
|
||||
|
||||
return {
|
||||
"dictionary": state["dictionary"],
|
||||
"session_resource": "new_illegal_value",
|
||||
}
|
||||
|
||||
graph = StateGraph(State)
|
||||
graph.add_node("setup", setup_node)
|
||||
graph.add_node("tool_node", tool_node)
|
||||
graph.add_edge(START, "setup")
|
||||
graph.add_conditional_edges("setup", send_to_tool)
|
||||
|
||||
app = graph.compile(checkpointer=sync_checkpointer)
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
result = app.invoke({}, config)
|
||||
|
||||
assert result["session_resource"] == "new_illegal_value"
|
||||
state = app.get_state(config)
|
||||
assert "session_resource" not in state.values
|
||||
assert state.values.get("dictionary") == {"session_resource": "legal_value"}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("as_json", [False, True])
|
||||
def test_overwrite_sequential(
|
||||
sync_checkpointer: BaseCheckpointSaver, as_json: bool
|
||||
) -> None:
|
||||
"""Test a sequential chain of nodes where the last node uses Overwrite to bypass a reducer and write a value directly to the channel."""
|
||||
|
||||
class State(TypedDict):
|
||||
messages: Annotated[list, operator.add]
|
||||
|
||||
def node_a(state: State):
|
||||
return {"messages": ["a"]}
|
||||
|
||||
def node_b(state: State):
|
||||
overwrite = {"__overwrite__": ["b"]} if as_json else Overwrite(["b"])
|
||||
return {"messages": overwrite}
|
||||
|
||||
builder = StateGraph(State)
|
||||
builder.add_node("node_a", node_a)
|
||||
builder.add_node("node_b", node_b)
|
||||
builder.add_edge(START, "node_a")
|
||||
builder.add_edge("node_a", "node_b")
|
||||
|
||||
graph = builder.compile(checkpointer=sync_checkpointer)
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
result = graph.invoke({"messages": ["START"]}, config)
|
||||
# a is overwritten by b
|
||||
assert result == {"messages": ["b"]}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("as_json", [False, True])
|
||||
def test_overwrite_parallel(
|
||||
sync_checkpointer: BaseCheckpointSaver, as_json: bool
|
||||
) -> None:
|
||||
"""Test parallel nodes where max one node uses Overwrite to bypass a reducer and write a value directly to the channel."""
|
||||
|
||||
class State(TypedDict):
|
||||
messages: Annotated[list, operator.add]
|
||||
|
||||
def node_a(state: State):
|
||||
return {"messages": ["a"]}
|
||||
|
||||
def node_b(state: State):
|
||||
overwrite = {"__overwrite__": ["b"]} if as_json else Overwrite(["b"])
|
||||
return {"messages": overwrite}
|
||||
|
||||
def node_c(state: State):
|
||||
return {"messages": ["c"]}
|
||||
|
||||
def node_d(state: State):
|
||||
return {"messages": ["d"]}
|
||||
|
||||
builder = StateGraph(State)
|
||||
builder.add_node("node_a", node_a)
|
||||
builder.add_node("node_b", node_b)
|
||||
builder.add_node("node_c", node_c)
|
||||
builder.add_node("node_d", node_d)
|
||||
builder.add_edge(START, "node_a")
|
||||
builder.add_edge("node_a", "node_b")
|
||||
builder.add_edge("node_a", "node_c")
|
||||
builder.add_edge("node_b", "node_d")
|
||||
builder.add_edge("node_c", "node_d")
|
||||
|
||||
graph = builder.compile(checkpointer=sync_checkpointer)
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
result = graph.invoke({"messages": ["START"]}, config)
|
||||
# a, c are overwritten by b, then d is written
|
||||
assert result == {"messages": ["b", "d"]}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("as_json", [False, True])
|
||||
def test_overwrite_parallel_error(
|
||||
sync_checkpointer: BaseCheckpointSaver, as_json: bool
|
||||
) -> None:
|
||||
"""Test parallel nodes where more than one node uses Overwrite to bypass a reducer and write a value directly to the channel. In this case, InvalidUpdateError should be raised."""
|
||||
|
||||
class State(TypedDict):
|
||||
messages: Annotated[list, operator.add]
|
||||
|
||||
def node_a(state: State):
|
||||
return {"messages": ["a"]}
|
||||
|
||||
def node_b(state: State):
|
||||
overwrite = {"__overwrite__": ["b"]} if as_json else Overwrite(["b"])
|
||||
return {"messages": overwrite}
|
||||
|
||||
def node_c(state: State):
|
||||
overwrite = {"__overwrite__": ["c"]} if as_json else Overwrite(["c"])
|
||||
return {"messages": overwrite}
|
||||
|
||||
builder = StateGraph(State)
|
||||
builder.add_node("node_a", node_a)
|
||||
builder.add_node("node_b", node_b)
|
||||
builder.add_node("node_c", node_c)
|
||||
builder.add_edge(START, "node_a")
|
||||
builder.add_edge("node_a", "node_b")
|
||||
builder.add_edge("node_a", "node_c")
|
||||
builder.add_edge("node_b", END)
|
||||
builder.add_edge("node_c", END)
|
||||
|
||||
graph = builder.compile(checkpointer=sync_checkpointer)
|
||||
config = {"configurable": {"thread_id": "1"}}
|
||||
with pytest.raises(
|
||||
InvalidUpdateError, match="Can receive only one Overwrite value per super-step."
|
||||
):
|
||||
graph.invoke({"messages": ["START"]}, config)
|
||||
|
||||
|
||||
def test_fork_does_not_apply_pending_writes(
|
||||
sync_checkpointer: BaseCheckpointSaver,
|
||||
) -> None:
|
||||
"""Test that forking with update_state does not apply pending writes from original execution."""
|
||||
|
||||
class State(TypedDict):
|
||||
value: Annotated[int, operator.add]
|
||||
|
||||
def node_a(state: State) -> State:
|
||||
return {"value": 10}
|
||||
|
||||
def node_b(state: State) -> State:
|
||||
return {"value": 100}
|
||||
|
||||
graph = (
|
||||
StateGraph(State)
|
||||
.add_node("node_a", node_a)
|
||||
.add_node("node_b", node_b)
|
||||
.add_edge(START, "node_a")
|
||||
.add_edge("node_a", "node_b")
|
||||
.compile(checkpointer=sync_checkpointer)
|
||||
)
|
||||
|
||||
thread1 = {"configurable": {"thread_id": "1"}}
|
||||
graph.invoke({"value": 1}, thread1)
|
||||
|
||||
history = list(graph.get_state_history(thread1))
|
||||
checkpoint_before_a = next(s for s in history if s.next == ("node_a",))
|
||||
|
||||
fork_config = graph.update_state(
|
||||
checkpoint_before_a.config, {"value": 20}, as_node="node_a"
|
||||
)
|
||||
|
||||
# Continue from fork (should run node_b)
|
||||
result = graph.invoke(None, fork_config)
|
||||
|
||||
# Should be: 1 (input) + 20 (forked node_a) + 100 (node_b) = 121
|
||||
assert result == {"value": 121}
|
||||
|
||||
@@ -9249,3 +9249,41 @@ async def test_supersteps_populate_task_results(
|
||||
|
||||
assert bulk_start_result == ref_start_result == {"num": 1, "text": "one"}
|
||||
assert bulk_double_result == ref_double_result == {"num": 2, "text": "oneone"}
|
||||
|
||||
|
||||
async def test_fork_does_not_apply_pending_writes(
|
||||
async_checkpointer: BaseCheckpointSaver,
|
||||
) -> None:
|
||||
"""Test that forking with aupdate_state does not apply pending writes from original execution."""
|
||||
|
||||
class State(TypedDict):
|
||||
value: Annotated[int, operator.add]
|
||||
|
||||
def node_a(state: State) -> State:
|
||||
return {"value": 10}
|
||||
|
||||
def node_b(state: State) -> State:
|
||||
return {"value": 100}
|
||||
|
||||
graph = (
|
||||
StateGraph(State)
|
||||
.add_node("node_a", node_a)
|
||||
.add_node("node_b", node_b)
|
||||
.add_edge(START, "node_a")
|
||||
.add_edge("node_a", "node_b")
|
||||
.compile(checkpointer=async_checkpointer)
|
||||
)
|
||||
|
||||
thread1 = {"configurable": {"thread_id": "1"}}
|
||||
await graph.ainvoke({"value": 1}, thread1)
|
||||
|
||||
history = [c async for c in graph.aget_state_history(thread1)]
|
||||
checkpoint_before_a = next(s for s in history if s.next == ("node_a",))
|
||||
|
||||
fork_config = await graph.aupdate_state(
|
||||
checkpoint_before_a.config, {"value": 20}, as_node="node_a"
|
||||
)
|
||||
result = await graph.ainvoke(None, fork_config)
|
||||
|
||||
# 1 (input) + 20 (forked node_a) + 100 (node_b) = 121
|
||||
assert result == {"value": 121}
|
||||
|
||||
@@ -34,6 +34,11 @@ NEEDS_CONTEXTVARS = pytest.mark.skipif(
|
||||
reason="Python 3.11+ is required for async contextvars support",
|
||||
)
|
||||
|
||||
SKIP_PYTHON_314 = pytest.mark.skipif(
|
||||
sys.version_info >= (3, 14),
|
||||
reason="Not yet testing Python 3.14 with the server bc of dependency limits on the api side",
|
||||
)
|
||||
|
||||
|
||||
def test_with_config():
|
||||
# set up test
|
||||
@@ -1106,6 +1111,7 @@ def get_message_dict(msg: BaseMessage | dict):
|
||||
|
||||
|
||||
@NEEDS_CONTEXTVARS
|
||||
@SKIP_PYTHON_314
|
||||
async def test_remote_graph_basic_invoke(remote_graph: RemoteGraph) -> None:
|
||||
# Basic smoke test of the remote graph
|
||||
response = await remote_graph.ainvoke(
|
||||
@@ -1118,7 +1124,6 @@ async def test_remote_graph_basic_invoke(remote_graph: RemoteGraph) -> None:
|
||||
"type": "ai",
|
||||
"name": None,
|
||||
"id": "ai3",
|
||||
"example": False,
|
||||
"tool_calls": [],
|
||||
"invalid_tool_calls": [],
|
||||
"usage_metadata": None,
|
||||
@@ -1143,6 +1148,7 @@ uid_pattern = re.compile(
|
||||
|
||||
|
||||
@NEEDS_CONTEXTVARS
|
||||
@SKIP_PYTHON_314
|
||||
async def test_remote_graph_stream_messages_tuple(
|
||||
nested_graph: Pregel, nested_remote_graph: Pregel
|
||||
) -> None:
|
||||
|
||||
Generated
+1058
-699
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(make test:*)",
|
||||
"Bash(uv run pytest:*)",
|
||||
"Bash(LANGGRAPH_TEST_FAST=0 make start-services:*)",
|
||||
"Bash(LANGGRAPH_TEST_FAST=0 uv run:*)",
|
||||
"Bash(EXIT_CODE=$?)",
|
||||
"Bash(make stop-services:*)",
|
||||
"Bash(exit $EXIT_CODE)",
|
||||
"Read(//Users/sydney_runkle/oss/langgraph/**)",
|
||||
"Bash(python3:*)",
|
||||
"Bash(find:*)",
|
||||
"Bash(python -m pytest:*)",
|
||||
"Bash(python:*)",
|
||||
"Read(//tmp/**)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ from langgraph.prebuilt.tool_node import (
|
||||
InjectedState,
|
||||
InjectedStore,
|
||||
ToolNode,
|
||||
ToolRuntime,
|
||||
tools_condition,
|
||||
)
|
||||
from langgraph.prebuilt.tool_validator import ValidationNode
|
||||
@@ -16,4 +17,5 @@ __all__ = [
|
||||
"ValidationNode",
|
||||
"InjectedState",
|
||||
"InjectedStore",
|
||||
"ToolRuntime",
|
||||
]
|
||||
|
||||
@@ -44,7 +44,7 @@ from langgraph.warnings import LangGraphDeprecatedSinceV10
|
||||
from pydantic import BaseModel
|
||||
from typing_extensions import NotRequired, TypedDict, deprecated
|
||||
|
||||
from langgraph.prebuilt.tool_node import ToolNode
|
||||
from langgraph.prebuilt.tool_node import ToolCallWithContext, ToolNode
|
||||
|
||||
StructuredResponse = dict | BaseModel
|
||||
StructuredResponseSchema = dict | type[BaseModel]
|
||||
@@ -63,7 +63,7 @@ class AgentState(TypedDict):
|
||||
|
||||
|
||||
@deprecated(
|
||||
"AgentStatePydantic has been moved to `langchain.agents`. Please update your import to `from langchain.agents import AgentStatePydantic`.",
|
||||
"AgentStatePydantic has been deprecated in favor of AgentState in `langchain.agents`.",
|
||||
category=LangGraphDeprecatedSinceV10,
|
||||
)
|
||||
class AgentStatePydantic(BaseModel):
|
||||
@@ -78,11 +78,11 @@ with warnings.catch_warnings():
|
||||
warnings.filterwarnings(
|
||||
"ignore",
|
||||
category=LangGraphDeprecatedSinceV10,
|
||||
message="AgentState has been moved to langchain.agents.*",
|
||||
message="AgentState has been moved to `langchain.agents`.*",
|
||||
)
|
||||
|
||||
@deprecated(
|
||||
"AgentStateWithStructuredResponse has been moved to `langchain.agents`. Please update your import to `from langchain.agents import AgentStateWithStructuredResponse`.",
|
||||
"AgentStateWithStructuredResponse has been deprecated in favor of AgentState in `langchain.agents`.",
|
||||
category=LangGraphDeprecatedSinceV10,
|
||||
)
|
||||
class AgentStateWithStructuredResponse(AgentState):
|
||||
@@ -95,11 +95,11 @@ with warnings.catch_warnings():
|
||||
warnings.filterwarnings(
|
||||
"ignore",
|
||||
category=LangGraphDeprecatedSinceV10,
|
||||
message="AgentStatePydantic has been moved to langchain.agents.*",
|
||||
message="AgentStatePydantic has been deprecated in favor of AgentState in `langchain.agents`.",
|
||||
)
|
||||
|
||||
@deprecated(
|
||||
"AgentStateWithStructuredResponsePydantic has been moved to `langchain.agents`. Please update your import to `from langchain.agents import AgentStateWithStructuredResponsePydantic`.",
|
||||
"AgentStateWithStructuredResponsePydantic has been deprecated in favor of AgentState in `langchain.agents`.",
|
||||
category=LangGraphDeprecatedSinceV10,
|
||||
)
|
||||
class AgentStateWithStructuredResponsePydantic(AgentStatePydantic):
|
||||
@@ -309,64 +309,71 @@ def create_react_agent(
|
||||
model: The language model for the agent. Supports static and dynamic
|
||||
model selection.
|
||||
|
||||
- **Static model**: A chat model instance (e.g., `ChatOpenAI()`) or
|
||||
string identifier (e.g., `"openai:gpt-4"`)
|
||||
- **Static model**: A chat model instance (e.g.,
|
||||
[`ChatOpenAI`][langchain_openai.ChatOpenAI]) or string identifier (e.g.,
|
||||
`"openai:gpt-4"`)
|
||||
- **Dynamic model**: A callable with signature
|
||||
`(state, runtime) -> BaseChatModel` that returns different models
|
||||
based on runtime context
|
||||
If the model has tools bound via `.bind_tools()` or other configurations,
|
||||
the return type should be a Runnable[LanguageModelInput, BaseMessage]
|
||||
Coroutines are also supported, allowing for asynchronous model selection.
|
||||
`(state, runtime) -> BaseChatModel` that returns different models
|
||||
based on runtime context
|
||||
|
||||
If the model has tools bound via `bind_tools` or other configurations,
|
||||
the return type should be a `Runnable[LanguageModelInput, BaseMessage]`
|
||||
Coroutines are also supported, allowing for asynchronous model selection.
|
||||
|
||||
Dynamic functions receive graph state and runtime, enabling
|
||||
context-dependent model selection. Must return a `BaseChatModel`
|
||||
instance. For tool calling, bind tools using `.bind_tools()`.
|
||||
Bound tools must be a subset of the `tools` parameter.
|
||||
|
||||
Dynamic model example:
|
||||
```python
|
||||
from dataclasses import dataclass
|
||||
!!! example "Dynamic model"
|
||||
|
||||
@dataclass
|
||||
class ModelContext:
|
||||
model_name: str = "gpt-3.5-turbo"
|
||||
```python
|
||||
from dataclasses import dataclass
|
||||
|
||||
# Instantiate models globally
|
||||
gpt4_model = ChatOpenAI(model="gpt-4")
|
||||
gpt35_model = ChatOpenAI(model="gpt-3.5-turbo")
|
||||
@dataclass
|
||||
class ModelContext:
|
||||
model_name: str = "gpt-3.5-turbo"
|
||||
|
||||
def select_model(state: AgentState, runtime: Runtime[ModelContext]) -> ChatOpenAI:
|
||||
model_name = runtime.context.model_name
|
||||
model = gpt4_model if model_name == "gpt-4" else gpt35_model
|
||||
return model.bind_tools(tools)
|
||||
```
|
||||
# Instantiate models globally
|
||||
gpt4_model = ChatOpenAI(model="gpt-4")
|
||||
gpt35_model = ChatOpenAI(model="gpt-3.5-turbo")
|
||||
|
||||
def select_model(state: AgentState, runtime: Runtime[ModelContext]) -> ChatOpenAI:
|
||||
model_name = runtime.context.model_name
|
||||
model = gpt4_model if model_name == "gpt-4" else gpt35_model
|
||||
return model.bind_tools(tools)
|
||||
```
|
||||
|
||||
!!! note "Dynamic Model Requirements"
|
||||
|
||||
Ensure returned models have appropriate tools bound via
|
||||
`.bind_tools()` and support required functionality. Bound tools
|
||||
must be a subset of those specified in the `tools` parameter.
|
||||
|
||||
tools: A list of tools or a ToolNode instance.
|
||||
tools: A list of tools or a `ToolNode` instance.
|
||||
If an empty list is provided, the agent will consist of a single LLM node without tool calling.
|
||||
prompt: An optional prompt for the LLM. Can take a few different forms:
|
||||
|
||||
- str: This is converted to a SystemMessage and added to the beginning of the list of messages in state["messages"].
|
||||
- SystemMessage: this is added to the beginning of the list of messages in state["messages"].
|
||||
- Callable: This function should take in full graph state and the output is then passed to the language model.
|
||||
- Runnable: This runnable should take in full graph state and the output is then passed to the language model.
|
||||
- `str`: This is converted to a `SystemMessage` and added to the beginning of the list of messages in `state["messages"]`.
|
||||
- `SystemMessage`: this is added to the beginning of the list of messages in `state["messages"]`.
|
||||
- `Callable`: This function should take in full graph state and the output is then passed to the language model.
|
||||
- `Runnable`: This runnable should take in full graph state and the output is then passed to the language model.
|
||||
|
||||
response_format: An optional schema for the final agent output.
|
||||
|
||||
If provided, output will be formatted to match the given schema and returned in the 'structured_response' state key.
|
||||
|
||||
If not provided, `structured_response` will not be present in the output state.
|
||||
|
||||
Can be passed in as:
|
||||
|
||||
- an OpenAI function/tool schema,
|
||||
- a JSON Schema,
|
||||
- a TypedDict class,
|
||||
- or a Pydantic class.
|
||||
- a tuple (prompt, schema), where schema is one of the above.
|
||||
The prompt will be used together with the model that is being used to generate the structured response.
|
||||
- An OpenAI function/tool schema,
|
||||
- A JSON Schema,
|
||||
- A TypedDict class,
|
||||
- A Pydantic class.
|
||||
- A tuple `(prompt, schema)`, where schema is one of the above.
|
||||
The prompt will be used together with the model that is being used to
|
||||
generate the structured response.
|
||||
|
||||
!!! Important
|
||||
`response_format` requires the model to support `.with_structured_output`
|
||||
@@ -427,13 +434,16 @@ def create_react_agent(
|
||||
store: An optional store object. This is used for persisting data
|
||||
across multiple threads (e.g., multiple conversations / users).
|
||||
interrupt_before: An optional list of node names to interrupt before.
|
||||
Should be one of the following: "agent", "tools".
|
||||
Should be one of the following: `"agent"`, `"tools"`.
|
||||
|
||||
This is useful if you want to add a user confirmation or other interrupt before taking an action.
|
||||
interrupt_after: An optional list of node names to interrupt after.
|
||||
Should be one of the following: "agent", "tools".
|
||||
Should be one of the following: `"agent"`, `"tools"`.
|
||||
|
||||
This is useful if you want to return directly or run additional processing on an output.
|
||||
debug: A flag indicating whether to enable debug mode.
|
||||
version: Determines the version of the graph to create.
|
||||
|
||||
Can be one of:
|
||||
|
||||
- `"v1"`: The tool node processes a single message. All tool
|
||||
@@ -442,7 +452,7 @@ def create_react_agent(
|
||||
Tool calls are distributed across multiple instances of the tool
|
||||
node using the [Send](https://langchain-ai.github.io/langgraph/concepts/low_level/#send)
|
||||
API.
|
||||
name: An optional name for the CompiledStateGraph.
|
||||
name: An optional name for the `CompiledStateGraph`.
|
||||
This name will be automatically used when adding ReAct agent graph to another graph as a subgraph node -
|
||||
particularly useful for building multi-agent systems.
|
||||
|
||||
@@ -452,14 +462,14 @@ def create_react_agent(
|
||||
|
||||
|
||||
Returns:
|
||||
A compiled LangChain runnable that can be used for chat interactions.
|
||||
A compiled LangChain `Runnable` that can be used for chat interactions.
|
||||
|
||||
The "agent" node calls the language model with the messages list (after applying the prompt).
|
||||
If the resulting AIMessage contains `tool_calls`, the graph will then call the ["tools"][langgraph.prebuilt.tool_node.ToolNode].
|
||||
The "tools" node executes the tools (1 tool per `tool_call`) and adds the responses to the messages list
|
||||
as `ToolMessage` objects. The agent node then calls the language model again.
|
||||
The process repeats until no more `tool_calls` are present in the response.
|
||||
The agent then returns the full list of messages as a dictionary containing the key "messages".
|
||||
The agent then returns the full list of messages as a dictionary containing the key `'messages'`.
|
||||
|
||||
``` mermaid
|
||||
sequenceDiagram
|
||||
@@ -825,11 +835,17 @@ def create_react_agent(
|
||||
elif version == "v2":
|
||||
if post_model_hook is not None:
|
||||
return "post_model_hook"
|
||||
tool_calls = [
|
||||
tool_node.inject_tool_args(call, state, store) # type: ignore[arg-type]
|
||||
return [
|
||||
Send(
|
||||
"tools",
|
||||
ToolCallWithContext(
|
||||
__type="tool_call_with_context",
|
||||
tool_call=call,
|
||||
state=state,
|
||||
),
|
||||
)
|
||||
for call in last_message.tool_calls
|
||||
]
|
||||
return [Send("tools", [tool_call]) for tool_call in tool_calls]
|
||||
|
||||
# Define a new graph
|
||||
workflow = StateGraph(
|
||||
@@ -910,11 +926,17 @@ def create_react_agent(
|
||||
]
|
||||
|
||||
if pending_tool_calls:
|
||||
pending_tool_calls = [
|
||||
tool_node.inject_tool_args(call, state, store) # type: ignore[arg-type]
|
||||
return [
|
||||
Send(
|
||||
"tools",
|
||||
ToolCallWithContext(
|
||||
__type="tool_call_with_context",
|
||||
tool_call=call,
|
||||
state=state,
|
||||
),
|
||||
)
|
||||
for call in pending_tool_calls
|
||||
]
|
||||
return [Send("tools", [tool_call]) for tool_call in pending_tool_calls]
|
||||
elif isinstance(messages[-1], ToolMessage):
|
||||
return entrypoint
|
||||
elif response_format is not None:
|
||||
|
||||
@@ -36,7 +36,7 @@ class ActionRequest(TypedDict):
|
||||
Contains the action type and any associated arguments needed for the action.
|
||||
|
||||
Attributes:
|
||||
action: The type or name of action being requested (e.g., "Approve XYZ action")
|
||||
action: The type or name of action being requested (e.g., `"Approve XYZ action"`)
|
||||
args: Key-value pairs of arguments needed for the action
|
||||
"""
|
||||
|
||||
@@ -89,14 +89,16 @@ class HumanResponse(TypedDict):
|
||||
|
||||
Attributes:
|
||||
type: The type of response:
|
||||
- "accept": Approves the current state without changes
|
||||
- "ignore": Skips/ignores the current step
|
||||
- "response": Provides text feedback or instructions
|
||||
- "edit": Modifies the current state/content
|
||||
|
||||
- `'accept'`: Approves the current state without changes
|
||||
- `'ignore'`: Skips/ignores the current step
|
||||
- `'response'`: Provides text feedback or instructions
|
||||
- `'edit'`: Modifies the current state/content
|
||||
args: The response payload:
|
||||
- None: For ignore/accept actions
|
||||
- str: For text responses
|
||||
- ActionRequest: For edit actions with updated content
|
||||
|
||||
- `None`: For ignore/accept actions
|
||||
- `str`: For text responses
|
||||
- `ActionRequest`: For edit actions with updated content
|
||||
"""
|
||||
|
||||
type: Literal["accept", "ignore", "response", "edit"]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,9 +45,9 @@ def _default_format_error(
|
||||
category=LangGraphDeprecatedSinceV10,
|
||||
)
|
||||
class ValidationNode(RunnableCallable):
|
||||
"""A node that validates all tools requests from the last AIMessage.
|
||||
"""A node that validates all tools requests from the last `AIMessage`.
|
||||
|
||||
It can be used either in StateGraph with a "messages" key.
|
||||
It can be used either in `StateGraph` with a `'messages'` key.
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -57,7 +57,8 @@ class ValidationNode(RunnableCallable):
|
||||
messages and tool IDs (for use in multi-turn conversations).
|
||||
|
||||
Returns:
|
||||
(Union[Dict[str, List[ToolMessage]], Sequence[ToolMessage]]): A list of ToolMessages with the validated content or error messages.
|
||||
(Union[Dict[str, List[ToolMessage]], Sequence[ToolMessage]]): A list of
|
||||
`ToolMessage` objects with the validated content or error messages.
|
||||
|
||||
Example:
|
||||
```python title="Example usage for re-prompting the model to generate a valid response:"
|
||||
|
||||
@@ -4,36 +4,58 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "langgraph-prebuilt"
|
||||
version = "0.7.0rc1"
|
||||
version = "1.0.4"
|
||||
description = "Library with high-level APIs for creating and executing LangGraph agents and tools."
|
||||
authors = []
|
||||
requires-python = ">=3.10"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
license-files = ['LICENSE']
|
||||
classifiers = [
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3 :: Only',
|
||||
'Programming Language :: Python :: 3.10',
|
||||
'Programming Language :: Python :: 3.11',
|
||||
'Programming Language :: Python :: 3.12',
|
||||
'Programming Language :: Python :: 3.13',
|
||||
]
|
||||
dependencies = [
|
||||
"langgraph-checkpoint>=2.1.0,<3.0.0",
|
||||
"langchain-core>=0.3.67",
|
||||
"langgraph-checkpoint>=2.1.0,<4.0.0",
|
||||
"langchain-core>=1.0.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/prebuilt"
|
||||
Twitter = "https://x.com/LangChainAI"
|
||||
Slack = "https://www.langchain.com/join-community"
|
||||
Reddit = "https://www.reddit.com/r/LangChain/"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
test = [
|
||||
"pytest",
|
||||
"pytest-asyncio",
|
||||
"pytest-mock",
|
||||
"pytest-watcher",
|
||||
"mypy",
|
||||
"langchain-core",
|
||||
"langgraph",
|
||||
"langgraph-checkpoint",
|
||||
"langgraph-checkpoint-sqlite",
|
||||
"langgraph-checkpoint-postgres",
|
||||
"syrupy",
|
||||
"psycopg-binary",
|
||||
]
|
||||
lint = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
"mypy",
|
||||
]
|
||||
dev = [
|
||||
{include-group = "test"},
|
||||
{include-group = "lint"},
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,14 @@
|
||||
import dataclasses
|
||||
import inspect
|
||||
import json
|
||||
import sys
|
||||
from functools import partial
|
||||
from typing import (
|
||||
Annotated,
|
||||
Literal,
|
||||
TypeVar,
|
||||
)
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from langchain_core.language_models import BaseChatModel
|
||||
@@ -63,6 +65,29 @@ pytestmark = pytest.mark.anyio
|
||||
REACT_TOOL_CALL_VERSIONS = ["v1", "v2"]
|
||||
|
||||
|
||||
def _create_mock_runtime(store: BaseStore | None = None) -> Mock:
|
||||
"""Create a mock Runtime object for testing ToolNode outside of graph context.
|
||||
|
||||
This helper is needed because ToolNode._func expects a Runtime parameter
|
||||
which is injected by RunnableCallable from config["configurable"]["__pregel_runtime"].
|
||||
When testing ToolNode directly (outside a graph), we need to provide this manually.
|
||||
"""
|
||||
mock_runtime = Mock()
|
||||
mock_runtime.store = store
|
||||
mock_runtime.context = None
|
||||
mock_runtime.stream_writer = lambda *args, **kwargs: None
|
||||
return mock_runtime
|
||||
|
||||
|
||||
def _create_config_with_runtime(store: BaseStore | None = None) -> RunnableConfig:
|
||||
"""Create a RunnableConfig with mock Runtime for testing ToolNode.
|
||||
|
||||
Returns:
|
||||
RunnableConfig with __pregel_runtime in configurable dict.
|
||||
"""
|
||||
return {"configurable": {"__pregel_runtime": _create_mock_runtime(store)}}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version", REACT_TOOL_CALL_VERSIONS)
|
||||
def test_no_prompt(sync_checkpointer: BaseCheckpointSaver, version: str) -> None:
|
||||
model = FakeToolCallingModel()
|
||||
@@ -326,7 +351,8 @@ def test_model_with_tools(tool_style: str, version: str, include_builtin: bool):
|
||||
],
|
||||
)
|
||||
]
|
||||
}
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
tool_messages: ToolMessage = result["messages"][-2:]
|
||||
for tool_message in tool_messages:
|
||||
@@ -678,7 +704,13 @@ T = TypeVar("T")
|
||||
"schema_",
|
||||
[
|
||||
_InjectStateSchema,
|
||||
_InjectedStatePydanticSchema,
|
||||
pytest.param(
|
||||
_InjectedStatePydanticSchema,
|
||||
marks=pytest.mark.skipif(
|
||||
sys.version_info >= (3, 14),
|
||||
reason="Pydantic v1 not supported in Python 3.14+",
|
||||
),
|
||||
),
|
||||
_InjectedStatePydanticV2Schema,
|
||||
_InjectedStateDataclassSchema,
|
||||
],
|
||||
@@ -721,37 +753,13 @@ def test_tool_node_inject_state(schema_: type[T]) -> None:
|
||||
"type": "tool_call",
|
||||
}
|
||||
msg = AIMessage("hi?", tool_calls=[tool_call])
|
||||
result = node.invoke(schema_(**{"messages": [msg], "foo": "bar"}))
|
||||
result = node.invoke(
|
||||
schema_(**{"messages": [msg], "foo": "bar"}),
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
tool_message = result["messages"][-1]
|
||||
assert tool_message.content == "bar", f"Failed for tool={tool_name}"
|
||||
|
||||
if tool_name == "tool3":
|
||||
failure_input = None
|
||||
try:
|
||||
failure_input = schema_(**{"messages": [msg], "notfoo": "bar"})
|
||||
except Exception:
|
||||
pass
|
||||
if failure_input is not None:
|
||||
with pytest.raises(KeyError):
|
||||
node.invoke(failure_input)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
node.invoke([msg])
|
||||
else:
|
||||
failure_input = None
|
||||
try:
|
||||
failure_input = schema_(**{"messages": [msg], "notfoo": "bar"})
|
||||
except Exception:
|
||||
# We'd get a validation error from pydantic state and wouldn't make it to the node
|
||||
# anyway
|
||||
pass
|
||||
if failure_input is not None:
|
||||
messages_ = node.invoke(failure_input)
|
||||
tool_message = messages_["messages"][-1]
|
||||
assert "KeyError" in tool_message.content
|
||||
tool_message = node.invoke([msg])[-1]
|
||||
assert "KeyError" in tool_message.content
|
||||
|
||||
tool_call = {
|
||||
"name": "tool4",
|
||||
"args": {"some_val": 1},
|
||||
@@ -759,11 +767,13 @@ def test_tool_node_inject_state(schema_: type[T]) -> None:
|
||||
"type": "tool_call",
|
||||
}
|
||||
msg = AIMessage("hi?", tool_calls=[tool_call])
|
||||
result = node.invoke(schema_(**{"messages": [msg], "foo": ""}))
|
||||
result = node.invoke(
|
||||
schema_(**{"messages": [msg], "foo": ""}), config=_create_config_with_runtime()
|
||||
)
|
||||
tool_message = result["messages"][-1]
|
||||
assert tool_message.content == "hi?"
|
||||
|
||||
result = node.invoke([msg])
|
||||
result = node.invoke([msg], config=_create_config_with_runtime())
|
||||
tool_message = result[-1]
|
||||
assert tool_message.content == "hi?"
|
||||
|
||||
@@ -875,7 +885,9 @@ def test_tool_node_inject_store() -> None:
|
||||
"type": "tool_call",
|
||||
}
|
||||
msg = AIMessage("hi?", tool_calls=[tool_call])
|
||||
node_result = node.invoke({"messages": [msg]}, store=store)
|
||||
node_result = node.invoke(
|
||||
{"messages": [msg]}, config=_create_config_with_runtime(store=store)
|
||||
)
|
||||
graph_result = graph.invoke({"messages": [msg]})
|
||||
for result in (node_result, graph_result):
|
||||
result["messages"][-1]
|
||||
@@ -891,7 +903,10 @@ def test_tool_node_inject_store() -> None:
|
||||
"type": "tool_call",
|
||||
}
|
||||
msg = AIMessage("hi?", tool_calls=[tool_call])
|
||||
node_result = node.invoke({"messages": [msg], "bar": "baz"}, store=store)
|
||||
node_result = node.invoke(
|
||||
{"messages": [msg], "bar": "baz"},
|
||||
config=_create_config_with_runtime(store=store),
|
||||
)
|
||||
graph_result = graph.invoke({"messages": [msg], "bar": "baz"})
|
||||
for result in (node_result, graph_result):
|
||||
result["messages"][-1]
|
||||
@@ -916,7 +931,8 @@ def test_tool_node_ensure_utf8() -> None:
|
||||
tools = [get_day_list]
|
||||
tool_calls = [ToolCall(name=get_day_list.name, args={"days": data}, id="test_id")]
|
||||
outputs: list[ToolMessage] = ToolNode(tools).invoke(
|
||||
[AIMessage(content="", tool_calls=tool_calls)]
|
||||
[AIMessage(content="", tool_calls=tool_calls)],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
assert outputs[0].content == json.dumps(data, ensure_ascii=False)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,578 @@
|
||||
"""Test tool node interceptor handling of unregistered tools."""
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from langchain_core.messages import AIMessage, ToolMessage
|
||||
from langchain_core.runnables.config import RunnableConfig
|
||||
from langchain_core.tools import tool as dec_tool
|
||||
from langgraph.store.base import BaseStore
|
||||
from langgraph.types import Command
|
||||
|
||||
from langgraph.prebuilt import ToolNode
|
||||
from langgraph.prebuilt.tool_node import ToolCallRequest
|
||||
|
||||
pytestmark = pytest.mark.anyio
|
||||
|
||||
|
||||
def _create_mock_runtime(store: BaseStore | None = None) -> Mock:
|
||||
"""Create a mock Runtime object for testing ToolNode outside of graph context.
|
||||
|
||||
This helper is needed because ToolNode._func expects a Runtime parameter
|
||||
which is injected by RunnableCallable from config["configurable"]["__pregel_runtime"].
|
||||
When testing ToolNode directly (outside a graph), we need to provide this manually.
|
||||
"""
|
||||
mock_runtime = Mock()
|
||||
mock_runtime.store = store
|
||||
mock_runtime.context = None
|
||||
mock_runtime.stream_writer = lambda *args, **kwargs: None
|
||||
return mock_runtime
|
||||
|
||||
|
||||
def _create_config_with_runtime(store: BaseStore | None = None) -> RunnableConfig:
|
||||
"""Create a RunnableConfig with mock Runtime for testing ToolNode.
|
||||
|
||||
Returns:
|
||||
RunnableConfig with __pregel_runtime in configurable dict.
|
||||
"""
|
||||
return {"configurable": {"__pregel_runtime": _create_mock_runtime(store)}}
|
||||
|
||||
|
||||
@dec_tool
|
||||
def registered_tool(x: int) -> str:
|
||||
"""A registered tool."""
|
||||
return f"Result: {x}"
|
||||
|
||||
|
||||
def test_interceptor_can_handle_unregistered_tool_sync() -> None:
|
||||
"""Test that interceptor can handle requests for unregistered tools (sync)."""
|
||||
|
||||
def interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], ToolMessage | Command],
|
||||
) -> ToolMessage | Command:
|
||||
"""Intercept and handle unregistered tools."""
|
||||
if request.tool_call["name"] == "unregistered_tool":
|
||||
# Short-circuit without calling execute for unregistered tool
|
||||
return ToolMessage(
|
||||
content="Handled by interceptor",
|
||||
tool_call_id=request.tool_call["id"],
|
||||
name="unregistered_tool",
|
||||
)
|
||||
# Pass through for registered tools
|
||||
return execute(request)
|
||||
|
||||
node = ToolNode([registered_tool], wrap_tool_call=interceptor)
|
||||
|
||||
# Test registered tool works normally
|
||||
result = node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "registered_tool",
|
||||
"args": {"x": 42},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
assert result[0].content == "Result: 42"
|
||||
assert result[0].tool_call_id == "1"
|
||||
|
||||
# Test unregistered tool is intercepted and handled
|
||||
result = node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "unregistered_tool",
|
||||
"args": {"x": 99},
|
||||
"id": "2",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
assert result[0].content == "Handled by interceptor"
|
||||
assert result[0].tool_call_id == "2"
|
||||
assert result[0].name == "unregistered_tool"
|
||||
|
||||
|
||||
async def test_interceptor_can_handle_unregistered_tool_async() -> None:
|
||||
"""Test that interceptor can handle requests for unregistered tools (async)."""
|
||||
|
||||
async def async_interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]],
|
||||
) -> ToolMessage | Command:
|
||||
"""Intercept and handle unregistered tools."""
|
||||
if request.tool_call["name"] == "unregistered_tool":
|
||||
# Short-circuit without calling execute for unregistered tool
|
||||
return ToolMessage(
|
||||
content="Handled by async interceptor",
|
||||
tool_call_id=request.tool_call["id"],
|
||||
name="unregistered_tool",
|
||||
)
|
||||
# Pass through for registered tools
|
||||
return await execute(request)
|
||||
|
||||
node = ToolNode([registered_tool], awrap_tool_call=async_interceptor)
|
||||
|
||||
# Test registered tool works normally
|
||||
result = await node.ainvoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "registered_tool",
|
||||
"args": {"x": 42},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
assert result[0].content == "Result: 42"
|
||||
assert result[0].tool_call_id == "1"
|
||||
|
||||
# Test unregistered tool is intercepted and handled
|
||||
result = await node.ainvoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "unregistered_tool",
|
||||
"args": {"x": 99},
|
||||
"id": "2",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
assert result[0].content == "Handled by async interceptor"
|
||||
assert result[0].tool_call_id == "2"
|
||||
assert result[0].name == "unregistered_tool"
|
||||
|
||||
|
||||
def test_unregistered_tool_error_when_interceptor_calls_execute() -> None:
|
||||
"""Test that unregistered tools error if interceptor tries to execute them."""
|
||||
|
||||
def bad_interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], ToolMessage | Command],
|
||||
) -> ToolMessage | Command:
|
||||
"""Interceptor that tries to execute unregistered tool."""
|
||||
# This should fail validation when execute is called
|
||||
return execute(request)
|
||||
|
||||
node = ToolNode([registered_tool], wrap_tool_call=bad_interceptor)
|
||||
|
||||
# Registered tool should still work
|
||||
result = node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "registered_tool",
|
||||
"args": {"x": 42},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
assert result[0].content == "Result: 42"
|
||||
|
||||
# Unregistered tool should error when interceptor calls execute
|
||||
result = node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "unregistered_tool",
|
||||
"args": {"x": 99},
|
||||
"id": "2",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
# Should get validation error message
|
||||
assert result[0].status == "error"
|
||||
assert "is not a valid tool" in result[0].content
|
||||
assert result[0].tool_call_id == "2"
|
||||
|
||||
|
||||
def test_interceptor_handles_mix_of_registered_and_unregistered() -> None:
|
||||
"""Test interceptor handling mix of registered and unregistered tools."""
|
||||
|
||||
def selective_interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], ToolMessage | Command],
|
||||
) -> ToolMessage | Command:
|
||||
"""Handle unregistered tools, pass through registered ones."""
|
||||
if request.tool_call["name"] == "magic_tool":
|
||||
return ToolMessage(
|
||||
content=f"Magic result: {request.tool_call['args'].get('value', 0) * 2}",
|
||||
tool_call_id=request.tool_call["id"],
|
||||
name="magic_tool",
|
||||
)
|
||||
return execute(request)
|
||||
|
||||
node = ToolNode([registered_tool], wrap_tool_call=selective_interceptor)
|
||||
|
||||
# Test multiple tool calls - mix of registered and unregistered
|
||||
result = node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "registered_tool",
|
||||
"args": {"x": 10},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
},
|
||||
{
|
||||
"name": "magic_tool",
|
||||
"args": {"value": 5},
|
||||
"id": "2",
|
||||
"type": "tool_call",
|
||||
},
|
||||
{
|
||||
"name": "registered_tool",
|
||||
"args": {"x": 20},
|
||||
"id": "3",
|
||||
"type": "tool_call",
|
||||
},
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
# All tools should execute successfully
|
||||
assert len(result) == 3
|
||||
assert result[0].content == "Result: 10"
|
||||
assert result[0].tool_call_id == "1"
|
||||
assert result[1].content == "Magic result: 10"
|
||||
assert result[1].tool_call_id == "2"
|
||||
assert result[2].content == "Result: 20"
|
||||
assert result[2].tool_call_id == "3"
|
||||
|
||||
|
||||
def test_interceptor_command_for_unregistered_tool() -> None:
|
||||
"""Test interceptor returning Command for unregistered tool."""
|
||||
|
||||
def command_interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], ToolMessage | Command],
|
||||
) -> ToolMessage | Command:
|
||||
"""Return Command for unregistered tools."""
|
||||
if request.tool_call["name"] == "routing_tool":
|
||||
return Command(
|
||||
update=[
|
||||
ToolMessage(
|
||||
content="Routing to special handler",
|
||||
tool_call_id=request.tool_call["id"],
|
||||
name="routing_tool",
|
||||
)
|
||||
],
|
||||
goto="special_node",
|
||||
)
|
||||
return execute(request)
|
||||
|
||||
node = ToolNode([registered_tool], wrap_tool_call=command_interceptor)
|
||||
|
||||
result = node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "routing_tool",
|
||||
"args": {},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
# Should get Command back
|
||||
assert len(result) == 1
|
||||
assert isinstance(result[0], Command)
|
||||
assert result[0].goto == "special_node"
|
||||
assert result[0].update is not None
|
||||
assert len(result[0].update) == 1
|
||||
assert result[0].update[0].content == "Routing to special handler"
|
||||
|
||||
|
||||
def test_interceptor_exception_with_unregistered_tool() -> None:
|
||||
"""Test that interceptor exceptions are caught by error handling."""
|
||||
|
||||
def failing_interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], ToolMessage | Command],
|
||||
) -> ToolMessage | Command:
|
||||
"""Interceptor that throws exception for unregistered tools."""
|
||||
if request.tool_call["name"] == "bad_tool":
|
||||
msg = "Interceptor failed"
|
||||
raise ValueError(msg)
|
||||
return execute(request)
|
||||
|
||||
node = ToolNode(
|
||||
[registered_tool], wrap_tool_call=failing_interceptor, handle_tool_errors=True
|
||||
)
|
||||
|
||||
# Interceptor exception should be caught and converted to error message
|
||||
result = node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "bad_tool",
|
||||
"args": {},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "error"
|
||||
assert "Interceptor failed" in result[0].content
|
||||
assert result[0].tool_call_id == "1"
|
||||
|
||||
# Test that exception is raised when handle_tool_errors is False
|
||||
node_no_handling = ToolNode(
|
||||
[registered_tool], wrap_tool_call=failing_interceptor, handle_tool_errors=False
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError, match="Interceptor failed"):
|
||||
node_no_handling.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "bad_tool",
|
||||
"args": {},
|
||||
"id": "2",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
|
||||
async def test_async_interceptor_exception_with_unregistered_tool() -> None:
|
||||
"""Test that async interceptor exceptions are caught by error handling."""
|
||||
|
||||
async def failing_async_interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], Awaitable[ToolMessage | Command]],
|
||||
) -> ToolMessage | Command:
|
||||
"""Async interceptor that throws exception for unregistered tools."""
|
||||
if request.tool_call["name"] == "bad_async_tool":
|
||||
msg = "Async interceptor failed"
|
||||
raise RuntimeError(msg)
|
||||
return await execute(request)
|
||||
|
||||
node = ToolNode(
|
||||
[registered_tool],
|
||||
awrap_tool_call=failing_async_interceptor,
|
||||
handle_tool_errors=True,
|
||||
)
|
||||
|
||||
# Interceptor exception should be caught and converted to error message
|
||||
result = await node.ainvoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "bad_async_tool",
|
||||
"args": {},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "error"
|
||||
assert "Async interceptor failed" in result[0].content
|
||||
assert result[0].tool_call_id == "1"
|
||||
|
||||
# Test that exception is raised when handle_tool_errors is False
|
||||
node_no_handling = ToolNode(
|
||||
[registered_tool],
|
||||
awrap_tool_call=failing_async_interceptor,
|
||||
handle_tool_errors=False,
|
||||
)
|
||||
|
||||
with pytest.raises(RuntimeError, match="Async interceptor failed"):
|
||||
await node_no_handling.ainvoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "bad_async_tool",
|
||||
"args": {},
|
||||
"id": "2",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
|
||||
def test_interceptor_with_dict_input_format() -> None:
|
||||
"""Test that interceptor works with dict input format."""
|
||||
|
||||
def interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], ToolMessage | Command],
|
||||
) -> ToolMessage | Command:
|
||||
"""Intercept unregistered tools with dict input."""
|
||||
if request.tool_call["name"] == "dict_tool":
|
||||
return ToolMessage(
|
||||
content="Handled dict input",
|
||||
tool_call_id=request.tool_call["id"],
|
||||
name="dict_tool",
|
||||
)
|
||||
return execute(request)
|
||||
|
||||
node = ToolNode([registered_tool], wrap_tool_call=interceptor)
|
||||
|
||||
# Test with dict input format
|
||||
result = node.invoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "dict_tool",
|
||||
"args": {"value": 5},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
# Should return dict format output
|
||||
assert isinstance(result, dict)
|
||||
assert "messages" in result
|
||||
assert len(result["messages"]) == 1
|
||||
assert result["messages"][0].content == "Handled dict input"
|
||||
assert result["messages"][0].tool_call_id == "1"
|
||||
|
||||
|
||||
def test_interceptor_verifies_tool_is_none_for_unregistered() -> None:
|
||||
"""Test that request.tool is None for unregistered tools."""
|
||||
|
||||
captured_requests: list[ToolCallRequest] = []
|
||||
|
||||
def capturing_interceptor(
|
||||
request: ToolCallRequest,
|
||||
execute: Callable[[ToolCallRequest], ToolMessage | Command],
|
||||
) -> ToolMessage | Command:
|
||||
"""Capture request to verify tool field."""
|
||||
captured_requests.append(request)
|
||||
if request.tool is None:
|
||||
# Tool is unregistered
|
||||
return ToolMessage(
|
||||
content=f"Unregistered: {request.tool_call['name']}",
|
||||
tool_call_id=request.tool_call["id"],
|
||||
name=request.tool_call["name"],
|
||||
)
|
||||
# Tool is registered
|
||||
return execute(request)
|
||||
|
||||
node = ToolNode([registered_tool], wrap_tool_call=capturing_interceptor)
|
||||
|
||||
# Test unregistered tool
|
||||
node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "unknown_tool",
|
||||
"args": {},
|
||||
"id": "1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
assert len(captured_requests) == 1
|
||||
assert captured_requests[0].tool is None
|
||||
assert captured_requests[0].tool_call["name"] == "unknown_tool"
|
||||
|
||||
# Clear and test registered tool
|
||||
captured_requests.clear()
|
||||
node.invoke(
|
||||
[
|
||||
AIMessage(
|
||||
"",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "registered_tool",
|
||||
"args": {"x": 10},
|
||||
"id": "2",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
],
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
assert len(captured_requests) == 1
|
||||
assert captured_requests[0].tool is not None
|
||||
assert captured_requests[0].tool.name == "registered_tool"
|
||||
@@ -0,0 +1,470 @@
|
||||
"""Unit tests for ValidationError filtering in ToolNode.
|
||||
|
||||
This module tests that validation errors are filtered to only include arguments
|
||||
that the LLM controls. Injected arguments (InjectedState, InjectedStore,
|
||||
ToolRuntime) are automatically provided by the system and should not appear in
|
||||
validation error messages. This ensures the LLM receives focused, actionable
|
||||
feedback about the parameters it can actually control, improving error correction
|
||||
and reducing confusion from irrelevant system implementation details.
|
||||
"""
|
||||
|
||||
from typing import Annotated
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
from langchain_core.messages import AIMessage
|
||||
from langchain_core.runnables.config import RunnableConfig
|
||||
from langchain_core.tools import tool as dec_tool
|
||||
from langgraph.store.base import BaseStore
|
||||
from langgraph.store.memory import InMemoryStore
|
||||
|
||||
from langgraph.prebuilt import InjectedState, InjectedStore, ToolNode, ToolRuntime
|
||||
from langgraph.prebuilt.tool_node import ToolInvocationError
|
||||
|
||||
pytestmark = pytest.mark.anyio
|
||||
|
||||
|
||||
def _create_mock_runtime(store: BaseStore | None = None) -> Mock:
|
||||
"""Create a mock Runtime object for testing ToolNode outside of graph context."""
|
||||
mock_runtime = Mock()
|
||||
mock_runtime.store = store
|
||||
mock_runtime.context = None
|
||||
mock_runtime.stream_writer = lambda *args, **kwargs: None
|
||||
return mock_runtime
|
||||
|
||||
|
||||
def _create_config_with_runtime(store: BaseStore | None = None) -> RunnableConfig:
|
||||
"""Create a RunnableConfig with mock Runtime for testing ToolNode."""
|
||||
return {"configurable": {"__pregel_runtime": _create_mock_runtime(store)}}
|
||||
|
||||
|
||||
async def test_filter_injected_state_validation_errors() -> None:
|
||||
"""Test that validation errors for InjectedState arguments are filtered out.
|
||||
|
||||
InjectedState parameters are not controlled by the LLM, so any validation
|
||||
errors related to them should not appear in error messages. This ensures
|
||||
the LLM receives only actionable feedback about its own tool call arguments.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(
|
||||
value: int,
|
||||
state: Annotated[dict, InjectedState],
|
||||
) -> str:
|
||||
"""Tool that uses injected state.
|
||||
|
||||
Args:
|
||||
value: An integer value.
|
||||
state: The graph state (injected).
|
||||
"""
|
||||
return f"value={value}, messages={len(state.get('messages', []))}"
|
||||
|
||||
tool_node = ToolNode([my_tool])
|
||||
|
||||
# Call with invalid 'value' argument (should be int, not str)
|
||||
result = await tool_node.ainvoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {"value": "not_an_int"}, # Invalid type
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
# Should get a ToolMessage with error
|
||||
assert len(result["messages"]) == 1
|
||||
tool_message = result["messages"][0]
|
||||
assert tool_message.status == "error"
|
||||
assert tool_message.tool_call_id == "call_1"
|
||||
|
||||
# Error should mention 'value' but NOT 'state' (which is injected)
|
||||
assert "value" in tool_message.content
|
||||
assert "state" not in tool_message.content.lower()
|
||||
|
||||
|
||||
async def test_filter_injected_store_validation_errors() -> None:
|
||||
"""Test that validation errors for InjectedStore arguments are filtered out.
|
||||
|
||||
InjectedStore parameters are not controlled by the LLM, so any validation
|
||||
errors related to them should not appear in error messages. This keeps
|
||||
error feedback focused on LLM-controllable parameters.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(
|
||||
key: str,
|
||||
store: Annotated[BaseStore, InjectedStore()],
|
||||
) -> str:
|
||||
"""Tool that uses injected store.
|
||||
|
||||
Args:
|
||||
key: A key to look up.
|
||||
store: The persistent store (injected).
|
||||
"""
|
||||
return f"key={key}"
|
||||
|
||||
tool_node = ToolNode([my_tool])
|
||||
|
||||
# Call with invalid 'key' argument (missing required argument)
|
||||
result = await tool_node.ainvoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {}, # Missing 'key'
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(store=InMemoryStore()),
|
||||
)
|
||||
|
||||
# Should get a ToolMessage with error
|
||||
assert len(result["messages"]) == 1
|
||||
tool_message = result["messages"][0]
|
||||
assert tool_message.status == "error"
|
||||
|
||||
# Error should mention 'key' is required
|
||||
assert "key" in tool_message.content.lower()
|
||||
# The error should be about 'key' field specifically (not about store field)
|
||||
# Note: 'store' might appear in input_value representation, but the validation
|
||||
# error itself should only be for 'key'
|
||||
assert (
|
||||
"field required" in tool_message.content.lower()
|
||||
or "missing" in tool_message.content.lower()
|
||||
)
|
||||
|
||||
|
||||
async def test_filter_tool_runtime_validation_errors() -> None:
|
||||
"""Test that validation errors for ToolRuntime arguments are filtered out.
|
||||
|
||||
ToolRuntime parameters are not controlled by the LLM, so any validation
|
||||
errors related to them should not appear in error messages. This ensures
|
||||
the LLM only sees errors for parameters it can fix.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(
|
||||
query: str,
|
||||
runtime: ToolRuntime,
|
||||
) -> str:
|
||||
"""Tool that uses ToolRuntime.
|
||||
|
||||
Args:
|
||||
query: A query string.
|
||||
runtime: The tool runtime context (injected).
|
||||
"""
|
||||
return f"query={query}"
|
||||
|
||||
tool_node = ToolNode([my_tool])
|
||||
|
||||
# Call with invalid 'query' argument (wrong type)
|
||||
result = await tool_node.ainvoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {"query": 123}, # Should be str, not int
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
# Should get a ToolMessage with error
|
||||
assert len(result["messages"]) == 1
|
||||
tool_message = result["messages"][0]
|
||||
assert tool_message.status == "error"
|
||||
|
||||
# Error should mention 'query' but NOT 'runtime' (which is injected)
|
||||
assert "query" in tool_message.content.lower()
|
||||
assert "runtime" not in tool_message.content.lower()
|
||||
|
||||
|
||||
async def test_filter_multiple_injected_args() -> None:
|
||||
"""Test filtering when a tool has multiple injected arguments.
|
||||
|
||||
When a tool uses multiple injected parameters (state, store, runtime), none of
|
||||
them should appear in validation error messages since they're all system-provided
|
||||
and not controlled by the LLM. Only LLM-controllable parameter errors should appear.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(
|
||||
value: int,
|
||||
state: Annotated[dict, InjectedState],
|
||||
store: Annotated[BaseStore, InjectedStore()],
|
||||
runtime: ToolRuntime,
|
||||
) -> str:
|
||||
"""Tool with multiple injected arguments.
|
||||
|
||||
Args:
|
||||
value: An integer value.
|
||||
state: The graph state (injected).
|
||||
store: The persistent store (injected).
|
||||
runtime: The tool runtime context (injected).
|
||||
"""
|
||||
return f"value={value}"
|
||||
|
||||
tool_node = ToolNode([my_tool])
|
||||
|
||||
# Call with invalid 'value' - injected args should be filtered from error
|
||||
result = await tool_node.ainvoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {"value": "not_an_int"},
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(store=InMemoryStore()),
|
||||
)
|
||||
|
||||
tool_message = result["messages"][0]
|
||||
assert tool_message.status == "error"
|
||||
|
||||
# Only 'value' error should be reported
|
||||
assert "value" in tool_message.content
|
||||
# None of the injected args should appear in error
|
||||
assert "state" not in tool_message.content.lower()
|
||||
assert "store" not in tool_message.content.lower()
|
||||
assert "runtime" not in tool_message.content.lower()
|
||||
|
||||
|
||||
async def test_no_filtering_when_all_errors_are_model_args() -> None:
|
||||
"""Test that validation errors for LLM-controlled arguments are preserved.
|
||||
|
||||
When validation fails for arguments the LLM controls, those errors should
|
||||
be fully reported to help the LLM correct its tool calls. This ensures
|
||||
the LLM receives complete feedback about all issues it can fix.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(
|
||||
value1: int,
|
||||
value2: str,
|
||||
state: Annotated[dict, InjectedState],
|
||||
) -> str:
|
||||
"""Tool with both regular and injected arguments.
|
||||
|
||||
Args:
|
||||
value1: First value.
|
||||
value2: Second value.
|
||||
state: The graph state (injected).
|
||||
"""
|
||||
return f"value1={value1}, value2={value2}"
|
||||
|
||||
tool_node = ToolNode([my_tool])
|
||||
|
||||
# Call with invalid arguments for BOTH non-injected parameters
|
||||
result = await tool_node.ainvoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {
|
||||
"value1": "not_an_int", # Invalid
|
||||
"value2": 456, # Invalid (should be str)
|
||||
},
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
tool_message = result["messages"][0]
|
||||
assert tool_message.status == "error"
|
||||
|
||||
# Both errors should be present
|
||||
assert "value1" in tool_message.content
|
||||
assert "value2" in tool_message.content
|
||||
# Injected state should not appear
|
||||
assert "state" not in tool_message.content.lower()
|
||||
|
||||
|
||||
async def test_validation_error_with_no_injected_args() -> None:
|
||||
"""Test that tools without injected arguments show all validation errors.
|
||||
|
||||
For tools that only have LLM-controlled parameters, all validation errors
|
||||
should be reported since everything is under the LLM's control and can be
|
||||
corrected by the LLM in subsequent tool calls.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(value1: int, value2: str) -> str:
|
||||
"""Regular tool without injected arguments.
|
||||
|
||||
Args:
|
||||
value1: First value.
|
||||
value2: Second value.
|
||||
"""
|
||||
return f"{value1} {value2}"
|
||||
|
||||
tool_node = ToolNode([my_tool])
|
||||
|
||||
result = await tool_node.ainvoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {"value1": "invalid", "value2": 123},
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
tool_message = result["messages"][0]
|
||||
assert tool_message.status == "error"
|
||||
|
||||
# Both errors should be present since there are no injected args to filter
|
||||
assert "value1" in tool_message.content
|
||||
assert "value2" in tool_message.content
|
||||
|
||||
|
||||
async def test_tool_invocation_error_without_handle_errors() -> None:
|
||||
"""Test that ToolInvocationError contains only LLM-controlled parameter errors.
|
||||
|
||||
When handle_tool_errors is False, the raised ToolInvocationError should still
|
||||
filter out system-injected arguments from the error details, ensuring that
|
||||
error messages focus on what the LLM can control.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(
|
||||
value: int,
|
||||
state: Annotated[dict, InjectedState],
|
||||
) -> str:
|
||||
"""Tool with injected state.
|
||||
|
||||
Args:
|
||||
value: An integer value.
|
||||
state: The graph state (injected).
|
||||
"""
|
||||
return f"value={value}"
|
||||
|
||||
tool_node = ToolNode([my_tool], handle_tool_errors=False)
|
||||
|
||||
# Should raise ToolInvocationError with filtered errors
|
||||
with pytest.raises(ToolInvocationError) as exc_info:
|
||||
await tool_node.ainvoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {"value": "not_an_int"},
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
error = exc_info.value
|
||||
assert error.tool_name == "my_tool"
|
||||
assert error.filtered_errors is not None
|
||||
assert len(error.filtered_errors) > 0
|
||||
|
||||
# Filtered errors should only contain 'value' error, not 'state'
|
||||
error_locs = [err["loc"] for err in error.filtered_errors]
|
||||
assert any("value" in str(loc) for loc in error_locs)
|
||||
assert not any("state" in str(loc) for loc in error_locs)
|
||||
|
||||
|
||||
async def test_sync_tool_validation_error_filtering() -> None:
|
||||
"""Test that error filtering works for sync tools.
|
||||
|
||||
Error filtering should work identically for both sync and async tool execution,
|
||||
excluding injected arguments from validation error messages.
|
||||
"""
|
||||
|
||||
@dec_tool
|
||||
def my_tool(
|
||||
value: int,
|
||||
state: Annotated[dict, InjectedState],
|
||||
) -> str:
|
||||
"""Sync tool with injected state.
|
||||
|
||||
Args:
|
||||
value: An integer value.
|
||||
state: The graph state (injected).
|
||||
"""
|
||||
return f"value={value}"
|
||||
|
||||
tool_node = ToolNode([my_tool])
|
||||
|
||||
# Test sync invocation
|
||||
result = tool_node.invoke(
|
||||
{
|
||||
"messages": [
|
||||
AIMessage(
|
||||
"hi?",
|
||||
tool_calls=[
|
||||
{
|
||||
"name": "my_tool",
|
||||
"args": {"value": "not_an_int"},
|
||||
"id": "call_1",
|
||||
"type": "tool_call",
|
||||
}
|
||||
],
|
||||
)
|
||||
]
|
||||
},
|
||||
config=_create_config_with_runtime(),
|
||||
)
|
||||
|
||||
tool_message = result["messages"][0]
|
||||
assert tool_message.status == "error"
|
||||
assert "value" in tool_message.content
|
||||
assert "state" not in tool_message.content.lower()
|
||||
@@ -1,3 +1,4 @@
|
||||
import sys
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
@@ -36,7 +37,13 @@ def my_tool(some_val: int, some_other_val: str) -> str:
|
||||
[
|
||||
my_function,
|
||||
MyModel,
|
||||
MyModelV1,
|
||||
pytest.param(
|
||||
MyModelV1,
|
||||
marks=pytest.mark.skipif(
|
||||
sys.version_info >= (3, 14),
|
||||
reason="Pydantic v1 not supported in Python 3.14+",
|
||||
),
|
||||
),
|
||||
my_tool,
|
||||
],
|
||||
)
|
||||
|
||||
Generated
+347
-130
@@ -228,7 +228,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "langchain-core"
|
||||
version = "0.3.76"
|
||||
version = "1.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "jsonpatch" },
|
||||
@@ -239,14 +239,14 @@ dependencies = [
|
||||
{ name = "tenacity" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4f/4d/5e2ea7754ee0a1f524c412801c6ba9ad49318ecb58b0d524903c3d9efe0a/langchain_core-0.3.76.tar.gz", hash = "sha256:71136a122dd1abae2c289c5809d035cf12b5f2bb682d8a4c1078cd94feae7419", size = 573568, upload-time = "2025-09-10T14:49:39.863Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ad/d0/9db6d375ecf8bd498fcc87016e43c3d930ddbfbacf9a1e99018ada4e824f/langchain_core-1.0.0.tar.gz", hash = "sha256:8e81c94a22fa3a362a0f101bbd1271bf3725e50cf1e31c84e8f4a1c731279785", size = 764484, upload-time = "2025-10-17T13:48:24.408Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/77/b5/501c0ffcb09c734457ceaa86bc7b1dd37b6a261147bd653add03b838aacb/langchain_core-0.3.76-py3-none-any.whl", hash = "sha256:46e0eb48c7ac532432d51f8ca1ece1804c82afe9ae3dcf027b867edadf82b3ec", size = 447508, upload-time = "2025-09-10T14:49:38.179Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/6a/8dd566cb7379d6e3a921f94713babba2f71cbed65c73c784c649c1fd7d4e/langchain_core-1.0.0-py3-none-any.whl", hash = "sha256:a94561bf75dd097c7d6e3864950f28dadc963f0bd810114de4095f41f634059b", size = 467157, upload-time = "2025-10-17T13:48:23.138Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph"
|
||||
version = "1.0.0rc1"
|
||||
version = "1.0.3"
|
||||
source = { editable = "../langgraph" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
@@ -271,11 +271,12 @@ requires-dist = [
|
||||
dev = [
|
||||
{ name = "httpx" },
|
||||
{ name = "jupyter" },
|
||||
{ name = "langchain-core", specifier = "==1.0.0a1" },
|
||||
{ name = "langchain-core", specifier = ">=1.0.0" },
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
{ name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" },
|
||||
{ name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" },
|
||||
{ name = "langgraph-cli", extras = ["inmem"], editable = "../cli" },
|
||||
{ name = "langgraph-cli", marker = "python_full_version < '3.14'", editable = "../cli" },
|
||||
{ name = "langgraph-cli", extras = ["inmem"], marker = "python_full_version < '3.14'", editable = "../cli" },
|
||||
{ name = "langgraph-prebuilt", editable = "." },
|
||||
{ name = "langgraph-sdk", editable = "../sdk-py" },
|
||||
{ name = "mypy" },
|
||||
@@ -296,10 +297,40 @@ dev = [
|
||||
{ name = "types-requests" },
|
||||
{ name = "uvloop", specifier = "==0.21.0b1" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
{ name = "types-requests" },
|
||||
]
|
||||
test = [
|
||||
{ name = "httpx" },
|
||||
{ name = "langchain-core", specifier = ">=1.0.0" },
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
{ name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" },
|
||||
{ name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" },
|
||||
{ name = "langgraph-cli", marker = "python_full_version < '3.14'", editable = "../cli" },
|
||||
{ name = "langgraph-cli", extras = ["inmem"], marker = "python_full_version < '3.14'", editable = "../cli" },
|
||||
{ name = "langgraph-prebuilt", editable = "." },
|
||||
{ name = "langgraph-sdk", editable = "../sdk-py" },
|
||||
{ name = "psycopg", extras = ["binary"] },
|
||||
{ name = "py-spy" },
|
||||
{ name = "pycryptodome" },
|
||||
{ name = "pyperf" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-cov" },
|
||||
{ name = "pytest-dotenv" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-repeat" },
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "pytest-xdist", extras = ["psutil"] },
|
||||
{ name = "redis" },
|
||||
{ name = "syrupy" },
|
||||
{ name = "uvloop", specifier = "==0.21.0b1" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint"
|
||||
version = "2.1.2"
|
||||
version = "3.0.1"
|
||||
source = { editable = "../checkpoint" }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
@@ -309,7 +340,7 @@ dependencies = [
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "langchain-core", specifier = ">=0.2.38" },
|
||||
{ name = "ormsgpack", specifier = ">=1.10.0" },
|
||||
{ name = "ormsgpack", specifier = ">=1.12.0" },
|
||||
]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
@@ -327,10 +358,26 @@ dev = [
|
||||
{ name = "redis" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "dataclasses-json" },
|
||||
{ name = "numpy" },
|
||||
{ name = "pandas" },
|
||||
{ name = "pandas-stubs", specifier = ">=2.2.2.240807" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "redis" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint-postgres"
|
||||
version = "2.0.25"
|
||||
version = "3.0.1"
|
||||
source = { editable = "../checkpoint-postgres" }
|
||||
dependencies = [
|
||||
{ name = "langgraph-checkpoint" },
|
||||
@@ -360,10 +407,24 @@ dev = [
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "anyio" },
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
{ name = "psycopg", extras = ["binary"] },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-checkpoint-sqlite"
|
||||
version = "2.0.11"
|
||||
version = "3.0.0"
|
||||
source = { editable = "../checkpoint-sqlite" }
|
||||
dependencies = [
|
||||
{ name = "aiosqlite" },
|
||||
@@ -390,10 +451,23 @@ dev = [
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-retry", specifier = ">=1.7.0" },
|
||||
{ name = "pytest-watcher" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-prebuilt"
|
||||
version = "0.7.0rc1"
|
||||
version = "1.0.4"
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "langchain-core" },
|
||||
@@ -409,6 +483,7 @@ dev = [
|
||||
{ name = "langgraph-checkpoint-postgres" },
|
||||
{ name = "langgraph-checkpoint-sqlite" },
|
||||
{ name = "mypy" },
|
||||
{ name = "psycopg-binary" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
@@ -416,10 +491,28 @@ dev = [
|
||||
{ name = "ruff" },
|
||||
{ name = "syrupy" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "langchain-core" },
|
||||
{ name = "langgraph" },
|
||||
{ name = "langgraph-checkpoint" },
|
||||
{ name = "langgraph-checkpoint-postgres" },
|
||||
{ name = "langgraph-checkpoint-sqlite" },
|
||||
{ name = "psycopg-binary" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "syrupy" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "langchain-core", specifier = ">=0.3.67" },
|
||||
{ name = "langchain-core", specifier = ">=1.0.0" },
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
]
|
||||
|
||||
@@ -432,6 +525,7 @@ dev = [
|
||||
{ name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" },
|
||||
{ name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" },
|
||||
{ name = "mypy" },
|
||||
{ name = "psycopg-binary" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
@@ -439,6 +533,24 @@ dev = [
|
||||
{ name = "ruff" },
|
||||
{ name = "syrupy" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "langchain-core" },
|
||||
{ name = "langgraph", editable = "../langgraph" },
|
||||
{ name = "langgraph-checkpoint", editable = "../checkpoint" },
|
||||
{ name = "langgraph-checkpoint-postgres", editable = "../checkpoint-postgres" },
|
||||
{ name = "langgraph-checkpoint-sqlite", editable = "../checkpoint-sqlite" },
|
||||
{ name = "psycopg-binary" },
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watcher" },
|
||||
{ name = "syrupy" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langgraph-sdk"
|
||||
@@ -464,6 +576,17 @@ dev = [
|
||||
{ name = "pytest-watch" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watch" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
@@ -616,42 +739,57 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ormsgpack"
|
||||
version = "1.10.0"
|
||||
version = "1.12.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/92/36/44eed5ef8ce93cded76a576780bab16425ce7876f10d3e2e6265e46c21ea/ormsgpack-1.10.0.tar.gz", hash = "sha256:7f7a27efd67ef22d7182ec3b7fa7e9d147c3ad9be2a24656b23c989077e08b16", size = 58629, upload-time = "2025-05-24T19:07:53.944Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/67/d5ef41c3b4a94400be801984ef7c7fc9623e1a82b643e74eeec367e7462b/ormsgpack-1.12.0.tar.gz", hash = "sha256:94be818fdbb0285945839b88763b269987787cb2f7ef280cad5d6ec815b7e608", size = 49959, upload-time = "2025-11-04T18:30:10.083Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/74/c2dd5daf069e3798d09d5746000f9b210de04df83834e5cb47f0ace51892/ormsgpack-1.10.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8a52c7ce7659459f3dc8dec9fd6a6c76f855a0a7e2b61f26090982ac10b95216", size = 376280, upload-time = "2025-05-24T19:06:51.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/78/7b/30ff4bffb709e8a242005a8c4d65714fd96308ad640d31cff1b85c0d8cc4/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:060f67fe927582f4f63a1260726d019204b72f460cf20930e6c925a1d129f373", size = 204335, upload-time = "2025-05-24T19:06:53.442Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/3f/c95b7d142819f801a0acdbd04280e8132e43b6e5a8920173e8eb92ea0e6a/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7058ef6092f995561bf9f71d6c9a4da867b6cc69d2e94cb80184f579a3ceed5", size = 215373, upload-time = "2025-05-24T19:06:55.153Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/1a/e30f4bcf386db2015d1686d1da6110c95110294d8ea04f86091dd5eb3361/ormsgpack-1.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f6f3509c1b0e51b15552d314b1d409321718122e90653122ce4b997f01453a", size = 216469, upload-time = "2025-05-24T19:06:56.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/fc/7e44aeade22b91883586f45b7278c118fd210834c069774891447f444fc9/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:51c1edafd5c72b863b1f875ec31c529f09c872a5ff6fe473b9dfaf188ccc3227", size = 384590, upload-time = "2025-05-24T19:06:58.286Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/78/f92c24e8446697caa83c122f10b6cf5e155eddf81ce63905c8223a260482/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c780b44107a547a9e9327270f802fa4d6b0f6667c9c03c3338c0ce812259a0f7", size = 478891, upload-time = "2025-05-24T19:07:00.126Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/75/87449690253c64bea2b663c7c8f2dbc9ad39d73d0b38db74bdb0f3947b16/ormsgpack-1.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:137aab0d5cdb6df702da950a80405eb2b7038509585e32b4e16289604ac7cb84", size = 390121, upload-time = "2025-05-24T19:07:01.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/cc/c83257faf3a5169ec29dd87121317a25711da9412ee8c1e82f2e1a00c0be/ormsgpack-1.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:3e666cb63030538fa5cd74b1e40cb55b6fdb6e2981f024997a288bf138ebad07", size = 121196, upload-time = "2025-05-24T19:07:03.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/27/7da748bc0d7d567950a378dee5a32477ed5d15462ab186918b5f25cac1ad/ormsgpack-1.10.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4bb7df307e17b36cbf7959cd642c47a7f2046ae19408c564e437f0ec323a7775", size = 376275, upload-time = "2025-05-24T19:07:05.128Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/65/c082cc8c74a914dbd05af0341c761c73c3d9960b7432bbf9b8e1e20811af/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8817ae439c671779e1127ee62f0ac67afdeaeeacb5f0db45703168aa74a2e4af", size = 204335, upload-time = "2025-05-24T19:07:06.423Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/62/17ef7e5d9766c79355b9c594cc9328c204f1677bc35da0595cc4e46449f0/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f345f81e852035d80232e64374d3a104139d60f8f43c6c5eade35c4bac5590e", size = 215372, upload-time = "2025-05-24T19:07:08.149Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/92/7c91e8115fc37e88d1a35e13200fda3054ff5d2e5adf017345e58cea4834/ormsgpack-1.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21de648a1c7ef692bdd287fb08f047bd5371d7462504c0a7ae1553c39fee35e3", size = 216470, upload-time = "2025-05-24T19:07:09.903Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/86/ce053c52e2517b90e390792d83e926a7a523c1bce5cc63d0a7cd05ce6cf6/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3a7d844ae9cbf2112c16086dd931b2acefce14cefd163c57db161170c2bfa22b", size = 384591, upload-time = "2025-05-24T19:07:11.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/e8/2ad59f2ab222c6029e500bc966bfd2fe5cb099f8ab6b7ebeb50ddb1a6fe5/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:e4d80585403d86d7f800cf3d0aafac1189b403941e84e90dd5102bb2b92bf9d5", size = 478892, upload-time = "2025-05-24T19:07:13.147Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/73/f55e4b47b7b18fd8e7789680051bf830f1e39c03f1d9ed993cd0c3e97215/ormsgpack-1.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da1de515a87e339e78a3ccf60e39f5fb740edac3e9e82d3c3d209e217a13ac08", size = 390122, upload-time = "2025-05-24T19:07:14.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/87/073251cdb93d4c6241748568b3ad1b2a76281fb2002eed16a3a4043d61cf/ormsgpack-1.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:57c4601812684024132cbb32c17a7d4bb46ffc7daf2fddf5b697391c2c4f142a", size = 121197, upload-time = "2025-05-24T19:07:15.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/95/f3ab1a7638f6aa9362e87916bb96087fbbc5909db57e19f12ad127560e1e/ormsgpack-1.10.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:4e159d50cd4064d7540e2bc6a0ab66eab70b0cc40c618b485324ee17037527c0", size = 376806, upload-time = "2025-05-24T19:07:17.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/2b/42f559f13c0b0f647b09d749682851d47c1a7e48308c43612ae6833499c8/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb47c85f3a866e29279d801115b554af0fefc409e2ed8aa90aabfa77efe5cc6", size = 204433, upload-time = "2025-05-24T19:07:18.569Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/42/1ca0cb4d8c80340a89a4af9e6d8951fb8ba0d076a899d2084eadf536f677/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c28249574934534c9bd5dce5485c52f21bcea0ee44d13ece3def6e3d2c3798b5", size = 215547, upload-time = "2025-05-24T19:07:20.245Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/38/184a570d7c44c0260bc576d1daaac35b2bfd465a50a08189518505748b9a/ormsgpack-1.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1957dcadbb16e6a981cd3f9caef9faf4c2df1125e2a1b702ee8236a55837ce07", size = 216746, upload-time = "2025-05-24T19:07:21.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/69/2f/1aaffd08f6b7fdc2a57336a80bdfb8df24e6a65ada5aa769afecfcbc6cc6/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3b29412558c740bf6bac156727aa85ac67f9952cd6f071318f29ee72e1a76044", size = 384783, upload-time = "2025-05-24T19:07:23.674Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/63/3e53d6f43bb35e00c98f2b8ab2006d5138089ad254bc405614fbf0213502/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6933f350c2041ec189fe739f0ba7d6117c8772f5bc81f45b97697a84d03020dd", size = 479076, upload-time = "2025-05-24T19:07:25.047Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/19/fa1121b03b61402bb4d04e35d164e2320ef73dfb001b57748110319dd014/ormsgpack-1.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a86de06d368fcc2e58b79dece527dc8ca831e0e8b9cec5d6e633d2777ec93d0", size = 390447, upload-time = "2025-05-24T19:07:26.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/0d/73143ecb94ac4a5dcba223402139240a75dee0cc6ba8a543788a5646407a/ormsgpack-1.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:35fa9f81e5b9a0dab42e09a73f7339ecffdb978d6dbf9deb2ecf1e9fc7808722", size = 121401, upload-time = "2025-05-24T19:07:28.308Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/f8/ec5f4e03268d0097545efaab2893aa63f171cf2959cb0ea678a5690e16a1/ormsgpack-1.10.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d816d45175a878993b7372bd5408e0f3ec5a40f48e2d5b9d8f1cc5d31b61f1f", size = 376806, upload-time = "2025-05-24T19:07:29.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c1/19/b3c53284aad1e90d4d7ed8c881a373d218e16675b8b38e3569d5b40cc9b8/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90345ccb058de0f35262893751c603b6376b05f02be2b6f6b7e05d9dd6d5643", size = 204433, upload-time = "2025-05-24T19:07:30.977Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/0b/845c258f59df974a20a536c06cace593698491defdd3d026a8a5f9b6e745/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:144b5e88f1999433e54db9d637bae6fe21e935888be4e3ac3daecd8260bd454e", size = 215549, upload-time = "2025-05-24T19:07:32.345Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/56/57fce8fb34ca6c9543c026ebebf08344c64dbb7b6643d6ddd5355d37e724/ormsgpack-1.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2190b352509d012915921cca76267db136cd026ddee42f1b0d9624613cc7058c", size = 216747, upload-time = "2025-05-24T19:07:34.075Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/3f/655b5f6a2475c8d209f5348cfbaaf73ce26237b92d79ef2ad439407dd0fa/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:86fd9c1737eaba43d3bb2730add9c9e8b5fbed85282433705dd1b1e88ea7e6fb", size = 384785, upload-time = "2025-05-24T19:07:35.83Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4b/94/687a0ad8afd17e4bce1892145d6a1111e58987ddb176810d02a1f3f18686/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:33afe143a7b61ad21bb60109a86bb4e87fec70ef35db76b89c65b17e32da7935", size = 479076, upload-time = "2025-05-24T19:07:37.533Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/34/68925232e81e0e062a2f0ac678f62aa3b6f7009d6a759e19324dbbaebae7/ormsgpack-1.10.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f23d45080846a7b90feabec0d330a9cc1863dc956728412e4f7986c80ab3a668", size = 390446, upload-time = "2025-05-24T19:07:39.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/ad/f4e1a36a6d1714afb7ffb74b3ababdcb96529cf4e7a216f9f7c8eda837b6/ormsgpack-1.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:534d18acb805c75e5fba09598bf40abe1851c853247e61dda0c01f772234da69", size = 121399, upload-time = "2025-05-24T19:07:40.854Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/0c/8f45fcd22c95190b05d4fba71375d8f783a9e3b0b6aaf476812b693e3868/ormsgpack-1.12.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e08904c232358b94a682ccfbb680bc47d3fd5c424bb7dccb65974dd20c95e8e1", size = 369156, upload-time = "2025-11-04T18:29:17.629Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/f8/c7adc093d4ceb05e38786906815f868210f808326c27f8124b4d9466a26b/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9ed7a4b0037d69c8ba7e670e03ee65ae8d5c5114a409e73c5770d7fb5e4b895", size = 195743, upload-time = "2025-11-04T18:29:18.964Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/b8/bf002648fa6c150ed6157837b00303edafb35f65c352429463f83214de18/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:db2928525b684f3f2af0367aef7ae8d20cde37fc5349c700017129d493a755aa", size = 206472, upload-time = "2025-11-04T18:29:19.951Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/d6/1f445947c95a931bb189b7864a3f9dcbeebe7dcbc1b3c7387427b3779228/ormsgpack-1.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45f911d9c5b23d11e49ff03fc8f9566745a2b1a7d9033733a1c0a2fa9301cd60", size = 207959, upload-time = "2025-11-04T18:29:21.282Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/9c/dd8ccd7553a5c1d0b4b69a0541611983a2f9bc2e8c5708a4bfffc0100468/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:98c54ae6fd682b2aceb264505af9b2255f3df9d84e6e4369bc44d2110f1f311d", size = 377659, upload-time = "2025-11-04T18:29:22.561Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/08/3282d8f6330e742d4cdbcfbe2c100b403ae5526ae82a1c1b6a11b7967e37/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:857ab987c3502de08258cc4baf0e87267cb2c80931601084e13df3c355b1ab9d", size = 471391, upload-time = "2025-11-04T18:29:23.663Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/d4/94a2fbfd4837754bda7a099b6a23b9d40aba9e76e1af8b8fb8133612eb54/ormsgpack-1.12.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:27579d45dc502ee736238e1024559cb0a01aa72a3b68827448b8edf6a2dcdc9c", size = 381501, upload-time = "2025-11-04T18:29:24.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/c6/1a9fa122cb5deb10b067bbaa43165b12291a914cc0ce364988ff17bbf405/ormsgpack-1.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:c78379d054760875540cf2e81f28da1bb78d09fda3eabdbeb6c53b3e297158cb", size = 112715, upload-time = "2025-11-04T18:29:26.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/ba/3cae83cf36420c1c8dd294f16c852c03313aafe2439a165c4c6ac611b1d0/ormsgpack-1.12.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c40d86d77391b18dd34de5295e3de2b8ad818bcab9c9def4121c8ec5c9714ae4", size = 369159, upload-time = "2025-11-04T18:29:27.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/d4/5e176309e01a8b9098d80201aac1eb7db9336c3b5b4fa6254a2bbb0d0fa0/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:777b7fab364dc0f200bb382a98a385c8222ffa6a2333d627d763797326202c86", size = 195744, upload-time = "2025-11-04T18:29:28.069Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/83/6d80c8c5571639c000a39f38f77752dfaf9d9e552d775331e8d280f66a4e/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b5089ad9dd5b3d3013b245a55e4abaea2f8ad70f4a78e1b002127b02340004", size = 206474, upload-time = "2025-11-04T18:29:29.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/e6/940311e48dc0cfc3e212bd7007a21ed0825158638057687d804f2c5c2cca/ormsgpack-1.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deaf0c87cace7bc08fbf68c5cc66605b593df6427e9f4de235b2da358787e008", size = 207959, upload-time = "2025-11-04T18:29:30.315Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/e3/fbe94b0a311815343b86a95a0627e4901b11ff6fd522679ca29a2a88c99b/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f62d476fe28bc5675d9aff30341bfa9f41d7de332c5b63fbbe9aaf6bb7ec74d4", size = 377666, upload-time = "2025-11-04T18:29:31.38Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/3b/229cfa28076798ffb619aaa854b842de3f2ed5ea4e6509bf34d14c038c4d/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:ded7810095b887e28434f32f5a345d354e88cf851bab3c5435aeb86a718618d2", size = 471394, upload-time = "2025-11-04T18:29:32.521Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6b/bd/4eae4ab35586e4175c07acb5f98aec83aa9d8987f71ea0443aa900191bdf/ormsgpack-1.12.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f72a1dea0c4ae7c4101dcfbe8133f274a9d769d0b87fe5188db4fab07ffabaee", size = 381506, upload-time = "2025-11-04T18:29:33.533Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/51/f9d56d6d015cbfa1ce9a4358ca30a41744644f0cf606e060d7203efe5af8/ormsgpack-1.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:8f479bfef847255d7d0b12c7a198f6a21490155da2da3062e082ba370893d4a1", size = 112707, upload-time = "2025-11-04T18:29:34.898Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/07/bb189ef7072979f2f96e8716e952172efdce9c54930aa0814bec73aee19b/ormsgpack-1.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:3583ca410e4502144b2594170542e4bbef7b15643fd1208703ae820f11029036", size = 106533, upload-time = "2025-11-04T18:29:36.112Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/f2/c1036b2775fcc0cfa5fd618c53bcd3b862ee07298fb627f03af4c7982f84/ormsgpack-1.12.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e0c1e08b64d99076fee155276097489b82cc56e8d5951c03c721a65a32f44494", size = 369538, upload-time = "2025-11-04T18:29:37.125Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/ca/526c4ae02f3cb34621af91bf8282a10d666757c2e0c6ff391ff5d403d607/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fd43bcb299131690b8e0677af172020b2ada8e625169034b42ac0c13adf84aa", size = 195872, upload-time = "2025-11-04T18:29:38.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/0f/83bb7968e9715f6a85be53d041b1e6324a05428f56b8b980dac866886871/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0149d595341e22ead340bf281b2995c4cc7dc8d522a6b5f575fe17aa407604", size = 206469, upload-time = "2025-11-04T18:29:39.749Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/e3/9e93ca1065f2d4af035804a842b1ff3025bab580c7918239bb225cd1fee2/ormsgpack-1.12.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f19a1b27d169deb553c80fd10b589fc2be1fc14cee779fae79fcaf40db04de2b", size = 208273, upload-time = "2025-11-04T18:29:40.769Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d8/6d6ef901b3a8b8f3ab8836b135a56eb7f66c559003e251d9530bedb12627/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f28896942d655064940dfe06118b7ce1e3468d051483148bf02c99ec157483a", size = 377839, upload-time = "2025-11-04T18:29:42.092Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/72/fcb704bfa4c2c3a37b647d597cc45a13cffc9d50baac635a9ad620731d29/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9396efcfa48b4abbc06e44c5dbc3c4574a8381a80cb4cd01eea15d28b38c554e", size = 471446, upload-time = "2025-11-04T18:29:43.133Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/f8/402e4e3eb997c2ee534c99bec4b5bb359c2a1f9edadf043e254a71e11378/ormsgpack-1.12.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:96586ed537a5fb386a162c4f9f7d8e6f76e07b38a990d50c73f11131e00ff040", size = 381783, upload-time = "2025-11-04T18:29:44.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/8d/5897b700360bc00911b70ae5ef1134ee7abf5baa81a92a4be005917d3dfd/ormsgpack-1.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:e70387112fb3870e4844de090014212cdcf1342f5022047aecca01ec7de05d7a", size = 112943, upload-time = "2025-11-04T18:29:45.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/44/1e73649f79bb96d6cf9e5bcbac68b6216d238bba80af351c4c0cbcf7ee15/ormsgpack-1.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:d71290a23de5d4829610c42665d816c661ecad8979883f3f06b2e3ab9639962e", size = 106688, upload-time = "2025-11-04T18:29:46.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/e8/35f11ce9313111488b26b3035e4cbe55caa27909c0b6c8b5b5cd59f9661e/ormsgpack-1.12.0-cp313-cp313-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:766f2f3b512d85cd375b26a8b1329b99843560b50b93d3880718e634ad4a5de5", size = 369574, upload-time = "2025-11-04T18:29:47.431Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/61/b0/77461587f412d4e598d3687bafe23455ed0f26269f44be20252eddaa624e/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84b285b1f3f185aad7da45641b873b30acfd13084cf829cf668c4c6480a81583", size = 195893, upload-time = "2025-11-04T18:29:48.735Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/67/e197ceb04c3b550589e5407fc9fdae10f4e2e2eba5fdac921a269e02e974/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e23604fc79fe110292cb365f4c8232e64e63a34f470538be320feae3921f271b", size = 206503, upload-time = "2025-11-04T18:29:49.99Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/b1/7fa8ba82a25cef678983c7976f85edeef5014f5c26495f338258e6a3cf1c/ormsgpack-1.12.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc32b156c113a0fae2975051417d8d9a7a5247c34b2d7239410c46b75ce9348a", size = 208257, upload-time = "2025-11-04T18:29:51.007Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/b1/759e999390000d2589e6d0797f7265e6ec28378547075d28d3736248ab63/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:94ac500dd10c20fa8b8a23bc55606250bfe711bf9716828d9f3d44dfd1f25668", size = 377852, upload-time = "2025-11-04T18:29:52.103Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/51/e7/0af737c94272494d9d84a3c29cc42c973ef7fd2342917020906596db863c/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:c5201ff7ec24f721f813a182885a17064cffdbe46b2412685a52e6374a872c8f", size = 471456, upload-time = "2025-11-04T18:29:53.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/ba/c81f0aa4f19fbf457213395945b672e6fde3ce777e3587456e7f0fca2147/ormsgpack-1.12.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a9740bb3839c9368aacae1cbcfc474ee6976458f41cc135372b7255d5206c953", size = 381813, upload-time = "2025-11-04T18:29:54.394Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/15/429c72d64323503fd42cc4ca8398930ded8aa8b3470df8a86b3bbae7a35c/ormsgpack-1.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ed37f29772432048b58174e920a1d4c4cde0404a5d448d3d8bbcc95d86a6918", size = 112949, upload-time = "2025-11-04T18:29:55.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/b9/e72c451a40f8c57bfc229e0b8e536ecea7203c8f0a839676df2ffb605c62/ormsgpack-1.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:b03994bbec5d6d42e03d6604e327863f885bde67aa61e06107ce1fa5bdd3e71d", size = 106689, upload-time = "2025-11-04T18:29:56.262Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/16/13eab1a75da531b359105fdee90dda0b6bd1ca0a09880250cf91d8bdfdea/ormsgpack-1.12.0-cp314-cp314-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0f3981ba3cba80656012090337e548e597799e14b41e3d0b595ab5ab05a23d7f", size = 369620, upload-time = "2025-11-04T18:29:57.255Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/c1/cbcc38b7af4ce58d8893e56d3595c0c8dcd117093bf048f889cf351bdba0/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:901f6f55184d6776dbd5183cbce14caf05bf7f467eef52faf9b094686980bf71", size = 195925, upload-time = "2025-11-04T18:29:58.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/59/4fa4dc0681490e12b75333440a1c0fd9741b0ebff272b1db4a29d35c2021/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e13b15412571422b711b40f45e3fe6d993ea3314b5e97d1a853fe99226c5effc", size = 206594, upload-time = "2025-11-04T18:29:59.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/67/249770896bc32bb91b22c30256961f935d0915cbcf6e289a7fc961d9b14c/ormsgpack-1.12.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91fa8a452553a62e5fb3fbab471e7faf7b3bec3c87a2f355ebf3d7aab290fe4f", size = 208307, upload-time = "2025-11-04T18:30:00.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/0a/e041a248cd72f2f4c07e155913e0a3ede4c86cf21a40ae6cd79f135f2847/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:74ec101f69624695eec4ce7c953192d97748254abe78fb01b591f06d529e1952", size = 377844, upload-time = "2025-11-04T18:30:01.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/71/6f7773e4ffda73a358ce4bba69b3e8bee9d40a7a06315e4c1cd7a3ea9d02/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:9bbf7896580848326c1f9bd7531f264e561f98db7e08e15aa75963d83832c717", size = 471572, upload-time = "2025-11-04T18:30:02.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/29/af6769a4289c07acc71e7bda1d64fb31800563147d73142686e185e82348/ormsgpack-1.12.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7567917da613b8f8d591c1674e411fd3404bea41ef2b9a0e0a1e049c0f9406d7", size = 381842, upload-time = "2025-11-04T18:30:03.799Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/dd/0a86195ee7a1a96c088aefc8504385e881cf56f4563ed81bafe21cbf1fb0/ormsgpack-1.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:4e418256c5d8622b8bc92861936f7c6a0131355e7bcad88a42102ae8227f8a1c", size = 113008, upload-time = "2025-11-04T18:30:04.777Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/57/fafc79e32f3087f6f26f509d80b8167516326bfea38d30502627c01617e0/ormsgpack-1.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:433ace29aa02713554f714c62a4e4dcad0c9e32674ba4f66742c91a4c3b1b969", size = 106648, upload-time = "2025-11-04T18:30:05.708Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/cf/5d58d9b132128d2fe5d586355dde76af386554abef00d608f66b913bff1f/ormsgpack-1.12.0-cp314-cp314t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e57164be4ca34b64e210ec515059193280ac84df4d6f31a6fcbfb2fc8436de55", size = 369803, upload-time = "2025-11-04T18:30:06.728Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/42/968a2da361eaff2e4cbb17c82c7599787babf16684110ad70409646cc1e4/ormsgpack-1.12.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:904f96289deaa92fc6440b122edc27c5bdc28234edd63717f6d853d88c823a83", size = 195991, upload-time = "2025-11-04T18:30:07.713Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/f0/9696c6c6cf8ad35170f0be8d0ef3523cc258083535f6c8071cb8235ebb8b/ormsgpack-1.12.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b291d086e524a1062d57d1b7b5a8bcaaf29caebf0212fec12fd86240bd33633", size = 208316, upload-time = "2025-11-04T18:30:08.663Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -694,6 +832,58 @@ wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/90/422ffbbeeb9418c795dae2a768db860401446af0c6768bc061ce22325f58/psycopg-3.2.10-py3-none-any.whl", hash = "sha256:ab5caf09a9ec42e314a21f5216dbcceac528e0e05142e42eea83a3b28b320ac3", size = 206586, upload-time = "2025-09-08T09:07:50.121Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psycopg-binary"
|
||||
version = "3.2.11"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/48/96/9fe31ef61b311c697a98709a31b875d152e4f67924dd2cb94a4de0396d74/psycopg_binary-3.2.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f72146ad5b69ea177c2707578e5a4a9422b79e50d5a80992dabc5619b0929771", size = 4031016, upload-time = "2025-10-18T22:43:35.867Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/55/fe/3ae6be34bfda1ba6dfd4e3b5c1d68bc51d4593399b5a10faaff68937c9a1/psycopg_binary-3.2.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b051aa1e67f0d03ccdb4503d716f22da56229896526f0aa721e5a199baa9e5d4", size = 4090430, upload-time = "2025-10-18T22:43:41.154Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/ea/7aa84f6bb64f94bfbe7d494d384a0d2bc66ba66e8607f5e9b515aa6af627/psycopg_binary-3.2.11-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:49d76391b225f72dd63fcab87937ccf307ae0f093b5a382eeacf05f19a57c176", size = 4641307, upload-time = "2025-10-18T22:43:45.959Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/67/ef12ff8a530230824965668b44ccd58a88dae40511f7bbd125defb7972c4/psycopg_binary-3.2.11-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:58997db1aa48a1119e26c1c2f893d1c92339bd3be5d1f25334f22eaeaeeca90e", size = 4742204, upload-time = "2025-10-18T22:43:50.702Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/9c/8f35345fe22a0e5997cbfba0b7e1a58f26b290400cb9a6cb67e72e503331/psycopg_binary-3.2.11-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:e3b6328bc2f3ca233f9a5f08d266089b96a534eca9ee4e45cb92d0a8d4629d9c", size = 4425352, upload-time = "2025-10-18T22:43:55.039Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/29/f0c585c6b48526f0ecf179e13ea2b6d8fed0dbba8c1a0d61da8ece149b0e/psycopg_binary-3.2.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:5bc571786a256a2fa2d8f13b5ecf714020b753bc76c2fa6d308e46751946dc31", size = 3885019, upload-time = "2025-10-18T22:43:59.256Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/6d/a139e1c7e9840491d9ad3c837264a900ac95ba35e5f83fd5715b1ce7a729/psycopg_binary-3.2.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:766089fdaa8af1b5f7e2ec9fd7ad190c865e226b4fb0e7b1bd8dbcd62b5b923e", size = 3568192, upload-time = "2025-10-18T22:44:03.915Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/ea/43a2b6fcfa816797dc6d2ac67e9cd09b3a7e4da0a29467a8b5940e7a1312/psycopg_binary-3.2.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5fb27dd9c52ae13cb4de90244207155b694f76a75a816115ead2d573f40e1e36", size = 3609300, upload-time = "2025-10-18T22:44:09.168Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/d5/c9d46e626528a44b0feb881064e8018107b603ac683a658be3ee9ca00222/psycopg_binary-3.2.11-cp310-cp310-win_amd64.whl", hash = "sha256:3f32b09fba85d9e239229bdc5b6254420c02054f6954fe7fbd1ecf1ca93009ed", size = 2918105, upload-time = "2025-10-18T22:44:14.203Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/c4/350473820759d7e599e68bd79c88d32376353ceb0f764db05de8f13ff421/psycopg_binary-3.2.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6688807ed07436c18e9946d01372bc80b9d20b7732cde27de9313e0860910c84", size = 4037740, upload-time = "2025-10-18T22:44:21.344Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/e0/00bf3e207676bbe6e9f32c0f924f0e5be1efcd1a9fb2fd84d1c3d9958a96/psycopg_binary-3.2.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:478a68d50f34f6203642d245e2046d266c719ab4e593a1bb94c3be5f82e1aee1", size = 4098558, upload-time = "2025-10-18T22:44:26.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/db/bc1d22fe57b01fa76b02943e1034cb59070bf906e982ebc507d079998b5b/psycopg_binary-3.2.11-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e7575ca710277cc3e9257ff803a3e0e3cb7cc1b7851639cb783a7cd55ebfc815", size = 4646689, upload-time = "2025-10-18T22:44:31.055Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/6e/b1234e784af5c999ca4bd2e3a8673c58e941926dc4a53b9196d00929f7c9/psycopg_binary-3.2.11-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:110a2036007230416fcc2c17bfe7aaa2c1fa9b6e9d21e2cd551523e3f6489759", size = 4749164, upload-time = "2025-10-18T22:44:39.529Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/77/98c2e6c683941e54560ef3449fbc97b7ca31318436576e0c9d92c1dc875d/psycopg_binary-3.2.11-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:31f1d5630afa673c37a6327f8e3efa1f17d4e4e42972643b3478b52275233529", size = 4432473, upload-time = "2025-10-18T22:44:45.323Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/1d/73e72427152c03f61b75c14642a7187b16be0e03480f7329ab5cf618fdac/psycopg_binary-3.2.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9f12a34bddaeffa7840a61163595ec0d70a9db855896865dcfbb731510014484", size = 3890114, upload-time = "2025-10-18T22:44:49.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/ed/08a6b135ece52bb4024e19d03a294f002992d2f0c60fccdc35f245801d9c/psycopg_binary-3.2.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:82fe30afbdd66fbdad583b02baad5c15930a3dc8a3756d2ae15fc874e9be8ec8", size = 3571474, upload-time = "2025-10-18T22:44:52.476Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/5c/b0c857cd0718b1a8af86a24e61deeb9643e9e4731f732a9b7cab280b1323/psycopg_binary-3.2.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:592fb928efe0674a7400af914bcf931eb5267d36237925947aaecf63bd9a91aa", size = 3613401, upload-time = "2025-10-18T22:44:56.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/29/437255bc149b132c63ab0279f8850648cd3ae524667f475b621a2a3d0d5b/psycopg_binary-3.2.11-cp311-cp311-win_amd64.whl", hash = "sha256:20d41bcd9ac289d44ac1f6151594f7883483b4ad14680a63e04b639dc90c3349", size = 2919850, upload-time = "2025-10-18T22:45:00.108Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/9e/58945c828b60820e5c192d04f238f1aa49de0fe5f3b9883e277f33c17c0a/psycopg_binary-3.2.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4cae9bdc482e36e825d5102a9f3010e729f33a4ca83fc8a1f439ba16eb61e1f1", size = 4019920, upload-time = "2025-10-18T22:45:05.023Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/c4/ac7f600ae5d8fb7a89c2712163b642d88739b3bb4c8d0fb3178c084dc521/psycopg_binary-3.2.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:749d23fbfd642a7abfef5fc0f6ca185fa82a2c0f895e6eab42c3f2a5d88f6011", size = 4092123, upload-time = "2025-10-18T22:45:09.763Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/aa/866c8b2c83490f0d55c4a27d16c0b733744faac442adf181eb59d8d48a3d/psycopg_binary-3.2.11-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58d8f9f80ae79ba7f2a0509424939236220d7d66a4f8256ae999b882cc58065b", size = 4626894, upload-time = "2025-10-18T22:45:13.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/a8/e7c1eba4ca230d510b76b3f8701321e0c21820953744db67ec7c8fb67537/psycopg_binary-3.2.11-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:eab6959fade522e586b8ec37d3fe337ce10861965edef3292f52e66e36dc375d", size = 4719913, upload-time = "2025-10-18T22:45:19.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/5f/de0dea38cef6e050ff8e9acd0f7c5d956251fcfece5360973329eb10b84b/psycopg_binary-3.2.11-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe5e3648e855df4fba1d70c18aef18c9880ea8d123fdfae754c18787c8cb37b3", size = 4411018, upload-time = "2025-10-18T22:45:24.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/bf/2bbefb24e491f2fa4a7c627d14680429ca33092176eadae88fab4fbce8c6/psycopg_binary-3.2.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:30e2c114d26554ae677088de5d4133cc112344d7a233200fdbf4a2ca5754c7ec", size = 3861940, upload-time = "2025-10-18T22:45:28.624Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/07/d68f78df7490fcd17eef7f138f96bf3398a961208262498cde7d30266481/psycopg_binary-3.2.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e3f5887019dfb094c60e7026968ca3a964ca16305807ba5e43f9a78483767d5f", size = 3534831, upload-time = "2025-10-18T22:45:32.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/18/fc5a881ca3d8b40b8e37a396bf14176b8439a7e4b1a29848af325009f955/psycopg_binary-3.2.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9b4b0fc4e774063ae64c92cc57e2b10160150de68c96d71743218159d953869d", size = 3583559, upload-time = "2025-10-18T22:45:36.438Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/98/c4418b609ffea80907861ddb01c043af860b179cb8fb41905ad2f0a4f400/psycopg_binary-3.2.11-cp312-cp312-win_amd64.whl", hash = "sha256:9bdc762600fcc8e4ad3224734a4e70cc226207fd8f2de47c36b115efeed01782", size = 2910294, upload-time = "2025-10-18T22:45:40.135Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/93/9cea78ed3b279909f0fd6c2badb24b2361b93c875d6a7c921e26f6254044/psycopg_binary-3.2.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:47f6cf8a1d02d25238bdb8741ac641ff0ec22b1c6ff6a2acd057d0da5c712842", size = 4017939, upload-time = "2025-10-18T22:45:45.114Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/86/fc9925f500b2c140c0bb8c1f8fcd04f8c45c76d4852e87baf4c75182de8c/psycopg_binary-3.2.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:91268f04380964a5e767f8102d05f1e23312ddbe848de1a9514b08b3fc57d354", size = 4090150, upload-time = "2025-10-18T22:45:50.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/10/752b698da1ca9e6c5f15d8798cb637c3615315fd2da17eee4a90cf20ee08/psycopg_binary-3.2.11-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:199f88a05dd22133eab2deb30348ef7a70c23d706c8e63fdc904234163c63517", size = 4625597, upload-time = "2025-10-18T22:45:54.638Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0a/9f/b578545c3c23484f4e234282d97ab24632a1d3cbfec64209786872e7cc8f/psycopg_binary-3.2.11-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7b3c5474dbad63bcccb8d14d4d4c7c19f1dc6f8e8c1914cbc771d261cf8eddca", size = 4720326, upload-time = "2025-10-18T22:45:59.266Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/3b/ba548d3fe65a7d4c96e568c2188e4b665802e3cba41664945ed95d16eae9/psycopg_binary-3.2.11-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:581358e770a4536e546841b78fd0fe318added4a82443bf22d0bbe3109cf9582", size = 4411647, upload-time = "2025-10-18T22:46:04.009Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/65/559ab485b198600e7ff70d70786ae5c89d63475ca01d43a7dda0d7c91386/psycopg_binary-3.2.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:54a30f00a51b9043048b3e7ee806ffd31fc5fbd02a20f0e69d21306ff33dc473", size = 3863037, upload-time = "2025-10-18T22:46:08.469Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/29/05d0b48c8bef147e8216a36a1263a309a6240dcc09a56f5b8174fa6216d2/psycopg_binary-3.2.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2a438fad4cc081b018431fde0e791b6d50201526edf39522a85164f606c39ddb", size = 3536975, upload-time = "2025-10-18T22:46:12.982Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/75/304e133d3ab1a49602616192edb81f603ed574f79966449105f2e200999d/psycopg_binary-3.2.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f5e7415b5d0f58edf2708842c66605092df67f3821161d861b09695fc326c4de", size = 3586213, upload-time = "2025-10-18T22:46:19.523Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/10/c47cce42fa3c37d439e1400eaa5eeb2ce53dc3abc84d52c8a8a9e544d945/psycopg_binary-3.2.11-cp313-cp313-win_amd64.whl", hash = "sha256:6b9632c42f76d5349e7dd50025cff02688eb760b258e891ad2c6428e7e4917d5", size = 2912997, upload-time = "2025-10-18T22:46:24.978Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/13/728b4763ef76a688737acebfcb5ab8696b024adc49a69c86081392b0e5ba/psycopg_binary-3.2.11-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:260738ae222b41dbefd0d84cb2e150a112f90b41688630f57fdac487ab6d6f38", size = 4016962, upload-time = "2025-10-18T22:46:29.207Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/0f/6180149621a907c5b60a2fae87d6ee10cc13e8c9f58d8250c310634ced04/psycopg_binary-3.2.11-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c594c199869099c59c85b9f4423370b6212491fb929e7fcda0da1768761a2c2c", size = 4090614, upload-time = "2025-10-18T22:46:33.073Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/97/cce19bdef510b698c9036d5573b941b539ffcaa7602450da559c8a62e0c3/psycopg_binary-3.2.11-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5768a9e7d393b2edd3a28de5a6d5850d054a016ed711f7044a9072f19f5e50d5", size = 4629749, upload-time = "2025-10-18T22:46:37.415Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/9d/9bff18989fb2bf05d18c1431dd8bec4a1d90141beb11fc45d3269947ddf3/psycopg_binary-3.2.11-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:27eb6367350b75fef882c40cd6f748bfd976db2f8651f7511956f11efc15154f", size = 4724035, upload-time = "2025-10-18T22:46:42.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/e5/39b930323428596990367b7953197730213d3d9d07bcedcad1d026608178/psycopg_binary-3.2.11-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fa2aa5094dc962967ca0978c035b3ef90329b802501ef12a088d3bac6a55598e", size = 4411419, upload-time = "2025-10-18T22:46:47.745Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/9c/97c25438d1e51ddc6a7f67990b4c59f94bc515114ada864804ccee27ef1b/psycopg_binary-3.2.11-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7744b4ed1f3b76fe37de7e9ef98014482fe74b6d3dfe1026cc4cfb4b4404e74f", size = 3867844, upload-time = "2025-10-18T22:46:53.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/51/8c1e291cf4aa9982666f71a886aa782d990aa16853a42de545a0a9a871ef/psycopg_binary-3.2.11-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5f6f948ff1cd252003ff534d7b50a2b25453b4212b283a7514ff8751bdb68c37", size = 3541539, upload-time = "2025-10-18T22:46:58.993Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/0a/e25edcdfa1111bfc5c95668b7469b5a957b40ce10cc81383688d65564826/psycopg_binary-3.2.11-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:3bd2c8fb1dec6f93383fbaa561591fa3d676e079f9cb9889af17c3020a19715f", size = 3588090, upload-time = "2025-10-18T22:47:04.105Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/aa/f8c2f4b4c13d5680a20e5bfcd61f9e154bce26e7a2c70cb0abeade088d61/psycopg_binary-3.2.11-cp314-cp314-win_amd64.whl", hash = "sha256:c45f61202e5691090a697e599997eaffa3ec298209743caa4fd346145acabafe", size = 3006049, upload-time = "2025-10-18T22:47:07.923Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psycopg-pool"
|
||||
version = "3.2.6"
|
||||
@@ -708,7 +898,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.11.9"
|
||||
version = "2.12.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
@@ -716,96 +906,123 @@ dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ff/5d/09a551ba512d7ca404d785072700d3f6727a02f6f3c24ecfd081c7cf0aa8/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2", size = 788495, upload-time = "2025-09-13T11:26:39.325Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8d/35/d319ed522433215526689bad428a94058b6dd12190ce7ddd78618ac14b28/pydantic-2.12.2.tar.gz", hash = "sha256:7b8fa15b831a4bbde9d5b84028641ac3080a4ca2cbd4a621a661687e741624fd", size = 816358, upload-time = "2025-10-14T15:02:21.842Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/d3/108f2006987c58e76691d5ae5d200dd3e0f532cb4e5fa3560751c3a1feba/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2", size = 444855, upload-time = "2025-09-13T11:26:36.909Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6c/98/468cb649f208a6f1279448e6e5247b37ae79cf5e4041186f1e2ef3d16345/pydantic-2.12.2-py3-none-any.whl", hash = "sha256:25ff718ee909acd82f1ff9b1a4acfd781bb23ab3739adaa7144f19a6a4e231ae", size = 460628, upload-time = "2025-10-14T15:02:19.623Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.33.2"
|
||||
version = "2.41.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/18/d0944e8eaaa3efd0a91b0f1fc537d3be55ad35091b6a87638211ba691964/pydantic_core-2.41.4.tar.gz", hash = "sha256:70e47929a9d4a1905a67e4b687d5946026390568a8e952b92824118063cee4d5", size = 457557, upload-time = "2025-10-14T10:23:47.909Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/3d/9b8ca77b0f76fcdbf8bc6b72474e264283f461284ca84ac3fde570c6c49a/pydantic_core-2.41.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2442d9a4d38f3411f22eb9dd0912b7cbf4b7d5b6c92c4173b75d3e1ccd84e36e", size = 2111197, upload-time = "2025-10-14T10:19:43.303Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/92/b7b0fe6ed4781642232755cb7e56a86e2041e1292f16d9ae410a0ccee5ac/pydantic_core-2.41.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:30a9876226dda131a741afeab2702e2d127209bde3c65a2b8133f428bc5d006b", size = 1917909, upload-time = "2025-10-14T10:19:45.194Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/8c/3eb872009274ffa4fb6a9585114e161aa1a0915af2896e2d441642929fe4/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d55bbac04711e2980645af68b97d445cdbcce70e5216de444a6c4b6943ebcccd", size = 1969905, upload-time = "2025-10-14T10:19:46.567Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/21/35adf4a753bcfaea22d925214a0c5b880792e3244731b3f3e6fec0d124f7/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e1d778fb7849a42d0ee5927ab0f7453bf9f85eef8887a546ec87db5ddb178945", size = 2051938, upload-time = "2025-10-14T10:19:48.237Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7d/d0/cdf7d126825e36d6e3f1eccf257da8954452934ede275a8f390eac775e89/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b65077a4693a98b90ec5ad8f203ad65802a1b9b6d4a7e48066925a7e1606706", size = 2250710, upload-time = "2025-10-14T10:19:49.619Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/1c/af1e6fd5ea596327308f9c8d1654e1285cc3d8de0d584a3c9d7705bf8a7c/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:62637c769dee16eddb7686bf421be48dfc2fae93832c25e25bc7242e698361ba", size = 2367445, upload-time = "2025-10-14T10:19:51.269Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/81/8cece29a6ef1b3a92f956ea6da6250d5b2d2e7e4d513dd3b4f0c7a83dfea/pydantic_core-2.41.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dfe3aa529c8f501babf6e502936b9e8d4698502b2cfab41e17a028d91b1ac7b", size = 2072875, upload-time = "2025-10-14T10:19:52.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/37/a6a579f5fc2cd4d5521284a0ab6a426cc6463a7b3897aeb95b12f1ba607b/pydantic_core-2.41.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ca2322da745bf2eeb581fc9ea3bbb31147702163ccbcbf12a3bb630e4bf05e1d", size = 2191329, upload-time = "2025-10-14T10:19:54.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/03/505020dc5c54ec75ecba9f41119fd1e48f9e41e4629942494c4a8734ded1/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e8cd3577c796be7231dcf80badcf2e0835a46665eaafd8ace124d886bab4d700", size = 2151658, upload-time = "2025-10-14T10:19:55.843Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/5d/2c0d09fb53aa03bbd2a214d89ebfa6304be7df9ed86ee3dc7770257f41ee/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:1cae8851e174c83633f0833e90636832857297900133705ee158cf79d40f03e6", size = 2316777, upload-time = "2025-10-14T10:19:57.607Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/4b/c2c9c8f5e1f9c864b57d08539d9d3db160e00491c9f5ee90e1bfd905e644/pydantic_core-2.41.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a26d950449aae348afe1ac8be5525a00ae4235309b729ad4d3399623125b43c9", size = 2320705, upload-time = "2025-10-14T10:19:59.016Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/c3/a74c1c37f49c0a02c89c7340fafc0ba816b29bd495d1a31ce1bdeacc6085/pydantic_core-2.41.4-cp310-cp310-win32.whl", hash = "sha256:0cf2a1f599efe57fa0051312774280ee0f650e11152325e41dfd3018ef2c1b57", size = 1975464, upload-time = "2025-10-14T10:20:00.581Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/23/5dd5c1324ba80303368f7569e2e2e1a721c7d9eb16acb7eb7b7f85cb1be2/pydantic_core-2.41.4-cp310-cp310-win_amd64.whl", hash = "sha256:a8c2e340d7e454dc3340d3d2e8f23558ebe78c98aa8f68851b04dcb7bc37abdc", size = 2024497, upload-time = "2025-10-14T10:20:03.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/4c/f6cbfa1e8efacd00b846764e8484fe173d25b8dab881e277a619177f3384/pydantic_core-2.41.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:28ff11666443a1a8cf2a044d6a545ebffa8382b5f7973f22c36109205e65dc80", size = 2109062, upload-time = "2025-10-14T10:20:04.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/f8/40b72d3868896bfcd410e1bd7e516e762d326201c48e5b4a06446f6cf9e8/pydantic_core-2.41.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:61760c3925d4633290292bad462e0f737b840508b4f722247d8729684f6539ae", size = 1916301, upload-time = "2025-10-14T10:20:06.857Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/4d/d203dce8bee7faeca791671c88519969d98d3b4e8f225da5b96dad226fc8/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eae547b7315d055b0de2ec3965643b0ab82ad0106a7ffd29615ee9f266a02827", size = 1968728, upload-time = "2025-10-14T10:20:08.353Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/65/f5/6a66187775df87c24d526985b3a5d78d861580ca466fbd9d4d0e792fcf6c/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef9ee5471edd58d1fcce1c80ffc8783a650e3e3a193fe90d52e43bb4d87bff1f", size = 2050238, upload-time = "2025-10-14T10:20:09.766Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/b9/78336345de97298cf53236b2f271912ce11f32c1e59de25a374ce12f9cce/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15dd504af121caaf2c95cb90c0ebf71603c53de98305621b94da0f967e572def", size = 2249424, upload-time = "2025-10-14T10:20:11.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/99/bb/a4584888b70ee594c3d374a71af5075a68654d6c780369df269118af7402/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a926768ea49a8af4d36abd6a8968b8790f7f76dd7cbd5a4c180db2b4ac9a3a2", size = 2366047, upload-time = "2025-10-14T10:20:13.647Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/8d/17fc5de9d6418e4d2ae8c675f905cdafdc59d3bf3bf9c946b7ab796a992a/pydantic_core-2.41.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6916b9b7d134bff5440098a4deb80e4cb623e68974a87883299de9124126c2a8", size = 2071163, upload-time = "2025-10-14T10:20:15.307Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/e7/03d2c5c0b8ed37a4617430db68ec5e7dbba66358b629cd69e11b4d564367/pydantic_core-2.41.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cf90535979089df02e6f17ffd076f07237efa55b7343d98760bde8743c4b265", size = 2190585, upload-time = "2025-10-14T10:20:17.3Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/fc/15d1c9fe5ad9266a5897d9b932b7f53d7e5cfc800573917a2c5d6eea56ec/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7533c76fa647fade2d7ec75ac5cc079ab3f34879626dae5689b27790a6cf5a5c", size = 2150109, upload-time = "2025-10-14T10:20:19.143Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/26/ef/e735dd008808226c83ba56972566138665b71477ad580fa5a21f0851df48/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:37e516bca9264cbf29612539801ca3cd5d1be465f940417b002905e6ed79d38a", size = 2315078, upload-time = "2025-10-14T10:20:20.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/90/00/806efdcf35ff2ac0f938362350cd9827b8afb116cc814b6b75cf23738c7c/pydantic_core-2.41.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0c19cb355224037c83642429b8ce261ae108e1c5fbf5c028bac63c77b0f8646e", size = 2318737, upload-time = "2025-10-14T10:20:22.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/41/7e/6ac90673fe6cb36621a2283552897838c020db343fa86e513d3f563b196f/pydantic_core-2.41.4-cp311-cp311-win32.whl", hash = "sha256:09c2a60e55b357284b5f31f5ab275ba9f7f70b7525e18a132ec1f9160b4f1f03", size = 1974160, upload-time = "2025-10-14T10:20:23.817Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/9d/7c5e24ee585c1f8b6356e1d11d40ab807ffde44d2db3b7dfd6d20b09720e/pydantic_core-2.41.4-cp311-cp311-win_amd64.whl", hash = "sha256:711156b6afb5cb1cb7c14a2cc2c4a8b4c717b69046f13c6b332d8a0a8f41ca3e", size = 2021883, upload-time = "2025-10-14T10:20:25.48Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/90/5c172357460fc28b2871eb4a0fb3843b136b429c6fa827e4b588877bf115/pydantic_core-2.41.4-cp311-cp311-win_arm64.whl", hash = "sha256:6cb9cf7e761f4f8a8589a45e49ed3c0d92d1d696a45a6feaee8c904b26efc2db", size = 1968026, upload-time = "2025-10-14T10:20:27.039Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/81/d3b3e95929c4369d30b2a66a91db63c8ed0a98381ae55a45da2cd1cc1288/pydantic_core-2.41.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ab06d77e053d660a6faaf04894446df7b0a7e7aba70c2797465a0a1af00fc887", size = 2099043, upload-time = "2025-10-14T10:20:28.561Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/da/46fdac49e6717e3a94fc9201403e08d9d61aa7a770fab6190b8740749047/pydantic_core-2.41.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c53ff33e603a9c1179a9364b0a24694f183717b2e0da2b5ad43c316c956901b2", size = 1910699, upload-time = "2025-10-14T10:20:30.217Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/63/4d948f1b9dd8e991a5a98b77dd66c74641f5f2e5225fee37994b2e07d391/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:304c54176af2c143bd181d82e77c15c41cbacea8872a2225dd37e6544dce9999", size = 1952121, upload-time = "2025-10-14T10:20:32.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b2/a7/e5fc60a6f781fc634ecaa9ecc3c20171d238794cef69ae0af79ac11b89d7/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025ba34a4cf4fb32f917d5d188ab5e702223d3ba603be4d8aca2f82bede432a4", size = 2041590, upload-time = "2025-10-14T10:20:34.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/69/dce747b1d21d59e85af433428978a1893c6f8a7068fa2bb4a927fba7a5ff/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9f5f30c402ed58f90c70e12eff65547d3ab74685ffe8283c719e6bead8ef53f", size = 2219869, upload-time = "2025-10-14T10:20:35.965Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/83/6a/c070e30e295403bf29c4df1cb781317b6a9bac7cd07b8d3acc94d501a63c/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd96e5d15385d301733113bcaa324c8bcf111275b7675a9c6e88bfb19fc05e3b", size = 2345169, upload-time = "2025-10-14T10:20:37.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f0/83/06d001f8043c336baea7fd202a9ac7ad71f87e1c55d8112c50b745c40324/pydantic_core-2.41.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f348cbb44fae6e9653c1055db7e29de67ea6a9ca03a5fa2c2e11a47cff0e47", size = 2070165, upload-time = "2025-10-14T10:20:39.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/0a/e567c2883588dd12bcbc110232d892cf385356f7c8a9910311ac997ab715/pydantic_core-2.41.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec22626a2d14620a83ca583c6f5a4080fa3155282718b6055c2ea48d3ef35970", size = 2189067, upload-time = "2025-10-14T10:20:41.015Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/1d/3d9fca34273ba03c9b1c5289f7618bc4bd09c3ad2289b5420481aa051a99/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3a95d4590b1f1a43bf33ca6d647b990a88f4a3824a8c4572c708f0b45a5290ed", size = 2132997, upload-time = "2025-10-14T10:20:43.106Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/70/d702ef7a6cd41a8afc61f3554922b3ed8d19dd54c3bd4bdbfe332e610827/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:f9672ab4d398e1b602feadcffcdd3af44d5f5e6ddc15bc7d15d376d47e8e19f8", size = 2307187, upload-time = "2025-10-14T10:20:44.849Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/4c/c06be6e27545d08b802127914156f38d10ca287a9e8489342793de8aae3c/pydantic_core-2.41.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:84d8854db5f55fead3b579f04bda9a36461dab0730c5d570e1526483e7bb8431", size = 2305204, upload-time = "2025-10-14T10:20:46.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/e5/35ae4919bcd9f18603419e23c5eaf32750224a89d41a8df1a3704b69f77e/pydantic_core-2.41.4-cp312-cp312-win32.whl", hash = "sha256:9be1c01adb2ecc4e464392c36d17f97e9110fbbc906bcbe1c943b5b87a74aabd", size = 1972536, upload-time = "2025-10-14T10:20:48.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/c2/49c5bb6d2a49eb2ee3647a93e3dae7080c6409a8a7558b075027644e879c/pydantic_core-2.41.4-cp312-cp312-win_amd64.whl", hash = "sha256:d682cf1d22bab22a5be08539dca3d1593488a99998f9f412137bc323179067ff", size = 2031132, upload-time = "2025-10-14T10:20:50.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/23/936343dbcba6eec93f73e95eb346810fc732f71ba27967b287b66f7b7097/pydantic_core-2.41.4-cp312-cp312-win_arm64.whl", hash = "sha256:833eebfd75a26d17470b58768c1834dfc90141b7afc6eb0429c21fc5a21dcfb8", size = 1969483, upload-time = "2025-10-14T10:20:52.35Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/13/d0/c20adabd181a029a970738dfe23710b52a31f1258f591874fcdec7359845/pydantic_core-2.41.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:85e050ad9e5f6fe1004eec65c914332e52f429bc0ae12d6fa2092407a462c746", size = 2105688, upload-time = "2025-10-14T10:20:54.448Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/b6/0ce5c03cec5ae94cca220dfecddc453c077d71363b98a4bbdb3c0b22c783/pydantic_core-2.41.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e7393f1d64792763a48924ba31d1e44c2cfbc05e3b1c2c9abb4ceeadd912cced", size = 1910807, upload-time = "2025-10-14T10:20:56.115Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/3e/800d3d02c8beb0b5c069c870cbb83799d085debf43499c897bb4b4aaff0d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94dab0940b0d1fb28bcab847adf887c66a27a40291eedf0b473be58761c9799a", size = 1956669, upload-time = "2025-10-14T10:20:57.874Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/60/a4/24271cc71a17f64589be49ab8bd0751f6a0a03046c690df60989f2f95c2c/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:de7c42f897e689ee6f9e93c4bec72b99ae3b32a2ade1c7e4798e690ff5246e02", size = 2051629, upload-time = "2025-10-14T10:21:00.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/de/45af3ca2f175d91b96bfb62e1f2d2f1f9f3b14a734afe0bfeff079f78181/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:664b3199193262277b8b3cd1e754fb07f2c6023289c815a1e1e8fb415cb247b1", size = 2224049, upload-time = "2025-10-14T10:21:01.801Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/8f/ae4e1ff84672bf869d0a77af24fd78387850e9497753c432875066b5d622/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95b253b88f7d308b1c0b417c4624f44553ba4762816f94e6986819b9c273fb2", size = 2342409, upload-time = "2025-10-14T10:21:03.556Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/62/273dd70b0026a085c7b74b000394e1ef95719ea579c76ea2f0cc8893736d/pydantic_core-2.41.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1351f5bbdbbabc689727cb91649a00cb9ee7203e0a6e54e9f5ba9e22e384b84", size = 2069635, upload-time = "2025-10-14T10:21:05.385Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/03/cf485fff699b4cdaea469bc481719d3e49f023241b4abb656f8d422189fc/pydantic_core-2.41.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1affa4798520b148d7182da0615d648e752de4ab1a9566b7471bc803d88a062d", size = 2194284, upload-time = "2025-10-14T10:21:07.122Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/7e/c8e713db32405dfd97211f2fc0a15d6bf8adb7640f3d18544c1f39526619/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7b74e18052fea4aa8dea2fb7dbc23d15439695da6cbe6cfc1b694af1115df09d", size = 2137566, upload-time = "2025-10-14T10:21:08.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/f7/db71fd4cdccc8b75990f79ccafbbd66757e19f6d5ee724a6252414483fb4/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:285b643d75c0e30abda9dc1077395624f314a37e3c09ca402d4015ef5979f1a2", size = 2316809, upload-time = "2025-10-14T10:21:10.805Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/63/a54973ddb945f1bca56742b48b144d85c9fc22f819ddeb9f861c249d5464/pydantic_core-2.41.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f52679ff4218d713b3b33f88c89ccbf3a5c2c12ba665fb80ccc4192b4608dbab", size = 2311119, upload-time = "2025-10-14T10:21:12.583Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/03/5d12891e93c19218af74843a27e32b94922195ded2386f7b55382f904d2f/pydantic_core-2.41.4-cp313-cp313-win32.whl", hash = "sha256:ecde6dedd6fff127c273c76821bb754d793be1024bc33314a120f83a3c69460c", size = 1981398, upload-time = "2025-10-14T10:21:14.584Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/d8/fd0de71f39db91135b7a26996160de71c073d8635edfce8b3c3681be0d6d/pydantic_core-2.41.4-cp313-cp313-win_amd64.whl", hash = "sha256:d081a1f3800f05409ed868ebb2d74ac39dd0c1ff6c035b5162356d76030736d4", size = 2030735, upload-time = "2025-10-14T10:21:16.432Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/86/c99921c1cf6650023c08bfab6fe2d7057a5142628ef7ccfa9921f2dda1d5/pydantic_core-2.41.4-cp313-cp313-win_arm64.whl", hash = "sha256:f8e49c9c364a7edcbe2a310f12733aad95b022495ef2a8d653f645e5d20c1564", size = 1973209, upload-time = "2025-10-14T10:21:18.213Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/36/0d/b5706cacb70a8414396efdda3d72ae0542e050b591119e458e2490baf035/pydantic_core-2.41.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ed97fd56a561f5eb5706cebe94f1ad7c13b84d98312a05546f2ad036bafe87f4", size = 1877324, upload-time = "2025-10-14T10:21:20.363Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/2d/cba1fa02cfdea72dfb3a9babb067c83b9dff0bbcb198368e000a6b756ea7/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a870c307bf1ee91fc58a9a61338ff780d01bfae45922624816878dce784095d2", size = 1884515, upload-time = "2025-10-14T10:21:22.339Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/ea/3df927c4384ed9b503c9cc2d076cf983b4f2adb0c754578dfb1245c51e46/pydantic_core-2.41.4-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25e97bc1f5f8f7985bdc2335ef9e73843bb561eb1fa6831fdfc295c1c2061cf", size = 2042819, upload-time = "2025-10-14T10:21:26.683Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/ee/df8e871f07074250270a3b1b82aad4cd0026b588acd5d7d3eb2fcb1471a3/pydantic_core-2.41.4-cp313-cp313t-win_amd64.whl", hash = "sha256:d405d14bea042f166512add3091c1af40437c2e7f86988f3915fabd27b1e9cd2", size = 1995866, upload-time = "2025-10-14T10:21:28.951Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/de/b20f4ab954d6d399499c33ec4fafc46d9551e11dc1858fb7f5dca0748ceb/pydantic_core-2.41.4-cp313-cp313t-win_arm64.whl", hash = "sha256:19f3684868309db5263a11bace3c45d93f6f24afa2ffe75a647583df22a2ff89", size = 1970034, upload-time = "2025-10-14T10:21:30.869Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/54/28/d3325da57d413b9819365546eb9a6e8b7cbd9373d9380efd5f74326143e6/pydantic_core-2.41.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:e9205d97ed08a82ebb9a307e92914bb30e18cdf6f6b12ca4bedadb1588a0bfe1", size = 2102022, upload-time = "2025-10-14T10:21:32.809Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/24/b58a1bc0d834bf1acc4361e61233ee217169a42efbdc15a60296e13ce438/pydantic_core-2.41.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:82df1f432b37d832709fbcc0e24394bba04a01b6ecf1ee87578145c19cde12ac", size = 1905495, upload-time = "2025-10-14T10:21:34.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/a4/71f759cc41b7043e8ecdaab81b985a9b6cad7cec077e0b92cff8b71ecf6b/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc3b4cc4539e055cfa39a3763c939f9d409eb40e85813257dcd761985a108554", size = 1956131, upload-time = "2025-10-14T10:21:36.924Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/64/1e79ac7aa51f1eec7c4cda8cbe456d5d09f05fdd68b32776d72168d54275/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1eb1754fce47c63d2ff57fdb88c351a6c0150995890088b33767a10218eaa4e", size = 2052236, upload-time = "2025-10-14T10:21:38.927Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/e3/a3ffc363bd4287b80f1d43dc1c28ba64831f8dfc237d6fec8f2661138d48/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6ab5ab30ef325b443f379ddb575a34969c333004fca5a1daa0133a6ffaad616", size = 2223573, upload-time = "2025-10-14T10:21:41.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/27/78814089b4d2e684a9088ede3790763c64693c3d1408ddc0a248bc789126/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:31a41030b1d9ca497634092b46481b937ff9397a86f9f51bd41c4767b6fc04af", size = 2342467, upload-time = "2025-10-14T10:21:44.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/97/4de0e2a1159cb85ad737e03306717637842c88c7fd6d97973172fb183149/pydantic_core-2.41.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a44ac1738591472c3d020f61c6df1e4015180d6262ebd39bf2aeb52571b60f12", size = 2063754, upload-time = "2025-10-14T10:21:46.466Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/50/8cb90ce4b9efcf7ae78130afeb99fd1c86125ccdf9906ef64b9d42f37c25/pydantic_core-2.41.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d72f2b5e6e82ab8f94ea7d0d42f83c487dc159c5240d8f83beae684472864e2d", size = 2196754, upload-time = "2025-10-14T10:21:48.486Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/3b/ccdc77af9cd5082723574a1cc1bcae7a6acacc829d7c0a06201f7886a109/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:c4d1e854aaf044487d31143f541f7aafe7b482ae72a022c664b2de2e466ed0ad", size = 2137115, upload-time = "2025-10-14T10:21:50.63Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/ba/e7c7a02651a8f7c52dc2cff2b64a30c313e3b57c7d93703cecea76c09b71/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b568af94267729d76e6ee5ececda4e283d07bbb28e8148bb17adad93d025d25a", size = 2317400, upload-time = "2025-10-14T10:21:52.959Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/ba/6c533a4ee8aec6b812c643c49bb3bd88d3f01e3cebe451bb85512d37f00f/pydantic_core-2.41.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6d55fb8b1e8929b341cc313a81a26e0d48aa3b519c1dbaadec3a6a2b4fcad025", size = 2312070, upload-time = "2025-10-14T10:21:55.419Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/ae/f10524fcc0ab8d7f96cf9a74c880243576fd3e72bd8ce4f81e43d22bcab7/pydantic_core-2.41.4-cp314-cp314-win32.whl", hash = "sha256:5b66584e549e2e32a1398df11da2e0a7eff45d5c2d9db9d5667c5e6ac764d77e", size = 1982277, upload-time = "2025-10-14T10:21:57.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/dc/e5aa27aea1ad4638f0c3fb41132f7eb583bd7420ee63204e2d4333a3bbf9/pydantic_core-2.41.4-cp314-cp314-win_amd64.whl", hash = "sha256:557a0aab88664cc552285316809cab897716a372afaf8efdbef756f8b890e894", size = 2024608, upload-time = "2025-10-14T10:21:59.557Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/61/51d89cc2612bd147198e120a13f150afbf0bcb4615cddb049ab10b81b79e/pydantic_core-2.41.4-cp314-cp314-win_arm64.whl", hash = "sha256:3f1ea6f48a045745d0d9f325989d8abd3f1eaf47dd00485912d1a3a63c623a8d", size = 1967614, upload-time = "2025-10-14T10:22:01.847Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/c2/472f2e31b95eff099961fa050c376ab7156a81da194f9edb9f710f68787b/pydantic_core-2.41.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6c1fe4c5404c448b13188dd8bd2ebc2bdd7e6727fa61ff481bcc2cca894018da", size = 1876904, upload-time = "2025-10-14T10:22:04.062Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/07/ea8eeb91173807ecdae4f4a5f4b150a520085b35454350fc219ba79e66a3/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:523e7da4d43b113bf8e7b49fa4ec0c35bf4fe66b2230bfc5c13cc498f12c6c3e", size = 1882538, upload-time = "2025-10-14T10:22:06.39Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1e/29/b53a9ca6cd366bfc928823679c6a76c7a4c69f8201c0ba7903ad18ebae2f/pydantic_core-2.41.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5729225de81fb65b70fdb1907fcf08c75d498f4a6f15af005aabb1fdadc19dfa", size = 2041183, upload-time = "2025-10-14T10:22:08.812Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/3d/f8c1a371ceebcaf94d6dd2d77c6cf4b1c078e13a5837aee83f760b4f7cfd/pydantic_core-2.41.4-cp314-cp314t-win_amd64.whl", hash = "sha256:de2cfbb09e88f0f795fd90cf955858fc2c691df65b1f21f0aa00b99f3fbc661d", size = 1993542, upload-time = "2025-10-14T10:22:11.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/ac/9fc61b4f9d079482a290afe8d206b8f490e9fd32d4fc03ed4fc698214e01/pydantic_core-2.41.4-cp314-cp314t-win_arm64.whl", hash = "sha256:d34f950ae05a83e0ede899c595f312ca976023ea1db100cd5aa188f7005e3ab0", size = 1973897, upload-time = "2025-10-14T10:22:13.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b0/12/5ba58daa7f453454464f92b3ca7b9d7c657d8641c48e370c3ebc9a82dd78/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:a1b2cfec3879afb742a7b0bcfa53e4f22ba96571c9e54d6a3afe1052d17d843b", size = 2122139, upload-time = "2025-10-14T10:22:47.288Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/fb/6860126a77725c3108baecd10fd3d75fec25191d6381b6eb2ac660228eac/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:d175600d975b7c244af6eb9c9041f10059f20b8bbffec9e33fdd5ee3f67cdc42", size = 1936674, upload-time = "2025-10-14T10:22:49.555Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/de/be/57dcaa3ed595d81f8757e2b44a38240ac5d37628bce25fb20d02c7018776/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f184d657fa4947ae5ec9c47bd7e917730fa1cbb78195037e32dcbab50aca5ee", size = 1956398, upload-time = "2025-10-14T10:22:52.19Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/1d/679a344fadb9695f1a6a294d739fbd21d71fa023286daeea8c0ed49e7c2b/pydantic_core-2.41.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ed810568aeffed3edc78910af32af911c835cc39ebbfacd1f0ab5dd53028e5c", size = 2138674, upload-time = "2025-10-14T10:22:54.499Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/48/ae937e5a831b7c0dc646b2ef788c27cd003894882415300ed21927c21efa/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:4f5d640aeebb438517150fdeec097739614421900e4a08db4a3ef38898798537", size = 2112087, upload-time = "2025-10-14T10:22:56.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5e/db/6db8073e3d32dae017da7e0d16a9ecb897d0a4d92e00634916e486097961/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:4a9ab037b71927babc6d9e7fc01aea9e66dc2a4a34dff06ef0724a4049629f94", size = 1920387, upload-time = "2025-10-14T10:22:59.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0d/c1/dd3542d072fcc336030d66834872f0328727e3b8de289c662faa04aa270e/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4dab9484ec605c3016df9ad4fd4f9a390bc5d816a3b10c6550f8424bb80b18c", size = 1951495, upload-time = "2025-10-14T10:23:02.089Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/c6/db8d13a1f8ab3f1eb08c88bd00fd62d44311e3456d1e85c0e59e0a0376e7/pydantic_core-2.41.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8a5028425820731d8c6c098ab642d7b8b999758e24acae03ed38a66eca8335", size = 2139008, upload-time = "2025-10-14T10:23:04.539Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/d4/912e976a2dd0b49f31c98a060ca90b353f3b73ee3ea2fd0030412f6ac5ec/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1e5ab4fc177dd41536b3c32b2ea11380dd3d4619a385860621478ac2d25ceb00", size = 2106739, upload-time = "2025-10-14T10:23:06.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/f0/66ec5a626c81eba326072d6ee2b127f8c139543f1bf609b4842978d37833/pydantic_core-2.41.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:3d88d0054d3fa11ce936184896bed3c1c5441d6fa483b498fac6a5d0dd6f64a9", size = 1932549, upload-time = "2025-10-14T10:23:09.24Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/af/625626278ca801ea0a658c2dcf290dc9f21bb383098e99e7c6a029fccfc0/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b2a054a8725f05b4b6503357e0ac1c4e8234ad3b0c2ac130d6ffc66f0e170e2", size = 2135093, upload-time = "2025-10-14T10:23:11.626Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/f6/2fba049f54e0f4975fef66be654c597a1d005320fa141863699180c7697d/pydantic_core-2.41.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0d9db5a161c99375a0c68c058e227bee1d89303300802601d76a3d01f74e258", size = 2187971, upload-time = "2025-10-14T10:23:14.437Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/80/65ab839a2dfcd3b949202f9d920c34f9de5a537c3646662bdf2f7d999680/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6273ea2c8ffdac7b7fda2653c49682db815aebf4a89243a6feccf5e36c18c347", size = 2147939, upload-time = "2025-10-14T10:23:16.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/44/58/627565d3d182ce6dfda18b8e1c841eede3629d59c9d7cbc1e12a03aeb328/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:4c973add636efc61de22530b2ef83a65f39b6d6f656df97f678720e20de26caa", size = 2311400, upload-time = "2025-10-14T10:23:19.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/06/8a84711162ad5a5f19a88cead37cca81b4b1f294f46260ef7334ae4f24d3/pydantic_core-2.41.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b69d1973354758007f46cf2d44a4f3d0933f10b6dc9bf15cf1356e037f6f731a", size = 2316840, upload-time = "2025-10-14T10:23:21.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/8b/b7bb512a4682a2f7fbfae152a755d37351743900226d29bd953aaf870eaa/pydantic_core-2.41.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3619320641fd212aaf5997b6ca505e97540b7e16418f4a241f44cdf108ffb50d", size = 2149135, upload-time = "2025-10-14T10:23:24.379Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/7d/138e902ed6399b866f7cfe4435d22445e16fff888a1c00560d9dc79a780f/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:491535d45cd7ad7e4a2af4a5169b0d07bebf1adfd164b0368da8aa41e19907a5", size = 2104721, upload-time = "2025-10-14T10:23:26.906Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/13/0525623cf94627f7b53b4c2034c81edc8491cbfc7c28d5447fa318791479/pydantic_core-2.41.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:54d86c0cada6aba4ec4c047d0e348cbad7063b87ae0f005d9f8c9ad04d4a92a2", size = 1931608, upload-time = "2025-10-14T10:23:29.306Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d6/f9/744bc98137d6ef0a233f808bfc9b18cf94624bf30836a18d3b05d08bf418/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca1124aced216b2500dc2609eade086d718e8249cb9696660ab447d50a758bd", size = 2132986, upload-time = "2025-10-14T10:23:32.057Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/17/c8/629e88920171173f6049386cc71f893dff03209a9ef32b4d2f7e7c264bcf/pydantic_core-2.41.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c9024169becccf0cb470ada03ee578d7348c119a0d42af3dcf9eda96e3a247c", size = 2187516, upload-time = "2025-10-14T10:23:34.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/0f/4f2734688d98488782218ca61bcc118329bf5de05bb7fe3adc7dd79b0b86/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:26895a4268ae5a2849269f4991cdc97236e4b9c010e51137becf25182daac405", size = 2146146, upload-time = "2025-10-14T10:23:37.342Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/f2/ab385dbd94a052c62224b99cf99002eee99dbec40e10006c78575aead256/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:ca4df25762cf71308c446e33c9b1fdca2923a3f13de616e2a949f38bf21ff5a8", size = 2311296, upload-time = "2025-10-14T10:23:40.145Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/8e/e4f12afe1beeb9823bba5375f8f258df0cc61b056b0195fb1cf9f62a1a58/pydantic_core-2.41.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:5a28fcedd762349519276c36634e71853b4541079cab4acaaac60c4421827308", size = 2315386, upload-time = "2025-10-14T10:23:42.624Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/f7/925f65d930802e3ea2eb4d5afa4cb8730c8dc0d2cb89a59dc4ed2fcb2d74/pydantic_core-2.41.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c173ddcd86afd2535e2b695217e82191580663a1d1928239f877f5a1649ef39f", size = 2147775, upload-time = "2025-10-14T10:23:45.406Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1083,14 +1300,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "typing-inspection"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -40,6 +40,7 @@ class Auth:
|
||||
Then the LangGraph server will load your auth file and run it server-side whenever a request comes in.
|
||||
|
||||
???+ example "Basic Usage"
|
||||
|
||||
```python
|
||||
from langgraph_sdk import Auth
|
||||
|
||||
@@ -76,6 +77,7 @@ class Auth:
|
||||
```
|
||||
|
||||
???+ note "Request Processing Flow"
|
||||
|
||||
1. Authentication (your `@auth.authenticate` handler) is performed first on **every request**
|
||||
2. For authorization, the most specific matching handler is called:
|
||||
* If a handler exists for the exact resource and action, it is used (e.g., `@auth.on.threads.create`)
|
||||
@@ -129,7 +131,9 @@ class Auth:
|
||||
- FilterType: Apply filtering rules to the response
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Global handler for all requests:
|
||||
|
||||
```python
|
||||
@auth.on
|
||||
async def reject_unhandled_requests(ctx: AuthContext, value: Any) -> None:
|
||||
@@ -139,6 +143,7 @@ class Auth:
|
||||
|
||||
Resource-specific handler. This would take precedence over the global handler
|
||||
for all actions on the `threads` resource:
|
||||
|
||||
```python
|
||||
@auth.on.threads
|
||||
async def check_thread_access(ctx: AuthContext, value: Any) -> bool:
|
||||
@@ -147,6 +152,7 @@ class Auth:
|
||||
```
|
||||
|
||||
Resource and action specific handler:
|
||||
|
||||
```python
|
||||
@auth.on.threads.delete
|
||||
async def prevent_thread_deletion(ctx: AuthContext, value: Any) -> bool:
|
||||
@@ -155,6 +161,7 @@ class Auth:
|
||||
```
|
||||
|
||||
Multiple resources or actions:
|
||||
|
||||
```python
|
||||
@auth.on(resources=["threads", "runs"], actions=["create", "update"])
|
||||
async def rate_limit_writes(ctx: AuthContext, value: Any) -> bool:
|
||||
@@ -163,7 +170,8 @@ class Auth:
|
||||
```
|
||||
|
||||
Auth for the `store` resource is a bit different since its structure is developer defined.
|
||||
You typically want to enforce user creds in the namespace. Y
|
||||
You typically want to enforce user creds in the namespace.
|
||||
|
||||
```python
|
||||
@auth.on.store
|
||||
async def check_store_access(ctx: AuthContext, value: Auth.types.on) -> bool:
|
||||
@@ -186,7 +194,6 @@ class Auth:
|
||||
by name:
|
||||
|
||||
- request (Request): The raw ASGI request object
|
||||
- body (dict): The parsed request body
|
||||
- path (str): The request path, e.g., "/threads/abcd-1234-abcd-1234/runs/abcd-1234-abcd-1234/stream"
|
||||
- method (str): The HTTP method, e.g., "GET"
|
||||
- path_params (dict[str, str]): URL path parameters, e.g., {"thread_id": "abcd-1234-abcd-1234", "run_id": "abcd-1234-abcd-1234"}
|
||||
@@ -209,7 +216,9 @@ class Auth:
|
||||
ValueError: If an authentication handler is already registered.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Basic token authentication:
|
||||
|
||||
```python
|
||||
@auth.authenticate
|
||||
async def authenticate(authorization: str) -> str:
|
||||
@@ -218,6 +227,7 @@ class Auth:
|
||||
```
|
||||
|
||||
Accept the full request context:
|
||||
|
||||
```python
|
||||
@auth.authenticate
|
||||
async def authenticate(
|
||||
@@ -230,6 +240,7 @@ class Auth:
|
||||
```
|
||||
|
||||
Return user name and permissions:
|
||||
|
||||
```python
|
||||
@auth.authenticate
|
||||
async def authenticate(
|
||||
@@ -248,7 +259,7 @@ class Auth:
|
||||
"""
|
||||
if self._authenticate_handler is not None:
|
||||
raise ValueError(
|
||||
"Authentication handler already set as {self._authenticate_handler}."
|
||||
f"Authentication handler already set as {self._authenticate_handler}."
|
||||
)
|
||||
self._authenticate_handler = fn
|
||||
return fn
|
||||
@@ -562,6 +573,7 @@ class _On:
|
||||
???+ example "Examples"
|
||||
|
||||
Global handler for all requests:
|
||||
|
||||
```python
|
||||
@auth.on
|
||||
async def log_all_requests(ctx: AuthContext, value: Any) -> None:
|
||||
@@ -570,6 +582,7 @@ class _On:
|
||||
```
|
||||
|
||||
Resource-specific handler:
|
||||
|
||||
```python
|
||||
@auth.on.threads
|
||||
async def check_thread_access(ctx: AuthContext, value: Any) -> bool:
|
||||
@@ -578,6 +591,7 @@ class _On:
|
||||
```
|
||||
|
||||
Resource and action specific handler:
|
||||
|
||||
```python
|
||||
@auth.on.threads.delete
|
||||
async def prevent_thread_deletion(ctx: AuthContext, value: Any) -> bool:
|
||||
@@ -586,6 +600,7 @@ class _On:
|
||||
```
|
||||
|
||||
Multiple resources or actions:
|
||||
|
||||
```python
|
||||
@auth.on(resources=["threads", "runs"], actions=["create", "update"])
|
||||
async def rate_limit_writes(ctx: AuthContext, value: Any) -> bool:
|
||||
|
||||
@@ -76,27 +76,33 @@ Subset containment is only supported by newer versions of the LangGraph dev serv
|
||||
install langgraph-runtime-inmem >= 0.14.1 to use this filter variant.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Simple exact match filter for the resource owner:
|
||||
|
||||
```python
|
||||
filter = {"owner": "user-abcd123"}
|
||||
```
|
||||
|
||||
Explicit version of the exact match filter:
|
||||
|
||||
```python
|
||||
filter = {"owner": {"$eq": "user-abcd123"}}
|
||||
```
|
||||
|
||||
|
||||
Containment (membership of a single element):
|
||||
|
||||
```python
|
||||
filter = {"participants": {"$contains": "user-abcd123"}}
|
||||
```
|
||||
|
||||
Containment (subset containment; all values must be present, but order doesn't matter):
|
||||
|
||||
```python
|
||||
filter = {"participants": {"$contains": ["user-abcd123", "user-efgh456"]}}
|
||||
```
|
||||
|
||||
Combining filters (treated as a logical `AND`):
|
||||
|
||||
```python
|
||||
filter = {"owner": "user-abcd123", "participants": {"$contains": "user-efgh456"}}
|
||||
```
|
||||
@@ -119,6 +125,7 @@ Allows storing custom key-value pairs with any entity.
|
||||
Keys must be strings, values can be any JSON-serializable type.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
metadata = {
|
||||
"created_by": "user123",
|
||||
@@ -225,6 +232,7 @@ class StudioUser:
|
||||
for developers accessing the instance from the LangGraph Studio UI.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
@auth.on
|
||||
async def allow_developers(ctx: Auth.types.AuthContext, value: Any) -> None:
|
||||
@@ -293,7 +301,9 @@ Parameters:
|
||||
authorization (str | None): The Authorization header value (e.g. "Bearer <token>")
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
Basic authentication with token:
|
||||
|
||||
```python
|
||||
from langgraph_sdk import Auth
|
||||
|
||||
@@ -305,6 +315,7 @@ Parameters:
|
||||
```
|
||||
|
||||
Authentication with multiple parameters:
|
||||
|
||||
```
|
||||
@auth.authenticate
|
||||
async def authenticate2(
|
||||
@@ -318,6 +329,7 @@ Parameters:
|
||||
```
|
||||
|
||||
Accepting the raw ASGI request:
|
||||
|
||||
```python
|
||||
MY_SECRET = "my-secret-key"
|
||||
@auth.authenticate
|
||||
@@ -423,6 +435,7 @@ class ThreadsCreate(typing.TypedDict, total=False):
|
||||
"""Parameters for creating a new thread.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
create_params = {
|
||||
"thread_id": UUID("123e4567-e89b-12d3-a456-426614174000"),
|
||||
@@ -522,6 +535,7 @@ class RunsCreate(typing.TypedDict, total=False):
|
||||
"""Payload for creating a run.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
create_params = {
|
||||
"assistant_id": UUID("123e4567-e89b-12d3-a456-426614174000"),
|
||||
@@ -577,6 +591,7 @@ class AssistantsCreate(typing.TypedDict, total=False):
|
||||
"""Payload for creating an assistant.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
create_params = {
|
||||
"assistant_id": UUID("123e4567-e89b-12d3-a456-426614174000"),
|
||||
@@ -615,6 +630,7 @@ class AssistantsRead(typing.TypedDict, total=False):
|
||||
"""Payload for reading an assistant.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
read_params = {
|
||||
"assistant_id": UUID("123e4567-e89b-12d3-a456-426614174000"),
|
||||
@@ -634,6 +650,7 @@ class AssistantsUpdate(typing.TypedDict, total=False):
|
||||
"""Payload for updating an assistant.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
update_params = {
|
||||
"assistant_id": UUID("123e4567-e89b-12d3-a456-426614174000"),
|
||||
@@ -673,6 +690,7 @@ class AssistantsDelete(typing.TypedDict):
|
||||
"""Payload for deleting an assistant.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
delete_params = {
|
||||
"assistant_id": UUID("123e4567-e89b-12d3-a456-426614174000")
|
||||
@@ -688,6 +706,7 @@ class AssistantsSearch(typing.TypedDict):
|
||||
"""Payload for searching assistants.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
search_params = {
|
||||
"graph_id": "graph123",
|
||||
@@ -715,6 +734,7 @@ class CronsCreate(typing.TypedDict, total=False):
|
||||
"""Payload for creating a cron job.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
create_params = {
|
||||
"payload": {"key": "value"},
|
||||
@@ -750,6 +770,7 @@ class CronsDelete(typing.TypedDict):
|
||||
"""Payload for deleting a cron job.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
delete_params = {
|
||||
"cron_id": UUID("123e4567-e89b-12d3-a456-426614174000")
|
||||
@@ -765,6 +786,7 @@ class CronsRead(typing.TypedDict):
|
||||
"""Payload for reading a cron job.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
read_params = {
|
||||
"cron_id": UUID("123e4567-e89b-12d3-a456-426614174000")
|
||||
@@ -780,6 +802,7 @@ class CronsUpdate(typing.TypedDict, total=False):
|
||||
"""Payload for updating a cron job.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
update_params = {
|
||||
"cron_id": UUID("123e4567-e89b-12d3-a456-426614174000"),
|
||||
@@ -803,6 +826,7 @@ class CronsSearch(typing.TypedDict, total=False):
|
||||
"""Payload for searching cron jobs.
|
||||
|
||||
???+ example "Examples"
|
||||
|
||||
```python
|
||||
search_params = {
|
||||
"assistant_id": UUID("123e4567-e89b-12d3-a456-426614174000"),
|
||||
@@ -888,7 +912,7 @@ class StorePut(typing.TypedDict):
|
||||
"""Unique identifier for the item within its namespace."""
|
||||
|
||||
value: dict[str, typing.Any] | None
|
||||
"""The data to store, or None to mark the item for deletion."""
|
||||
"""The data to store, or `None` to mark the item for deletion."""
|
||||
|
||||
index: typing.Literal[False] | list[str] | None
|
||||
"""Optional index configuration for full-text search."""
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""The LangGraph client implementations connect to the LangGraph API.
|
||||
|
||||
This module provides both asynchronous ([get_client(url="http://localhost:2024"))](#get_client) or [LangGraphClient](#LangGraphClient))
|
||||
and synchronous ([get_sync_client(url="http://localhost:2024"))](#get_sync_client) or [SyncLanggraphClient](#SyncLanggraphClient))
|
||||
clients to interacting with the LangGraph API's core resources such as
|
||||
Assistants, Threads, Runs, and Cron jobs, as well as its persistent
|
||||
document Store.
|
||||
""" # noqa: E501
|
||||
This module provides both asynchronous (`get_client(url="http://localhost:2024")` or
|
||||
`LangGraphClient`) and synchronous (`get_sync_client(url="http://localhost:2024")` or
|
||||
`SyncLanggraphClient`) clients to interacting with the LangGraph API's core resources
|
||||
such as Assistants, Threads, Runs, and Cron jobs, as well as its persistent document
|
||||
Store.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -304,7 +304,7 @@ class HttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a GET request."""
|
||||
"""Send a `GET` request."""
|
||||
r = await self.client.get(path, params=params, headers=headers)
|
||||
if on_response:
|
||||
on_response(r)
|
||||
@@ -320,7 +320,7 @@ class HttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a POST request."""
|
||||
"""Send a `POST` request."""
|
||||
if json is not None:
|
||||
request_headers, content = await _aencode_json(json)
|
||||
else:
|
||||
@@ -345,7 +345,7 @@ class HttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a PUT request."""
|
||||
"""Send a `PUT` request."""
|
||||
request_headers, content = await _aencode_json(json)
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
@@ -366,7 +366,7 @@ class HttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a PATCH request."""
|
||||
"""Send a `PATCH` request."""
|
||||
request_headers, content = await _aencode_json(json)
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
@@ -387,7 +387,7 @@ class HttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> None:
|
||||
"""Send a DELETE request."""
|
||||
"""Send a `DELETE` request."""
|
||||
r = await self.client.request(
|
||||
"DELETE", path, json=json, params=params, headers=headers
|
||||
)
|
||||
@@ -950,7 +950,7 @@ class AssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Assistant: The updated assistant.
|
||||
The updated assistant.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1000,7 +1000,7 @@ class AssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1043,7 +1043,7 @@ class AssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Assistant]: A list of assistants.
|
||||
A list of assistants.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1127,7 +1127,7 @@ class AssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[AssistantVersion]: A list of assistant versions.
|
||||
A list of assistant versions.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1169,7 +1169,7 @@ class AssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Assistant: Assistant Object.
|
||||
Assistant Object.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1226,7 +1226,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Thread: Thread object.
|
||||
Thread object.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1285,7 +1285,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Thread: The created thread.
|
||||
The created thread.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1353,7 +1353,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Thread: The created thread.
|
||||
The created thread.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1394,7 +1394,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1439,7 +1439,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Thread]: List of the threads matching the search parameters.
|
||||
List of the threads matching the search parameters.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1526,7 +1526,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1563,7 +1563,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
ThreadState: the thread of the state.
|
||||
The thread of the state.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1701,7 +1701,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
ThreadUpdateStateResponse: Response after updating a thread's state.
|
||||
Response after updating a thread's state.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1764,7 +1764,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[ThreadState]: the state history of the thread.
|
||||
The state history of the thread.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1811,7 +1811,7 @@ class ThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Iterator[StreamPart]: An iterator of stream parts.
|
||||
An iterator of stream parts.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -1987,7 +1987,7 @@ class RunsClient:
|
||||
"exit" means checkpoints are only persisted when the run exits, does not save intermediate steps
|
||||
|
||||
Returns:
|
||||
AsyncIterator[StreamPart]: Asynchronous iterator of stream results.
|
||||
Asynchronous iterator of stream results.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2193,7 +2193,7 @@ class RunsClient:
|
||||
"exit" means checkpoints are only persisted when the run exits, does not save intermediate steps
|
||||
|
||||
Returns:
|
||||
Run: The created background run.
|
||||
The created background run.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2443,7 +2443,7 @@ class RunsClient:
|
||||
"exit" means checkpoints are only persisted when the run exits, does not save intermediate steps
|
||||
|
||||
Returns:
|
||||
Union[list[dict], dict[str, Any]]: The output of the run.
|
||||
The output of the run.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2572,7 +2572,7 @@ class RunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Run]: The runs for the thread.
|
||||
The runs for the thread.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2617,7 +2617,7 @@ class RunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Run: Run object.
|
||||
`Run` object.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2657,7 +2657,7 @@ class RunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2710,7 +2710,7 @@ class RunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2757,7 +2757,7 @@ class RunsClient:
|
||||
last_event_id: The last event ID to use for the stream.
|
||||
|
||||
Returns:
|
||||
AsyncIterator[StreamPart]: The stream of parts.
|
||||
The stream of parts.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2806,7 +2806,7 @@ class RunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2843,6 +2843,7 @@ class CronClient:
|
||||
```
|
||||
|
||||
!!! note "Feature Availability"
|
||||
|
||||
The crons client functionality is not supported on all licenses.
|
||||
Please check the relevant license documentation for the most up-to-date
|
||||
details on feature availability.
|
||||
@@ -2893,7 +2894,7 @@ class CronClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Run: The cron run.
|
||||
The cron run.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -2973,7 +2974,7 @@ class CronClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Run: The cron run.
|
||||
The cron run.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3027,7 +3028,7 @@ class CronClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3065,7 +3066,7 @@ class CronClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Cron]: The list of cron jobs returned by the search,
|
||||
The list of cron jobs returned by the search,
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3191,7 +3192,7 @@ class StoreClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3294,7 +3295,7 @@ class StoreClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3338,7 +3339,7 @@ class StoreClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Item]: A list of items matching the search criteria.
|
||||
A list of items matching the search criteria.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3411,7 +3412,7 @@ class StoreClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[list[str]]: A list of namespaces matching the criteria.
|
||||
A list of namespaces matching the criteria.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3568,7 +3569,7 @@ class SyncHttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a GET request."""
|
||||
"""Send a `GET` request."""
|
||||
r = self.client.get(path, params=params, headers=headers)
|
||||
if on_response:
|
||||
on_response(r)
|
||||
@@ -3584,7 +3585,7 @@ class SyncHttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a POST request."""
|
||||
"""Send a `POST` request."""
|
||||
if json is not None:
|
||||
request_headers, content = _encode_json(json)
|
||||
else:
|
||||
@@ -3608,7 +3609,7 @@ class SyncHttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a PUT request."""
|
||||
"""Send a `PUT` request."""
|
||||
request_headers, content = _encode_json(json)
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
@@ -3630,7 +3631,7 @@ class SyncHttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> Any:
|
||||
"""Send a PATCH request."""
|
||||
"""Send a `PATCH` request."""
|
||||
request_headers, content = _encode_json(json)
|
||||
if headers:
|
||||
request_headers.update(headers)
|
||||
@@ -3651,7 +3652,7 @@ class SyncHttpClient:
|
||||
headers: Mapping[str, str] | None = None,
|
||||
on_response: Callable[[httpx.Response], None] | None = None,
|
||||
) -> None:
|
||||
"""Send a DELETE request."""
|
||||
"""Send a `DELETE` request."""
|
||||
r = self.client.request(
|
||||
"DELETE", path, json=json, params=params, headers=headers
|
||||
)
|
||||
@@ -3828,7 +3829,7 @@ class SyncAssistantsClient:
|
||||
|
||||
This class provides methods to interact with assistants, which are versioned configurations of your graph.
|
||||
|
||||
???+ example "Examples"
|
||||
???+ example "Example"
|
||||
|
||||
```python
|
||||
client = get_sync_client(url="http://localhost:2024")
|
||||
@@ -3854,7 +3855,7 @@ class SyncAssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Assistant: Assistant Object.
|
||||
`Assistant` Object.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3901,7 +3902,7 @@ class SyncAssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Graph: The graph information for the assistant in JSON format.
|
||||
The graph information for the assistant in JSON format.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -3954,7 +3955,7 @@ class SyncAssistantsClient:
|
||||
Returns:
|
||||
GraphSchema: The graph schema for the assistant.
|
||||
|
||||
???+ example " Example Usage"
|
||||
???+ example "Example Usage"
|
||||
|
||||
```python
|
||||
client = get_sync_client(url="http://localhost:2024")
|
||||
@@ -4140,7 +4141,7 @@ class SyncAssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Assistant: The created assistant.
|
||||
The created assistant.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4208,7 +4209,7 @@ class SyncAssistantsClient:
|
||||
The description field is available for langgraph-api server version>=0.0.45
|
||||
|
||||
Returns:
|
||||
Assistant: The updated assistant.
|
||||
The updated assistant.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4257,7 +4258,7 @@ class SyncAssistantsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4295,7 +4296,7 @@ class SyncAssistantsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Assistant]: A list of assistants.
|
||||
A list of assistants.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4378,7 +4379,7 @@ class SyncAssistantsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Assistant]: A list of assistants.
|
||||
A list of assistants.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4420,7 +4421,7 @@ class SyncAssistantsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
Assistant: Assistant Object.
|
||||
`Assistant` Object.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4475,7 +4476,7 @@ class SyncThreadsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
Thread: Thread object.
|
||||
`Thread` object.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4530,7 +4531,7 @@ class SyncThreadsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
Thread: The created thread.
|
||||
The created `Thread`.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4597,7 +4598,7 @@ class SyncThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Thread: The created thread.
|
||||
The created `Thread`.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4638,7 +4639,7 @@ class SyncThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4679,7 +4680,7 @@ class SyncThreadsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Thread]: List of the threads matching the search parameters.
|
||||
List of the threads matching the search parameters.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4762,7 +4763,7 @@ class SyncThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4797,7 +4798,7 @@ class SyncThreadsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
ThreadState: the thread of the state.
|
||||
The thread of the state.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4934,7 +4935,7 @@ class SyncThreadsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
ThreadUpdateStateResponse: Response after updating a thread's state.
|
||||
Response after updating a thread's state.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -4995,7 +4996,7 @@ class SyncThreadsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
list[ThreadState]: the state history of the thread.
|
||||
The state history of the `Thread`.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5044,7 +5045,7 @@ class SyncThreadsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
Iterator[StreamPart]: An iterator of stream parts.
|
||||
An iterator of stream parts.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5221,7 +5222,7 @@ class SyncRunsClient:
|
||||
|
||||
|
||||
Returns:
|
||||
Iterator[StreamPart]: Iterator of stream results.
|
||||
Iterator of stream results.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5423,7 +5424,7 @@ class SyncRunsClient:
|
||||
"exit" means checkpoints are only persisted when the run exits, does not save intermediate steps
|
||||
|
||||
Returns:
|
||||
Run: The created background run.
|
||||
The created background `Run`.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5674,7 +5675,7 @@ class SyncRunsClient:
|
||||
"exit" means checkpoints are only persisted when the run exits, does not save intermediate steps
|
||||
|
||||
Returns:
|
||||
Union[list[dict], dict[str, Any]]: The output of the run.
|
||||
The output of the `Run`.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5794,7 +5795,7 @@ class SyncRunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Run]: The runs for the thread.
|
||||
The runs for the thread.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5835,7 +5836,7 @@ class SyncRunsClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
Run: Run object.
|
||||
`Run` object.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5874,7 +5875,7 @@ class SyncRunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5927,7 +5928,7 @@ class SyncRunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -5974,7 +5975,7 @@ class SyncRunsClient:
|
||||
last_event_id: The last event ID to use for the stream.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6022,7 +6023,7 @@ class SyncRunsClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6053,6 +6054,7 @@ class SyncCronClient:
|
||||
```
|
||||
|
||||
!!! note "Feature Availability"
|
||||
|
||||
The crons client functionality is not supported on all licenses.
|
||||
Please check the relevant license documentation for the most up-to-date
|
||||
details on feature availability.
|
||||
@@ -6100,7 +6102,7 @@ class SyncCronClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
Run: The cron run.
|
||||
The cron `Run`.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6178,7 +6180,7 @@ class SyncCronClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
Run: The cron run.
|
||||
The cron `Run`.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6232,7 +6234,7 @@ class SyncCronClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6269,7 +6271,7 @@ class SyncCronClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Cron]: The list of cron jobs returned by the search,
|
||||
The list of cron jobs returned by the search,
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6394,7 +6396,7 @@ class SyncStoreClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6442,7 +6444,7 @@ class SyncStoreClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
Item: The retrieved item.
|
||||
The retrieved item.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6497,7 +6499,7 @@ class SyncStoreClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
None
|
||||
`None`
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6541,7 +6543,7 @@ class SyncStoreClient:
|
||||
params: Optional query parameters to include with the request.
|
||||
|
||||
Returns:
|
||||
list[Item]: A list of items matching the search criteria.
|
||||
A list of items matching the search criteria.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
@@ -6612,7 +6614,7 @@ class SyncStoreClient:
|
||||
headers: Optional custom headers to include with the request.
|
||||
|
||||
Returns:
|
||||
list[list[str]]: A list of namespaces matching the criteria.
|
||||
A list of namespaces matching the criteria.
|
||||
|
||||
???+ example "Example Usage"
|
||||
|
||||
|
||||
@@ -20,18 +20,27 @@ dependencies = [
|
||||
path = "langgraph_sdk/__init__.py"
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://www.github.com/langchain-ai/langgraph"
|
||||
Source = "https://github.com/langchain-ai/langgraph/tree/main/libs/sdk-py"
|
||||
Twitter = "https://x.com/LangChainAI"
|
||||
Slack = "https://www.langchain.com/join-community"
|
||||
Reddit = "https://www.reddit.com/r/LangChain/"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
test = [
|
||||
"pytest",
|
||||
"pytest-asyncio",
|
||||
"pytest-mock",
|
||||
"pytest-watch",
|
||||
]
|
||||
lint = [
|
||||
"ruff",
|
||||
"codespell",
|
||||
"mypy",
|
||||
]
|
||||
dev = [
|
||||
{include-group = "test"},
|
||||
{include-group = "lint"},
|
||||
]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
include = ["langgraph_sdk"]
|
||||
|
||||
Generated
+22
@@ -144,6 +144,17 @@ dev = [
|
||||
{ name = "pytest-watch" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watch" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
@@ -161,6 +172,17 @@ dev = [
|
||||
{ name = "pytest-watch" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
lint = [
|
||||
{ name = "codespell" },
|
||||
{ name = "mypy" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
test = [
|
||||
{ name = "pytest" },
|
||||
{ name = "pytest-asyncio" },
|
||||
{ name = "pytest-mock" },
|
||||
{ name = "pytest-watch" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user