From f72d2cb12d01d6be169e69b7bfaada778952ffab Mon Sep 17 00:00:00 2001 From: "Paul S. Schweigert" Date: Thu, 30 Jan 2025 12:18:00 -0500 Subject: [PATCH] move bee_hive to root level Signed-off-by: Paul S. Schweigert --- .github/workflows/tests.yaml | 2 - bee-hive/Dockerfile => Dockerfile | 0 README.md | 144 +- bee-hive/bee-hive.sh => bee-hive.sh | 0 bee-hive/.python-version | 1 - bee-hive/README.md | 108 - bee-hive/beeAI => beeAI | 0 {bee-hive/bee_hive => bee_hive}/__init__.py | 0 {bee-hive/bee_hive => bee_hive}/agent.py | 0 .../bee_hive => bee_hive}/agent_factory.py | 0 .../bee_hive => bee_hive}/agent_schema.json | 0 .../bee_hive => bee_hive}/agent_store.json | 0 {bee-hive/bee_hive => bee_hive}/bee_agent.py | 0 .../bee_hive => bee_hive}/create_agents.py | 0 .../bee_hive => bee_hive}/crewai_agent.py | 0 {bee-hive/bee_hive => bee_hive}/interface.py | 0 .../bee_hive => bee_hive}/run_workflow.py | 0 {bee-hive/bee_hive => bee_hive}/step.py | 0 {bee-hive/bee_hive => bee_hive}/workflow.py | 0 {bee-hive/cli => cli}/__init__.py | 0 {bee-hive/cli => cli}/beeAI.py | 0 {bee-hive/cli => cli}/cli.py | 0 {bee-hive/cli => cli}/commands.py | 0 {bee-hive/cli => cli}/common.py | 0 docs/README.md | 67 - docs/assets/Bee_Dark.svg | 16 - docs/assets/components.png | Bin 231474 -> 0 bytes ...ramework.bee_agent_module_documentation.md | 59 - docs/framework.llms_module_documentation.md | 64 - docs/framework.memory_module_documentation.md | 63 - ...m_architecture_and_key_design_decisions.md | 54 - docs/framework.tools_module_documentation.md | 59 - .../hive.high-level_component_interactions.md | 45 - bee-hive/entrypoint.sh => entrypoint.sh | 0 examples/bee-hive/weather-checker/README.md | 19 - examples/bee-hive/weather-checker/agents.yaml | 28 - examples/bee-hive/weather-checker/example.env | 6 - examples/bee-hive/weather-checker/hive | 7 - .../bee-hive/weather-checker/workflow.yaml | 18 - examples/bee_agent/agents/README.md | 8 - examples/bee_agent/agents/bee.py | 166 -- examples/bee_agent/agents/bee_advanced.py | 214 -- examples/bee_agent/agents/requirements.txt | 2 - examples/bee_agent/basic.py | 7 - examples/bee_agent/llms.py | 43 - examples/bee_agent/memory/agentMemory.py | 72 - examples/bee_agent/memory/slidingMemory.py | 57 - examples/bee_agent/memory/summarizeMemory.py | 48 - examples/bee_agent/memory/tokenMemory.py | 68 - .../bee_agent/memory/unconstrainedMemory.py | 34 - examples/bee_agent/requirements.txt | 2 - examples/bee_agent/tools/weather.py | 8 - framework/bee-py/README.md | 129 - framework/bee-py/bee_agent/__init__.py | 31 - framework/bee-py/bee_agent/agents/__init__.py | 4 - framework/bee-py/bee_agent/agents/agent.py | 230 -- framework/bee-py/bee_agent/agents/runner.py | 24 - framework/bee-py/bee_agent/llms/__init__.py | 23 - .../bee-py/bee_agent/llms/base_output.py | 26 - framework/bee-py/bee_agent/llms/llm.py | 127 - framework/bee-py/bee_agent/llms/output.py | 30 - framework/bee-py/bee_agent/llms/prompt.py | 99 - framework/bee-py/bee_agent/memory/__init__.py | 36 - .../bee-py/bee_agent/memory/base_cache.py | 107 - .../bee-py/bee_agent/memory/base_memory.py | 88 - .../bee-py/bee_agent/memory/exceptions.py | 21 - .../bee-py/bee_agent/memory/file_cache.py | 238 -- framework/bee-py/bee_agent/memory/message.py | 112 - .../bee_agent/memory/readonly_memory.py | 35 - .../bee-py/bee_agent/memory/serializable.py | 102 - .../bee-py/bee_agent/memory/serializer.py | 263 -- .../bee-py/bee_agent/memory/sliding_cache.py | 116 - .../bee-py/bee_agent/memory/sliding_memory.py | 130 - .../bee_agent/memory/summarize_memory.py | 79 - framework/bee-py/bee_agent/memory/task_map.py | 148 -- .../bee-py/bee_agent/memory/token_memory.py | 129 - .../bee_agent/memory/unconstrained_cache.py | 160 -- .../bee_agent/memory/unconstrained_memory.py | 41 - framework/bee-py/bee_agent/tools/__init__.py | 5 - framework/bee-py/bee_agent/tools/mcp_tools.py | 73 - framework/bee-py/bee_agent/tools/tool.py | 42 - framework/bee-py/bee_agent/tools/weather.py | 84 - framework/bee-py/bee_agent/tools/wikipedia.py | 15 - framework/bee-py/bee_agent/utils/__init__.py | 7 - framework/bee-py/bee_agent/utils/config.py | 18 - .../bee-py/bee_agent/utils/custom_logger.py | 55 - framework/bee-py/bee_agent/utils/events.py | 49 - framework/bee-py/bee_agent/utils/roles.py | 22 - framework/bee-py/dev_tools/scripts.py | 35 - framework/bee-py/poetry.lock | 2308 ----------------- framework/bee-py/pyproject.toml | 50 - framework/bee-py/tests/__init__.py | 0 .../tests/bee_agent/tools/test_mcp_tool.py | 137 - framework/bee-py/tests/conftest.py | 8 - framework/bee-ts/README.md | 3 - bee-hive/pyproject.toml => pyproject.toml | 0 bee-hive/run_workflow.py => run_workflow.py | 0 {bee-hive/tests => tests}/__init__.py | 0 {bee-hive/tests => tests}/bee/__init__.py | 0 {bee-hive/tests => tests}/bee/agents.yaml | 0 {bee-hive/tests => tests}/bee/test_bee.py | 0 {bee-hive/tests => tests}/bee/workflow.yaml | 0 {bee-hive/tests => tests}/crewai/__init__.py | 0 {bee-hive/tests => tests}/crewai/agents.yaml | 0 .../tests => tests}/crewai/crew_dummy.py | 0 .../tests => tests}/crewai/test_crewai.py | 0 .../tests => tests}/crewai/workflow.yaml | 0 .../examples/condition_agents.yaml | 0 .../examples/condition_workflow.yaml | 0 {test => tests}/examples/test_condition.py | 2 +- .../schema/conditional_workflow.json | 0 .../schema/conditional_workflow.yml | 0 {test => tests}/schema/funnier_workflow.json | 0 {test => tests}/schema/funnier_workflow.yml | 0 {test => tests}/schema/simple_agent.json | 0 {test => tests}/schema/simple_agent.yml | 0 {test => tests}/schema/simple_workflow.json | 0 {test => tests}/schema/simple_workflow.yml | 0 .../tests => tests}/workflow/__init__.py | 0 .../tests => tests}/workflow/test_sequence.py | 0 .../tests => tests}/workflow/workflow.yaml | 0 121 files changed, 95 insertions(+), 6835 deletions(-) rename bee-hive/Dockerfile => Dockerfile (100%) rename bee-hive/bee-hive.sh => bee-hive.sh (100%) delete mode 100644 bee-hive/.python-version delete mode 100644 bee-hive/README.md rename bee-hive/beeAI => beeAI (100%) rename {bee-hive/bee_hive => bee_hive}/__init__.py (100%) rename {bee-hive/bee_hive => bee_hive}/agent.py (100%) rename {bee-hive/bee_hive => bee_hive}/agent_factory.py (100%) rename {bee-hive/bee_hive => bee_hive}/agent_schema.json (100%) rename {bee-hive/bee_hive => bee_hive}/agent_store.json (100%) rename {bee-hive/bee_hive => bee_hive}/bee_agent.py (100%) rename {bee-hive/bee_hive => bee_hive}/create_agents.py (100%) rename {bee-hive/bee_hive => bee_hive}/crewai_agent.py (100%) rename {bee-hive/bee_hive => bee_hive}/interface.py (100%) rename {bee-hive/bee_hive => bee_hive}/run_workflow.py (100%) rename {bee-hive/bee_hive => bee_hive}/step.py (100%) rename {bee-hive/bee_hive => bee_hive}/workflow.py (100%) rename {bee-hive/cli => cli}/__init__.py (100%) rename {bee-hive/cli => cli}/beeAI.py (100%) rename {bee-hive/cli => cli}/cli.py (100%) rename {bee-hive/cli => cli}/commands.py (100%) rename {bee-hive/cli => cli}/common.py (100%) delete mode 100644 docs/README.md delete mode 100644 docs/assets/Bee_Dark.svg delete mode 100644 docs/assets/components.png delete mode 100644 docs/framework.bee_agent_module_documentation.md delete mode 100644 docs/framework.llms_module_documentation.md delete mode 100644 docs/framework.memory_module_documentation.md delete mode 100644 docs/framework.system_architecture_and_key_design_decisions.md delete mode 100644 docs/framework.tools_module_documentation.md delete mode 100644 docs/hive.high-level_component_interactions.md rename bee-hive/entrypoint.sh => entrypoint.sh (100%) delete mode 100644 examples/bee-hive/weather-checker/README.md delete mode 100644 examples/bee-hive/weather-checker/agents.yaml delete mode 100644 examples/bee-hive/weather-checker/example.env delete mode 100755 examples/bee-hive/weather-checker/hive delete mode 100644 examples/bee-hive/weather-checker/workflow.yaml delete mode 100644 examples/bee_agent/agents/README.md delete mode 100644 examples/bee_agent/agents/bee.py delete mode 100644 examples/bee_agent/agents/bee_advanced.py delete mode 100644 examples/bee_agent/agents/requirements.txt delete mode 100644 examples/bee_agent/basic.py delete mode 100644 examples/bee_agent/llms.py delete mode 100644 examples/bee_agent/memory/agentMemory.py delete mode 100644 examples/bee_agent/memory/slidingMemory.py delete mode 100644 examples/bee_agent/memory/summarizeMemory.py delete mode 100644 examples/bee_agent/memory/tokenMemory.py delete mode 100644 examples/bee_agent/memory/unconstrainedMemory.py delete mode 100644 examples/bee_agent/requirements.txt delete mode 100644 examples/bee_agent/tools/weather.py delete mode 100644 framework/bee-py/README.md delete mode 100644 framework/bee-py/bee_agent/__init__.py delete mode 100644 framework/bee-py/bee_agent/agents/__init__.py delete mode 100644 framework/bee-py/bee_agent/agents/agent.py delete mode 100644 framework/bee-py/bee_agent/agents/runner.py delete mode 100644 framework/bee-py/bee_agent/llms/__init__.py delete mode 100644 framework/bee-py/bee_agent/llms/base_output.py delete mode 100644 framework/bee-py/bee_agent/llms/llm.py delete mode 100644 framework/bee-py/bee_agent/llms/output.py delete mode 100644 framework/bee-py/bee_agent/llms/prompt.py delete mode 100644 framework/bee-py/bee_agent/memory/__init__.py delete mode 100644 framework/bee-py/bee_agent/memory/base_cache.py delete mode 100644 framework/bee-py/bee_agent/memory/base_memory.py delete mode 100644 framework/bee-py/bee_agent/memory/exceptions.py delete mode 100644 framework/bee-py/bee_agent/memory/file_cache.py delete mode 100644 framework/bee-py/bee_agent/memory/message.py delete mode 100644 framework/bee-py/bee_agent/memory/readonly_memory.py delete mode 100644 framework/bee-py/bee_agent/memory/serializable.py delete mode 100644 framework/bee-py/bee_agent/memory/serializer.py delete mode 100644 framework/bee-py/bee_agent/memory/sliding_cache.py delete mode 100644 framework/bee-py/bee_agent/memory/sliding_memory.py delete mode 100644 framework/bee-py/bee_agent/memory/summarize_memory.py delete mode 100644 framework/bee-py/bee_agent/memory/task_map.py delete mode 100644 framework/bee-py/bee_agent/memory/token_memory.py delete mode 100644 framework/bee-py/bee_agent/memory/unconstrained_cache.py delete mode 100644 framework/bee-py/bee_agent/memory/unconstrained_memory.py delete mode 100644 framework/bee-py/bee_agent/tools/__init__.py delete mode 100644 framework/bee-py/bee_agent/tools/mcp_tools.py delete mode 100644 framework/bee-py/bee_agent/tools/tool.py delete mode 100644 framework/bee-py/bee_agent/tools/weather.py delete mode 100644 framework/bee-py/bee_agent/tools/wikipedia.py delete mode 100644 framework/bee-py/bee_agent/utils/__init__.py delete mode 100644 framework/bee-py/bee_agent/utils/config.py delete mode 100644 framework/bee-py/bee_agent/utils/custom_logger.py delete mode 100644 framework/bee-py/bee_agent/utils/events.py delete mode 100644 framework/bee-py/bee_agent/utils/roles.py delete mode 100644 framework/bee-py/dev_tools/scripts.py delete mode 100644 framework/bee-py/poetry.lock delete mode 100644 framework/bee-py/pyproject.toml delete mode 100644 framework/bee-py/tests/__init__.py delete mode 100644 framework/bee-py/tests/bee_agent/tools/test_mcp_tool.py delete mode 100644 framework/bee-py/tests/conftest.py delete mode 100644 framework/bee-ts/README.md rename bee-hive/pyproject.toml => pyproject.toml (100%) rename bee-hive/run_workflow.py => run_workflow.py (100%) rename {bee-hive/tests => tests}/__init__.py (100%) rename {bee-hive/tests => tests}/bee/__init__.py (100%) rename {bee-hive/tests => tests}/bee/agents.yaml (100%) rename {bee-hive/tests => tests}/bee/test_bee.py (100%) rename {bee-hive/tests => tests}/bee/workflow.yaml (100%) rename {bee-hive/tests => tests}/crewai/__init__.py (100%) rename {bee-hive/tests => tests}/crewai/agents.yaml (100%) rename {bee-hive/tests => tests}/crewai/crew_dummy.py (100%) rename {bee-hive/tests => tests}/crewai/test_crewai.py (100%) rename {bee-hive/tests => tests}/crewai/workflow.yaml (100%) rename {test => tests}/examples/condition_agents.yaml (100%) rename {test => tests}/examples/condition_workflow.yaml (100%) rename {test => tests}/examples/test_condition.py (94%) rename {test => tests}/schema/conditional_workflow.json (100%) rename {test => tests}/schema/conditional_workflow.yml (100%) rename {test => tests}/schema/funnier_workflow.json (100%) rename {test => tests}/schema/funnier_workflow.yml (100%) rename {test => tests}/schema/simple_agent.json (100%) rename {test => tests}/schema/simple_agent.yml (100%) rename {test => tests}/schema/simple_workflow.json (100%) rename {test => tests}/schema/simple_workflow.yml (100%) rename {bee-hive/tests => tests}/workflow/__init__.py (100%) rename {bee-hive/tests => tests}/workflow/test_sequence.py (100%) rename {bee-hive/tests => tests}/workflow/workflow.yaml (100%) diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 1766da0..804cacc 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -23,10 +23,8 @@ jobs: poetry self add poetry-plugin-shell - name: Install dependencies run: | - cd bee-hive poetry install - name: Run unit tests run: | - cd bee-hive poetry run pytest diff --git a/bee-hive/Dockerfile b/Dockerfile similarity index 100% rename from bee-hive/Dockerfile rename to Dockerfile diff --git a/README.md b/README.md index 3b8d783..eed025f 100644 --- a/README.md +++ b/README.md @@ -3,62 +3,106 @@ # Bee Hive -## Overview +A multi-agent platform with the vision to facilitate deploy and run Bee agents. -**Bee Hive** is a multi-agent platform designed to build, deploy, and serve powerful agentic workflows at scale. This repository contains implementations for both [TypeScript](https://github.com/i-am-bee/bee-agent-framework) and [Python](https://github.com/i-am-bee/bee-hive/tree/main/framework/bee-py), enabling flexibility and interoperability for developers. The platform simplifies the creation and orchestration of AI agents powered by popular LLMs such as [Llama 3.x](https://ai.meta.com/blog/meta-llama-3-1/) and [IBM Granite](https://www.ibm.com/granite?adoper=255252_0_LS1). +In this initial version you are going to find some examples how run a group of agents, that you can build using current and more mature TypeScript [Bee Agent framework](https://github.com/i-am-bee/bee-agent-framework), or experiment with the new [Python version](../framework/bee-py). -## Key Features +## Usage -* **🔓 Open Platform**: Run and orchestrate agents seamlessly on an open platform designed for experimentation and scalability. +There are two steps to running a workflow: defining some agents and creating a workflow to run those agents. -* **🤖 Flexible Agent Framework**: Write and experiment with agent and tool building in a flexible and modular framework. +> Note: to run Bee Hive, you will need to [configure your local environment](#local-environment) -* **⛓️‍💥 Versatile Agent Orchestration Capabilities**: Design multi-agent workflows tailored to your specific needs. +### Agent Definition -* **✨ Optimized for Open-Source Models**: Achieve best-in-class performance against open-source models like IBM Granite and Llama 3.x +* You can define your Agent in a declarative way using a YAML file, where you can use the current Bee Agent implementation. With that, you can configure your agent or agents. For example, create an `agents.yaml` file containing the following: -## Modules - -This repository includes the following key modules: - -1. Bee Agent Framework - - 1.1 TypeScript - - The Typescript implementation of the Bee Agent Framework is available at: https://github.com/i-am-bee/bee-agent-framework - - 1.2 Python - - The Python implementation of the Bee Agent Framework is available at: https://github.com/i-am-bee/bee-hive/tree/main/framework/bee-py - -2. Bee Hive - - The Bee Hive module serves as a multi-agent platform for orchestrating workflows. It supports declarative agent definitions and YAML-based workflows. Refer to the Bee Hive [README](bee-hive/README.md) for detailed instructions. - -## Roadmap - -* **API 2.0**: a powerful and lightweight API to help you integrate your agents - -* **Dev UI**: build and optimize your agentic workflows in a developer-friendly UI - -* **Additional multi-agent workflows**: conditionals, looping, async, meta-agent orchestration - -* **Agent and tool library**: shareable assets to help you get started - -* **Streamlined experience**: integrate key developer functionality in one repository - -## Contributing - -We welcome contributions from the community! Please check our [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines and our [Code of Conduct](CODE_OF_CONDUCT.md) for standards of behavior. - -## Reporting Issues - -Report bugs or feature requests via [GitHub Issues](https://github.com/i-am-bee/bee-hive/issues/new). Ensure to check for duplicates before filing a new issue. - -## Legal Notice - -All content in this repository is provided by IBM under the associated open source software license. IBM is under no obligation to provide enhancements, updates, or support for this code. +```yaml +apiVersion: beehive/v1alpha1 +kind: Agent +metadata: + name: current-affairs + labels: + app: mas-example +spec: + model: meta-llama/llama-3-1-70b-instruct + description: Get the current weather + tools: + - code_interpreter + - weather + instructions: Get the current temperature for the location provided by the user. Return results in Fahrenheit. --- - -Happy coding with Bee Hive 🚀 +apiVersion: beehive/v1alpha1 +kind: Agent +metadata: + name: hot-or-not + labels: + app: mas-example +spec: + model: meta-llama/llama-3-1-70b-instruct + description: Is the current temperature hotter than usual? + tools: + - code_interpreter + - weather + instructions: The user will give you a temperature in Fahrenheit and a location. Use the OpenMateo weather tool to find the average monthly temperature for the location. Answer if the temperature provided by the user is hotter or colder than the average found by the tool. +``` + +* Create the agents by running the following command: + +```bash +python create_agents.py agents.yaml +``` + +### Running a Workflow + +#### Sequential + +* Define a workflow in YAML listing the agents you wish to run. For example, create a `workflow.yaml` file containing the following: + +```yaml +apiVersion: beehive/v1alpha1 +kind: Workflow +metadata: + name: beehive-deployment + labels: + app: mas-example +spec: + strategy: + type: sequence + output: verbose + template: + metadata: + labels: + app: mas-example + agents: + - name: current-affairs + - name: hot-or-not + prompt: New York +``` + +* Execute the workflow: + +```bash +python run_workflow workflow.yaml +``` + +## Local environment + +* Run a local instance of the [Bee Stack](https://github.com/i-am-bee/bee-stack) + +* Install dependencies: `poetry shell && poetry install` + +* Configure environmental variables: `cp example.env .env` + +### Run workflow in local environment with container runtime (e.g. podman) + +* Run a local instance of the [Bee Stack](https://github.com/i-am-bee/bee-stack) + +* Build bee-hive container image: `./bee-hive.sh build` in bee-hive/bee-hive directory + +* Prepare agent and workflow definition yaml files in the current directory (e.g. agent.yaml, workflow.yaml) + +* Run workflow: `./bee-hive.sh run $PWD agents.yaml workflow.yaml BEE_API=http://xxx.xxx.xxx.xxx:4000 BEE_API_KEY=sk-proj-testkey` + * The required environment variables can be provided at the end of command argunets (e.g. `BEE_API=http://192.168.86.45:4000`). + diff --git a/bee-hive/bee-hive.sh b/bee-hive.sh similarity index 100% rename from bee-hive/bee-hive.sh rename to bee-hive.sh diff --git a/bee-hive/.python-version b/bee-hive/.python-version deleted file mode 100644 index 04e2079..0000000 --- a/bee-hive/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.12.8 diff --git a/bee-hive/README.md b/bee-hive/README.md deleted file mode 100644 index eed025f..0000000 --- a/bee-hive/README.md +++ /dev/null @@ -1,108 +0,0 @@ -> [!WARNING] -> [PRE-Alpha] Please reach out if you want to get involved in the discussions. All feedback is welcomed - -# Bee Hive - -A multi-agent platform with the vision to facilitate deploy and run Bee agents. - -In this initial version you are going to find some examples how run a group of agents, that you can build using current and more mature TypeScript [Bee Agent framework](https://github.com/i-am-bee/bee-agent-framework), or experiment with the new [Python version](../framework/bee-py). - -## Usage - -There are two steps to running a workflow: defining some agents and creating a workflow to run those agents. - -> Note: to run Bee Hive, you will need to [configure your local environment](#local-environment) - -### Agent Definition - -* You can define your Agent in a declarative way using a YAML file, where you can use the current Bee Agent implementation. With that, you can configure your agent or agents. For example, create an `agents.yaml` file containing the following: - -```yaml -apiVersion: beehive/v1alpha1 -kind: Agent -metadata: - name: current-affairs - labels: - app: mas-example -spec: - model: meta-llama/llama-3-1-70b-instruct - description: Get the current weather - tools: - - code_interpreter - - weather - instructions: Get the current temperature for the location provided by the user. Return results in Fahrenheit. - ---- -apiVersion: beehive/v1alpha1 -kind: Agent -metadata: - name: hot-or-not - labels: - app: mas-example -spec: - model: meta-llama/llama-3-1-70b-instruct - description: Is the current temperature hotter than usual? - tools: - - code_interpreter - - weather - instructions: The user will give you a temperature in Fahrenheit and a location. Use the OpenMateo weather tool to find the average monthly temperature for the location. Answer if the temperature provided by the user is hotter or colder than the average found by the tool. -``` - -* Create the agents by running the following command: - -```bash -python create_agents.py agents.yaml -``` - -### Running a Workflow - -#### Sequential - -* Define a workflow in YAML listing the agents you wish to run. For example, create a `workflow.yaml` file containing the following: - -```yaml -apiVersion: beehive/v1alpha1 -kind: Workflow -metadata: - name: beehive-deployment - labels: - app: mas-example -spec: - strategy: - type: sequence - output: verbose - template: - metadata: - labels: - app: mas-example - agents: - - name: current-affairs - - name: hot-or-not - prompt: New York -``` - -* Execute the workflow: - -```bash -python run_workflow workflow.yaml -``` - -## Local environment - -* Run a local instance of the [Bee Stack](https://github.com/i-am-bee/bee-stack) - -* Install dependencies: `poetry shell && poetry install` - -* Configure environmental variables: `cp example.env .env` - -### Run workflow in local environment with container runtime (e.g. podman) - -* Run a local instance of the [Bee Stack](https://github.com/i-am-bee/bee-stack) - -* Build bee-hive container image: `./bee-hive.sh build` in bee-hive/bee-hive directory - -* Prepare agent and workflow definition yaml files in the current directory (e.g. agent.yaml, workflow.yaml) - -* Run workflow: `./bee-hive.sh run $PWD agents.yaml workflow.yaml BEE_API=http://xxx.xxx.xxx.xxx:4000 BEE_API_KEY=sk-proj-testkey` - * The required environment variables can be provided at the end of command argunets (e.g. `BEE_API=http://192.168.86.45:4000`). - diff --git a/bee-hive/beeAI b/beeAI similarity index 100% rename from bee-hive/beeAI rename to beeAI diff --git a/bee-hive/bee_hive/__init__.py b/bee_hive/__init__.py similarity index 100% rename from bee-hive/bee_hive/__init__.py rename to bee_hive/__init__.py diff --git a/bee-hive/bee_hive/agent.py b/bee_hive/agent.py similarity index 100% rename from bee-hive/bee_hive/agent.py rename to bee_hive/agent.py diff --git a/bee-hive/bee_hive/agent_factory.py b/bee_hive/agent_factory.py similarity index 100% rename from bee-hive/bee_hive/agent_factory.py rename to bee_hive/agent_factory.py diff --git a/bee-hive/bee_hive/agent_schema.json b/bee_hive/agent_schema.json similarity index 100% rename from bee-hive/bee_hive/agent_schema.json rename to bee_hive/agent_schema.json diff --git a/bee-hive/bee_hive/agent_store.json b/bee_hive/agent_store.json similarity index 100% rename from bee-hive/bee_hive/agent_store.json rename to bee_hive/agent_store.json diff --git a/bee-hive/bee_hive/bee_agent.py b/bee_hive/bee_agent.py similarity index 100% rename from bee-hive/bee_hive/bee_agent.py rename to bee_hive/bee_agent.py diff --git a/bee-hive/bee_hive/create_agents.py b/bee_hive/create_agents.py similarity index 100% rename from bee-hive/bee_hive/create_agents.py rename to bee_hive/create_agents.py diff --git a/bee-hive/bee_hive/crewai_agent.py b/bee_hive/crewai_agent.py similarity index 100% rename from bee-hive/bee_hive/crewai_agent.py rename to bee_hive/crewai_agent.py diff --git a/bee-hive/bee_hive/interface.py b/bee_hive/interface.py similarity index 100% rename from bee-hive/bee_hive/interface.py rename to bee_hive/interface.py diff --git a/bee-hive/bee_hive/run_workflow.py b/bee_hive/run_workflow.py similarity index 100% rename from bee-hive/bee_hive/run_workflow.py rename to bee_hive/run_workflow.py diff --git a/bee-hive/bee_hive/step.py b/bee_hive/step.py similarity index 100% rename from bee-hive/bee_hive/step.py rename to bee_hive/step.py diff --git a/bee-hive/bee_hive/workflow.py b/bee_hive/workflow.py similarity index 100% rename from bee-hive/bee_hive/workflow.py rename to bee_hive/workflow.py diff --git a/bee-hive/cli/__init__.py b/cli/__init__.py similarity index 100% rename from bee-hive/cli/__init__.py rename to cli/__init__.py diff --git a/bee-hive/cli/beeAI.py b/cli/beeAI.py similarity index 100% rename from bee-hive/cli/beeAI.py rename to cli/beeAI.py diff --git a/bee-hive/cli/cli.py b/cli/cli.py similarity index 100% rename from bee-hive/cli/cli.py rename to cli/cli.py diff --git a/bee-hive/cli/commands.py b/cli/commands.py similarity index 100% rename from bee-hive/cli/commands.py rename to cli/commands.py diff --git a/bee-hive/cli/common.py b/cli/common.py similarity index 100% rename from bee-hive/cli/common.py rename to cli/common.py diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 049ef04..0000000 --- a/docs/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Comprehensive Overview -The Bee AI is a collection of multiple components and tools. This documentation provides a high-level overview of the project, including its architecture, design, and key components. - -![Alt text](assets/components.png "Image title") - -## Introduction -The Bee AI project is base in a AI Agent Framework and a multi-agent platform designed to build, deploy, and serve powerful agentic workflows at scale. The framwork is focus in the creation of AI Agents and the platform help to deploy, run and orchestration these AI agents powered by popular LLMs. - -## Project Structure -The project is structured into several repositories. The main directories are: -- `framework`: This directory link the core framework of the project, including the `bee-py` and `bee-ts` implementations. [Docs](framework.bee_agent_module_documentation.md) -- `bee-hive`: This directory contains the main application code. [Docs](/docs/hive.high-level_component_interactions.md) - -Also you can find extras as: -- `docs`: This directory contains documentation and assets for the project. -- `tools`: This directory contains scripts and tools for the project. -- `examples`: This directory contains example code and configurations for the project. - -## Architecture -The architecture of the Bee AI projects is represented in the following diagram: -```mermaid -graph TD - A[Framework TS/PY] -->|build| B[Agents] - B -->|uses| E[LLMs] - E -->|Output| B - C[Tools] --> |use| B - A --> |build| C - A --> |run| B - - B -->|uses| G[Memory] - B -->|provides| H[Cache] - B -->|provides| L[Serializer] - B -->|uses| M[Message] - B -->|uses| O[Events] - - - O[Hive] -->|provides| Q[Config] - O -->|provides| R[Observability] - O -->|uses| S[SandBox] - O -->|deploy| B - -``` - -## Components -You can find several components and tools, including: -- `Agents`: These are the main actors in the system, responsible for performing tasks and interacting with the environment. -- `LLMs`: These are large language models that provide output and interact with the agents. -- `Memory`: This component provides a cache and serialization mechanism for the system. -- `Cache`: This component provides a caching mechanism for the system. -- `File Cache`: This component provides a file-based caching mechanism for the system. -- `Sliding Cache`: This component provides a sliding window caching mechanism for the system. -- `Unconstrained Cache`: This component provides an unconstrained caching mechanism for the system. -- `Serializer`: This component provides a serialization mechanism for the system. -- `Message`: This component provides a messaging mechanism for the system. -- `Task Map`: This component provides a task mapping mechanism for the system. -- `Events`: This component provides an event handling mechanism for the system. -- `Roles`: This component provides a role-based access control mechanism for the system. -- `Config`: This component provides a configuration mechanism for the system. -- `Custom Logger`: This component provides a custom logging mechanism for the system. - -## Example Use Cases -The Bee can be used in a variety of scenarios, including: -- Simple Agent implementation using tools: The project can be used to check the weather using the `weather.py` script. -- Agent creation/deployment: The project can be used to create agents using the `create_agents.py` script. -- Workflow execution: The project can be used to execute workflows using the `run_workflow.py` script. - - \ No newline at end of file diff --git a/docs/assets/Bee_Dark.svg b/docs/assets/Bee_Dark.svg deleted file mode 100644 index 3806d80..0000000 --- a/docs/assets/Bee_Dark.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - .py - - - - - - diff --git a/docs/assets/components.png b/docs/assets/components.png deleted file mode 100644 index 90531080f005de13e584566596c23403c38300ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 231474 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�=oKT?jc?}V7T1hIkA;p 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

