[0.0.6] - 3-21-2024 Bug Fixes (#47)

* 🧪 asyncify tests

* ✨ asyncify client

* Basic Test for Page based pagination

* add sync buildstep and client

* add vscode DX

* Added Testing for generators and updated examples

* feat: example updates

* readme exists now

* Stylistic changes and generic message

* Metamessages with other refactoring - untested

* Work with unit tests

* Fix Examples

* MEME-78 Update Changelogs

* Docstrings to client

* 🧪 autogenerate sync tests

* test one

* add db type

* sync client

* add status badge

* add coverage

* add file

* give perms

* properly output coverage

* split test and coverage

* rename action

* 🧪 autogenerate sync tests (#16)

* Vector Support (#18)

* Scaffold for PGVector support

* Buggy crud with logic skeleton on api

* Crud logic and schema definition for pgvector

* Populate all routes and refactor to name Collection

* vince's progress

* AsyncCollection progress

* Local PGVector Docker Container

* client methods for sdk except document delete and update

* Vector Support Passing All Test Cases

* Docs Updates

---------

Co-authored-by: vintro <vince@plasticlabs.ai>

* Add reverse parameters for paginated routes

* Address dependabot

* Formatting

* initial commit on honcho dspy personas

* working, hit token limit and can't test dspy optimization

* initial version working, need to test optimization

* optimizers working, but appending any example

* ready for user object (tbomk)

* Revert "add test actions and coverage"

* Refactor to add User and App Tables

* User Object passing test cases

* Update examples

* DSPy Todo and documentation updates

* Add is_active filtering

* Add is_active filtering to the generator

* Fix update user metadata

* working, but weird compiler error

* fixed str error in optimizer

* ship

* sentry

* Open Telemetry

* optional logging with environment variables

* add actions again? (#29)

* add postgres

* add openai key

* readd coverage

* desyncify and add detailed coverage

* ⚙️ chore: update start script in VS Code to include poetry install --no-root before running uvicorn (#33)

* Refactored code but need to tweak asyncpg

* Working Async API using Psycopg3

* Update Workflow Connection URI

* Update Workflow Connection URI in coverage test as well

* Skeleton for Dialectic API

* Fixes DEV-217 URL Encoding

* Add Built-in Langchain Utility function

* Sphinx Docs MVP

* Metadata filtering for all fixes dev-261

* Basic Dialectic Endpoint fixes dev-253

* Working Fact Deriver

* 0.0.5 Docs and README updates

* Cloudflare Sphinx

* update example to use right function (#36)

* 🚀 feat: add support for running API using docker-compose with configurable environment variables and update docker-compose.yml for API and database services. (#34)

Co-authored-by: Vineeth Voruganti <13438633+VVoruganti@users.noreply.github.com>

* add interrogate

* routerify everything

* full docstring coverage

* remove unused imports and fix env issue

* Update docker-compose connection uri and remove auto-stop to deriver process

* Docstrings and langchain message converter in reverse

* Sentry, OTEL, langchain both directions, fly.toml for deriver

* Rename to deriver

* Fix favicon and remove metadata from schema

* 0.0.6 Notes

* Changelog edit

* Route bug fix

* Route bug fix again

---------

Co-authored-by: hyusap <paulayush@gmail.com>
Co-authored-by: vintro <vince@plasticlabs.ai>
Co-authored-by: vintro <77507980+vintrocode@users.noreply.github.com>
This commit is contained in:
Vineeth Voruganti 2024-03-21 12:22:29 -07:00 committed by GitHub
parent 663d065293
commit 29cd37bc90
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 2352 additions and 1595 deletions

View File

@ -36,6 +36,9 @@ jobs:
poetry install
poetry run coverage run -m pytest
poetry run coverage report --format=markdown > coverage.md
echo -e "\n---\n# Docstring Coverage\n\`\`\`" >> coverage.md
poetry run interrogate -v honcho >> coverage.md
echo -e "\`\`\`" >> coverage.md
cd ..
- name: Add Coverage PR Comment
uses: marocchino/sticky-pull-request-comment@v2

3
.gitignore vendored
View File

@ -1,5 +1,6 @@
api/**/*.db
api/data
api/docker-compose.yml
# Byte-compiled / optimized / DLL files

View File

@ -1,17 +1,30 @@
# Honcho
![Static Badge](https://img.shields.io/badge/Version-0.0.5-blue)
# 🫡 Honcho
![Static Badge](https://img.shields.io/badge/Version-0.0.6-blue)
[![Discord](https://img.shields.io/discord/1016845111637839922?style=flat&logo=discord&logoColor=23ffffff&label=Plastic%20Labs&labelColor=235865F2)](https://discord.gg/plasticlabs)
![GitHub License](https://img.shields.io/github/license/plastic-labs/honcho)
![GitHub Repo stars](https://img.shields.io/github/stars/plastic-labs/honcho)
[![X (formerly Twitter) URL](https://img.shields.io/twitter/url?url=https%3A%2F%2Ftwitter.com%2Fplastic_labs)](https://twitter.com/plastic_labs)
A User context management solution for building AI Agents and LLM powered
applications.
Honcho is a platform for making AI agents and LLM powered applications that are personalized
to their end users.
Read about the motivation of this project [here](https://blog.plasticlabs.ai).
Read the user documenation [here](https://docs.honcho.dev)
## Table of Contents
- [Project Structure](#project-structure)
- [Usage](#usage)
- [API](#api)
- [Docker](#docker)
- [Manually](#manually)
- [Deploying on Fly.io](#deploy-on-fly)
- [Client SDK](#client-sdk)
- [Use Locally](#use-locally)
- [Contributing](#contributing)
- [License](#license)
## Project Structure
The Honcho repo is a monorepo containing the server/API that manages database
@ -35,6 +48,19 @@ directories.
### API
#### Docker
The API can be run using docker-compose. The `docker-compose.yml.example` file can be copied to `docker-compose.yml` and the environment variables can be set in the `.env` file.
```bash
cd honcho/api
cp docker-compose.yml.example docker-compose.yml
[ update the file with openai key and other wanted environment variables ]
docker compose up -d
```
#### Manually
The API can be run either by installing the necessary dependencies and then
specifying the appropriate environment variables.
@ -48,7 +74,7 @@ poetry install # install dependencies
2. Copy the `.env.template` file and specify the type of database and
connection_uri. For testing sqlite is fine. The below example uses an
in-memory sqlite database.
in-memory sqlite database.
> Honcho has been tested with Postgresql and PGVector
@ -72,26 +98,11 @@ poetry shell # Activate virtual environment if not already enabled
python -m uvicorn src.main:app --reload
```
#### Docker
Alternatively there is also a `Dockerfile` included to run the API server from a
docker container.
The `.env` file is not loaded into the docker container and should still be
configured from outside.
```bash
cd honcho/api
docker build -t honcho-api .
docker run --env-file .env -p 8000:8000 honcho-api:latest
```
#### Deploy on Fly
The API can also be deployed on fly.io. Follow the [Fly.io
Docs](https://fly.io/docs/getting-started/) to setup your environment and the
`flyctl`.
`flyctl`.
Once `flyctl` is set up use the following commands to launch the application:
@ -116,7 +127,10 @@ alternatively if you are using poetry run:
poetry add honcho-ai
```
checkout the [example folder](./example/) for examples of how to use the sdk
checkout the [SDK Reference](https://api.python.honcho.dev) for a detailed
look at the different methods and how to use them.
Also, check out the[example folder](./example/) for examples of how to use the sdk
#### Use Locally
@ -134,12 +148,12 @@ See more information [here](https://python-poetry.org/docs/cli/#add)
This project is completely open source and welcomes any and all open source
contributions. The workflow for contributing is to make a fork of the
repository. You can claim an issue in the issues tab or start a new thread to
indicate a feature or bug fix you are working on.
indicate a feature or bug fix you are working on.
Once you have finished your contribution make a PR pointed at the `staging`
branch, and it will be reviewed by a project manager. Feel free to join us in
our [discord](http://discord.gg/plasticlabs) to discuss your changes or get
help.
help.
Once your changes are accepted and merged into staging they will undergo a
period of live testing before entering the upstream into `main`

View File

@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.0.6] — 2024-03-21
### Added
* Full docker-compose for API and Database
### Fixed
* API Response schema removed unnecessary fields
* OTEL logging to properly work with async database engine
* `fly.toml` default settings for deriver set `auto_stop=false`
### Changed
* Refactored API server into multiple route files
## [0.0.5] — 2024-03-14
### Added

View File

@ -0,0 +1,41 @@
version: "3.8"
services:
api:
build:
context: .
dockerfile: Dockerfile
ports:
- 8000:8000
volumes:
- .:/app
environment:
- DATABASE_TYPE=postgres
- CONNECTION_URI=postgresql+psycopg://testuser:testpwd@database:5432/honcho
- OPENAI_API_KEY=[YOUR_OPENAI_API_KEY]
- OPENTELEMETRY_ENABLED=false
- SENTRY_ENABLED=false
- SENTRY_DSN=
- OTEL_SERVICE_NAME=honcho
- OTEL_PYTHON_LOGGING_AUTO_INSTRUMENTATION_ENABLED=true
- OTEL_PYTHON_LOG_CORRELATION=true
- OTEL_PYTHON_LOG_LEVEL=
- OTEL_EXPORTER_OTLP_PROTOCOL=
- OTEL_EXPORTER_OTLP_ENDPOINT=
- OTEL_EXPORTER_OTLP_HEADERS=
- OTEL_RESOURCE_ATTRIBUTES=
- DEBUG_LOG_OTEL_TO_PROVIDER=false
- DEBUG_LOG_OTEL_TO_CONSOLE=true
database:
image: ankane/pgvector
restart: always
ports:
- 5432:5432
environment:
- POSTGRES_DB=honcho
- POSTGRES_USER=testuser
- POSTGRES_PASSWORD=testpwd
- POSTGRES_HOST_AUTH_METHOD=trust
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- ./local/init.sql:/docker-entrypoint-initdb.d/init.sql
- ./data:/var/lib/postgresql/data/

View File

@ -14,7 +14,17 @@ kill_timeout = "5s"
[processes]
api = "python -m uvicorn src.main:app --host 0.0.0.0 --port 8000"
deriver = "python -m src.harvester"
deriver = "python -m src.deriver"
[[services]]
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 1
processes = ["deriver"]
protocol = "tcp"
[services.concurrency]
hard_limit = 250
soft_limit = 200
[http_service]
internal_port = 8000
@ -31,4 +41,4 @@ kill_timeout = "5s"
cpu_kind = "shared"
cpus = 1
memory_mb = 512
processes = ["api"]
processes = ["api", "deriver"]

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "honcho"
version = "0.0.5"
version = "0.0.6"
description = "Honcho Server"
authors = ["Plastic Labs <hello@plasticlabs.ai>"]
readme = "README.md"

View File

@ -5,7 +5,7 @@ from sqlalchemy import create_engine
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from sqlalchemy.ext.declarative import declarative_base
load_dotenv()
load_dotenv(override=True)
connect_args = {}

15
api/src/dependencies.py Normal file
View File

@ -0,0 +1,15 @@
from fastapi import Depends
from .db import SessionLocal
from sqlalchemy.ext.asyncio import AsyncSession
async def get_db():
"""FastAPI Dependency Generator for Database"""
db: AsyncSession = SessionLocal()
try:
yield db
finally:
await db.close()
db: AsyncSession = Depends(get_db)

211
api/src/deriver.py Normal file
View File

@ -0,0 +1,211 @@
import asyncio
import os
import uuid
from typing import List
import sentry_sdk
from dotenv import load_dotenv
from langchain_core.output_parsers import NumberedListOutputParser
from langchain_core.prompts import (
ChatPromptTemplate,
SystemMessagePromptTemplate,
load_prompt,
)
from langchain_openai import ChatOpenAI
from realtime.connection import Socket
from sqlalchemy import select
from sqlalchemy.orm import selectinload
from . import crud, models, schemas
from .db import SessionLocal
load_dotenv()
SENTRY_ENABLED = os.getenv("SENTRY_ENABLED", "False").lower() == "true"
if SENTRY_ENABLED:
sentry_sdk.init(
dsn=os.getenv("SENTRY_DSN"),
enable_tracing=True,
)
SUPABASE_ID = os.getenv("SUPABASE_ID")
SUPABASE_API_KEY = os.getenv("SUPABASE_API_KEY")
llm = ChatOpenAI(model_name="gpt-4")
output_parser = NumberedListOutputParser()
SYSTEM_DERIVE_FACTS = load_prompt(
os.path.join(os.path.dirname(__file__), "prompts/derive_facts.yaml")
)
SYSTEM_CHECK_DUPS = load_prompt(
os.path.join(os.path.dirname(__file__), "prompts/check_dup_facts.yaml")
)
system_check_dups: SystemMessagePromptTemplate = SystemMessagePromptTemplate(
prompt=SYSTEM_CHECK_DUPS
)
system_derive_facts: SystemMessagePromptTemplate = SystemMessagePromptTemplate(
prompt=SYSTEM_DERIVE_FACTS
)
async def callback(payload):
# print(payload["record"]["is_user"])
# print(type(payload["record"]["is_user"]))
if payload["record"]["is_user"]: # Check if the message is from a user
session_id = payload["record"]["session_id"]
message_id = payload["record"]["id"]
content = payload["record"]["content"]
# Example of querying for a user_id based on session_id, adjust according to your schema
session: models.Session
user_id: uuid.UUID
app_id: uuid.UUID
async with SessionLocal() as db:
stmt = (
select(models.Session)
.join(models.Session.messages)
.where(models.Message.id == message_id)
.where(models.Session.id == session_id)
.options(selectinload(models.Session.user))
)
result = await db.execute(stmt)
session = result.scalars().one()
user = session.user
user_id = user.id
app_id = user.app_id
collection: models.Collection
async with SessionLocal() as db:
collection = await crud.get_collection_by_name(
db, app_id, user_id, "honcho"
)
if collection is None:
collection_create = schemas.CollectionCreate(name="honcho", metadata={})
collection = await crud.create_collection(
db,
collection=collection_create,
app_id=app_id,
user_id=user_id,
)
collection_id = collection.id
await process_user_message(
content, app_id, user_id, session_id, collection_id, message_id
)
return
async def process_user_message(
content: str,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
collection_id: uuid.UUID,
message_id: uuid.UUID,
):
async with SessionLocal() as db:
messages_stmt = await crud.get_messages(
db=db, app_id=app_id, user_id=user_id, session_id=session_id, reverse=True
)
messages_stmt = messages_stmt.limit(10)
response = await db.execute(messages_stmt)
messages = response.scalars().all()
messages = messages[::-1]
# contents = [m.content for m in messages]
# print(contents)
facts = await derive_facts(messages, content)
print("===================")
print(f"DERIVED FACTS: {facts}")
print("===================")
new_facts = await check_dups(app_id, user_id, collection_id, facts)
print("===================")
print(f"CHECKED FOR DUPLICATES: {new_facts}")
print("===================")
for fact in new_facts:
create_document = schemas.DocumentCreate(content=fact)
async with SessionLocal() as db:
doc = await crud.create_document(
db,
document=create_document,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
)
print(f"Returned Document: {doc}")
# doc = crud.create_document(content=fact)
# for fact in new_facts:
# session.create_metamessage(
# message=user_message, metamessage_type="fact", content=fact
# )
# print(f"Created fact: {fact}")
async def derive_facts(chat_history, input: str) -> List[str]:
"""Derive facts from the user input"""
fact_derivation = ChatPromptTemplate.from_messages([system_derive_facts])
chain = fact_derivation | llm
response = await chain.ainvoke(
{
"chat_history": [
(
"user: " + message.content
if message.is_user
else "ai: " + message.content
)
for message in chat_history
],
"user_input": input,
}
)
facts = output_parser.parse(response.content)
return facts
async def check_dups(
app_id: uuid.UUID, user_id: uuid.UUID, collection_id: uuid.UUID, facts: List[str]
):
"""Check that we're not storing duplicate facts"""
check_duplication = ChatPromptTemplate.from_messages([system_check_dups])
query = " ".join(facts)
result = None
async with SessionLocal() as db:
result = await crud.query_documents(
db=db,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
query=query,
top_k=10,
)
# result = collection.query(query=query, top_k=10)
existing_facts = [document.content for document in result]
print("===================")
print(f"Existing Facts {existing_facts}")
print("===================")
if len(existing_facts) == 0:
return facts
chain = check_duplication | llm
response = await chain.ainvoke({"existing_facts": existing_facts, "facts": facts})
new_facts = output_parser.parse(response.content)
print("===================")
print(f"New Facts {facts}")
print("===================")
return new_facts
if __name__ == "__main__":
URL = f"wss://{SUPABASE_ID}.supabase.co/realtime/v1/websocket?apikey={SUPABASE_API_KEY}&vsn=1.0.0"
# URL = f"ws://127.0.0.1:54321/realtime/v1/websocket?apikey={SUPABASE_API_KEY}" # For local Supabase
s = Socket(URL)
s.connect()
channel = s.set_channel("realtime:public:messages")
channel.join().on("INSERT", lambda payload: asyncio.create_task(callback(payload)))
s.listen()

File diff suppressed because it is too large Load Diff

99
api/src/routers/apps.py Normal file
View File

@ -0,0 +1,99 @@
import uuid
from fastapi import APIRouter, HTTPException, Request
from sqlalchemy.ext.asyncio import AsyncSession
from src import crud, schemas
from src.dependencies import db
router = APIRouter(
prefix="/apps",
tags=["apps"],
)
@router.get("/{app_id}", response_model=schemas.App)
async def get_app(request: Request, app_id: uuid.UUID, db=db):
"""Get an App by ID
Args:
app_id (uuid.UUID): The ID of the app
Returns:
schemas.App: App object
"""
app = await crud.get_app(db, app_id=app_id)
if app is None:
raise HTTPException(status_code=404, detail="App not found")
return app
@router.get("/name/{name}", response_model=schemas.App)
async def get_app_by_name(request: Request, name: str, db=db):
"""Get an App by Name
Args:
app_name (str): The name of the app
Returns:
schemas.App: App object
"""
app = await crud.get_app_by_name(db, name=name)
if app is None:
raise HTTPException(status_code=404, detail="App not found")
return app
@router.post("", response_model=schemas.App)
async def create_app(request: Request, app: schemas.AppCreate, db=db):
"""Create an App
Args:
app (schemas.AppCreate): The App object containing any metadata
Returns:
schemas.App: Created App object
"""
return await crud.create_app(db, app=app)
@router.get("/get_or_create/{name}", response_model=schemas.App)
async def get_or_create_app(request: Request, name: str, db=db):
"""Get or Create an App
Args:
app_name (str): The name of the app
Returns:
schemas.App: App object
"""
print("name", name)
app = await crud.get_app_by_name(db, name=name)
if app is None:
app = await crud.create_app(db, app=schemas.AppCreate(name=name))
return app
@router.put("/{app_id}", response_model=schemas.App)
async def update_app(
request: Request, app_id: uuid.UUID, app: schemas.AppUpdate, db=db
):
"""Update an App
Args:
app_id (uuid.UUID): The ID of the app to update
app (schemas.AppUpdate): The App object containing any new metadata
Returns:
schemas.App: The App object of the updated App
"""
honcho_app = await crud.update_app(db, app_id=app_id, app=app)
if honcho_app is None:
raise HTTPException(status_code=404, detail="App not found")
return honcho_app

View File

@ -0,0 +1,160 @@
import json
from typing import Optional
import uuid
from fastapi import APIRouter, HTTPException, Request
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
from src import crud, schemas
from src.dependencies import db
router = APIRouter(
prefix="/apps/{app_id}/users/{user_id}/collections",
tags=["collections"],
)
@router.get("", response_model=Page[schemas.Collection])
async def get_collections(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
reverse: Optional[bool] = False,
filter: Optional[str] = None,
db=db,
):
"""Get All Collections for a User
Args:
app_id (uuid.UUID): The ID of the app representing the client
application using honcho
user_id (uuid.UUID): The User ID representing the user, managed by the user
Returns:
list[schemas.Collection]: List of Collection objects
"""
data = None
if filter is not None:
data = json.loads(filter)
return await paginate(
db,
await crud.get_collections(
db, app_id=app_id, user_id=user_id, filter=data, reverse=reverse
),
)
# @router.get("/id/{collection_id}", response_model=schemas.Collection)
# def get_collection_by_id(
# request: Request,
# app_id: uuid.UUID,
# user_id: uuid.UUID,
# collection_id: uuid.UUID,
# db=db,
# ) -> schemas.Collection:
# honcho_collection = crud.get_collection_by_id(
# db, app_id=app_id, user_id=user_id, collection_id=collection_id
# )
# if honcho_collection is None:
# raise HTTPException(
# status_code=404, detail="collection not found or does not belong to user"
# )
# return honcho_collection
@router.get("/{name}", response_model=schemas.Collection)
async def get_collection_by_name(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
name: str,
db=db,
) -> schemas.Collection:
honcho_collection = await crud.get_collection_by_name(
db, app_id=app_id, user_id=user_id, name=name
)
if honcho_collection is None:
raise HTTPException(
status_code=404, detail="collection not found or does not belong to user"
)
return honcho_collection
@router.post("", response_model=schemas.Collection)
async def create_collection(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection: schemas.CollectionCreate,
db=db,
):
if collection.name == "honcho":
raise HTTPException(
status_code=406,
detail="error invalid collection configuration - honcho is a reserved name",
)
try:
return await crud.create_collection(
db, collection=collection, app_id=app_id, user_id=user_id
)
except ValueError:
raise HTTPException(
status_code=406,
detail="Error invalid collection configuration - name may already exist",
) from None
@router.put("/{collection_id}", response_model=schemas.Collection)
async def update_collection(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
collection: schemas.CollectionUpdate,
db=db,
):
if collection.name is None:
raise HTTPException(
status_code=400, detail="invalid request - name cannot be None"
)
if collection.name == "honcho":
raise HTTPException(
status_code=406,
detail="error invalid collection configuration - honcho is a reserved name",
)
try:
honcho_collection = await crud.update_collection(
db,
collection=collection,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
)
except ValueError:
raise HTTPException(
status_code=406,
detail="Error invalid collection configuration - name may already exist",
) from None
return honcho_collection
@router.delete("/{collection_id}")
async def delete_collection(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
db=db,
):
response = await crud.delete_collection(
db, app_id=app_id, user_id=user_id, collection_id=collection_id
)
if response:
return {"message": "Collection deleted successfully"}
else:
raise HTTPException(
status_code=404, detail="collection not found or does not belong to user"
)

View File

@ -0,0 +1,175 @@
import json
from typing import Optional, Sequence
import uuid
from fastapi import APIRouter, HTTPException, Request
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
from src import crud, schemas
from src.dependencies import db
router = APIRouter(
prefix="/apps/{app_id}/users/{user_id}/collections/{collection_id}",
tags=["documents"],
)
@router.get("/documents", response_model=Page[schemas.Document])
async def get_documents(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
reverse: Optional[bool] = False,
filter: Optional[str] = None,
db=db,
):
try:
data = None
if filter is not None:
data = json.loads(filter)
return await paginate(
db,
await crud.get_documents(
db,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
filter=data,
reverse=reverse,
),
)
except (
ValueError
): # TODO can probably remove this exception ok to return empty here
raise HTTPException(
status_code=404, detail="collection not found or does not belong to user"
) from None
@router.get(
"/documents/{document_id}",
response_model=schemas.Document,
)
async def get_document(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
document_id: uuid.UUID,
db=db,
):
honcho_document = await crud.get_document(
db,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
document_id=document_id,
)
if honcho_document is None:
raise HTTPException(
status_code=404, detail="document not found or does not belong to user"
)
return honcho_document
@router.get("/query", response_model=Sequence[schemas.Document])
async def query_documents(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
query: str,
top_k: int = 5,
filter: Optional[str] = None,
db=db,
):
if top_k is not None and top_k > 50:
top_k = 50 # TODO see if we need to paginate this
data = None
if filter is not None:
data = json.loads(filter)
return await crud.query_documents(
db=db,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
query=query,
filter=data,
top_k=top_k,
)
@router.post("/documents", response_model=schemas.Document)
async def create_document(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
document: schemas.DocumentCreate,
db=db,
):
try:
return await crud.create_document(
db,
document=document,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
)
except ValueError:
raise HTTPException(
status_code=404, detail="collection not found or does not belong to user"
) from None
@router.put(
"/documents/{document_id}",
response_model=schemas.Document,
)
async def update_document(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
document_id: uuid.UUID,
document: schemas.DocumentUpdate,
db=db,
):
if document.content is None and document.metadata is None:
raise HTTPException(
status_code=400, detail="content and metadata cannot both be None"
)
return await crud.update_document(
db,
document=document,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
document_id=document_id,
)
@router.delete("/documents/{document_id}")
async def delete_document(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
collection_id: uuid.UUID,
document_id: uuid.UUID,
db=db,
):
response = await crud.delete_document(
db,
app_id=app_id,
user_id=user_id,
collection_id=collection_id,
document_id=document_id,
)
if response:
return {"message": "Document deleted successfully"}
else:
raise HTTPException(
status_code=404, detail="document not found or does not belong to user"
)

138
api/src/routers/messages.py Normal file
View File

@ -0,0 +1,138 @@
import json
from typing import Optional
import uuid
from fastapi import APIRouter, HTTPException, Request
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
from src import crud, schemas
from src.dependencies import db
router = APIRouter(
prefix="/apps/{app_id}/users/{user_id}/sessions/{session_id}/messages",
tags=["messages"],
)
@router.post("", response_model=schemas.Message)
async def create_message_for_session(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
message: schemas.MessageCreate,
db=db,
):
"""Adds a message to a session
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
session_id (int): The ID of the Session to add the message to
message (schemas.MessageCreate): The Message object to add containing the
message content and type
Returns:
schemas.Message: The Message object of the added message
Raises:
HTTPException: If the session is not found
"""
try:
return await crud.create_message(
db, message=message, app_id=app_id, user_id=user_id, session_id=session_id
)
except ValueError:
raise HTTPException(status_code=404, detail="Session not found") from None
@router.get("", response_model=Page[schemas.Message])
async def get_messages(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
reverse: Optional[bool] = False,
filter: Optional[str] = None,
db=db,
):
"""Get all messages for a session
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
session_id (int): The ID of the Session to retrieve
reverse (bool): Whether to reverse the order of the messages
Returns:
list[schemas.Message]: List of Message objects
Raises:
HTTPException: If the session is not found
"""
try:
data = None
if filter is not None:
data = json.loads(filter)
return await paginate(
db,
await crud.get_messages(
db,
app_id=app_id,
user_id=user_id,
session_id=session_id,
filter=data,
reverse=reverse,
),
)
except ValueError:
raise HTTPException(status_code=404, detail="Session not found") from None
@router.get("/{message_id}", response_model=schemas.Message)
async def get_message(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
message_id: uuid.UUID,
db=db,
):
""" """
honcho_message = await crud.get_message(
db, app_id=app_id, session_id=session_id, user_id=user_id, message_id=message_id
)
if honcho_message is None:
raise HTTPException(status_code=404, detail="Session not found")
return honcho_message
@router.put("/{message_id}", response_model=schemas.Message)
async def update_message(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
message_id: uuid.UUID,
message: schemas.MessageUpdate,
db=db,
):
"""Update's the metadata of a message"""
if message.metadata is None:
raise HTTPException(status_code=400, detail="Message metadata cannot be empty")
try:
return await crud.update_message(
db,
message=message,
app_id=app_id,
user_id=user_id,
session_id=session_id,
message_id=message_id,
)
except ValueError:
raise HTTPException(status_code=404, detail="Session not found") from None

View File

@ -0,0 +1,173 @@
import json
from typing import Optional
import uuid
from fastapi import APIRouter, HTTPException, Request
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
from src import crud, schemas
from src.dependencies import db
router = APIRouter(
prefix="/apps/{app_id}/users/{user_id}/sessions/{session_id}/metamessages",
tags=["messages"],
)
@router.post("", response_model=schemas.Metamessage)
async def create_metamessage(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
metamessage: schemas.MetamessageCreate,
db=db,
):
"""Adds a message to a session
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
session_id (int): The ID of the Session to add the message to
message (schemas.MessageCreate): The Message object to add containing the
message content and type
Returns:
schemas.Message: The Message object of the added message
Raises:
HTTPException: If the session is not found
"""
try:
return await crud.create_metamessage(
db,
metamessage=metamessage,
app_id=app_id,
user_id=user_id,
session_id=session_id,
)
except ValueError:
raise HTTPException(status_code=404, detail="Session not found") from None
@router.get("", response_model=Page[schemas.Metamessage])
async def get_metamessages(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
message_id: Optional[uuid.UUID] = None,
metamessage_type: Optional[str] = None,
reverse: Optional[bool] = False,
filter: Optional[str] = None,
db=db,
):
"""Get all messages for a session
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
session_id (int): The ID of the Session to retrieve
reverse (bool): Whether to reverse the order of the metamessages
Returns:
list[schemas.Message]: List of Message objects
Raises:
HTTPException: If the session is not found
"""
try:
data = None
if filter is not None:
data = json.loads(filter)
return await paginate(
db,
await crud.get_metamessages(
db,
app_id=app_id,
user_id=user_id,
session_id=session_id,
message_id=message_id,
metamessage_type=metamessage_type,
filter=data,
reverse=reverse,
),
)
except ValueError:
raise HTTPException(status_code=404, detail="Session not found") from None
@router.get(
"/{metamessage_id}",
response_model=schemas.Metamessage,
)
async def get_metamessage(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
message_id: uuid.UUID,
metamessage_id: uuid.UUID,
db=db,
):
"""Get a specific Metamessage by ID
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
session_id (int): The ID of the Session to retrieve
Returns:
schemas.Session: The Session object of the requested Session
Raises:
HTTPException: If the session is not found
"""
honcho_metamessage = await crud.get_metamessage(
db,
app_id=app_id,
session_id=session_id,
user_id=user_id,
message_id=message_id,
metamessage_id=metamessage_id,
)
if honcho_metamessage is None:
raise HTTPException(status_code=404, detail="Session not found")
return honcho_metamessage
@router.put(
"/{metamessage_id}",
response_model=schemas.Metamessage,
)
async def update_metamessage(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
metamessage_id: uuid.UUID,
metamessage: schemas.MetamessageUpdate,
db=db,
):
"""Update's the metadata of a metamessage"""
if metamessage.metadata is None:
raise HTTPException(
status_code=400, detail="Metamessage metadata cannot be empty"
)
try:
return await crud.update_metamessage(
db,
metamessage=metamessage,
app_id=app_id,
user_id=user_id,
session_id=session_id,
metamessage_id=metamessage_id,
)
except ValueError:
raise HTTPException(status_code=404, detail="Session not found") from None

193
api/src/routers/sessions.py Normal file
View File

@ -0,0 +1,193 @@
import json
import uuid
from typing import Optional
from fastapi import APIRouter, HTTPException, Request
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
from src import agent, crud, schemas
from src.dependencies import db
router = APIRouter(
prefix="/apps/{app_id}/users/{user_id}/sessions",
tags=["sessions"],
)
@router.get("", response_model=Page[schemas.Session])
async def get_sessions(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
location_id: Optional[str] = None,
is_active: Optional[bool] = False,
reverse: Optional[bool] = False,
filter: Optional[str] = None,
db=db,
):
"""Get All Sessions for a User
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (uuid.UUID): The User ID representing the user, managed by the user
location_id (str, optional): Optional Location ID representing the location of a
session
Returns:
list[schemas.Session]: List of Session objects
"""
data = None
if filter is not None:
data = json.loads(filter)
return await paginate(
db,
await crud.get_sessions(
db,
app_id=app_id,
user_id=user_id,
location_id=location_id,
reverse=reverse,
is_active=is_active,
filter=data,
),
)
@router.post("", response_model=schemas.Session)
async def create_session(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session: schemas.SessionCreate,
db=db,
):
"""Create a Session for a User
Args:
app_id (uuid.UUID): The ID of the app representing the client
application using honcho
user_id (uuid.UUID): The User ID representing the user, managed by the user
session (schemas.SessionCreate): The Session object containing any
metadata and a location ID
Returns:
schemas.Session: The Session object of the new Session
"""
value = await crud.create_session(
db, app_id=app_id, user_id=user_id, session=session
)
return value
@router.put("/{session_id}", response_model=schemas.Session)
async def update_session(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
session: schemas.SessionUpdate,
db=db,
):
"""Update the metadata of a Session
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (uuid.UUID): The User ID representing the user, managed by the user
session_id (uuid.UUID): The ID of the Session to update
session (schemas.SessionUpdate): The Session object containing any new metadata
Returns:
schemas.Session: The Session object of the updated Session
"""
if session.metadata is None:
raise HTTPException(status_code=400, detail="Session metadata cannot be empty")
try:
return await crud.update_session(
db, app_id=app_id, user_id=user_id, session_id=session_id, session=session
)
except ValueError:
raise HTTPException(status_code=404, detail="Session not found") from None
@router.delete("/{session_id}")
async def delete_session(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
db=db,
):
"""Delete a session by marking it as inactive
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (uuid.UUID): The User ID representing the user, managed by the user
session_id (uuid.UUID): The ID of the Session to delete
Returns:
dict: A message indicating that the session was deleted
Raises:
HTTPException: If the session is not found
"""
response = await crud.delete_session(
db, app_id=app_id, user_id=user_id, session_id=session_id
)
if response:
return {"message": "Session deleted successfully"}
else:
raise HTTPException(status_code=404, detail="Session not found")
@router.get("/{session_id}", response_model=schemas.Session)
async def get_session(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
db=db,
):
"""Get a specific session for a user by ID
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (uuid.UUID): The User ID representing the user, managed by the user
session_id (uuid.UUID): The ID of the Session to retrieve
Returns:
schemas.Session: The Session object of the requested Session
Raises:
HTTPException: If the session is not found
"""
honcho_session = await crud.get_session(
db, app_id=app_id, session_id=session_id, user_id=user_id
)
if honcho_session is None:
raise HTTPException(status_code=404, detail="Session not found")
return honcho_session
@router.get("/{session_id}/chat", response_model=schemas.AgentChat)
async def get_chat(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
session_id: uuid.UUID,
query: str,
db=db,
):
return await agent.chat(
app_id=app_id, user_id=user_id, session_id=session_id, query=query, db=db
)

128
api/src/routers/users.py Normal file
View File

@ -0,0 +1,128 @@
import json
from typing import Optional
import uuid
from fastapi import APIRouter, Request
from fastapi_pagination import Page
from fastapi_pagination.ext.sqlalchemy import paginate
from src import crud, schemas
from src.dependencies import db
router = APIRouter(
prefix="/apps/{app_id}/users",
tags=["users"],
)
@router.post("", response_model=schemas.User)
async def create_user(
request: Request,
app_id: uuid.UUID,
user: schemas.UserCreate,
db=db,
):
"""Create a User
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user (schemas.UserCreate): The User object containing any metadata
Returns:
schemas.User: Created User object
"""
print("running create_user")
return await crud.create_user(db, app_id=app_id, user=user)
@router.get("", response_model=Page[schemas.User])
async def get_users(
request: Request,
app_id: uuid.UUID,
reverse: bool = False,
filter: Optional[str] = None,
db=db,
):
"""Get All Users for an App
Args:
app_id (uuid.UUID): The ID of the app representing the client
application using honcho
Returns:
list[schemas.User]: List of User objects
"""
data = None
if filter is not None:
data = json.loads(filter)
return await paginate(
db, await crud.get_users(db, app_id=app_id, reverse=reverse, filter=data)
)
@router.get("/{name}", response_model=schemas.User)
async def get_user_by_name(
request: Request,
app_id: uuid.UUID,
name: str,
db=db,
):
"""Get a User
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
Returns:
schemas.User: User object
"""
return await crud.get_user_by_name(db, app_id=app_id, name=name)
@router.get("/get_or_create/{name}", response_model=schemas.User)
async def get_or_create_user(request: Request, app_id: uuid.UUID, name: str, db=db):
"""Get or Create a User
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
Returns:
schemas.User: User object
"""
user = await crud.get_user_by_name(db, app_id=app_id, name=name)
if user is None:
user = await crud.create_user(
db, app_id=app_id, user=schemas.UserCreate(name=name)
)
return user
@router.put("/{user_id}", response_model=schemas.User)
async def update_user(
request: Request,
app_id: uuid.UUID,
user_id: uuid.UUID,
user: schemas.UserUpdate,
db=db,
):
"""Update a User
Args:
app_id (uuid.UUID): The ID of the app representing the client application using
honcho
user_id (str): The User ID representing the user, managed by the user
user (schemas.UserCreate): The User object containing any metadata
Returns:
schemas.User: Updated User object
"""
return await crud.update_user(db, app_id=app_id, user_id=user_id, user=user)

View File

@ -1,7 +1,7 @@
import datetime
import uuid
from pydantic import BaseModel, validator
from pydantic import BaseModel, Field, validator
class AppBase(BaseModel):
@ -21,7 +21,7 @@ class AppUpdate(AppBase):
class App(AppBase):
id: uuid.UUID
name: str
h_metadata: dict
h_metadata: dict = Field(exclude=True)
metadata: dict
created_at: datetime.datetime
@ -33,7 +33,7 @@ class App(AppBase):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}
json_schema_extra = {"exclude": ["h_metadata"]}
class UserBase(BaseModel):
@ -54,7 +54,7 @@ class User(UserBase):
id: uuid.UUID
app_id: uuid.UUID
created_at: datetime.datetime
h_metadata: dict
h_metadata: dict = Field(exclude=True)
metadata: dict
@validator("metadata", pre=True, allow_reuse=True)
@ -65,7 +65,7 @@ class User(UserBase):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}
json_schema_extra = {"exclude": ["h_metadata"]}
class MessageBase(BaseModel):
@ -87,7 +87,7 @@ class Message(MessageBase):
is_user: bool
session_id: uuid.UUID
id: uuid.UUID
h_metadata: dict
h_metadata: dict = Field(exclude=True)
metadata: dict
created_at: datetime.datetime
@ -99,7 +99,7 @@ class Message(MessageBase):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}
json_schema_extra = {"exclude": ["h_metadata"]}
class SessionBase(BaseModel):
@ -121,7 +121,7 @@ class Session(SessionBase):
is_active: bool
user_id: uuid.UUID
location_id: str
h_metadata: dict
h_metadata: dict = Field(exclude=True)
metadata: dict
created_at: datetime.datetime
@ -133,7 +133,7 @@ class Session(SessionBase):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}
json_schema_extra = {"exclude": ["h_metadata"]}
class MetamessageBase(BaseModel):
@ -158,7 +158,7 @@ class Metamessage(MetamessageBase):
content: str
id: uuid.UUID
message_id: uuid.UUID
h_metadata: dict
h_metadata: dict = Field(exclude=True)
metadata: dict
created_at: datetime.datetime
@ -170,7 +170,7 @@ class Metamessage(MetamessageBase):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}
json_schema_extra = {"exclude": ["h_metadata"]}
class CollectionBase(BaseModel):
@ -191,7 +191,7 @@ class Collection(CollectionBase):
id: uuid.UUID
name: str
user_id: uuid.UUID
h_metadata: dict
h_metadata: dict = Field(exclude=True)
metadata: dict
created_at: datetime.datetime
@ -203,7 +203,7 @@ class Collection(CollectionBase):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}
json_schema_extra = {"exclude": ["h_metadata"]}
class DocumentBase(BaseModel):
@ -222,7 +222,7 @@ class DocumentUpdate(DocumentBase):
class Document(DocumentBase):
id: uuid.UUID
content: str
h_metadata: dict
h_metadata: dict = Field(exclude=True)
metadata: dict
created_at: datetime.datetime
collection_id: uuid.UUID
@ -235,7 +235,7 @@ class Document(DocumentBase):
class Config:
from_attributes = True
schema_extra = {"exclude": ["h_metadata"]}
json_schema_extra = {"exclude": ["h_metadata"]}
class AgentChat(BaseModel):

View File

@ -7,7 +7,7 @@ from langchain.schema import AIMessage, HumanMessage, SystemMessage
from langchain_community.chat_models.fake import FakeListChatModel
from honcho import Honcho
from honcho.ext.langchain import langchain_message_converter
from honcho.ext.langchain import _messages_to_langchain
app_name = str(uuid4())
@ -28,16 +28,6 @@ user = honcho.create_user(user_name)
session = user.create_session()
# def langchain_message_converter(messages: List):
# new_messages = []
# for message in messages:
# if message.is_user:
# new_messages.append(HumanMessage(content=message.content))
# else:
# new_messages.append(AIMessage(content=message.content))
# return new_messages
def chat():
while True:
user_input = input("User: ")
@ -46,7 +36,7 @@ def chat():
break
user_message = HumanMessage(content=user_input)
history = list(session.get_messages_generator())
langchain_history = langchain_message_converter(history)
langchain_history = _messages_to_langchain(history)
prompt = ChatPromptTemplate.from_messages(
[system, *langchain_history, user_message]
)

View File

@ -2,7 +2,7 @@ import os
from uuid import uuid1
import discord
from honcho import Honcho
from honcho.ext.langchain import langchain_message_converter
from honcho.ext.langchain import _messages_to_langchain
from graph import chat
from dspy import Example
@ -61,7 +61,7 @@ async def on_message(message):
session = user.create_session(location_id)
history = list(session.get_messages_generator())[:5]
chat_history = langchain_message_converter(history)
chat_history = _messages_to_langchain(history)
inp = message.content
user_message = session.create_message(is_user=True, content=inp)

View File

@ -2,7 +2,7 @@ import os
from uuid import uuid1
import discord
from honcho import Honcho
from honcho.ext.langchain import langchain_message_converter
from honcho.ext.langchain import _messages_to_langchain
from chain import LMChain
@ -44,7 +44,7 @@ async def on_message(message):
return
user_id = f"discord_{str(message.author.id)}"
user = honcho.get_or_create(user_id)
user = honcho.get_or_create_user(user_id)
location_id = str(message.channel.id)
sessions = list(user.get_sessions_generator(location_id))
@ -59,7 +59,7 @@ async def on_message(message):
session = user.create_session(location_id)
history = list(session.get_messages_generator())
chat_history = langchain_message_converter(history)
chat_history = _messages_to_langchain(history)
inp = message.content
user_message = session.create_message(is_user=True, content=inp)

View File

@ -1,117 +1,106 @@
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand.
[[package]]
name = "aiohttp"
version = "3.8.6"
version = "3.9.3"
description = "Async http client/server framework (asyncio)"
category = "main"
optional = false
python-versions = ">=3.6"
python-versions = ">=3.8"
files = [
{file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:41d55fc043954cddbbd82503d9cc3f4814a40bcef30b3569bc7b5e34130718c1"},
{file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d84166673694841d8953f0a8d0c90e1087739d24632fe86b1a08819168b4566"},
{file = "aiohttp-3.8.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:253bf92b744b3170eb4c4ca2fa58f9c4b87aeb1df42f71d4e78815e6e8b73c9e"},
{file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fd194939b1f764d6bb05490987bfe104287bbf51b8d862261ccf66f48fb4096"},
{file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c5f938d199a6fdbdc10bbb9447496561c3a9a565b43be564648d81e1102ac22"},
{file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2817b2f66ca82ee699acd90e05c95e79bbf1dc986abb62b61ec8aaf851e81c93"},
{file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fa375b3d34e71ccccf172cab401cd94a72de7a8cc01847a7b3386204093bb47"},
{file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9de50a199b7710fa2904be5a4a9b51af587ab24c8e540a7243ab737b45844543"},
{file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e1d8cb0b56b3587c5c01de3bf2f600f186da7e7b5f7353d1bf26a8ddca57f965"},
{file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8e31e9db1bee8b4f407b77fd2507337a0a80665ad7b6c749d08df595d88f1cf5"},
{file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7bc88fc494b1f0311d67f29fee6fd636606f4697e8cc793a2d912ac5b19aa38d"},
{file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ec00c3305788e04bf6d29d42e504560e159ccaf0be30c09203b468a6c1ccd3b2"},
{file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad1407db8f2f49329729564f71685557157bfa42b48f4b93e53721a16eb813ed"},
{file = "aiohttp-3.8.6-cp310-cp310-win32.whl", hash = "sha256:ccc360e87341ad47c777f5723f68adbb52b37ab450c8bc3ca9ca1f3e849e5fe2"},
{file = "aiohttp-3.8.6-cp310-cp310-win_amd64.whl", hash = "sha256:93c15c8e48e5e7b89d5cb4613479d144fda8344e2d886cf694fd36db4cc86865"},
{file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e2f9cc8e5328f829f6e1fb74a0a3a939b14e67e80832975e01929e320386b34"},
{file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e6a00ffcc173e765e200ceefb06399ba09c06db97f401f920513a10c803604ca"},
{file = "aiohttp-3.8.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:41bdc2ba359032e36c0e9de5a3bd00d6fb7ea558a6ce6b70acedf0da86458321"},
{file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14cd52ccf40006c7a6cd34a0f8663734e5363fd981807173faf3a017e202fec9"},
{file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d5b785c792802e7b275c420d84f3397668e9d49ab1cb52bd916b3b3ffcf09ad"},
{file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1bed815f3dc3d915c5c1e556c397c8667826fbc1b935d95b0ad680787896a358"},
{file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96603a562b546632441926cd1293cfcb5b69f0b4159e6077f7c7dbdfb686af4d"},
{file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d76e8b13161a202d14c9584590c4df4d068c9567c99506497bdd67eaedf36403"},
{file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e3f1e3f1a1751bb62b4a1b7f4e435afcdade6c17a4fd9b9d43607cebd242924a"},
{file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:76b36b3124f0223903609944a3c8bf28a599b2cc0ce0be60b45211c8e9be97f8"},
{file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:a2ece4af1f3c967a4390c284797ab595a9f1bc1130ef8b01828915a05a6ae684"},
{file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:16d330b3b9db87c3883e565340d292638a878236418b23cc8b9b11a054aaa887"},
{file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:42c89579f82e49db436b69c938ab3e1559e5a4409eb8639eb4143989bc390f2f"},
{file = "aiohttp-3.8.6-cp311-cp311-win32.whl", hash = "sha256:efd2fcf7e7b9d7ab16e6b7d54205beded0a9c8566cb30f09c1abe42b4e22bdcb"},
{file = "aiohttp-3.8.6-cp311-cp311-win_amd64.whl", hash = "sha256:3b2ab182fc28e7a81f6c70bfbd829045d9480063f5ab06f6e601a3eddbbd49a0"},
{file = "aiohttp-3.8.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fdee8405931b0615220e5ddf8cd7edd8592c606a8e4ca2a00704883c396e4479"},
{file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d25036d161c4fe2225d1abff2bd52c34ed0b1099f02c208cd34d8c05729882f0"},
{file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d791245a894be071d5ab04bbb4850534261a7d4fd363b094a7b9963e8cdbd31"},
{file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0cccd1de239afa866e4ce5c789b3032442f19c261c7d8a01183fd956b1935349"},
{file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f13f60d78224f0dace220d8ab4ef1dbc37115eeeab8c06804fec11bec2bbd07"},
{file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a9b5a0606faca4f6cc0d338359d6fa137104c337f489cd135bb7fbdbccb1e39"},
{file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:13da35c9ceb847732bf5c6c5781dcf4780e14392e5d3b3c689f6d22f8e15ae31"},
{file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:4d4cbe4ffa9d05f46a28252efc5941e0462792930caa370a6efaf491f412bc66"},
{file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:229852e147f44da0241954fc6cb910ba074e597f06789c867cb7fb0621e0ba7a"},
{file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:713103a8bdde61d13490adf47171a1039fd880113981e55401a0f7b42c37d071"},
{file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:45ad816b2c8e3b60b510f30dbd37fe74fd4a772248a52bb021f6fd65dff809b6"},
{file = "aiohttp-3.8.6-cp36-cp36m-win32.whl", hash = "sha256:2b8d4e166e600dcfbff51919c7a3789ff6ca8b3ecce16e1d9c96d95dd569eb4c"},
{file = "aiohttp-3.8.6-cp36-cp36m-win_amd64.whl", hash = "sha256:0912ed87fee967940aacc5306d3aa8ba3a459fcd12add0b407081fbefc931e53"},
{file = "aiohttp-3.8.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e2a988a0c673c2e12084f5e6ba3392d76c75ddb8ebc6c7e9ead68248101cd446"},
{file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebf3fd9f141700b510d4b190094db0ce37ac6361a6806c153c161dc6c041ccda"},
{file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3161ce82ab85acd267c8f4b14aa226047a6bee1e4e6adb74b798bd42c6ae1f80"},
{file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95fc1bf33a9a81469aa760617b5971331cdd74370d1214f0b3109272c0e1e3c"},
{file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c43ecfef7deaf0617cee936836518e7424ee12cb709883f2c9a1adda63cc460"},
{file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca80e1b90a05a4f476547f904992ae81eda5c2c85c66ee4195bb8f9c5fb47f28"},
{file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:90c72ebb7cb3a08a7f40061079817133f502a160561d0675b0a6adf231382c92"},
{file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bb54c54510e47a8c7c8e63454a6acc817519337b2b78606c4e840871a3e15349"},
{file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:de6a1c9f6803b90e20869e6b99c2c18cef5cc691363954c93cb9adeb26d9f3ae"},
{file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:a3628b6c7b880b181a3ae0a0683698513874df63783fd89de99b7b7539e3e8a8"},
{file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fc37e9aef10a696a5a4474802930079ccfc14d9f9c10b4662169671ff034b7df"},
{file = "aiohttp-3.8.6-cp37-cp37m-win32.whl", hash = "sha256:f8ef51e459eb2ad8e7a66c1d6440c808485840ad55ecc3cafefadea47d1b1ba2"},
{file = "aiohttp-3.8.6-cp37-cp37m-win_amd64.whl", hash = "sha256:b2fe42e523be344124c6c8ef32a011444e869dc5f883c591ed87f84339de5976"},
{file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9e2ee0ac5a1f5c7dd3197de309adfb99ac4617ff02b0603fd1e65b07dc772e4b"},
{file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01770d8c04bd8db568abb636c1fdd4f7140b284b8b3e0b4584f070180c1e5c62"},
{file = "aiohttp-3.8.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3c68330a59506254b556b99a91857428cab98b2f84061260a67865f7f52899f5"},
{file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89341b2c19fb5eac30c341133ae2cc3544d40d9b1892749cdd25892bbc6ac951"},
{file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71783b0b6455ac8f34b5ec99d83e686892c50498d5d00b8e56d47f41b38fbe04"},
{file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f628dbf3c91e12f4d6c8b3f092069567d8eb17814aebba3d7d60c149391aee3a"},
{file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04691bc6601ef47c88f0255043df6f570ada1a9ebef99c34bd0b72866c217ae"},
{file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee912f7e78287516df155f69da575a0ba33b02dd7c1d6614dbc9463f43066e3"},
{file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9c19b26acdd08dd239e0d3669a3dddafd600902e37881f13fbd8a53943079dbc"},
{file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:99c5ac4ad492b4a19fc132306cd57075c28446ec2ed970973bbf036bcda1bcc6"},
{file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f0f03211fd14a6a0aed2997d4b1c013d49fb7b50eeb9ffdf5e51f23cfe2c77fa"},
{file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:8d399dade330c53b4106160f75f55407e9ae7505263ea86f2ccca6bfcbdb4921"},
{file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ec4fd86658c6a8964d75426517dc01cbf840bbf32d055ce64a9e63a40fd7b771"},
{file = "aiohttp-3.8.6-cp38-cp38-win32.whl", hash = "sha256:33164093be11fcef3ce2571a0dccd9041c9a93fa3bde86569d7b03120d276c6f"},
{file = "aiohttp-3.8.6-cp38-cp38-win_amd64.whl", hash = "sha256:bdf70bfe5a1414ba9afb9d49f0c912dc524cf60141102f3a11143ba3d291870f"},
{file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d52d5dc7c6682b720280f9d9db41d36ebe4791622c842e258c9206232251ab2b"},
{file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ac39027011414dbd3d87f7edb31680e1f430834c8cef029f11c66dad0670aa5"},
{file = "aiohttp-3.8.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3f5c7ce535a1d2429a634310e308fb7d718905487257060e5d4598e29dc17f0b"},
{file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b30e963f9e0d52c28f284d554a9469af073030030cef8693106d918b2ca92f54"},
{file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:918810ef188f84152af6b938254911055a72e0f935b5fbc4c1a4ed0b0584aed1"},
{file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:002f23e6ea8d3dd8d149e569fd580c999232b5fbc601c48d55398fbc2e582e8c"},
{file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fcf3eabd3fd1a5e6092d1242295fa37d0354b2eb2077e6eb670accad78e40e1"},
{file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:255ba9d6d5ff1a382bb9a578cd563605aa69bec845680e21c44afc2670607a95"},
{file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d67f8baed00870aa390ea2590798766256f31dc5ed3ecc737debb6e97e2ede78"},
{file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:86f20cee0f0a317c76573b627b954c412ea766d6ada1a9fcf1b805763ae7feeb"},
{file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:39a312d0e991690ccc1a61f1e9e42daa519dcc34ad03eb6f826d94c1190190dd"},
{file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e827d48cf802de06d9c935088c2924e3c7e7533377d66b6f31ed175c1620e05e"},
{file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bd111d7fc5591ddf377a408ed9067045259ff2770f37e2d94e6478d0f3fc0c17"},
{file = "aiohttp-3.8.6-cp39-cp39-win32.whl", hash = "sha256:caf486ac1e689dda3502567eb89ffe02876546599bbf915ec94b1fa424eeffd4"},
{file = "aiohttp-3.8.6-cp39-cp39-win_amd64.whl", hash = "sha256:3f0e27e5b733803333bb2371249f41cf42bae8884863e8e8965ec69bebe53132"},
{file = "aiohttp-3.8.6.tar.gz", hash = "sha256:b0cf2a4501bff9330a8a5248b4ce951851e415bdcce9dc158e76cfd55e15085c"},
{file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"},
{file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"},
{file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"},
{file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"},
{file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"},
{file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"},
{file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"},
{file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"},
{file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"},
{file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"},
{file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"},
{file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"},
{file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"},
{file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"},
{file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"},
{file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"},
{file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"},
{file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"},
{file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"},
{file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"},
{file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"},
{file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"},
{file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"},
{file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"},
{file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"},
{file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"},
{file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"},
{file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"},
{file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"},
{file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"},
{file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"},
{file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"},
{file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"},
{file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"},
{file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"},
{file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"},
]
[package.dependencies]
aiosignal = ">=1.1.2"
async-timeout = ">=4.0.0a3,<5.0"
attrs = ">=17.3.0"
charset-normalizer = ">=2.0,<4.0"
frozenlist = ">=1.1.1"
multidict = ">=4.5,<7.0"
yarl = ">=1.0,<2.0"
[package.extras]
speedups = ["Brotli", "aiodns", "cchardet"]
speedups = ["Brotli", "aiodns", "brotlicffi"]
[[package]]
name = "aiosignal"
version = "1.3.1"
description = "aiosignal: a list of registered asynchronous callbacks"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -126,6 +115,7 @@ frozenlist = ">=1.1.0"
name = "annotated-types"
version = "0.6.0"
description = "Reusable constraint types to use with typing.Annotated"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
@ -135,13 +125,14 @@ files = [
[[package]]
name = "anyio"
version = "4.2.0"
version = "4.3.0"
description = "High level compatibility layer for multiple asynchronous event loop implementations"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "anyio-4.2.0-py3-none-any.whl", hash = "sha256:745843b39e829e108e518c489b31dc757de7d2131d53fac32bd8df268227bfee"},
{file = "anyio-4.2.0.tar.gz", hash = "sha256:e1875bb4b4e2de1669f4bc7869b6d3f54231cdced71605e6e64c9be77e3be50f"},
{file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"},
{file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"},
]
[package.dependencies]
@ -153,21 +144,11 @@ doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphin
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
trio = ["trio (>=0.23)"]
[[package]]
name = "async-timeout"
version = "4.0.3"
description = "Timeout context manager for asyncio programs"
optional = false
python-versions = ">=3.7"
files = [
{file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"},
{file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"},
]
[[package]]
name = "attrs"
version = "23.2.0"
description = "Classes Without Boilerplate"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -187,6 +168,7 @@ tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "p
name = "certifi"
version = "2024.2.2"
description = "Python package for providing Mozilla's CA Bundle."
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@ -198,6 +180,7 @@ files = [
name = "charset-normalizer"
version = "3.3.2"
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
category = "main"
optional = false
python-versions = ">=3.7.0"
files = [
@ -297,6 +280,7 @@ files = [
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
@ -308,6 +292,7 @@ files = [
name = "dataclasses-json"
version = "0.6.4"
description = "Easily serialize dataclasses to and from JSON."
category = "main"
optional = false
python-versions = ">=3.7,<4.0"
files = [
@ -323,6 +308,7 @@ typing-inspect = ">=0.4.0,<1"
name = "distro"
version = "1.9.0"
description = "Distro - an OS platform information API"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@ -334,6 +320,7 @@ files = [
name = "frozenlist"
version = "1.4.1"
description = "A list-like structure which implements collections.abc.MutableSequence"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
@ -420,6 +407,7 @@ files = [
name = "greenlet"
version = "3.0.3"
description = "Lightweight in-process concurrent programming"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -491,6 +479,7 @@ test = ["objgraph", "psutil"]
name = "h11"
version = "0.14.0"
description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -500,13 +489,14 @@ files = [
[[package]]
name = "honcho-ai"
version = "0.0.3"
version = "0.0.5"
description = "Python Client SDK for Honcho"
category = "main"
optional = false
python-versions = ">=3.10,<4.0"
python-versions = ">=3.9,<4.0"
files = [
{file = "honcho_ai-0.0.3-py3-none-any.whl", hash = "sha256:a817ec62c4fd8dad1d629927511ce98a3f626f4bc55474187b80010e208e61ba"},
{file = "honcho_ai-0.0.3.tar.gz", hash = "sha256:ca52bb8c5036bfdbeee0c71ca754c580c672b28a4824240123b783f8679ca18e"},
{file = "honcho_ai-0.0.5-py3-none-any.whl", hash = "sha256:3278aac9dd80cde10fa3216cc38e84eae90acc0b5c0fac986abb40973a8fe156"},
{file = "honcho_ai-0.0.5.tar.gz", hash = "sha256:7283ae2ee3baa5f0429c9ea2eb9f1e74b3fb164d5a7448ee7872ba9847500ae6"},
]
[package.dependencies]
@ -514,13 +504,14 @@ httpx = ">=0.26.0,<0.27.0"
[[package]]
name = "httpcore"
version = "1.0.3"
version = "1.0.4"
description = "A minimal low-level HTTP client."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "httpcore-1.0.3-py3-none-any.whl", hash = "sha256:9a6a501c3099307d9fd76ac244e08503427679b1e81ceb1d922485e2f2462ad2"},
{file = "httpcore-1.0.3.tar.gz", hash = "sha256:5c0f9546ad17dac4d0772b0808856eb616eb8b48ce94f49ed819fd6982a8a544"},
{file = "httpcore-1.0.4-py3-none-any.whl", hash = "sha256:ac418c1db41bade2ad53ae2f3834a3a0f5ae76b56cf5aa497d2d033384fc7d73"},
{file = "httpcore-1.0.4.tar.gz", hash = "sha256:cb2839ccfcba0d2d3c1131d3c3e26dfc327326fbe7a5dc0dbfe9f6c9151bb022"},
]
[package.dependencies]
@ -530,13 +521,14 @@ 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,<0.24.0)"]
socks = ["socksio (>=1.0.0,<2.0.0)"]
trio = ["trio (>=0.22.0,<0.25.0)"]
[[package]]
name = "httpx"
version = "0.26.0"
description = "The next generation HTTP client."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
@ -547,20 +539,21 @@ files = [
[package.dependencies]
anyio = "*"
certifi = "*"
httpcore = "==1.*"
httpcore = ">=1.0.0,<2.0.0"
idna = "*"
sniffio = "*"
[package.extras]
brotli = ["brotli", "brotlicffi"]
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
socks = ["socksio (>=1.0.0,<2.0.0)"]
[[package]]
name = "idna"
version = "3.6"
description = "Internationalized Domain Names in Applications (IDNA)"
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@ -572,6 +565,7 @@ files = [
name = "jsonpatch"
version = "1.33"
description = "Apply JSON-Patches (RFC 6902)"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
files = [
@ -586,6 +580,7 @@ jsonpointer = ">=1.9"
name = "jsonpointer"
version = "2.4"
description = "Identify specific nodes in a JSON document (RFC 6901)"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*"
files = [
@ -597,6 +592,7 @@ files = [
name = "langchain-community"
version = "0.0.20"
description = "Community contributed LangChain integrations."
category = "main"
optional = false
python-versions = ">=3.8.1,<4.0"
files = [
@ -623,6 +619,7 @@ extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.
name = "langchain-core"
version = "0.1.23"
description = "Building applications with LLMs through composability"
category = "main"
optional = false
python-versions = ">=3.8.1,<4.0"
files = [
@ -647,6 +644,7 @@ extended-testing = ["jinja2 (>=3,<4)"]
name = "langchain-openai"
version = "0.0.6"
description = "An integration package connecting OpenAI and LangChain"
category = "main"
optional = false
python-versions = ">=3.8.1,<4.0"
files = [
@ -664,6 +662,7 @@ tiktoken = ">=0.5.2,<1"
name = "langsmith"
version = "0.0.87"
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
category = "main"
optional = false
python-versions = ">=3.8.1,<4.0"
files = [
@ -677,28 +676,29 @@ requests = ">=2,<3"
[[package]]
name = "marshmallow"
version = "3.20.2"
version = "3.21.1"
description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "marshmallow-3.20.2-py3-none-any.whl", hash = "sha256:c21d4b98fee747c130e6bc8f45c4b3199ea66bc00c12ee1f639f0aeca034d5e9"},
{file = "marshmallow-3.20.2.tar.gz", hash = "sha256:4c1daff273513dc5eb24b219a8035559dc573c8f322558ef85f5438ddd1236dd"},
{file = "marshmallow-3.21.1-py3-none-any.whl", hash = "sha256:f085493f79efb0644f270a9bf2892843142d80d7174bbbd2f3713f2a589dc633"},
{file = "marshmallow-3.21.1.tar.gz", hash = "sha256:4e65e9e0d80fc9e609574b9983cf32579f305c718afb30d7233ab818571768c3"},
]
[package.dependencies]
packaging = ">=17.0"
[package.extras]
dev = ["pre-commit (>=2.4,<4.0)", "pytest", "pytz", "simplejson", "tox"]
docs = ["alabaster (==0.7.15)", "autodocsumm (==0.2.12)", "sphinx (==7.2.6)", "sphinx-issues (==3.0.1)", "sphinx-version-warning (==1.1.2)"]
lint = ["pre-commit (>=2.4,<4.0)"]
dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"]
docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.2.6)", "sphinx-issues (==4.0.0)", "sphinx-version-warning (==1.1.2)"]
tests = ["pytest", "pytz", "simplejson"]
[[package]]
name = "multidict"
version = "6.0.5"
description = "multidict implementation"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -798,6 +798,7 @@ files = [
name = "mypy-extensions"
version = "1.0.0"
description = "Type system extensions for programs checked with the mypy type checker."
category = "main"
optional = false
python-versions = ">=3.5"
files = [
@ -809,6 +810,7 @@ files = [
name = "numpy"
version = "1.26.4"
description = "Fundamental package for array computing in Python"
category = "main"
optional = false
python-versions = ">=3.9"
files = [
@ -852,13 +854,14 @@ files = [
[[package]]
name = "openai"
version = "1.12.0"
version = "1.14.1"
description = "The official Python library for the openai API"
category = "main"
optional = false
python-versions = ">=3.7.1"
files = [
{file = "openai-1.12.0-py3-none-any.whl", hash = "sha256:a54002c814e05222e413664f651b5916714e4700d041d5cf5724d3ae1a3e3481"},
{file = "openai-1.12.0.tar.gz", hash = "sha256:99c5d257d09ea6533d689d1cc77caa0ac679fa21efef8893d8b0832a86877f1b"},
{file = "openai-1.14.1-py3-none-any.whl", hash = "sha256:f9322b0bf3b82bbd06930fad535369a023f35a3a96d3ef0b827644a15d7aae97"},
{file = "openai-1.14.1.tar.gz", hash = "sha256:1fab5dd623cdc0c7c6e7da5d8d11fa6900f94191c2dfb6510d7eac33195fa175"},
]
[package.dependencies]
@ -877,6 +880,7 @@ datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
name = "packaging"
version = "23.2"
description = "Core utilities for Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -886,37 +890,39 @@ files = [
[[package]]
name = "py-cord"
version = "2.4.1"
version = "2.5.0"
description = "A Python wrapper for the Discord API"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "py-cord-2.4.1.tar.gz", hash = "sha256:0266c9d9a9d2397622a0e5ead09826690e688ba3cf14c470167b81e6cd2d8a56"},
{file = "py_cord-2.4.1-py3-none-any.whl", hash = "sha256:862a372c364cd263e2c8e696c64887f969c02cbdf0fdd6b09f0283e9dd67a290"},
{file = "py-cord-2.5.0.tar.gz", hash = "sha256:faf08af5da5eac2ed3d1c8a43d8307d5a1e3f01602def283330c9d2cde0b1162"},
{file = "py_cord-2.5.0-py3-none-any.whl", hash = "sha256:9e5fc79feec5a48f53aa4c066b57dd75fe67d29021b042d12f378a513d308bbc"},
]
[package.dependencies]
aiohttp = ">=3.6.0,<3.9.0"
aiohttp = ">=3.6.0,<4.0"
[package.extras]
docs = ["furo", "myst-parser (==0.18.1)", "sphinx (==5.3.0)", "sphinx-autodoc-typehints (==1.22)", "sphinx-copybutton (==0.5.1)", "sphinxcontrib-trio (==1.1.2)", "sphinxcontrib-websupport (==1.2.4)", "sphinxext-opengraph (==0.8.1)"]
speed = ["aiohttp[speedups]", "orjson (>=3.5.4)"]
docs = ["furo (==2023.3.23)", "myst-parser (==1.0.0)", "sphinx (==5.3.0)", "sphinx-autodoc-typehints (==1.23.0)", "sphinx-copybutton (==0.5.2)", "sphinxcontrib-trio (==1.1.2)", "sphinxcontrib-websupport (==1.2.4)", "sphinxext-opengraph (==0.9.1)"]
speed = ["aiohttp[speedups]", "msgspec (>=0.18.6,<0.19.0)"]
voice = ["PyNaCl (>=1.3.0,<1.6)"]
[[package]]
name = "pydantic"
version = "2.6.1"
version = "2.6.4"
description = "Data validation using Python type hints"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "pydantic-2.6.1-py3-none-any.whl", hash = "sha256:0b6a909df3192245cb736509a92ff69e4fef76116feffec68e93a567347bae6f"},
{file = "pydantic-2.6.1.tar.gz", hash = "sha256:4fd5c182a2488dc63e6d32737ff19937888001e2a6d86e94b3f233104a5d1fa9"},
{file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"},
{file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"},
]
[package.dependencies]
annotated-types = ">=0.4.0"
pydantic-core = "2.16.2"
pydantic-core = "2.16.3"
typing-extensions = ">=4.6.1"
[package.extras]
@ -924,90 +930,91 @@ email = ["email-validator (>=2.0.0)"]
[[package]]
name = "pydantic-core"
version = "2.16.2"
version = "2.16.3"
description = ""
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "pydantic_core-2.16.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3fab4e75b8c525a4776e7630b9ee48aea50107fea6ca9f593c98da3f4d11bf7c"},
{file = "pydantic_core-2.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8bde5b48c65b8e807409e6f20baee5d2cd880e0fad00b1a811ebc43e39a00ab2"},
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2924b89b16420712e9bb8192396026a8fbd6d8726224f918353ac19c4c043d2a"},
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16aa02e7a0f539098e215fc193c8926c897175d64c7926d00a36188917717a05"},
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:936a787f83db1f2115ee829dd615c4f684ee48ac4de5779ab4300994d8af325b"},
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:459d6be6134ce3b38e0ef76f8a672924460c455d45f1ad8fdade36796df1ddc8"},
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9ee4febb249c591d07b2d4dd36ebcad0ccd128962aaa1801508320896575ef"},
{file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40a0bd0bed96dae5712dab2aba7d334a6c67cbcac2ddfca7dbcc4a8176445990"},
{file = "pydantic_core-2.16.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:870dbfa94de9b8866b37b867a2cb37a60c401d9deb4a9ea392abf11a1f98037b"},
{file = "pydantic_core-2.16.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:308974fdf98046db28440eb3377abba274808bf66262e042c412eb2adf852731"},
{file = "pydantic_core-2.16.2-cp310-none-win32.whl", hash = "sha256:a477932664d9611d7a0816cc3c0eb1f8856f8a42435488280dfbf4395e141485"},
{file = "pydantic_core-2.16.2-cp310-none-win_amd64.whl", hash = "sha256:8f9142a6ed83d90c94a3efd7af8873bf7cefed2d3d44387bf848888482e2d25f"},
{file = "pydantic_core-2.16.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:406fac1d09edc613020ce9cf3f2ccf1a1b2f57ab00552b4c18e3d5276c67eb11"},
{file = "pydantic_core-2.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce232a6170dd6532096cadbf6185271e4e8c70fc9217ebe105923ac105da9978"},
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90fec23b4b05a09ad988e7a4f4e081711a90eb2a55b9c984d8b74597599180f"},
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8aafeedb6597a163a9c9727d8a8bd363a93277701b7bfd2749fbefee2396469e"},
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9957433c3a1b67bdd4c63717eaf174ebb749510d5ea612cd4e83f2d9142f3fc8"},
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0d7a9165167269758145756db43a133608a531b1e5bb6a626b9ee24bc38a8f7"},
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dffaf740fe2e147fedcb6b561353a16243e654f7fe8e701b1b9db148242e1272"},
{file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8ed79883b4328b7f0bd142733d99c8e6b22703e908ec63d930b06be3a0e7113"},
{file = "pydantic_core-2.16.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cf903310a34e14651c9de056fcc12ce090560864d5a2bb0174b971685684e1d8"},
{file = "pydantic_core-2.16.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:46b0d5520dbcafea9a8645a8164658777686c5c524d381d983317d29687cce97"},
{file = "pydantic_core-2.16.2-cp311-none-win32.whl", hash = "sha256:70651ff6e663428cea902dac297066d5c6e5423fda345a4ca62430575364d62b"},
{file = "pydantic_core-2.16.2-cp311-none-win_amd64.whl", hash = "sha256:98dc6f4f2095fc7ad277782a7c2c88296badcad92316b5a6e530930b1d475ebc"},
{file = "pydantic_core-2.16.2-cp311-none-win_arm64.whl", hash = "sha256:ef6113cd31411eaf9b39fc5a8848e71c72656fd418882488598758b2c8c6dfa0"},
{file = "pydantic_core-2.16.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:88646cae28eb1dd5cd1e09605680c2b043b64d7481cdad7f5003ebef401a3039"},
{file = "pydantic_core-2.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7b883af50eaa6bb3299780651e5be921e88050ccf00e3e583b1e92020333304b"},
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bf26c2e2ea59d32807081ad51968133af3025c4ba5753e6a794683d2c91bf6e"},
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99af961d72ac731aae2a1b55ccbdae0733d816f8bfb97b41909e143de735f522"},
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02906e7306cb8c5901a1feb61f9ab5e5c690dbbeaa04d84c1b9ae2a01ebe9379"},
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5362d099c244a2d2f9659fb3c9db7c735f0004765bbe06b99be69fbd87c3f15"},
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ac426704840877a285d03a445e162eb258924f014e2f074e209d9b4ff7bf380"},
{file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b94cbda27267423411c928208e89adddf2ea5dd5f74b9528513f0358bba019cb"},
{file = "pydantic_core-2.16.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6db58c22ac6c81aeac33912fb1af0e930bc9774166cdd56eade913d5f2fff35e"},
{file = "pydantic_core-2.16.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396fdf88b1b503c9c59c84a08b6833ec0c3b5ad1a83230252a9e17b7dfb4cffc"},
{file = "pydantic_core-2.16.2-cp312-none-win32.whl", hash = "sha256:7c31669e0c8cc68400ef0c730c3a1e11317ba76b892deeefaf52dcb41d56ed5d"},
{file = "pydantic_core-2.16.2-cp312-none-win_amd64.whl", hash = "sha256:a3b7352b48fbc8b446b75f3069124e87f599d25afb8baa96a550256c031bb890"},
{file = "pydantic_core-2.16.2-cp312-none-win_arm64.whl", hash = "sha256:a9e523474998fb33f7c1a4d55f5504c908d57add624599e095c20fa575b8d943"},
{file = "pydantic_core-2.16.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ae34418b6b389d601b31153b84dce480351a352e0bb763684a1b993d6be30f17"},
{file = "pydantic_core-2.16.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:732bd062c9e5d9582a30e8751461c1917dd1ccbdd6cafb032f02c86b20d2e7ec"},
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b52776a2e3230f4854907a1e0946eec04d41b1fc64069ee774876bbe0eab55"},
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef551c053692b1e39e3f7950ce2296536728871110e7d75c4e7753fb30ca87f4"},
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ebb892ed8599b23fa8f1799e13a12c87a97a6c9d0f497525ce9858564c4575a4"},
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa6c8c582036275997a733427b88031a32ffa5dfc3124dc25a730658c47a572f"},
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ba0884a91f1aecce75202473ab138724aa4fb26d7707f2e1fa6c3e68c84fbf"},
{file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7924e54f7ce5d253d6160090ddc6df25ed2feea25bfb3339b424a9dd591688bc"},
{file = "pydantic_core-2.16.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69a7b96b59322a81c2203be537957313b07dd333105b73db0b69212c7d867b4b"},
{file = "pydantic_core-2.16.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7e6231aa5bdacda78e96ad7b07d0c312f34ba35d717115f4b4bff6cb87224f0f"},
{file = "pydantic_core-2.16.2-cp38-none-win32.whl", hash = "sha256:41dac3b9fce187a25c6253ec79a3f9e2a7e761eb08690e90415069ea4a68ff7a"},
{file = "pydantic_core-2.16.2-cp38-none-win_amd64.whl", hash = "sha256:f685dbc1fdadb1dcd5b5e51e0a378d4685a891b2ddaf8e2bba89bd3a7144e44a"},
{file = "pydantic_core-2.16.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:55749f745ebf154c0d63d46c8c58594d8894b161928aa41adbb0709c1fe78b77"},
{file = "pydantic_core-2.16.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b30b0dd58a4509c3bd7eefddf6338565c4905406aee0c6e4a5293841411a1286"},
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18de31781cdc7e7b28678df7c2d7882f9692ad060bc6ee3c94eb15a5d733f8f7"},
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5864b0242f74b9dd0b78fd39db1768bc3f00d1ffc14e596fd3e3f2ce43436a33"},
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8f9186ca45aee030dc8234118b9c0784ad91a0bb27fc4e7d9d6608a5e3d386c"},
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc6f6c9be0ab6da37bc77c2dda5f14b1d532d5dbef00311ee6e13357a418e646"},
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa057095f621dad24a1e906747179a69780ef45cc8f69e97463692adbcdae878"},
{file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ad84731a26bcfb299f9eab56c7932d46f9cad51c52768cace09e92a19e4cf55"},
{file = "pydantic_core-2.16.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3b052c753c4babf2d1edc034c97851f867c87d6f3ea63a12e2700f159f5c41c3"},
{file = "pydantic_core-2.16.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e0f686549e32ccdb02ae6f25eee40cc33900910085de6aa3790effd391ae10c2"},
{file = "pydantic_core-2.16.2-cp39-none-win32.whl", hash = "sha256:7afb844041e707ac9ad9acad2188a90bffce2c770e6dc2318be0c9916aef1469"},
{file = "pydantic_core-2.16.2-cp39-none-win_amd64.whl", hash = "sha256:9da90d393a8227d717c19f5397688a38635afec89f2e2d7af0df037f3249c39a"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f60f920691a620b03082692c378661947d09415743e437a7478c309eb0e4f82"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:47924039e785a04d4a4fa49455e51b4eb3422d6eaacfde9fc9abf8fdef164e8a"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6294e76b0380bb7a61eb8a39273c40b20beb35e8c87ee101062834ced19c545"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe56851c3f1d6f5384b3051c536cc81b3a93a73faf931f404fef95217cf1e10d"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d776d30cde7e541b8180103c3f294ef7c1862fd45d81738d156d00551005784"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:72f7919af5de5ecfaf1eba47bf9a5d8aa089a3340277276e5636d16ee97614d7"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4bfcbde6e06c56b30668a0c872d75a7ef3025dc3c1823a13cf29a0e9b33f67e8"},
{file = "pydantic_core-2.16.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ff7c97eb7a29aba230389a2661edf2e9e06ce616c7e35aa764879b6894a44b25"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9b5f13857da99325dcabe1cc4e9e6a3d7b2e2c726248ba5dd4be3e8e4a0b6d0e"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a7e41e3ada4cca5f22b478c08e973c930e5e6c7ba3588fb8e35f2398cdcc1545"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60eb8ceaa40a41540b9acae6ae7c1f0a67d233c40dc4359c256ad2ad85bdf5e5"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7beec26729d496a12fd23cf8da9944ee338c8b8a17035a560b585c36fe81af20"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22c5f022799f3cd6741e24f0443ead92ef42be93ffda0d29b2597208c94c3753"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:eca58e319f4fd6df004762419612122b2c7e7d95ffafc37e890252f869f3fb2a"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed957db4c33bc99895f3a1672eca7e80e8cda8bd1e29a80536b4ec2153fa9804"},
{file = "pydantic_core-2.16.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:459c0d338cc55d099798618f714b21b7ece17eb1a87879f2da20a3ff4c7628e2"},
{file = "pydantic_core-2.16.2.tar.gz", hash = "sha256:0ba503850d8b8dcc18391f10de896ae51d37fe5fe43dbfb6a35c5c5cad271a06"},
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
{file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
{file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
{file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
{file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
{file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
{file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
{file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
{file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
{file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
{file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
{file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
{file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
{file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
{file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
{file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
{file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
{file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
{file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
{file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
{file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
{file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
{file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
{file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
{file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
{file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
{file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
{file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
{file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
{file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
{file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
]
[package.dependencies]
@ -1017,6 +1024,7 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
name = "python-dotenv"
version = "1.0.1"
description = "Read key-value pairs from a .env file and set them as environment variables"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
@ -1031,6 +1039,7 @@ cli = ["click (>=5.0)"]
name = "pyyaml"
version = "6.0.1"
description = "YAML parser and emitter for Python"
category = "main"
optional = false
python-versions = ">=3.6"
files = [
@ -1039,7 +1048,6 @@ files = [
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
@ -1047,15 +1055,8 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
@ -1072,7 +1073,6 @@ files = [
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
@ -1080,7 +1080,6 @@ files = [
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
@ -1090,6 +1089,7 @@ files = [
name = "regex"
version = "2023.12.25"
description = "Alternative regular expression module, to replace re."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -1192,6 +1192,7 @@ files = [
name = "requests"
version = "2.31.0"
description = "Python HTTP for Humans."
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -1211,71 +1212,73 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "sniffio"
version = "1.3.0"
version = "1.3.1"
description = "Sniff out which async library your code is running under"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"},
{file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"},
{file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
{file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
]
[[package]]
name = "sqlalchemy"
version = "2.0.27"
version = "2.0.28"
description = "Database Abstraction Library"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
{file = "SQLAlchemy-2.0.27-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d04e579e911562f1055d26dab1868d3e0bb905db3bccf664ee8ad109f035618a"},
{file = "SQLAlchemy-2.0.27-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fa67d821c1fd268a5a87922ef4940442513b4e6c377553506b9db3b83beebbd8"},
{file = "SQLAlchemy-2.0.27-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c7a596d0be71b7baa037f4ac10d5e057d276f65a9a611c46970f012752ebf2d"},
{file = "SQLAlchemy-2.0.27-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:954d9735ee9c3fa74874c830d089a815b7b48df6f6b6e357a74130e478dbd951"},
{file = "SQLAlchemy-2.0.27-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5cd20f58c29bbf2680039ff9f569fa6d21453fbd2fa84dbdb4092f006424c2e6"},
{file = "SQLAlchemy-2.0.27-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:03f448ffb731b48323bda68bcc93152f751436ad6037f18a42b7e16af9e91c07"},
{file = "SQLAlchemy-2.0.27-cp310-cp310-win32.whl", hash = "sha256:d997c5938a08b5e172c30583ba6b8aad657ed9901fc24caf3a7152eeccb2f1b4"},
{file = "SQLAlchemy-2.0.27-cp310-cp310-win_amd64.whl", hash = "sha256:eb15ef40b833f5b2f19eeae65d65e191f039e71790dd565c2af2a3783f72262f"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6c5bad7c60a392850d2f0fee8f355953abaec878c483dd7c3836e0089f046bf6"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3012ab65ea42de1be81fff5fb28d6db893ef978950afc8130ba707179b4284a"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbcd77c4d94b23e0753c5ed8deba8c69f331d4fd83f68bfc9db58bc8983f49cd"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d177b7e82f6dd5e1aebd24d9c3297c70ce09cd1d5d37b43e53f39514379c029c"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:680b9a36029b30cf063698755d277885d4a0eab70a2c7c6e71aab601323cba45"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1306102f6d9e625cebaca3d4c9c8f10588735ef877f0360b5cdb4fdfd3fd7131"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-win32.whl", hash = "sha256:5b78aa9f4f68212248aaf8943d84c0ff0f74efc65a661c2fc68b82d498311fd5"},
{file = "SQLAlchemy-2.0.27-cp311-cp311-win_amd64.whl", hash = "sha256:15e19a84b84528f52a68143439d0c7a3a69befcd4f50b8ef9b7b69d2628ae7c4"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:0de1263aac858f288a80b2071990f02082c51d88335a1db0d589237a3435fe71"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce850db091bf7d2a1f2fdb615220b968aeff3849007b1204bf6e3e50a57b3d32"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8dfc936870507da96aebb43e664ae3a71a7b96278382bcfe84d277b88e379b18"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4fbe6a766301f2e8a4519f4500fe74ef0a8509a59e07a4085458f26228cd7cc"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4535c49d961fe9a77392e3a630a626af5baa967172d42732b7a43496c8b28876"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0fb3bffc0ced37e5aa4ac2416f56d6d858f46d4da70c09bb731a246e70bff4d5"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-win32.whl", hash = "sha256:7f470327d06400a0aa7926b375b8e8c3c31d335e0884f509fe272b3c700a7254"},
{file = "SQLAlchemy-2.0.27-cp312-cp312-win_amd64.whl", hash = "sha256:f9374e270e2553653d710ece397df67db9d19c60d2647bcd35bfc616f1622dcd"},
{file = "SQLAlchemy-2.0.27-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e97cf143d74a7a5a0f143aa34039b4fecf11343eed66538610debc438685db4a"},
{file = "SQLAlchemy-2.0.27-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7b5a3e2120982b8b6bd1d5d99e3025339f7fb8b8267551c679afb39e9c7c7f1"},
{file = "SQLAlchemy-2.0.27-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e36aa62b765cf9f43a003233a8c2d7ffdeb55bc62eaa0a0380475b228663a38f"},
{file = "SQLAlchemy-2.0.27-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5ada0438f5b74c3952d916c199367c29ee4d6858edff18eab783b3978d0db16d"},
{file = "SQLAlchemy-2.0.27-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b1d9d1bfd96eef3c3faedb73f486c89e44e64e40e5bfec304ee163de01cf996f"},
{file = "SQLAlchemy-2.0.27-cp37-cp37m-win32.whl", hash = "sha256:ca891af9f3289d24a490a5fde664ea04fe2f4984cd97e26de7442a4251bd4b7c"},
{file = "SQLAlchemy-2.0.27-cp37-cp37m-win_amd64.whl", hash = "sha256:fd8aafda7cdff03b905d4426b714601c0978725a19efc39f5f207b86d188ba01"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ec1f5a328464daf7a1e4e385e4f5652dd9b1d12405075ccba1df842f7774b4fc"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ad862295ad3f644e3c2c0d8b10a988e1600d3123ecb48702d2c0f26771f1c396"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48217be1de7d29a5600b5c513f3f7664b21d32e596d69582be0a94e36b8309cb"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e56afce6431450442f3ab5973156289bd5ec33dd618941283847c9fd5ff06bf"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:611068511b5531304137bcd7fe8117c985d1b828eb86043bd944cebb7fae3910"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b86abba762ecfeea359112b2bb4490802b340850bbee1948f785141a5e020de8"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-win32.whl", hash = "sha256:30d81cc1192dc693d49d5671cd40cdec596b885b0ce3b72f323888ab1c3863d5"},
{file = "SQLAlchemy-2.0.27-cp38-cp38-win_amd64.whl", hash = "sha256:120af1e49d614d2525ac247f6123841589b029c318b9afbfc9e2b70e22e1827d"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d07ee7793f2aeb9b80ec8ceb96bc8cc08a2aec8a1b152da1955d64e4825fcbac"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb0845e934647232b6ff5150df37ceffd0b67b754b9fdbb095233deebcddbd4a"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fc19ae2e07a067663dd24fca55f8ed06a288384f0e6e3910420bf4b1270cc51"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b90053be91973a6fb6020a6e44382c97739736a5a9d74e08cc29b196639eb979"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2f5c9dfb0b9ab5e3a8a00249534bdd838d943ec4cfb9abe176a6c33408430230"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:33e8bde8fff203de50399b9039c4e14e42d4d227759155c21f8da4a47fc8053c"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-win32.whl", hash = "sha256:d873c21b356bfaf1589b89090a4011e6532582b3a8ea568a00e0c3aab09399dd"},
{file = "SQLAlchemy-2.0.27-cp39-cp39-win_amd64.whl", hash = "sha256:ff2f1b7c963961d41403b650842dc2039175b906ab2093635d8319bef0b7d620"},
{file = "SQLAlchemy-2.0.27-py3-none-any.whl", hash = "sha256:1ab4e0448018d01b142c916cc7119ca573803a4745cfe341b8f95657812700ac"},
{file = "SQLAlchemy-2.0.27.tar.gz", hash = "sha256:86a6ed69a71fe6b88bf9331594fa390a2adda4a49b5c06f98e47bf0d392534f8"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0b148ab0438f72ad21cb004ce3bdaafd28465c4276af66df3b9ecd2037bf252"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bbda76961eb8f27e6ad3c84d1dc56d5bc61ba8f02bd20fcf3450bd421c2fcc9c"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feea693c452d85ea0015ebe3bb9cd15b6f49acc1a31c28b3c50f4db0f8fb1e71"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5da98815f82dce0cb31fd1e873a0cb30934971d15b74e0d78cf21f9e1b05953f"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4a5adf383c73f2d49ad15ff363a8748319ff84c371eed59ffd0127355d6ea1da"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56856b871146bfead25fbcaed098269d90b744eea5cb32a952df00d542cdd368"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-win32.whl", hash = "sha256:943aa74a11f5806ab68278284a4ddd282d3fb348a0e96db9b42cb81bf731acdc"},
{file = "SQLAlchemy-2.0.28-cp310-cp310-win_amd64.whl", hash = "sha256:c6c4da4843e0dabde41b8f2e8147438330924114f541949e6318358a56d1875a"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46a3d4e7a472bfff2d28db838669fc437964e8af8df8ee1e4548e92710929adc"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0d3dd67b5d69794cfe82862c002512683b3db038b99002171f624712fa71aeaa"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61e2e41656a673b777e2f0cbbe545323dbe0d32312f590b1bc09da1de6c2a02"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0315d9125a38026227f559488fe7f7cee1bd2fbc19f9fd637739dc50bb6380b2"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:af8ce2d31679006e7b747d30a89cd3ac1ec304c3d4c20973f0f4ad58e2d1c4c9"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:81ba314a08c7ab701e621b7ad079c0c933c58cdef88593c59b90b996e8b58fa5"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-win32.whl", hash = "sha256:1ee8bd6d68578e517943f5ebff3afbd93fc65f7ef8f23becab9fa8fb315afb1d"},
{file = "SQLAlchemy-2.0.28-cp311-cp311-win_amd64.whl", hash = "sha256:ad7acbe95bac70e4e687a4dc9ae3f7a2f467aa6597049eeb6d4a662ecd990bb6"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d3499008ddec83127ab286c6f6ec82a34f39c9817f020f75eca96155f9765097"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9b66fcd38659cab5d29e8de5409cdf91e9986817703e1078b2fdaad731ea66f5"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea30da1e76cb1acc5b72e204a920a3a7678d9d52f688f087dc08e54e2754c67"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:124202b4e0edea7f08a4db8c81cc7859012f90a0d14ba2bf07c099aff6e96462"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e23b88c69497a6322b5796c0781400692eca1ae5532821b39ce81a48c395aae9"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b6303bfd78fb3221847723104d152e5972c22367ff66edf09120fcde5ddc2e2"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-win32.whl", hash = "sha256:a921002be69ac3ab2cf0c3017c4e6a3377f800f1fca7f254c13b5f1a2f10022c"},
{file = "SQLAlchemy-2.0.28-cp312-cp312-win_amd64.whl", hash = "sha256:b4a2cf92995635b64876dc141af0ef089c6eea7e05898d8d8865e71a326c0385"},
{file = "SQLAlchemy-2.0.28-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e91b5e341f8c7f1e5020db8e5602f3ed045a29f8e27f7f565e0bdee3338f2c7"},
{file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45c7b78dfc7278329f27be02c44abc0d69fe235495bb8e16ec7ef1b1a17952db"},
{file = "SQLAlchemy-2.0.28-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eba73ef2c30695cb7eabcdb33bb3d0b878595737479e152468f3ba97a9c22a4"},
{file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5df5d1dafb8eee89384fb7a1f79128118bc0ba50ce0db27a40750f6f91aa99d5"},
{file = "SQLAlchemy-2.0.28-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2858bbab1681ee5406650202950dc8f00e83b06a198741b7c656e63818633526"},
{file = "SQLAlchemy-2.0.28-cp37-cp37m-win32.whl", hash = "sha256:9461802f2e965de5cff80c5a13bc945abea7edaa1d29360b485c3d2b56cdb075"},
{file = "SQLAlchemy-2.0.28-cp37-cp37m-win_amd64.whl", hash = "sha256:a6bec1c010a6d65b3ed88c863d56b9ea5eeefdf62b5e39cafd08c65f5ce5198b"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:843a882cadebecc655a68bd9a5b8aa39b3c52f4a9a5572a3036fb1bb2ccdc197"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dbb990612c36163c6072723523d2be7c3eb1517bbdd63fe50449f56afafd1133"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7e4baf9161d076b9a7e432fce06217b9bd90cfb8f1d543d6e8c4595627edb9"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0a5354cb4de9b64bccb6ea33162cb83e03dbefa0d892db88a672f5aad638a75"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fffcc8edc508801ed2e6a4e7b0d150a62196fd28b4e16ab9f65192e8186102b6"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aca7b6d99a4541b2ebab4494f6c8c2f947e0df4ac859ced575238e1d6ca5716b"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-win32.whl", hash = "sha256:8c7f10720fc34d14abad5b647bc8202202f4948498927d9f1b4df0fb1cf391b7"},
{file = "SQLAlchemy-2.0.28-cp38-cp38-win_amd64.whl", hash = "sha256:243feb6882b06a2af68ecf4bec8813d99452a1b62ba2be917ce6283852cf701b"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc4974d3684f28b61b9a90fcb4c41fb340fd4b6a50c04365704a4da5a9603b05"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87724e7ed2a936fdda2c05dbd99d395c91ea3c96f029a033a4a20e008dd876bf"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68722e6a550f5de2e3cfe9da6afb9a7dd15ef7032afa5651b0f0c6b3adb8815d"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:328529f7c7f90adcd65aed06a161851f83f475c2f664a898af574893f55d9e53"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:df40c16a7e8be7413b885c9bf900d402918cc848be08a59b022478804ea076b8"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:426f2fa71331a64f5132369ede5171c52fd1df1bd9727ce621f38b5b24f48750"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-win32.whl", hash = "sha256:33157920b233bc542ce497a81a2e1452e685a11834c5763933b440fedd1d8e2d"},
{file = "SQLAlchemy-2.0.28-cp39-cp39-win_amd64.whl", hash = "sha256:2f60843068e432311c886c5f03c4664acaef507cf716f6c60d5fde7265be9d7b"},
{file = "SQLAlchemy-2.0.28-py3-none-any.whl", hash = "sha256:78bb7e8da0183a8301352d569900d9d3594c48ac21dc1c2ec6b3121ed8b6c986"},
{file = "SQLAlchemy-2.0.28.tar.gz", hash = "sha256:dd53b6c4e6d960600fd6532b79ee28e2da489322fcf6648738134587faf767b6"},
]
[package.dependencies]
@ -1311,6 +1314,7 @@ sqlcipher = ["sqlcipher3_binary"]
name = "tenacity"
version = "8.2.3"
description = "Retry code until it succeeds"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -1325,6 +1329,7 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"]
name = "tiktoken"
version = "0.6.0"
description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
@ -1377,6 +1382,7 @@ blobfile = ["blobfile (>=2)"]
name = "tqdm"
version = "4.66.2"
description = "Fast, Extensible Progress Meter"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -1395,19 +1401,21 @@ telegram = ["requests"]
[[package]]
name = "typing-extensions"
version = "4.9.0"
version = "4.10.0"
description = "Backported and Experimental Type Hints for Python 3.8+"
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.9.0-py3-none-any.whl", hash = "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd"},
{file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"},
{file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
{file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
]
[[package]]
name = "typing-inspect"
version = "0.9.0"
description = "Runtime inspection utilities for typing module."
category = "main"
optional = false
python-versions = "*"
files = [
@ -1421,13 +1429,14 @@ typing-extensions = ">=3.7.4"
[[package]]
name = "urllib3"
version = "2.2.0"
version = "2.2.1"
description = "HTTP library with thread-safe connection pooling, file post, and more."
category = "main"
optional = false
python-versions = ">=3.8"
files = [
{file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
{file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
]
[package.extras]
@ -1440,6 +1449,7 @@ zstd = ["zstandard (>=0.18.0)"]
name = "yarl"
version = "1.9.4"
description = "Yet another URL library"
category = "main"
optional = false
python-versions = ">=3.7"
files = [
@ -1542,4 +1552,4 @@ multidict = ">=4.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
content-hash = "ec01ccebabbdd1053e6dc7778ff629842adeff8e97200636460028a1338d656f"
content-hash = "3f4ec2cb731a6b5b3cd11481853b12565c08a6b48f9602977a1bececec308720"

View File

@ -13,7 +13,8 @@ openai = "^1.12.0"
py-cord = "^2.4.1"
python-dotenv = "^1.0.1"
langchain-openai = "^0.0.6"
honcho-ai = "0.0.3"
honcho-ai = "0.0.5"
aiohttp = "^3.9.3"
[build-system]

View File

@ -11,7 +11,8 @@ from langchain_core.output_parsers import StrOutputParser
from langchain_core.messages import AIMessage, HumanMessage
from honcho import Honcho
from honcho.ext.langchain import langchain_message_converter
from honcho.ext.langchain import _messages_to_langchain
>>>>>>> main
load_dotenv()
@ -67,7 +68,7 @@ async def on_message(message):
session = user.create_session(location_id)
history = list(session.get_messages_generator())
chat_history = langchain_message_converter(history)
chat_history = _messages_to_langchain(history)
inp = message.content
session.create_message(is_user=True, content=inp)

View File

@ -13,6 +13,7 @@ with open(source_file_path, "r") as source_file:
sync_code = re.sub(r"async\s", "", source_code)
sync_code = re.sub(r"await\s", "", sync_code)
sync_code = re.sub(r"Async", "", sync_code)
sync_code = re.sub(r"asynchronous", "synchronous", sync_code)
# Write the modified code to the destination file
destination_file_path = os.path.join(this_dir, "../sdk/honcho/sync_client.py")

View File

@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.0.6] — 2024-03-21
### Added
* Full docstring coverage
* Code coverage tests
* Add LangChain to Honcho message converter in both directions
* Synonym `init` function that acts the same as `initialize`
## [0.0.5] — 2024-03-14
### Added

28
sdk/docs/_static/favicon.svg vendored Normal file
View File

@ -0,0 +1,28 @@
<svg width="650" height="650" viewBox="0 0 650 650" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="650" height="650" fill="#101447"/>
<g filter="url(#filter0_dd_11_8)">
<path d="M325.56 80C238.59 80 157.54 126.59 113.62 201.69C94.1801 213.51 81.0001 221.78 80.7301 221.92C42.8201 242.58 23.9001 262.29 14.6201 277.9C7.41011 278.03 1.1701 283.37 0.150101 290.73C-1.0099 298.88 4.6801 306.44 12.8401 307.58C21.0101 308.74 28.5501 303.05 29.7101 294.88C30.3101 290.68 29.0701 286.63 26.6301 283.55C40.3601 261.4 69.3201 243.18 87.0601 233.52C90.1101 231.86 261.89 127.81 274.74 130.38C276.89 130.81 280.03 131.97 282.5 137.08C289.3 151.18 226.78 192.95 214.03 200.59C201.82 207.9 191.06 215.71 181.75 224.01C162.02 241.59 148.85 261.32 142.45 282.97C138.6 296.02 127.63 333.6 101.02 342.94C99.1301 338.74 95.3301 335.46 90.4701 334.46C82.4001 332.77 74.4901 337.95 72.8201 346.02C71.2201 353.66 75.7801 361.14 83.1201 363.34C101.49 482.47 203.51 570.77 325.56 570.77C460.86 570.77 570.95 460.69 570.95 325.38C570.95 190.07 460.87 80 325.56 80ZM187.7 236.51C187.12 244.15 185.37 252.9 181.07 258.61C176.54 264.61 167.95 269.71 160.23 273.31C166.33 260.21 175.51 247.92 187.7 236.51ZM325.56 557.54C210.02 557.54 113.46 473.91 96.1601 361.12C97.9201 359.84 99.4201 358.2 100.48 356.25C122.53 348.38 139.19 337.49 154.08 290.08C162.07 287.28 182.01 279.35 191.64 266.56C201.32 253.69 201.46 233.61 201.05 225.28C207.1 220.67 213.7 216.22 220.83 211.95C261.59 187.55 305.55 154.35 294.41 131.32C290.74 123.73 284.83 118.92 277.34 117.43C263.23 114.63 192.72 154.44 140.15 185.73C183.7 128.08 252.41 93.24 325.56 93.24C453.57 93.24 557.71 197.39 557.71 325.39C557.71 453.39 453.57 557.55 325.56 557.55V557.54Z" fill="white"/>
<path d="M247.34 325.38C261.296 325.38 272.61 307.843 272.61 286.21C272.61 264.577 261.296 247.04 247.34 247.04C233.384 247.04 222.07 264.577 222.07 286.21C222.07 307.843 233.384 325.38 247.34 325.38Z" fill="white"/>
<path d="M403.78 325.38C417.736 325.38 429.05 307.843 429.05 286.21C429.05 264.577 417.736 247.04 403.78 247.04C389.824 247.04 378.51 264.577 378.51 286.21C378.51 307.843 389.824 325.38 403.78 325.38Z" fill="white"/>
<path d="M386.18 406.91H264.94C258.48 406.91 253.25 412.14 253.25 418.6C253.25 425.06 258.48 430.29 264.94 430.29H386.18C392.64 430.29 397.87 425.06 397.87 418.6C397.87 412.14 392.64 406.91 386.18 406.91Z" fill="white"/>
<path d="M93.9401 333.61L93.9701 333.58L93.9401 333.6V333.62V333.61Z" fill="white"/>
</g>
<defs>
<filter id="filter0_dd_11_8" x="0" y="80" width="594.95" height="514.77" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="20" dy="20"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.352941 0 0 0 0 0.494118 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_11_8"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="10" dy="10"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.0352941 0 0 0 0 0.996078 0 0 0 0 0.972549 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_11_8" result="effect2_dropShadow_11_8"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_11_8" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -39,3 +39,5 @@ viewcode_import = "import honcho"
html_theme = "furo"
html_static_path = ["_static"]
html_favicon = "_static/favicon.svg"

View File

@ -1,3 +1,5 @@
"""Honcho is a Python client for the Honcho API."""
from .client import (
AsyncHoncho,
AsyncUser,

View File

@ -1,11 +1,18 @@
"""
This module provides an LRU (Least Recently Used) cache implementation as part of the Honcho SDK's caching mechanisms.
"""
from collections import OrderedDict
class LRUCache:
"""
An implementation of a basic LRUcache that utilizes the built
in OrderedDict data structure.
"""
def __init__(self, capacity: int):
"""Initialize the cache"""
self.capacity = capacity
self.cache = OrderedDict()

View File

@ -1,3 +1,7 @@
"""
This module provides asynchronous client functionality for interacting with the Honcho API.
"""
from __future__ import annotations
import datetime
@ -45,6 +49,7 @@ class AsyncGetUserPage(AsyncGetPage):
Args:
response (dict): Response from API with pagination information
honcho (AsyncHoncho): Honcho Client
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -62,6 +67,11 @@ class AsyncGetUserPage(AsyncGetPage):
]
async def next(self):
"""Get the next page of results
Returns:
AsyncGetUserPage | None: Next Page of Results or None if there are no more users to retreive from a query
"""
if self.page >= self.pages:
return None
return await self.honcho.get_users(
@ -90,7 +100,10 @@ class AsyncGetSessionPage(AsyncGetPage):
response (dict): Response from API with pagination information
user (AsyncUser): Honcho User associated with the session
reverse (bool): Whether to reverse the order of the results or not
location_id (str): ID of the location associated with the session
filter (dict, optional): Key value filter to apply to the results
location_id (str, optional): ID of the location associated with the session
is_active (bool): boolean filter for restricint results to only active
sessions
"""
super().__init__(response)
self.user = user
@ -143,6 +156,7 @@ class AsyncGetMessagePage(AsyncGetPage):
Args:
response (dict): Response from API with pagination information
session (AsyncSession): Session the returned messages are associated with
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -176,6 +190,8 @@ class AsyncGetMessagePage(AsyncGetPage):
class AsyncGetMetamessagePage(AsyncGetPage):
"""Paginated Results for Get Metamessage Requests"""
def __init__(
self,
response: dict,
@ -191,9 +207,10 @@ class AsyncGetMetamessagePage(AsyncGetPage):
response (dict): Response from API with pagination information
session (AsyncSession): Session the returned messages are
associated with
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results
message_id (Optional[str]): ID of the message associated with the
metamessage_type (Optional[str]): Type of the metamessage
message_id (str, optional): ID of the message associated with the
metamessage_type (str, optional): Type of the metamessage
"""
super().__init__(response)
self.session = session
@ -244,6 +261,7 @@ class AsyncGetDocumentPage(AsyncGetPage):
response (dict): Response from API with pagination information
collection (AsyncCollection): Collection the returned documents are
associated with
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -289,6 +307,7 @@ class AsyncGetCollectionPage(AsyncGetPage):
Args:
response (dict): Response from API with pagination information
user (AsyncUser): Honcho Client
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -327,7 +346,13 @@ class AsyncHoncho:
"""Honcho API Client Object"""
def __init__(self, app_name: str, base_url: str = "https://demo.honcho.dev"):
"""Constructor for Client"""
"""Constructor for Client
Args:
app_name (str): Name of the application
base_url (str): Base URL for the instance of the Honcho API defaults to
https://demo.honcho.dev
"""
self.server_url: str = base_url # Base URL for the instance of the Honcho API
self.client: httpx.AsyncClient = httpx.AsyncClient()
self.app_name: str = app_name # Representing name of the client application
@ -335,6 +360,7 @@ class AsyncHoncho:
self.metadata: dict
async def initialize(self):
"""Run initialization tasks for the Honcho client"""
res = await self.client.get(
f"{self.server_url}/apps/get_or_create/{self.app_name}"
)
@ -343,9 +369,13 @@ class AsyncHoncho:
self.app_id: uuid.UUID = data["id"]
self.metadata: dict = data["metadata"]
async def init(self):
"""Synonym for initialize"""
await self.initialize()
@property
def base_url(self):
"""Shorcut for common API prefix. made a property to prevent tampering"""
"""Shortcut for common API prefix. made a property to prevent tampering"""
return f"{self.server_url}/apps/{self.app_id}"
async def update(self, metadata: dict):
@ -440,9 +470,11 @@ class AsyncHoncho:
"""Get Paginated list of users
Args:
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return. Defaults to 50
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to False
Returns:
AsyncGetUserPage: Paginated list of users
@ -471,7 +503,9 @@ class AsyncHoncho:
all users in an app
Args:
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply. Defaults to None
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to False
Yields:
AsyncUser: The User object
@ -507,7 +541,7 @@ class AsyncHoncho:
class AsyncUser:
"""Represents a single user in an app"""
"""Represents a single user in an app and associated methods"""
def __init__(
self,
@ -516,7 +550,18 @@ class AsyncUser:
metadata: dict,
created_at: datetime.datetime,
):
"""Constructor for User"""
"""Constructor for User
Args:
honcho (AsyncHoncho): The honcho object
id (uuid.UUID): The id of the user
metadata (dict): The metadata for the user
created_at (datetime.datetime): The time the user was created
Returns:
AsyncUser: The created User object
"""
# self.base_url: str = honcho.base_url
self.honcho: AsyncHoncho = honcho
self.id: uuid.UUID = id
@ -530,7 +575,7 @@ class AsyncUser:
def __str__(self):
"""String representation of User"""
return f"AsyncUser(id={self.id}, app_id={self.honcho.app_id}, metadata={self.metadata})" # noqa: E501
return f"AsyncUser(id={self.id}, app_id={self.honcho.app_id}, metadata={self.metadata})"
async def update(self, metadata: dict):
"""Updates a user's metadata
@ -588,11 +633,13 @@ class AsyncUser:
Args:
location_id (str, optional): Optional Location ID representing the
location of a session
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return
reverse (bool): Whether to reverse the order of the results
is_active (bool): Whether to only return active sessions
location of a session. Defaults to None
filter (dict, optional): The key value filter to apply. Defaults to None
page (int, optional): The page of results to return. Defaults to 1
page_size (int, optional): The number of results to return. Defaults to 50
reverse (bool): Whether to reverse the order of the results. Defaults to
False
is_active (bool): Whether to only return active sessions. Defaults to False
Returns:
AsyncGetSessionPage: Page or results for get_sessions query
@ -632,8 +679,10 @@ class AsyncUser:
Args:
location_id (str, optional): Optional Location ID representing the
location of a session
reverse (bool): Whether to reverse the order of the results
is_active (bool): Whether to only return active sessions
reverse (bool): Whether to reverse the order of the results. Defaults to
False
is_active (bool): Whether to only return active sessions. Defaults to False
filter (dict, optional): The key value filter to apply. Defaults to None
Yields:
AsyncSession: The Session object of the requested Session
@ -661,8 +710,8 @@ class AsyncUser:
Args:
location_id (str, optional): Optional Location ID representing the
location of a session
metadata (dict, optional): Optional session metadata
location of a session. Defaults to "default"
metadata (dict, optional): Optional session metadata. Defaults to None
Returns:
AsyncSession: The Session object of the new Session
@ -693,6 +742,7 @@ class AsyncUser:
Args:
name (str): unique name for the collection for the user
metadata (dict, optional): Optional metadata. Defaults to None
Returns:
AsyncCollection: The Collection object of the new Collection
@ -745,15 +795,15 @@ class AsyncUser:
"""Return collections associated with a user paginated
Args:
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return
filter (dict, optional): The key value filter to apply. Defaults to None
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return
reverse (bool): Whether to reverse the order of the results
Returns:
AsyncGetCollectionPage: Page or results for get_collections query
"""
# url = f"{self.base_url}/collections?page={page}&size={page_size}&reverse={reverse}" # noqa: E501
url = f"{self.base_url}/collections"
params = {
"page": page,
@ -775,7 +825,9 @@ class AsyncUser:
all sessions for a user in an app
Args:
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply. Defaults to None
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Yields:
AsyncCollection: The Session object of the requested Session
@ -809,7 +861,20 @@ class AsyncSession:
is_active: bool,
created_at: datetime.datetime,
):
"""Constructor for Session"""
"""Constructor for Session
Args:
user (AsyncUser): The user object
id (uuid.UUID): The id of the session
location_id (str): The id of the location associated with the session
metadata (dict): The metadata associated with the session
is_active (bool): Whether the session is active
created_at (datetime.datetime): When the session was created
Returns:
AsyncSession: The Session object
"""
self.user: AsyncUser = user
self.id: uuid.UUID = id
self.location_id: str = location_id
@ -824,7 +889,7 @@ class AsyncSession:
def __str__(self):
"""String representation of Session"""
return f"AsyncSession(id={self.id}, location_id={self.location_id}, metadata={self.metadata}, is_active={self.is_active})" # noqa: E501
return f"AsyncSession(id={self.id}, location_id={self.location_id}, metadata={self.metadata}, is_active={self.is_active})"
@property
def is_active(self):
@ -839,6 +904,7 @@ class AsyncSession:
Args:
is_user (bool): Whether the message is from the user
content (str): The content of the message
metadata (dict, optional): The metadata of the message. Defaults to None
Returns:
Message: The Message object of the added message
@ -895,9 +961,11 @@ class AsyncSession:
"""Get all messages for a session
Args:
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return per page
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply. Defaults to None
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return per page. Defaults to 50
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Returns:
AsyncGetMessagePage: Page of Message objects
@ -923,6 +991,11 @@ class AsyncSession:
"""Shortcut Generator for get_messages. Generator to iterate through
all messages for a session in an app
Args:
filter (dict, optional): The key value filter to apply. Defaults to None
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Yields:
Message: The Message object of the next Message
@ -953,6 +1026,7 @@ class AsyncSession:
message (Message): A message to associate the metamessage with
metamessage_type (str): The type of the metamessage arbitrary identifier
content (str): The content of the metamessage
metadata (dict, optional): The metadata of the metamessage. Defaults to None
Returns:
Metamessage: The Metamessage object of the added metamessage
@ -985,7 +1059,7 @@ class AsyncSession:
"""Get a specific metamessage
Args:
message_id (uuid.UUID): The ID of the Message to retrieve
metamessage_id (uuid.UUID): The ID of the Metamessage to retrieve
Returns:
Message: The Message object
@ -1016,17 +1090,21 @@ class AsyncSession:
"""Get all messages for a session
Args:
metamessage_type (str, optional): The type of the metamessage
message (Message, optional): The message to associate the metamessage with
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return per page
reverse (bool): Whether to reverse the order of the results
metamessage_type (str, optional): The type of the metamessage. Defaults to
None
message (Message, optional): The message to associate the metamessage with.
Defaults to None
filter (dict, optional): The key value filter to apply. Defaults to None
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return per page. Defaults to 50
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Returns:
list[dict]: List of Message objects
"""
# url = f"{self.base_url}/metamessages?page={page}&size={page_size}&reverse={reverse}" # noqa: E501
# url = f"{self.base_url}/metamessages?page={page}&size={page_size}&reverse={reverse}"
url = f"{self.base_url}/metamessages"
params = {
"page": page,
@ -1061,8 +1139,12 @@ class AsyncSession:
through all metamessages for a session in an app
Args:
metamessage_type (str, optional): Optional Metamessage type to filter by
message (Message, optional): Optional Message to filter by
metamessage_type (str, optional): Optional Metamessage type to filter by.
Defaults to None
message (Message, optional): Optional Message to filter by. Defaults to None
filter (dict, optional): Optional key value filter. Defaults to None
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Yields:
Metamessage: The next Metamessage object of the requested query
@ -1131,7 +1213,8 @@ class AsyncSession:
Args:
metamessage (Metamessage): The metamessage to update
metadata (dict): The new metadata for the metamessage
metamessage_type (str, optional): The new type of the metamessage
metadata (dict, optional): The new metadata for the metamessage
Returns:
boolean: Whether the metamessage was successfully updated
@ -1149,13 +1232,23 @@ class AsyncSession:
return success
async def close(self):
"""Closes a session by marking it as inactive"""
"""Closes a session by marking it as inactive. An inactive session can no longer
create new messages"""
url = f"{self.base_url}"
response = await self.user.honcho.client.delete(url)
response.raise_for_status()
self._is_active = False
async def chat(self, query) -> str:
"""Chat with the dialectic Honcho Agent that asynchonously reasons about users
Args:
query (str): The query to send to the agent
Returns:
str: The response from the agent
"""
url = f"{self.base_url}/chat"
params = {"query": query}
response = await self.user.honcho.client.get(url, params=params)
@ -1189,13 +1282,14 @@ class AsyncCollection:
def __str__(self):
"""String representation of Collection"""
return f"AsyncCollection(id={self.id}, name={self.name}, created_at={self.created_at})" # noqa: E501
return f"AsyncCollection(id={self.id}, name={self.name}, created_at={self.created_at})"
async def update(self, name: Optional[str] = None, metadata: Optional[dict] = None):
"""Update the name of the collection
"""Update the name of the collection. Atleast one argument is required
Args:
name (str): The new name of the document
name (str, optional): The new name of the document
metadata (dict, optional): The new metadata of the document
Returns:
boolean: Whether the session was successfully updated
@ -1224,7 +1318,7 @@ class AsyncCollection:
Args:
content (str): The content of the document
metadata (dict): The metadata of the document
metadata (dict, optional): The metadata of the document
Returns:
Document: The Document object of the added document
@ -1277,14 +1371,17 @@ class AsyncCollection:
"""Get all documents for a collection
Args:
filter (dict, optional): The key value filter to apply
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return per page
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to None
Returns:
AsyncGetDocumentPage: Page of Document objects
"""
# url = f"{self.base_url}/documents?page={page}&size={page_size}&reverse={reverse}" # noqa: E501
# url = f"{self.base_url}/documents?page={page}&size={page_size}&reverse={reverse}"
url = f"{self.base_url}/documents"
params = {
"page": page,
@ -1305,6 +1402,11 @@ class AsyncCollection:
"""Shortcut Generator for get_documents. Generator to iterate through
all documents for a collection in an app
Args:
filter (dict, optional): The key value filter to apply
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to None
Yields:
Document: The Document object of the next Document
@ -1358,8 +1460,8 @@ class AsyncCollection:
Args:
document (Document): The Document to update
metadata (dict): The metadata of the document
content (str): The content of the document
content (str, optional): The content of the document
metadata (dict, optional): The metadata of the document
Returns:
Document: The newly updated Document

View File

@ -0,0 +1 @@
"""Extensions/utilities for the Honcho Ecosystem"""

View File

@ -1,14 +1,23 @@
"""
Utilities to integrate Honcho with Langchain projects
"""
import functools
import importlib
from typing import List
from typing import List, Union
from honcho import AsyncSession, Session
from honcho.schemas import Message
def requires_langchain(func):
"""A utility to check if langchain is installed before running a function"""
@functools.wraps(func)
def wrapper(*args, **kwargs):
if importlib.util.find_spec("langchain") is None:
"""Check if langchain is installed before running a function"""
if importlib.util.find_spec("langchain") is None: # type: ignore
raise ImportError("Langchain must be installed to use this feature")
# raise RuntimeError("langchain is not installed")
return func(*args, **kwargs)
@ -17,8 +26,17 @@ def requires_langchain(func):
@requires_langchain
def langchain_message_converter(messages: List[Message]):
from langchain_core.messages import AIMessage, HumanMessage
def _messages_to_langchain(messages: List[Message]):
"""Converts Honcho messages to Langchain messages
Args:
messages (List[Message]): The list of messages to convert
Returns:
List: The list of converted LangChain messages
"""
from langchain_core.messages import AIMessage, HumanMessage # type: ignore
new_messages = []
for message in messages:
@ -27,3 +45,34 @@ def langchain_message_converter(messages: List[Message]):
else:
new_messages.append(AIMessage(content=message.content))
return new_messages
@requires_langchain
def _langchain_to_messages(
messages, session: Union[Session, AsyncSession]
) -> List[Message]:
"""Converts Langchain messages to Honcho messages and adds to appropriate session
Args:
messages: The LangChain messages to convert
session: The session to add the messages to
Returns:
List[Message]: The list of converted messages
"""
from langchain_core.messages import HumanMessage # type: ignore
messages = []
for message in messages:
if isinstance(message, HumanMessage):
message = session.create_message(
is_user=True, content=message.content, metadata=message.metadata
)
messages.append(message)
else:
message = session.create_message(
is_user=False, content=message.content, metadata=message.metadata
)
messages.append(message)
return messages

View File

@ -1,8 +1,14 @@
import uuid
"""
This module defines the schema classes for various entities such as Message, Metamessage, and Document.
"""
import datetime
import uuid
class Message:
"""Class representing a Message"""
def __init__(
self,
session_id: uuid.UUID,
@ -21,10 +27,13 @@ class Message:
self.created_at = created_at
def __str__(self):
"""String representation of Message object"""
return f"Message(id={self.id}, is_user={self.is_user}, content={self.content})"
class Metamessage:
"""Class representing a Metamessage"""
def __init__(
self,
id: uuid.UUID,
@ -43,10 +52,13 @@ class Metamessage:
self.created_at = created_at
def __str__(self):
"""String representation of Metamessage object"""
return f"Metamessage(id={self.id}, message_id={self.message_id}, metamessage_type={self.metamessage_type}, content={self.content})"
class Document:
"""Class representing a Document"""
def __init__(
self,
id: uuid.UUID,
@ -63,4 +75,5 @@ class Document:
self.created_at = created_at
def __str__(self) -> str:
"""String representation of Document object"""
return f"Document(id={self.id}, metadata={self.metadata}, content={self.content}, created_at={self.created_at})"

View File

@ -1,3 +1,7 @@
"""
This module provides synchronous client functionality for interacting with the Honcho API.
"""
from __future__ import annotations
import datetime
@ -45,6 +49,7 @@ class GetUserPage(GetPage):
Args:
response (dict): Response from API with pagination information
honcho (Honcho): Honcho Client
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -62,6 +67,11 @@ class GetUserPage(GetPage):
]
def next(self):
"""Get the next page of results
Returns:
GetUserPage | None: Next Page of Results or None if there are no more users to retreive from a query
"""
if self.page >= self.pages:
return None
return self.honcho.get_users(
@ -90,7 +100,10 @@ class GetSessionPage(GetPage):
response (dict): Response from API with pagination information
user (User): Honcho User associated with the session
reverse (bool): Whether to reverse the order of the results or not
location_id (str): ID of the location associated with the session
filter (dict, optional): Key value filter to apply to the results
location_id (str, optional): ID of the location associated with the session
is_active (bool): boolean filter for restricint results to only active
sessions
"""
super().__init__(response)
self.user = user
@ -143,6 +156,7 @@ class GetMessagePage(GetPage):
Args:
response (dict): Response from API with pagination information
session (Session): Session the returned messages are associated with
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -176,6 +190,8 @@ class GetMessagePage(GetPage):
class GetMetamessagePage(GetPage):
"""Paginated Results for Get Metamessage Requests"""
def __init__(
self,
response: dict,
@ -191,9 +207,10 @@ class GetMetamessagePage(GetPage):
response (dict): Response from API with pagination information
session (Session): Session the returned messages are
associated with
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results
message_id (Optional[str]): ID of the message associated with the
metamessage_type (Optional[str]): Type of the metamessage
message_id (str, optional): ID of the message associated with the
metamessage_type (str, optional): Type of the metamessage
"""
super().__init__(response)
self.session = session
@ -244,6 +261,7 @@ class GetDocumentPage(GetPage):
response (dict): Response from API with pagination information
collection (Collection): Collection the returned documents are
associated with
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -289,6 +307,7 @@ class GetCollectionPage(GetPage):
Args:
response (dict): Response from API with pagination information
user (User): Honcho Client
filter (dict, optional): Key value filter to apply to the results
reverse (bool): Whether to reverse the order of the results or not
"""
super().__init__(response)
@ -327,7 +346,13 @@ class Honcho:
"""Honcho API Client Object"""
def __init__(self, app_name: str, base_url: str = "https://demo.honcho.dev"):
"""Constructor for Client"""
"""Constructor for Client
Args:
app_name (str): Name of the application
base_url (str): Base URL for the instance of the Honcho API defaults to
https://demo.honcho.dev
"""
self.server_url: str = base_url # Base URL for the instance of the Honcho API
self.client: httpx.Client = httpx.Client()
self.app_name: str = app_name # Representing name of the client application
@ -335,6 +360,7 @@ class Honcho:
self.metadata: dict
def initialize(self):
"""Run initialization tasks for the Honcho client"""
res = self.client.get(
f"{self.server_url}/apps/get_or_create/{self.app_name}"
)
@ -343,9 +369,13 @@ class Honcho:
self.app_id: uuid.UUID = data["id"]
self.metadata: dict = data["metadata"]
def init(self):
"""Synonym for initialize"""
self.initialize()
@property
def base_url(self):
"""Shorcut for common API prefix. made a property to prevent tampering"""
"""Shortcut for common API prefix. made a property to prevent tampering"""
return f"{self.server_url}/apps/{self.app_id}"
def update(self, metadata: dict):
@ -440,9 +470,11 @@ class Honcho:
"""Get Paginated list of users
Args:
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return. Defaults to 50
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to False
Returns:
GetUserPage: Paginated list of users
@ -471,7 +503,9 @@ class Honcho:
all users in an app
Args:
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply. Defaults to None
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to False
Yields:
User: The User object
@ -507,7 +541,7 @@ class Honcho:
class User:
"""Represents a single user in an app"""
"""Represents a single user in an app and associated methods"""
def __init__(
self,
@ -516,7 +550,18 @@ class User:
metadata: dict,
created_at: datetime.datetime,
):
"""Constructor for User"""
"""Constructor for User
Args:
honcho (Honcho): The honcho object
id (uuid.UUID): The id of the user
metadata (dict): The metadata for the user
created_at (datetime.datetime): The time the user was created
Returns:
User: The created User object
"""
# self.base_url: str = honcho.base_url
self.honcho: Honcho = honcho
self.id: uuid.UUID = id
@ -530,7 +575,7 @@ class User:
def __str__(self):
"""String representation of User"""
return f"User(id={self.id}, app_id={self.honcho.app_id}, metadata={self.metadata})" # noqa: E501
return f"User(id={self.id}, app_id={self.honcho.app_id}, metadata={self.metadata})"
def update(self, metadata: dict):
"""Updates a user's metadata
@ -588,11 +633,13 @@ class User:
Args:
location_id (str, optional): Optional Location ID representing the
location of a session
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return
reverse (bool): Whether to reverse the order of the results
is_active (bool): Whether to only return active sessions
location of a session. Defaults to None
filter (dict, optional): The key value filter to apply. Defaults to None
page (int, optional): The page of results to return. Defaults to 1
page_size (int, optional): The number of results to return. Defaults to 50
reverse (bool): Whether to reverse the order of the results. Defaults to
False
is_active (bool): Whether to only return active sessions. Defaults to False
Returns:
GetSessionPage: Page or results for get_sessions query
@ -632,8 +679,10 @@ class User:
Args:
location_id (str, optional): Optional Location ID representing the
location of a session
reverse (bool): Whether to reverse the order of the results
is_active (bool): Whether to only return active sessions
reverse (bool): Whether to reverse the order of the results. Defaults to
False
is_active (bool): Whether to only return active sessions. Defaults to False
filter (dict, optional): The key value filter to apply. Defaults to None
Yields:
Session: The Session object of the requested Session
@ -661,8 +710,8 @@ class User:
Args:
location_id (str, optional): Optional Location ID representing the
location of a session
metadata (dict, optional): Optional session metadata
location of a session. Defaults to "default"
metadata (dict, optional): Optional session metadata. Defaults to None
Returns:
Session: The Session object of the new Session
@ -693,6 +742,7 @@ class User:
Args:
name (str): unique name for the collection for the user
metadata (dict, optional): Optional metadata. Defaults to None
Returns:
Collection: The Collection object of the new Collection
@ -745,15 +795,15 @@ class User:
"""Return collections associated with a user paginated
Args:
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return
filter (dict, optional): The key value filter to apply. Defaults to None
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return
reverse (bool): Whether to reverse the order of the results
Returns:
GetCollectionPage: Page or results for get_collections query
"""
# url = f"{self.base_url}/collections?page={page}&size={page_size}&reverse={reverse}" # noqa: E501
url = f"{self.base_url}/collections"
params = {
"page": page,
@ -775,7 +825,9 @@ class User:
all sessions for a user in an app
Args:
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply. Defaults to None
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Yields:
Collection: The Session object of the requested Session
@ -809,7 +861,20 @@ class Session:
is_active: bool,
created_at: datetime.datetime,
):
"""Constructor for Session"""
"""Constructor for Session
Args:
user (User): The user object
id (uuid.UUID): The id of the session
location_id (str): The id of the location associated with the session
metadata (dict): The metadata associated with the session
is_active (bool): Whether the session is active
created_at (datetime.datetime): When the session was created
Returns:
Session: The Session object
"""
self.user: User = user
self.id: uuid.UUID = id
self.location_id: str = location_id
@ -824,7 +889,7 @@ class Session:
def __str__(self):
"""String representation of Session"""
return f"Session(id={self.id}, location_id={self.location_id}, metadata={self.metadata}, is_active={self.is_active})" # noqa: E501
return f"Session(id={self.id}, location_id={self.location_id}, metadata={self.metadata}, is_active={self.is_active})"
@property
def is_active(self):
@ -839,6 +904,7 @@ class Session:
Args:
is_user (bool): Whether the message is from the user
content (str): The content of the message
metadata (dict, optional): The metadata of the message. Defaults to None
Returns:
Message: The Message object of the added message
@ -895,9 +961,11 @@ class Session:
"""Get all messages for a session
Args:
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return per page
reverse (bool): Whether to reverse the order of the results
filter (dict, optional): The key value filter to apply. Defaults to None
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return per page. Defaults to 50
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Returns:
GetMessagePage: Page of Message objects
@ -923,6 +991,11 @@ class Session:
"""Shortcut Generator for get_messages. Generator to iterate through
all messages for a session in an app
Args:
filter (dict, optional): The key value filter to apply. Defaults to None
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Yields:
Message: The Message object of the next Message
@ -953,6 +1026,7 @@ class Session:
message (Message): A message to associate the metamessage with
metamessage_type (str): The type of the metamessage arbitrary identifier
content (str): The content of the metamessage
metadata (dict, optional): The metadata of the metamessage. Defaults to None
Returns:
Metamessage: The Metamessage object of the added metamessage
@ -985,7 +1059,7 @@ class Session:
"""Get a specific metamessage
Args:
message_id (uuid.UUID): The ID of the Message to retrieve
metamessage_id (uuid.UUID): The ID of the Metamessage to retrieve
Returns:
Message: The Message object
@ -1016,17 +1090,21 @@ class Session:
"""Get all messages for a session
Args:
metamessage_type (str, optional): The type of the metamessage
message (Message, optional): The message to associate the metamessage with
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return per page
reverse (bool): Whether to reverse the order of the results
metamessage_type (str, optional): The type of the metamessage. Defaults to
None
message (Message, optional): The message to associate the metamessage with.
Defaults to None
filter (dict, optional): The key value filter to apply. Defaults to None
page (int): The page of results to return. Defaults to 1
page_size (int): The number of results to return per page. Defaults to 50
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Returns:
list[dict]: List of Message objects
"""
# url = f"{self.base_url}/metamessages?page={page}&size={page_size}&reverse={reverse}" # noqa: E501
# url = f"{self.base_url}/metamessages?page={page}&size={page_size}&reverse={reverse}"
url = f"{self.base_url}/metamessages"
params = {
"page": page,
@ -1061,8 +1139,12 @@ class Session:
through all metamessages for a session in an app
Args:
metamessage_type (str, optional): Optional Metamessage type to filter by
message (Message, optional): Optional Message to filter by
metamessage_type (str, optional): Optional Metamessage type to filter by.
Defaults to None
message (Message, optional): Optional Message to filter by. Defaults to None
filter (dict, optional): Optional key value filter. Defaults to None
reverse (bool): Whether to reverse the order of the results. Defaults to
False
Yields:
Metamessage: The next Metamessage object of the requested query
@ -1131,7 +1213,8 @@ class Session:
Args:
metamessage (Metamessage): The metamessage to update
metadata (dict): The new metadata for the metamessage
metamessage_type (str, optional): The new type of the metamessage
metadata (dict, optional): The new metadata for the metamessage
Returns:
boolean: Whether the metamessage was successfully updated
@ -1149,13 +1232,23 @@ class Session:
return success
def close(self):
"""Closes a session by marking it as inactive"""
"""Closes a session by marking it as inactive. An inactive session can no longer
create new messages"""
url = f"{self.base_url}"
response = self.user.honcho.client.delete(url)
response.raise_for_status()
self._is_active = False
def chat(self, query) -> str:
"""Chat with the dialectic Honcho Agent that asynchonously reasons about users
Args:
query (str): The query to send to the agent
Returns:
str: The response from the agent
"""
url = f"{self.base_url}/chat"
params = {"query": query}
response = self.user.honcho.client.get(url, params=params)
@ -1189,13 +1282,14 @@ class Collection:
def __str__(self):
"""String representation of Collection"""
return f"Collection(id={self.id}, name={self.name}, created_at={self.created_at})" # noqa: E501
return f"Collection(id={self.id}, name={self.name}, created_at={self.created_at})"
def update(self, name: Optional[str] = None, metadata: Optional[dict] = None):
"""Update the name of the collection
"""Update the name of the collection. Atleast one argument is required
Args:
name (str): The new name of the document
name (str, optional): The new name of the document
metadata (dict, optional): The new metadata of the document
Returns:
boolean: Whether the session was successfully updated
@ -1224,7 +1318,7 @@ class Collection:
Args:
content (str): The content of the document
metadata (dict): The metadata of the document
metadata (dict, optional): The metadata of the document
Returns:
Document: The Document object of the added document
@ -1277,14 +1371,17 @@ class Collection:
"""Get all documents for a collection
Args:
filter (dict, optional): The key value filter to apply
page (int, optional): The page of results to return
page_size (int, optional): The number of results to return per page
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to None
Returns:
GetDocumentPage: Page of Document objects
"""
# url = f"{self.base_url}/documents?page={page}&size={page_size}&reverse={reverse}" # noqa: E501
# url = f"{self.base_url}/documents?page={page}&size={page_size}&reverse={reverse}"
url = f"{self.base_url}/documents"
params = {
"page": page,
@ -1305,6 +1402,11 @@ class Collection:
"""Shortcut Generator for get_documents. Generator to iterate through
all documents for a collection in an app
Args:
filter (dict, optional): The key value filter to apply
reverse (bool): Whether to pull from the beginning or end of the list —
latest or earliest. Defaults to None
Yields:
Document: The Document object of the next Document
@ -1358,8 +1460,8 @@ class Collection:
Args:
document (Document): The Document to update
metadata (dict): The metadata of the document
content (str): The content of the document
content (str, optional): The content of the document
metadata (dict, optional): The metadata of the document
Returns:
Document: The newly updated Document

228
sdk/poetry.lock generated
View File

@ -35,6 +35,26 @@ doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphin
test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
trio = ["trio (>=0.23)"]
[[package]]
name = "attrs"
version = "23.2.0"
description = "Classes Without Boilerplate"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"},
{file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"},
]
[package.extras]
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
dev = ["attrs[tests]", "pre-commit"]
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
tests = ["attrs[tests-no-zope]", "zope-interface"]
tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"]
tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"]
[[package]]
name = "babel"
version = "2.14.0"
@ -184,6 +204,21 @@ files = [
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
]
[[package]]
name = "click"
version = "8.1.7"
description = "Composable command line interface toolkit"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.6"
@ -198,64 +233,64 @@ files = [
[[package]]
name = "coverage"
version = "7.4.3"
version = "7.4.4"
description = "Code coverage measurement for Python"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "coverage-7.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8580b827d4746d47294c0e0b92854c85a92c2227927433998f0d3320ae8a71b6"},
{file = "coverage-7.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:718187eeb9849fc6cc23e0d9b092bc2348821c5e1a901c9f8975df0bc785bfd4"},
{file = "coverage-7.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:767b35c3a246bcb55b8044fd3a43b8cd553dd1f9f2c1eeb87a302b1f8daa0524"},
{file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae7f19afe0cce50039e2c782bff379c7e347cba335429678450b8fe81c4ef96d"},
{file = "coverage-7.4.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba3a8aaed13770e970b3df46980cb068d1c24af1a1968b7818b69af8c4347efb"},
{file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:ee866acc0861caebb4f2ab79f0b94dbfbdbfadc19f82e6e9c93930f74e11d7a0"},
{file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:506edb1dd49e13a2d4cac6a5173317b82a23c9d6e8df63efb4f0380de0fbccbc"},
{file = "coverage-7.4.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd6545d97c98a192c5ac995d21c894b581f1fd14cf389be90724d21808b657e2"},
{file = "coverage-7.4.3-cp310-cp310-win32.whl", hash = "sha256:f6a09b360d67e589236a44f0c39218a8efba2593b6abdccc300a8862cffc2f94"},
{file = "coverage-7.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:18d90523ce7553dd0b7e23cbb28865db23cddfd683a38fb224115f7826de78d0"},
{file = "coverage-7.4.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cbbe5e739d45a52f3200a771c6d2c7acf89eb2524890a4a3aa1a7fa0695d2a47"},
{file = "coverage-7.4.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:489763b2d037b164846ebac0cbd368b8a4ca56385c4090807ff9fad817de4113"},
{file = "coverage-7.4.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:451f433ad901b3bb00184d83fd83d135fb682d780b38af7944c9faeecb1e0bfe"},
{file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fcc66e222cf4c719fe7722a403888b1f5e1682d1679bd780e2b26c18bb648cdc"},
{file = "coverage-7.4.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ec74cfef2d985e145baae90d9b1b32f85e1741b04cd967aaf9cfa84c1334f3"},
{file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:abbbd8093c5229c72d4c2926afaee0e6e3140de69d5dcd918b2921f2f0c8baba"},
{file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:35eb581efdacf7b7422af677b92170da4ef34500467381e805944a3201df2079"},
{file = "coverage-7.4.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8249b1c7334be8f8c3abcaaa996e1e4927b0e5a23b65f5bf6cfe3180d8ca7840"},
{file = "coverage-7.4.3-cp311-cp311-win32.whl", hash = "sha256:cf30900aa1ba595312ae41978b95e256e419d8a823af79ce670835409fc02ad3"},
{file = "coverage-7.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:18c7320695c949de11a351742ee001849912fd57e62a706d83dfc1581897fa2e"},
{file = "coverage-7.4.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b51bfc348925e92a9bd9b2e48dad13431b57011fd1038f08316e6bf1df107d10"},
{file = "coverage-7.4.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d6cdecaedea1ea9e033d8adf6a0ab11107b49571bbb9737175444cea6eb72328"},
{file = "coverage-7.4.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b2eccb883368f9e972e216c7b4c7c06cabda925b5f06dde0650281cb7666a30"},
{file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c00cdc8fa4e50e1cc1f941a7f2e3e0f26cb2a1233c9696f26963ff58445bac7"},
{file = "coverage-7.4.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9a4a8dd3dcf4cbd3165737358e4d7dfbd9d59902ad11e3b15eebb6393b0446e"},
{file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:062b0a75d9261e2f9c6d071753f7eef0fc9caf3a2c82d36d76667ba7b6470003"},
{file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ebe7c9e67a2d15fa97b77ea6571ce5e1e1f6b0db71d1d5e96f8d2bf134303c1d"},
{file = "coverage-7.4.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c0a120238dd71c68484f02562f6d446d736adcc6ca0993712289b102705a9a3a"},
{file = "coverage-7.4.3-cp312-cp312-win32.whl", hash = "sha256:37389611ba54fd6d278fde86eb2c013c8e50232e38f5c68235d09d0a3f8aa352"},
{file = "coverage-7.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:d25b937a5d9ffa857d41be042b4238dd61db888533b53bc76dc082cb5a15e914"},
{file = "coverage-7.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:28ca2098939eabab044ad68850aac8f8db6bf0b29bc7f2887d05889b17346454"},
{file = "coverage-7.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:280459f0a03cecbe8800786cdc23067a8fc64c0bd51dc614008d9c36e1659d7e"},
{file = "coverage-7.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c0cdedd3500e0511eac1517bf560149764b7d8e65cb800d8bf1c63ebf39edd2"},
{file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9a9babb9466fe1da12417a4aed923e90124a534736de6201794a3aea9d98484e"},
{file = "coverage-7.4.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dec9de46a33cf2dd87a5254af095a409ea3bf952d85ad339751e7de6d962cde6"},
{file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:16bae383a9cc5abab9bb05c10a3e5a52e0a788325dc9ba8499e821885928968c"},
{file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2c854ce44e1ee31bda4e318af1dbcfc929026d12c5ed030095ad98197eeeaed0"},
{file = "coverage-7.4.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ce8c50520f57ec57aa21a63ea4f325c7b657386b3f02ccaedeccf9ebe27686e1"},
{file = "coverage-7.4.3-cp38-cp38-win32.whl", hash = "sha256:708a3369dcf055c00ddeeaa2b20f0dd1ce664eeabde6623e516c5228b753654f"},
{file = "coverage-7.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:1bf25fbca0c8d121a3e92a2a0555c7e5bc981aee5c3fdaf4bb7809f410f696b9"},
{file = "coverage-7.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b253094dbe1b431d3a4ac2f053b6d7ede2664ac559705a704f621742e034f1f"},
{file = "coverage-7.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77fbfc5720cceac9c200054b9fab50cb2a7d79660609200ab83f5db96162d20c"},
{file = "coverage-7.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6679060424faa9c11808598504c3ab472de4531c571ab2befa32f4971835788e"},
{file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4af154d617c875b52651dd8dd17a31270c495082f3d55f6128e7629658d63765"},
{file = "coverage-7.4.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8640f1fde5e1b8e3439fe482cdc2b0bb6c329f4bb161927c28d2e8879c6029ee"},
{file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:69b9f6f66c0af29642e73a520b6fed25ff9fd69a25975ebe6acb297234eda501"},
{file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0842571634f39016a6c03e9d4aba502be652a6e4455fadb73cd3a3a49173e38f"},
{file = "coverage-7.4.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a78ed23b08e8ab524551f52953a8a05d61c3a760781762aac49f8de6eede8c45"},
{file = "coverage-7.4.3-cp39-cp39-win32.whl", hash = "sha256:c0524de3ff096e15fcbfe8f056fdb4ea0bf497d584454f344d59fce069d3e6e9"},
{file = "coverage-7.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:0209a6369ccce576b43bb227dc8322d8ef9e323d089c6f3f26a597b09cb4d2aa"},
{file = "coverage-7.4.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:7cbde573904625509a3f37b6fecea974e363460b556a627c60dc2f47e2fffa51"},
{file = "coverage-7.4.3.tar.gz", hash = "sha256:276f6077a5c61447a48d133ed13e759c09e62aff0dc84274a68dc18660104d52"},
{file = "coverage-7.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0be5efd5127542ef31f165de269f77560d6cdef525fffa446de6f7e9186cfb2"},
{file = "coverage-7.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ccd341521be3d1b3daeb41960ae94a5e87abe2f46f17224ba5d6f2b8398016cf"},
{file = "coverage-7.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fa497a8ab37784fbb20ab699c246053ac294d13fc7eb40ec007a5043ec91f8"},
{file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b1a93009cb80730c9bca5d6d4665494b725b6e8e157c1cb7f2db5b4b122ea562"},
{file = "coverage-7.4.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:690db6517f09336559dc0b5f55342df62370a48f5469fabf502db2c6d1cffcd2"},
{file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:09c3255458533cb76ef55da8cc49ffab9e33f083739c8bd4f58e79fecfe288f7"},
{file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8ce1415194b4a6bd0cdcc3a1dfbf58b63f910dcb7330fe15bdff542c56949f87"},
{file = "coverage-7.4.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b91cbc4b195444e7e258ba27ac33769c41b94967919f10037e6355e998af255c"},
{file = "coverage-7.4.4-cp310-cp310-win32.whl", hash = "sha256:598825b51b81c808cb6f078dcb972f96af96b078faa47af7dfcdf282835baa8d"},
{file = "coverage-7.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:09ef9199ed6653989ebbcaacc9b62b514bb63ea2f90256e71fea3ed74bd8ff6f"},
{file = "coverage-7.4.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0f9f50e7ef2a71e2fae92774c99170eb8304e3fdf9c8c3c7ae9bab3e7229c5cf"},
{file = "coverage-7.4.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:623512f8ba53c422fcfb2ce68362c97945095b864cda94a92edbaf5994201083"},
{file = "coverage-7.4.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0513b9508b93da4e1716744ef6ebc507aff016ba115ffe8ecff744d1322a7b63"},
{file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40209e141059b9370a2657c9b15607815359ab3ef9918f0196b6fccce8d3230f"},
{file = "coverage-7.4.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a2b2b78c78293782fd3767d53e6474582f62443d0504b1554370bde86cc8227"},
{file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:73bfb9c09951125d06ee473bed216e2c3742f530fc5acc1383883125de76d9cd"},
{file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f384c3cc76aeedce208643697fb3e8437604b512255de6d18dae3f27655a384"},
{file = "coverage-7.4.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54eb8d1bf7cacfbf2a3186019bcf01d11c666bd495ed18717162f7eb1e9dd00b"},
{file = "coverage-7.4.4-cp311-cp311-win32.whl", hash = "sha256:cac99918c7bba15302a2d81f0312c08054a3359eaa1929c7e4b26ebe41e9b286"},
{file = "coverage-7.4.4-cp311-cp311-win_amd64.whl", hash = "sha256:b14706df8b2de49869ae03a5ccbc211f4041750cd4a66f698df89d44f4bd30ec"},
{file = "coverage-7.4.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:201bef2eea65e0e9c56343115ba3814e896afe6d36ffd37bab783261db430f76"},
{file = "coverage-7.4.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:41c9c5f3de16b903b610d09650e5e27adbfa7f500302718c9ffd1c12cf9d6818"},
{file = "coverage-7.4.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d898fe162d26929b5960e4e138651f7427048e72c853607f2b200909794ed978"},
{file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ea79bb50e805cd6ac058dfa3b5c8f6c040cb87fe83de10845857f5535d1db70"},
{file = "coverage-7.4.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce4b94265ca988c3f8e479e741693d143026632672e3ff924f25fab50518dd51"},
{file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:00838a35b882694afda09f85e469c96367daa3f3f2b097d846a7216993d37f4c"},
{file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fdfafb32984684eb03c2d83e1e51f64f0906b11e64482df3c5db936ce3839d48"},
{file = "coverage-7.4.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:69eb372f7e2ece89f14751fbcbe470295d73ed41ecd37ca36ed2eb47512a6ab9"},
{file = "coverage-7.4.4-cp312-cp312-win32.whl", hash = "sha256:137eb07173141545e07403cca94ab625cc1cc6bc4c1e97b6e3846270e7e1fea0"},
{file = "coverage-7.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:d71eec7d83298f1af3326ce0ff1d0ea83c7cb98f72b577097f9083b20bdaf05e"},
{file = "coverage-7.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ae728ff3b5401cc320d792866987e7e7e880e6ebd24433b70a33b643bb0384"},
{file = "coverage-7.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cc4f1358cb0c78edef3ed237ef2c86056206bb8d9140e73b6b89fbcfcbdd40e1"},
{file = "coverage-7.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8130a2aa2acb8788e0b56938786c33c7c98562697bf9f4c7d6e8e5e3a0501e4a"},
{file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cf271892d13e43bc2b51e6908ec9a6a5094a4df1d8af0bfc360088ee6c684409"},
{file = "coverage-7.4.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4cdc86d54b5da0df6d3d3a2f0b710949286094c3a6700c21e9015932b81447e"},
{file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ae71e7ddb7a413dd60052e90528f2f65270aad4b509563af6d03d53e979feafd"},
{file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:38dd60d7bf242c4ed5b38e094baf6401faa114fc09e9e6632374388a404f98e7"},
{file = "coverage-7.4.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa5b1c1bfc28384f1f53b69a023d789f72b2e0ab1b3787aae16992a7ca21056c"},
{file = "coverage-7.4.4-cp38-cp38-win32.whl", hash = "sha256:dfa8fe35a0bb90382837b238fff375de15f0dcdb9ae68ff85f7a63649c98527e"},
{file = "coverage-7.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:b2991665420a803495e0b90a79233c1433d6ed77ef282e8e152a324bbbc5e0c8"},
{file = "coverage-7.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3b799445b9f7ee8bf299cfaed6f5b226c0037b74886a4e11515e569b36fe310d"},
{file = "coverage-7.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b4d33f418f46362995f1e9d4f3a35a1b6322cb959c31d88ae56b0298e1c22357"},
{file = "coverage-7.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aadacf9a2f407a4688d700e4ebab33a7e2e408f2ca04dbf4aef17585389eff3e"},
{file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c95949560050d04d46b919301826525597f07b33beba6187d04fa64d47ac82e"},
{file = "coverage-7.4.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff7687ca3d7028d8a5f0ebae95a6e4827c5616b31a4ee1192bdfde697db110d4"},
{file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fc1de20b2d4a061b3df27ab9b7c7111e9a710f10dc2b84d33a4ab25065994ec"},
{file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c74880fc64d4958159fbd537a091d2a585448a8f8508bf248d72112723974cbd"},
{file = "coverage-7.4.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:742a76a12aa45b44d236815d282b03cfb1de3b4323f3e4ec933acfae08e54ade"},
{file = "coverage-7.4.4-cp39-cp39-win32.whl", hash = "sha256:d89d7b2974cae412400e88f35d86af72208e1ede1a541954af5d944a8ba46c57"},
{file = "coverage-7.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:9ca28a302acb19b6af89e90f33ee3e1906961f94b54ea37de6737b7ca9d8827c"},
{file = "coverage-7.4.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:b2c5edc4ac10a7ef6605a966c58929ec6c1bd0917fb8c15cb3363f65aa40e677"},
{file = "coverage-7.4.4.tar.gz", hash = "sha256:c901df83d097649e257e803be22592aedfd5182f07b3cc87d640bbb9afd50f49"},
]
[package.extras]
@ -391,14 +426,14 @@ files = [
[[package]]
name = "importlib-metadata"
version = "7.0.2"
version = "7.1.0"
description = "Read metadata from Python packages"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "importlib_metadata-7.0.2-py3-none-any.whl", hash = "sha256:f4bc4c0c070c490abf4ce96d715f68e95923320370efb66143df00199bb6c100"},
{file = "importlib_metadata-7.0.2.tar.gz", hash = "sha256:198f568f3230878cb1b44fbd7975f87906c22336dba2e4a7f05278c281fbd792"},
{file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"},
{file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"},
]
[package.dependencies]
@ -407,7 +442,7 @@ zipp = ">=0.5"
[package.extras]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
perf = ["ipython"]
testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
[[package]]
name = "iniconfig"
@ -421,6 +456,32 @@ files = [
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
]
[[package]]
name = "interrogate"
version = "1.5.0"
description = "Interrogate a codebase for docstring coverage."
category = "dev"
optional = false
python-versions = ">=3.6"
files = [
{file = "interrogate-1.5.0-py3-none-any.whl", hash = "sha256:a4ccc5cbd727c74acc98dee6f5e79ef264c0bcfa66b68d4e123069b2af89091a"},
{file = "interrogate-1.5.0.tar.gz", hash = "sha256:b6f325f0aa84ac3ac6779d8708264d366102226c5af7d69058cecffcff7a6d6c"},
]
[package.dependencies]
attrs = "*"
click = ">=7.1"
colorama = "*"
py = "*"
tabulate = "*"
toml = "*"
[package.extras]
dev = ["cairosvg", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "sphinx", "sphinx-autobuild", "wheel"]
docs = ["sphinx", "sphinx-autobuild"]
png = ["cairosvg"]
tests = ["pytest", "pytest-cov", "pytest-mock"]
[[package]]
name = "jinja2"
version = "3.1.3"
@ -537,6 +598,18 @@ files = [
dev = ["pre-commit", "tox"]
testing = ["pytest", "pytest-benchmark"]
[[package]]
name = "py"
version = "1.11.0"
description = "library with cross-python path, ini-parsing, io, code, log facilities"
category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
files = [
{file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
{file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
]
[[package]]
name = "pygments"
version = "2.17.2"
@ -578,14 +651,14 @@ testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "no
[[package]]
name = "pytest-asyncio"
version = "0.23.5.post1"
version = "0.23.6"
description = "Pytest support for asyncio"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "pytest-asyncio-0.23.5.post1.tar.gz", hash = "sha256:b9a8806bea78c21276bc34321bbf234ba1b2ea5b30d9f0ce0f2dea45e4685813"},
{file = "pytest_asyncio-0.23.5.post1-py3-none-any.whl", hash = "sha256:30f54d27774e79ac409778889880242b0403d09cabd65b727ce90fe92dd5d80e"},
{file = "pytest-asyncio-0.23.6.tar.gz", hash = "sha256:ffe523a89c1c222598c76856e76852b787504ddb72dd5d9b6617ffa8aa2cde5f"},
{file = "pytest_asyncio-0.23.6-py3-none-any.whl", hash = "sha256:68516fdd1018ac57b846c9846b954f0393b26f094764a28c955eabb0536a4e8a"},
]
[package.dependencies]
@ -807,6 +880,33 @@ lint = ["docutils-stubs", "flake8", "mypy"]
standalone = ["Sphinx (>=5)"]
test = ["pytest"]
[[package]]
name = "tabulate"
version = "0.9.0"
description = "Pretty-print tabular data"
category = "dev"
optional = false
python-versions = ">=3.7"
files = [
{file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"},
{file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"},
]
[package.extras]
widechars = ["wcwidth"]
[[package]]
name = "toml"
version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
[[package]]
name = "tomli"
version = "2.0.1"
@ -851,14 +951,14 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "zipp"
version = "3.18.0"
version = "3.18.1"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "dev"
optional = false
python-versions = ">=3.8"
files = [
{file = "zipp-3.18.0-py3-none-any.whl", hash = "sha256:c1bb803ed69d2cce2373152797064f7e79bc43f0a3748eb494096a867e0ebf79"},
{file = "zipp-3.18.0.tar.gz", hash = "sha256:df8d042b02765029a09b157efd8e820451045890acc30f8e37dd2f94a060221f"},
{file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"},
{file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"},
]
[package.extras]
@ -868,4 +968,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata]
lock-version = "2.0"
python-versions = "^3.9"
content-hash = "bf46c7a976758553f5f41e0d73766388e5b93ccf383d7870106286c5c570cedf"
content-hash = "3265d992168555f7d9d60f6f03c18dc515b32de3b975290158b086d82247fefc"

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "honcho-ai"
version = "0.0.5"
version = "0.0.6"
description = "Python Client SDK for Honcho"
authors = ["Plastic Labs <hello@plasticlabs.ai>"]
license = "AGPL-3.0"
@ -15,6 +15,7 @@ httpx = "^0.26.0"
pytest = "^7.4.4"
pytest-asyncio = "^0.23.4"
coverage = "^7.4.3"
interrogate = "^1.5.0"
[tool.poetry.group.docs.dependencies]
sphinx = "^7.2.6"
@ -23,20 +24,19 @@ furo = "^2024.1.29"
[tool.ruff.lint]
# from https://docs.astral.sh/ruff/linter/#rule-selection example
select = [
# pycodestyle
"E",
# Pyflakes
"F",
# pyupgrade
"UP",
# flake8-bugbear
"B",
# flake8-simplify
"SIM",
# isort
"I",
"E", # pycodestyle
"F", # Pyflakes
"UP", # pyupgrade
"B", # flake8-bugbear
"SIM", # flake8-simplify
"S", # flake8-bandit
"I", # isort
"RUF", # ruff
]
ignore = [
"UP007", # https://docs.astral.sh/ruff/rules/non-pep604-annotation/
"E501", # line too long
]
ignore = ["UP007"]
[build-system]

View File

@ -251,9 +251,7 @@ def test_paginated_messages():
created_session.create_message(is_user=False, content="Hi")
page_size = 7
get_message_response = created_session.get_messages(
page=1, page_size=page_size
)
get_message_response = created_session.get_messages(page=1, page_size=page_size)
assert get_message_response is not None
assert isinstance(get_message_response, GetMessagePage)
@ -448,9 +446,7 @@ def test_collection_query():
collection = user.create_collection(col_name)
# Add documents
doc1 = collection.create_document(
content="The user loves puppies", metadata={}
)
doc1 = collection.create_document(content="The user loves puppies", metadata={})
doc2 = collection.create_document(content="The user owns a dog", metadata={})
doc3 = collection.create_document(content="The user is a doctor", metadata={})