O|G&2_gmF1o&UC7HO}QGCz^Z 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 BYnA{2 diff --git a/docs/framework.bee_agent_module_documentation.md b/docs/framework.bee_agent_module_documentation.md deleted file mode 100644 index 2566efb..0000000 --- a/docs/framework.bee_agent_module_documentation.md +++ /dev/null @@ -1,59 +0,0 @@ -# Bee Agent Module Documentation -This document provides detailed documentation of the bee_agent module, including its classes, functions, and methods. - -## System Architecture and Key Design Decisions -The bee_agent module is designed to provide a flexible and modular architecture for building agents. The module is organized into several sub-modules, including tools, memory, llms, and agents. - -### Architecture Diagrams -The following diagram shows the high-level architecture of the bee_agent module: -```mermaid -classDiagram - class Agent { - + tools: Tool - + memory: Memory - + llms: LLM - } - class Tool { - + weather: Weather - + wikipedia: Wikipedia - } - class Memory { - + token_memory: TokenMemory - + summarize_memory: SummarizeMemory - + sliding_memory: SlidingMemory - } - class LLM { - + base_llm: BaseLLM - + prompt: Prompt - } - Agent --* Tool - Agent --* Memory - Agent --* LLM -``` -This diagram shows the relationships between the different classes in the bee_agent module. - -### Agents -The agents sub-module provides a set of classes for building agents, including a base agent class and a runner class. - -> [LLMs Agents](framework.bee_agent_module_documentation.md) - -### LLMs -The llms sub-module provides a set of classes for working with large language models, including a base LLM class and a prompt class. - -> [LLMs Docs](framework.llms_module_documentation.md) - -### Tools -The tools sub-module provides a set of utility functions for tasks such as weather forecasting and Wikipedia queries. - -> [Tools Docs](framework.tools_module_documentation.md) - -### Memory -The memory sub-module provides a set of classes for managing agent memory, including token memory, summarize memory, and sliding memory. - -> [Memory Docs](framework.memory_module_documentation.md) - - -## Examples -The examples sub-module provides a set of example code for using the bee_agent module, including examples for basic agent usage, LLM usage, and tool usage. - -> [Examples](/examples/) \ No newline at end of file diff --git a/docs/framework.llms_module_documentation.md b/docs/framework.llms_module_documentation.md deleted file mode 100644 index 9e05b7d..0000000 --- a/docs/framework.llms_module_documentation.md +++ /dev/null @@ -1,64 +0,0 @@ -# LLMs Module Documentation -The LLMs module is a crucial component of the bee-hive project, providing the functionality for large language models. This documentation aims to provide a detailed understanding of the llms module and how to use it effectively. - -## Overview -The llms module is located in the `workdir/bee-hive/framework/bee-py/bee_agent/llms` directory. It contains the following files: -- `llm.py`: This file contains the base class for large language models. -- `output.py`: This file contains the output class for large language models. -- `base_output.py`: This file contains the base output class for large language models. -- `__init__.py`: This file initializes the llms module. -- `prompt.py`: This file contains the prompt class for large language models. - -## Setup Instructions -To use the llms module, you need to have the bee-hive project set up on your local machine. You can do this by cloning the repository and following the instructions in the `README.md` file. - -## Example Usage -Here is an example of how to use the llms module: -```python -from bee_agent.llms import LLM - -# Create an instance of the LLM class -llm = LLM() - -# Use the llm instance to generate text -text = llm.generate_text("This is a prompt") -``` - -## mermaid Art Diagrams -The following mermaid art diagram shows the relationship between the classes in the llms module: -```mermaid -classDiagram - LLM <|-- Output - LLM <|-- BaseOutput - LLM <|-- Prompt - class LLM { - +generate_text(prompt: str) - } - class Output { - +__init__(text: str) - } - class BaseOutput { - +__init__(text: str) - } - class Prompt { - +__init__(text: str) - } -``` -This diagram shows that the `LLM` class is the base class, and it has methods to generate text. The `Output`, `BaseOutput`, and `Prompt` classes inherit from the `LLM` class. - -## Code Examples -The following code example shows how to use the `generate_text` method of the `LLM` class: -```python -from bee_agent.llms import LLM - -def generate_text(prompt: str) -> str: - llm = LLM() - return llm.generate_text(prompt) - -# Test the function -print(generate_text("This is a test prompt")) -``` -This code example creates an instance of the `LLM` class and uses it to generate text based on a prompt. The generated text is then printed to the console. - -## Conclusion -In conclusion, the llms module is a powerful tool for working with large language models. It provides a simple and intuitive API for generating text based on prompts. With this documentation, you should be able to use the llms module effectively in your own projects. \ No newline at end of file diff --git a/docs/framework.memory_module_documentation.md b/docs/framework.memory_module_documentation.md deleted file mode 100644 index cb14648..0000000 --- a/docs/framework.memory_module_documentation.md +++ /dev/null @@ -1,63 +0,0 @@ -# Memory Module Documentation -The Memory Module is a crucial component of the bee-hive project, responsible for managing and storing data. This documentation provides a detailed overview of the Memory Module, its classes, functions, and methods. - -## Introduction -The Memory Module is designed to provide a flexible and efficient way to store and retrieve data. It consists of several classes and functions that work together to manage memory. - -## Classes and Functions -The Memory Module includes the following classes and functions: - -* `token_memory.py`: This class provides a basic implementation of a token-based memory system. -* `serializer.py`: This class is responsible for serializing and deserializing data. -* `summarize_memory.py`: This class provides a way to summarize and condense memory data. -* `unconstrained_memory.py`: This class provides an implementation of an unconstrained memory system. -* `base_memory.py`: This class provides a basic implementation of a memory system. -* `sliding_cache.py`: This class provides a sliding cache implementation. -* `readonly_memory.py`: This class provides a read-only memory implementation. -* `task_map.py`: This class provides a task mapping implementation. -* `exceptions.py`: This class provides custom exceptions for the Memory Module. -* `serializable.py`: This class provides a serializable interface. -* `message.py`: This class provides a message implementation. - -## Code Examples -Here are some examples of how to use the Memory Module: -```python -from bee_agent.memory.token_memory import TokenMemory - -# Create a token memory instance -token_memory = TokenMemory() - -# Store a token in memory -token_memory.store_token("example_token") - -# Retrieve a token from memory -token = token_memory.retrieve_token("example_token") -``` - -## Setup Instructions -To use the Memory Module, follow these steps: - -1. Install the required dependencies. -2. Import the relevant classes and functions. -3. Create an instance of the desired memory class. -4. Use the instance to store and retrieve data. - -## Mermaid Diagrams -Here is a mermaid diagram showing the relationships between the different classes and functions in the Memory Module: -```mermaid -classDiagram - class TokenMemory { - + store_token(token: str) - + retrieve_token(token: str) - } - class Serializer { - + serialize(data: any) - + deserialize(data: any) - } - class SummarizeMemory { - + summarize(data: any) - } - TokenMemory --|> Serializer - TokenMemory --|> SummarizeMemory -``` -This diagram shows the relationships between the `TokenMemory`, `Serializer`, and `SummarizeMemory` classes. The `TokenMemory` class uses the `Serializer` class to serialize and deserialize data, and it also uses the `SummarizeMemory` class to summarize memory data. \ No newline at end of file diff --git a/docs/framework.system_architecture_and_key_design_decisions.md b/docs/framework.system_architecture_and_key_design_decisions.md deleted file mode 100644 index 643a6c8..0000000 --- a/docs/framework.system_architecture_and_key_design_decisions.md +++ /dev/null @@ -1,54 +0,0 @@ -# System Architecture and Key Design Decisions -The bee-hive project is designed to provide a framework for creating and managing agents that can perform various tasks. The system architecture consists of several components, including the agent framework, the memory management system, and the workflow management system. - -## Agent Framework -The agent framework is responsible for defining the structure and behavior of the agents. It provides a set of tools and libraries that can be used to create and manage agents. The framework is written in Python and uses the poetry package manager to manage dependencies. - -```python -# Example of an agent definition -from bee_agent import Agent - -class MyAgent(Agent): - def __init__(self): - super().__init__() - self.tools = ["weather", "wikipedia"] - - def run(self): - # Code to run the agent - pass -``` - -## Memory Management System -The memory management system is responsible for managing the memory of the agents. It provides a set of libraries and tools that can be used to store and retrieve data from the memory. The system uses a combination of in-memory and file-based storage to manage the data. - -```python -# Example of using the memory management system -from bee_agent.memory import Memory - -memory = Memory() -memory.store("key", "value") -value = memory.retrieve("key") -``` - -## Workflow Management System -The workflow management system is responsible for managing the workflows of the agents. It provides a set of libraries and tools that can be used to define and execute workflows. The system uses a YAML-based configuration file to define the workflows. - -```yml -# Example of a workflow definition -workflows: - - name: my_workflow - agents: - - my_agent - steps: - - run: my_agent -``` - -## Diagrams -The following mermaid art diagram shows the high-level architecture of the bee-hive project: -```mermaid -graph LR; - A[Agent Framework] -->|uses| B[Memory Management System]; - B -->|stores| C[Data]; - A -->|defines| D[Workflow Management System]; - D -->|executes| E[Workflow]; -``` diff --git a/docs/framework.tools_module_documentation.md b/docs/framework.tools_module_documentation.md deleted file mode 100644 index 729fbda..0000000 --- a/docs/framework.tools_module_documentation.md +++ /dev/null @@ -1,59 +0,0 @@ -# Tools Module Documentation -## Introduction -The Tools Module is a crucial component of the bee-hive project, in particular are part of the Framework tools, aand anabled the Agents use them. The framework providing various tools and utilities to support the development and use of the project. This documentation aims to provide a detailed understanding of the Tools Module, its classes, functions, and methods, as well as guidance on how to use and integrate it with other systems. - -## Architecture -The Tools Module is located in the `bee_agent/tools` directory and consists of several sub-modules, including `weather.py`, `tool.py`, and `wikipedia.py`. Each sub-module provides a specific set of tools and utilities, such as weather data retrieval, tool management, and Wikipedia data access. - -## Setup Instructions -To use the Tools Module, follow these setup instructions: - -1. Clone the bee-hive repository using `git clone`. -2. Install the required dependencies using `poetry install`. -3. Import the Tools Module in your Python script using `from bee_agent.tools import *`. - -## Examples -Here are some examples of using the Tools Module: - -* Weather data retrieval: `weather.get_weather_data('London')` -* Tool management: `tool.create_tool('example_tool')` -* Wikipedia data access: `wikipedia.get_wikipedia_data('example_topic')` - -## mermaid Art Diagrams -The following mermaid art diagram shows the relationships between the Tools Module and other components of the bee-hive project: -```mermaid -graph LR - A[Tools Module] -->|uses| B[bee-agent] - A -->|provides| C[Weather Data] - A -->|provides| D[Tool Management] - A -->|provides| E[Wikipedia Data] - B -->|uses| C - B -->|uses| D - B -->|uses| E -``` -This diagram illustrates the dependences between the Tools Module and other components of the bee-hive project, such as the bee-agent, weather data, tool management, and Wikipedia data. - -## Code References -The Tools Module is implemented in Python and uses various libraries and frameworks, such as `poetry` for dependency management and `git` for version control. The code is organized into several sub-modules, each providing a specific set of tools and utilities. - -## Conclusion -The Tools Module is a crucial component of the bee-hive project, providing various tools and utilities to support the development and use of the project. By following the setup instructions and using the examples provided, developers can easily integrate the Tools Module with other systems and take advantage of its features. - -## Component Relationships and Flows -The following mermaid art diagram shows the component relationships and flows of the Tools Module: -```mermaid -sequenceDiagram - participant Tools Module as "Tools Module" - participant bee-agent as "bee-agent" - participant Weather Data as "Weather Data" - participant Tool Management as "Tool Management" - participant Wikipedia Data as "Wikipedia Data" - Tools Module->>bee-agent: uses - bee-agent->>Tools Module: uses - Tools Module->>Weather Data: provides - Tools Module->>Tool Management: provides - Tools Module->>Wikipedia Data: provides - Weather Data->>bee-agent: used by - Tool Management->>bee-agent: used by - Wikipedia Data->>bee-agent: used by -``` \ No newline at end of file diff --git a/docs/hive.high-level_component_interactions.md b/docs/hive.high-level_component_interactions.md deleted file mode 100644 index cbb0513..0000000 --- a/docs/hive.high-level_component_interactions.md +++ /dev/null @@ -1,45 +0,0 @@ -# High-Level Component Interactions -This document provides an overview of how the components of the bee-hive project interact with each other, including their communication and data exchange mechanisms. - -## Project Structure -The bee-hive project consists of several key components, including the `bee-hive`, and use the `bee-agent frameworks` to build the agents. The `bee-hive` directory contains the configuration and tools for the hive. The `bee-agent framewors` contains the core logic for the Bee AI Agents, and is base in the same interface implementation for TypeScript and Python, more references: -- [`bee-framework-ts`](https://github.com/i-am-bee/bee-agent-framework) -- [`bee-framework-py`](https://github.com/i-am-bee/bee-hive/tree/main/framework/bee-py) - -## Component Interactions -The components of the bee-hive project interact with each other through a series of APIs and data exchanges. The `bee-hive` help to deploy and stablish communication with/between `bee-agent` through a RESTful API, having the `framework` as provider of the main set of libraries and tools for building the `bee-agents`. - -### Bee Agent Component -The `bee-agent` component is responsible for executing the core logic of the project. It interacts with the `bee-hive` component to retrieve configuration and data, and with the `framework` component to utilize the underlying libraries and tools. - -### Bee Hive Component -The `bee-hive` component is responsible for storing and managing the configuration and data for the project. It interacts with the `bee-agent` component to provide configuration and data, and with the `framework` component to utilize the underlying libraries and tools. - -### Framework Component -The `framework` component provides a set of libraries and tools for building and deploying the project. It interacts with the `bee-agent` and `bee-hive` components to provide underlying functionality and support. - -## Data Flows -The components of the bee-hive project exchange data through a series of APIs and data pipelines. The `bee-agent` component retrieves configuration and data from the `bee-hive` component, and sends output and results back to the `bee-hive` component. The `framework` component provides a set of libraries and tools for building and deploying the project, and interacts with the `bee-agent` and `bee-hive` components to provide underlying functionality and support. - -## Components Diagram -```mermaid -graph TD - B[Bee Hive] --> |RESTful API| A[Bee Agent] - A -->|Data Pipeline| B - A <-->|Data Pipeline| A - C[Framework] -->|Libraries and Tools| A - -``` -This diagram illustrates the high-level interactions between the components of the Bee project, including the communication and data exchange mechanisms. - -## Setup Instructions -To set up the bee-hive project, follow these steps: - -* Clone the repository from GitHub -* Run a local instance of the Bee Stack -* Install dependencies: `pip install -r ../../../bee-hive/requirements.txt` -* Configure environmental variables: `cp example.env .env` -* Copy `.env` to main bee-hive directory: `cp .env ../../../bee-hive` -* Create the agents: `./hive create agents.yaml` -* Open the UI ( http://localhost:3000 ) and enable the `OpenMateo` tool for both agents -* Run the workflow: `./hive run workflow.yaml` (to run for a different city, change the `prompt` field in `workflow.yaml`) diff --git a/bee-hive/entrypoint.sh b/entrypoint.sh similarity index 100% rename from bee-hive/entrypoint.sh rename to entrypoint.sh diff --git a/examples/bee-hive/weather-checker/README.md b/examples/bee-hive/weather-checker/README.md deleted file mode 100644 index 4b56038..0000000 --- a/examples/bee-hive/weather-checker/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Weather-Checker Example - -A multi-agent workflow using Bee-Hive to check if the current temperature in a location is hotter or colder than average. - -## Getting Started - -* Run a local instance of the Bee Stack - -* Install dependencies: `cd ../../../bee-hive/bee_hive && poetry shell && poetry install && cd -` - -* Configure environmental variables: `cp example.env .env` - -* Copy `.env` to main bee-hive directory: `cp .env ../../../bee-hive/bee_hive` - -* Create the agents: `./hive create agents.yaml` - -* Open the UI ( http://localhost:3000 ) and enable the `OpenMateo` tool for both agents - -* Run the workflow: `./hive run workflow.yaml` (to run for a different city, change the `prompt` field in `workflow.yaml`) diff --git a/examples/bee-hive/weather-checker/agents.yaml b/examples/bee-hive/weather-checker/agents.yaml deleted file mode 100644 index 7385c7c..0000000 --- a/examples/bee-hive/weather-checker/agents.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: beehive/v1alpha1 -kind: Agent -metadata: - name: current-affairs - labels: - app: mas-example -spec: - model: meta-llama/llama-3-1-70b-instruct - description: Get the current weather - tools: - - code_interpreter - - weather - instructions: Get the current temperature for the location provided by the user. Return results in Fahrenheit. - ---- -apiVersion: beehive/v1alpha1 -kind: Agent -metadata: - name: hot-or-not - labels: - app: mas-example -spec: - model: meta-llama/llama-3-1-70b-instruct - description: Is the current temperature hotter than usual? - tools: - - code_interpreter - - weather - instructions: The user will give you a temperature in Fahrenheit and a location. Use the OpenMateo weather tool to find the average monthly temperature for the location. Answer if the temperature provided by the user is hotter or colder than the average found by the tool. diff --git a/examples/bee-hive/weather-checker/example.env b/examples/bee-hive/weather-checker/example.env deleted file mode 100644 index cfb94ba..0000000 --- a/examples/bee-hive/weather-checker/example.env +++ /dev/null @@ -1,6 +0,0 @@ -BEE_API=http://localhost:4000 -BEE_API_KEY=sk-proj-testkey - -# This is required to prevent some pydantic serialization errors -DEFER_PYDANTIC_BUILD=false - diff --git a/examples/bee-hive/weather-checker/hive b/examples/bee-hive/weather-checker/hive deleted file mode 100755 index 31c4f1a..0000000 --- a/examples/bee-hive/weather-checker/hive +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/bash -do=${1:-"none"} -case "$do" in - run) DEFER_PYDANTIC_BUILD=false ../../../bee-hive/bee_hive/run_workflow.py "$2" ;; - create) ../../../bee-hive/bee_hive/create_agents.py "$2";; - none) echo "invalid option" ;; -esac diff --git a/examples/bee-hive/weather-checker/workflow.yaml b/examples/bee-hive/weather-checker/workflow.yaml deleted file mode 100644 index 28a9570..0000000 --- a/examples/bee-hive/weather-checker/workflow.yaml +++ /dev/null @@ -1,18 +0,0 @@ -apiVersion: beehive/v1alpha1 -kind: Workflow -metadata: - name: beehive-deployment - labels: - app: mas-example -spec: - strategy: - type: sequence - output: verbose - template: - metadata: - labels: - app: mas-example - agents: - - name: current-affairs - - name: hot-or-not - prompt: New York diff --git a/examples/bee_agent/agents/README.md b/examples/bee_agent/agents/README.md deleted file mode 100644 index 78b3c42..0000000 --- a/examples/bee_agent/agents/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Examples how use Bee Framework - -be sure that you install all the potencial dependencies before run this examples. - -```bash -pip install -r examples/bee_agent/agents/requirements.txt -``` - diff --git a/examples/bee_agent/agents/bee.py b/examples/bee_agent/agents/bee.py deleted file mode 100644 index d0a2cae..0000000 --- a/examples/bee_agent/agents/bee.py +++ /dev/null @@ -1,166 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import os -from dotenv import load_dotenv -import asyncio -from typing import Dict, Any -import logging - -from bee_agent.agents import BeeAgent -from bee_agent.memory import TokenMemory -from bee_agent.utils import BeeLogger -from bee_agent.llms import LLM -from bee_agent.tools import Tool - -# Import LangChain's Wikipedia tool from community package -from langchain_community.tools import WikipediaQueryRun -from langchain_community.utilities import WikipediaAPIWrapper - -# Load environment variables -load_dotenv() - -# Configure logging - using DEBUG instead of trace -logger = BeeLogger("app", level=logging.DEBUG) - - -def get_env_var(key: str, default: str = None) -> str: - """Helper function to get environment variables with defaults""" - return os.getenv(key, default) - - -class LangChainWikipediaTool(Tool): - """Adapter class to integrate LangChain's Wikipedia tool with our framework""" - - name = "Wikipedia" - description = ( - "Search factual and historical information from Wikipedia about given topics." - ) - - def __init__(self): - super().__init__() - wikipedia = WikipediaAPIWrapper() - self.wikipedia = WikipediaQueryRun(api_wrapper=wikipedia) - - def input_schema(self): - return """{ - "type": "object", - "properties": { - "query": { - "type": "string", - "description": "The topic or question to search for on Wikipedia", - } - }, - "required": ["query"], - }""" - - def _run(self, input: Dict[str, Any], options=None): - query = input.get("query", "") - try: - result = self.wikipedia.run(query) - return result - except Exception as e: - logger.error(f"Wikipedia search error: {str(e)}") - return f"Error searching Wikipedia: {str(e)}" - - -def create_agent() -> BeeAgent: - """Create and configure the agent with tools and LLM""" - - # Initialize LLM - llm = LLM( - model="llama3.1", # Use llama3.1 for better performance - parameters={ - "temperature": 0, - "repeat_penalty": 1.0, - "num_predict": 2048, - }, - ) - - # Configure tools with LangChain's Wikipedia tool - # tools = [LangChainWikipediaTool(), WeatherTool()] - tools = [LangChainWikipediaTool()] - - # Add code interpreter tool if URL is configured - code_interpreter_url = get_env_var("CODE_INTERPRETER_URL") - if code_interpreter_url: - # Note: Python tool implementation would go here - pass - - # Create agent with memory and tools - agent = BeeAgent(llm=llm, tools=tools, memory=TokenMemory(llm)) - - return agent - - -async def process_agent_events( - event_data: Dict[str, Any], metadata: Dict[str, Any] -) -> None: - """Process agent events and log appropriately""" - - if event_data.get("error"): - logger.error(f"Agent error: {event_data['error']}") - - if event_data.get("retry"): - logger.info("Agent: retrying the action...") - - if event_data.get("update"): - update = event_data["update"] - logger.info(f"Agent ({update.get('key')}): {update.get('value')}") - - -async def main(): - """Main application loop""" - - try: - # Create agent - agent = create_agent() - - # Print code interpreter status if configured - code_interpreter_url = get_env_var("CODE_INTERPRETER_URL") - if code_interpreter_url: - print( - f"🛠️ System: The code interpreter tool is enabled. Please ensure that it is running on {code_interpreter_url}" - ) - - print( - "Agent initialized with LangChain Wikipedia tool. Type 'exit' or 'quit' to end." - ) - - # Main interaction loop - while True: - try: - # Get user input - prompt = input("\nUser: ").strip() - if not prompt: - continue - - if prompt.lower() in ["exit", "quit"]: - break - print(">>>", prompt) - # Run agent with the prompt - agent.run( - prompt=prompt, - options={ - "execution": { - "max_retries_per_step": 3, - "total_max_retries": 10, - "max_iterations": 20, - } - }, - ) - - except KeyboardInterrupt: - print("\nExiting...") - break - except Exception as e: - logger.error(f"Error processing prompt: {str(e)}") - - except Exception as e: - logger.error(f"Application error: {str(e)}") - - -if __name__ == "__main__": - # Run the async main function - # logging.basicConfig(level=logging.DEBUG) - - asyncio.run(main()) diff --git a/examples/bee_agent/agents/bee_advanced.py b/examples/bee_agent/agents/bee_advanced.py deleted file mode 100644 index 51fea6e..0000000 --- a/examples/bee_agent/agents/bee_advanced.py +++ /dev/null @@ -1,214 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import json -from dotenv import load_dotenv -import asyncio -from typing import Dict, Any -import logging -import signal - -from bee_agent.agents import BeeAgent -from bee_agent.memory import UnconstrainedMemory -from bee_agent.utils import BeeLogger, BeeEventEmitter, MessageEvent -from bee_agent.llms import LLM -from bee_agent.tools import WeatherTool, Tool - -# Load environment variables -load_dotenv() - -# Configure logging -logger = BeeLogger("app", level=logging.DEBUG) -event_emitter = BeeEventEmitter() - - -class DuckDuckGoSearchType: - STRICT = "STRICT" - MODERATE = "MODERATE" - OFF = "OFF" - - -class DuckDuckGoSearchTool(Tool): - """DuckDuckGo search tool implementation""" - - name = "DuckDuckGoSearch" - description = "Search for information on the web using DuckDuckGo" - - def __init__( - self, max_results: int = 10, safe_search: str = DuckDuckGoSearchType.STRICT - ): - super().__init__() - self.max_results = max_results - self.safe_search = safe_search - - def input_schema(self): - return """ - { - "type": "object", - "properties": { - "query": { - "type": "string", - "description": "The search query" - } - }, - "required": ["query"] - } - """ - - def _run(self, input: Dict[str, Any], options=None): - try: - # Ensure input is properly formatted - if isinstance(input, str): - input = json.loads(input) - - query = input.get("query", "") - - if not query: - return "Error: No search query provided" - - # Here you would implement the actual DuckDuckGo search - # For now, return a mock response - return { - "results": [ - { - "title": f"Search result for: {query}", - "link": "https://example.com", - "snippet": f"This is a mock search result for the query: {query}", - } - ], - "total": 1, - } - except json.JSONDecodeError as e: - logger.error(f"JSON parsing error: {str(e)}") - return f"Error parsing search input: {str(e)}" - except Exception as e: - logger.error(f"Search error: {str(e)}") - return f"Error performing search: {str(e)}" - - -def create_agent() -> BeeAgent: - """Create and configure the agent with custom tools and prompts""" - - # Initialize LLM - llm = LLM( - model="llama3.1", - parameters={ - "temperature": 0, - "repeat_penalty": 1.0, - "num_predict": 2048, - }, - ) - - # Configure tools - tools = [ - DuckDuckGoSearchTool(max_results=10, safe_search=DuckDuckGoSearchType.STRICT), - WeatherTool(), - ] - - # Create agent with custom configuration - agent = BeeAgent(llm=llm, tools=tools, memory=UnconstrainedMemory()) - - return agent - - -async def handle_tool_response(response: Any, tool_name: str): - """Handle tool response and emit appropriate events""" - try: - if isinstance(response, (dict, list)): - response_str = json.dumps(response, ensure_ascii=False, indent=2) - else: - response_str = str(response) - - event_emitter.emit( - MessageEvent( - source="Agent", message=response_str, state=f"tool_response_{tool_name}" - ) - ) - - return response_str - except Exception as e: - logger.error(f"Error handling tool response: {str(e)}") - event_emitter.emit(MessageEvent(source="Agent", message=str(e), state="error")) - return str(e) - - -async def run_agent(): - """Main function to run the agent""" - - try: - # Create agent - agent = create_agent() - print( - "Agent initialized with custom tools and prompts. Type 'exit' or 'quit' to end." - ) - - # Main interaction loop - while True: - try: - # Get user input - prompt = input("\nUser: ").strip() - if not prompt: - continue - - if prompt.lower() in ["exit", "quit"]: - break - - # Emit user message event - event_emitter.emit(MessageEvent(source="User", message=prompt)) - - # Run agent with timeout - try: - # Set timeout signal - signal.alarm(120) # 2 minutes timeout - - result = agent.run( - prompt=prompt, - options={ - "execution": { - "max_retries_per_step": 3, - "total_max_retries": 10, - "max_iterations": 20, - } - }, - ) - - # Handle final response - if result: - event_emitter.emit( - MessageEvent( - source="Agent", - message=str(result), - state="final_answer", - ) - ) - - finally: - # Clear timeout - signal.alarm(0) - - except KeyboardInterrupt: - print("\nExiting...") - break - except json.JSONDecodeError as e: - logger.error(f"JSON parsing error: {str(e)}") - event_emitter.emit( - MessageEvent( - source="Agent", - message=f"Error parsing JSON: {str(e)}", - state="error", - ) - ) - except Exception as e: - logger.error(f"Error processing prompt: {str(e)}") - event_emitter.emit( - MessageEvent(source="Agent", message=str(e), state="error") - ) - - except Exception as e: - logger.error(f"Application error: {str(e)}") - event_emitter.emit(MessageEvent(source="Agent", message=str(e), state="error")) - - -if __name__ == "__main__": - # Run the async main function - # logging.basicConfig(level=logging.DEBUG) - asyncio.run(run_agent()) diff --git a/examples/bee_agent/agents/requirements.txt b/examples/bee_agent/agents/requirements.txt deleted file mode 100644 index 3c9efc9..0000000 --- a/examples/bee_agent/agents/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -wikipedia -langchain_community \ No newline at end of file diff --git a/examples/bee_agent/basic.py b/examples/bee_agent/basic.py deleted file mode 100644 index 0864a2d..0000000 --- a/examples/bee_agent/basic.py +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from bee_agent import BeeAgent, LLM - -agent = BeeAgent(llm=LLM()) - -agent.run("What is the capital of Massachusetts") diff --git a/examples/bee_agent/llms.py b/examples/bee_agent/llms.py deleted file mode 100644 index 3fbb746..0000000 --- a/examples/bee_agent/llms.py +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import sys - -from dotenv import load_dotenv - -from bee_agent import BeeAgent, LLM - - -LLMS = { - "ollama": "ollama/llama3.1", - "openai": "openai/gpt-4o-mini", - "watsonx": "watsonx/ibm/granite-3-8b-instruct", -} - -HELP = """ -Usage: - examples.bee_agent.llms -Arguments - `ollama` - requires local ollama service running (i.e., http://127.0.0.1:11434) - `openai` - requires environment variable - - OPENAI_API_KEY: API key - `watsonx` - requires environment variable - - WATSONX_URL - base URL of your WatsonX instance - and one of the following - - WATSONX_APIKEY: API key - - WATSONX_TOKEN: auth token -""" - - -if __name__ == "__main__": - if len(sys.argv) < 2: - print(HELP) - elif sys.argv[1] == "--help": - print(HELP) - else: - load_dotenv() - model = LLMS.get(sys.argv[1]) - if model: - agent = BeeAgent(llm=LLM(model=model)) - agent.run("What is the smallest of the Cabo Verde islands?") - else: - print(f"Unknown provider: {sys.argv[1]}\n{HELP}") diff --git a/examples/bee_agent/memory/agentMemory.py b/examples/bee_agent/memory/agentMemory.py deleted file mode 100644 index 8cbd206..0000000 --- a/examples/bee_agent/memory/agentMemory.py +++ /dev/null @@ -1,72 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import asyncio - -from bee_agent import BeeAgent, LLM -from bee_agent.memory import UnconstrainedMemory, BaseMessage -from bee_agent.llms.prompt import Prompt -from bee_agent.utils import Role - - -# Initialize the memory and LLM -memory = UnconstrainedMemory() - -llm = LLM( - model="llama3.2", # or whatever model you're using - base_url="http://localhost:11434", -) - -# Initialize the agent -agent = BeeAgent(llm=llm, memory=memory, tools=[]) - - -async def main(): - try: - # Create user message - user_input = "Hello world!" - user_message = BaseMessage(role=Role.USER, text=user_input) - - # Await adding user message to memory - await memory.add(user_message) - print("Added user message to memory") - - # Create and run the prompt (synchronously) - prompt: Prompt = {"prompt": user_input} - # No await here since run() is not async - response = agent.run(prompt) - print(f"Received response: {response}") - - # Get the actual text from the ChatLLMOutput - response_text = ( - response.output.response if hasattr(response, "output") else str(response) - ) - - # Create and store assistant's response - assistant_message = BaseMessage(role=Role.ASSISTANT, text=response_text) - - # Await adding assistant message to memory - await memory.add(assistant_message) - print("Added assistant message to memory") - - # Print results - print(f"\nMessages in memory: {len(agent.memory.messages)}") - - if len(agent.memory.messages) >= 1: - user_msg = agent.memory.messages[0] - print(f"User: {user_msg.text}") - - if len(agent.memory.messages) >= 2: - agent_msg = agent.memory.messages[1] - print(f"Agent: {agent_msg.text}") - else: - print("No agent message found in memory") - - except Exception as e: - print(f"An error occurred: {str(e)}") - import traceback - - print(traceback.format_exc()) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/examples/bee_agent/memory/slidingMemory.py b/examples/bee_agent/memory/slidingMemory.py deleted file mode 100644 index 3e35b19..0000000 --- a/examples/bee_agent/memory/slidingMemory.py +++ /dev/null @@ -1,57 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import asyncio - -from bee_agent.memory.sliding_memory import SlidingMemory, SlidingMemoryConfig -from bee_agent.memory.message import BaseMessage -from bee_agent.utils import Role - - -async def main(): - try: - # Create sliding memory with size 3 - memory = SlidingMemory( - SlidingMemoryConfig( - size=3, - handlers={ - "removal_selector": lambda messages: messages[ - 0 - ] # Remove oldest message - }, - ) - ) - - # Add messages - await memory.add( - BaseMessage.of( - {"role": Role.SYSTEM, "text": "You are a helpful assistant."} - ) - ) - - await memory.add(BaseMessage.of({"role": Role.USER, "text": "What is Python?"})) - - await memory.add( - BaseMessage.of( - {"role": Role.ASSISTANT, "text": "Python is a programming language."} - ) - ) - - # Adding a fourth message should trigger sliding window - await memory.add( - BaseMessage.of({"role": Role.USER, "text": "What about JavaScript?"}) - ) - - # Print results - print(f"Messages in memory: {len(memory.messages)}") # Should print 3 - for msg in memory.messages: - print(f"{msg.role}: {msg.text}") - - except Exception as e: - print(f"An error occurred: {str(e)}") - import traceback - - print(traceback.format_exc()) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/examples/bee_agent/memory/summarizeMemory.py b/examples/bee_agent/memory/summarizeMemory.py deleted file mode 100644 index 9e65fd9..0000000 --- a/examples/bee_agent/memory/summarizeMemory.py +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import asyncio - -from bee_agent.llms import LLM -from bee_agent.memory.summarize_memory import SummarizeMemory -from bee_agent.memory.message import BaseMessage -from bee_agent.utils import Role - - -async def main(): - try: - # Initialize the LLM with parameters - llm = LLM(model="llama3.2", parameters={"temperature": 0, "num_predict": 250}) - - # Create summarize memory instance - memory = SummarizeMemory(llm) - - # Add messages - await memory.add_many( - [ - BaseMessage.of( - {"role": Role.SYSTEM, "text": "You are a guide through France."} - ), - BaseMessage.of({"role": Role.USER, "text": "What is the capital?"}), - BaseMessage.of({"role": Role.ASSISTANT, "text": "Paris"}), - BaseMessage.of( - {"role": Role.USER, "text": "What language is spoken there?"} - ), - ] - ) - - # Print results - print(f"Is Empty: {memory.is_empty()}") - print(f"Message Count: {len(memory.messages)}") - - if memory.messages: - print(f"Summary: {memory.messages[0].text}") - - except Exception as e: - print(f"An error occurred: {str(e)}") - import traceback - - print(traceback.format_exc()) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/examples/bee_agent/memory/tokenMemory.py b/examples/bee_agent/memory/tokenMemory.py deleted file mode 100644 index 5a74de7..0000000 --- a/examples/bee_agent/memory/tokenMemory.py +++ /dev/null @@ -1,68 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import asyncio -import math - -from bee_agent import LLM -from bee_agent.memory import TokenMemory -from bee_agent.memory.message import BaseMessage -from bee_agent.utils import Role - - -# Initialize the LLM -llm = LLM() - -# Initialize TokenMemory with handlers -memory = TokenMemory( - llm=llm, - max_tokens=None, # Will be inferred from LLM - capacity_threshold=0.75, - sync_threshold=0.25, - handlers={ - "removal_selector": lambda messages: next( - (msg for msg in messages if msg.role != Role.SYSTEM), messages[0] - ), - "estimate": lambda msg: math.ceil((len(msg.role) + len(msg.text)) / 4), - }, -) - - -async def main(): - try: - # Add system message - system_message = BaseMessage.of( - {"role": Role.SYSTEM, "text": "You are a helpful assistant."} - ) - await memory.add(system_message) - print(f"Added system message (hash: {hash(system_message)})") - - # Add user message - user_message = BaseMessage.of({"role": Role.USER, "text": "Hello world!"}) - await memory.add(user_message) - print(f"Added user message (hash: {hash(user_message)})") - - # Check initial memory state - print("\nInitial state:") - print(f"Is Dirty: {memory.is_dirty}") - print(f"Tokens Used: {memory.tokens_used}") - - # Sync token counts - await memory.sync() - print("\nAfter sync:") - print(f"Is Dirty: {memory.is_dirty}") - print(f"Tokens Used: {memory.tokens_used}") - - # Print all messages - print("\nMessages in memory:") - for msg in memory.messages: - print(f"{msg.role}: {msg.text} (hash: {hash(msg)})") - - except Exception as e: - print(f"An error occurred: {str(e)}") - import traceback - - print(traceback.format_exc()) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/examples/bee_agent/memory/unconstrainedMemory.py b/examples/bee_agent/memory/unconstrainedMemory.py deleted file mode 100644 index 38f5557..0000000 --- a/examples/bee_agent/memory/unconstrainedMemory.py +++ /dev/null @@ -1,34 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import asyncio - -from bee_agent.memory import UnconstrainedMemory -from bee_agent.memory.message import BaseMessage -from bee_agent.utils import Role - - -async def main(): - try: - # Create memory instance - memory = UnconstrainedMemory() - - # Add a message - await memory.add(BaseMessage.of({"role": Role.USER, "text": "Hello world!"})) - - # Print results - print(f"Is Empty: {memory.is_empty()}") # Should print: False - print(f"Message Count: {len(memory.messages)}") # Should print: 1 - - print("\nMessages:") - for msg in memory.messages: - print(f"{msg.role}: {msg.text}") - - except Exception as e: - print(f"An error occurred: {str(e)}") - import traceback - - print(traceback.format_exc()) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/examples/bee_agent/requirements.txt b/examples/bee_agent/requirements.txt deleted file mode 100644 index a3c2c13..0000000 --- a/examples/bee_agent/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -langchain-community -langchain \ No newline at end of file diff --git a/examples/bee_agent/tools/weather.py b/examples/bee_agent/tools/weather.py deleted file mode 100644 index 67245fe..0000000 --- a/examples/bee_agent/tools/weather.py +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from bee_agent import BeeAgent, LLM -from bee_agent.tools import WeatherTool - -agent = BeeAgent(llm=LLM(model="llama3.1"), tools=[WeatherTool()]) - -agent.run("What's the current weather in Las Vegas?") diff --git a/framework/bee-py/README.md b/framework/bee-py/README.md deleted file mode 100644 index c63d874..0000000 --- a/framework/bee-py/README.md +++ /dev/null @@ -1,129 +0,0 @@ -> [!WARNING] -> [PRE-Alpha] Please reach out if you want to get involved in the discussions. All feedback is welcomed - -

- Bee Framework logo -

Bee Agent Framework Python

-

- -

- Project Status: Alpha -

Python implementation of the Bee Agent Framework for building, deploying, and serving powerful agentic workflows at scale.

-

- -The Bee Agent Framework Python makes it easy to build scalable agent-based workflows with your model of choice. This framework is designed to perform robustly with [IBM Granite](https://www.ibm.com/granite?adoper=255252_0_LS1) and [Llama 3.x](https://ai.meta.com/blog/meta-llama-3-1/) models. Varying level of support is currently availble for [other LLMs using LiteLLM](https://docs.litellm.ai/docs/providers). We're actively working on optimizing its performance with these popular LLMs. - -Our goal is to empower Python developers to adopt the latest open-source and proprietary models with minimal changes to their current agent implementation. - -## Key Features - -- 🤖 **AI agents**: Use our powerful Bee agent refined for Llama 3.x and Granite 3.x, or build your own. -- 🛠️ **Tools**: Use our built-in tools or create your own in Python. -- 💾 **Memory**: Multiple strategies to optimize token spend. -- ... more on our Roadmap - -## Getting Started - -### Installation - -```bash -pip install ./framework/bee-py -``` - -### Quick Example - -```python -from bee_agent import BeeAgent, LLM - -agent = BeeAgent(llm=LLM()) - -agent.run("What is the capital of Massachusetts") -``` - -> **Note**: To run this example, ensure you have [ollama](https://ollama.com) installed with the [llama3.1](https://ollama.com/library/llama3.1) model downloaded. - -to run other examples you can use, "python -m examples/bee_agent/[example_name]": - -```bash -python examples/bee_agent/basic.py -``` - -## Local Development - -1. Clone the repository: `git clone https://github.com/i-am-bee/bee-hive.git` -1. Change into the `./framework/bee-py` directory -1. Install dependencies: `poetry install` -1. Activate virtual environment: `poetry shell` -1. Create `.env` from `.env.example` and fill in required values - - -### Build the pip package - -#### Build the package: - -```bash -cd ./framework/bee-py -poetry build -``` - -#### Test the Build Locally (Recommended) - -```bash -# Create a virtual environment -python -m venv test_env - -source test_env/bin/activate # On Windows: test_env\Scripts\activate - -# Install the built package -pip install dist/bee-py-0.1.0.tar.gz -``` - -#### Publish to TestPyPI - -```bash -# Configure Poetry: -poetry config repositories.testpypi https://test.pypi.org/legacy/ -# Publish -poetry publish -r testpypi -#Test the installation -pip install --index-url https://test.pypi.org/simple/ bee-py -``` - -## Modules - -The package provides several modules: - -| Module | Description | -| -------- | ----------------------------------------------------- | -| `agents` | Base classes defining the common interface for agents | -| `llms` | Base classes for text inference (standard or chat) | -| `tools` | Tools that an agent can use | - -## Roadmap - -- 👩‍💻 **Code interpreter**: Run code safely in a sandbox container. -- ⏸️ **Serialization**: Handle complex agentic workflows and easily pause/resume them without losing state. -- 🔍 **Instrumentation**: Full visibility of your agent's inner workings. -- 🎛️ **Production-level** control with caching and error handling. -- 🔁 **API**: OpenAI-compatible Assistants API integration. -- Bee agent performance optimization with additional models -- Examples, tutorials, and comprehensive documentation -- Improvements to building custom agents -- Multi-agent orchestration -- Feature parity with TypeScript version - -## Contributing - -The Bee Agent Framework Python is an open-source project and we ❤️ contributions. Please check our [contribution guidelines](./CONTRIBUTING.md) before getting started. - -### Reporting Issues - -We use [GitHub Issues](https://github.com/i-am-bee/bee-hive/issues) to track public bugs. Please check existing issues before filing new ones. - -### Code of Conduct - -This project adheres to our [Code of Conduct](./CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. - -## Legal Notice - -All content in these repositories including code has been provided by IBM under the associated open source software license and IBM is under no obligation to provide enhancements, updates, or support. IBM developers produced this code as an open source project (not as an IBM product), and IBM makes no assertions as to the level of quality nor security, and will not be maintaining this code going forward. diff --git a/framework/bee-py/bee_agent/__init__.py b/framework/bee-py/bee_agent/__init__.py deleted file mode 100644 index ea1d573..0000000 --- a/framework/bee-py/bee_agent/__init__.py +++ /dev/null @@ -1,31 +0,0 @@ -from .agents import BaseAgent, BeeAgent - -from .llms import BaseLLM, LLM, Prompt, AgentInput - -from .tools import WeatherTool, Tool - -from .memory import BaseMemory, UnconstrainedMemory, ReadOnlyMemory, TokenMemory - -from .memory.message import BaseMessage - -from .memory.serializable import Serializable - -from .utils.roles import Role - -__all__ = [ - "BaseAgent", - "BeeAgent", - "BaseLLM", - "LLM", - "Prompt", - "AgentInput", - "WeatherTool", - "Tool", - "BaseMemory", - "UnconstrainedMemory", - "ReadOnlyMemory", - "TokenMemory", - "BaseMessage", - "Role", - "Serializable", -] diff --git a/framework/bee-py/bee_agent/agents/__init__.py b/framework/bee-py/bee_agent/agents/__init__.py deleted file mode 100644 index b03b0c7..0000000 --- a/framework/bee-py/bee_agent/agents/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .agent import BaseAgent, BeeAgent - - -__all__ = ["BaseAgent", "BeeAgent"] diff --git a/framework/bee-py/bee_agent/agents/agent.py b/framework/bee-py/bee_agent/agents/agent.py deleted file mode 100644 index b770b02..0000000 --- a/framework/bee-py/bee_agent/agents/agent.py +++ /dev/null @@ -1,230 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import asyncio -import json - -from abc import ABC, abstractmethod -from concurrent.futures import ThreadPoolExecutor -from datetime import datetime -from typing import Any, Dict, List, Optional, TypeVar, Union - - -from bee_agent.llms import ( - BaseLLM, - Prompt, - AssistantPromptTemplate, - SystemPromptTemplate, - UserPromptTemplate, -) -from bee_agent.memory import BaseMessage, BaseMemory, UnconstrainedMemory -from bee_agent.tools import Tool -from bee_agent.utils import BeeLogger, BeeEventEmitter, MessageEvent, Role - - -logger = BeeLogger(__name__) -event_emitter = BeeEventEmitter() -T = TypeVar("T") - - -class BaseAgent(ABC): - llm: Optional[BaseLLM] = None - tools: List[Tool] - memory: BaseMemory - - max_iterations = 20 - - @property - def __is_loop_running(self) -> bool: - try: - asyncio.get_running_loop() - return True - except RuntimeError: - return False - - def __init__( - self, - llm: Optional[BaseLLM] = None, - tools: Optional[List[Tool]] = [], - memory: Optional[BaseMemory] = None, - ): - self.llm = llm - self.tools = tools - self.memory = memory if memory else UnconstrainedMemory() - - logger.debug(f"Using model {self.llm.model}") - - @abstractmethod - def _run(self, prompt: Optional[Prompt] = None, options: Optional[T] = None): - pass - - async def init_memory(self): - logger.debug(f"Initializing {type(self.memory).__name__}") - - self.memory.reset() - system_prompt_data = {} - - if len(self.tools): - tool_box = [tool.prompt_data() for tool in self.tools] - system_prompt_data = { - "tools": tool_box, - "tools_length": len(tool_box), - "instructions": "You are a helpful assistant", - } - - await self.memory.add( - BaseMessage.of( - { - "role": Role.SYSTEM, - "text": SystemPromptTemplate.render(system_prompt_data), - "meta": {"createdAt": datetime.now().isoformat()}, - } - ) - ) - - async def plan_step(self, prompt, step_state={}, options=None): - iteration_count = step_state.get("count", 0) - - logger.debug(f"Preparing for iteration: {iteration_count + 1}") - - if iteration_count >= self.max_iterations: - logger.warning("Maximum iterations reached. Stopping.") - return - - if iteration_count == 0: - user_prompt_text = UserPromptTemplate.render( - {"input": prompt.get("prompt", "")} - ) - - event_emitter.emit( - MessageEvent(source=Role.USER, message=prompt.get("prompt", "")) - ) - - await self.memory.add( - BaseMessage.of( - { - "role": Role.USER, - "text": user_prompt_text, - "meta": {"createdAt": datetime.now().isoformat()}, - } - ) - ) - - step_state["count"] = iteration_count + 1 - - output_parts = step_state.pop("output_parts", {}) - if output_parts.get("Function Name") and output_parts.get("Function Input"): - tool_input = json.loads(output_parts.get("Function Input")) - tool_name = output_parts.get("Function Name") - - tool = list(filter(lambda t: t.name == tool_name, self.tools))[0] - - tool_response = tool.run(tool_input) - logger.debug(f"Response from {tool_name}: {tool_response}") - - assistant_prompt_text = AssistantPromptTemplate.render( - { - "thought": output_parts.get("Thought"), - "tool_name": output_parts.get("Function Name"), - "tool_input": tool_input, - "tool_output": tool_response, - } - ) - - event_emitter.emit_many( - [ - MessageEvent( - source="Agent", - state="thought", - message=output_parts.get("Thought"), - ), - MessageEvent( - source="Agent", - state="tool_name", - message=output_parts.get("Function Name"), - ), - MessageEvent( - source="Agent", - state="tool_input", - message=output_parts.get("Function Input"), - ), - ] - ) - - await self.memory.add( - BaseMessage.of( - { - "role": Role.ASSISTANT, - "text": assistant_prompt_text, - "meta": {"createdAt": datetime.now().isoformat()}, - } - ) - ) - - await self.execute_step(prompt, step_state, options) - - async def execute_step(self, prompt, step_state={}, options=None): - logger.debug(f"Running iteration: {step_state.get('count')}") - - response = self._run(prompt, options) - await self.observe_step(response, prompt, step_state, options) - - async def observe_step(self, output, prompt, step_state, options): - logger.debug(f"Reviewing result of iteration: {step_state.get('count')}") - - content = ( - output if type(output) is str else output.messages[0] - ) # output.get("message", {}).get("content") - result = self.llm.parse_output(content, self.tools) if self.llm else content - - if result: - output_parts = {} - for line in result.split("\n"): - if ":" in line: - k, v = line.split(":", 1) - output_parts[k.strip()] = v.strip() - - final_answer = output_parts.get("Final Answer") - if final_answer: - event_emitter.emit( - MessageEvent( - source="Agent", message=final_answer, state="final_answer" - ) - ) - - await self.memory.add( - BaseMessage.of( - { - "role": Role.ASSISTANT, - "text": final_answer, - "meta": {"createdAt": datetime.now().isoformat()}, - } - ) - ) - else: - step_state["output_parts"] = output_parts - await self.plan_step(prompt, step_state, options) - else: - await self.plan_step(prompt, step_state, options) - - def run( - self, prompt: Optional[Union[Prompt, str]] = None, options: Optional[T] = None - ): - _prompt = {"prompt": prompt} if type(prompt) is str else prompt - - async def runner(agent, _prompt): - await agent.init_memory() - await agent.plan_step(_prompt, {"count": 0}, options) - - if self.__is_loop_running: - # Create a separate thread so we can block before returning - with ThreadPoolExecutor(1) as pool: - pool.submit(lambda: asyncio.run(runner(self, _prompt))).result() - else: - # No event loop - asyncio.run(runner(self, _prompt)) - - -class BeeAgent(BaseAgent): - def _run(self, prompt: Prompt, options: Optional[Dict[str, Any]] = None): - if self.llm: - return self.llm.generate(self.memory.messages, options) diff --git a/framework/bee-py/bee_agent/agents/runner.py b/framework/bee-py/bee_agent/agents/runner.py deleted file mode 100644 index 3bec983..0000000 --- a/framework/bee-py/bee_agent/agents/runner.py +++ /dev/null @@ -1,24 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod - - -class BaseRunner(ABC): - _llm = None - tools = [] - iterations = [] - - def __init__(self, llm, tools=[], options=None): - self._llm = llm - self.tools = tools - - @abstractmethod - def init_memory(self, input): - pass - - @abstractmethod - def iterate(self): - pass - - def start_iteration(self): - pass diff --git a/framework/bee-py/bee_agent/llms/__init__.py b/framework/bee-py/bee_agent/llms/__init__.py deleted file mode 100644 index 5edd46c..0000000 --- a/framework/bee-py/bee_agent/llms/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -from .base_output import BaseChatLLMOutput, BaseLLMOutput -from .llm import BaseLLM, LLM, AgentInput -from .prompt import ( - Prompt, - AssistantPromptTemplate, - SystemPromptTemplate, - UserPromptTemplate, -) -from .output import ChatLLMOutput, ChatOutput - -__all__ = [ - "BaseLLM", - "LLM", - "BaseChatLLMOutput", - "BaseLLMOutput", - "Prompt", - "ChatLLMOutput", - "ChatOutput", - "AgentInput", - "AssistantPromptTemplate", - "SystemPromptTemplate", - "UserPromptTemplate", -] diff --git a/framework/bee-py/bee_agent/llms/base_output.py b/framework/bee-py/bee_agent/llms/base_output.py deleted file mode 100644 index b9e40e2..0000000 --- a/framework/bee-py/bee_agent/llms/base_output.py +++ /dev/null @@ -1,26 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod -from dataclasses import dataclass -from typing import Sequence -from bee_agent.memory.message import BaseMessage - - -@dataclass -class BaseLLMOutput: - """Base class for LLM outputs.""" - - pass - - -class BaseChatLLMOutput(BaseLLMOutput, ABC): - """Abstract base class for chat LLM outputs.""" - - @property - @abstractmethod - def messages(self) -> Sequence[BaseMessage]: - """Get the messages from the LLM output. - Returns: - Sequence[BaseMessage]: A read-only sequence of messages - """ - raise NotImplementedError diff --git a/framework/bee-py/bee_agent/llms/llm.py b/framework/bee-py/bee_agent/llms/llm.py deleted file mode 100644 index b0deae9..0000000 --- a/framework/bee-py/bee_agent/llms/llm.py +++ /dev/null @@ -1,127 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod -from typing import Any, Dict, List, Optional, TypeVar, Generic, Union -from dataclasses import dataclass -import re - -from litellm import completion -import math - - -from .base_output import BaseChatLLMOutput -from .output import ChatLLMOutput, ChatOutput -from .prompt import Prompt -from bee_agent.memory.base_memory import BaseMemory, BaseMessage -from bee_agent.utils.custom_logger import BeeLogger -from bee_agent.utils.roles import Role - - -T = TypeVar("T", bound="BaseChatLLMOutput") -logger = BeeLogger(__name__) - - -class BaseLLM(Generic[T], ABC): - """Abstract base class for Language Model implementations.""" - - base_url: Optional[str] - model: Optional[str] - - def __init__(self, base_url: Optional[str] = None, model: Optional[str] = None): - self.base_url = base_url - - if "/" not in model: - self.model = f"ollama_chat/{model}" - else: - self.model = ( - model - if not model.startswith("ollama/") - else f"{model.replace('ollama/', 'ollama_chat/')}" - ) - - @abstractmethod - def inference(self, input: List[BaseMessage], options: Any) -> T: - pass - - @abstractmethod - def parse_output(self, output, tools): - pass - - def generate(self, prompt: Union[Prompt, List[BaseMessage]], options=None) -> T: - if type(prompt) is dict: - input = [BaseMessage.of({"role": Role.USER, "text": prompt.get("prompt")})] - else: - input = prompt - - answer = self.inference(input, options) - return answer - - @abstractmethod - def tokenize(self, input: str) -> T: - pass - - -class LLM(BaseLLM[BaseChatLLMOutput]): - parameters: Dict[str, Any] = {} - chat_endpoint = "/api/chat" - - def __init__( - self, - model: str = "ollama_chat/llama3.1", - base_url: Optional[str] = None, - api_key: Optional[str] = None, - parameters: Dict[str, Any] = {}, - ): - self.api_key = api_key - - h = base_url[:-1] if base_url and base_url.endswith("/") else base_url - self.parameters = { - "temperature": 0, - "repeat_penalty": 1.0, - "num_predict": 2048, - } | parameters - - super().__init__(h, model) - - def prepare_messages(self, input: List[BaseMessage]): - return list(map(lambda x: {"role": x.role, "content": x.text}, input)) - - def inference(self, input: List[BaseMessage], options=None) -> BaseChatLLMOutput: - response = completion( - model=self.model, - messages=self.prepare_messages(input), - base_url=self.base_url, - api_key=self.api_key, - ) - - logger.debug(f"Inference response choices size: {len(response.choices)}") - response_content = ( - response.get("choices", [{}])[0].get("message", {}).get("content", "") - ) - logger.debug(f"Inference response content:\n{response_content}") - - return ChatLLMOutput(output=ChatOutput(response=response_content)) - - def tokenize(self, input: str) -> T: - return {"tokens_count": math.ceil(len(input) / 4)} - - def parse_output(self, output, tools): - if len(tools): - regex = ( - r"Thought: .+\n+(?:Final Answer: [\s\S]+|Function Name: (" - + "|".join(list(map(lambda x: x.name, tools))) - + ")\n+Function Input: \\{.*\\}(\n+Function Output:)?)" - ) - else: - regex = r"Thought: .+\n+Final Answer: [\s\S]+" - r = re.search(regex, output.text) - if r is not None: - return r.group() - - -@dataclass -class AgentInput(Generic[T]): - """Input configuration for agent initialization.""" - - llm: BaseLLM[T] - memory: "BaseMemory" diff --git a/framework/bee-py/bee_agent/llms/output.py b/framework/bee-py/bee_agent/llms/output.py deleted file mode 100644 index 592ba6b..0000000 --- a/framework/bee-py/bee_agent/llms/output.py +++ /dev/null @@ -1,30 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from dataclasses import dataclass -from typing import Sequence, List - -from .base_output import BaseChatLLMOutput -from bee_agent.memory.message import BaseMessage -from bee_agent.utils import Role - - -@dataclass -class ChatOutput: - """Represents a chat output from Ollama LLM.""" - - response: str - - def to_messages(self) -> List[BaseMessage]: - """Convert the response to a list of messages.""" - return [BaseMessage(role=Role.ASSISTANT, text=self.response)] - - -@dataclass -class ChatLLMOutput(BaseChatLLMOutput): - """Concrete implementation of ChatLLMOutput for Ollama.""" - - output: ChatOutput - - @property - def messages(self) -> Sequence[BaseMessage]: - return self.output.to_messages() diff --git a/framework/bee-py/bee_agent/llms/prompt.py b/framework/bee-py/bee_agent/llms/prompt.py deleted file mode 100644 index d0acb78..0000000 --- a/framework/bee-py/bee_agent/llms/prompt.py +++ /dev/null @@ -1,99 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import Any, Optional, TypedDict - -import chevron - - -class Prompt(TypedDict): - prompt: Optional[str] - - -class PromptTemplate: - template: str - - def __init__(self, template: str): - self.template = template - - def render(self, data: dict[str, Any] = {}): - return chevron.render(template=self.template, data=data) - - -UserPromptTemplate = PromptTemplate("Message: {{input}}") - - -AssistantPromptTemplate = PromptTemplate( - "{{#thought}}Thought: {{.}}\n{{/thought}}{{#tool_name}}Function Name: {{.}}\n{{/tool_name}}{{#tool_input}}Function Input: {{.}}\n{{/tool_input}}{{#toolOutput}}Function Output: {{.}}\n{{/toolOutput}}{{#final_answer}}Final Answer: {{.}}{{/final_answer}}" -) - - -SystemPromptTemplate = PromptTemplate( - """# Available functions -{{#tools_length}} -You can only use the following functions. Always use all required parameters. - -{{#tools}} -Function Name: {{name}} -Description: {{description}} -Parameters: {{&schema}} - -{{/tools}} -{{/tools_length}} -{{^tools_length}} -No functions are available. - -{{/tools_length}} -# Communication structure -You communicate only in instruction lines. The format is: "Instruction: expected output". You must only use these instruction lines and must not enter empty lines or anything else between instruction lines. -{{#tools_length}} -You must skip the instruction lines Function Name, Function Input and Function Output if no function calling is required. -{{/tools_length}} - -Message: User's message. You never use this instruction line. -{{^tools_length}} -Thought: A single-line plan of how to answer the user's message. It must be immediately followed by Final Answer. -{{/tools_length}} -{{#tools_length}} -Thought: A single-line step-by-step plan of how to answer the user's message. You can use the available functions defined above. This instruction line must be immediately followed by Function Name if one of the available functions defined above needs to be called, or by Final Answer. Do not provide the answer here. -Function Name: Name of the function. This instruction line must be immediately followed by Function Input. -Function Input: Function parameters. Empty object is a valid parameter. -Function Output: Output of the function in JSON format. -Thought: Continue your thinking process. -{{/tools_length}} -Final Answer: Answer the user or ask for more information or clarification. It must always be preceded by Thought. - -## Examples -Message: Can you translate "How are you" into French? -Thought: The user wants to translate a text into French. I can do that. -Final Answer: Comment vas-tu? - -# Instructions -User can only see the Final Answer, all answers must be provided there. -{{^tools_length}} -You must always use the communication structure and instructions defined above. Do not forget that Thought must be a single-line immediately followed by Final Answer. -{{/tools_length}} -{{#tools_length}} -You must always use the communication structure and instructions defined above. Do not forget that Thought must be a single-line immediately followed by either Function Name or Final Answer. -Functions must be used to retrieve factual or historical information to answer the message. -{{/tools_length}} -If the user suggests using a function that is not available, answer that the function is not available. You can suggest alternatives if appropriate. -When the message is unclear or you need more information from the user, ask in Final Answer. - -# Your capabilities -Prefer to use these capabilities over functions. -- You understand these languages: English, Spanish, French. -- You can translate and summarize, even long documents. - -# Notes -- If you don't know the answer, say that you don't know. -- The current time and date in ISO format can be found in the last message. -- When answering the user, use friendly formats for time and date. -- Use markdown syntax for formatting code snippets, links, JSON, tables, images, files. -- Sometimes, things don't go as planned. Functions may not provide useful information on the first few tries. You should always try a few different approaches before declaring the problem unsolvable. -- When the function doesn't give you what you were asking for, you must either use another function or a different function input. - - When using search engines, you try different formulations of the query, possibly even in a different language. -- You cannot do complex calculations, computations, or data manipulations without using functions. - -# Role -{{instructions}}""" -) diff --git a/framework/bee-py/bee_agent/memory/__init__.py b/framework/bee-py/bee_agent/memory/__init__.py deleted file mode 100644 index 3f4c575..0000000 --- a/framework/bee-py/bee_agent/memory/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -from .message import BaseMessage, BaseMessageMeta -from .base_memory import BaseMemory -from .exceptions import MemoryError, MemoryFatalError -from .unconstrained_memory import UnconstrainedMemory -from .readonly_memory import ReadOnlyMemory -from .token_memory import TokenMemory - -from .base_cache import BaseCache -from .file_cache import FileCache -from .sliding_cache import SlidingCache -from .unconstrained_cache import UnconstrainedCache - -from .serializable import Serializable -from .serializer import Serializer -from .task_map import Task, SlidingTaskMap - -__all__ = [ - "BaseMemory", - "BaseMessageMeta", - "UnconstrainedMemory", - "ReadOnlyMemory", - "TokenMemory", - "MemoryError", - "MemoryFatalError", - "SummarizeMemory", - "SlidingMemory", - "BaseMessage", - "BaseCache", - "FileCache", - "SlidingCache", - "UnconstrainedCache", - "Serializable", - "Serializer", - "Task", - "SlidingTaskMap", -] diff --git a/framework/bee-py/bee_agent/memory/base_cache.py b/framework/bee-py/bee_agent/memory/base_cache.py deleted file mode 100644 index 5132218..0000000 --- a/framework/bee-py/bee_agent/memory/base_cache.py +++ /dev/null @@ -1,107 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod -from typing import Dict, Generic, Any, TypeVar - - -T = TypeVar("T") - - -class BaseCache(ABC, Generic[T]): - """Abstract base class for all Cache implementations.""" - - def __init__(self): - """Initialize the cache with an empty elements dictionary.""" - self._elements: Dict[str, Any] = {} - self._enabled: bool = True - - @property - def enabled(self) -> bool: - """ - Property that indicates if the cache is enabled. - - Returns: - bool: True if cache is enabled, False otherwise - """ - return self._enabled - - @enabled.setter - def enabled(self, value: bool) -> None: - """ - Set the enabled status of the cache. - - Args: - value (bool): The new enabled status - """ - self._enabled = value - - @property - def elements(self) -> Dict[str, Any]: - """ - Property that provides access to the internal elements dictionary. - - Returns: - Dict[str, Any]: The cache elements - """ - return self._elements - - async def serialize(self) -> str: - """Serialize the cache state.""" - snapshot = await self.create_snapshot() - from .serializer import Serializer # Import here to avoid circular imports - - return await Serializer.serialize( - { - "target": { - "module": self.__class__.__module__, - "name": self.__class__.__name__, - }, - "snapshot": snapshot, - } - ) - - @abstractmethod - async def set(self, key: str, value: Any) -> None: - """Add a element in the cache.""" - pass - - @abstractmethod - async def get(self, key: str) -> Any: - """Get a element in the cache.""" - pass - - @abstractmethod - async def has(self, key: str) -> bool: - """Get a element in the cache.""" - pass - - @abstractmethod - async def delete(self, key: str) -> bool: - """Delete a element in the Cache.""" - pass - - @abstractmethod - def clear(self) -> None: - """Clear all the Cache content.""" - pass - - def size(self) -> int: - """Clear all the Cache content.""" - return len(self.elements) - - def is_empty(self) -> bool: - """Check if memory is empty.""" - return len(self.elements) == 0 - - def __iter__(self): - return iter(self.elements) - - @abstractmethod - def create_snapshot(self) -> Any: - """Create a serializable snapshot of current state.""" - pass - - @abstractmethod - def load_snapshot(self, state: Any) -> None: - """Restore state from a snapshot.""" - pass diff --git a/framework/bee-py/bee_agent/memory/base_memory.py b/framework/bee-py/bee_agent/memory/base_memory.py deleted file mode 100644 index 905ba41..0000000 --- a/framework/bee-py/bee_agent/memory/base_memory.py +++ /dev/null @@ -1,88 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod -from typing import List, Optional, Iterable, Any, TYPE_CHECKING - -from .message import BaseMessage - -if TYPE_CHECKING: - from .readonly_memory import ReadOnlyMemory - - -class BaseMemory(ABC): - """Abstract base class for all memory implementations.""" - - @property - @abstractmethod - def messages(self) -> List[BaseMessage]: - """Return list of stored messages.""" - pass - - @abstractmethod - async def add(self, message: BaseMessage, index: Optional[int] = None) -> None: - """Add a message to memory.""" - pass - - @abstractmethod - async def delete(self, message: BaseMessage) -> bool: - """Delete a message from memory.""" - pass - - @abstractmethod - def reset(self) -> None: - """Clear all messages from memory.""" - pass - - async def add_many( - self, messages: Iterable[BaseMessage], start: Optional[int] = None - ) -> None: - """Add multiple messages to memory.""" - counter = 0 - for msg in messages: - index = None if start is None else start + counter - await self.add(msg, index) - counter += 1 - - async def delete_many(self, messages: Iterable[BaseMessage]) -> None: - """Delete multiple messages from memory.""" - for msg in messages: - await self.delete(msg) - - async def splice( - self, start: int, delete_count: int, *items: BaseMessage - ) -> List[BaseMessage]: - """Remove and insert messages at a specific position.""" - total = len(self.messages) - start = max(total + start, 0) if start < 0 else start - delete_count = min(delete_count, total - start) - - deleted_items = self.messages[start : start + delete_count] - await self.delete_many(deleted_items) - await self.add_many(items, start) - - return deleted_items - - def is_empty(self) -> bool: - """Check if memory is empty.""" - return len(self.messages) == 0 - - def __iter__(self): - return iter(self.messages) - - @abstractmethod - def create_snapshot(self) -> Any: - """Create a serializable snapshot of current state.""" - pass - - @abstractmethod - def load_snapshot(self, state: Any) -> None: - """Restore state from a snapshot.""" - pass - - def as_read_only(self) -> "ReadOnlyMemory": - """Return a read-only view of this memory.""" - from .readonly_memory import ( - ReadOnlyMemory, - ) # Import here to avoid circular import - - return ReadOnlyMemory(self) diff --git a/framework/bee-py/bee_agent/memory/exceptions.py b/framework/bee-py/bee_agent/memory/exceptions.py deleted file mode 100644 index d919a1f..0000000 --- a/framework/bee-py/bee_agent/memory/exceptions.py +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import List, Optional - - -class MemoryError(Exception): - """Base class for memory-related exceptions.""" - - pass - - -class MemoryFatalError(MemoryError): - """Fatal memory errors that cannot be recovered from.""" - - def __init__( - self, message: str, errors: Optional[List[Exception]] = None, **kwargs - ): - super().__init__(message) - self.errors = errors or [] - self.is_fatal = kwargs.get("is_fatal", True) - self.is_retryable = kwargs.get("is_retryable", False) diff --git a/framework/bee-py/bee_agent/memory/file_cache.py b/framework/bee-py/bee_agent/memory/file_cache.py deleted file mode 100644 index 8df319b..0000000 --- a/framework/bee-py/bee_agent/memory/file_cache.py +++ /dev/null @@ -1,238 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import os -import aiofiles -from typing import TypeVar, Generic, Dict, Any -from dataclasses import dataclass -from functools import wraps - -from .base_cache import BaseCache -from .sliding_cache import SlidingCache -from .serializer import Serializer - -T = TypeVar("T") - - -def cache(): - """Decorator to cache method results.""" - - def decorator(func): - cache_key = f"_cache_{func.__name__}" - - @wraps(func) - async def wrapper(self, *args, **kwargs): - if not hasattr(self, cache_key): - setattr(self, cache_key, await func(self, *args, **kwargs)) - return getattr(self, cache_key) - - wrapper.clear_cache = lambda self: ( - delattr(self, cache_key) if hasattr(self, cache_key) else None - ) - return wrapper - - return decorator - - -@dataclass -class Input: - """Input configuration for FileCache.""" - - full_path: str - - -class FileCache(BaseCache[T], Generic[T]): - """File-based cache implementation.""" - - def __init__(self, input_config: Input): - """Initialize the FileCache with the given input configuration.""" - super().__init__() - self._input = input_config - self._register() - - @classmethod - def _register(cls) -> None: - """Register the cache class.""" - Serializer.register( - cls, - { - "to_plain": lambda x: x.create_snapshot(), - "from_plain": lambda x: cls.from_snapshot(x), - }, - ) - - @property - def source(self) -> str: - """Get the source file path.""" - return self._input.full_path - - @classmethod - async def from_provider( - cls, provider: BaseCache[T], input_config: Input - ) -> "FileCache[T]": - """Create a new FileCache instance from a provider.""" - async with aiofiles.open(input_config.full_path, "w") as f: - serialized = await provider.serialize() # Await the serialization - await f.write(serialized) - return cls(input_config) - - @cache() - async def _get_provider(self) -> BaseCache[T]: - """Get the cache provider instance.""" - try: - exists = os.path.isfile(self._input.full_path) - except Exception: - exists = False - - if exists: - async with aiofiles.open(self._input.full_path, "r") as f: - serialized = await f.read() - - deserialized = await Serializer.deserialize(serialized) - target = deserialized["target"] - snapshot = deserialized["snapshot"] - - Target = Serializer.get_factory(target).ref - instance = Target.from_snapshot(snapshot) - - if not isinstance(instance, BaseCache): - raise TypeError( - "Provided file does not serialize any instance of BaseCache class." - ) - - return instance - else: - return SlidingCache(size=float("inf"), ttl=float("inf")) - - async def reload(self) -> None: - """Reload the cache from the file.""" - self._get_provider.clear_cache(self) - await self._get_provider() - - async def _save(self) -> None: - """Save the cache to the file.""" - provider = await self._get_provider() - async with aiofiles.open(self._input.full_path, "w") as f: - serialized = await provider.serialize() # Await the serialization - await f.write(serialized) - - async def size(self) -> int: - """Get the number of items in the cache.""" - provider = await self._get_provider() - return await provider.size() - - async def set(self, key: str, value: T) -> None: - """Set a value in the cache.""" - provider = await self._get_provider() - await provider.set(key, value) - try: - await provider.get(key) - finally: - await self._save() - - async def get(self, key: str) -> T: - """Get a value from the cache.""" - provider = await self._get_provider() - return await provider.get(key) - - async def has(self, key: str) -> bool: - """Check if a key exists in the cache.""" - provider = await self._get_provider() - return await provider.has(key) - - async def delete(self, key: str) -> bool: - """Delete a key from the cache.""" - provider = await self._get_provider() - result = await provider.delete(key) - await self._save() - return result - - async def clear(self) -> None: - """Clear all items from the cache.""" - provider = await self._get_provider() - await provider.clear() - await self._save() - - async def create_snapshot(self) -> Dict[str, Any]: - """Create a serializable snapshot of the current state.""" - return { - "input": {"full_path": self._input.full_path}, - "provider": await self._get_provider(), - } - - def load_snapshot(self, snapshot: Dict[str, Any]) -> None: - """Restore state from a snapshot.""" - for key, value in snapshot.items(): - setattr(self, key, value) - - @classmethod - def from_snapshot(cls, snapshot: Dict[str, Any]) -> "FileCache[T]": - """Create an instance from a snapshot.""" - instance = cls(Input(full_path=snapshot["input"]["full_path"])) - instance.load_snapshot(snapshot) - return instance - - -if __name__ == "__main__": - import asyncio - import tempfile - import os - from pathlib import Path - - async def test_file_cache(): - try: - # Create a temporary directory for our test cache files - with tempfile.TemporaryDirectory() as temp_dir: - cache_file = Path(temp_dir) / "test_cache.json" - - print("\n1. Creating and Testing Basic Cache Operations:") - # Initialize the cache - cache = FileCache[str](Input(str(cache_file))) - - # Test basic operations - print("Setting values in cache...") - await cache.set("key1", "value1") - await cache.set("key2", "value2") - - # Verify values - value1 = await cache.get("key1") - value2 = await cache.get("key2") - print(f"Retrieved values: key1={value1}, key2={value2}") - - # Check existence - has_key = await cache.has("key1") - print(f"Has key1: {has_key}") - - # Get cache size - size = await cache.size() - print(f"Cache size: {size}") - - print("\n2. Testing File Persistence:") - # Verify file was created - print(f"Cache file exists: {cache_file.exists()}") - print(f"Cache file size: {cache_file.stat().st_size} bytes") - - print("\n3. Testing Delete Operation:") - # Delete a key - deleted = await cache.delete("key2") - print(f"Deleted key2: {deleted}") - has_key2 = await cache.has("key2") - print(f"Has key2 after delete: {has_key2}") - - print("\n4. Testing Clear Operation:") - # Clear the cache - await cache.clear() - size = await cache.size() - print(f"Cache size after clear: {size}") - - print("\n5. Testing Provider Creation:") - # Test with non-existent file - new_file = Path(temp_dir) / "new_cache.json" - new_cache = FileCache[str](Input(str(new_file))) - await new_cache.set("test_key", "test_value") - print(f"Created new cache file: {new_file.exists()}") - - except Exception as e: - print(f"Error during test: {str(e)}") - - # Run the test - asyncio.run(test_file_cache()) diff --git a/framework/bee-py/bee_agent/memory/message.py b/framework/bee-py/bee_agent/memory/message.py deleted file mode 100644 index 5110e2c..0000000 --- a/framework/bee-py/bee_agent/memory/message.py +++ /dev/null @@ -1,112 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC -from typing import Dict, Any, Optional, Type -from datetime import datetime -from copy import deepcopy -from dataclasses import dataclass - -from bee_agent.utils import Role, RoleType - - -# Basic Serialization implementation -class Serializable(ABC): - """Base class for serializable objects.""" - - @classmethod - def register(cls): - # Registration logic would go here - pass - - def serialize(self) -> Dict[str, Any]: - """Serialize the object to a dictionary.""" - return self.create_snapshot() - - @classmethod - def from_serialized( - cls: Type["Serializable"], data: Dict[str, Any] - ) -> "Serializable": - """Create an instance from serialized data.""" - instance = cls.__new__(cls) - instance.load_snapshot(data) - return instance - - -# TypedDict equivalent for BaseMessageMeta -class BaseMessageMeta(Dict[str, Any]): - def __init__(self, **kwargs): - super().__init__(**kwargs) - self.created_at: Optional[datetime] = kwargs.get("created_at") - - -# Equivalent to TypeScript's BaseMessageInput interface -@dataclass -class BaseMessageInput: - role: RoleType - text: str - meta: Optional[BaseMessageMeta] = None - - -@dataclass -class BaseMessage(Serializable): - role: Role - text: str - meta: Optional[BaseMessageMeta] = None - - @classmethod - def of(cls, data: Dict[str, str]) -> "BaseMessage": - return cls(role=data["role"], text=data["text"]) - - def __hash__(self): - """Make BaseMessage hashable by using role and text.""" - return hash((self.role, self.text)) - - def __eq__(self, other): - """Define equality for BaseMessage.""" - if not isinstance(other, BaseMessage): - return False - return ( - self.role == other.role - and self.text == other.text - and self.meta == other.meta - ) - - def create_snapshot(self) -> Dict[str, Any]: - """Create a serializable snapshot of the message.""" - return {"role": self.role, "text": self.text, "meta": deepcopy(self.meta)} - - def load_snapshot(self, state: Dict[str, Any]) -> None: - """Load message state from a snapshot.""" - for key, value in state.items(): - setattr(self, key, value) - return self - - @classmethod - def register(cls): - """Register the class for serialization.""" - super().register() - - -# Example usage: -if __name__ == "__main__": - # Create a message using the of() factory method - message = BaseMessage.of( - { - "role": Role.USER, - "text": "Hello, how are you?", - "meta": {"created_at": datetime.now()}, - } - ) - message = BaseMessage.of( - { - "role": Role.USER, - "text": "Hello, how are you?", - "meta": {"created_at": datetime.now()}, - } - ) - print(message) - # Serialize the message - serialized = message.serialize() - print(serialized) - # Create a new message from serialized data - deserialized = BaseMessage.from_serialized(serialized) diff --git a/framework/bee-py/bee_agent/memory/readonly_memory.py b/framework/bee-py/bee_agent/memory/readonly_memory.py deleted file mode 100644 index 26c2f9c..0000000 --- a/framework/bee-py/bee_agent/memory/readonly_memory.py +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import List, Dict, Optional -from .base_memory import BaseMemory -from .message import BaseMessage - - -class ReadOnlyMemory(BaseMemory): - """Read-only wrapper for a memory instance.""" - - def __init__(self, source: BaseMemory): - self.source = source - - @property - def messages(self) -> List[BaseMessage]: - return self.source.messages - - async def add(self, message: BaseMessage, index: Optional[int] = None) -> None: - pass # No-op for read-only memory - - async def delete(self, message: BaseMessage) -> bool: - return False # No-op for read-only memory - - def reset(self) -> None: - pass # No-op for read-only memory - - def create_snapshot(self) -> Dict: - return {"source": self.source} - - def load_snapshot(self, state: Dict) -> None: - self.source = state["source"] - - def as_read_only(self) -> "ReadOnlyMemory": - """Return self since already read-only.""" - return self diff --git a/framework/bee-py/bee_agent/memory/serializable.py b/framework/bee-py/bee_agent/memory/serializable.py deleted file mode 100644 index 5d7ec99..0000000 --- a/framework/bee-py/bee_agent/memory/serializable.py +++ /dev/null @@ -1,102 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod -from typing import Dict, Any, Type, TypeVar, Optional, ClassVar -from copy import deepcopy - -T = TypeVar("T") - - -class Serializable(ABC): - """Base class for all serializable objects.""" - - _registered_classes: ClassVar[Dict[str, Type["Serializable"]]] = {} - - def __init_subclass__(cls, **kwargs): - """Automatically register subclasses when they're created.""" - super().__init_subclass__(**kwargs) - cls._registered_classes[cls.__name__] = cls - - @classmethod - def register(cls, aliases: Optional[list[str]] = None) -> None: - """Register the class and any aliases for serialization.""" - cls._registered_classes[cls.__name__] = cls - if aliases: - for alias in aliases: - if ( - alias in cls._registered_classes - and cls._registered_classes[alias] != cls - ): - raise ValueError( - f"Alias '{alias}' already registered to a different class" - ) - cls._registered_classes[alias] = cls - - @classmethod - def from_serialized(cls: Type[T], data: Dict[str, Any]) -> T: - """Create an instance from serialized data.""" - instance = cls.__new__(cls) - Serializable.__init__(instance) - instance.load_snapshot(data) - return instance - - @classmethod - def from_snapshot(cls: Type[T], data: Dict[str, Any]) -> T: - """Create an instance from a snapshot.""" - instance = cls.__new__(cls) - Serializable.__init__(instance) - instance.load_snapshot(data) - return instance - - def serialize(self) -> Dict[str, Any]: - """Serialize the object to a dictionary.""" - return {"__class": self.__class__.__name__, "__value": self.create_snapshot()} - - @abstractmethod - def create_snapshot(self) -> Dict[str, Any]: - """Create a serializable snapshot of the object's state.""" - raise NotImplementedError - - @abstractmethod - def load_snapshot(self, state: Dict[str, Any]) -> None: - """Load object state from a snapshot.""" - raise NotImplementedError - - def clone(self: T) -> T: - """Create a deep copy of the object.""" - snapshot = self.create_snapshot() - return self.__class__.from_snapshot(deepcopy(snapshot)) - - -# Example of how to use the base class: -class ExampleSerializable(Serializable): - def __init__(self, data: str): - super().__init__() - self.data = data - - @classmethod - def register(cls, aliases: Optional[list[str]] = None) -> None: - """Register with custom aliases.""" - super().register(aliases) - - def create_snapshot(self) -> Dict[str, Any]: - return {"data": self.data} - - def load_snapshot(self, state: Dict[str, Any]) -> None: - self.data = state["data"] - - -# Usage example: -if __name__ == "__main__": - # Register the class with an alias - ExampleSerializable.register(aliases=["Example", "ExampleClass"]) - - # Create and serialize an instance - obj = ExampleSerializable("test data") - serialized = obj.serialize() - - # Create new instance from serialized data - new_obj = ExampleSerializable.from_serialized(serialized["__value"]) - - # Create a clone - cloned = obj.clone() diff --git a/framework/bee-py/bee_agent/memory/serializer.py b/framework/bee-py/bee_agent/memory/serializer.py deleted file mode 100644 index 2cc4b31..0000000 --- a/framework/bee-py/bee_agent/memory/serializer.py +++ /dev/null @@ -1,263 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod -import json -from typing import Any, Dict, Type, TypeVar, Optional, Callable -import base64 -from datetime import datetime -from .task_map import SlidingTaskMap, Task - - -T = TypeVar("T") - - -class SerializerError(Exception): - """Custom error for serialization issues.""" - - pass - - -class SerializerFactory: - """Factory for serializable class registration and instantiation.""" - - def __init__(self, cls_ref: Type[Any]): - self.ref = cls_ref - self.module = cls_ref.__module__ - self.name = cls_ref.__name__ - self.to_plain = None - self.from_plain = None - self.create_empty = None - self.update_instance = None - - -class Serializable(ABC): - """Base class for serializable objects.""" - - @classmethod - def register(cls) -> None: - """Register for serialization.""" - Serializer.register_serializable(cls) - - @classmethod - def from_snapshot(cls: Type[T], snapshot: Dict[str, Any]) -> T: - """Create instance from snapshot.""" - instance = cls() - instance.load_snapshot(snapshot) - return instance - - @abstractmethod - async def create_snapshot(self) -> Dict[str, Any]: - """Create serializable snapshot.""" - pass - - @abstractmethod - def load_snapshot(self, snapshot: Dict[str, Any]) -> None: - """Restore from snapshot.""" - pass - - -class Serializer: - """Main serializer class.""" - - _factories: Dict[str, SerializerFactory] = {} - - @classmethod - def register_serializable(cls, target_cls: Type[Any]) -> None: - """Register a serializable class.""" - # Register with both module name and __main__ - names = [ - f"{target_cls.__module__}.{target_cls.__name__}", - f"__main__.{target_cls.__name__}", - ] - factory = SerializerFactory(target_cls) - factory.to_plain = lambda x: x.create_snapshot() - factory.from_plain = target_cls.from_snapshot - - for name in names: - cls._factories[name] = factory - - @classmethod - def register(cls, target_cls: Type[Any], processors: Dict[str, Callable]): - """Register a class with custom processors.""" - names = [ - f"{target_cls.__module__}.{target_cls.__name__}", - f"__main__.{target_cls.__name__}", - ] - factory = SerializerFactory(target_cls) - factory.to_plain = processors.get("to_plain") - factory.from_plain = processors.get("from_plain") - factory.create_empty = processors.get("create_empty") - factory.update_instance = processors.get("update_instance") - - for name in names: - cls._factories[name] = factory - - @classmethod - def get_factory(cls, class_name: str) -> SerializerFactory: - """Get factory for class name.""" - factory = cls._factories.get(class_name) - if not factory: - raise SerializerError(f"Class {class_name} not registered") - return factory - - @classmethod - async def serialize(cls, data: Any) -> str: - """Serialize data to JSON string with async support.""" - - async def serialize_obj(obj: Any) -> Any: - if isinstance(obj, (str, int, float, bool)) or obj is None: - return obj - - if isinstance(obj, (list, tuple)): - return [await serialize_obj(item) for item in obj] - - if isinstance(obj, dict): - return {str(k): await serialize_obj(v) for k, v in obj.items()} - - class_name = f"{obj.__class__.__module__}.{obj.__class__.__name__}" - try: - factory = cls.get_factory(class_name) - if factory.to_plain: - snapshot = ( - await obj.create_snapshot() - if hasattr(obj, "create_snapshot") - else factory.to_plain(obj) - ) - return { - "__type": class_name, - "__value": await serialize_obj(snapshot), - } - except SerializerError: - pass - - raise SerializerError(f"Cannot serialize object of type {class_name}") - - serialized_data = await serialize_obj(data) - return json.dumps(serialized_data) - - @classmethod - async def deserialize(cls, data: str) -> Any: - """Deserialize JSON string to object with async support.""" - - async def deserialize_obj(obj: Any) -> Any: - if isinstance(obj, (str, int, float, bool)) or obj is None: - return obj - - if isinstance(obj, list): - return [await deserialize_obj(item) for item in obj] - - if isinstance(obj, dict): - if "__type" in obj: - factory = cls.get_factory(obj["__type"]) - if factory.from_plain: - return factory.from_plain(await deserialize_obj(obj["__value"])) - return {k: await deserialize_obj(v) for k, v in obj.items()} - - return obj - - return await deserialize_obj(json.loads(data)) - - -# Register basic types -for type_cls in (list, dict, set): - Serializer.register( - type_cls, - { - "to_plain": lambda x: list(x) if isinstance(x, (list, set)) else dict(x), - "from_plain": lambda x: type_cls(x), - }, - ) - -Serializer.register( - datetime, - { - "to_plain": lambda x: x.isoformat(), - "from_plain": lambda x: datetime.fromisoformat(x), - }, -) - -Serializer.register( - bytes, - { - "to_plain": lambda x: base64.b64encode(x).decode("utf-8"), - "from_plain": lambda x: base64.b64decode(x.encode("utf-8")), - }, -) - -Serializer.register( - SlidingTaskMap, - { - "to_plain": lambda value: { - "config": {"size": value.size, "ttl": value.ttl}, - "entries": list(value.entries()), - }, - "from_plain": lambda data: SlidingTaskMap.from_snapshot(data), - "create_empty": lambda: SlidingTaskMap(size=1, ttl=1000), - "update_instance": lambda instance, update: instance.load_snapshot(update), - }, -) - -# Register Task for serialization -Serializer.register( - Task, - { - "to_plain": lambda task: { - "value": task.get_value() if task.is_resolved() else None, - "state": task.get_state(), - }, - "from_plain": lambda data: Task.from_snapshot(data), - "create_empty": lambda: Task(), - "update_instance": lambda instance, update: instance.load_snapshot(update), - }, -) - -if __name__ == "__main__": - import asyncio - from typing import Optional - - class User(Serializable): - def __init__(self, name: str = "", age: int = 0, email: Optional[str] = None): - self.name = name - self.age = age - self.email = email - - async def create_snapshot(self) -> Dict[str, Any]: - return {"name": self.name, "age": self.age, "email": self.email} - - def load_snapshot(self, snapshot: Dict[str, Any]) -> None: - self.name = snapshot["name"] - self.age = snapshot["age"] - self.email = snapshot.get("email") - - # Register the class - User.register() - - async def main(): - try: - # Create and test serialization - user = User("Alice", 30, "alice@example.com") - - print("\n1. Basic User Serialization:") - serialized = await Serializer.serialize(user) - print(f"Serialized User: {serialized}") - - deserialized = await Serializer.deserialize(serialized) - print(f"Deserialized User: {deserialized.name}, {deserialized.age}") - - # Test with built-in types - print("\n2. Built-in Types Serialization:") - data = {"user": user, "numbers": [1, 2, 3], "timestamp": datetime.now()} - - serialized = await Serializer.serialize(data) - print(f"Serialized Data: {serialized}") - - deserialized = await Serializer.deserialize(serialized) - print(f"Deserialized Data (user name): {deserialized['user'].name}") - - except SerializerError as e: - print(f"Serialization Error: {e}") - except Exception as e: - print(f"Unexpected Error: {str(e)}") - - # Run the async main function - asyncio.run(main()) diff --git a/framework/bee-py/bee_agent/memory/sliding_cache.py b/framework/bee-py/bee_agent/memory/sliding_cache.py deleted file mode 100644 index b85f5aa..0000000 --- a/framework/bee-py/bee_agent/memory/sliding_cache.py +++ /dev/null @@ -1,116 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import Generic, TypeVar, Optional, Dict, Any -from collections import OrderedDict -import time -from .base_cache import BaseCache -from .serializer import Serializer - -T = TypeVar("T") - - -class SlidingCache(BaseCache[T], Generic[T]): - """Cache implementation using a sliding window strategy.""" - - def __init__(self, size: float = float("inf"), ttl: Optional[float] = None): - """ - Initialize the sliding cache. - - Args: - size: Maximum number of items (default: infinite) - ttl: Time-to-live in seconds (default: None) - """ - super().__init__() - self._max_size = size - self._ttl = ttl - self._items: OrderedDict[str, tuple[T, float]] = OrderedDict() - # Register for serialization - self._register() - - @classmethod - def _register(cls) -> None: - """Register this class for serialization.""" - Serializer.register_serializable(cls) - - def _evict_expired(self) -> None: - """Remove expired entries.""" - if self._ttl is None: - return - - current_time = time.time() - expired_keys = [ - key - for key, (_, timestamp) in self._items.items() - if current_time - timestamp > self._ttl - ] - - for key in expired_keys: - self._items.pop(key, None) - - def _evict_overflow(self) -> None: - """Remove oldest entries if size limit is exceeded.""" - while len(self._items) > self._max_size: - self._items.popitem(last=False) - - async def set(self, key: str, value: T) -> None: - """Set a value in the cache.""" - self._evict_expired() - self._items[key] = (value, time.time()) - self._evict_overflow() - - async def get(self, key: str) -> Optional[T]: - """Get a value from the cache.""" - self._evict_expired() - if key in self._items: - value, _ = self._items[key] - # Move to end (most recently used) - self._items.move_to_end(key) - return value - return None - - async def has(self, key: str) -> bool: - """Check if a key exists in the cache.""" - self._evict_expired() - return key in self._items - - async def delete(self, key: str) -> bool: - """Delete a key from the cache.""" - if key in self._items: - del self._items[key] - return True - return False - - async def clear(self) -> None: - """Clear all items from the cache.""" - self._items.clear() - - async def size(self) -> int: - """Get the current number of items in the cache.""" - self._evict_expired() - return len(self._items) - - async def create_snapshot(self) -> Dict[str, Any]: - """Create a serializable snapshot of the current state.""" - self._evict_expired() - return { - "max_size": self._max_size, - "ttl": self._ttl, - "items": [(k, v[0], v[1]) for k, v in self._items.items()], - } - - def load_snapshot(self, snapshot: Dict[str, Any]) -> None: - """Restore state from a snapshot.""" - self._max_size = snapshot["max_size"] - self._ttl = snapshot["ttl"] - self._items = OrderedDict() - for key, value, timestamp in snapshot["items"]: - self._items[key] = (value, timestamp) - - @classmethod - def from_snapshot(cls, snapshot: Dict[str, Any]) -> "SlidingCache[T]": - """Create an instance from a snapshot.""" - instance = cls( - size=snapshot.get("max_size", float("inf")), ttl=snapshot.get("ttl") - ) - instance.load_snapshot(snapshot) - return instance diff --git a/framework/bee-py/bee_agent/memory/sliding_memory.py b/framework/bee-py/bee_agent/memory/sliding_memory.py deleted file mode 100644 index 8230a85..0000000 --- a/framework/bee-py/bee_agent/memory/sliding_memory.py +++ /dev/null @@ -1,130 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import List, Optional, Dict, Any, Callable, Union, TypedDict -from copy import copy -from dataclasses import dataclass -from .base_memory import BaseMemory -from .message import BaseMessage - - -class SlidingMemoryHandlers(TypedDict, total=False): - """Type definition for SlidingMemory handlers.""" - - removal_selector: Callable[ - [List[BaseMessage]], Union[BaseMessage, List[BaseMessage]] - ] - - -@dataclass -class SlidingMemoryConfig: - """Configuration for SlidingMemory.""" - - size: int - handlers: Optional[SlidingMemoryHandlers] = None - - -class SlidingMemory(BaseMemory): - """Memory implementation using a sliding window approach.""" - - def __init__(self, config: SlidingMemoryConfig): - """Initialize SlidingMemory with given configuration. - - Args: - config: Configuration including window size and optional handlers - """ - self._messages: List[BaseMessage] = [] - self.config = config - - # Set default handlers if not provided - if self.config.handlers is None: - self.config.handlers = {} - - # Set default removal selector if not provided - if "removal_selector" not in self.config.handlers: - self.config.handlers["removal_selector"] = lambda messages: [messages[0]] - - @property - def messages(self) -> List[BaseMessage]: - """Get list of stored messages.""" - return self._messages - - def _is_overflow(self, additional_messages: int = 1) -> bool: - """Check if adding messages would cause overflow.""" - return len(self._messages) + additional_messages > self.config.size - - def _ensure_range(self, index: int, min_val: int, max_val: int) -> int: - """Ensure index is within the specified range.""" - return max(min_val, min(index, max_val)) - - async def add(self, message: BaseMessage, index: Optional[int] = None) -> None: - """Add a message to memory, managing window size. - - Args: - message: Message to add - index: Optional position to insert message - - Raises: - MemoryFatalError: If removal selector fails to prevent overflow - """ - # Check for overflow - if self._is_overflow(): - # Get messages to remove using removal selector - to_remove = self.config.handlers["removal_selector"](self._messages) - if not isinstance(to_remove, list): - to_remove = [to_remove] - - # Remove selected messages - for msg in to_remove: - try: - msg_index = self._messages.index(msg) - self._messages.pop(msg_index) - except ValueError: - raise MemoryError( - "Cannot delete non existing message.", - context={"message": msg, "messages": self._messages}, - ) - - # Check if we still have overflow - if self._is_overflow(): - raise MemoryError( - "Custom memory removalSelector did not return enough messages. Memory overflow has occurred." - ) - - # Add new message - if index is None: - index = len(self._messages) - index = self._ensure_range(index, 0, len(self._messages)) - self._messages.insert(index, message) - - async def delete(self, message: BaseMessage) -> bool: - """Delete a message from memory. - - Args: - message: Message to delete - - Returns: - bool: True if message was found and deleted - """ - try: - self._messages.remove(message) - return True - except ValueError: - return False - - def reset(self) -> None: - """Clear all messages from memory.""" - self._messages.clear() - - def create_snapshot(self) -> Dict[str, Any]: - """Create a serializable snapshot of current state.""" - return { - "config": {"size": self.config.size, "handlers": self.config.handlers}, - "messages": copy(self._messages), - } - - def load_snapshot(self, state: Dict[str, Any]) -> None: - """Restore state from a snapshot.""" - self.config = SlidingMemoryConfig( - size=state["config"]["size"], handlers=state["config"]["handlers"] - ) - self._messages = copy(state["messages"]) diff --git a/framework/bee-py/bee_agent/memory/summarize_memory.py b/framework/bee-py/bee_agent/memory/summarize_memory.py deleted file mode 100644 index bed7039..0000000 --- a/framework/bee-py/bee_agent/memory/summarize_memory.py +++ /dev/null @@ -1,79 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import List, Optional, Dict, Iterable, TYPE_CHECKING - -from .base_memory import BaseMemory -from .message import BaseMessage -from bee_agent.utils import Role - - -if TYPE_CHECKING: - from bee_agent.llms import BaseLLM - - -class SummarizeMemory(BaseMemory): - """Memory implementation that summarizes conversations.""" - - def __init__(self, llm: "BaseLLM"): - self._messages: List[BaseMessage] = [] - self.llm = llm - - @property - def messages(self) -> List[BaseMessage]: - return self._messages - - async def add(self, message: BaseMessage, index: Optional[int] = None) -> None: - """Add a message and trigger summarization if needed.""" - messages_to_summarize = self._messages + [message] - summary = self._summarize_messages(messages_to_summarize) - - self._messages = [BaseMessage(role=Role.SYSTEM, text=summary)] - - async def add_many( - self, messages: Iterable[BaseMessage], start: Optional[int] = None - ) -> None: - """Add multiple messages and summarize.""" - messages_to_summarize = self._messages + list(messages) - summary = self._summarize_messages(messages_to_summarize) - - self._messages = [BaseMessage(role=Role.SYSTEM, text=summary)] - - def _summarize_messages(self, messages: List[BaseMessage]) -> str: - """Summarize a list of messages using the LLM.""" - if not messages: - return "" - - prompt = { - "prompt": """Summarize the following conversation. Be concise but include all key information. - -Previous messages: -{} - -Summary:""".format( - "\n".join([f"{msg.role}: {msg.text}" for msg in messages]) - ) - } - - # Generate is synchronous, not async - response = self.llm.generate(prompt) - return response.output.response - - async def delete(self, message: BaseMessage) -> bool: - """Delete a message from memory.""" - try: - self._messages.remove(message) - return True - except ValueError: - return False - - def reset(self) -> None: - """Clear all messages from memory.""" - self._messages.clear() - - def create_snapshot(self) -> Dict: - """Create a serializable snapshot of current state.""" - return {"messages": self._messages.copy()} - - def load_snapshot(self, state: Dict) -> None: - """Restore state from a snapshot.""" - self._messages = state["messages"].copy() diff --git a/framework/bee-py/bee_agent/memory/task_map.py b/framework/bee-py/bee_agent/memory/task_map.py deleted file mode 100644 index 7642637..0000000 --- a/framework/bee-py/bee_agent/memory/task_map.py +++ /dev/null @@ -1,148 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import Any, Dict, Generic, List, TypeVar, Optional -import time -from collections import OrderedDict - -K = TypeVar("K") -V = TypeVar("V") - - -class Task: - def __init__(self): - self._value = None - self._state = "pending" - self._resolved = False - - def resolve(self, value: Any) -> None: - self._value = value - self._state = "resolved" - self._resolved = True - - def get_value(self) -> Any: - return self._value - - def get_state(self) -> str: - return self._state - - def is_resolved(self) -> bool: - return self._resolved - - @classmethod - def from_snapshot(cls, snapshot: Dict[str, Any]) -> "Task": - """Create instance from snapshot data.""" - task = cls() - if snapshot["state"] == "resolved": - task.resolve(snapshot["value"]) - return task - - def load_snapshot(self, snapshot: Dict[str, Any]) -> None: - """Load state from snapshot data.""" - if snapshot["state"] == "resolved": - self.resolve(snapshot["value"]) - - -class SlidingTaskMap(Generic[K, V]): - """ - A size-limited map that evicts oldest entries when full. - Optionally supports TTL-based eviction. - """ - - def __init__(self, size: float, ttl: Optional[float] = None): - """ - Initialize the sliding map. - - Args: - size: Maximum number of items to store - ttl: Time-to-live in seconds for entries (optional) - """ - self._max_size = size - self._ttl = ttl - self._items: OrderedDict[K, tuple[V, float]] = OrderedDict() - - def _evict_expired(self) -> None: - """Remove expired entries based on TTL.""" - if self._ttl is None: - return - - current_time = time.time() - expired_keys = [ - key - for key, (_, timestamp) in self._items.items() - if current_time - timestamp > self._ttl - ] - - for key in expired_keys: - self.delete(key) - - def get(self, key: K) -> Optional[V]: - """Get a value by key, handling expiration.""" - self._evict_expired() - if key in self._items: - value, _ = self._items[key] - # Move to end to mark as recently used - self._items.move_to_end(key) - return value - return None - - def set(self, key: K, value: V) -> None: - """Set a value, handling size limits.""" - self._evict_expired() - - # If we're at max size and this is a new key, remove oldest - if len(self._items) >= self._max_size and key not in self._items: - self._items.popitem(last=False) - - self._items[key] = (value, time.time()) - self._items.move_to_end(key) - - def has(self, key: K) -> bool: - """Check if a key exists and hasn't expired.""" - self._evict_expired() - return key in self._items - - def delete(self, key: K) -> bool: - """Delete a key, returning True if it existed.""" - if key in self._items: - value, _ = self._items.pop(key) - if isinstance(value, Task): - value.destructor() - return True - return False - - def clear(self) -> None: - """Remove all items.""" - for key in list(self._items.keys()): - self.delete(key) - - @property - def size(self) -> int: - """Get current number of items.""" - self._evict_expired() - return len(self._items) - - @property - def ttl(self) -> Optional[float]: - """Get the TTL value.""" - return self._ttl - - def entries(self) -> List[tuple[K, V]]: - """Get all entries for serialization.""" - return [(k, v[0]) for k, v in self._items.items()] - - @classmethod - def from_snapshot(cls, snapshot: Dict[str, Any]) -> "SlidingTaskMap": - """Create instance from snapshot data.""" - instance = cls(size=snapshot["config"]["size"], ttl=snapshot["config"]["ttl"]) - for key, value in snapshot["entries"]: - instance.set(key, value) - return instance - - def load_snapshot(self, snapshot: Dict[str, Any]) -> None: - """Load state from snapshot data.""" - self._size = snapshot["config"]["size"] - self._ttl = snapshot["config"]["ttl"] - self._items.clear() - current_time = time.time() - for key, value in snapshot["entries"]: - self._items[key] = (value, current_time) diff --git a/framework/bee-py/bee_agent/memory/token_memory.py b/framework/bee-py/bee_agent/memory/token_memory.py deleted file mode 100644 index 401c9db..0000000 --- a/framework/bee-py/bee_agent/memory/token_memory.py +++ /dev/null @@ -1,129 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import List, Optional, Dict, Any -from copy import copy -from .base_memory import BaseMemory -from .message import BaseMessage - - -class TokenMemory(BaseMemory): - """Memory implementation that respects token limits.""" - - def __init__( - self, - llm: Any, - max_tokens: Optional[int] = None, - sync_threshold: float = 0.25, - capacity_threshold: float = 0.75, - handlers: Optional[Dict] = None, - ): - self._messages: List[BaseMessage] = [] - self.llm = llm - self.max_tokens = max_tokens - self.threshold = capacity_threshold - self.sync_threshold = sync_threshold - self._tokens_by_message = {} - - self.handlers = { - "estimate": ( - handlers.get("estimate", self._default_estimate) - if handlers - else self._default_estimate - ), - "removal_selector": ( - handlers.get("removal_selector", lambda msgs: msgs[0]) - if handlers - else lambda msgs: msgs[0] - ), - } - - if not 0 <= self.threshold <= 1: - raise ValueError('"capacity_threshold" must be a number in range (0, 1)') - - @staticmethod - def _default_estimate(msg: BaseMessage) -> int: - return int((len(msg.role) + len(msg.text)) / 4) - - def _get_message_key(self, message: BaseMessage) -> str: - """Generate a unique key for a message.""" - return f"{message.role}:{message.text}" - - @property - def messages(self) -> List[BaseMessage]: - return self._messages - - @property - def tokens_used(self) -> int: - return sum( - info.get("tokens_count", 0) for info in self._tokens_by_message.values() - ) - - @property - def is_dirty(self) -> bool: - return any(info.get("dirty", True) for info in self._tokens_by_message.values()) - - async def sync(self) -> None: - """Synchronize token counts with LLM.""" - for msg in self._messages: - key = self._get_message_key(msg) - cache = self._tokens_by_message.get(key, {}) - if cache.get("dirty", True): - try: - result = self.llm.tokenize([msg]) - self._tokens_by_message[key] = { - "tokens_count": result["tokens_count"], - "dirty": False, - } - except Exception as e: - print(f"Error tokenizing message: {str(e)}") - self._tokens_by_message[key] = { - "tokens_count": self.handlers["estimate"](msg), - "dirty": True, - } - - async def add(self, message: BaseMessage, index: Optional[int] = None) -> None: - index = ( - len(self._messages) - if index is None - else max(0, min(index, len(self._messages))) - ) - self._messages.insert(index, message) - - key = self._get_message_key(message) - estimated_tokens = self.handlers["estimate"](message) - self._tokens_by_message[key] = { - "tokens_count": estimated_tokens, - "dirty": True, - } - - dirty_count = sum( - 1 for info in self._tokens_by_message.values() if info.get("dirty", True) - ) - if ( - len(self._messages) > 0 - and dirty_count / len(self._messages) >= self.sync_threshold - ): - await self.sync() - - async def delete(self, message: BaseMessage) -> bool: - try: - key = self._get_message_key(message) - self._messages.remove(message) - self._tokens_by_message.pop(key, None) - return True - except ValueError: - return False - - def reset(self) -> None: - self._messages.clear() - self._tokens_by_message.clear() - - def create_snapshot(self) -> Dict[str, Any]: - return { - "messages": copy(self._messages), - "token_counts": copy(self._tokens_by_message), - } - - def load_snapshot(self, state: Dict[str, Any]) -> None: - self._messages = copy(state["messages"]) - self._tokens_by_message = copy(state["token_counts"]) diff --git a/framework/bee-py/bee_agent/memory/unconstrained_cache.py b/framework/bee-py/bee_agent/memory/unconstrained_cache.py deleted file mode 100644 index 3192dc4..0000000 --- a/framework/bee-py/bee_agent/memory/unconstrained_cache.py +++ /dev/null @@ -1,160 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import TypeVar, Dict, Any, Generic -from .base_cache import BaseCache -from .serializer import Serializer - -T = TypeVar("T") - - -class UnconstrainedCache(BaseCache[T], Generic[T]): - """Cache implementation without size or time constraints.""" - - def __init__(self): - """Initialize the unconstrained cache.""" - super().__init__() - self._provider: Dict[str, T] = {} - self._register() - - @classmethod - def _register(cls) -> None: - """Register for serialization.""" - Serializer.register( - cls, - { - "to_plain": lambda x: { - "enabled": x.enabled, - "provider": dict(x._provider), - }, - "from_plain": lambda x: cls.from_snapshot(x), - }, - ) - - async def get(self, key: str) -> T: - """Get a value from the cache.""" - return self._provider.get(key) - - async def has(self, key: str) -> bool: - """Check if a key exists in the cache.""" - return key in self._provider - - async def clear(self) -> None: - """Clear all items from the cache.""" - self._provider.clear() - - async def delete(self, key: str) -> bool: - """Delete a key from the cache.""" - if key in self._provider: - del self._provider[key] - return True - return False - - async def set(self, key: str, value: T) -> None: - """Set a value in the cache.""" - self._provider[key] = value - - async def size(self) -> int: - """Get the current number of items in the cache.""" - return len(self._provider) - - async def create_snapshot(self) -> Dict[str, Any]: - """Create a serializable snapshot of the current state.""" - return {"enabled": self.enabled, "provider": dict(self._provider)} - - def load_snapshot(self, snapshot: Dict[str, Any]) -> None: - """Restore state from a snapshot.""" - self._enabled = snapshot["enabled"] - self._provider = dict(snapshot["provider"]) - - @classmethod - def from_snapshot(cls, snapshot: Dict[str, Any]) -> "UnconstrainedCache[T]": - """Create an instance from a snapshot.""" - instance = cls() - instance.load_snapshot(snapshot) - return instance - - -if __name__ == "__main__": - import asyncio - - async def test_unconstrained_cache(): - try: - print("\n1. Testing Basic Operations:") - # Create cache instance - cache = UnconstrainedCache[str]() - - # Test setting and getting values - print("Setting test values...") - await cache.set("key1", "value1") - await cache.set("key2", "value2") - await cache.set("key3", "value3") - - # Test retrieval - value1 = await cache.get("key1") - value2 = await cache.get("key2") - print(f"Retrieved values: key1={value1}, key2={value2}") - - # Test has method - exists = await cache.has("key1") - not_exists = await cache.has("nonexistent") - print(f"Has key1: {exists}") - print(f"Has nonexistent: {not_exists}") - - # Test size - size = await cache.size() - print(f"Cache size: {size}") - - print("\n2. Testing Delete Operation:") - # Test deletion - deleted = await cache.delete("key2") - size_after_delete = await cache.size() - print(f"Deleted key2: {deleted}") - print(f"Size after delete: {size_after_delete}") - - print("\n3. Testing Clear Operation:") - # Test clear - await cache.clear() - size_after_clear = await cache.size() - print(f"Size after clear: {size_after_clear}") - - print("\n4. Testing Serialization:") - # Test serialization - new_cache = UnconstrainedCache[str]() - await new_cache.set("test1", "data1") - await new_cache.set("test2", "data2") - - # Create snapshot - snapshot = await new_cache.create_snapshot() - print(f"Created snapshot: {snapshot}") - - # Create new instance from snapshot - restored_cache = UnconstrainedCache.from_snapshot(snapshot) - restored_value = await restored_cache.get("test1") - print(f"Restored value from snapshot: {restored_value}") - - print("\n5. Testing Enabled Property:") - # Test enabled property - original_state = new_cache.enabled - new_cache.enabled = False - print(f"Original enabled state: {original_state}") - print(f"New enabled state: {new_cache.enabled}") - - print("\n6. Testing Large Dataset:") - # Test with larger dataset - large_cache = UnconstrainedCache[int]() - print("Adding 1000 items...") - for i in range(1000): - await large_cache.set(f"key{i}", i) - - large_size = await large_cache.size() - sample_value = await large_cache.get("key500") - print(f"Large cache size: {large_size}") - print(f"Sample value (key500): {sample_value}") - - print("\nAll tests completed successfully!") - - except Exception as e: - print(f"Error during test: {str(e)}") - - # Run the tests - asyncio.run(test_unconstrained_cache()) diff --git a/framework/bee-py/bee_agent/memory/unconstrained_memory.py b/framework/bee-py/bee_agent/memory/unconstrained_memory.py deleted file mode 100644 index 5d50124..0000000 --- a/framework/bee-py/bee_agent/memory/unconstrained_memory.py +++ /dev/null @@ -1,41 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import List, Optional, Dict -from copy import copy -from .base_memory import BaseMemory -from .message import BaseMessage - - -class UnconstrainedMemory(BaseMemory): - """Simple memory implementation with no constraints.""" - - def __init__(self): - self._messages: List[BaseMessage] = [] - - @property - def messages(self) -> List[BaseMessage]: - return self._messages - - async def add(self, message: BaseMessage, index: Optional[int] = None) -> None: - index = ( - len(self._messages) - if index is None - else max(0, min(index, len(self._messages))) - ) - self._messages.insert(index, message) - - async def delete(self, message: BaseMessage) -> bool: - try: - self._messages.remove(message) - return True - except ValueError: - return False - - def reset(self) -> None: - self._messages.clear() - - def create_snapshot(self) -> Dict: - return {"messages": copy(self._messages)} - - def load_snapshot(self, state: Dict) -> None: - self._messages = copy(state["messages"]) diff --git a/framework/bee-py/bee_agent/tools/__init__.py b/framework/bee-py/bee_agent/tools/__init__.py deleted file mode 100644 index 7684a7f..0000000 --- a/framework/bee-py/bee_agent/tools/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from .weather import WeatherTool -from .tool import Tool -from .mcp_tools import MCPTool, MCPToolOutput, MCPToolInput - -__all__ = ["WeatherTool", "Tool", "MCPTool", "MCPToolOutput", "MCPToolInput"] diff --git a/framework/bee-py/bee_agent/tools/mcp_tools.py b/framework/bee-py/bee_agent/tools/mcp_tools.py deleted file mode 100644 index 474f4d9..0000000 --- a/framework/bee-py/bee_agent/tools/mcp_tools.py +++ /dev/null @@ -1,73 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import Dict, List, Optional, TypeVar, Any, Sequence -from dataclasses import dataclass - -from bee_agent.tools import Tool -from bee_agent.utils import BeeEventEmitter -from mcp.client.session import ClientSession -from mcp.types import ( - Tool as MCPToolInfo, - CallToolResult, - TextContent, - ImageContent, - EmbeddedResource, -) - -T = TypeVar("T") - - -@dataclass -class MCPToolInput: - """Input configuration for MCP Tool initialization.""" - - client: ClientSession - tool: MCPToolInfo - - -class MCPToolOutput: - """Output class for MCP Tool results.""" - - def __init__(self, result: CallToolResult): - self.result = result - - -class MCPTool(Tool[MCPToolOutput]): - """Tool implementation for Model Context Protocol.""" - - def __init__(self, client: ClientSession, tool: MCPToolInfo, **options): - """Initialize MCPTool with client and tool configuration.""" - super().__init__(options) - self.client = client - self._tool = tool - self._name = tool.name - self._description = ( - tool.description - or "No available description, use the tool based on its name and schema." - ) - self.emitter = BeeEventEmitter() - - @property - def name(self) -> str: - return self._name - - @property - def description(self) -> str: - return self._description - - def input_schema(self) -> str: - return self._tool.inputSchema - - async def _run( - self, input_data: Any, options: Optional[Dict] = None - ) -> MCPToolOutput: - """Execute the tool with given input.""" - print(f"Executing tool {self.name} with input: {input_data}") # Debug - result = await self.client.call_tool(name=self.name, arguments=input_data) - print(f"Tool result: {result}") # Debug - return MCPToolOutput(result) - - @classmethod - async def from_client(cls, client: ClientSession) -> List["MCPTool"]: - tools_result = await client.list_tools() - return [cls(client=client, tool=tool) for tool in tools_result.tools] diff --git a/framework/bee-py/bee_agent/tools/tool.py b/framework/bee-py/bee_agent/tools/tool.py deleted file mode 100644 index 72c0567..0000000 --- a/framework/bee-py/bee_agent/tools/tool.py +++ /dev/null @@ -1,42 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from abc import ABC, abstractmethod -from typing import Any, Dict, Generic, TypeVar - - -T = TypeVar("T") - - -class Tool(Generic[T], ABC): - options: Dict[str, Any] = {} - - def __init__(self, options={}): - self.options = options - - @property - @abstractmethod - def name(self): - pass - - @property - @abstractmethod - def description(self): - pass - - @abstractmethod - def input_schema(self): - pass - - @abstractmethod - def _run(self, input, options=None): - pass - - def prompt_data(self): - return { - "name": self.name, - "description": self.description, - "schema": self.input_schema(), - } - - def run(self, input: T, options=None): - return self._run(input, options) diff --git a/framework/bee-py/bee_agent/tools/weather.py b/framework/bee-py/bee_agent/tools/weather.py deleted file mode 100644 index a4c2d8e..0000000 --- a/framework/bee-py/bee_agent/tools/weather.py +++ /dev/null @@ -1,84 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from typing import Literal, Optional, TypedDict -from urllib.parse import urlencode - -import requests - -from .tool import Tool - - -class WeatherLocation(TypedDict): - name: Optional[str] - country: Optional[str] - language: Optional[str] - latitude: Optional[float] - longitude: Optional[float] - - -class WeatherInput(TypedDict): - location: WeatherLocation - start_date: Optional[str] - end_data: Optional[str] - temperature_unit: Optional[Literal["celsius", "fahrenheit"]] = "celsius" - - -class WeatherTool(Tool): - name = "WeatherTool" - description = "Retrieve current, past, or future weather forecasts for a location." - - def input_schema(self): - # # TODO: remove hard code - return '{"type":"object","properties":{"location":{"anyOf":[{"type":"object","properties":{"name":{"type":"string"},"country":{"type":"string"},"language":{"type":"string","default":"English"}},"required":["name"],"additionalProperties":false},{"type":"object","properties":{"latitude":{"type":"number"},"longitude":{"type":"number"}},"required":["latitude","longitude"],"additionalProperties":false}]},"start_date":{"type":"string","format":"date","description":"Start date for the weather forecast in the format YYYY-MM-DD (UTC)"},"end_date":{"type":"string","format":"date","description":"End date for the weather forecast in the format YYYY-MM-DD (UTC)"},"temperature_unit":{"type":"string","enum":["celsius","fahrenheit"],"default":"celsius"}},"required":["location","start_date"],"additionalProperties":false}' - - def _geocode(self, location): - params = {"format": "json", "count": 1} - if location.get("name"): - params["name"] = location.get("name") - if location.get("country"): - params["country"] = location.get("country") - if location.get("language"): - params["language"] = location.get("language") - params = urlencode(params, doseq=True) - - response = requests.get( - f"https://geocoding-api.open-meteo.com/v1/search?${params}", - headers={"Content-Type": "application/json", "Accept": "application/json"}, - ) - - response.raise_for_status() - results = response.json()["results"] - return results[0] - - def get_params(self, input: WeatherInput): - params = { - "forecast_days": 1, - "current": [ - "temperature_2m", - "rain", - "relative_humidity_2m", - "wind_speed_10m", - ], - "daily": ["temperature_2m_max", "temperature_2m_min", "rain_sum"], - "hourly": ["temperature_2m", "relative_humidity_2m", "rain"], - "timezone": "UTC", - } - - if input.get("location", {}).get("name"): - geocode = self._geocode(input.get("location")) - params["latitude"] = geocode.get("latitude") - params["longitude"] = geocode.get("longitude") - else: - params["latitude"] = input.get("location", {}).get("latitude") - params["longitude"] = input.get("location", {}).get("longitude") - - return params - - def _run(self, input: WeatherInput, options=None): - params = urlencode(self.get_params(input), doseq=True) - response = requests.get( - f"https://api.open-meteo.com/v1/forecast?${params}", - headers={"Content-Type": "application/json", "Accept": "application/json"}, - ) - response.raise_for_status() - return response.json() diff --git a/framework/bee-py/bee_agent/tools/wikipedia.py b/framework/bee-py/bee_agent/tools/wikipedia.py deleted file mode 100644 index f7b1ac2..0000000 --- a/framework/bee-py/bee_agent/tools/wikipedia.py +++ /dev/null @@ -1,15 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from .tool import Tool - - -class WikipediaTool(Tool): - name = "Wikipedia" - description = "Search factual and historical information, including biography, history, politics, geography, society, culture, science, technology, people, animal species, mathematics, and other subjects." - - def input_schema(self): - # # TODO: remove hard code - return '{"type":"object","properties":{"query":{"type":"string","format":"date","description":"Name of the wikipedia page, for example \'New York\'"}}}' - - def _run(self, input, options=None): - pass diff --git a/framework/bee-py/bee_agent/utils/__init__.py b/framework/bee-py/bee_agent/utils/__init__.py deleted file mode 100644 index 9964bdb..0000000 --- a/framework/bee-py/bee_agent/utils/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from .config import CONFIG -from .custom_logger import BeeLogger -from .events import BeeEventEmitter, MessageEvent -from .roles import Role, RoleType - - -__all__ = ["CONFIG", "BeeEventEmitter", "BeeLogger", "MessageEvent", "Role", "RoleType"] diff --git a/framework/bee-py/bee_agent/utils/config.py b/framework/bee-py/bee_agent/utils/config.py deleted file mode 100644 index 6bcfc77..0000000 --- a/framework/bee-py/bee_agent/utils/config.py +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from pydantic_settings import BaseSettings, SettingsConfigDict - - -class Settings(BaseSettings): - model_config = SettingsConfigDict( - env_file=".env", - env_file_encoding="utf-8", - env_nested_delimiter="__", - env_prefix="bee_", - extra="ignore", - ) - - log_level: str = "INFO" - - -CONFIG = Settings() diff --git a/framework/bee-py/bee_agent/utils/custom_logger.py b/framework/bee-py/bee_agent/utils/custom_logger.py deleted file mode 100644 index 1afb5cb..0000000 --- a/framework/bee-py/bee_agent/utils/custom_logger.py +++ /dev/null @@ -1,55 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import logging -import sys - -from pyventus import EventHandler, EventLinker - -from .config import CONFIG -from .events import MessageEvent -from .roles import Role - - -_handler: EventHandler = None - - -class BeeLoggerFormatter: - def format(self, record: logging.LogRecord): - if hasattr(record, "is_event_message") and record.is_event_message: - return logging.Formatter( - "{asctime} {levelname:<8s} - {message}", - style="{", - datefmt="%Y-%m-%d %H:%M:%S", - ).format(record) - else: - return logging.Formatter( - "{asctime} {levelname:<8s} {name} - {message}", - style="{", - datefmt="%Y-%m-%d %H:%M:%S", - ).format(record) - - -class BeeLogger(logging.Logger): - - def __init__(self, name, level=CONFIG.log_level): - super().__init__(name, level) - - console_handler = logging.StreamHandler(stream=sys.stdout) - console_handler.setFormatter(BeeLoggerFormatter()) - - self.addHandler(console_handler) - - global _handler - if _handler is None: - _handler = EventLinker.subscribe( - MessageEvent, event_callback=self.log_message_events - ) - - def log_message_events(self, event: MessageEvent): - source = str.lower(event.source) - state = f" ({event.state})" if event.state else "" - icon = " 👤" if source == str.lower(Role.USER) else " 🤖" - self.info( - f" {str.capitalize(source)}{state}{icon}: {event.message}", - extra={"is_event_message": True}, - ) diff --git a/framework/bee-py/bee_agent/utils/events.py b/framework/bee-py/bee_agent/utils/events.py deleted file mode 100644 index f1a93d6..0000000 --- a/framework/bee-py/bee_agent/utils/events.py +++ /dev/null @@ -1,49 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import asyncio - -from concurrent.futures import ThreadPoolExecutor -from dataclasses import dataclass -from typing import Any, List, Literal, Optional - -from pyventus import AsyncIOEventEmitter, EmittableEventType, EventEmitter - - -@dataclass -class MessageEvent: - source: Literal["User", "Agent"] - message: str - state: Optional[str] = None - - -class BeeEventEmitter(AsyncIOEventEmitter): - @property - def __is_loop_running(self) -> bool: - try: - asyncio.get_running_loop() - return True - except RuntimeError: - return False - - def _process(self, event_emission: EventEmitter.EventEmission) -> None: - # Check if there is an active event loop - is_loop_running: bool = self.__is_loop_running - - # Log the execution context, if debug mode is enabled - if self._logger.debug_enabled: # pragma: no cover - self._logger.debug( - action="Context:", msg=f"{'Async' if is_loop_running else 'Sync'}" - ) - - if is_loop_running: - # Create a separate thread - with ThreadPoolExecutor(1) as pool: - pool.submit(lambda: asyncio.run(event_emission())).result() - - else: - # Run the event emission in a blocking manner - asyncio.run(event_emission()) - - def emit_many(self, /, events: List[EmittableEventType], *args: Any, **kwargs: Any): - for event in events: - self.emit(event, *args, **kwargs) diff --git a/framework/bee-py/bee_agent/utils/roles.py b/framework/bee-py/bee_agent/utils/roles.py deleted file mode 100644 index 4bc7ff3..0000000 --- a/framework/bee-py/bee_agent/utils/roles.py +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -from enum import Enum -from typing import Union - - -RoleType = Union[str, None] # Equivalent to TypeScript's string type for roles - - -# Basic Role class -class Role(str, Enum): - ASSISTANT: str = "assistant" - SYSTEM: str = "system" - USER: str = "user" - - @classmethod - def values(cls) -> set[str]: - return { - value - for key, value in vars(cls).items() - if not key.startswith("_") and isinstance(value, str) - } diff --git a/framework/bee-py/dev_tools/scripts.py b/framework/bee-py/dev_tools/scripts.py deleted file mode 100644 index 2ca1e27..0000000 --- a/framework/bee-py/dev_tools/scripts.py +++ /dev/null @@ -1,35 +0,0 @@ -import subprocess -import sys - - -def lint(): - try: - subprocess.run(["black", "."], check=True) - subprocess.run(["ruff", "check", "."], check=True) - except subprocess.CalledProcessError: - sys.exit(1) - - -def commit(): - try: - if len(sys.argv) < 2: - print("Error: Please provide a commit message") - print('Usage: poetry run commit ""') - sys.exit(1) - - commit_message = sys.argv[1] - - print("📦 Adding files...") - subprocess.run(["git", "add", "--all"], check=True) - - print("📝 Committing changes...") - subprocess.run(["git", "commit", "-s", "-m", commit_message], check=True) - - print("Successfully committed changes") - - except subprocess.CalledProcessError as e: - print(f"Error during git operations: {e}", file=sys.stderr) - sys.exit(1) - except Exception as e: - print(f"Unexpected error: {e}", file=sys.stderr) - sys.exit(1) diff --git a/framework/bee-py/poetry.lock b/framework/bee-py/poetry.lock deleted file mode 100644 index 7622495..0000000 --- a/framework/bee-py/poetry.lock +++ /dev/null @@ -1,2308 +0,0 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. - -[[package]] -name = "aiofiles" -version = "24.1.0" -description = "File support for asyncio." -optional = false -python-versions = ">=3.8" -files = [ - {file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"}, - {file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"}, -] - -[[package]] -name = "aiohappyeyeballs" -version = "2.4.4" -description = "Happy Eyeballs for asyncio" -optional = false -python-versions = ">=3.8" -files = [ - {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, - {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, -] - -[[package]] -name = "aiohttp" -version = "3.11.11" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.9" -files = [ - {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8"}, - {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5"}, - {file = "aiohttp-3.11.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef"}, - {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33"}, - {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c"}, - {file = "aiohttp-3.11.11-cp310-cp310-win32.whl", hash = "sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745"}, - {file = "aiohttp-3.11.11-cp310-cp310-win_amd64.whl", hash = "sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9"}, - {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76"}, - {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538"}, - {file = "aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e"}, - {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2"}, - {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773"}, - {file = "aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62"}, - {file = "aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac"}, - {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886"}, - {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2"}, - {file = "aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8"}, - {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853"}, - {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e"}, - {file = "aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600"}, - {file = "aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d"}, - {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9"}, - {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194"}, - {file = "aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1"}, - {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12"}, - {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5"}, - {file = "aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d"}, - {file = "aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99"}, - {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e"}, - {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add"}, - {file = "aiohttp-3.11.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e"}, - {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28"}, - {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226"}, - {file = "aiohttp-3.11.11-cp39-cp39-win32.whl", hash = "sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3"}, - {file = "aiohttp-3.11.11-cp39-cp39-win_amd64.whl", hash = "sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1"}, - {file = "aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e"}, -] - -[package.dependencies] -aiohappyeyeballs = ">=2.3.0" -aiosignal = ">=1.1.2" -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -propcache = ">=0.2.0" -yarl = ">=1.17.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] - -[[package]] -name = "aiosignal" -version = "1.3.2" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.9" -files = [ - {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, - {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "annotated-types" -version = "0.7.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, - {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, -] - -[[package]] -name = "anyio" -version = "4.8.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.9" -files = [ - {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, - {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" -typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} - -[package.extras] -doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] -trio = ["trio (>=0.26.1)"] - -[[package]] -name = "astroid" -version = "3.3.8" -description = "An abstract syntax tree for Python with inference support." -optional = false -python-versions = ">=3.9.0" -files = [ - {file = "astroid-3.3.8-py3-none-any.whl", hash = "sha256:187ccc0c248bfbba564826c26f070494f7bc964fd286b6d9fff4420e55de828c"}, - {file = "astroid-3.3.8.tar.gz", hash = "sha256:a88c7994f914a4ea8572fac479459f4955eeccc877be3f2d959a33273b0cf40b"}, -] - -[[package]] -name = "attrs" -version = "24.3.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.8" -files = [ - {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, - {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, -] - -[package.extras] -benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] -tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] - -[[package]] -name = "beautifulsoup4" -version = "4.12.3" -description = "Screen-scraping library" -optional = false -python-versions = ">=3.6.0" -files = [ - {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, - {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, -] - -[package.dependencies] -soupsieve = ">1.2" - -[package.extras] -cchardet = ["cchardet"] -chardet = ["chardet"] -charset-normalizer = ["charset-normalizer"] -html5lib = ["html5lib"] -lxml = ["lxml"] - -[[package]] -name = "black" -version = "24.10.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -files = [ - {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, - {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, - {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, - {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, - {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, - {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, - {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, - {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, - {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, - {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, - {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, - {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, - {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, - {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, - {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, - {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, - {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, - {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, - {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, - {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, - {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, - {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "cachetools" -version = "5.5.1" -description = "Extensible memoizing collections and decorators" -optional = false -python-versions = ">=3.7" -files = [ - {file = "cachetools-5.5.1-py3-none-any.whl", hash = "sha256:b76651fdc3b24ead3c648bbdeeb940c1b04d365b38b4af66788f9ec4a81d42bb"}, - {file = "cachetools-5.5.1.tar.gz", hash = "sha256:70f238fbba50383ef62e55c6aff6d9673175fe59f7c6782c7a0b9e38f4a9df95"}, -] - -[[package]] -name = "certifi" -version = "2024.12.14" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, - {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, -] - -[[package]] -name = "chardet" -version = "5.2.0" -description = "Universal encoding detector for Python 3" -optional = false -python-versions = ">=3.7" -files = [ - {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, - {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.1" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7" -files = [ - {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, - {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, - {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, - {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, - {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, - {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, - {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, - {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, - {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, - {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, -] - -[[package]] -name = "chevron" -version = "0.14.0" -description = "Mustache templating language renderer" -optional = false -python-versions = "*" -files = [ - {file = "chevron-0.14.0-py3-none-any.whl", hash = "sha256:fbf996a709f8da2e745ef763f482ce2d311aa817d287593a5b990d6d6e4f0443"}, - {file = "chevron-0.14.0.tar.gz", hash = "sha256:87613aafdf6d77b6a90ff073165a61ae5086e21ad49057aa0e53681601800ebf"}, -] - -[[package]] -name = "click" -version = "8.1.8" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, - {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "dill" -version = "0.3.9" -description = "serialize all of Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "dill-0.3.9-py3-none-any.whl", hash = "sha256:468dff3b89520b474c0397703366b7b95eebe6303f108adf9b19da1f702be87a"}, - {file = "dill-0.3.9.tar.gz", hash = "sha256:81aa267dddf68cbfe8029c42ca9ec6a4ab3b22371d1c450abc54422577b4512c"}, -] - -[package.extras] -graph = ["objgraph (>=1.7.2)"] -profile = ["gprof2dot (>=2022.7.29)"] - -[[package]] -name = "distlib" -version = "0.3.9" -description = "Distribution utilities" -optional = false -python-versions = "*" -files = [ - {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, - {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, -] - -[[package]] -name = "distro" -version = "1.9.0" -description = "Distro - an OS platform information API" -optional = false -python-versions = ">=3.6" -files = [ - {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, - {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, -] - -[[package]] -name = "filelock" -version = "3.17.0" -description = "A platform independent file lock." -optional = false -python-versions = ">=3.9" -files = [ - {file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"}, - {file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] -typing = ["typing-extensions (>=4.12.2)"] - -[[package]] -name = "frozenlist" -version = "1.5.0" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -files = [ - {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, - {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, - {file = "frozenlist-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba"}, - {file = "frozenlist-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab"}, - {file = "frozenlist-1.5.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5"}, - {file = "frozenlist-1.5.0-cp310-cp310-win32.whl", hash = "sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb"}, - {file = "frozenlist-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4"}, - {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30"}, - {file = "frozenlist-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5"}, - {file = "frozenlist-1.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45"}, - {file = "frozenlist-1.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2"}, - {file = "frozenlist-1.5.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf"}, - {file = "frozenlist-1.5.0-cp311-cp311-win32.whl", hash = "sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942"}, - {file = "frozenlist-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d"}, - {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21"}, - {file = "frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d"}, - {file = "frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6"}, - {file = "frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631"}, - {file = "frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f"}, - {file = "frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8"}, - {file = "frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f"}, - {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953"}, - {file = "frozenlist-1.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0"}, - {file = "frozenlist-1.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840"}, - {file = "frozenlist-1.5.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9"}, - {file = "frozenlist-1.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03"}, - {file = "frozenlist-1.5.0-cp313-cp313-win32.whl", hash = "sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c"}, - {file = "frozenlist-1.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28"}, - {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca"}, - {file = "frozenlist-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10"}, - {file = "frozenlist-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9"}, - {file = "frozenlist-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf"}, - {file = "frozenlist-1.5.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e"}, - {file = "frozenlist-1.5.0-cp38-cp38-win32.whl", hash = "sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723"}, - {file = "frozenlist-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923"}, - {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972"}, - {file = "frozenlist-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336"}, - {file = "frozenlist-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08"}, - {file = "frozenlist-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0"}, - {file = "frozenlist-1.5.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c"}, - {file = "frozenlist-1.5.0-cp39-cp39-win32.whl", hash = "sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3"}, - {file = "frozenlist-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0"}, - {file = "frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3"}, - {file = "frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817"}, -] - -[[package]] -name = "fsspec" -version = "2024.12.0" -description = "File-system specification" -optional = false -python-versions = ">=3.8" -files = [ - {file = "fsspec-2024.12.0-py3-none-any.whl", hash = "sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2"}, - {file = "fsspec-2024.12.0.tar.gz", hash = "sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f"}, -] - -[package.extras] -abfs = ["adlfs"] -adl = ["adlfs"] -arrow = ["pyarrow (>=1)"] -dask = ["dask", "distributed"] -dev = ["pre-commit", "ruff"] -doc = ["numpydoc", "sphinx", "sphinx-design", "sphinx-rtd-theme", "yarl"] -dropbox = ["dropbox", "dropboxdrivefs", "requests"] -full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] -fuse = ["fusepy"] -gcs = ["gcsfs"] -git = ["pygit2"] -github = ["requests"] -gs = ["gcsfs"] -gui = ["panel"] -hdfs = ["pyarrow (>=1)"] -http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] -libarchive = ["libarchive-c"] -oci = ["ocifs"] -s3 = ["s3fs"] -sftp = ["paramiko"] -smb = ["smbprotocol"] -ssh = ["paramiko"] -test = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "numpy", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "requests"] -test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe,test]", "moto[server] (>4,<5)", "pytest-timeout", "xarray"] -test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] -tqdm = ["tqdm"] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "httpcore" -version = "1.0.7" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, - {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<1.0)"] - -[[package]] -name = "httpx" -version = "0.27.2" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, - {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" -sniffio = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "huggingface-hub" -version = "0.27.1" -description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "huggingface_hub-0.27.1-py3-none-any.whl", hash = "sha256:1c5155ca7d60b60c2e2fc38cbb3ffb7f7c3adf48f824015b219af9061771daec"}, - {file = "huggingface_hub-0.27.1.tar.gz", hash = "sha256:c004463ca870283909d715d20f066ebd6968c2207dae9393fdffb3c1d4d8f98b"}, -] - -[package.dependencies] -filelock = "*" -fsspec = ">=2023.5.0" -packaging = ">=20.9" -pyyaml = ">=5.1" -requests = "*" -tqdm = ">=4.42.1" -typing-extensions = ">=3.7.4.3" - -[package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] -cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] -fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] -hf-transfer = ["hf-transfer (>=0.1.4)"] -inference = ["aiohttp"] -quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.5.0)"] -tensorflow = ["graphviz", "pydot", "tensorflow"] -tensorflow-testing = ["keras (<3.0)", "tensorflow"] -testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] -torch = ["safetensors[torch]", "torch"] -typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] - -[[package]] -name = "idna" -version = "3.10" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.6" -files = [ - {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, - {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, -] - -[package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] - -[[package]] -name = "importlib-metadata" -version = "8.6.1" -description = "Read metadata from Python packages" -optional = false -python-versions = ">=3.9" -files = [ - {file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"}, - {file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"}, -] - -[package.dependencies] -zipp = ">=3.20" - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -perf = ["ipython"] -test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] -type = ["pytest-mypy"] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "jinja2" -version = "3.1.5" -description = "A very fast and expressive template engine." -optional = false -python-versions = ">=3.7" -files = [ - {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"}, - {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"}, -] - -[package.dependencies] -MarkupSafe = ">=2.0" - -[package.extras] -i18n = ["Babel (>=2.7)"] - -[[package]] -name = "jiter" -version = "0.8.2" -description = "Fast iterable JSON parser." -optional = false -python-versions = ">=3.8" -files = [ - {file = "jiter-0.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b"}, - {file = "jiter-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393"}, - {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c826a221851a8dc028eb6d7d6429ba03184fa3c7e83ae01cd6d3bd1d4bd17d"}, - {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d35c864c2dff13dfd79fb070fc4fc6235d7b9b359efe340e1261deb21b9fcb66"}, - {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f557c55bc2b7676e74d39d19bcb8775ca295c7a028246175d6a8b431e70835e5"}, - {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:580ccf358539153db147e40751a0b41688a5ceb275e6f3e93d91c9467f42b2e3"}, - {file = "jiter-0.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af102d3372e917cffce49b521e4c32c497515119dc7bd8a75665e90a718bbf08"}, - {file = "jiter-0.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cadcc978f82397d515bb2683fc0d50103acff2a180552654bb92d6045dec2c49"}, - {file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ba5bdf56969cad2019d4e8ffd3f879b5fdc792624129741d3d83fc832fef8c7d"}, - {file = "jiter-0.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3b94a33a241bee9e34b8481cdcaa3d5c2116f575e0226e421bed3f7a6ea71cff"}, - {file = "jiter-0.8.2-cp310-cp310-win32.whl", hash = "sha256:6e5337bf454abddd91bd048ce0dca5134056fc99ca0205258766db35d0a2ea43"}, - {file = "jiter-0.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:4a9220497ca0cb1fe94e3f334f65b9b5102a0b8147646118f020d8ce1de70105"}, - {file = "jiter-0.8.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:2dd61c5afc88a4fda7d8b2cf03ae5947c6ac7516d32b7a15bf4b49569a5c076b"}, - {file = "jiter-0.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a6c710d657c8d1d2adbbb5c0b0c6bfcec28fd35bd6b5f016395f9ac43e878a15"}, - {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9584de0cd306072635fe4b89742bf26feae858a0683b399ad0c2509011b9dc0"}, - {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a90a923338531b7970abb063cfc087eebae6ef8ec8139762007188f6bc69a9f"}, - {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21974d246ed0181558087cd9f76e84e8321091ebfb3a93d4c341479a736f099"}, - {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:32475a42b2ea7b344069dc1e81445cfc00b9d0e3ca837f0523072432332e9f74"}, - {file = "jiter-0.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b9931fd36ee513c26b5bf08c940b0ac875de175341cbdd4fa3be109f0492586"}, - {file = "jiter-0.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0820f4a3a59ddced7fce696d86a096d5cc48d32a4183483a17671a61edfddc"}, - {file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8ffc86ae5e3e6a93765d49d1ab47b6075a9c978a2b3b80f0f32628f39caa0c88"}, - {file = "jiter-0.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5127dc1abd809431172bc3fbe8168d6b90556a30bb10acd5ded41c3cfd6f43b6"}, - {file = "jiter-0.8.2-cp311-cp311-win32.whl", hash = "sha256:66227a2c7b575720c1871c8800d3a0122bb8ee94edb43a5685aa9aceb2782d44"}, - {file = "jiter-0.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:cde031d8413842a1e7501e9129b8e676e62a657f8ec8166e18a70d94d4682855"}, - {file = "jiter-0.8.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f"}, - {file = "jiter-0.8.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44"}, - {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f"}, - {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60"}, - {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57"}, - {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e"}, - {file = "jiter-0.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887"}, - {file = "jiter-0.8.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d"}, - {file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152"}, - {file = "jiter-0.8.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29"}, - {file = "jiter-0.8.2-cp312-cp312-win32.whl", hash = "sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e"}, - {file = "jiter-0.8.2-cp312-cp312-win_amd64.whl", hash = "sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c"}, - {file = "jiter-0.8.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84"}, - {file = "jiter-0.8.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4"}, - {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587"}, - {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c"}, - {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18"}, - {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6"}, - {file = "jiter-0.8.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef"}, - {file = "jiter-0.8.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1"}, - {file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9"}, - {file = "jiter-0.8.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05"}, - {file = "jiter-0.8.2-cp313-cp313-win32.whl", hash = "sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a"}, - {file = "jiter-0.8.2-cp313-cp313-win_amd64.whl", hash = "sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865"}, - {file = "jiter-0.8.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca"}, - {file = "jiter-0.8.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0"}, - {file = "jiter-0.8.2-cp313-cp313t-win_amd64.whl", hash = "sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566"}, - {file = "jiter-0.8.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9e1fa156ee9454642adb7e7234a383884452532bc9d53d5af2d18d98ada1d79c"}, - {file = "jiter-0.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0cf5dfa9956d96ff2efb0f8e9c7d055904012c952539a774305aaaf3abdf3d6c"}, - {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e52bf98c7e727dd44f7c4acb980cb988448faeafed8433c867888268899b298b"}, - {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a2ecaa3c23e7a7cf86d00eda3390c232f4d533cd9ddea4b04f5d0644faf642c5"}, - {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:08d4c92bf480e19fc3f2717c9ce2aa31dceaa9163839a311424b6862252c943e"}, - {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d9a1eded738299ba8e106c6779ce5c3893cffa0e32e4485d680588adae6db8"}, - {file = "jiter-0.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d20be8b7f606df096e08b0b1b4a3c6f0515e8dac296881fe7461dfa0fb5ec817"}, - {file = "jiter-0.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d33f94615fcaf872f7fd8cd98ac3b429e435c77619777e8a449d9d27e01134d1"}, - {file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:317b25e98a35ffec5c67efe56a4e9970852632c810d35b34ecdd70cc0e47b3b6"}, - {file = "jiter-0.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fc9043259ee430ecd71d178fccabd8c332a3bf1e81e50cae43cc2b28d19e4cb7"}, - {file = "jiter-0.8.2-cp38-cp38-win32.whl", hash = "sha256:fc5adda618205bd4678b146612ce44c3cbfdee9697951f2c0ffdef1f26d72b63"}, - {file = "jiter-0.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:cd646c827b4f85ef4a78e4e58f4f5854fae0caf3db91b59f0d73731448a970c6"}, - {file = "jiter-0.8.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e41e75344acef3fc59ba4765df29f107f309ca9e8eace5baacabd9217e52a5ee"}, - {file = "jiter-0.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f22b16b35d5c1df9dfd58843ab2cd25e6bf15191f5a236bed177afade507bfc"}, - {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7200b8f7619d36aa51c803fd52020a2dfbea36ffec1b5e22cab11fd34d95a6d"}, - {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70bf4c43652cc294040dbb62256c83c8718370c8b93dd93d934b9a7bf6c4f53c"}, - {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f9d471356dc16f84ed48768b8ee79f29514295c7295cb41e1133ec0b2b8d637d"}, - {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:859e8eb3507894093d01929e12e267f83b1d5f6221099d3ec976f0c995cb6bd9"}, - {file = "jiter-0.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaa58399c01db555346647a907b4ef6d4f584b123943be6ed5588c3f2359c9f4"}, - {file = "jiter-0.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8f2d5ed877f089862f4c7aacf3a542627c1496f972a34d0474ce85ee7d939c27"}, - {file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:03c9df035d4f8d647f8c210ddc2ae0728387275340668fb30d2421e17d9a0841"}, - {file = "jiter-0.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8bd2a824d08d8977bb2794ea2682f898ad3d8837932e3a74937e93d62ecbb637"}, - {file = "jiter-0.8.2-cp39-cp39-win32.whl", hash = "sha256:ca29b6371ebc40e496995c94b988a101b9fbbed48a51190a4461fcb0a68b4a36"}, - {file = "jiter-0.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:1c0dfbd1be3cbefc7510102370d86e35d1d53e5a93d48519688b1bf0f761160a"}, - {file = "jiter-0.8.2.tar.gz", hash = "sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d"}, -] - -[[package]] -name = "jsonschema" -version = "4.23.0" -description = "An implementation of JSON Schema validation for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, - {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.03.6" -referencing = ">=0.28.4" -rpds-py = ">=0.7.1" - -[package.extras] -format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] -format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "uri-template", "webcolors (>=24.6.0)"] - -[[package]] -name = "jsonschema-specifications" -version = "2024.10.1" -description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" -optional = false -python-versions = ">=3.9" -files = [ - {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, - {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, -] - -[package.dependencies] -referencing = ">=0.31.0" - -[[package]] -name = "litellm" -version = "1.59.5" -description = "Library to easily interface with LLM API providers" -optional = false -python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" -files = [ - {file = "litellm-1.59.5-py3-none-any.whl", hash = "sha256:2e3a5242c41203e08500d5d1bad746ad67869842227b8f8f768795c627cb85f6"}, - {file = "litellm-1.59.5.tar.gz", hash = "sha256:5124014c0c239ee63adc8aa29f1c396bc653e2b53e5aceca9081cd665e58202f"}, -] - -[package.dependencies] -aiohttp = "*" -click = "*" -httpx = ">=0.23.0,<0.28.0" -importlib-metadata = ">=6.8.0" -jinja2 = ">=3.1.2,<4.0.0" -jsonschema = ">=4.22.0,<5.0.0" -openai = ">=1.55.3" -pydantic = ">=2.0.0,<3.0.0" -python-dotenv = ">=0.2.0" -tiktoken = ">=0.7.0" -tokenizers = "*" - -[package.extras] -extra-proxy = ["azure-identity (>=1.15.0,<2.0.0)", "azure-keyvault-secrets (>=4.8.0,<5.0.0)", "google-cloud-kms (>=2.21.3,<3.0.0)", "prisma (==0.11.0)", "resend (>=0.8.0,<0.9.0)"] -proxy = ["PyJWT (>=2.8.0,<3.0.0)", "apscheduler (>=3.10.4,<4.0.0)", "backoff", "cryptography (>=43.0.1,<44.0.0)", "fastapi (>=0.115.5,<0.116.0)", "fastapi-sso (>=0.16.0,<0.17.0)", "gunicorn (>=22.0.0,<23.0.0)", "orjson (>=3.9.7,<4.0.0)", "pynacl (>=1.5.0,<2.0.0)", "python-multipart (>=0.0.18,<0.0.19)", "pyyaml (>=6.0.1,<7.0.0)", "rq", "uvicorn (>=0.29.0,<0.30.0)", "uvloop (>=0.21.0,<0.22.0)"] - -[[package]] -name = "markupsafe" -version = "3.0.2" -description = "Safely add untrusted strings to HTML/XML markup." -optional = false -python-versions = ">=3.9" -files = [ - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, - {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, - {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, - {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, - {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, - {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, - {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, - {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, -] - -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "multidict" -version = "6.1.0" -description = "multidict implementation" -optional = false -python-versions = ">=3.8" -files = [ - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, - {file = "multidict-6.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429"}, - {file = "multidict-6.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160"}, - {file = "multidict-6.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7"}, - {file = "multidict-6.1.0-cp310-cp310-win32.whl", hash = "sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0"}, - {file = "multidict-6.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156"}, - {file = "multidict-6.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351"}, - {file = "multidict-6.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3"}, - {file = "multidict-6.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753"}, - {file = "multidict-6.1.0-cp311-cp311-win32.whl", hash = "sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80"}, - {file = "multidict-6.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436"}, - {file = "multidict-6.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925"}, - {file = "multidict-6.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6"}, - {file = "multidict-6.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3"}, - {file = "multidict-6.1.0-cp312-cp312-win32.whl", hash = "sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133"}, - {file = "multidict-6.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f"}, - {file = "multidict-6.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44"}, - {file = "multidict-6.1.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4"}, - {file = "multidict-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6"}, - {file = "multidict-6.1.0-cp313-cp313-win32.whl", hash = "sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81"}, - {file = "multidict-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a"}, - {file = "multidict-6.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d"}, - {file = "multidict-6.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492"}, - {file = "multidict-6.1.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd"}, - {file = "multidict-6.1.0-cp38-cp38-win32.whl", hash = "sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167"}, - {file = "multidict-6.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1"}, - {file = "multidict-6.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255"}, - {file = "multidict-6.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972"}, - {file = "multidict-6.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43"}, - {file = "multidict-6.1.0-cp39-cp39-win32.whl", hash = "sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada"}, - {file = "multidict-6.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a"}, - {file = "multidict-6.1.0-py3-none-any.whl", hash = "sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506"}, - {file = "multidict-6.1.0.tar.gz", hash = "sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a"}, -] - -[[package]] -name = "mypy" -version = "1.14.1" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb"}, - {file = "mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d"}, - {file = "mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b"}, - {file = "mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427"}, - {file = "mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c"}, - {file = "mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8"}, - {file = "mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f"}, - {file = "mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1"}, - {file = "mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14"}, - {file = "mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11"}, - {file = "mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e"}, - {file = "mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89"}, - {file = "mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255"}, - {file = "mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a"}, - {file = "mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9"}, - {file = "mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd"}, - {file = "mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7084fb8f1128c76cd9cf68fe5971b37072598e7c31b2f9f95586b65c741a9d31"}, - {file = "mypy-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8f845a00b4f420f693f870eaee5f3e2692fa84cc8514496114649cfa8fd5e2c6"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:44bf464499f0e3a2d14d58b54674dee25c031703b2ffc35064bd0df2e0fac319"}, - {file = "mypy-1.14.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c99f27732c0b7dc847adb21c9d47ce57eb48fa33a17bc6d7d5c5e9f9e7ae5bac"}, - {file = "mypy-1.14.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:bce23c7377b43602baa0bd22ea3265c49b9ff0b76eb315d6c34721af4cdf1d9b"}, - {file = "mypy-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:8edc07eeade7ebc771ff9cf6b211b9a7d93687ff892150cb5692e4f4272b0837"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35"}, - {file = "mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9"}, - {file = "mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb"}, - {file = "mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60"}, - {file = "mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c"}, - {file = "mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1"}, - {file = "mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6"}, -] - -[package.dependencies] -mypy_extensions = ">=1.0.0" -typing_extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "openai" -version = "1.60.0" -description = "The official Python library for the openai API" -optional = false -python-versions = ">=3.8" -files = [ - {file = "openai-1.60.0-py3-none-any.whl", hash = "sha256:df06c43be8018274980ac363da07d4b417bd835ead1c66e14396f6f15a0d5dda"}, - {file = "openai-1.60.0.tar.gz", hash = "sha256:7fa536cd4b644718645b874d2706e36dbbef38b327e42ca0623275da347ee1a9"}, -] - -[package.dependencies] -anyio = ">=3.5.0,<5" -distro = ">=1.7.0,<2" -httpx = ">=0.23.0,<1" -jiter = ">=0.4.0,<1" -pydantic = ">=1.9.0,<3" -sniffio = "*" -tqdm = ">4" -typing-extensions = ">=4.11,<5" - -[package.extras] -datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -realtime = ["websockets (>=13,<15)"] - -[[package]] -name = "packaging" -version = "24.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, - {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, -] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.3.6" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." -optional = false -python-versions = ">=3.8" -files = [ - {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, - {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, -] - -[package.extras] -docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] -type = ["mypy (>=1.11.2)"] - -[[package]] -name = "pluggy" -version = "1.5.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, - {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "propcache" -version = "0.2.1" -description = "Accelerated property cache" -optional = false -python-versions = ">=3.9" -files = [ - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"}, - {file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"}, - {file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, - {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, - {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, - {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, - {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, - {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, - {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"}, - {file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"}, - {file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"}, - {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, - {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, -] - -[[package]] -name = "pydantic" -version = "2.10.5" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, - {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, -] - -[package.dependencies] -annotated-types = ">=0.6.0" -pydantic-core = "2.27.2" -typing-extensions = ">=4.12.2" - -[package.extras] -email = ["email-validator (>=2.0.0)"] -timezone = ["tzdata"] - -[[package]] -name = "pydantic-core" -version = "2.27.2" -description = "Core functionality for Pydantic validation and serialization" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, - {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, - {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, - {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, - {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, - {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, - {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, - {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, - {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, - {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, - {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, - {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, - {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, - {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, - {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, - {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, - {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, - {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, - {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, - {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, - {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, - {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, - {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, - {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, - {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, - {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pydantic-settings" -version = "2.7.1" -description = "Settings management using Pydantic" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd"}, - {file = "pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93"}, -] - -[package.dependencies] -pydantic = ">=2.7.0" -python-dotenv = ">=0.21.0" - -[package.extras] -azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] -toml = ["tomli (>=2.0.1)"] -yaml = ["pyyaml (>=6.0.1)"] - -[[package]] -name = "pylint" -version = "3.3.3" -description = "python code static checker" -optional = false -python-versions = ">=3.9.0" -files = [ - {file = "pylint-3.3.3-py3-none-any.whl", hash = "sha256:26e271a2bc8bce0fc23833805a9076dd9b4d5194e2a02164942cb3cdc37b4183"}, - {file = "pylint-3.3.3.tar.gz", hash = "sha256:07c607523b17e6d16e2ae0d7ef59602e332caa762af64203c24b41c27139f36a"}, -] - -[package.dependencies] -astroid = ">=3.3.8,<=3.4.0-dev0" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -dill = [ - {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, - {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, -] -isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomlkit = ">=0.10.1" - -[package.extras] -spelling = ["pyenchant (>=3.2,<4.0)"] -testutils = ["gitpython (>3)"] - -[[package]] -name = "pyproject-api" -version = "1.9.0" -description = "API to interact with the python pyproject.toml based projects" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pyproject_api-1.9.0-py3-none-any.whl", hash = "sha256:326df9d68dea22d9d98b5243c46e3ca3161b07a1b9b18e213d1e24fd0e605766"}, - {file = "pyproject_api-1.9.0.tar.gz", hash = "sha256:7e8a9854b2dfb49454fae421cb86af43efbb2b2454e5646ffb7623540321ae6e"}, -] - -[package.dependencies] -packaging = ">=24.2" - -[package.extras] -docs = ["furo (>=2024.8.6)", "sphinx-autodoc-typehints (>=3)"] -testing = ["covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "setuptools (>=75.8)"] - -[[package]] -name = "pytest" -version = "8.3.4" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, - {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=1.5,<2" - -[package.extras] -dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "python-dotenv" -version = "1.0.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.8" -files = [ - {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, - {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "pyventus" -version = "0.6.0" -description = "A powerful Python package for event-driven programming; define, emit, and orchestrate events with ease." -optional = false -python-versions = ">=3.10" -files = [ - {file = "pyventus-0.6.0-py3-none-any.whl", hash = "sha256:fab55c04cc1c08c57af60116eb54e309c38245c0a4ef70d19b54f6c6bd44dafa"}, - {file = "pyventus-0.6.0.tar.gz", hash = "sha256:1950f8ac7a6591fe3a36c66a79fdceea03ec34f9ad064b2e7e66120c8031cc6a"}, -] - -[package.extras] -all = ["celery (>=5.3.5)", "fastapi (>=0.95.2)", "rq (>=1.15.0)"] -celery = ["celery (>=5.3.5)"] -dev = ["black (>=23.12.0)", "celery (>=5.3.5)", "coverage[toml] (>=7.3.3)", "fakeredis (>=2.20.0)", "fastapi (>=0.95.2)", "hatch (>=1.8.1)", "httpx (>=0.23.0)", "mike (>=2.1.3)", "mkdocs-git-committers-plugin-2 (>=2.3.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.1)", "mkdocs-material (>=9.5.17)", "mkdocs-material[imaging]", "mkdocstrings[python] (>=0.24.0)", "mypy (>=1.7.1)", "pytest (>=7.4.0)", "pytest-asyncio (>=0.21.0)", "rq (>=1.15.0)"] -docs = ["mike (>=2.1.3)", "mkdocs-git-committers-plugin-2 (>=2.3.0)", "mkdocs-git-revision-date-localized-plugin (>=1.2.1)", "mkdocs-material (>=9.5.17)", "mkdocs-material[imaging]", "mkdocstrings[python] (>=0.24.0)"] -fastapi = ["fastapi (>=0.95.2)"] -rq = ["rq (>=1.15.0)"] -tests = ["black (>=23.12.0)", "celery (>=5.3.5)", "coverage[toml] (>=7.3.3)", "fakeredis (>=2.20.0)", "fastapi (>=0.95.2)", "httpx (>=0.23.0)", "mypy (>=1.7.1)", "pytest (>=7.4.0)", "pytest-asyncio (>=0.21.0)", "rq (>=1.15.0)"] - -[[package]] -name = "pyyaml" -version = "6.0.2" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, - {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, - {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, - {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, - {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, - {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, - {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, - {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, - {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, - {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, - {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, - {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, - {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, - {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, - {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, - {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, - {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, - {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, - {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, - {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, - {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, - {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, - {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, - {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, - {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, - {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, - {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, - {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, - {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, - {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, - {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, - {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, -] - -[[package]] -name = "referencing" -version = "0.36.1" -description = "JSON Referencing + Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "referencing-0.36.1-py3-none-any.whl", hash = "sha256:363d9c65f080d0d70bc41c721dce3c7f3e77fc09f269cd5c8813da18069a6794"}, - {file = "referencing-0.36.1.tar.gz", hash = "sha256:ca2e6492769e3602957e9b831b94211599d2aade9477f5d44110d2530cf9aade"}, -] - -[package.dependencies] -attrs = ">=22.2.0" -rpds-py = ">=0.7.0" -typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} - -[[package]] -name = "regex" -version = "2024.11.6" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.8" -files = [ - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, - {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, - {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, - {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, - {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, - {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, - {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, - {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, - {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, - {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, - {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, - {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, - {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, - {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, -] - -[[package]] -name = "requests" -version = "2.32.3" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.8" -files = [ - {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, - {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "rpds-py" -version = "0.22.3" -description = "Python bindings to Rust's persistent data structures (rpds)" -optional = false -python-versions = ">=3.9" -files = [ - {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, - {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf"}, - {file = "rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652"}, - {file = "rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8"}, - {file = "rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f"}, - {file = "rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a"}, - {file = "rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64"}, - {file = "rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c"}, - {file = "rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e"}, - {file = "rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7"}, - {file = "rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627"}, - {file = "rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4"}, - {file = "rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84"}, - {file = "rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f"}, - {file = "rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de"}, - {file = "rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9"}, - {file = "rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333"}, - {file = "rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730"}, - {file = "rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf"}, - {file = "rpds_py-0.22.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea"}, - {file = "rpds_py-0.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520"}, - {file = "rpds_py-0.22.3-cp39-cp39-win32.whl", hash = "sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9"}, - {file = "rpds_py-0.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6"}, - {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, -] - -[[package]] -name = "ruff" -version = "0.6.9" -description = "An extremely fast Python linter and code formatter, written in Rust." -optional = false -python-versions = ">=3.7" -files = [ - {file = "ruff-0.6.9-py3-none-linux_armv6l.whl", hash = "sha256:064df58d84ccc0ac0fcd63bc3090b251d90e2a372558c0f057c3f75ed73e1ccd"}, - {file = "ruff-0.6.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:140d4b5c9f5fc7a7b074908a78ab8d384dd7f6510402267bc76c37195c02a7ec"}, - {file = "ruff-0.6.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:53fd8ca5e82bdee8da7f506d7b03a261f24cd43d090ea9db9a1dc59d9313914c"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645d7d8761f915e48a00d4ecc3686969761df69fb561dd914a773c1a8266e14e"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eae02b700763e3847595b9d2891488989cac00214da7f845f4bcf2989007d577"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d5ccc9e58112441de8ad4b29dcb7a86dc25c5f770e3c06a9d57e0e5eba48829"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:417b81aa1c9b60b2f8edc463c58363075412866ae4e2b9ab0f690dc1e87ac1b5"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c866b631f5fbce896a74a6e4383407ba7507b815ccc52bcedabb6810fdb3ef7"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7b118afbb3202f5911486ad52da86d1d52305b59e7ef2031cea3425142b97d6f"}, - {file = "ruff-0.6.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67267654edc23c97335586774790cde402fb6bbdb3c2314f1fc087dee320bfa"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3ef0cc774b00fec123f635ce5c547dac263f6ee9fb9cc83437c5904183b55ceb"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:12edd2af0c60fa61ff31cefb90aef4288ac4d372b4962c2864aeea3a1a2460c0"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:55bb01caeaf3a60b2b2bba07308a02fca6ab56233302406ed5245180a05c5625"}, - {file = "ruff-0.6.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:925d26471fa24b0ce5a6cdfab1bb526fb4159952385f386bdcc643813d472039"}, - {file = "ruff-0.6.9-py3-none-win32.whl", hash = "sha256:eb61ec9bdb2506cffd492e05ac40e5bc6284873aceb605503d8494180d6fc84d"}, - {file = "ruff-0.6.9-py3-none-win_amd64.whl", hash = "sha256:785d31851c1ae91f45b3d8fe23b8ae4b5170089021fbb42402d811135f0b7117"}, - {file = "ruff-0.6.9-py3-none-win_arm64.whl", hash = "sha256:a9641e31476d601f83cd602608739a0840e348bda93fec9f1ee816f8b6798b93"}, - {file = "ruff-0.6.9.tar.gz", hash = "sha256:b076ef717a8e5bc819514ee1d602bbdca5b4420ae13a9cf61a0c0a4f53a2baa2"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "soupsieve" -version = "2.6" -description = "A modern CSS selector implementation for Beautiful Soup." -optional = false -python-versions = ">=3.8" -files = [ - {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, - {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, -] - -[[package]] -name = "tiktoken" -version = "0.8.0" -description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" -optional = false -python-versions = ">=3.9" -files = [ - {file = "tiktoken-0.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b07e33283463089c81ef1467180e3e00ab00d46c2c4bbcef0acab5f771d6695e"}, - {file = "tiktoken-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9269348cb650726f44dd3bbb3f9110ac19a8dcc8f54949ad3ef652ca22a38e21"}, - {file = "tiktoken-0.8.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e13f37bc4ef2d012731e93e0fef21dc3b7aea5bb9009618de9a4026844e560"}, - {file = "tiktoken-0.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f13d13c981511331eac0d01a59b5df7c0d4060a8be1e378672822213da51e0a2"}, - {file = "tiktoken-0.8.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6b2ddbc79a22621ce8b1166afa9f9a888a664a579350dc7c09346a3b5de837d9"}, - {file = "tiktoken-0.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d8c2d0e5ba6453a290b86cd65fc51fedf247e1ba170191715b049dac1f628005"}, - {file = "tiktoken-0.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d622d8011e6d6f239297efa42a2657043aaed06c4f68833550cac9e9bc723ef1"}, - {file = "tiktoken-0.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2efaf6199717b4485031b4d6edb94075e4d79177a172f38dd934d911b588d54a"}, - {file = "tiktoken-0.8.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5637e425ce1fc49cf716d88df3092048359a4b3bbb7da762840426e937ada06d"}, - {file = "tiktoken-0.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fb0e352d1dbe15aba082883058b3cce9e48d33101bdaac1eccf66424feb5b47"}, - {file = "tiktoken-0.8.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:56edfefe896c8f10aba372ab5706b9e3558e78db39dd497c940b47bf228bc419"}, - {file = "tiktoken-0.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:326624128590def898775b722ccc327e90b073714227175ea8febbc920ac0a99"}, - {file = "tiktoken-0.8.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:881839cfeae051b3628d9823b2e56b5cc93a9e2efb435f4cf15f17dc45f21586"}, - {file = "tiktoken-0.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fe9399bdc3f29d428f16a2f86c3c8ec20be3eac5f53693ce4980371c3245729b"}, - {file = "tiktoken-0.8.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9a58deb7075d5b69237a3ff4bb51a726670419db6ea62bdcd8bd80c78497d7ab"}, - {file = "tiktoken-0.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2908c0d043a7d03ebd80347266b0e58440bdef5564f84f4d29fb235b5df3b04"}, - {file = "tiktoken-0.8.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:294440d21a2a51e12d4238e68a5972095534fe9878be57d905c476017bff99fc"}, - {file = "tiktoken-0.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:d8f3192733ac4d77977432947d563d7e1b310b96497acd3c196c9bddb36ed9db"}, - {file = "tiktoken-0.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:02be1666096aff7da6cbd7cdaa8e7917bfed3467cd64b38b1f112e96d3b06a24"}, - {file = "tiktoken-0.8.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94ff53c5c74b535b2cbf431d907fc13c678bbd009ee633a2aca269a04389f9a"}, - {file = "tiktoken-0.8.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b231f5e8982c245ee3065cd84a4712d64692348bc609d84467c57b4b72dcbc5"}, - {file = "tiktoken-0.8.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4177faa809bd55f699e88c96d9bb4635d22e3f59d635ba6fd9ffedf7150b9953"}, - {file = "tiktoken-0.8.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5376b6f8dc4753cd81ead935c5f518fa0fbe7e133d9e25f648d8c4dabdd4bad7"}, - {file = "tiktoken-0.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:18228d624807d66c87acd8f25fc135665617cab220671eb65b50f5d70fa51f69"}, - {file = "tiktoken-0.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7e17807445f0cf1f25771c9d86496bd8b5c376f7419912519699f3cc4dc5c12e"}, - {file = "tiktoken-0.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:886f80bd339578bbdba6ed6d0567a0d5c6cfe198d9e587ba6c447654c65b8edc"}, - {file = "tiktoken-0.8.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6adc8323016d7758d6de7313527f755b0fc6c72985b7d9291be5d96d73ecd1e1"}, - {file = "tiktoken-0.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b591fb2b30d6a72121a80be24ec7a0e9eb51c5500ddc7e4c2496516dd5e3816b"}, - {file = "tiktoken-0.8.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:845287b9798e476b4d762c3ebda5102be87ca26e5d2c9854002825d60cdb815d"}, - {file = "tiktoken-0.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:1473cfe584252dc3fa62adceb5b1c763c1874e04511b197da4e6de51d6ce5a02"}, - {file = "tiktoken-0.8.0.tar.gz", hash = "sha256:9ccbb2740f24542534369c5635cfd9b2b3c2490754a78ac8831d99f89f94eeb2"}, -] - -[package.dependencies] -regex = ">=2022.1.18" -requests = ">=2.26.0" - -[package.extras] -blobfile = ["blobfile (>=2)"] - -[[package]] -name = "tokenizers" -version = "0.21.0" -description = "" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tokenizers-0.21.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2"}, - {file = "tokenizers-0.21.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e"}, - {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b177fb54c4702ef611de0c069d9169f0004233890e0c4c5bd5508ae05abf193"}, - {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6b43779a269f4629bebb114e19c3fca0223296ae9fea8bb9a7a6c6fb0657ff8e"}, - {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aeb255802be90acfd363626753fda0064a8df06031012fe7d52fd9a905eb00e"}, - {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8b09dbeb7a8d73ee204a70f94fc06ea0f17dcf0844f16102b9f414f0b7463ba"}, - {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:400832c0904f77ce87c40f1a8a27493071282f785724ae62144324f171377273"}, - {file = "tokenizers-0.21.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84ca973b3a96894d1707e189c14a774b701596d579ffc7e69debfc036a61a04"}, - {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:eb7202d231b273c34ec67767378cd04c767e967fda12d4a9e36208a34e2f137e"}, - {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:089d56db6782a73a27fd8abf3ba21779f5b85d4a9f35e3b493c7bbcbbf0d539b"}, - {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:c87ca3dc48b9b1222d984b6b7490355a6fdb411a2d810f6f05977258400ddb74"}, - {file = "tokenizers-0.21.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4145505a973116f91bc3ac45988a92e618a6f83eb458f49ea0790df94ee243ff"}, - {file = "tokenizers-0.21.0-cp39-abi3-win32.whl", hash = "sha256:eb1702c2f27d25d9dd5b389cc1f2f51813e99f8ca30d9e25348db6585a97e24a"}, - {file = "tokenizers-0.21.0-cp39-abi3-win_amd64.whl", hash = "sha256:87841da5a25a3a5f70c102de371db120f41873b854ba65e52bccd57df5a3780c"}, - {file = "tokenizers-0.21.0.tar.gz", hash = "sha256:ee0894bf311b75b0c03079f33859ae4b2334d675d4e93f5a4132e1eae2834fe4"}, -] - -[package.dependencies] -huggingface-hub = ">=0.16.4,<1.0" - -[package.extras] -dev = ["tokenizers[testing]"] -docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] -testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] - -[[package]] -name = "tomlkit" -version = "0.13.2" -description = "Style preserving TOML library" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tomlkit-0.13.2-py3-none-any.whl", hash = "sha256:7a974427f6e119197f670fbbbeae7bef749a6c14e793db934baefc1b5f03efde"}, - {file = "tomlkit-0.13.2.tar.gz", hash = "sha256:fff5fe59a87295b278abd31bec92c15d9bc4a06885ab12bcea52c71119392e79"}, -] - -[[package]] -name = "tox" -version = "4.24.1" -description = "tox is a generic virtualenv management and test command line tool" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tox-4.24.1-py3-none-any.whl", hash = "sha256:57ba7df7d199002c6df8c2db9e6484f3de6ca8f42013c083ea2d4d1e5c6bdc75"}, - {file = "tox-4.24.1.tar.gz", hash = "sha256:083a720adbc6166fff0b7d1df9d154f9d00bfccb9403b8abf6bc0ee435d6a62e"}, -] - -[package.dependencies] -cachetools = ">=5.5" -chardet = ">=5.2" -colorama = ">=0.4.6" -filelock = ">=3.16.1" -packaging = ">=24.2" -platformdirs = ">=4.3.6" -pluggy = ">=1.5" -pyproject-api = ">=1.8" -virtualenv = ">=20.27.1" - -[package.extras] -test = ["devpi-process (>=1.0.2)", "pytest (>=8.3.3)", "pytest-mock (>=3.14)"] - -[[package]] -name = "tqdm" -version = "4.67.1" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, - {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["nbval", "pytest (>=6)", "pytest-asyncio (>=0.24)", "pytest-cov", "pytest-timeout"] -discord = ["requests"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "types-requests" -version = "2.32.0.20241016" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.8" -files = [ - {file = "types-requests-2.32.0.20241016.tar.gz", hash = "sha256:0d9cad2f27515d0e3e3da7134a1b6f28fb97129d86b867f24d9c726452634d95"}, - {file = "types_requests-2.32.0.20241016-py3-none-any.whl", hash = "sha256:4195d62d6d3e043a4eaaf08ff8a62184584d2e8684e9d2aa178c7915a7da3747"}, -] - -[package.dependencies] -urllib3 = ">=2" - -[[package]] -name = "typing-extensions" -version = "4.12.2" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "urllib3" -version = "2.3.0" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.9" -files = [ - {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, - {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "virtualenv" -version = "20.29.1" -description = "Virtual Python Environment builder" -optional = false -python-versions = ">=3.8" -files = [ - {file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"}, - {file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"}, -] - -[package.dependencies] -distlib = ">=0.3.7,<1" -filelock = ">=3.12.2,<4" -platformdirs = ">=3.9.1,<5" - -[package.extras] -docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] -test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] - -[[package]] -name = "wikipedia" -version = "1.4.0" -description = "Wikipedia API for Python" -optional = false -python-versions = "*" -files = [ - {file = "wikipedia-1.4.0.tar.gz", hash = "sha256:db0fad1829fdd441b1852306e9856398204dc0786d2996dd2e0c8bb8e26133b2"}, -] - -[package.dependencies] -beautifulsoup4 = "*" -requests = ">=2.0.0,<3.0.0" - -[[package]] -name = "yarl" -version = "1.18.3" -description = "Yet another URL library" -optional = false -python-versions = ">=3.9" -files = [ - {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, - {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, - {file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"}, - {file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"}, - {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"}, - {file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"}, - {file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"}, - {file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"}, - {file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"}, - {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"}, - {file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"}, - {file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"}, - {file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"}, - {file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"}, - {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"}, - {file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"}, - {file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"}, - {file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"}, - {file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"}, - {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"}, - {file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"}, - {file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"}, - {file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"}, - {file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"}, - {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"}, - {file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"}, - {file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"}, - {file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"}, - {file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" -propcache = ">=0.2.0" - -[[package]] -name = "zipp" -version = "3.21.0" -description = "Backport of pathlib-compatible object wrapper for zip files" -optional = false -python-versions = ">=3.9" -files = [ - {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, - {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, -] - -[package.extras] -check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] -cover = ["pytest-cov"] -doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -enabler = ["pytest-enabler (>=2.2)"] -test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] -type = ["pytest-mypy"] - -[metadata] -lock-version = "2.0" -python-versions = ">= 3.11, < 3.13" -content-hash = "3a1b14c8f0d901bdfa4487f46ccab27868fd6ff6b6869f80c03738cf03c0d75a" diff --git a/framework/bee-py/pyproject.toml b/framework/bee-py/pyproject.toml deleted file mode 100644 index 60a638d..0000000 --- a/framework/bee-py/pyproject.toml +++ /dev/null @@ -1,50 +0,0 @@ -[tool.poetry] -name = "bee_agent" -version = "0.1.0" -description = "" -authors = ["IBM"] -readme = "README.md" - -[tool.poetry.dependencies] -python = ">= 3.11, < 3.13" -pydantic = "^2.10" -requests = "^2.32" -pylint = "^3.3.2" -pydantic-settings = "^2.6.1" -chevron = "^0.14.0" -types-requests = "^2.32.0.20241016" -litellm = "^1.55.3" -aiofiles = "^24.1.0" -pyventus = "^0.6.0" -wikipedia = "^1.4.0" -jinja2 = "^3.1.5" - -[tool.poetry.group.dev.dependencies] -tox = "^4.20" -black = "^24.0" -mypy = "^1.13" -ruff = "^0.6.7" -pylint = "^3.3.2" -pytest = "^8.3.3" - -[build-system] -requires = ["poetry-core"] -build-backend = "poetry.core.masonry.api" - -[tool.poetry.scripts] -lint = "dev_tools.scripts:lint" -commit = "dev_tools.scripts:commit" - -[tool.pytest.ini_options] -addopts = "-v" -testpaths = ["tests"] -python_files = ["test_*.py", "*_test.py"] -log_cli = true -log_cli_level = "DEBUG" -log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" -log_cli_date_format = "%Y-%m-%d %H:%M:%S" -asyncio_mode = "strict" - -[tool.pytest-asyncio] -asyncio_mode = "strict" -default_fixture_loop_scope = "function" diff --git a/framework/bee-py/tests/__init__.py b/framework/bee-py/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/framework/bee-py/tests/bee_agent/tools/test_mcp_tool.py b/framework/bee-py/tests/bee_agent/tools/test_mcp_tool.py deleted file mode 100644 index 76bda23..0000000 --- a/framework/bee-py/tests/bee_agent/tools/test_mcp_tool.py +++ /dev/null @@ -1,137 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -import pytest -from unittest.mock import AsyncMock, MagicMock -from mcp.types import ( - Tool as MCPToolInfo, - CallToolResult, - TextContent, -) -from mcp.client.session import ClientSession -from bee_agent.tools import MCPTool, MCPToolOutput - - -# Common Fixtures -@pytest.fixture -def mock_client_session(): - return AsyncMock(spec=ClientSession) - - -# Basic Tool Test Fixtures -@pytest.fixture -def mock_tool_info(): - return MCPToolInfo( - name="test_tool", - description="A test tool", - inputSchema={}, - ) - - -@pytest.fixture -def call_tool_result(): - return CallToolResult( - output="test_output", - content=[ - { - "text": "test_content", - "type": "text", - } - ], - ) - - -# Calculator Tool Test Fixtures -@pytest.fixture -def add_numbers_tool_info(): - return MCPToolInfo( - name="add_numbers", - description="Adds two numbers together", - inputSchema={ - "type": "object", - "properties": {"a": {"type": "number"}, "b": {"type": "number"}}, - "required": ["a", "b"], - }, - ) - - -@pytest.fixture -def add_result(): - return CallToolResult( - output="8", - content=[TextContent(text="8", type="text")], - ) - - -# Basic Tool Tests -class TestMCPTool: - @pytest.mark.asyncio - async def test_mcp_tool_initialization(self, mock_client_session, mock_tool_info): - tool = MCPTool(client=mock_client_session, tool=mock_tool_info) - - assert tool.name == "test_tool" - assert tool.description == "A test tool" - assert tool.input_schema() == {} - - @pytest.mark.asyncio - async def test_mcp_tool_run( - self, mock_client_session, mock_tool_info, call_tool_result - ): - mock_client_session.call_tool = AsyncMock(return_value=call_tool_result) - tool = MCPTool(client=mock_client_session, tool=mock_tool_info) - input_data = {"key": "value"} - - result = await tool._run(input_data) - - mock_client_session.call_tool.assert_awaited_once_with( - name="test_tool", arguments=input_data - ) - assert isinstance(result, MCPToolOutput) - assert result.result == call_tool_result - - @pytest.mark.asyncio - async def test_mcp_tool_from_client(self, mock_client_session, mock_tool_info): - tools_result = MagicMock() - tools_result.tools = [mock_tool_info] - mock_client_session.list_tools = AsyncMock(return_value=tools_result) - - tools = await MCPTool.from_client(mock_client_session) - - mock_client_session.list_tools.assert_awaited_once() - assert len(tools) == 1 - assert tools[0].name == "test_tool" - assert tools[0].description == "A test tool" - - -# Calculator Tool Tests -class TestAddNumbersTool: - @pytest.mark.asyncio - async def test_add_numbers_mcp( - self, mock_client_session, add_numbers_tool_info, add_result - ): - mock_client_session.call_tool = AsyncMock(return_value=add_result) - tool = MCPTool(client=mock_client_session, tool=add_numbers_tool_info) - input_data = {"a": 5, "b": 3} - - result = await tool._run(input_data) - - mock_client_session.call_tool.assert_awaited_once_with( - name="add_numbers", arguments=input_data - ) - assert isinstance(result, MCPToolOutput) - assert result.result.output == "8" - assert result.result.content[0].text == "8" - - @pytest.mark.asyncio - async def test_add_numbers_from_client( - self, mock_client_session, add_numbers_tool_info - ): - tools_result = MagicMock() - tools_result.tools = [add_numbers_tool_info] - mock_client_session.list_tools = AsyncMock(return_value=tools_result) - - tools = await MCPTool.from_client(mock_client_session) - - mock_client_session.list_tools.assert_awaited_once() - assert len(tools) == 1 - assert tools[0].name == "add_numbers" - assert "adds two numbers" in tools[0].description.lower() diff --git a/framework/bee-py/tests/conftest.py b/framework/bee-py/tests/conftest.py deleted file mode 100644 index 029ceee..0000000 --- a/framework/bee-py/tests/conftest.py +++ /dev/null @@ -1,8 +0,0 @@ -"""Pytest configuration for asyncio testing.""" - -import pytest - - -def pytest_addoption(parser): - """Add pytest command line options.""" - parser.addini("asyncio_mode", "default mode for async fixtures", default="strict") diff --git a/framework/bee-ts/README.md b/framework/bee-ts/README.md deleted file mode 100644 index 15b0981..0000000 --- a/framework/bee-ts/README.md +++ /dev/null @@ -1,3 +0,0 @@ -> COMING SOON - -The Typescript implementation of the Bee Agent Framework is available at: https://github.com/i-am-bee/bee-agent-framework diff --git a/bee-hive/pyproject.toml b/pyproject.toml similarity index 100% rename from bee-hive/pyproject.toml rename to pyproject.toml diff --git a/bee-hive/run_workflow.py b/run_workflow.py similarity index 100% rename from bee-hive/run_workflow.py rename to run_workflow.py diff --git a/bee-hive/tests/__init__.py b/tests/__init__.py similarity index 100% rename from bee-hive/tests/__init__.py rename to tests/__init__.py diff --git a/bee-hive/tests/bee/__init__.py b/tests/bee/__init__.py similarity index 100% rename from bee-hive/tests/bee/__init__.py rename to tests/bee/__init__.py diff --git a/bee-hive/tests/bee/agents.yaml b/tests/bee/agents.yaml similarity index 100% rename from bee-hive/tests/bee/agents.yaml rename to tests/bee/agents.yaml diff --git a/bee-hive/tests/bee/test_bee.py b/tests/bee/test_bee.py similarity index 100% rename from bee-hive/tests/bee/test_bee.py rename to tests/bee/test_bee.py diff --git a/bee-hive/tests/bee/workflow.yaml b/tests/bee/workflow.yaml similarity index 100% rename from bee-hive/tests/bee/workflow.yaml rename to tests/bee/workflow.yaml diff --git a/bee-hive/tests/crewai/__init__.py b/tests/crewai/__init__.py similarity index 100% rename from bee-hive/tests/crewai/__init__.py rename to tests/crewai/__init__.py diff --git a/bee-hive/tests/crewai/agents.yaml b/tests/crewai/agents.yaml similarity index 100% rename from bee-hive/tests/crewai/agents.yaml rename to tests/crewai/agents.yaml diff --git a/bee-hive/tests/crewai/crew_dummy.py b/tests/crewai/crew_dummy.py similarity index 100% rename from bee-hive/tests/crewai/crew_dummy.py rename to tests/crewai/crew_dummy.py diff --git a/bee-hive/tests/crewai/test_crewai.py b/tests/crewai/test_crewai.py similarity index 100% rename from bee-hive/tests/crewai/test_crewai.py rename to tests/crewai/test_crewai.py diff --git a/bee-hive/tests/crewai/workflow.yaml b/tests/crewai/workflow.yaml similarity index 100% rename from bee-hive/tests/crewai/workflow.yaml rename to tests/crewai/workflow.yaml diff --git a/test/examples/condition_agents.yaml b/tests/examples/condition_agents.yaml similarity index 100% rename from test/examples/condition_agents.yaml rename to tests/examples/condition_agents.yaml diff --git a/test/examples/condition_workflow.yaml b/tests/examples/condition_workflow.yaml similarity index 100% rename from test/examples/condition_workflow.yaml rename to tests/examples/condition_workflow.yaml diff --git a/test/examples/test_condition.py b/tests/examples/test_condition.py similarity index 94% rename from test/examples/test_condition.py rename to tests/examples/test_condition.py index 5d611aa..9e8a5af 100644 --- a/test/examples/test_condition.py +++ b/tests/examples/test_condition.py @@ -8,7 +8,7 @@ import dotenv from openai import OpenAI import yaml -from workflow import Workflow +from bee_hive.workflow import Workflow dotenv.load_dotenv() diff --git a/test/schema/conditional_workflow.json b/tests/schema/conditional_workflow.json similarity index 100% rename from test/schema/conditional_workflow.json rename to tests/schema/conditional_workflow.json diff --git a/test/schema/conditional_workflow.yml b/tests/schema/conditional_workflow.yml similarity index 100% rename from test/schema/conditional_workflow.yml rename to tests/schema/conditional_workflow.yml diff --git a/test/schema/funnier_workflow.json b/tests/schema/funnier_workflow.json similarity index 100% rename from test/schema/funnier_workflow.json rename to tests/schema/funnier_workflow.json diff --git a/test/schema/funnier_workflow.yml b/tests/schema/funnier_workflow.yml similarity index 100% rename from test/schema/funnier_workflow.yml rename to tests/schema/funnier_workflow.yml diff --git a/test/schema/simple_agent.json b/tests/schema/simple_agent.json similarity index 100% rename from test/schema/simple_agent.json rename to tests/schema/simple_agent.json diff --git a/test/schema/simple_agent.yml b/tests/schema/simple_agent.yml similarity index 100% rename from test/schema/simple_agent.yml rename to tests/schema/simple_agent.yml diff --git a/test/schema/simple_workflow.json b/tests/schema/simple_workflow.json similarity index 100% rename from test/schema/simple_workflow.json rename to tests/schema/simple_workflow.json diff --git a/test/schema/simple_workflow.yml b/tests/schema/simple_workflow.yml similarity index 100% rename from test/schema/simple_workflow.yml rename to tests/schema/simple_workflow.yml diff --git a/bee-hive/tests/workflow/__init__.py b/tests/workflow/__init__.py similarity index 100% rename from bee-hive/tests/workflow/__init__.py rename to tests/workflow/__init__.py diff --git a/bee-hive/tests/workflow/test_sequence.py b/tests/workflow/test_sequence.py similarity index 100% rename from bee-hive/tests/workflow/test_sequence.py rename to tests/workflow/test_sequence.py diff --git a/bee-hive/tests/workflow/workflow.yaml b/tests/workflow/workflow.yaml similarity index 100% rename from bee-hive/tests/workflow/workflow.yaml rename to tests/workflow/workflow.yaml