From c5bcb20514515388d8d569fbb54c65946b9840fc Mon Sep 17 00:00:00 2001 From: antopiahk Date: Mon, 15 Apr 2024 16:35:13 +0200 Subject: [PATCH 01/76] finetuning commenting prompt --- apps/rest/api/poetry.lock | 50 ++++++++++++++++++++++++- apps/rest/api/pyproject.toml | 1 + apps/rest/api/src/prompts/commenting.py | 2 + apps/rest/api/src/upwork_worker.py | 5 +++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 apps/rest/api/src/upwork_worker.py diff --git a/apps/rest/api/poetry.lock b/apps/rest/api/poetry.lock index 34084297..eaade821 100644 --- a/apps/rest/api/poetry.lock +++ b/apps/rest/api/poetry.lock @@ -1335,6 +1335,22 @@ files = [ {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, ] +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + [[package]] name = "openai" version = "1.16.2" @@ -1855,6 +1871,20 @@ files = [ [package.extras] cli = ["click (>=5.0)"] +[[package]] +name = "python-upwork-oauth2" +version = "3.1.0" +description = "Python bindings for Upwork API (OAuth2)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-upwork-oauth2-3.1.0.tar.gz", hash = "sha256:97e6fd2090b600f063c2ee924f4d71c6c13c0c5400d751be4d9613820fdd6b84"}, + {file = "python_upwork_oauth2-3.1.0-py3-none-any.whl", hash = "sha256:0f778f4dc6eee59da10a7bff980025508c3636eba71f0ca61a8e328f3a308877"}, +] + +[package.dependencies] +requests-oauthlib = ">=1.3.0" + [[package]] name = "pytz" version = "2024.1" @@ -2098,6 +2128,24 @@ urllib3 = ">=1.21.1,<3" socks = ["PySocks (>=1.5.6,!=1.5.7)"] use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +[[package]] +name = "requests-oauthlib" +version = "2.0.0" +description = "OAuthlib authentication support for Requests." +optional = false +python-versions = ">=3.4" +files = [ + {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, + {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, +] + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + [[package]] name = "selenium" version = "4.19.0" @@ -2765,4 +2813,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.13" -content-hash = "398f60cab46bede82a8595c0028819fe707aa83ff26ac1997af5f4feebc866df" +content-hash = "9cb7ae5fc1426e07b7938da4118d665fc3549e57acf28d3deb21b1121654ce51" diff --git a/apps/rest/api/pyproject.toml b/apps/rest/api/pyproject.toml index 719672b2..94855306 100644 --- a/apps/rest/api/pyproject.toml +++ b/apps/rest/api/pyproject.toml @@ -34,6 +34,7 @@ mail = "^2.1.0" python-dotenv = "^1.0.1" diskcache = "^5.6.3" pydantic = "^2.6.4" +python-upwork-oauth2 = "^3.1.0" [tool.poetry.group.dev.dependencies] mypy = "^1.7.0" diff --git a/apps/rest/api/src/prompts/commenting.py b/apps/rest/api/src/prompts/commenting.py index dc7f70d1..fb942413 100644 --- a/apps/rest/api/src/prompts/commenting.py +++ b/apps/rest/api/src/prompts/commenting.py @@ -29,6 +29,8 @@ - Keep the comment concise and to the point. - Don't mention about cost effectiveness of Futino. - Mention how we gaurantee our dedication through our services for equity model. +- Do not mention how much equity we are willing to take. +- You may mention that we sometimes take equity if the post is a startup. - Do not use more than 50 words. """ diff --git a/apps/rest/api/src/upwork_worker.py b/apps/rest/api/src/upwork_worker.py new file mode 100644 index 00000000..45ed5823 --- /dev/null +++ b/apps/rest/api/src/upwork_worker.py @@ -0,0 +1,5 @@ +import upwork +from upwork.routers.jobs import search +client = upwork.Client(config) +params = {'q': 'python', 'title': 'Web developer'} +search.Api(client).find(params) From cc0ae9d529a4701a8944ee4c7d84349052d91c80 Mon Sep 17 00:00:00 2001 From: antopiahk Date: Mon, 15 Apr 2024 20:56:48 +0200 Subject: [PATCH 02/76] fine tuning the bot and adding uniqueness checking in db.py --- apps/rest/api/src/__init__.py | 2 ++ apps/rest/api/src/comment_bot.py | 2 +- apps/rest/api/src/interfaces/db.py | 17 +++++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/apps/rest/api/src/__init__.py b/apps/rest/api/src/__init__.py index 735ea8d6..fdf21dc9 100644 --- a/apps/rest/api/src/__init__.py +++ b/apps/rest/api/src/__init__.py @@ -15,6 +15,7 @@ PublishCommentRequest, GenerateCommentRequest, FalseLead, + Lead ) from .reddit_worker import RedditStreamWorker @@ -75,6 +76,7 @@ def redirect_to_docs() -> RedirectResponse: @app.get("/test") def test(): print("TEST") + db.post_lead(Lead(id=uuid4(), submission_id=uuid4(), reddit_id="test", prospect_username="test", source="test", last_event="test", status="test", data={"test": "test"})) @app.post("/start") diff --git a/apps/rest/api/src/comment_bot.py b/apps/rest/api/src/comment_bot.py index 5ffd7395..6cfbdf33 100644 --- a/apps/rest/api/src/comment_bot.py +++ b/apps/rest/api/src/comment_bot.py @@ -57,7 +57,7 @@ def publish_comment( id, text: str, username: str, password: str ) -> PublishCommentResponse | None: lead = db.get_lead(id) - if lead is None: + if lead is None or lead.status == "subscriber": logging.error(f"Lead with id {id} not found") return None diff --git a/apps/rest/api/src/interfaces/db.py b/apps/rest/api/src/interfaces/db.py index ce0ffbfb..44dcb879 100644 --- a/apps/rest/api/src/interfaces/db.py +++ b/apps/rest/api/src/interfaces/db.py @@ -71,9 +71,16 @@ def post_lead(lead: Lead) -> None: """ supabase: Client = create_client(url, key) logger.debug(f"Posting lead: {lead}") + + # Check if lead already exists (temporary until supabase-py supports onConflict) + existing_lead = supabase.table("leads").select("*").eq("prospect_username", lead.prospect_username).execute() + + if existing_lead: + return + supabase.table("leads").insert( - json.loads(json.dumps(lead.model_dump(), default=str)) - ).execute() + json.loads(json.dumps(lead.dict(), default=str)) + ).execute() def update_lead( @@ -125,6 +132,12 @@ def post_evaluated_submission(saved_submission: SavedSubmission) -> None: supabase: Client = create_client(url, key) logger.debug(f"Posting submission: {saved_submission}") + # Check if submission already exists (temporary until supabase-py supports onConflict) + existing_submission = supabase.table("evaluated_submissions").select("*").eq("body", saved_submission.body).execute() + + if existing_submission: + return + supabase.table("evaluated_submissions").insert( json.loads(json.dumps(saved_submission.model_dump(), default=str)) ).execute() From b91fb1382df5b2ccc0b098343fee4b7aa4ed324c Mon Sep 17 00:00:00 2001 From: antopiahk Date: Sat, 20 Apr 2024 14:47:48 +0200 Subject: [PATCH 03/76] fixing submissions and leads not getting submitted to db --- apps/rest/api/src/__init__.py | 27 ++++-- apps/rest/api/src/comment_bot.py | 2 +- apps/rest/api/src/interfaces/db.py | 4 +- .../api/src/prompts/bad_proposal_examples.md | 0 apps/rest/api/src/prompts/commenting.py | 2 +- .../api/src/prompts/good_proposal_examples.md | 74 ++++++++++++++ apps/rest/api/src/prompts/upwork_proposals.py | 97 +++++++++++++++++++ apps/rest/api/src/reddit_worker.py | 49 +++++----- apps/rest/api/src/relevance_bot.py | 23 +---- apps/rest/api/src/upwork_worker.py | 46 ++++++++- 10 files changed, 268 insertions(+), 56 deletions(-) create mode 100644 apps/rest/api/src/prompts/bad_proposal_examples.md create mode 100644 apps/rest/api/src/prompts/good_proposal_examples.md create mode 100644 apps/rest/api/src/prompts/upwork_proposals.py diff --git a/apps/rest/api/src/__init__.py b/apps/rest/api/src/__init__.py index fdf21dc9..ce75d20e 100644 --- a/apps/rest/api/src/__init__.py +++ b/apps/rest/api/src/__init__.py @@ -11,13 +11,9 @@ from .relevance_bot import evaluate_relevance from .interfaces import db from . import comment_bot -from .models import ( - PublishCommentRequest, - GenerateCommentRequest, - FalseLead, - Lead -) +from .models import PublishCommentRequest, GenerateCommentRequest, FalseLead, Lead from .reddit_worker import RedditStreamWorker +from . import upwork_worker from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware @@ -76,7 +72,18 @@ def redirect_to_docs() -> RedirectResponse: @app.get("/test") def test(): print("TEST") - db.post_lead(Lead(id=uuid4(), submission_id=uuid4(), reddit_id="test", prospect_username="test", source="test", last_event="test", status="test", data={"test": "test"})) + db.post_lead( + Lead( + id=uuid4(), + submission_id=uuid4(), + reddit_id="test", + prospect_username="test", + source="test", + last_event="test", + status="test", + data={"test": "test"}, + ) + ) @app.post("/start") @@ -148,3 +155,9 @@ def publish_comment(publish_request: PublishCommentRequest): raise HTTPException(404, "lead not found") return updated_content + + +@app.get("/generate-proposal") +def generate_proposal(post: str): + proposal = upwork_worker.generate_proposal(post) + return proposal diff --git a/apps/rest/api/src/comment_bot.py b/apps/rest/api/src/comment_bot.py index 6cfbdf33..f67f74c0 100644 --- a/apps/rest/api/src/comment_bot.py +++ b/apps/rest/api/src/comment_bot.py @@ -17,7 +17,7 @@ def generate_comment(title: str, selftext: str, instructions: str = "") -> str: - llm = ChatOpenAI(model="gpt-4-turbo-preview", temperature=0.3) + llm = ChatOpenAI(model="gpt-4-turbo", temperature=0.3) # Set up a parser + inject instructions into the prompt template. parser = JsonOutputParser(pydantic_object=RedditComment) diff --git a/apps/rest/api/src/interfaces/db.py b/apps/rest/api/src/interfaces/db.py index 44dcb879..4dfcf325 100644 --- a/apps/rest/api/src/interfaces/db.py +++ b/apps/rest/api/src/interfaces/db.py @@ -75,7 +75,7 @@ def post_lead(lead: Lead) -> None: # Check if lead already exists (temporary until supabase-py supports onConflict) existing_lead = supabase.table("leads").select("*").eq("prospect_username", lead.prospect_username).execute() - if existing_lead: + if len(existing_lead.data) > 0: return supabase.table("leads").insert( @@ -135,7 +135,7 @@ def post_evaluated_submission(saved_submission: SavedSubmission) -> None: # Check if submission already exists (temporary until supabase-py supports onConflict) existing_submission = supabase.table("evaluated_submissions").select("*").eq("body", saved_submission.body).execute() - if existing_submission: + if len(existing_submission.data) > 0: return supabase.table("evaluated_submissions").insert( diff --git a/apps/rest/api/src/prompts/bad_proposal_examples.md b/apps/rest/api/src/prompts/bad_proposal_examples.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/rest/api/src/prompts/commenting.py b/apps/rest/api/src/prompts/commenting.py index fb942413..7c7e42a7 100644 --- a/apps/rest/api/src/prompts/commenting.py +++ b/apps/rest/api/src/prompts/commenting.py @@ -14,7 +14,7 @@ ) as file: good_examples = file.read() -with open(os.path.join(script_dir, "bad_examples.md"), "r", encoding="utf-8") as file: +with open(os.path.join(script_dir, "bad_comment_examples.md"), "r", encoding="utf-8") as file: bad_examples = file.read() purpose = """ diff --git a/apps/rest/api/src/prompts/good_proposal_examples.md b/apps/rest/api/src/prompts/good_proposal_examples.md new file mode 100644 index 00000000..48cf4fdd --- /dev/null +++ b/apps/rest/api/src/prompts/good_proposal_examples.md @@ -0,0 +1,74 @@ +Upwork proposal example #1: + +Hi, + +I would love to be your freelance writer and help you execute your website content strategy. + +I have 5 years of experience writing content for websites, including Forbes.com, Buzzfeed.com, and more. Below, I’ve linked two samples that showcase my writing ability in a similar niche to your brand. As you can see, I understand your audience and know how to write compelling articles to get your website visitors to purchase your products. + +I can complete 1,000-word articles with a 2-day turnaround time. Would that work for your needs? Let me know if my writing meets your expectations, and we can set up a time to talk about your project in more detail. + +Example Website Content #1 (link) + +Example Website Content #2 (link) + +Thanks, + +John Doe + +--- + +Upwork proposal example #2: + +Hello, + +If you need high-quality articles written for your website at an affordable price, I am the right writer for you! My goal with every content piece is to lead your website’s visitors along their buyer’s journey—hopefully ending with a purchase on your website. + +As you can see in my Upwork profile, I have three years of experience writing content for websites just like yours. You can even find some of my published work on Inc.com, Marketwatch.com, and Hubspot.com. Linked below are two writing samples that demonstrate my ability to craft excellent blog content for B2B e-commerce websites. + +- Example Website Article #1 + +- Example Website Article #2 + +My current turnaround time for 1,000-word articles is two days. If my work aligns with what you need, can we set up a time to discuss your goals for this project? + +Best regards, + +Jessica Doe + +--- + +Upwork proposal example #3: + +Hello Nicki, + +I’m a detail-driven writer who turns ideas into valuable website content for clients just like you. I enjoy writing for various topics and niches (business, lifestyle, travel, personal blogs, etc.). You can find examples of my past writing work on my Upwork profile, plus (insert link here) and (insert link here). + +My experience has given me a deep understanding of SEO writing and strong digital marketing strategies to help drive traffic to your site. I excel in writing all types of content such as blogs, press releases, product descriptions, and more. + +My rate is $50 for projects like this one, and I can have a finished piece of writing delivered to you this week if you’re interested. Let’s talk! + +– Anna G. + +--- + +UpWork proposal sample for web developer + +Hello, + +My name is Vijay Reddy and I’d love to help you launch your new website. I am a web developer, who has worked on over 40 different websites. I studied web development for 4 years and have worked with startups to build their web presence over the past 3 years. + +Below are a few links for websites I have built: + +Sample link 1 +Sample link 2 +Sample link 3 +Sample link 4 + +If you are looking for a different type of website than the ones above, I’d be happy to tailor it to your needs. I understand you are a new company and I am happy to be flexible to make sure we work with your timeline. Could you tell me more about your target market and audience? If you are unsure, I can brainstorm with you on this point. + +Do let me know if you have any questions and I am excited to have the possibility to work on this project! + +Best regards, + +Vijay Reddy diff --git a/apps/rest/api/src/prompts/upwork_proposals.py b/apps/rest/api/src/prompts/upwork_proposals.py new file mode 100644 index 00000000..ef27ff08 --- /dev/null +++ b/apps/rest/api/src/prompts/upwork_proposals.py @@ -0,0 +1,97 @@ +from gptrim import trim +import os + +# Get the directory of the current script file +script_dir = os.path.dirname(os.path.realpath(__file__)) + +with open( + os.path.join(script_dir, "startino_business_plan.md"), "r", encoding="utf-8" +) as file: + company_context = file.read() + +with open( + os.path.join(script_dir, "good_proposal_examples.md"), "r", encoding="utf-8" +) as file: + good_examples = file.read() + +with open( + os.path.join(script_dir, "bad_proposal_examples.md"), "r", encoding="utf-8" +) as file: + bad_examples = file.read() + +purpose = """ +Write a proposal for a job listing in order to close the client. +""" + +context = f""" +{company_context} +""" + +guidance = """ +## Output the proposal in the following format +``` +PROPOSAL +Dear Startup Team, I am .... +``` + +## Job listing format +``` +[Title] +Posted [x] days ago +[Location] + +[Description] +``` +When writing, remember that you are writing on behalf of Futino. + +**Effective Strategies for Crafting Winning Upwork Proposals** + +**Introduction to Upwork Proposals** +Upwork, a leading global freelancing platform, offers numerous opportunities for freelancers to connect with clients and secure freelance work. A crucial element in this process is the Upwork proposal—comparable to a cover letter—that serves as your first interaction with a potential client. This proposal allows you to highlight your suitability for the project, demonstrate your understanding of the client’s needs, and outline how you plan to address their specific requirements. + +**The Role of Upwork Proposals** +Proposals on Upwork are more than just introductory messages; they are strategic tools designed to capture the client’s attention and differentiate you from the competition. Given the sheer volume of job postings and applicants on Upwork, your proposal must be succinct yet compelling, ensuring it conveys your understanding of the project and your ability to deliver results efficiently. + +**Crafting a Standout Upwork Proposal** +1. **Start Strong:** Begin with a personalized greeting that leverages any client-specific insights you can glean from their Upwork profile or feedback. Addressing the client by name, for instance, can make your proposal more engaging and personal. +2. **Demonstrate Understanding:** Quickly affirm your grasp of the client’s main challenges and goals. This shows you’ve thoroughly read the project description and are prepared to address their needs. +3. **Present Your Strategy:** Clearly outline your approach to the project. Describe the steps you will take, the methodology you intend to employ, and the timeline you anticipate. This part should reassure the client of your structured and thoughtful process in tackling their project. +4. **Highlight Relevant Experience:** Include brief examples or links to similar work you’ve done in the past. This is crucial for building credibility and trust, showing the client that you have successfully handled similar challenges. +5. **Conclude with a Strong Closing:** Summarize why you are the ideal candidate for the project, touching on your understanding of the project, your relevant experience, and your readiness to begin immediately. Make sure this summary is tailored to the specifics of the job posting. + +**Additional Tips for Enhancing Your Proposal** +- **Conciseness is Key:** Keep your proposal concise and to the point. Avoid lengthy descriptions; instead, focus on brevity and relevance to the client’s needs. +- **Add Personal Touches:** Where appropriate, include a personal touch or a unique element, such as a video introduction linked in your proposal, to make your submission stand out. +- **Continuous Improvement:** Always seek feedback and refine your approach. Experiment with different styles and structures to discover what resonates best with clients on Upwork. + +""" + +examples = f""" +Here is a list of good examples and bad examples that +you can use to guide your response. + +GOOD EXAMPLES: +{good_examples if good_examples else "NONE"} +BAD EXAMPLES: +{bad_examples if bad_examples else "NONE"} +""" + +roleplay = """ +Imagine you are an experienced virtual assistant who is helping the company find +clients on upwork by writing compelling proposals for the job listings. +""" + +generate_proposal_prompt = trim( + f""" + # INSTRUCTIONS + {roleplay} + # PURPOSE + {purpose} + # GUIDANCE + {guidance} + # CONTEXT + {context} + # EXAMPLES + {examples} +""" +) diff --git a/apps/rest/api/src/reddit_worker.py b/apps/rest/api/src/reddit_worker.py index 20282fc4..f2dd35a7 100644 --- a/apps/rest/api/src/reddit_worker.py +++ b/apps/rest/api/src/reddit_worker.py @@ -4,6 +4,7 @@ from dotenv import load_dotenv from urllib.parse import quote_plus import diskcache as dc +import logging from pathlib import Path @@ -34,28 +35,32 @@ def __init__(self, subreddit_names: str, username: str, password: str): def start(self): self._running = True while self._running: - if not REDDIT_USERNAME or not REDDIT_PASSWORD: - raise TypeError("couldnt find username or password in env vars") - - for submission in self.subreddits.stream.submissions(pause_after=-1): - if submission is None: - break - # Skip if not a submission (for typing) - if not isinstance(submission, Submission): - continue - - # TODO: filter by kewords - - # Avoid repeating posts using caching - is_cached = cache.get(submission.id) - if is_cached: - continue - - # Use LLMs to see if submission is relevant (expensive part) - evaluated_submission = evaluate_relevance(submission, filter=True) - - # Save to db and cache - update_db_with_submission(evaluated_submission) + try: + if not REDDIT_USERNAME or not REDDIT_PASSWORD: + raise TypeError("couldnt find username or password in env vars") + + for submission in self.subreddits.stream.submissions(pause_after=-1): + if submission is None: + break + # Skip if not a submission (for typing) + if not isinstance(submission, Submission): + continue + + # TODO: filter by kewords + + # Avoid repeating posts using caching + is_cached = cache.get(submission.id) + if is_cached: + continue + + # Use LLMs to see if submission is relevant (expensive part) + evaluated_submission = evaluate_relevance(submission, filter=True) + + # Save to db and cache + update_db_with_submission(evaluated_submission) + cache.set(submission.id, submission.id) + except Exception as e: + logging.error(f"Error when evalauting submission. Error: {e} \n Submission: {submission}") cache.set(submission.id, submission.id) def stop(self): diff --git a/apps/rest/api/src/relevance_bot.py b/apps/rest/api/src/relevance_bot.py index 80f378f3..dc4d59c3 100644 --- a/apps/rest/api/src/relevance_bot.py +++ b/apps/rest/api/src/relevance_bot.py @@ -26,8 +26,6 @@ def create_chain(model: str): """ Creates a processing chain for evaluating the relevance of a submission using a specified language model. - The chain is composed of a prompt template, a language model, and a parser to interpret the model's output as a Pydantic object. - Parameters: - model (str): The name of the language model to be used for generating responses. @@ -74,11 +72,11 @@ def invoke_chain(chain, submission: Submission) -> tuple[RelevanceResult, float] return result, cb.total_cost except Exception as e: print(f"An error occurred while invoke_chain: {e}") - time.sleep(10) # Wait for 10 seconds before trying again + time.sleep(2) # Wait for 10 seconds before trying again raise RuntimeError( - "Failed to invoke chain after 3 attempts. Most likely no more credits left or usage limit has been reached." -) + "Failed to invoke chain after 3 attempts. Most likely no more credits left or usage limit has been reached." + ) def summarize_submission(submission: Submission) -> Submission: @@ -308,17 +306,6 @@ def evaluate_relevance(submission: Submission, filter: bool) -> EvaluatedSubmiss if filter: questions = [ - FilterQuestion( - question="Is the author himself a technical person? is/was he a programmer? is/was he a software developer?", - reject_on=True, - ), - FilterQuestion( - question="Has the project already started development?", reject_on=True - ), - FilterQuestion( - question="Is the author currently engaged in job searching activities and promoting their technical expertise?", - reject_on=True, - ), FilterQuestion( question="Is the author starting a non digital business? Like a bakery, garden business, salon, etc.", reject_on=True, @@ -336,9 +323,9 @@ def evaluate_relevance(submission: Submission, filter: bool) -> EvaluatedSubmiss submission=submission, is_relevant=False, cost=cost, reason=source ) - evalualuated_submission = calculate_relevance("gpt-4-turbo-preview", 1, submission) + evalualuated_submission = calculate_relevance("gpt-4-turbo", 1, submission) log_relevance_calculation( - "gpt-4-turbo-preview", + "gpt-4-turbo", submission, evalualuated_submission.is_relevant, evalualuated_submission.cost, diff --git a/apps/rest/api/src/upwork_worker.py b/apps/rest/api/src/upwork_worker.py index 45ed5823..8bfe2fd7 100644 --- a/apps/rest/api/src/upwork_worker.py +++ b/apps/rest/api/src/upwork_worker.py @@ -1,5 +1,41 @@ -import upwork -from upwork.routers.jobs import search -client = upwork.Client(config) -params = {'q': 'python', 'title': 'Web developer'} -search.Api(client).find(params) +import time +from gptrim import trim +from praw.models import Submission +from langchain_openai import ChatOpenAI +from langchain_core.prompts import PromptTemplate +from langchain_core.output_parsers import JsonOutputParser, PydanticOutputParser +from langchain_community.callbacks import get_openai_callback +from langchain_core.messages import AIMessage +from .prompts.upwork_proposals import generate_proposal_prompt + + +def generate_proposal(post: str) -> str: + """ + Generate a proposal for a job listing on Upwork + """ + + cost = 0 + + llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) + + template = """ + + {generate_proposal_prompt} + + + # Job Listing + {post} + """ + + prompt = PromptTemplate( + template=template, + input_variables=["generate_proposal_prompt", "post"], + ) + + chain = prompt | llm + + result = chain.invoke( + {"generate_proposal_prompt": generate_proposal_prompt, "post": post} + ) + + return str(result.content) From 9f615854d9b1f021921d7ba42eb6dd2adade01fb Mon Sep 17 00:00:00 2001 From: antopiahk Date: Mon, 29 Apr 2024 19:30:30 +0700 Subject: [PATCH 04/76] fixed db checking for existing leads --- apps/rest/api/src/comment_bot.py | 1 + apps/rest/api/src/interfaces/db.py | 44 +++++++++++++++++++++++++----- apps/rest/api/src/relevance_bot.py | 8 ++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/apps/rest/api/src/comment_bot.py b/apps/rest/api/src/comment_bot.py index f67f74c0..d230f984 100644 --- a/apps/rest/api/src/comment_bot.py +++ b/apps/rest/api/src/comment_bot.py @@ -57,6 +57,7 @@ def publish_comment( id, text: str, username: str, password: str ) -> PublishCommentResponse | None: lead = db.get_lead(id) + print(lead) if lead is None or lead.status == "subscriber": logging.error(f"Lead with id {id} not found") return None diff --git a/apps/rest/api/src/interfaces/db.py b/apps/rest/api/src/interfaces/db.py index 4dfcf325..3d87613a 100644 --- a/apps/rest/api/src/interfaces/db.py +++ b/apps/rest/api/src/interfaces/db.py @@ -73,14 +73,19 @@ def post_lead(lead: Lead) -> None: logger.debug(f"Posting lead: {lead}") # Check if lead already exists (temporary until supabase-py supports onConflict) - existing_lead = supabase.table("leads").select("*").eq("prospect_username", lead.prospect_username).execute() + existing_lead = ( + supabase.table("leads") + .select("*") + .eq("prospect_username", lead.prospect_username) + .execute() + ) if len(existing_lead.data) > 0: return - + supabase.table("leads").insert( - json.loads(json.dumps(lead.dict(), default=str)) - ).execute() + json.loads(json.dumps(lead.dict(), default=str)) + ).execute() def update_lead( @@ -90,8 +95,28 @@ def update_lead( Update a lead in the database. """ supabase: Client = create_client(url, key) - # Create a dictionary with only non-empty values - data = {k: v for k, v in {"status": status, "last_event": last_event}.items() if v} + + if status is "subscriber": + last_contacted_at = datetime.now() + # Create a dictionary with only non-empty values + data = { + k: v + for k, v in { + "status": status, + "last_event": last_event, + "last_contacted_at": str(last_contacted_at), + }.items() + if v + } + else: + data = { + k: v + for k, v in { + "status": status, + "last_event": last_event, + }.items() + if v + } logger.debug(f"Updating lead with data: {data}") response = supabase.table("leads").update(data).eq("id", str(id)).execute() @@ -133,7 +158,12 @@ def post_evaluated_submission(saved_submission: SavedSubmission) -> None: logger.debug(f"Posting submission: {saved_submission}") # Check if submission already exists (temporary until supabase-py supports onConflict) - existing_submission = supabase.table("evaluated_submissions").select("*").eq("body", saved_submission.body).execute() + existing_submission = ( + supabase.table("evaluated_submissions") + .select("*") + .eq("body", saved_submission.body) + .execute() + ) if len(existing_submission.data) > 0: return diff --git a/apps/rest/api/src/relevance_bot.py b/apps/rest/api/src/relevance_bot.py index dc4d59c3..1ce57878 100644 --- a/apps/rest/api/src/relevance_bot.py +++ b/apps/rest/api/src/relevance_bot.py @@ -306,6 +306,14 @@ def evaluate_relevance(submission: Submission, filter: bool) -> EvaluatedSubmiss if filter: questions = [ + FilterQuestion( + question="Is the author himself an IT person? is/was he a programmer? is/was he a software developer?", + reject_on=True, + ), + FilterQuestion( + question="Is the author currently engaged in job searching activities and promoting their technical expertise?", + reject_on=True, + ), FilterQuestion( question="Is the author starting a non digital business? Like a bakery, garden business, salon, etc.", reject_on=True, From d80539d3a5f3ed9131ebfcbd6fe453fa1f6d95da Mon Sep 17 00:00:00 2001 From: antopiahk Date: Fri, 3 May 2024 07:45:48 +0000 Subject: [PATCH 05/76] nix shell removing poetry --- apps/rest/api/poetry.lock | 2816 ------------------------------------- apps/rest/api/shell.nix | 1 - 2 files changed, 2817 deletions(-) delete mode 100644 apps/rest/api/poetry.lock diff --git a/apps/rest/api/poetry.lock b/apps/rest/api/poetry.lock deleted file mode 100644 index eaade821..00000000 --- a/apps/rest/api/poetry.lock +++ /dev/null @@ -1,2816 +0,0 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. - -[[package]] -name = "aiohttp" -version = "3.9.3" -description = "Async http client/server framework (asyncio)" -optional = false -python-versions = ">=3.8" -files = [ - {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" -attrs = ">=17.3.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns", "brotlicffi"] - -[[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" -optional = false -python-versions = ">=3.7" -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[package.dependencies] -frozenlist = ">=1.1.0" - -[[package]] -name = "annotated-types" -version = "0.6.0" -description = "Reusable constraint types to use with typing.Annotated" -optional = false -python-versions = ">=3.8" -files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, -] - -[[package]] -name = "anyio" -version = "4.3.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -optional = false -python-versions = ">=3.8" -files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, -] - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "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" -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 = "autoflake" -version = "2.3.1" -description = "Removes unused imports and unused variables" -optional = false -python-versions = ">=3.8" -files = [ - {file = "autoflake-2.3.1-py3-none-any.whl", hash = "sha256:3ae7495db9084b7b32818b4140e6dc4fc280b712fb414f5b8fe57b0a8e85a840"}, - {file = "autoflake-2.3.1.tar.gz", hash = "sha256:c98b75dc5b0a86459c4f01a1d32ac7eb4338ec4317a4469515ff1e687ecd909e"}, -] - -[package.dependencies] -pyflakes = ">=3.0.0" - -[[package]] -name = "barenecessities" -version = "0.2.8" -description = "Provides the ``bn`` module containing a dictionary allowing attribute access to values - I use it so much I've made into a package." -optional = false -python-versions = "*" -files = [ - {file = "BareNecessities-0.2.8.tar.gz", hash = "sha256:b702013af3ea2913b5cfc7d7ed008083a4bf62ad75d5df1af1fe9e6f47a06a03"}, -] - -[[package]] -name = "black" -version = "24.3.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.8" -files = [ - {file = "black-24.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395"}, - {file = "black-24.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995"}, - {file = "black-24.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7"}, - {file = "black-24.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0"}, - {file = "black-24.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9"}, - {file = "black-24.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597"}, - {file = "black-24.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d"}, - {file = "black-24.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5"}, - {file = "black-24.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f"}, - {file = "black-24.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11"}, - {file = "black-24.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4"}, - {file = "black-24.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5"}, - {file = "black-24.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837"}, - {file = "black-24.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd"}, - {file = "black-24.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213"}, - {file = "black-24.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959"}, - {file = "black-24.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb"}, - {file = "black-24.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7"}, - {file = "black-24.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7"}, - {file = "black-24.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f"}, - {file = "black-24.3.0-py3-none-any.whl", hash = "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93"}, - {file = "black-24.3.0.tar.gz", hash = "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - -[[package]] -name = "certifi" -version = "2024.2.2" -description = "Python package for providing Mozilla's CA Bundle." -optional = false -python-versions = ">=3.6" -files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, -] - -[[package]] -name = "cffi" -version = "1.16.0" -description = "Foreign Function Interface for Python calling C code." -optional = false -python-versions = ">=3.8" -files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, -] - -[package.dependencies] -pycparser = "*" - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, - {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, - {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, - {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, - {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, - {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, - {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" -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" -description = "Cross-platform colored terminal text." -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" -files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, -] - -[[package]] -name = "coverage" -version = "7.4.4" -description = "Code coverage measurement for Python" -optional = false -python-versions = ">=3.8" -files = [ - {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] -toml = ["tomli"] - -[[package]] -name = "dataclasses-json" -version = "0.6.4" -description = "Easily serialize dataclasses to and from JSON." -optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "dataclasses_json-0.6.4-py3-none-any.whl", hash = "sha256:f90578b8a3177f7552f4e1a6e535e84293cd5da421fcce0642d49c0d7bdf8df2"}, - {file = "dataclasses_json-0.6.4.tar.gz", hash = "sha256:73696ebf24936560cca79a2430cbc4f3dd23ac7bf46ed17f38e5e5e7657a6377"}, -] - -[package.dependencies] -marshmallow = ">=3.18.0,<4.0.0" -typing-inspect = ">=0.4.0,<1" - -[[package]] -name = "deprecation" -version = "2.1.0" -description = "A library to handle automated deprecations" -optional = false -python-versions = "*" -files = [ - {file = "deprecation-2.1.0-py2.py3-none-any.whl", hash = "sha256:a10811591210e1fb0e768a8c25517cabeabcba6f0bf96564f8ff45189f90b14a"}, - {file = "deprecation-2.1.0.tar.gz", hash = "sha256:72b3bde64e5d778694b0cf68178aed03d15e15477116add3fb773e581f9518ff"}, -] - -[package.dependencies] -packaging = "*" - -[[package]] -name = "diskcache" -version = "5.6.3" -description = "Disk Cache -- Disk and file backed persistent cache." -optional = false -python-versions = ">=3" -files = [ - {file = "diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19"}, - {file = "diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc"}, -] - -[[package]] -name = "distro" -version = "1.9.0" -description = "Distro - an OS platform information API" -optional = false -python-versions = ">=3.6" -files = [ - {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, - {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, -] - -[[package]] -name = "fastapi" -version = "0.110.1" -description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" -optional = false -python-versions = ">=3.8" -files = [ - {file = "fastapi-0.110.1-py3-none-any.whl", hash = "sha256:5df913203c482f820d31f48e635e022f8cbfe7350e4830ef05a3163925b1addc"}, - {file = "fastapi-0.110.1.tar.gz", hash = "sha256:6feac43ec359dfe4f45b2c18ec8c94edb8dc2dfc461d417d9e626590c071baad"}, -] - -[package.dependencies] -pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.37.2,<0.38.0" -typing-extensions = ">=4.8.0" - -[package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] - -[[package]] -name = "flake8" -version = "7.0.0" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8-7.0.0-py2.py3-none-any.whl", hash = "sha256:a6dfbb75e03252917f2473ea9653f7cd799c3064e54d4c8140044c5c065f53c3"}, - {file = "flake8-7.0.0.tar.gz", hash = "sha256:33f96621059e65eec474169085dc92bf26e7b2d47366b70be2f67ab80dc25132"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.11.0,<2.12.0" -pyflakes = ">=3.2.0,<3.3.0" - -[[package]] -name = "frozenlist" -version = "1.4.1" -description = "A list-like structure which implements collections.abc.MutableSequence" -optional = false -python-versions = ">=3.8" -files = [ - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f9aa1878d1083b276b0196f2dfbe00c9b7e752475ed3b682025ff20c1c1f51ac"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:29acab3f66f0f24674b7dc4736477bcd4bc3ad4b896f5f45379a67bce8b96868"}, - {file = "frozenlist-1.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:74fb4bee6880b529a0c6560885fce4dc95936920f9f20f53d99a213f7bf66776"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:590344787a90ae57d62511dd7c736ed56b428f04cd8c161fcc5e7232c130c69a"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:068b63f23b17df8569b7fdca5517edef76171cf3897eb68beb01341131fbd2ad"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c849d495bf5154cd8da18a9eb15db127d4dba2968d88831aff6f0331ea9bd4c"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9750cc7fe1ae3b1611bb8cfc3f9ec11d532244235d75901fb6b8e42ce9229dfe"}, - {file = "frozenlist-1.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b2de4cf0cdd5bd2dee4c4f63a653c61d2408055ab77b151c1957f221cabf2a"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0633c8d5337cb5c77acbccc6357ac49a1770b8c487e5b3505c57b949b4b82e98"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:27657df69e8801be6c3638054e202a135c7f299267f1a55ed3a598934f6c0d75"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:f9a3ea26252bd92f570600098783d1371354d89d5f6b7dfd87359d669f2109b5"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:4f57dab5fe3407b6c0c1cc907ac98e8a189f9e418f3b6e54d65a718aaafe3950"}, - {file = "frozenlist-1.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e02a0e11cf6597299b9f3bbd3f93d79217cb90cfd1411aec33848b13f5c656cc"}, - {file = "frozenlist-1.4.1-cp310-cp310-win32.whl", hash = "sha256:a828c57f00f729620a442881cc60e57cfcec6842ba38e1b19fd3e47ac0ff8dc1"}, - {file = "frozenlist-1.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:f56e2333dda1fe0f909e7cc59f021eba0d2307bc6f012a1ccf2beca6ba362439"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a0cb6f11204443f27a1628b0e460f37fb30f624be6051d490fa7d7e26d4af3d0"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b46c8ae3a8f1f41a0d2ef350c0b6e65822d80772fe46b653ab6b6274f61d4a49"}, - {file = "frozenlist-1.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fde5bd59ab5357e3853313127f4d3565fc7dad314a74d7b5d43c22c6a5ed2ced"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:722e1124aec435320ae01ee3ac7bec11a5d47f25d0ed6328f2273d287bc3abb0"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2471c201b70d58a0f0c1f91261542a03d9a5e088ed3dc6c160d614c01649c106"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c757a9dd70d72b076d6f68efdbb9bc943665ae954dad2801b874c8c69e185068"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f146e0911cb2f1da549fc58fc7bcd2b836a44b79ef871980d605ec392ff6b0d2"}, - {file = "frozenlist-1.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9c515e7914626b2a2e1e311794b4c35720a0be87af52b79ff8e1429fc25f19"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c302220494f5c1ebeb0912ea782bcd5e2f8308037b3c7553fad0e48ebad6ad82"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:442acde1e068288a4ba7acfe05f5f343e19fac87bfc96d89eb886b0363e977ec"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:1b280e6507ea8a4fa0c0a7150b4e526a8d113989e28eaaef946cc77ffd7efc0a"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:fe1a06da377e3a1062ae5fe0926e12b84eceb8a50b350ddca72dc85015873f74"}, - {file = "frozenlist-1.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db9e724bebd621d9beca794f2a4ff1d26eed5965b004a97f1f1685a173b869c2"}, - {file = "frozenlist-1.4.1-cp311-cp311-win32.whl", hash = "sha256:e774d53b1a477a67838a904131c4b0eef6b3d8a651f8b138b04f748fccfefe17"}, - {file = "frozenlist-1.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb3c2db03683b5767dedb5769b8a40ebb47d6f7f45b1b3e3b4b51ec8ad9d9825"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:20b51fa3f588ff2fe658663db52a41a4f7aa6c04f6201449c6c7c476bd255c0d"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:410478a0c562d1a5bcc2f7ea448359fcb050ed48b3c6f6f4f18c313a9bdb1826"}, - {file = "frozenlist-1.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c6321c9efe29975232da3bd0af0ad216800a47e93d763ce64f291917a381b8eb"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:48f6a4533887e189dae092f1cf981f2e3885175f7a0f33c91fb5b7b682b6bab6"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6eb73fa5426ea69ee0e012fb59cdc76a15b1283d6e32e4f8dc4482ec67d1194d"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbeb989b5cc29e8daf7f976b421c220f1b8c731cbf22b9130d8815418ea45887"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32453c1de775c889eb4e22f1197fe3bdfe457d16476ea407472b9442e6295f7a"}, - {file = "frozenlist-1.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693945278a31f2086d9bf3df0fe8254bbeaef1fe71e1351c3bd730aa7d31c41b"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1d0ce09d36d53bbbe566fe296965b23b961764c0bcf3ce2fa45f463745c04701"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3a670dc61eb0d0eb7080890c13de3066790f9049b47b0de04007090807c776b0"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:dca69045298ce5c11fd539682cff879cc1e664c245d1c64da929813e54241d11"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a06339f38e9ed3a64e4c4e43aec7f59084033647f908e4259d279a52d3757d09"}, - {file = "frozenlist-1.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b7f2f9f912dca3934c1baec2e4585a674ef16fe00218d833856408c48d5beee7"}, - {file = "frozenlist-1.4.1-cp38-cp38-win32.whl", hash = "sha256:e7004be74cbb7d9f34553a5ce5fb08be14fb33bc86f332fb71cbe5216362a497"}, - {file = "frozenlist-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:5a7d70357e7cee13f470c7883a063aae5fe209a493c57d86eb7f5a6f910fae09"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bfa4a17e17ce9abf47a74ae02f32d014c5e9404b6d9ac7f729e01562bbee601e"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b7e3ed87d4138356775346e6845cccbe66cd9e207f3cd11d2f0b9fd13681359d"}, - {file = "frozenlist-1.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c99169d4ff810155ca50b4da3b075cbde79752443117d89429595c2e8e37fed8"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edb678da49d9f72c9f6c609fbe41a5dfb9a9282f9e6a2253d5a91e0fc382d7c0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6db4667b187a6742b33afbbaf05a7bc551ffcf1ced0000a571aedbb4aa42fc7b"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55fdc093b5a3cb41d420884cdaf37a1e74c3c37a31f46e66286d9145d2063bd0"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82e8211d69a4f4bc360ea22cd6555f8e61a1bd211d1d5d39d3d228b48c83a897"}, - {file = "frozenlist-1.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89aa2c2eeb20957be2d950b85974b30a01a762f3308cd02bb15e1ad632e22dc7"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d3e0c25a2350080e9319724dede4f31f43a6c9779be48021a7f4ebde8b2d742"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7268252af60904bf52c26173cbadc3a071cece75f873705419c8681f24d3edea"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:0c250a29735d4f15321007fb02865f0e6b6a41a6b88f1f523ca1596ab5f50bd5"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:96ec70beabbd3b10e8bfe52616a13561e58fe84c0101dd031dc78f250d5128b9"}, - {file = "frozenlist-1.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:23b2d7679b73fe0e5a4560b672a39f98dfc6f60df63823b0a9970525325b95f6"}, - {file = "frozenlist-1.4.1-cp39-cp39-win32.whl", hash = "sha256:a7496bfe1da7fb1a4e1cc23bb67c58fab69311cc7d32b5a99c2007b4b2a0e932"}, - {file = "frozenlist-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e6a20a581f9ce92d389a8c7d7c3dd47c81fd5d6e655c8dddf341e14aa48659d0"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - -[[package]] -name = "gotrue" -version = "2.4.2" -description = "Python Client Library for Supabase Auth" -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "gotrue-2.4.2-py3-none-any.whl", hash = "sha256:64cd40933d1f0a5d5cc4f4bd93bc51d730b94812447b6600f774790a4901e455"}, - {file = "gotrue-2.4.2.tar.gz", hash = "sha256:e100745161f1c58dd05b9c1ef8bcd4cd78cdfb38d8d2c253ade63143a3dc6aeb"}, -] - -[package.dependencies] -httpx = ">=0.23,<0.28" -pydantic = ">=1.10,<3" - -[[package]] -name = "gptrim" -version = "0.1.6" -description = "Reduce the size of GPT inputs by 40-60% without losing most of the information." -optional = false -python-versions = "*" -files = [ - {file = "gptrim-0.1.6-py3-none-any.whl", hash = "sha256:cbe6990a352a6cbcd0115ab9c7a50f63c70191943e2739ee511877e86e314659"}, -] - -[package.dependencies] -nltk = "3.8.1" - -[[package]] -name = "greenlet" -version = "3.0.3" -description = "Lightweight in-process concurrent programming" -optional = false -python-versions = ">=3.7" -files = [ - {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d353cadd6083fdb056bb46ed07e4340b0869c305c8ca54ef9da3421acbdf6881"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dca1e2f3ca00b84a396bc1bce13dd21f680f035314d2379c4160c98153b2059b"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ed7fb269f15dc662787f4119ec300ad0702fa1b19d2135a37c2c4de6fadfd4a"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4f49ae60e10adbc94b45c0b5e6a179acc1736cf7a90160b404076ee283cf83"}, - {file = "greenlet-3.0.3-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:73a411ef564e0e097dbe7e866bb2dda0f027e072b04da387282b02c308807405"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7f362975f2d179f9e26928c5b517524e89dd48530a0202570d55ad6ca5d8a56f"}, - {file = "greenlet-3.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:649dde7de1a5eceb258f9cb00bdf50e978c9db1b996964cd80703614c86495eb"}, - {file = "greenlet-3.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:68834da854554926fbedd38c76e60c4a2e3198c6fbed520b106a8986445caaf9"}, - {file = "greenlet-3.0.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:b1b5667cced97081bf57b8fa1d6bfca67814b0afd38208d52538316e9422fc61"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52f59dd9c96ad2fc0d5724107444f76eb20aaccb675bf825df6435acb7703559"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:afaff6cf5200befd5cec055b07d1c0a5a06c040fe5ad148abcd11ba6ab9b114e"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe754d231288e1e64323cfad462fcee8f0288654c10bdf4f603a39ed923bef33"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2797aa5aedac23af156bbb5a6aa2cd3427ada2972c828244eb7d1b9255846379"}, - {file = "greenlet-3.0.3-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7f009caad047246ed379e1c4dbcb8b020f0a390667ea74d2387be2998f58a22"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c5e1536de2aad7bf62e27baf79225d0d64360d4168cf2e6becb91baf1ed074f3"}, - {file = "greenlet-3.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:894393ce10ceac937e56ec00bb71c4c2f8209ad516e96033e4b3b1de270e200d"}, - {file = "greenlet-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:1ea188d4f49089fc6fb283845ab18a2518d279c7cd9da1065d7a84e991748728"}, - {file = "greenlet-3.0.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:70fb482fdf2c707765ab5f0b6655e9cfcf3780d8d87355a063547b41177599be"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4d1ac74f5c0c0524e4a24335350edad7e5f03b9532da7ea4d3c54d527784f2e"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149e94a2dd82d19838fe4b2259f1b6b9957d5ba1b25640d2380bea9c5df37676"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15d79dd26056573940fcb8c7413d84118086f2ec1a8acdfa854631084393efcc"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b7db1ebff4ba09aaaeae6aa491daeb226c8150fc20e836ad00041bcb11230"}, - {file = "greenlet-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fcd2469d6a2cf298f198f0487e0a5b1a47a42ca0fa4dfd1b6862c999f018ebbf"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f672519db1796ca0d8753f9e78ec02355e862d0998193038c7073045899f305"}, - {file = "greenlet-3.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2516a9957eed41dd8f1ec0c604f1cdc86758b587d964668b5b196a9db5bfcde6"}, - {file = "greenlet-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:bba5387a6975598857d86de9eac14210a49d554a77eb8261cc68b7d082f78ce2"}, - {file = "greenlet-3.0.3-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:5b51e85cb5ceda94e79d019ed36b35386e8c37d22f07d6a751cb659b180d5274"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:daf3cb43b7cf2ba96d614252ce1684c1bccee6b2183a01328c98d36fcd7d5cb0"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99bf650dc5d69546e076f413a87481ee1d2d09aaaaaca058c9251b6d8c14783f"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dd6e660effd852586b6a8478a1d244b8dc90ab5b1321751d2ea15deb49ed414"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e3391d1e16e2a5a1507d83e4a8b100f4ee626e8eca43cf2cadb543de69827c4c"}, - {file = "greenlet-3.0.3-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e1f145462f1fa6e4a4ae3c0f782e580ce44d57c8f2c7aae1b6fa88c0b2efdb41"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1a7191e42732df52cb5f39d3527217e7ab73cae2cb3694d241e18f53d84ea9a7"}, - {file = "greenlet-3.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0448abc479fab28b00cb472d278828b3ccca164531daab4e970a0458786055d6"}, - {file = "greenlet-3.0.3-cp37-cp37m-win32.whl", hash = "sha256:b542be2440edc2d48547b5923c408cbe0fc94afb9f18741faa6ae970dbcb9b6d"}, - {file = "greenlet-3.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:01bc7ea167cf943b4c802068e178bbf70ae2e8c080467070d01bfa02f337ee67"}, - {file = "greenlet-3.0.3-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1996cb9306c8595335bb157d133daf5cf9f693ef413e7673cb07e3e5871379ca"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ddc0f794e6ad661e321caa8d2f0a55ce01213c74722587256fb6566049a8b04"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9db1c18f0eaad2f804728c67d6c610778456e3e1cc4ab4bbd5eeb8e6053c6fc"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7170375bcc99f1a2fbd9c306f5be8764eaf3ac6b5cb968862cad4c7057756506"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b66c9c1e7ccabad3a7d037b2bcb740122a7b17a53734b7d72a344ce39882a1b"}, - {file = "greenlet-3.0.3-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:098d86f528c855ead3479afe84b49242e174ed262456c342d70fc7f972bc13c4"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:81bb9c6d52e8321f09c3d165b2a78c680506d9af285bfccbad9fb7ad5a5da3e5"}, - {file = "greenlet-3.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd096eb7ffef17c456cfa587523c5f92321ae02427ff955bebe9e3c63bc9f0da"}, - {file = "greenlet-3.0.3-cp38-cp38-win32.whl", hash = "sha256:d46677c85c5ba00a9cb6f7a00b2bfa6f812192d2c9f7d9c4f6a55b60216712f3"}, - {file = "greenlet-3.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:419b386f84949bf0e7c73e6032e3457b82a787c1ab4a0e43732898a761cc9dbf"}, - {file = "greenlet-3.0.3-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:da70d4d51c8b306bb7a031d5cff6cc25ad253affe89b70352af5f1cb68e74b53"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086152f8fbc5955df88382e8a75984e2bb1c892ad2e3c80a2508954e52295257"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d73a9fe764d77f87f8ec26a0c85144d6a951a6c438dfe50487df5595c6373eac"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7dcbe92cc99f08c8dd11f930de4d99ef756c3591a5377d1d9cd7dd5e896da71"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1551a8195c0d4a68fac7a4325efac0d541b48def35feb49d803674ac32582f61"}, - {file = "greenlet-3.0.3-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:64d7675ad83578e3fc149b617a444fab8efdafc9385471f868eb5ff83e446b8b"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b37eef18ea55f2ffd8f00ff8fe7c8d3818abd3e25fb73fae2ca3b672e333a7a6"}, - {file = "greenlet-3.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:77457465d89b8263bca14759d7c1684df840b6811b2499838cc5b040a8b5b113"}, - {file = "greenlet-3.0.3-cp39-cp39-win32.whl", hash = "sha256:57e8974f23e47dac22b83436bdcf23080ade568ce77df33159e019d161ce1d1e"}, - {file = "greenlet-3.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:c5ee858cfe08f34712f548c3c363e807e7186f03ad7a5039ebadb29e8c6be067"}, - {file = "greenlet-3.0.3.tar.gz", hash = "sha256:43374442353259554ce33599da8b692d5aa96f8976d567d4badf263371fbe491"}, -] - -[package.extras] -docs = ["Sphinx", "furo"] -test = ["objgraph", "psutil"] - -[[package]] -name = "h11" -version = "0.14.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -optional = false -python-versions = ">=3.7" -files = [ - {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, - {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, -] - -[[package]] -name = "httpcore" -version = "1.0.5" -description = "A minimal low-level HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpcore-1.0.5-py3-none-any.whl", hash = "sha256:421f18bac248b25d310f3cacd198d55b8e6125c107797b609ff9b7a6ba7991b5"}, - {file = "httpcore-1.0.5.tar.gz", hash = "sha256:34a38e2f9291467ee3b44e89dd52615370e152954ba21721378a87b2960f7a61"}, -] - -[package.dependencies] -certifi = "*" -h11 = ">=0.13,<0.15" - -[package.extras] -asyncio = ["anyio (>=4.0,<5.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] -trio = ["trio (>=0.22.0,<0.26.0)"] - -[[package]] -name = "httpx" -version = "0.27.0" -description = "The next generation HTTP client." -optional = false -python-versions = ">=3.8" -files = [ - {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, - {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, -] - -[package.dependencies] -anyio = "*" -certifi = "*" -httpcore = "==1.*" -idna = "*" -sniffio = "*" - -[package.extras] -brotli = ["brotli", "brotlicffi"] -cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (==1.*)"] - -[[package]] -name = "idna" -version = "3.7" -description = "Internationalized Domain Names in Applications (IDNA)" -optional = false -python-versions = ">=3.5" -files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, -] - -[[package]] -name = "iniconfig" -version = "2.0.0" -description = "brain-dead simple config-ini parsing" -optional = false -python-versions = ">=3.7" -files = [ - {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, - {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, -] - -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - -[[package]] -name = "joblib" -version = "1.4.0" -description = "Lightweight pipelining with Python functions" -optional = false -python-versions = ">=3.8" -files = [ - {file = "joblib-1.4.0-py3-none-any.whl", hash = "sha256:42942470d4062537be4d54c83511186da1fc14ba354961a2114da91efa9a4ed7"}, - {file = "joblib-1.4.0.tar.gz", hash = "sha256:1eb0dc091919cd384490de890cb5dfd538410a6d4b3b54eef09fb8c50b409b1c"}, -] - -[[package]] -name = "jsonpatch" -version = "1.33" -description = "Apply JSON-Patches (RFC 6902)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -files = [ - {file = "jsonpatch-1.33-py2.py3-none-any.whl", hash = "sha256:0ae28c0cd062bbd8b8ecc26d7d164fbbea9652a1a3693f3b956c1eae5145dade"}, - {file = "jsonpatch-1.33.tar.gz", hash = "sha256:9fcd4009c41e6d12348b4a0ff2563ba56a2923a7dfee731d004e212e1ee5030c"}, -] - -[package.dependencies] -jsonpointer = ">=1.9" - -[[package]] -name = "jsonpointer" -version = "2.4" -description = "Identify specific nodes in a JSON document (RFC 6901)" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" -files = [ - {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, - {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, -] - -[[package]] -name = "langchain" -version = "0.1.12" -description = "Building applications with LLMs through composability" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [ - {file = "langchain-0.1.12-py3-none-any.whl", hash = "sha256:b4dd1760e2d035daefad08af60a209b96b729ee45492d34e3e127e553a471034"}, - {file = "langchain-0.1.12.tar.gz", hash = "sha256:5f612761ba548b81748ed8dc70535e8de0531445415028a82de3fd8255bfa8a3"}, -] - -[package.dependencies] -aiohttp = ">=3.8.3,<4.0.0" -dataclasses-json = ">=0.5.7,<0.7" -jsonpatch = ">=1.33,<2.0" -langchain-community = ">=0.0.28,<0.1" -langchain-core = ">=0.1.31,<0.2.0" -langchain-text-splitters = ">=0.0.1,<0.1" -langsmith = ">=0.1.17,<0.2.0" -numpy = ">=1,<2" -pydantic = ">=1,<3" -PyYAML = ">=5.3" -requests = ">=2,<3" -SQLAlchemy = ">=1.4,<3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"] -clarifai = ["clarifai (>=9.1.0)"] -cli = ["typer (>=0.9.0,<0.10.0)"] -cohere = ["cohere (>=4,<5)"] -docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"] -embeddings = ["sentence-transformers (>=2,<3)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"] -javascript = ["esprima (>=4.0.1,<5.0.0)"] -llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"] -openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] -qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] -text-helpers = ["chardet (>=5.1.0,<6.0.0)"] - -[[package]] -name = "langchain-community" -version = "0.0.28" -description = "Community contributed LangChain integrations." -optional = false -python-versions = ">=3.8.1,<4.0" -files = [ - {file = "langchain_community-0.0.28-py3-none-any.whl", hash = "sha256:bdb015ac455ae68432ea104628717583dce041e1abdfcefe86e39f034f5e90b8"}, - {file = "langchain_community-0.0.28.tar.gz", hash = "sha256:8664d243a90550fc5ddc137b712034e02c8d43afc8d4cc832ba5842b44c864ce"}, -] - -[package.dependencies] -aiohttp = ">=3.8.3,<4.0.0" -dataclasses-json = ">=0.5.7,<0.7" -langchain-core = ">=0.1.31,<0.2.0" -langsmith = ">=0.1.0,<0.2.0" -numpy = ">=1,<2" -PyYAML = ">=5.3" -requests = ">=2,<3" -SQLAlchemy = ">=1.4,<3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -cli = ["typer (>=0.9.0,<0.10.0)"] -extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cloudpickle (>=2.0.0)", "cohere (>=4,<5)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "friendli-client (>=1.2.4,<2.0.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "httpx (>=0.24.1,<0.25.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "nvidia-riva-client (>=2.14.0,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "rdflib (==7.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "tidb-vector (>=0.0.3,<1.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "tree-sitter (>=0.20.2,<0.21.0)", "tree-sitter-languages (>=1.8.0,<2.0.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"] - -[[package]] -name = "langchain-core" -version = "0.1.41" -description = "Building applications with LLMs through composability" -optional = false -python-versions = "<4.0,>=3.8.1" -files = [ - {file = "langchain_core-0.1.41-py3-none-any.whl", hash = "sha256:92d3da5ca0d5fb1606b3ab42bfd455c7b386fe4c38f6c0d44ba6014abf46147d"}, - {file = "langchain_core-0.1.41.tar.gz", hash = "sha256:4002304883b251af8cb781f01c59f56aeee58be42c965dbbdeca0a3bfb8f96af"}, -] - -[package.dependencies] -jsonpatch = ">=1.33,<2.0" -langsmith = ">=0.1.0,<0.2.0" -packaging = ">=23.2,<24.0" -pydantic = ">=1,<3" -PyYAML = ">=5.3" -tenacity = ">=8.1.0,<9.0.0" - -[package.extras] -extended-testing = ["jinja2 (>=3,<4)"] - -[[package]] -name = "langchain-openai" -version = "0.1.2" -description = "An integration package connecting OpenAI and LangChain" -optional = false -python-versions = "<4.0,>=3.8.1" -files = [ - {file = "langchain_openai-0.1.2-py3-none-any.whl", hash = "sha256:45fab91803df22c6d5fce7c010df404569898372df5ae8cd03af50bef774d2ec"}, - {file = "langchain_openai-0.1.2.tar.gz", hash = "sha256:cd391e61bd93ab72ae24d8e1f250257d6acff6d9e455e623363b8c171533050a"}, -] - -[package.dependencies] -langchain-core = ">=0.1.41,<0.2.0" -openai = ">=1.10.0,<2.0.0" -tiktoken = ">=0.5.2,<1" - -[[package]] -name = "langchain-text-splitters" -version = "0.0.1" -description = "LangChain text splitting utilities" -optional = false -python-versions = ">=3.8.1,<4.0" -files = [ - {file = "langchain_text_splitters-0.0.1-py3-none-any.whl", hash = "sha256:f5b802f873f5ff6a8b9259ff34d53ed989666ef4e1582e6d1adb3b5520e3839a"}, - {file = "langchain_text_splitters-0.0.1.tar.gz", hash = "sha256:ac459fa98799f5117ad5425a9330b21961321e30bc19a2a2f9f761ddadd62aa1"}, -] - -[package.dependencies] -langchain-core = ">=0.1.28,<0.2.0" - -[package.extras] -extended-testing = ["lxml (>=5.1.0,<6.0.0)"] - -[[package]] -name = "langsmith" -version = "0.1.43" -description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform." -optional = false -python-versions = "<4.0,>=3.8.1" -files = [ - {file = "langsmith-0.1.43-py3-none-any.whl", hash = "sha256:c0a3658f10cbefaa2f53d15db519592982b59d99f24e018dc73aca6092b4158d"}, - {file = "langsmith-0.1.43.tar.gz", hash = "sha256:983c5a35bf191bb23d93e453c9fc6ea7cda998b1ca96f94680a1446092caf347"}, -] - -[package.dependencies] -orjson = ">=3.9.14,<4.0.0" -pydantic = ">=1,<3" -requests = ">=2,<3" - -[[package]] -name = "mail" -version = "2.1.0" -description = "Simple wrapper over Python's email package for common operations, and a mail pipe." -optional = false -python-versions = "*" -files = [ - {file = "Mail-2.1.0.tar.gz", hash = "sha256:04e69aaba47d45c6853c7b8dcec74896153e7ce38a512d2eb96a13650633e720"}, -] - -[package.dependencies] -BareNecessities = "*" - -[[package]] -name = "markdown" -version = "3.6" -description = "Python implementation of John Gruber's Markdown." -optional = false -python-versions = ">=3.8" -files = [ - {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, - {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, -] - -[package.extras] -docs = ["mdx-gh-links (>=0.2)", "mkdocs (>=1.5)", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-nature (>=0.6)", "mkdocs-section-index", "mkdocstrings[python]"] -testing = ["coverage", "pyyaml"] - -[[package]] -name = "marshmallow" -version = "3.21.1" -description = "A lightweight library for converting complex datatypes to and from native Python datatypes." -optional = false -python-versions = ">=3.8" -files = [ - {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 = ["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 = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - -[[package]] -name = "multidict" -version = "6.0.5" -description = "multidict implementation" -optional = false -python-versions = ">=3.7" -files = [ - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, - {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, - {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, - {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, - {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, - {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, - {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, - {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, - {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, - {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, - {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, - {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, - {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, - {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, - {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, - {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, - {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, - {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, - {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, - {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, - {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, - {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, - {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, - {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, - {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, -] - -[[package]] -name = "mypy" -version = "1.9.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, - {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, - {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, - {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, - {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, - {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, - {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, - {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, - {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, - {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, - {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, - {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, - {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, - {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, - {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, - {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, - {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, - {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, - {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" -typing-extensions = ">=4.1.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - -[[package]] -name = "nltk" -version = "3.8.1" -description = "Natural Language Toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "nltk-3.8.1-py3-none-any.whl", hash = "sha256:fd5c9109f976fa86bcadba8f91e47f5e9293bd034474752e92a520f81c93dda5"}, - {file = "nltk-3.8.1.zip", hash = "sha256:1834da3d0682cba4f2cede2f9aad6b0fafb6461ba451db0efb6f9c39798d64d3"}, -] - -[package.dependencies] -click = "*" -joblib = "*" -regex = ">=2021.8.3" -tqdm = "*" - -[package.extras] -all = ["matplotlib", "numpy", "pyparsing", "python-crfsuite", "requests", "scikit-learn", "scipy", "twython"] -corenlp = ["requests"] -machine-learning = ["numpy", "python-crfsuite", "scikit-learn", "scipy"] -plot = ["matplotlib"] -tgrep = ["pyparsing"] -twitter = ["twython"] - -[[package]] -name = "nodeenv" -version = "1.8.0" -description = "Node.js virtual environment builder" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" -files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, -] - -[package.dependencies] -setuptools = "*" - -[[package]] -name = "numpy" -version = "1.26.4" -description = "Fundamental package for array computing in Python" -optional = false -python-versions = ">=3.9" -files = [ - {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, - {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, - {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, - {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, - {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, - {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, - {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, - {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, - {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, - {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, - {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, - {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, - {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, - {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, - {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, - {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, - {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, - {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, - {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, - {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, - {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, - {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, - {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, -] - -[[package]] -name = "oauthlib" -version = "3.2.2" -description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" -optional = false -python-versions = ">=3.6" -files = [ - {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, - {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, -] - -[package.extras] -rsa = ["cryptography (>=3.0.0)"] -signals = ["blinker (>=1.4.0)"] -signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] - -[[package]] -name = "openai" -version = "1.16.2" -description = "The official Python library for the openai API" -optional = false -python-versions = ">=3.7.1" -files = [ - {file = "openai-1.16.2-py3-none-any.whl", hash = "sha256:46a435380921e42dae218d04d6dd0e89a30d7f3b9d8a778d5887f78003cf9354"}, - {file = "openai-1.16.2.tar.gz", hash = "sha256:c93d5efe5b73b6cb72c4cd31823852d2e7c84a138c0af3cbe4a8eb32b1164ab2"}, -] - -[package.dependencies] -anyio = ">=3.5.0,<5" -distro = ">=1.7.0,<2" -httpx = ">=0.23.0,<1" -pydantic = ">=1.9.0,<3" -sniffio = "*" -tqdm = ">4" -typing-extensions = ">=4.7,<5" - -[package.extras] -datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] - -[[package]] -name = "orjson" -version = "3.10.0" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -files = [ - {file = "orjson-3.10.0-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:47af5d4b850a2d1328660661f0881b67fdbe712aea905dadd413bdea6f792c33"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c90681333619d78360d13840c7235fdaf01b2b129cb3a4f1647783b1971542b6"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:400c5b7c4222cb27b5059adf1fb12302eebcabf1978f33d0824aa5277ca899bd"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5dcb32e949eae80fb335e63b90e5808b4b0f64e31476b3777707416b41682db5"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7d507c7493252c0a0264b5cc7e20fa2f8622b8a83b04d819b5ce32c97cf57b"}, - {file = "orjson-3.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e286a51def6626f1e0cc134ba2067dcf14f7f4b9550f6dd4535fd9d79000040b"}, - {file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:8acd4b82a5f3a3ec8b1dc83452941d22b4711964c34727eb1e65449eead353ca"}, - {file = "orjson-3.10.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:30707e646080dd3c791f22ce7e4a2fc2438765408547c10510f1f690bd336217"}, - {file = "orjson-3.10.0-cp310-none-win32.whl", hash = "sha256:115498c4ad34188dcb73464e8dc80e490a3e5e88a925907b6fedcf20e545001a"}, - {file = "orjson-3.10.0-cp310-none-win_amd64.whl", hash = "sha256:6735dd4a5a7b6df00a87d1d7a02b84b54d215fb7adac50dd24da5997ffb4798d"}, - {file = "orjson-3.10.0-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9587053e0cefc284e4d1cd113c34468b7d3f17666d22b185ea654f0775316a26"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bef1050b1bdc9ea6c0d08468e3e61c9386723633b397e50b82fda37b3563d72"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d16c6963ddf3b28c0d461641517cd312ad6b3cf303d8b87d5ef3fa59d6844337"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4251964db47ef090c462a2d909f16c7c7d5fe68e341dabce6702879ec26d1134"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:73bbbdc43d520204d9ef0817ac03fa49c103c7f9ea94f410d2950755be2c349c"}, - {file = "orjson-3.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:414e5293b82373606acf0d66313aecb52d9c8c2404b1900683eb32c3d042dbd7"}, - {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:feaed5bb09877dc27ed0d37f037ddef6cb76d19aa34b108db270d27d3d2ef747"}, - {file = "orjson-3.10.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5127478260db640323cea131ee88541cb1a9fbce051f0b22fa2f0892f44da302"}, - {file = "orjson-3.10.0-cp311-none-win32.whl", hash = "sha256:b98345529bafe3c06c09996b303fc0a21961820d634409b8639bc16bd4f21b63"}, - {file = "orjson-3.10.0-cp311-none-win_amd64.whl", hash = "sha256:658ca5cee3379dd3d37dbacd43d42c1b4feee99a29d847ef27a1cb18abdfb23f"}, - {file = "orjson-3.10.0-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4329c1d24fd130ee377e32a72dc54a3c251e6706fccd9a2ecb91b3606fddd998"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef0f19fdfb6553342b1882f438afd53c7cb7aea57894c4490c43e4431739c700"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c4f60db24161534764277f798ef53b9d3063092f6d23f8f962b4a97edfa997a0"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1de3fd5c7b208d836f8ecb4526995f0d5877153a4f6f12f3e9bf11e49357de98"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f93e33f67729d460a177ba285002035d3f11425ed3cebac5f6ded4ef36b28344"}, - {file = "orjson-3.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:237ba922aef472761acd697eef77fef4831ab769a42e83c04ac91e9f9e08fa0e"}, - {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98c1bfc6a9bec52bc8f0ab9b86cc0874b0299fccef3562b793c1576cf3abb570"}, - {file = "orjson-3.10.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:30d795a24be16c03dca0c35ca8f9c8eaaa51e3342f2c162d327bd0225118794a"}, - {file = "orjson-3.10.0-cp312-none-win32.whl", hash = "sha256:6a3f53dc650bc860eb26ec293dfb489b2f6ae1cbfc409a127b01229980e372f7"}, - {file = "orjson-3.10.0-cp312-none-win_amd64.whl", hash = "sha256:983db1f87c371dc6ffc52931eb75f9fe17dc621273e43ce67bee407d3e5476e9"}, - {file = "orjson-3.10.0-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9a667769a96a72ca67237224a36faf57db0c82ab07d09c3aafc6f956196cfa1b"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade1e21dfde1d37feee8cf6464c20a2f41fa46c8bcd5251e761903e46102dc6b"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:23c12bb4ced1c3308eff7ba5c63ef8f0edb3e4c43c026440247dd6c1c61cea4b"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2d014cf8d4dc9f03fc9f870de191a49a03b1bcda51f2a957943fb9fafe55aac"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eadecaa16d9783affca33597781328e4981b048615c2ddc31c47a51b833d6319"}, - {file = "orjson-3.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd583341218826f48bd7c6ebf3310b4126216920853cbc471e8dbeaf07b0b80e"}, - {file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:90bfc137c75c31d32308fd61951d424424426ddc39a40e367704661a9ee97095"}, - {file = "orjson-3.10.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:13b5d3c795b09a466ec9fcf0bd3ad7b85467d91a60113885df7b8d639a9d374b"}, - {file = "orjson-3.10.0-cp38-none-win32.whl", hash = "sha256:5d42768db6f2ce0162544845facb7c081e9364a5eb6d2ef06cd17f6050b048d8"}, - {file = "orjson-3.10.0-cp38-none-win_amd64.whl", hash = "sha256:33e6655a2542195d6fd9f850b428926559dee382f7a862dae92ca97fea03a5ad"}, - {file = "orjson-3.10.0-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:4050920e831a49d8782a1720d3ca2f1c49b150953667eed6e5d63a62e80f46a2"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1897aa25a944cec774ce4a0e1c8e98fb50523e97366c637b7d0cddabc42e6643"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9bf565a69e0082ea348c5657401acec3cbbb31564d89afebaee884614fba36b4"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b6ebc17cfbbf741f5c1a888d1854354536f63d84bee537c9a7c0335791bb9009"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2817877d0b69f78f146ab305c5975d0618df41acf8811249ee64231f5953fee"}, - {file = "orjson-3.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:57d017863ec8aa4589be30a328dacd13c2dc49de1c170bc8d8c8a98ece0f2925"}, - {file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:22c2f7e377ac757bd3476ecb7480c8ed79d98ef89648f0176deb1da5cd014eb7"}, - {file = "orjson-3.10.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e62ba42bfe64c60c1bc84799944f80704e996592c6b9e14789c8e2a303279912"}, - {file = "orjson-3.10.0-cp39-none-win32.whl", hash = "sha256:60c0b1bdbccd959ebd1575bd0147bd5e10fc76f26216188be4a36b691c937077"}, - {file = "orjson-3.10.0-cp39-none-win_amd64.whl", hash = "sha256:175a41500ebb2fdf320bf78e8b9a75a1279525b62ba400b2b2444e274c2c8bee"}, - {file = "orjson-3.10.0.tar.gz", hash = "sha256:ba4d8cac5f2e2cff36bea6b6481cdb92b38c202bcec603d6f5ff91960595a1ed"}, -] - -[[package]] -name = "outcome" -version = "1.3.0.post0" -description = "Capture the outcome of Python function calls." -optional = false -python-versions = ">=3.7" -files = [ - {file = "outcome-1.3.0.post0-py2.py3-none-any.whl", hash = "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"}, - {file = "outcome-1.3.0.post0.tar.gz", hash = "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8"}, -] - -[package.dependencies] -attrs = ">=19.2.0" - -[[package]] -name = "packaging" -version = "23.2" -description = "Core utilities for Python packages" -optional = false -python-versions = ">=3.7" -files = [ - {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, - {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, -] - -[[package]] -name = "pandas" -version = "2.2.1" -description = "Powerful data structures for data analysis, time series, and statistics" -optional = false -python-versions = ">=3.9" -files = [ - {file = "pandas-2.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8df8612be9cd1c7797c93e1c5df861b2ddda0b48b08f2c3eaa0702cf88fb5f88"}, - {file = "pandas-2.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0f573ab277252ed9aaf38240f3b54cfc90fff8e5cab70411ee1d03f5d51f3944"}, - {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f02a3a6c83df4026e55b63c1f06476c9aa3ed6af3d89b4f04ea656ccdaaaa359"}, - {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c38ce92cb22a4bea4e3929429aa1067a454dcc9c335799af93ba9be21b6beb51"}, - {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c2ce852e1cf2509a69e98358e8458775f89599566ac3775e70419b98615f4b06"}, - {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53680dc9b2519cbf609c62db3ed7c0b499077c7fefda564e330286e619ff0dd9"}, - {file = "pandas-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:94e714a1cca63e4f5939cdce5f29ba8d415d85166be3441165edd427dc9f6bc0"}, - {file = "pandas-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f821213d48f4ab353d20ebc24e4faf94ba40d76680642fb7ce2ea31a3ad94f9b"}, - {file = "pandas-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70e00c2d894cb230e5c15e4b1e1e6b2b478e09cf27cc593a11ef955b9ecc81a"}, - {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97fbb5387c69209f134893abc788a6486dbf2f9e511070ca05eed4b930b1b02"}, - {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101d0eb9c5361aa0146f500773395a03839a5e6ecde4d4b6ced88b7e5a1a6403"}, - {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7d2ed41c319c9fb4fd454fe25372028dfa417aacb9790f68171b2e3f06eae8cd"}, - {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5d3c00557d657c8773ef9ee702c61dd13b9d7426794c9dfeb1dc4a0bf0ebc7"}, - {file = "pandas-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:06cf591dbaefb6da9de8472535b185cba556d0ce2e6ed28e21d919704fef1a9e"}, - {file = "pandas-2.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:88ecb5c01bb9ca927ebc4098136038519aa5d66b44671861ffab754cae75102c"}, - {file = "pandas-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:04f6ec3baec203c13e3f8b139fb0f9f86cd8c0b94603ae3ae8ce9a422e9f5bee"}, - {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a935a90a76c44fe170d01e90a3594beef9e9a6220021acfb26053d01426f7dc2"}, - {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c391f594aae2fd9f679d419e9a4d5ba4bce5bb13f6a989195656e7dc4b95c8f0"}, - {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9d1265545f579edf3f8f0cb6f89f234f5e44ba725a34d86535b1a1d38decbccc"}, - {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11940e9e3056576ac3244baef2fedade891977bcc1cb7e5cc8f8cc7d603edc89"}, - {file = "pandas-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:4acf681325ee1c7f950d058b05a820441075b0dd9a2adf5c4835b9bc056bf4fb"}, - {file = "pandas-2.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9bd8a40f47080825af4317d0340c656744f2bfdb6819f818e6ba3cd24c0e1397"}, - {file = "pandas-2.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df0c37ebd19e11d089ceba66eba59a168242fc6b7155cba4ffffa6eccdfb8f16"}, - {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:739cc70eaf17d57608639e74d63387b0d8594ce02f69e7a0b046f117974b3019"}, - {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d3558d263073ed95e46f4650becff0c5e1ffe0fc3a015de3c79283dfbdb3df"}, - {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4aa1d8707812a658debf03824016bf5ea0d516afdea29b7dc14cf687bc4d4ec6"}, - {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:76f27a809cda87e07f192f001d11adc2b930e93a2b0c4a236fde5429527423be"}, - {file = "pandas-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:1ba21b1d5c0e43416218db63037dbe1a01fc101dc6e6024bcad08123e48004ab"}, - {file = "pandas-2.2.1.tar.gz", hash = "sha256:0ab90f87093c13f3e8fa45b48ba9f39181046e8f3317d3aadb2fffbb1b978572"}, -] - -[package.dependencies] -numpy = [ - {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, - {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, -] -python-dateutil = ">=2.8.2" -pytz = ">=2020.1" -tzdata = ">=2022.7" - -[package.extras] -all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] -aws = ["s3fs (>=2022.11.0)"] -clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] -compression = ["zstandard (>=0.19.0)"] -computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] -consortium-standard = ["dataframe-api-compat (>=0.1.7)"] -excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] -feather = ["pyarrow (>=10.0.1)"] -fss = ["fsspec (>=2022.11.0)"] -gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] -hdf5 = ["tables (>=3.8.0)"] -html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] -mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] -output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] -parquet = ["pyarrow (>=10.0.1)"] -performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] -plot = ["matplotlib (>=3.6.3)"] -postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] -pyarrow = ["pyarrow (>=10.0.1)"] -spss = ["pyreadstat (>=1.2.0)"] -sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] -test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] -xml = ["lxml (>=4.9.2)"] - -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - -[[package]] -name = "platformdirs" -version = "4.2.0" -description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." -optional = false -python-versions = ">=3.8" -files = [ - {file = "platformdirs-4.2.0-py3-none-any.whl", hash = "sha256:0614df2a2f37e1a662acbd8e2b25b92ccf8632929bc6d43467e17fe89c75e068"}, - {file = "platformdirs-4.2.0.tar.gz", hash = "sha256:ef0cc731df711022c174543cb70a9b5bd22e5a9337c8624ef2c2ceb8ddad8768"}, -] - -[package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] - -[[package]] -name = "pluggy" -version = "1.4.0" -description = "plugin and hook calling mechanisms for python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, - {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, -] - -[package.extras] -dev = ["pre-commit", "tox"] -testing = ["pytest", "pytest-benchmark"] - -[[package]] -name = "postgrest" -version = "0.16.2" -description = "PostgREST client for Python. This library provides an ORM interface to PostgREST." -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "postgrest-0.16.2-py3-none-any.whl", hash = "sha256:cf89106d0877ac2c7b070ad136f78350eb89dbdd998cd83d6852010e0bcdb878"}, - {file = "postgrest-0.16.2.tar.gz", hash = "sha256:6c5c8e53cdcede8b6654ddfc7505e5af0c41ce56c6935f7b1d05545bb899d8b8"}, -] - -[package.dependencies] -deprecation = ">=2.1.0,<3.0.0" -httpx = ">=0.24,<0.28" -pydantic = ">=1.9,<3.0" -strenum = ">=0.4.9,<0.5.0" - -[[package]] -name = "praw" -version = "7.7.1" -description = "PRAW, an acronym for \"Python Reddit API Wrapper\", is a Python package that allows for simple access to Reddit's API." -optional = false -python-versions = "~=3.7" -files = [ - {file = "praw-7.7.1-py3-none-any.whl", hash = "sha256:9ec5dc943db00c175bc6a53f4e089ce625f3fdfb27305564b616747b767d38ef"}, - {file = "praw-7.7.1.tar.gz", hash = "sha256:f1d7eef414cafe28080dda12ed09253a095a69933d5c8132eca11d4dc8a070bf"}, -] - -[package.dependencies] -prawcore = ">=2.1,<3" -update-checker = ">=0.18" -websocket-client = ">=0.54.0" - -[package.extras] -ci = ["coveralls"] -dev = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "furo", "packaging", "pre-commit", "pytest (>=2.7.3)", "requests (>=2.20.1,<3)", "sphinx", "urllib3 (==1.26.*)"] -lint = ["furo", "pre-commit", "sphinx"] -readthedocs = ["furo", "sphinx"] -test = ["betamax (>=0.8,<0.9)", "betamax-matchers (>=0.3.0,<0.5)", "pytest (>=2.7.3)", "requests (>=2.20.1,<3)", "urllib3 (==1.26.*)"] - -[[package]] -name = "prawcore" -version = "2.4.0" -description = "\"Low-level communication layer for PRAW 4+." -optional = false -python-versions = "~=3.8" -files = [ - {file = "prawcore-2.4.0-py3-none-any.whl", hash = "sha256:29af5da58d85704b439ad3c820873ad541f4535e00bb98c66f0fbcc8c603065a"}, - {file = "prawcore-2.4.0.tar.gz", hash = "sha256:b7b2b5a1d04406e086ab4e79988dc794df16059862f329f4c6a43ed09986c335"}, -] - -[package.dependencies] -requests = ">=2.6.0,<3.0" - -[package.extras] -ci = ["coveralls"] -dev = ["packaging", "prawcore[lint]", "prawcore[test]"] -lint = ["pre-commit", "ruff (>=0.0.291)"] -test = ["betamax (>=0.8,<0.9)", "pytest (>=2.7.3)", "urllib3 (==1.26.*)"] - -[[package]] -name = "pycodestyle" -version = "2.11.1" -description = "Python style guide checker" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycodestyle-2.11.1-py2.py3-none-any.whl", hash = "sha256:44fe31000b2d866f2e41841b18528a505fbd7fef9017b04eff4e2648a0fadc67"}, - {file = "pycodestyle-2.11.1.tar.gz", hash = "sha256:41ba0e7afc9752dfb53ced5489e89f8186be00e599e712660695b7a75ff2663f"}, -] - -[[package]] -name = "pycparser" -version = "2.22" -description = "C parser in Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, - {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, -] - -[[package]] -name = "pydantic" -version = "2.6.4" -description = "Data validation using Python type hints" -optional = false -python-versions = ">=3.8" -files = [ - {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.3" -typing-extensions = ">=4.6.1" - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.16.3" -description = "" -optional = false -python-versions = ">=3.8" -files = [ - {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] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pyflakes" -version = "3.2.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, - {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, -] - -[[package]] -name = "pyright" -version = "1.1.357" -description = "Command line wrapper for pyright" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pyright-1.1.357-py3-none-any.whl", hash = "sha256:1cf29ee38e4928131895cd8e90eef37b5b77e2ed72a14e6e8e2405266f5f0aca"}, - {file = "pyright-1.1.357.tar.gz", hash = "sha256:7c66261116c78c5fa9629134fe85c54cc5302ab73e376be4b0a99d89c80a9403"}, -] - -[package.dependencies] -nodeenv = ">=1.6.0" - -[package.extras] -all = ["twine (>=3.4.1)"] -dev = ["twine (>=3.4.1)"] - -[[package]] -name = "pysocks" -version = "1.7.1" -description = "A Python SOCKS client module. See https://github.com/Anorov/PySocks for more information." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "PySocks-1.7.1-py27-none-any.whl", hash = "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299"}, - {file = "PySocks-1.7.1-py3-none-any.whl", hash = "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5"}, - {file = "PySocks-1.7.1.tar.gz", hash = "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"}, -] - -[[package]] -name = "pytest" -version = "8.1.1" -description = "pytest: simple powerful testing with Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"}, - {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "sys_platform == \"win32\""} -iniconfig = "*" -packaging = "*" -pluggy = ">=1.4,<2.0" - -[package.extras] -testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] - -[[package]] -name = "pytest-cov" -version = "4.1.0" -description = "Pytest plugin for measuring coverage." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, - {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, -] - -[package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} -pytest = ">=4.6" - -[package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -description = "Extensions to the standard Python datetime module" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" -files = [ - {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, - {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, -] - -[package.dependencies] -six = ">=1.5" - -[[package]] -name = "python-dotenv" -version = "1.0.1" -description = "Read key-value pairs from a .env file and set them as environment variables" -optional = false -python-versions = ">=3.8" -files = [ - {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, - {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, -] - -[package.extras] -cli = ["click (>=5.0)"] - -[[package]] -name = "python-upwork-oauth2" -version = "3.1.0" -description = "Python bindings for Upwork API (OAuth2)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "python-upwork-oauth2-3.1.0.tar.gz", hash = "sha256:97e6fd2090b600f063c2ee924f4d71c6c13c0c5400d751be4d9613820fdd6b84"}, - {file = "python_upwork_oauth2-3.1.0-py3-none-any.whl", hash = "sha256:0f778f4dc6eee59da10a7bff980025508c3636eba71f0ca61a8e328f3a308877"}, -] - -[package.dependencies] -requests-oauthlib = ">=1.3.0" - -[[package]] -name = "pytz" -version = "2024.1" -description = "World timezone definitions, modern and historical" -optional = false -python-versions = "*" -files = [ - {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, - {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, -] - -[[package]] -name = "pyyaml" -version = "6.0.1" -description = "YAML parser and emitter for Python" -optional = false -python-versions = ">=3.6" -files = [ - {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, - {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, - {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"}, - {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, - {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_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, - {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"}, - {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, - {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, - {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, - {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, - {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, - {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, - {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"}, - {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, - {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"}, -] - -[[package]] -name = "realtime" -version = "1.0.3" -description = "" -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "realtime-1.0.3-py3-none-any.whl", hash = "sha256:809b99a1c09390a4580ca2d37d84c85dffacb1804f80c6f5a4491d312c20e6e3"}, - {file = "realtime-1.0.3.tar.gz", hash = "sha256:1a39b5dcdb345b4cc7fd43bc035feb38ca915c9248962f20d264625bc8eb2c4e"}, -] - -[package.dependencies] -python-dateutil = ">=2.8.1,<3.0.0" -typing-extensions = ">=4.2.0,<5.0.0" -websockets = ">=11,<13" - -[[package]] -name = "reddit-chatbot-python" -version = "1.4.9" -description = "an event-driven chatbot library for reddit chatrooms" -optional = false -python-versions = ">=3.6" -files = [ - {file = "Reddit_ChatBot_Python-1.4.9-py3-none-any.whl", hash = "sha256:71b0732c83db15410d622a7fb8bc0911d4a50d88640bfa35ef99b2e9845a08e9"}, - {file = "Reddit_ChatBot_Python-1.4.9.tar.gz", hash = "sha256:685dc0474760a9e19b73e225dd49cf86623c3c69403fdfa7e946129f981f731a"}, -] - -[package.dependencies] -requests = ">=2.26.0" -websocket-client = ">=1.2.3" - -[[package]] -name = "redis" -version = "5.0.3" -description = "Python client for Redis database and key-value store" -optional = false -python-versions = ">=3.7" -files = [ - {file = "redis-5.0.3-py3-none-any.whl", hash = "sha256:5da9b8fe9e1254293756c16c008e8620b3d15fcc6dde6babde9541850e72a32d"}, - {file = "redis-5.0.3.tar.gz", hash = "sha256:4973bae7444c0fbed64a06b87446f79361cb7e4ec1538c022d696ed7a5015580"}, -] - -[package.dependencies] -async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\""} - -[package.extras] -hiredis = ["hiredis (>=1.0.0)"] -ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"] - -[[package]] -name = "regex" -version = "2023.12.25" -description = "Alternative regular expression module, to replace re." -optional = false -python-versions = ">=3.7" -files = [ - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"}, - {file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"}, - {file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"}, - {file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"}, - {file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"}, - {file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"}, - {file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"}, - {file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"}, - {file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"}, - {file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"}, - {file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"}, - {file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"}, - {file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"}, - {file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"}, - {file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"}, - {file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"}, - {file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"}, - {file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"}, - {file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"}, - {file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"}, - {file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"}, - {file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"}, - {file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"}, - {file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"}, - {file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"}, - {file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"}, - {file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"}, - {file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"}, - {file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"}, - {file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"}, - {file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"}, - {file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"}, -] - -[[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -optional = false -python-versions = ">=3.7" -files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, -] - -[package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" - -[package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] - -[[package]] -name = "requests-oauthlib" -version = "2.0.0" -description = "OAuthlib authentication support for Requests." -optional = false -python-versions = ">=3.4" -files = [ - {file = "requests-oauthlib-2.0.0.tar.gz", hash = "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9"}, - {file = "requests_oauthlib-2.0.0-py2.py3-none-any.whl", hash = "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36"}, -] - -[package.dependencies] -oauthlib = ">=3.0.0" -requests = ">=2.0.0" - -[package.extras] -rsa = ["oauthlib[signedtoken] (>=3.0.0)"] - -[[package]] -name = "selenium" -version = "4.19.0" -description = "" -optional = false -python-versions = ">=3.8" -files = [ - {file = "selenium-4.19.0-py3-none-any.whl", hash = "sha256:5b4f49240d61e687a73f7968ae2517d403882aae3550eae2a229c745e619f1d9"}, - {file = "selenium-4.19.0.tar.gz", hash = "sha256:d9dfd6d0b021d71d0a48b865fe7746490ba82b81e9c87b212360006629eb1853"}, -] - -[package.dependencies] -certifi = ">=2021.10.8" -trio = ">=0.17,<1.0" -trio-websocket = ">=0.9,<1.0" -typing_extensions = ">=4.9.0" -urllib3 = {version = ">=1.26,<3", extras = ["socks"]} - -[[package]] -name = "setuptools" -version = "69.2.0" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"}, - {file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"}, -] - -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - -[[package]] -name = "six" -version = "1.16.0" -description = "Python 2 and 3 compatibility utilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, -] - -[[package]] -name = "sniffio" -version = "1.3.1" -description = "Sniff out which async library your code is running under" -optional = false -python-versions = ">=3.7" -files = [ - {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, - {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, -] - -[[package]] -name = "sortedcontainers" -version = "2.4.0" -description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" -optional = false -python-versions = "*" -files = [ - {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, - {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, -] - -[[package]] -name = "sqlalchemy" -version = "2.0.29" -description = "Database Abstraction Library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "SQLAlchemy-2.0.29-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c142852ae192e9fe5aad5c350ea6befe9db14370b34047e1f0f7cf99e63c63b"}, - {file = "SQLAlchemy-2.0.29-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99a1e69d4e26f71e750e9ad6fdc8614fbddb67cfe2173a3628a2566034e223c7"}, - {file = "SQLAlchemy-2.0.29-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef3fbccb4058355053c51b82fd3501a6e13dd808c8d8cd2561e610c5456013c"}, - {file = "SQLAlchemy-2.0.29-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d6753305936eddc8ed190e006b7bb33a8f50b9854823485eed3a886857ab8d1"}, - {file = "SQLAlchemy-2.0.29-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0f3ca96af060a5250a8ad5a63699180bc780c2edf8abf96c58af175921df847a"}, - {file = "SQLAlchemy-2.0.29-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c4520047006b1d3f0d89e0532978c0688219857eb2fee7c48052560ae76aca1e"}, - {file = "SQLAlchemy-2.0.29-cp310-cp310-win32.whl", hash = "sha256:b2a0e3cf0caac2085ff172c3faacd1e00c376e6884b5bc4dd5b6b84623e29e4f"}, - {file = "SQLAlchemy-2.0.29-cp310-cp310-win_amd64.whl", hash = "sha256:01d10638a37460616708062a40c7b55f73e4d35eaa146781c683e0fa7f6c43fb"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:308ef9cb41d099099fffc9d35781638986870b29f744382904bf9c7dadd08513"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:296195df68326a48385e7a96e877bc19aa210e485fa381c5246bc0234c36c78e"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a13b917b4ffe5a0a31b83d051d60477819ddf18276852ea68037a144a506efb9"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f6d971255d9ddbd3189e2e79d743ff4845c07f0633adfd1de3f63d930dbe673"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:61405ea2d563407d316c63a7b5271ae5d274a2a9fbcd01b0aa5503635699fa1e"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:de7202ffe4d4a8c1e3cde1c03e01c1a3772c92858837e8f3879b497158e4cb44"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-win32.whl", hash = "sha256:b5d7ed79df55a731749ce65ec20d666d82b185fa4898430b17cb90c892741520"}, - {file = "SQLAlchemy-2.0.29-cp311-cp311-win_amd64.whl", hash = "sha256:205f5a2b39d7c380cbc3b5dcc8f2762fb5bcb716838e2d26ccbc54330775b003"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d96710d834a6fb31e21381c6d7b76ec729bd08c75a25a5184b1089141356171f"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:52de4736404e53c5c6a91ef2698c01e52333988ebdc218f14c833237a0804f1b"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c7b02525ede2a164c5fa5014915ba3591730f2cc831f5be9ff3b7fd3e30958e"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0dfefdb3e54cd15f5d56fd5ae32f1da2d95d78319c1f6dfb9bcd0eb15d603d5d"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a88913000da9205b13f6f195f0813b6ffd8a0c0c2bd58d499e00a30eb508870c"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fecd5089c4be1bcc37c35e9aa678938d2888845a134dd016de457b942cf5a758"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-win32.whl", hash = "sha256:8197d6f7a3d2b468861ebb4c9f998b9df9e358d6e1cf9c2a01061cb9b6cf4e41"}, - {file = "SQLAlchemy-2.0.29-cp312-cp312-win_amd64.whl", hash = "sha256:9b19836ccca0d321e237560e475fd99c3d8655d03da80c845c4da20dda31b6e1"}, - {file = "SQLAlchemy-2.0.29-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:87a1d53a5382cdbbf4b7619f107cc862c1b0a4feb29000922db72e5a66a5ffc0"}, - {file = "SQLAlchemy-2.0.29-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0732dffe32333211801b28339d2a0babc1971bc90a983e3035e7b0d6f06b93"}, - {file = "SQLAlchemy-2.0.29-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90453597a753322d6aa770c5935887ab1fc49cc4c4fdd436901308383d698b4b"}, - {file = "SQLAlchemy-2.0.29-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ea311d4ee9a8fa67f139c088ae9f905fcf0277d6cd75c310a21a88bf85e130f5"}, - {file = "SQLAlchemy-2.0.29-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5f20cb0a63a3e0ec4e169aa8890e32b949c8145983afa13a708bc4b0a1f30e03"}, - {file = "SQLAlchemy-2.0.29-cp37-cp37m-win32.whl", hash = "sha256:e5bbe55e8552019c6463709b39634a5fc55e080d0827e2a3a11e18eb73f5cdbd"}, - {file = "SQLAlchemy-2.0.29-cp37-cp37m-win_amd64.whl", hash = "sha256:c2f9c762a2735600654c654bf48dad388b888f8ce387b095806480e6e4ff6907"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e614d7a25a43a9f54fcce4675c12761b248547f3d41b195e8010ca7297c369c"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:471fcb39c6adf37f820350c28aac4a7df9d3940c6548b624a642852e727ea586"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:988569c8732f54ad3234cf9c561364221a9e943b78dc7a4aaf35ccc2265f1930"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dddaae9b81c88083e6437de95c41e86823d150f4ee94bf24e158a4526cbead01"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:334184d1ab8f4c87f9652b048af3f7abea1c809dfe526fb0435348a6fef3d380"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:38b624e5cf02a69b113c8047cf7f66b5dfe4a2ca07ff8b8716da4f1b3ae81567"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-win32.whl", hash = "sha256:bab41acf151cd68bc2b466deae5deeb9e8ae9c50ad113444151ad965d5bf685b"}, - {file = "SQLAlchemy-2.0.29-cp38-cp38-win_amd64.whl", hash = "sha256:52c8011088305476691b8750c60e03b87910a123cfd9ad48576d6414b6ec2a1d"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3071ad498896907a5ef756206b9dc750f8e57352113c19272bdfdc429c7bd7de"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dba622396a3170974f81bad49aacebd243455ec3cc70615aeaef9e9613b5bca5"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b184e3de58009cc0bf32e20f137f1ec75a32470f5fede06c58f6c355ed42a72"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c37f1050feb91f3d6c32f864d8e114ff5545a4a7afe56778d76a9aec62638ba"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bda7ce59b06d0f09afe22c56714c65c957b1068dee3d5e74d743edec7daba552"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:25664e18bef6dc45015b08f99c63952a53a0a61f61f2e48a9e70cec27e55f699"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-win32.whl", hash = "sha256:77d29cb6c34b14af8a484e831ab530c0f7188f8efed1c6a833a2c674bf3c26ec"}, - {file = "SQLAlchemy-2.0.29-cp39-cp39-win_amd64.whl", hash = "sha256:04c487305ab035a9548f573763915189fc0fe0824d9ba28433196f8436f1449c"}, - {file = "SQLAlchemy-2.0.29-py3-none-any.whl", hash = "sha256:dc4ee2d4ee43251905f88637d5281a8d52e916a021384ec10758826f5cbae305"}, - {file = "SQLAlchemy-2.0.29.tar.gz", hash = "sha256:bd9566b8e58cabd700bc367b60e90d9349cd16f0984973f98a9a09f9c64e86f0"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} -typing-extensions = ">=4.6.0" - -[package.extras] -aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] -mssql = ["pyodbc"] -mssql-pymssql = ["pymssql"] -mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)"] -mysql = ["mysqlclient (>=1.4.0)"] -mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=8)"] -oracle-oracledb = ["oracledb (>=1.0.1)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.29.1)"] -postgresql-psycopg = ["psycopg (>=3.0.7)"] -postgresql-psycopg2binary = ["psycopg2-binary"] -postgresql-psycopg2cffi = ["psycopg2cffi"] -postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] -pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3_binary"] - -[[package]] -name = "starlette" -version = "0.37.2" -description = "The little ASGI library that shines." -optional = false -python-versions = ">=3.8" -files = [ - {file = "starlette-0.37.2-py3-none-any.whl", hash = "sha256:6fe59f29268538e5d0d182f2791a479a0c64638e6935d1c6989e63fb2699c6ee"}, - {file = "starlette-0.37.2.tar.gz", hash = "sha256:9af890290133b79fc3db55474ade20f6220a364a0402e0b556e7cd5e1e093823"}, -] - -[package.dependencies] -anyio = ">=3.4.0,<5" - -[package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] - -[[package]] -name = "storage3" -version = "0.7.4" -description = "Supabase Storage client for Python." -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "storage3-0.7.4-py3-none-any.whl", hash = "sha256:0b8e8839b10a64063796ce55a41462c7ffd6842e0ada74f25f5dcf37e1d1bade"}, - {file = "storage3-0.7.4.tar.gz", hash = "sha256:61fcbf836f566405981722abb7d56caa57025b261e7a316e73316701abf0c040"}, -] - -[package.dependencies] -httpx = ">=0.24,<0.28" -python-dateutil = ">=2.8.2,<3.0.0" -typing-extensions = ">=4.2.0,<5.0.0" - -[[package]] -name = "strenum" -version = "0.4.15" -description = "An Enum that inherits from str." -optional = false -python-versions = "*" -files = [ - {file = "StrEnum-0.4.15-py3-none-any.whl", hash = "sha256:a30cda4af7cc6b5bf52c8055bc4bf4b2b6b14a93b574626da33df53cf7740659"}, - {file = "StrEnum-0.4.15.tar.gz", hash = "sha256:878fb5ab705442070e4dd1929bb5e2249511c0bcf2b0eeacf3bcd80875c82eff"}, -] - -[package.extras] -docs = ["myst-parser[linkify]", "sphinx", "sphinx-rtd-theme"] -release = ["twine"] -test = ["pylint", "pytest", "pytest-black", "pytest-cov", "pytest-pylint"] - -[[package]] -name = "supabase" -version = "2.4.1" -description = "Supabase client for Python." -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "supabase-2.4.1-py3-none-any.whl", hash = "sha256:8b95744ce4ad24245ec23c090f273dfc9c2d9a53e3a80186959903947dbe1ed6"}, - {file = "supabase-2.4.1.tar.gz", hash = "sha256:a7dec0586f8931f378a45b2ffb28d8e37b3719f979c17f541b0156019144e645"}, -] - -[package.dependencies] -gotrue = ">=1.3,<3.0" -httpx = ">=0.24,<0.28" -postgrest = ">=0.10.8,<0.17.0" -realtime = ">=1.0.0,<2.0.0" -storage3 = ">=0.5.3,<0.8.0" -supafunc = ">=0.3.1,<0.5.0" - -[[package]] -name = "supafunc" -version = "0.4.5" -description = "Library for Supabase Functions" -optional = false -python-versions = "<4.0,>=3.8" -files = [ - {file = "supafunc-0.4.5-py3-none-any.whl", hash = "sha256:2208045f8f5c797924666f6a332efad75ad368f8030b2e4ceb9d2bf63f329373"}, - {file = "supafunc-0.4.5.tar.gz", hash = "sha256:a6466d78bdcaa58b7f0303793643103baae8106a87acd5d01e196179a9d0d024"}, -] - -[package.dependencies] -httpx = ">=0.24,<0.28" - -[[package]] -name = "tenacity" -version = "8.2.3" -description = "Retry code until it succeeds" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, - {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, -] - -[package.extras] -doc = ["reno", "sphinx", "tornado (>=4.5)"] - -[[package]] -name = "tiktoken" -version = "0.6.0" -description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" -optional = false -python-versions = ">=3.8" -files = [ - {file = "tiktoken-0.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:277de84ccd8fa12730a6b4067456e5cf72fef6300bea61d506c09e45658d41ac"}, - {file = "tiktoken-0.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c44433f658064463650d61387623735641dcc4b6c999ca30bc0f8ba3fccaf5c"}, - {file = "tiktoken-0.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:afb9a2a866ae6eef1995ab656744287a5ac95acc7e0491c33fad54d053288ad3"}, - {file = "tiktoken-0.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c62c05b3109fefca26fedb2820452a050074ad8e5ad9803f4652977778177d9f"}, - {file = "tiktoken-0.6.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0ef917fad0bccda07bfbad835525bbed5f3ab97a8a3e66526e48cdc3e7beacf7"}, - {file = "tiktoken-0.6.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e095131ab6092d0769a2fda85aa260c7c383072daec599ba9d8b149d2a3f4d8b"}, - {file = "tiktoken-0.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:05b344c61779f815038292a19a0c6eb7098b63c8f865ff205abb9ea1b656030e"}, - {file = "tiktoken-0.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cefb9870fb55dca9e450e54dbf61f904aab9180ff6fe568b61f4db9564e78871"}, - {file = "tiktoken-0.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:702950d33d8cabc039845674107d2e6dcabbbb0990ef350f640661368df481bb"}, - {file = "tiktoken-0.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8d49d076058f23254f2aff9af603863c5c5f9ab095bc896bceed04f8f0b013a"}, - {file = "tiktoken-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:430bc4e650a2d23a789dc2cdca3b9e5e7eb3cd3935168d97d43518cbb1f9a911"}, - {file = "tiktoken-0.6.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:293cb8669757301a3019a12d6770bd55bec38a4d3ee9978ddbe599d68976aca7"}, - {file = "tiktoken-0.6.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7bd1a288b7903aadc054b0e16ea78e3171f70b670e7372432298c686ebf9dd47"}, - {file = "tiktoken-0.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:ac76e000183e3b749634968a45c7169b351e99936ef46f0d2353cd0d46c3118d"}, - {file = "tiktoken-0.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:17cc8a4a3245ab7d935c83a2db6bb71619099d7284b884f4b2aea4c74f2f83e3"}, - {file = "tiktoken-0.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:284aebcccffe1bba0d6571651317df6a5b376ff6cfed5aeb800c55df44c78177"}, - {file = "tiktoken-0.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c1a3a5d33846f8cd9dd3b7897c1d45722f48625a587f8e6f3d3e85080559be8"}, - {file = "tiktoken-0.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6318b2bb2337f38ee954fd5efa82632c6e5ced1d52a671370fa4b2eff1355e91"}, - {file = "tiktoken-0.6.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1f5f0f2ed67ba16373f9a6013b68da298096b27cd4e1cf276d2d3868b5c7efd1"}, - {file = "tiktoken-0.6.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:75af4c0b16609c2ad02581f3cdcd1fb698c7565091370bf6c0cf8624ffaba6dc"}, - {file = "tiktoken-0.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:45577faf9a9d383b8fd683e313cf6df88b6076c034f0a16da243bb1c139340c3"}, - {file = "tiktoken-0.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c1492ab90c21ca4d11cef3a236ee31a3e279bb21b3fc5b0e2210588c4209e68"}, - {file = "tiktoken-0.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e2b380c5b7751272015400b26144a2bab4066ebb8daae9c3cd2a92c3b508fe5a"}, - {file = "tiktoken-0.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9f497598b9f58c99cbc0eb764b4a92272c14d5203fc713dd650b896a03a50ad"}, - {file = "tiktoken-0.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e65e8bd6f3f279d80f1e1fbd5f588f036b9a5fa27690b7f0cc07021f1dfa0839"}, - {file = "tiktoken-0.6.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5f1495450a54e564d236769d25bfefbf77727e232d7a8a378f97acddee08c1ae"}, - {file = "tiktoken-0.6.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6c4e4857d99f6fb4670e928250835b21b68c59250520a1941618b5b4194e20c3"}, - {file = "tiktoken-0.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:168d718f07a39b013032741867e789971346df8e89983fe3c0ef3fbd5a0b1cb9"}, - {file = "tiktoken-0.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:47fdcfe11bd55376785a6aea8ad1db967db7f66ea81aed5c43fad497521819a4"}, - {file = "tiktoken-0.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fb7d2ccbf1a7784810aff6b80b4012fb42c6fc37eaa68cb3b553801a5cc2d1fc"}, - {file = "tiktoken-0.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1ccb7a111ee76af5d876a729a347f8747d5ad548e1487eeea90eaf58894b3138"}, - {file = "tiktoken-0.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2048e1086b48e3c8c6e2ceeac866561374cd57a84622fa49a6b245ffecb7744"}, - {file = "tiktoken-0.6.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07f229a5eb250b6403a61200199cecf0aac4aa23c3ecc1c11c1ca002cbb8f159"}, - {file = "tiktoken-0.6.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:432aa3be8436177b0db5a2b3e7cc28fd6c693f783b2f8722539ba16a867d0c6a"}, - {file = "tiktoken-0.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:8bfe8a19c8b5c40d121ee7938cd9c6a278e5b97dc035fd61714b4f0399d2f7a1"}, - {file = "tiktoken-0.6.0.tar.gz", hash = "sha256:ace62a4ede83c75b0374a2ddfa4b76903cf483e9cb06247f566be3bf14e6beed"}, -] - -[package.dependencies] -regex = ">=2022.1.18" -requests = ">=2.26.0" - -[package.extras] -blobfile = ["blobfile (>=2)"] - -[[package]] -name = "tqdm" -version = "4.66.2" -description = "Fast, Extensible Progress Meter" -optional = false -python-versions = ">=3.7" -files = [ - {file = "tqdm-4.66.2-py3-none-any.whl", hash = "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9"}, - {file = "tqdm-4.66.2.tar.gz", hash = "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - -[package.extras] -dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] -notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] - -[[package]] -name = "trio" -version = "0.25.0" -description = "A friendly Python library for async concurrency and I/O" -optional = false -python-versions = ">=3.8" -files = [ - {file = "trio-0.25.0-py3-none-any.whl", hash = "sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81"}, - {file = "trio-0.25.0.tar.gz", hash = "sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e"}, -] - -[package.dependencies] -attrs = ">=23.2.0" -cffi = {version = ">=1.14", markers = "os_name == \"nt\" and implementation_name != \"pypy\""} -idna = "*" -outcome = "*" -sniffio = ">=1.3.0" -sortedcontainers = "*" - -[[package]] -name = "trio-websocket" -version = "0.11.1" -description = "WebSocket library for Trio" -optional = false -python-versions = ">=3.7" -files = [ - {file = "trio-websocket-0.11.1.tar.gz", hash = "sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f"}, - {file = "trio_websocket-0.11.1-py3-none-any.whl", hash = "sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"}, -] - -[package.dependencies] -trio = ">=0.11" -wsproto = ">=0.14" - -[[package]] -name = "typing-extensions" -version = "4.11.0" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, -] - -[[package]] -name = "typing-inspect" -version = "0.9.0" -description = "Runtime inspection utilities for typing module." -optional = false -python-versions = "*" -files = [ - {file = "typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f"}, - {file = "typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78"}, -] - -[package.dependencies] -mypy-extensions = ">=0.3.0" -typing-extensions = ">=3.7.4" - -[[package]] -name = "tzdata" -version = "2024.1" -description = "Provider of IANA time zone data" -optional = false -python-versions = ">=2" -files = [ - {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, - {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, -] - -[[package]] -name = "update-checker" -version = "0.18.0" -description = "A python module that will check for package updates." -optional = false -python-versions = "*" -files = [ - {file = "update_checker-0.18.0-py3-none-any.whl", hash = "sha256:cbba64760a36fe2640d80d85306e8fe82b6816659190993b7bdabadee4d4bbfd"}, - {file = "update_checker-0.18.0.tar.gz", hash = "sha256:6a2d45bb4ac585884a6b03f9eade9161cedd9e8111545141e9aa9058932acb13"}, -] - -[package.dependencies] -requests = ">=2.3.0" - -[package.extras] -dev = ["black", "flake8", "pytest (>=2.7.3)"] -lint = ["black", "flake8"] -test = ["pytest (>=2.7.3)"] - -[[package]] -name = "urllib3" -version = "2.2.1" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.8" -files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, -] - -[package.dependencies] -pysocks = {version = ">=1.5.6,<1.5.7 || >1.5.7,<2.0", optional = true, markers = "extra == \"socks\""} - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -h2 = ["h2 (>=4,<5)"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - -[[package]] -name = "uvicorn" -version = "0.27.1" -description = "The lightning-fast ASGI server." -optional = false -python-versions = ">=3.8" -files = [ - {file = "uvicorn-0.27.1-py3-none-any.whl", hash = "sha256:5c89da2f3895767472a35556e539fd59f7edbe9b1e9c0e1c99eebeadc61838e4"}, - {file = "uvicorn-0.27.1.tar.gz", hash = "sha256:3d9a267296243532db80c83a959a3400502165ade2c1338dea4e67915fd4745a"}, -] - -[package.dependencies] -click = ">=7.0" -h11 = ">=0.8" - -[package.extras] -standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] - -[[package]] -name = "websocket-client" -version = "1.7.0" -description = "WebSocket client for Python with low level API options" -optional = false -python-versions = ">=3.8" -files = [ - {file = "websocket-client-1.7.0.tar.gz", hash = "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6"}, - {file = "websocket_client-1.7.0-py3-none-any.whl", hash = "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588"}, -] - -[package.extras] -docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] -optional = ["python-socks", "wsaccel"] -test = ["websockets"] - -[[package]] -name = "websockets" -version = "12.0" -description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" -optional = false -python-versions = ">=3.8" -files = [ - {file = "websockets-12.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d554236b2a2006e0ce16315c16eaa0d628dab009c33b63ea03f41c6107958374"}, - {file = "websockets-12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2d225bb6886591b1746b17c0573e29804619c8f755b5598d875bb4235ea639be"}, - {file = "websockets-12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:eb809e816916a3b210bed3c82fb88eaf16e8afcf9c115ebb2bacede1797d2547"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c588f6abc13f78a67044c6b1273a99e1cf31038ad51815b3b016ce699f0d75c2"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5aa9348186d79a5f232115ed3fa9020eab66d6c3437d72f9d2c8ac0c6858c558"}, - {file = "websockets-12.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6350b14a40c95ddd53e775dbdbbbc59b124a5c8ecd6fbb09c2e52029f7a9f480"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:70ec754cc2a769bcd218ed8d7209055667b30860ffecb8633a834dde27d6307c"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6e96f5ed1b83a8ddb07909b45bd94833b0710f738115751cdaa9da1fb0cb66e8"}, - {file = "websockets-12.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4d87be612cbef86f994178d5186add3d94e9f31cc3cb499a0482b866ec477603"}, - {file = "websockets-12.0-cp310-cp310-win32.whl", hash = "sha256:befe90632d66caaf72e8b2ed4d7f02b348913813c8b0a32fae1cc5fe3730902f"}, - {file = "websockets-12.0-cp310-cp310-win_amd64.whl", hash = "sha256:363f57ca8bc8576195d0540c648aa58ac18cf85b76ad5202b9f976918f4219cf"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5d873c7de42dea355d73f170be0f23788cf3fa9f7bed718fd2830eefedce01b4"}, - {file = "websockets-12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3f61726cae9f65b872502ff3c1496abc93ffbe31b278455c418492016e2afc8f"}, - {file = "websockets-12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed2fcf7a07334c77fc8a230755c2209223a7cc44fc27597729b8ef5425aa61a3"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e332c210b14b57904869ca9f9bf4ca32f5427a03eeb625da9b616c85a3a506c"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5693ef74233122f8ebab026817b1b37fe25c411ecfca084b29bc7d6efc548f45"}, - {file = "websockets-12.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e9e7db18b4539a29cc5ad8c8b252738a30e2b13f033c2d6e9d0549b45841c04"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6e2df67b8014767d0f785baa98393725739287684b9f8d8a1001eb2839031447"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bea88d71630c5900690fcb03161ab18f8f244805c59e2e0dc4ffadae0a7ee0ca"}, - {file = "websockets-12.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dff6cdf35e31d1315790149fee351f9e52978130cef6c87c4b6c9b3baf78bc53"}, - {file = "websockets-12.0-cp311-cp311-win32.whl", hash = "sha256:3e3aa8c468af01d70332a382350ee95f6986db479ce7af14d5e81ec52aa2b402"}, - {file = "websockets-12.0-cp311-cp311-win_amd64.whl", hash = "sha256:25eb766c8ad27da0f79420b2af4b85d29914ba0edf69f547cc4f06ca6f1d403b"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0e6e2711d5a8e6e482cacb927a49a3d432345dfe7dea8ace7b5790df5932e4df"}, - {file = "websockets-12.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:dbcf72a37f0b3316e993e13ecf32f10c0e1259c28ffd0a85cee26e8549595fbc"}, - {file = "websockets-12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12743ab88ab2af1d17dd4acb4645677cb7063ef4db93abffbf164218a5d54c6b"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b645f491f3c48d3f8a00d1fce07445fab7347fec54a3e65f0725d730d5b99cb"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9893d1aa45a7f8b3bc4510f6ccf8db8c3b62120917af15e3de247f0780294b92"}, - {file = "websockets-12.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f38a7b376117ef7aff996e737583172bdf535932c9ca021746573bce40165ed"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f764ba54e33daf20e167915edc443b6f88956f37fb606449b4a5b10ba42235a5"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1e4b3f8ea6a9cfa8be8484c9221ec0257508e3a1ec43c36acdefb2a9c3b00aa2"}, - {file = "websockets-12.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9fdf06fd06c32205a07e47328ab49c40fc1407cdec801d698a7c41167ea45113"}, - {file = "websockets-12.0-cp312-cp312-win32.whl", hash = "sha256:baa386875b70cbd81798fa9f71be689c1bf484f65fd6fb08d051a0ee4e79924d"}, - {file = "websockets-12.0-cp312-cp312-win_amd64.whl", hash = "sha256:ae0a5da8f35a5be197f328d4727dbcfafa53d1824fac3d96cdd3a642fe09394f"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5f6ffe2c6598f7f7207eef9a1228b6f5c818f9f4d53ee920aacd35cec8110438"}, - {file = "websockets-12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9edf3fc590cc2ec20dc9d7a45108b5bbaf21c0d89f9fd3fd1685e223771dc0b2"}, - {file = "websockets-12.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8572132c7be52632201a35f5e08348137f658e5ffd21f51f94572ca6c05ea81d"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:604428d1b87edbf02b233e2c207d7d528460fa978f9e391bd8aaf9c8311de137"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a9d160fd080c6285e202327aba140fc9a0d910b09e423afff4ae5cbbf1c7205"}, - {file = "websockets-12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87b4aafed34653e465eb77b7c93ef058516cb5acf3eb21e42f33928616172def"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b2ee7288b85959797970114deae81ab41b731f19ebcd3bd499ae9ca0e3f1d2c8"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7fa3d25e81bfe6a89718e9791128398a50dec6d57faf23770787ff441d851967"}, - {file = "websockets-12.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a571f035a47212288e3b3519944f6bf4ac7bc7553243e41eac50dd48552b6df7"}, - {file = "websockets-12.0-cp38-cp38-win32.whl", hash = "sha256:3c6cc1360c10c17463aadd29dd3af332d4a1adaa8796f6b0e9f9df1fdb0bad62"}, - {file = "websockets-12.0-cp38-cp38-win_amd64.whl", hash = "sha256:1bf386089178ea69d720f8db6199a0504a406209a0fc23e603b27b300fdd6892"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ab3d732ad50a4fbd04a4490ef08acd0517b6ae6b77eb967251f4c263011a990d"}, - {file = "websockets-12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1d9697f3337a89691e3bd8dc56dea45a6f6d975f92e7d5f773bc715c15dde28"}, - {file = "websockets-12.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1df2fbd2c8a98d38a66f5238484405b8d1d16f929bb7a33ed73e4801222a6f53"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23509452b3bc38e3a057382c2e941d5ac2e01e251acce7adc74011d7d8de434c"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e5fc14ec6ea568200ea4ef46545073da81900a2b67b3e666f04adf53ad452ec"}, - {file = "websockets-12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46e71dbbd12850224243f5d2aeec90f0aaa0f2dde5aeeb8fc8df21e04d99eff9"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b81f90dcc6c85a9b7f29873beb56c94c85d6f0dac2ea8b60d995bd18bf3e2aae"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a02413bc474feda2849c59ed2dfb2cddb4cd3d2f03a2fedec51d6e959d9b608b"}, - {file = "websockets-12.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bbe6013f9f791944ed31ca08b077e26249309639313fff132bfbf3ba105673b9"}, - {file = "websockets-12.0-cp39-cp39-win32.whl", hash = "sha256:cbe83a6bbdf207ff0541de01e11904827540aa069293696dd528a6640bd6a5f6"}, - {file = "websockets-12.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc4e7fa5414512b481a2483775a8e8be7803a35b30ca805afa4998a84f9fd9e8"}, - {file = "websockets-12.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:248d8e2446e13c1d4326e0a6a4e9629cb13a11195051a73acf414812700badbd"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f44069528d45a933997a6fef143030d8ca8042f0dfaad753e2906398290e2870"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c4e37d36f0d19f0a4413d3e18c0d03d0c268ada2061868c1e6f5ab1a6d575077"}, - {file = "websockets-12.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d829f975fc2e527a3ef2f9c8f25e553eb7bc779c6665e8e1d52aa22800bb38b"}, - {file = "websockets-12.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2c71bd45a777433dd9113847af751aae36e448bc6b8c361a566cb043eda6ec30"}, - {file = "websockets-12.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0bee75f400895aef54157b36ed6d3b308fcab62e5260703add87f44cee9c82a6"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:423fc1ed29f7512fceb727e2d2aecb952c46aa34895e9ed96071821309951123"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27a5e9964ef509016759f2ef3f2c1e13f403725a5e6a1775555994966a66e931"}, - {file = "websockets-12.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3181df4583c4d3994d31fb235dc681d2aaad744fbdbf94c4802485ececdecf2"}, - {file = "websockets-12.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b067cb952ce8bf40115f6c19f478dc71c5e719b7fbaa511359795dfd9d1a6468"}, - {file = "websockets-12.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:00700340c6c7ab788f176d118775202aadea7602c5cc6be6ae127761c16d6b0b"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e469d01137942849cff40517c97a30a93ae79917752b34029f0ec72df6b46399"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffefa1374cd508d633646d51a8e9277763a9b78ae71324183693959cf94635a7"}, - {file = "websockets-12.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba0cab91b3956dfa9f512147860783a1829a8d905ee218a9837c18f683239611"}, - {file = "websockets-12.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2cb388a5bfb56df4d9a406783b7f9dbefb888c09b71629351cc6b036e9259370"}, - {file = "websockets-12.0-py3-none-any.whl", hash = "sha256:dc284bbc8d7c78a6c69e0c7325ab46ee5e40bb4d50e494d8131a07ef47500e9e"}, - {file = "websockets-12.0.tar.gz", hash = "sha256:81df9cbcbb6c260de1e007e58c011bfebe2dafc8435107b0537f393dd38c8b1b"}, -] - -[[package]] -name = "wsproto" -version = "1.2.0" -description = "WebSockets state-machine based protocol implementation" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"}, - {file = "wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065"}, -] - -[package.dependencies] -h11 = ">=0.9.0,<1" - -[[package]] -name = "yarl" -version = "1.9.4" -description = "Yet another URL library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, -] - -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" - -[metadata] -lock-version = "2.0" -python-versions = ">=3.11,<3.13" -content-hash = "9cb7ae5fc1426e07b7938da4118d665fc3549e57acf28d3deb21b1121654ce51" diff --git a/apps/rest/api/shell.nix b/apps/rest/api/shell.nix index 4ccfc6db..11446ff6 100644 --- a/apps/rest/api/shell.nix +++ b/apps/rest/api/shell.nix @@ -3,7 +3,6 @@ name = "pipzone"; targetPkgs = pkgs: (with pkgs; [ python312 - poetry ]); runScript = "fish"; }).env From 93d9e3f6c9bcd97ea16ad2f4ffce7dacf6185d9c Mon Sep 17 00:00:00 2001 From: Jonas Lindberg Date: Fri, 3 May 2024 08:11:08 +0000 Subject: [PATCH 06/76] convert rest to using new organizational fastapi structure --- apps/rest/api/logging.yaml | 22 ++++ apps/rest/api/src/__init__.py | 186 +++++------------------------ apps/rest/api/src/routers/index.py | 133 +++++++++++++++++++++ 3 files changed, 187 insertions(+), 154 deletions(-) create mode 100644 apps/rest/api/logging.yaml create mode 100644 apps/rest/api/src/routers/index.py diff --git a/apps/rest/api/logging.yaml b/apps/rest/api/logging.yaml new file mode 100644 index 00000000..7286f53d --- /dev/null +++ b/apps/rest/api/logging.yaml @@ -0,0 +1,22 @@ +version: 1 +disable_existing_loggers: false + +formatters: + standard: + format: "%(asctime)s - %(levelname)s - %(message)s" + +handlers: + console: + class: logging.StreamHandler + formatter: standard + stream: ext://sys.stdout + +loggers: + uvicorn: + error: + propagate: true + +root: + level: INFO + handlers: [console] + propagate: no diff --git a/apps/rest/api/src/__init__.py b/apps/rest/api/src/__init__.py index ce75d20e..c29fa41b 100644 --- a/apps/rest/api/src/__init__.py +++ b/apps/rest/api/src/__init__.py @@ -1,163 +1,41 @@ -import os -from dotenv import load_dotenv -import logging -import diskcache as dc -import threading -from uuid import uuid4 +import uvicorn -from .saving import update_db_with_submission -from . import mail -from .reddit_utils import get_subreddits -from .relevance_bot import evaluate_relevance -from .interfaces import db -from . import comment_bot -from .models import PublishCommentRequest, GenerateCommentRequest, FalseLead, Lead -from .reddit_worker import RedditStreamWorker -from . import upwork_worker - -from fastapi import FastAPI, HTTPException +from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from fastapi.responses import RedirectResponse - - -# Relevant subreddits to Startino -SUBREDDIT_NAMES = ( - "SaaS+SaaSy+startups+YoungEntrepreneurs+NoCodeSaas+nocode+cofounder+Entrepreneur" -) - -load_dotenv() -REDDIT_PASSWORD = os.getenv("REDDIT_PASSWORD") -REDDIT_USERNAME = os.getenv("REDDIT_USERNAME") - -if REDDIT_PASSWORD is None: - raise ValueError("REDDIT_PASSWORD is not set") - -if REDDIT_USERNAME is None: - raise ValueError("REDDIT_USERNAME is not set") - -logger = logging.getLogger("root") - -app = FastAPI() -workers = {} - -app.add_middleware( - CORSMiddleware, - allow_origins=[ - "http://localhost:5173", - "http://localhost:5174", - "http://localhost:8000", - "http://localhost:8001", - "http://localhost:8080", - "http://localhost:8081", - "http://127.0.0.1:5173", - "http://127.0.0.1:5174", - "http://127.0.0.1:8000", - "http://127.0.0.1:8001", - "http://127.0.0.1:8080", - "http://127.0.0.1:8081", - "https://aiti.no", - "https://api.aiti.no", - ], - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - - -@app.get("/") -def redirect_to_docs() -> RedirectResponse: - return RedirectResponse(url="/docs") - - -@app.get("/test") -def test(): - print("TEST") - db.post_lead( - Lead( - id=uuid4(), - submission_id=uuid4(), - reddit_id="test", - prospect_username="test", - source="test", - last_event="test", - status="test", - data={"test": "test"}, - ) - ) - -@app.post("/start") -def start_stream(): - worker_id = str(uuid4()) - worker = RedditStreamWorker(SUBREDDIT_NAMES, REDDIT_USERNAME, REDDIT_PASSWORD) - thread = threading.Thread(target=worker.start) - workers[worker_id] = (worker, thread) - thread.start() - return {"worker_id": worker_id} - - -@app.post("/stop/{worker_id}") -def stop_stream(worker_id: str): - worker, thread = workers.get(worker_id, (None, None)) - if worker is None: - raise HTTPException(status_code=404, detail="Worker not found") - worker.stop() - thread.join(timeout=10) # Waits 10 seconds for the thread to finish - - if thread.is_alive(): - logger.error(f"Thread for Reddit worker didn't stop in time") - - del workers[worker_id] # Cleanup - - return {"message": "Stream stopped"} - - -@app.post("/generate-comment") -def generate_comment(generate_request: GenerateCommentRequest): - comment: str = comment_bot.generate_comment( - generate_request.title, - generate_request.selftext, +def create_app() -> FastAPI: + app = FastAPI() + + app.add_middleware( + CORSMiddleware, + allow_origins=[ + "http://localhost:5173", + "http://localhost:5174", + "http://localhost:8000", + "http://localhost:8001", + "http://localhost:8080", + "http://localhost:8081", + "http://127.0.0.1:5173", + "http://127.0.0.1:5174", + "http://127.0.0.1:8000", + "http://127.0.0.1:8001", + "http://127.0.0.1:8080", + "http://127.0.0.1:8081", + "https://rest.futi.no", + "https://api.rest.futi.no", + ], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], ) - if comment is None: - raise HTTPException(404, "comment not found") - - return comment + return app -@app.post("/mark-lead-as-irrelevant") -def mark_lead_as_irrelevant(false_lead: FalseLead): - # Mark the lead as irrelevant in 'leads' table - lead = db.update_lead(id=false_lead.lead_id, status="rejected") - - if lead is None: - raise HTTPException(404, "lead not found") - - # Mark the submission as irrelevant in 'evaluated_submissions' table as a - # human answer and review - db.update_human_review_for_submission( - id=false_lead.submission_id, - human_answer=False, - correct_reason=false_lead.correct_reason, - ) - - return {"status": "success"} - - -@app.post("/publish-comment") -def publish_comment(publish_request: PublishCommentRequest): - updated_content = comment_bot.publish_comment( - publish_request.lead_id, - publish_request.comment, - publish_request.reddit_username, - publish_request.reddit_password, - ) - if updated_content is None: - raise HTTPException(404, "lead not found") +def run(): + app = create_app() - return updated_content + uvicorn.run(app, host="0.0.0.0", port=8000, log_config="logging.yaml") -@app.get("/generate-proposal") -def generate_proposal(post: str): - proposal = upwork_worker.generate_proposal(post) - return proposal +if __name__ == "__main__": + run() diff --git a/apps/rest/api/src/routers/index.py b/apps/rest/api/src/routers/index.py new file mode 100644 index 00000000..b1c32022 --- /dev/null +++ b/apps/rest/api/src/routers/index.py @@ -0,0 +1,133 @@ +import logging +from fastapi import APIRouter +from fastapi.responses import RedirectResponse +import os +from dotenv import load_dotenv +import threading +from uuid import uuid4 + +from src.interfaces import db +from src import comment_bot +from src.models import PublishCommentRequest, GenerateCommentRequest, FalseLead, Lead +from src.reddit_worker import RedditStreamWorker +from src import upwork_worker + +from fastapi import HTTPException +from fastapi.responses import RedirectResponse + +# Relevant subreddits to Startino +SUBREDDIT_NAMES = ( + "SaaS+SaaSy+startups+YoungEntrepreneurs+NoCodeSaas+nocode+cofounder+Entrepreneur" +) + +load_dotenv() +REDDIT_PASSWORD = os.getenv("REDDIT_PASSWORD") +REDDIT_USERNAME = os.getenv("REDDIT_USERNAME") + +if REDDIT_PASSWORD is None: + raise ValueError("REDDIT_PASSWORD is not set") + +if REDDIT_USERNAME is None: + raise ValueError("REDDIT_USERNAME is not set") + +workers = {} + +router = APIRouter() + +@router.get("/") +def redirect_to_docs() -> RedirectResponse: + return RedirectResponse(url="/docs") + + +@router.get("/test") +def test(): + print("TEST") + db.post_lead( + Lead( + id=uuid4(), + submission_id=uuid4(), + reddit_id="test", + prospect_username="test", + source="test", + last_event="test", + status="test", + data={"test": "test"}, + ) + ) + + +@router.post("/start") +def start_stream(): + worker_id = str(uuid4()) + worker = RedditStreamWorker(SUBREDDIT_NAMES, REDDIT_USERNAME, REDDIT_PASSWORD) + thread = threading.Thread(target=worker.start) + workers[worker_id] = (worker, thread) + thread.start() + return {"worker_id": worker_id} + + +@router.post("/stop/{worker_id}") +def stop_stream(worker_id: str): + worker, thread = workers.get(worker_id, (None, None)) + if worker is None: + raise HTTPException(status_code=404, detail="Worker not found") + worker.stop() + thread.join(timeout=10) # Waits 10 seconds for the thread to finish + + if thread.is_alive(): + logging.error(f"Thread for Reddit worker didn't stop in time") + + del workers[worker_id] # Cleanup + + return {"message": "Stream stopped"} + + +@router.post("/generate-comment") +def generate_comment(generate_request: GenerateCommentRequest): + comment: str = comment_bot.generate_comment( + generate_request.title, + generate_request.selftext, + ) + if comment is None: + raise HTTPException(404, "comment not found") + + return comment + + +@router.post("/mark-lead-as-irrelevant") +def mark_lead_as_irrelevant(false_lead: FalseLead): + # Mark the lead as irrelevant in 'leads' table + lead = db.update_lead(id=false_lead.lead_id, status="rejected") + + if lead is None: + raise HTTPException(404, "lead not found") + + # Mark the submission as irrelevant in 'evaluated_submissions' table as a + # human answer and review + db.update_human_review_for_submission( + id=false_lead.submission_id, + human_answer=False, + correct_reason=false_lead.correct_reason, + ) + + return {"status": "success"} + + +@router.post("/publish-comment") +def publish_comment(publish_request: PublishCommentRequest): + updated_content = comment_bot.publish_comment( + publish_request.lead_id, + publish_request.comment, + publish_request.reddit_username, + publish_request.reddit_password, + ) + if updated_content is None: + raise HTTPException(404, "lead not found") + + return updated_content + + +@router.get("/generate-proposal") +def generate_proposal(post: str): + proposal = upwork_worker.generate_proposal(post) + return proposal From ff36f7934c45abde1c5abdddf666e5855468cb4c Mon Sep 17 00:00:00 2001 From: Jonas Lindberg Date: Fri, 3 May 2024 08:13:07 +0000 Subject: [PATCH 07/76] whops forgor router --- apps/rest/api/src/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/rest/api/src/__init__.py b/apps/rest/api/src/__init__.py index c29fa41b..886556ad 100644 --- a/apps/rest/api/src/__init__.py +++ b/apps/rest/api/src/__init__.py @@ -2,10 +2,12 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware +from src.routers import index def create_app() -> FastAPI: app = FastAPI() + app.include_router(index.router) app.add_middleware( CORSMiddleware, allow_origins=[ From f66880fb2c8c0e5a2628578334bae94ffea9e38a Mon Sep 17 00:00:00 2001 From: antopiahk Date: Wed, 15 May 2024 17:27:30 +0700 Subject: [PATCH 08/76] adding option for adding instructions to generate comment and improving promptws --- apps/rest/api/hello | 1 + apps/rest/api/src/comment_bot.py | 6 +++++- apps/rest/api/src/models/reddit_comment.py | 3 ++- apps/rest/api/src/prompts/commenting.py | 9 +++++---- apps/rest/api/src/prompts/startino_business_plan.md | 4 ++-- apps/rest/api/src/routers/index.py | 3 ++- 6 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 apps/rest/api/hello diff --git a/apps/rest/api/hello b/apps/rest/api/hello new file mode 100644 index 00000000..b4785957 --- /dev/null +++ b/apps/rest/api/hello @@ -0,0 +1 @@ +s diff --git a/apps/rest/api/src/comment_bot.py b/apps/rest/api/src/comment_bot.py index d230f984..e7c2b32e 100644 --- a/apps/rest/api/src/comment_bot.py +++ b/apps/rest/api/src/comment_bot.py @@ -31,12 +31,15 @@ def generate_comment(title: str, selftext: str, instructions: str = "") -> str: # Post Title: {title} Content: {selftext} + + # Additional instructions + {instructions} """ ) prompt = PromptTemplate( template=template, - input_variables=["title", "selftext"], + input_variables=["title", "selftext", "instructions"], partial_variables={"format_instructions": parser.get_format_instructions()}, ) @@ -47,6 +50,7 @@ def generate_comment(title: str, selftext: str, instructions: str = "") -> str: { "title": title, "selftext": selftext, + "instructions": instructions, } ) diff --git a/apps/rest/api/src/models/reddit_comment.py b/apps/rest/api/src/models/reddit_comment.py index b8823d42..7ffd3682 100644 --- a/apps/rest/api/src/models/reddit_comment.py +++ b/apps/rest/api/src/models/reddit_comment.py @@ -2,7 +2,7 @@ from langchain.prompts import PromptTemplate from langchain_core.pydantic_v1 import BaseModel, Field, validator from pydantic import BaseModel as PydanticBaseModel - +from typing import Optional class RedditComment(BaseModel): comment: str = Field(description="the text of the reddit comment") @@ -12,3 +12,4 @@ class RedditComment(BaseModel): class GenerateCommentRequest(PydanticBaseModel): title: str selftext: str + instructions: str = "" diff --git a/apps/rest/api/src/prompts/commenting.py b/apps/rest/api/src/prompts/commenting.py index 7c7e42a7..e8e11808 100644 --- a/apps/rest/api/src/prompts/commenting.py +++ b/apps/rest/api/src/prompts/commenting.py @@ -18,7 +18,8 @@ bad_examples = file.read() purpose = """ -Introduce myself and Futino and quickly capture interest with a relevant value proposition, setting the stage for further engagement and relationship building. +Introduce myself and Startino and quickly capture interest with a relevant value proposition, setting the stage for further engagement and relationship building. +Sometimes, if they are simply looking for advice, write a valuable comment, rather than trying to sell them. This is because I will later try to sell them after they respond. """ context = f""" @@ -27,9 +28,9 @@ guidance = """ - Keep the comment concise and to the point. -- Don't mention about cost effectiveness of Futino. -- Mention how we gaurantee our dedication through our services for equity model. -- Do not mention how much equity we are willing to take. +- Don't mention about cost effectiveness of Startino. +- Do not mention how we gaurantee our dedication through our services for equity model. +- Do not mention the equity for services model or anything about equity. - You may mention that we sometimes take equity if the post is a startup. - Do not use more than 50 words. """ diff --git a/apps/rest/api/src/prompts/startino_business_plan.md b/apps/rest/api/src/prompts/startino_business_plan.md index 18a1ddde..e67faca6 100644 --- a/apps/rest/api/src/prompts/startino_business_plan.md +++ b/apps/rest/api/src/prompts/startino_business_plan.md @@ -1,8 +1,8 @@ -# Futino Business Plan +# Startino Business Plan ### Identity -Futino combines the upsides of a tech co-founder with a development agency, eliminating the downsides typically associated with each. +Startino combines the upsides of a tech co-founder with a development agency, eliminating the downsides typically associated with each. ### Problem diff --git a/apps/rest/api/src/routers/index.py b/apps/rest/api/src/routers/index.py index b1c32022..9526be5a 100644 --- a/apps/rest/api/src/routers/index.py +++ b/apps/rest/api/src/routers/index.py @@ -17,7 +17,7 @@ # Relevant subreddits to Startino SUBREDDIT_NAMES = ( - "SaaS+SaaSy+startups+YoungEntrepreneurs+NoCodeSaas+nocode+cofounder+Entrepreneur" + "SaaS+SaaSy+startups+YoungEntrepreneurs+NoCodeSaas+nocode+cofounder+Entrepreneur+futino" ) load_dotenv() @@ -87,6 +87,7 @@ def generate_comment(generate_request: GenerateCommentRequest): comment: str = comment_bot.generate_comment( generate_request.title, generate_request.selftext, + generate_request.instructions ) if comment is None: raise HTTPException(404, "comment not found") From 1a46729c41fca7145aacc6c8d90219b0fc7df358 Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Tue, 16 Apr 2024 18:13:45 +0200 Subject: [PATCH 09/76] Move api keys to own router, add small fixups and error handling (#194) --- apps/api/src/__init__.py | 13 +----- apps/api/src/crew.py | 5 +- apps/api/src/interfaces/db.py | 80 +++++++++++++++++++++++++------- apps/api/src/models/__init__.py | 2 + apps/api/src/models/api_key.py | 6 +++ apps/api/src/models/edge.py | 2 +- apps/api/src/routers/agents.py | 2 +- apps/api/src/routers/api_keys.py | 55 ++++++++++++++++++++++ apps/api/src/routers/crews.py | 1 + apps/api/src/routers/messages.py | 9 +++- apps/api/src/routers/profiles.py | 33 +------------ apps/api/src/routers/sessions.py | 6 +-- 12 files changed, 145 insertions(+), 69 deletions(-) create mode 100644 apps/api/src/routers/api_keys.py diff --git a/apps/api/src/__init__.py b/apps/api/src/__init__.py index f75830c3..13c7bf29 100644 --- a/apps/api/src/__init__.py +++ b/apps/api/src/__init__.py @@ -20,7 +20,7 @@ from .interfaces import db from .models import CrewProcessed from .routers import auth as auth_router -from .routers import agents, crews, messages, sessions, profiles, api_key_types, rest +from .routers import agents, crews, messages, sessions, profiles, api_key_types, rest, api_keys logger = logging.getLogger("root") @@ -31,6 +31,7 @@ app.include_router(crews.router) app.include_router(agents.router) app.include_router(profiles.router) +app.include_router(api_keys.router) app.include_router(auth_router.router) app.include_router(api_key_types.router) app.include_router(rest.router) @@ -64,16 +65,6 @@ def redirect_to_docs() -> RedirectResponse: return RedirectResponse(url="/docs") -@app.get("/compile", dependencies=[Depends(rate_limit(3, 30, "compile"))]) -def compile(id: UUID) -> dict[str, str | CrewProcessed]: - message, composition = db.get_compiled(id) - - return { - "prompt": message if message else "Not Found", - "composition": composition if composition else "Not Found", - } - - @app.get( "/improve", dependencies=[Depends(rate_limit_profile(limit=4, period_seconds=60))] ) diff --git a/apps/api/src/crew.py b/apps/api/src/crew.py index 7797d8fd..27ff23de 100644 --- a/apps/api/src/crew.py +++ b/apps/api/src/crew.py @@ -18,7 +18,6 @@ logger = logging.getLogger("root") - class AutogenCrew: def __init__( self, @@ -59,7 +58,7 @@ def __init__( ) if self.valid_tools else None - ) + ) self.user_proxy.register_reply([autogen.Agent, None], self._on_reply) self.base_config_list = autogen.config_list_from_json( @@ -131,7 +130,7 @@ async def _on_reply( recipient.name == "chat_manager", ] ): - logger.warn( + logger.error( f"on_reply: both ids are none, sender is not admin and recipient is not chat manager" ) diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index 8ced12d3..451e34f0 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -13,7 +13,6 @@ Agent, AgentInsertRequest, AgentUpdateModel, - CrewProcessed, CrewInsertRequest, Crew, CrewUpdateRequest, @@ -152,11 +151,14 @@ def get_messages( return [Message(**data) for data in response.data] -def get_message(message_id: UUID) -> Message: +def get_message(message_id: UUID) -> Message | None: """Get a message by its id""" supabase: Client = create_client(url, key) - response = supabase.table("messages").select("*").eq("id", message_id).single().execute() - return Message(**response.data) + response = supabase.table("messages").select("*").eq("id", message_id).execute() + if len(response.data) == 0: + return None + + return Message(**response.data[0]) # TODO: combine this function with the insert_message one, or use this post_message for both the endpoint and internal operations def post_message(message: Message) -> None: @@ -258,11 +260,11 @@ def update_crew(crew_id: UUID, content: CrewUpdateRequest) -> Crew: def get_crew(crew_id: UUID) -> Crew | None: supabase: Client = create_client(url, key) - response = supabase.table("crews").select("*").eq("id", crew_id).single().execute() - if not response.data: + response = supabase.table("crews").select("*").eq("id", crew_id).execute() + if len(response.data) == 0: return None - return Crew(**response.data) + return Crew(**response.data[0]) def get_crews( @@ -318,21 +320,58 @@ def get_tool_api_keys( return {data["api_key_type_id"]: data["api_key"] for data in response.data} -def get_api_keys(profile_id: UUID) -> list[APIKey]: +def get_api_key(api_key_id: UUID) -> APIKey | None: supabase: Client = create_client(url, key) - response = supabase.table("users_api_keys").select("*, api_key_types(*)").eq("profile_id", profile_id).execute() + response = ( + supabase.table("users_api_keys") + .select("*, api_key_types(*)") + .eq("id", api_key_id) + .execute() + ) + if len(response.data) == 0: + return None + + api_key_type = APIKeyType(**response.data[0]["api_key_types"]) + return APIKey(**response.data[0], api_key_type=api_key_type) + + +def get_api_keys( + profile_id: UUID | None = None, + api_key_type_id: UUID | None = None, + api_key: str | None = None, +) -> list[APIKey]: + supabase: Client = create_client(url, key) + query = supabase.table("users_api_keys").select("*, api_key_types(*)") + + if profile_id: + query = query.eq("profile_id", profile_id) + + if api_key_type_id: + query = query.eq("api_key_type_id", api_key_type_id) + + if api_key: + query = query.eq("api_key", api_key) + + response = query.execute() + api_keys = [] for data in response.data: api_key_type = APIKeyType(**data["api_key_types"]) api_keys.append(APIKey(**data, api_key_type=api_key_type)) - return api_keys + return api_keys -def insert_api_key(api_key: APIKeyInsertRequest) -> APIKey: +def insert_api_key(api_key: APIKeyInsertRequest) -> APIKey | None: supabase: Client = create_client(url, key) + type_response = supabase.table("api_key_types").select("*").eq("id", api_key.api_key_type_id).execute() + if len(type_response.data) == 0: + return None + response = supabase.table("users_api_keys").insert(json.loads(api_key.model_dump_json())).execute() - return APIKey(**response.data[0]) + + api_key_type = APIKeyType(**type_response.data[0]) + return APIKey(**response.data[0], api_key_type=api_key_type) def delete_api_key(api_key_id: UUID) -> APIKey | None: @@ -340,13 +379,19 @@ def delete_api_key(api_key_id: UUID) -> APIKey | None: response = supabase.table("users_api_keys").delete().eq("id", api_key_id).execute() if not len(response.data): return None - return APIKey(**response.data[0]) + + type_response = supabase.table("api_key_types").select("*").eq("id", response.data[0]["api_key_type_id"]).execute() + api_key_type = APIKeyType(**type_response.data[0]) + return APIKey(**response.data[0], api_key_type=api_key_type) def update_api_key(api_key_id: UUID, api_key_update: APIKeyUpdateRequest) -> APIKey: supabase: Client = create_client(url, key) response = supabase.table("users_api_keys").update(json.loads(api_key_update.model_dump_json())).eq("id", api_key_id).execute() - return APIKey(**response.data[0]) + type_response = supabase.table("api_key_types").select("*").eq("id", response.data[0]["api_key_type_id"]).execute() + + api_key_type = APIKeyType(**type_response.data[0]) + return APIKey(**response.data[0], api_key_type=api_key_type) def get_api_key_types() -> list[APIKeyType]: @@ -507,7 +552,7 @@ def delete_profile(profile_id: UUID) -> Profile: # ) # ) # - print(get_crew(UUID("bf9f1cdc-fb63-45e1-b1ff-9a1989373ce3"))) + #print(get_crew(UUID("bf9f1cdc-fb63-45e1-b1ff-9a1989373ce3"))) ##print(insert_message(MessageRequestModel( # session_id=UUID("ec4a9ae1-f4de-46cf-946d-956b3081c432"), # profile_id=UUID("070c1d2e-9d72-4854-a55e-52ade5a42071"), @@ -515,5 +560,6 @@ def delete_profile(profile_id: UUID) -> Profile: # recipient_id=UUID("7c707c30-2cfe-46a0-afa7-8bcc38f9687e"), #))) - print(delete_message(UUID('0e30e657-2ee1-482f-ab07-1952dc4d20fb'))) - print(update_message(UUID("c3e4755b-141d-4f77-8ea8-924961ccf36d"), content=MessageUpdateRequest(content="wowzer"))) \ No newline at end of file + #print(update_message(UUID("c3e4755b-141d-4f77-8ea8-924961ccf36d"), content=MessageUpdateRequest(content="wowzer"))) + #print(get_api_keys(api_key_type_id=UUID("3b64fe26-20b9-4064-907e-f2708b5f1656"))) + print(get_api_key_type_ids(["612ddae6-ecdd-4900-9314-1a2c9de6003d"])) \ No newline at end of file diff --git a/apps/api/src/models/__init__.py b/apps/api/src/models/__init__.py index a8a25e92..17425541 100644 --- a/apps/api/src/models/__init__.py +++ b/apps/api/src/models/__init__.py @@ -40,6 +40,7 @@ APIKey, APIKeyType, APIKeyUpdateRequest, + APIKeyGetRequest, ) from .user import User __all__ = [ @@ -75,4 +76,5 @@ "CrewGetRequest", "AgentGetRequest", "ProfileGetRequest", + "APIKeyGetRequest", ] diff --git a/apps/api/src/models/api_key.py b/apps/api/src/models/api_key.py index 16abb74b..9ee5febe 100644 --- a/apps/api/src/models/api_key.py +++ b/apps/api/src/models/api_key.py @@ -22,6 +22,12 @@ class APIKeyUpdateRequest(BaseModel): api_key: str +class APIKeyGetRequest(BaseModel): + profile_id: UUID | None = None + api_key_type_id: UUID | None = None + api_key: str | None = None + + class APIKeyType(BaseModel): id: UUID created_at: datetime diff --git a/apps/api/src/models/edge.py b/apps/api/src/models/edge.py index a18798cd..5ec54da4 100644 --- a/apps/api/src/models/edge.py +++ b/apps/api/src/models/edge.py @@ -42,4 +42,4 @@ class Edge(Generic[T], BaseModel): pathOptions: Optional[PathOptions] = None class Config: - allow_population_by_field_name = True \ No newline at end of file + populate_by_name = True \ No newline at end of file diff --git a/apps/api/src/routers/agents.py b/apps/api/src/routers/agents.py index 60ec9c11..4401c44d 100644 --- a/apps/api/src/routers/agents.py +++ b/apps/api/src/routers/agents.py @@ -37,7 +37,7 @@ def get_agent_by_id(agent_id: UUID) -> Agent: return agent -@router.post("/") +@router.post("/", status_code=201) def insert_agent(agent_request: AgentInsertRequest) -> Agent: if not db.get_profile(agent_request.profile_id): raise HTTPException(404, "profile not found") diff --git a/apps/api/src/routers/api_keys.py b/apps/api/src/routers/api_keys.py new file mode 100644 index 00000000..333b93ea --- /dev/null +++ b/apps/api/src/routers/api_keys.py @@ -0,0 +1,55 @@ +import logging +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException + +from src.interfaces import db +from src.models import ( + APIKey, + APIKeyInsertRequest, + APIKeyUpdateRequest, + APIKeyGetRequest, +) + +router = APIRouter(prefix="/api_keys", tags=["api keys"]) + + +@router.get("/") +def get_api_keys(q: APIKeyGetRequest = Depends()) -> list[APIKey]: + """Returns api keys with the api key type as an object with the id, name, description etc.""" + if q.profile_id: + if not db.get_profile(q.profile_id): + raise HTTPException(404, "profile not found") + + return db.get_api_keys(q.profile_id, q.api_key_type_id, q.api_key) + + +@router.get("/{api_key_id}") +def get_api_key(api_key_id: UUID) -> APIKey: + response = db.get_api_key(api_key_id) + if not response: + raise HTTPException(404, "id not found") + + return response + + +@router.post("/", status_code=201) +def insert_api_key(api_key_request: APIKeyInsertRequest) -> APIKey: + response = db.insert_api_key(api_key_request) + if not response: + raise HTTPException(404, "could not find given type id") + + return response + +@router.delete("/{api_key_id}") +def delete_api_key(api_key_id: UUID) -> APIKey: + deleted_key = db.delete_api_key(api_key_id) + if not deleted_key: + raise HTTPException(404, "api key id not found") + + return deleted_key + + +@router.patch("/{api_key_id}") +def update_api_key(api_key_id: UUID, api_key_update: APIKeyUpdateRequest) -> APIKey: + return db.update_api_key(api_key_id, api_key_update) \ No newline at end of file diff --git a/apps/api/src/routers/crews.py b/apps/api/src/routers/crews.py index e774c2fe..3a18cc29 100644 --- a/apps/api/src/routers/crews.py +++ b/apps/api/src/routers/crews.py @@ -43,6 +43,7 @@ def get_crew_by_id(crew_id: UUID) -> Crew: return response + @router.delete("/{crew_id}") def delete_crew(crew_id: UUID) -> Crew: return db.delete_crew(crew_id) diff --git a/apps/api/src/routers/messages.py b/apps/api/src/routers/messages.py index 33ff1924..2c2ab76e 100644 --- a/apps/api/src/routers/messages.py +++ b/apps/api/src/routers/messages.py @@ -11,6 +11,7 @@ ) from src.interfaces import db from src.models import Message, MessageInsertRequest, Message, MessageUpdateRequest, MessageGetRequest +from postgrest.exceptions import APIError router = APIRouter(prefix="/messages", tags=["messages"]) @@ -22,7 +23,7 @@ def get_messages(q: MessageGetRequest = Depends()) -> list[Message]: return db.get_messages(q.session_id, q.profile_id, q.recipient_id, q.sender_id) -@router.post("/") +@router.post("/", status_code=201) def insert_message(message: MessageInsertRequest) -> Message: return db.insert_message(message) @@ -47,4 +48,8 @@ def update_message(message_id: UUID, content: MessageUpdateRequest) -> Message: @router.get("/{message_id}") def get_message(message_id: UUID) -> Message: - return db.get_message(message_id) \ No newline at end of file + response = db.get_message(message_id) + if not response: + raise HTTPException(404, "message not found") + + return response \ No newline at end of file diff --git a/apps/api/src/routers/profiles.py b/apps/api/src/routers/profiles.py index 77939170..e59dcced 100644 --- a/apps/api/src/routers/profiles.py +++ b/apps/api/src/routers/profiles.py @@ -8,15 +8,12 @@ Profile, ProfileUpdateRequest, ProfileInsertRequest, - APIKey, - APIKeyInsertRequest, - APIKeyUpdateRequest, - APIKeyType, ProfileGetRequest ) router = APIRouter(prefix="/profiles", tags=["profiles"]) + @router.get("/") def get_profiles(q: ProfileGetRequest = Depends()) -> list[Profile]: return db.get_profiles(q.tier_id, q.display_name, q.stripe_customer_id) @@ -35,20 +32,12 @@ def get_profile_by_id(profile_id: UUID) -> Profile: return profile + @router.delete("/{profile_id}") def delete_profile(profile_id: UUID) -> Profile: return db.delete_profile(profile_id) -@router.get("/{profile_id}/api_keys") -def get_api_keys(profile_id: UUID) -> list[APIKey]: - """Returns api keys with the api key type as an object with the id, name, description etc.""" - if not db.get_profile(profile_id): - raise HTTPException(404, "profile not found") - - return db.get_api_keys(profile_id) - - @router.patch("/{profile_id}") def update_profile( profile_id: UUID, profile_update_request: ProfileUpdateRequest @@ -58,21 +47,3 @@ def update_profile( return db.update_profile(profile_id, profile_update_request) - -@router.post("/api_keys", status_code=201) -def insert_api_key(api_key_request: APIKeyInsertRequest) -> APIKey: - return db.insert_api_key(api_key_request) - - -@router.delete("/api_keys/{api_key_id}") -def delete_api_key(api_key_id: UUID) -> APIKey: - deleted_key = db.delete_api_key(api_key_id) - if not deleted_key: - raise HTTPException(404, "api key id not found") - - return deleted_key - - -@router.patch("/api_keys/{api_key_id}") -def update_api_key(api_key_id: UUID, api_key_update: APIKeyUpdateRequest) -> APIKey: - return db.update_api_key(api_key_id, api_key_update) diff --git a/apps/api/src/routers/sessions.py b/apps/api/src/routers/sessions.py index 94360876..18ca18e4 100644 --- a/apps/api/src/routers/sessions.py +++ b/apps/api/src/routers/sessions.py @@ -42,7 +42,6 @@ def get_sessions( return db.get_sessions(q.profile_id, q.crew_id, q.title, q.status) - @router.get("/{session_id}") def get_session(session_id: UUID) -> Session: response = db.get_session(session_id) @@ -55,15 +54,16 @@ def get_session(session_id: UUID) -> Session: # pretty sure this response object will always be a session, so casting it to stop typing errors -@router.patch("/{session_id}", response_model=Session) +@router.patch("/{session_id}") def update_session(session_id: UUID, content: SessionUpdateRequest) -> Session: return db.update_session(session_id, content) -@router.post("/", response_model=Session) +@router.post("/", status_code=201) def insert_session(content: SessionInsertRequest) -> Session: return db.insert_session(content) + # apparently status code 204 doesnt allow response bodies, so i'll have to look into that @router.delete("/{session_id}") def delete_session(session_id: UUID) -> Session: From f4a2dd1c6754eed4281b89e0081318e502dda95e Mon Sep 17 00:00:00 2001 From: Daniel Aanensen <60237496+LVGrinder@users.noreply.github.com> Date: Wed, 17 Apr 2024 07:41:05 +0200 Subject: [PATCH 10/76] Add more tools (#195) * add brave search * add stackapi tool --- apps/api/poetry.lock | 17 +++++- apps/api/pyproject.toml | 1 + apps/api/src/mock.py | 80 +++++++++++++++-------------- apps/api/src/tools/__init__.py | 29 +++++++---- apps/api/src/tools/brave_search.py | 29 +++++++++++ apps/api/src/tools/stackapi_tool.py | 30 +++++++++++ 6 files changed, 137 insertions(+), 49 deletions(-) create mode 100644 apps/api/src/tools/brave_search.py create mode 100644 apps/api/src/tools/stackapi_tool.py diff --git a/apps/api/poetry.lock b/apps/api/poetry.lock index 65205dd0..ef97f18c 100644 --- a/apps/api/poetry.lock +++ b/apps/api/poetry.lock @@ -3690,6 +3690,21 @@ postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] pymysql = ["pymysql"] sqlcipher = ["sqlcipher3_binary"] +[[package]] +name = "stackapi" +version = "0.3.0" +description = "Library for interacting with the Stack Exchange API" +optional = false +python-versions = "*" +files = [ + {file = "StackAPI-0.3.0-py3-none-any.whl", hash = "sha256:217f494aae3b4f267a0e4f8565e1761c4e55ec30f0c5a50a205632a52ca28481"}, + {file = "StackAPI-0.3.0.tar.gz", hash = "sha256:4147c9587f1c719d1ff9e01a70216290766821f9f7c1401e47b60ee89c329288"}, +] + +[package.dependencies] +requests = "*" +six = "*" + [[package]] name = "starlette" version = "0.37.2" @@ -4621,4 +4636,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.13" -content-hash = "dfa697f06d9fd1971d71249073d3aa33a62d44eac25a4840697c375f6dc1bfef" +content-hash = "0162a9621b5487162b64103aeb609b65901aecb2ee79b06d6f824b5a49c3cd62" diff --git a/apps/api/pyproject.toml b/apps/api/pyproject.toml index 35c753e4..de01e355 100644 --- a/apps/api/pyproject.toml +++ b/apps/api/pyproject.toml @@ -39,6 +39,7 @@ selenium = "^4.19.0" mail = "^2.1.0" duckduckgo-search = "^5.2.2" langchain-exa = "^0.0.1" +stackapi = "^0.3.0" [tool.poetry.group.dev.dependencies] mypy = "^1.7.0" diff --git a/apps/api/src/mock.py b/apps/api/src/mock.py index be09b92a..37432c51 100644 --- a/apps/api/src/mock.py +++ b/apps/api/src/mock.py @@ -38,50 +38,50 @@ "created_at": "2024-01-01T00:00:00.000Z", } -read_file: dict = { - "id": "00000000-0000-0000-0000-000000000001", - "profile_id": "6fcde4e6-6592-471b-9d33-dbf7e2ecfab4", - "title": "Output file content", - "description": "Read content of file and output it in a nice format", - "receiver_id": "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", - "published": False, - "nodes": [ - "8e26f947-a0e9-4e47-b86f-22930ea948fa", - # "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", - "6e541720-b4ac-4c47-abf3-f17147c9a32a", - ], - "prompt": { - "id": "", - "title": "", - "content": f"Get the file content of the file '{get_file_path_of_example()}', the 'agent python software' can call what function it has been", - }, - "created_at": "2024-01-01T00:00:00.000Z", -} +# read_file: dict = { +# "id": "00000000-0000-0000-0000-000000000001", +# "profile_id": "6fcde4e6-6592-471b-9d33-dbf7e2ecfab4", +# "title": "Output file content", +# "description": "Read content of file and output it in a nice format", +# "receiver_id": "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", +# "published": False, +# "nodes": [ +# "8e26f947-a0e9-4e47-b86f-22930ea948fa", +# # "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", +# "6e541720-b4ac-4c47-abf3-f17147c9a32a", +# ], +# "prompt": { +# "id": "", +# "title": "", +# "content": f"Get the file content of the file '{get_file_path_of_example()}', the 'agent python software' can call what function it has been", +# }, +# "created_at": "2024-01-01T00:00:00.000Z", +# } # "6e541720-b4ac-4c47-abf3-f17147c9a32a", agent for code reviewing # "2ce0b7db-84f7-4d59-8c38-3fcc3fd7da98", agent for writing tables in markdown -move_file: dict = { - "id": "00000000-0000-0000-0000-000000000001", - "profile_id": "6fcde4e6-6592-471b-9d33-dbf7e2ecfab4", - "title": "Output file content", - "description": "Read content of file and output it in a nice format", - "receiver_id": "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", - "published": False, - "nodes": [ - "8e26f947-a0e9-4e47-b86f-22930ea948fa", - # "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", - "6e541720-b4ac-4c47-abf3-f17147c9a32a", - ], - "prompt": { - "id": "", - "title": "", - "content": f"Move the file: '{get_file_path_of_example()}' to the destination: {get_file_path_of_example().replace('.txt', '_2.txt')} the 'agent python software' can call what function it has been", - }, - "created_at": "2024-01-01T00:00:00.000Z", -} +# move_file: dict = { +# "id": "00000000-0000-0000-0000-000000000001", +# "profile_id": "6fcde4e6-6592-471b-9d33-dbf7e2ecfab4", +# "title": "Output file content", +# "description": "Read content of file and output it in a nice format", +# "receiver_id": "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", +# "published": False, +# "nodes": [ +# "8e26f947-a0e9-4e47-b86f-22930ea948fa", +# # "0c0f0b05-e4ff-4d9a-a103-96a9702248f4", +# "6e541720-b4ac-4c47-abf3-f17147c9a32a", +# ], +# "prompt": { +# "id": "", +# "title": "", +# "content": f"Move the file: '{get_file_path_of_example()}' to the destination: {get_file_path_of_example().replace('.txt', '_2.txt')} the 'agent python software' can call what function it has been", +# }, +# "created_at": "2024-01-01T00:00:00.000Z", +# } -tool, prompt = "bing search tool", "what is openai? restrict the number of results to 3" +tool, prompt = "stack api tool", "what is openai?" test_tool: dict = { "id": "00000000-0000-0000-0000-000000000001", @@ -99,5 +99,7 @@ "content": f"This is a tool testing environment, use the tool: {tool}, {prompt}. Suggest this function call", }, "created_at": "2024-01-01T00:00:00.000Z", + "edges": [], + "updated_at": "2024-01-01T00:00:00.000Z", } crew_model = test_tool diff --git a/apps/api/src/tools/__init__.py b/apps/api/src/tools/__init__.py index b5eab4fb..caf7193c 100644 --- a/apps/api/src/tools/__init__.py +++ b/apps/api/src/tools/__init__.py @@ -27,6 +27,10 @@ from src.tools.google_serper import GoogleSerperRunTool from src.tools.google_serper import RESULTS_ID as GOOGLE_SERPER_RESULTS_TOOL_ID from src.tools.google_serper import GoogleSerperResultsTool +from src.tools.brave_search import ID as BRAVE_TOOL_ID +from src.tools.brave_search import BraveSearchTool +from src.tools.stackapi_tool import ID as STACKAPI_ID +from src.tools.stackapi_tool import StackAPISearchTool tools: dict = { ARXIV_TOOL_ID: ArxivTool, @@ -39,11 +43,14 @@ DDGS_TOOL_ID: DuckDuckGoSearchTool, GOOGLE_SERPER_RUN_TOOL_ID: GoogleSerperRunTool, GOOGLE_SERPER_RESULTS_TOOL_ID: GoogleSerperResultsTool, + BRAVE_TOOL_ID: BraveSearchTool, + STACKAPI_ID: StackAPISearchTool, } logger = logging.getLogger("root") load_dotenv() + def get_file_path_of_example(): current_dir = os.getcwd() target_folder = os.path.join(current_dir, "src/tools/test_files") @@ -92,10 +99,9 @@ def generate_tool_from_uuid( if tool in api_key_types.keys(): # set the api_key_type to the current tools api_key_type (the api_key_types dict has key "tool_id" and value "api_key_type_id") tool_key_type = api_key_types[tool] - - if tool_key_type in api_keys.keys(): - # set current api key that will be given to current tool (the api_keys dict has key "api_key_type_íd" and value "api_key") - api_key = api_keys[tool_key_type] + if tool_key_type in api_keys.keys(): + # set current api key that will be given to current tool (the api_keys dict has key "api_key_type_íd" and value "api_key") + api_key = api_keys[tool_key_type] if has_param(tool_cls, "api_key"): logger.info(f"has parameter 'api_key'") @@ -118,15 +124,17 @@ def generate_tool_from_uuid( bing_key = os.environ.get("BING_SUBSCRIPTION_KEY") alphavantage_key = os.environ.get("ALPHAVANTAGE_API_KEY") google_search_key = os.environ.get("GOOGLE_SEARCH_API_KEY") + brave_search_key = os.environ.get("BRAVE_API_KEY") print(serpapi_key, bing_key, alphavantage_key, google_search_key) if not all([serpapi_key, bing_key, alphavantage_key, google_search_key]): raise TypeError("a key was not found in env variables") api_keys = { - '3b64fe26-20b9-4064-907e-f2708b5f1656': serpapi_key, - "5281bbc4-45ea-4f4b-b790-e92c62bbc019": bing_key, - "8a29840f-4748-4ce4-88e6-44e1ef5b7637": alphavantage_key, - "4d950712-8b4c-4cc0-a24d-7599638119f2": google_search_key, + "3b64fe26-20b9-4064-907e-f2708b5f1656": serpapi_key, + "5281bbc4-45ea-4f4b-b790-e92c62bbc019": bing_key, + "8a29840f-4748-4ce4-88e6-44e1ef5b7637": alphavantage_key, + "4d950712-8b4c-4cc0-a24d-7599638119f2": google_search_key, + "58dc6249-3a0c-496b-91f3-27cf0054bfb0": brave_search_key, } api_key_types = { "fa4c2568-00d9-4e3c-9ab7-44f76f3a0e3f": "8a29840f-4748-4ce4-88e6-44e1ef5b7637", # alpha vantage @@ -134,6 +142,7 @@ def generate_tool_from_uuid( "71e4ddcc-4475-46f2-9816-894173b1292e": "5281bbc4-45ea-4f4b-b790-e92c62bbc019", # bing search "3e2665a8-6d73-42ee-a64f-50ddcc0621c6": "4d950712-8b4c-4cc0-a24d-7599638119f2", # google search (run) "1046fefb-a540-498f-8b96-7292523559e0": "4d950712-8b4c-4cc0-a24d-7599638119f2", # google search (results) + "3c0d3635-80f4-4286-aab6-c359795e1ac4": "58dc6249-3a0c-496b-91f3-27cf0054bfb0", # brave search } agents_tools = [ "f57d47fd-5783-4aac-be34-17ba36bb6242", # Move File Tool @@ -145,10 +154,12 @@ def generate_tool_from_uuid( "7dc53d81-cdac-4320-8077-1a7ab9497551", # DuckDuckGoSearch Tool "3e2665a8-6d73-42ee-a64f-50ddcc0621c6", # Google Serper Run "1046fefb-a540-498f-8b96-7292523559e0", # Google Serper Results + "3c0d3635-80f4-4286-aab6-c359795e1ac4", # Brave search + "612ddae6-ecdd-4900-9314-1a2c9de6003d", # StackAPI ] generated_tools = [] for tool in agents_tools: - tool = generate_tool_from_uuid(tool, api_key_types, api_keys) # type: ignore + tool = generate_tool_from_uuid(tool, api_key_types, api_keys) # type: ignore if tool is None: print("fail") else: diff --git a/apps/api/src/tools/brave_search.py b/apps/api/src/tools/brave_search.py new file mode 100644 index 00000000..7cbad0dd --- /dev/null +++ b/apps/api/src/tools/brave_search.py @@ -0,0 +1,29 @@ +import logging +from typing import Callable, Optional, Type + +from langchain.agents import Tool +from langchain.pydantic_v1 import BaseModel, Field +from langchain.tools import BaseTool +from langchain_community.tools import BraveSearch + +ID = "3c0d3635-80f4-4286-aab6-c359795e1ac4" + +logger = logging.getLogger("root") + + +class BraveSearchToolInput(BaseModel): + tool_input: str = Field( + title="query", description="Search query input to look up on brave" + ) + + +class BraveSearchTool(Tool, BaseTool): + args_schema: Type[BaseModel] = BraveSearchToolInput + + def __init__(self, api_key): + tool = BraveSearch.from_api_key(api_key=api_key, search_kwargs={"count": 3}) + super().__init__( + name="brave_search", + func=tool.run, + description="""search the internet through the search engine brave""", + ) diff --git a/apps/api/src/tools/stackapi_tool.py b/apps/api/src/tools/stackapi_tool.py new file mode 100644 index 00000000..858a70c7 --- /dev/null +++ b/apps/api/src/tools/stackapi_tool.py @@ -0,0 +1,30 @@ +import logging +from typing import Callable, Optional, Type + +from langchain.agents import Tool +from langchain.pydantic_v1 import BaseModel, Field +from langchain.tools import BaseTool +from langchain_community.utilities import StackExchangeAPIWrapper +from langchain_community.tools.stackexchange.tool import StackExchangeTool + +ID = "612ddae6-ecdd-4900-9314-1a2c9de6003d" + +logger = logging.getLogger("root") + + +class StackAPIToolInput(BaseModel): + query: str = Field( + title="query", description="Search query input to look up on Stack Exchange" + ) + + +class StackAPISearchTool(Tool, BaseTool): + args_schema: Type[BaseModel] = StackAPIToolInput + + def __init__(self): + tool = StackExchangeTool(api_wrapper=StackExchangeAPIWrapper()) + super().__init__( + name="stack_api_tool", + func=tool._run, + description="""StackAPI searches through a network of question-and-answer (Q&A) websites""", + ) From 8a4f43f52ffbf38507735399f250eaba5d01855f Mon Sep 17 00:00:00 2001 From: Daniel Aanensen <60237496+LVGrinder@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:15:22 +0200 Subject: [PATCH 11/76] Add subscription endpoints (#196) * subscriptions * subscriptions endpoint --- apps/api/src/__init__.py | 18 ++- apps/api/src/interfaces/db.py | 215 ++++++++++++++++++++------ apps/api/src/models/__init__.py | 17 +- apps/api/src/models/subscription.py | 25 +++ apps/api/src/routers/subscriptions.py | 59 +++++++ apps/api/src/routers/tools.py | 25 +++ 6 files changed, 308 insertions(+), 51 deletions(-) create mode 100644 apps/api/src/models/subscription.py create mode 100644 apps/api/src/routers/subscriptions.py create mode 100644 apps/api/src/routers/tools.py diff --git a/apps/api/src/__init__.py b/apps/api/src/__init__.py index 13c7bf29..8b2d630b 100644 --- a/apps/api/src/__init__.py +++ b/apps/api/src/__init__.py @@ -2,7 +2,7 @@ from uuid import UUID import autogen -from fastapi import Depends, FastAPI +from fastapi import Depends, FastAPI from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse @@ -20,7 +20,18 @@ from .interfaces import db from .models import CrewProcessed from .routers import auth as auth_router -from .routers import agents, crews, messages, sessions, profiles, api_key_types, rest, api_keys +from .routers import ( + agents, + crews, + messages, + sessions, + profiles, + api_key_types, + rest, + api_keys, + tools, + subscriptions, +) logger = logging.getLogger("root") @@ -35,6 +46,8 @@ app.include_router(auth_router.router) app.include_router(api_key_types.router) app.include_router(rest.router) +app.include_router(tools.router) +app.include_router(subscriptions.router) app.add_middleware( CORSMiddleware, @@ -99,4 +112,3 @@ def auto_build_crew(general_task: str) -> str: @app.get("/me") def get_profile_from_header(current_user=Depends(get_current_user)): return current_user - diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index 451e34f0..d0e90a0d 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -33,6 +33,10 @@ MessageInsertRequest, Message, MessageUpdateRequest, + Subscription, + SubscriptionInsertRequest, + SubscriptionUpdateRequest, + SubscriptionGetRequest, ) load_dotenv() @@ -46,7 +50,7 @@ logger = logging.getLogger("root") -# keeping this function for now, since typing gets crazy with the sessions/run endpoint +# keeping this function for now, since typing gets crazy with the sessions/run endpoint # if it uses the "get_session_by_param" function def get_session(session_id: UUID) -> Session | None: """Get a session from the database.""" @@ -59,10 +63,10 @@ def get_session(session_id: UUID) -> Session | None: def get_sessions( - profile_id: UUID | None = None, + profile_id: UUID | None = None, crew_id: UUID | None = None, title: str | None = None, - status: str | None = None + status: str | None = None, ) -> list[Session]: """Gets session(s), filtered by what parameters are given""" supabase: Client = create_client(url, key) @@ -127,7 +131,7 @@ def get_messages( session_id: UUID | None = None, profile_id: UUID | None = None, recipient_id: UUID | None = None, - sender_id: UUID | None = None + sender_id: UUID | None = None, ) -> list[Message]: """Gets messages, filtered by what parameters are given""" supabase: Client = create_client(url, key) @@ -146,20 +150,20 @@ def get_messages( if sender_id: query = query.eq("sender_id", sender_id) - response = query.execute() return [Message(**data) for data in response.data] -def get_message(message_id: UUID) -> Message | None: + +def get_message(message_id: UUID) -> Message: """Get a message by its id""" supabase: Client = create_client(url, key) - response = supabase.table("messages").select("*").eq("id", message_id).execute() - if len(response.data) == 0: - return None + response = ( + supabase.table("messages").select("*").eq("id", message_id).single().execute() + ) + return Message(**response.data) + - return Message(**response.data[0]) - # TODO: combine this function with the insert_message one, or use this post_message for both the endpoint and internal operations def post_message(message: Message) -> None: """Post a message to the database.""" @@ -173,7 +177,11 @@ def post_message(message: Message) -> None: def insert_message(message: MessageInsertRequest) -> Message: """Posts a message like the post_message function, but uses a request model""" supabase: Client = create_client(url, key) - response = supabase.table("messages").insert(json.loads(message.model_dump_json(exclude_none=True))).execute() + response = ( + supabase.table("messages") + .insert(json.loads(message.model_dump_json(exclude_none=True))) + .execute() + ) return Message(**response.data[0]) @@ -202,6 +210,66 @@ def update_message(message_id: UUID, content: MessageUpdateRequest) -> Message | return Message(**response.data[0]) +def get_subscriptions( + profile_id: UUID | None = None, + stripe_subscription_id: str | None = None, +) -> list[Subscription]: + """Gets messages, filtered by what parameters are given""" + supabase: Client = create_client(url, key) + logger.debug(f"Getting subscriptions") + query = supabase.table("subscriptions").select("*") + + if profile_id: + query = query.eq("profile_id", profile_id) + + if stripe_subscription_id: + query = query.eq("stripe_subscription_id", stripe_subscription_id) + + response = query.execute() + + return [Subscription(**data) for data in response.data] + + +def insert_subscription(subscription: SubscriptionInsertRequest) -> Subscription: + """Posts a Subscription to the db""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("subscriptions") + .insert(json.loads(subscription.model_dump_json(exclude_none=True))) + .execute() + ) + return Subscription(**response.data[0]) + + +def delete_subscription(profile_id: UUID) -> Subscription | None: + """Deletes a subscription by an id (the primary key)""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("subscriptions").delete().eq("profile_id", profile_id).execute() + ) + if len(response.data) == 0: + return None + + return Subscription(**response.data[0]) + + +def update_subscription( + profile_id: UUID, content: SubscriptionUpdateRequest +) -> Subscription | None: + """Updates a subscription by an id""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("subscriptions") + .update(json.loads(content.model_dump_json(exclude_none=True))) + .eq("profile_id", profile_id) + .execute() + ) + if len(response.data) == 0: + return None + + return Subscription(**response.data[0]) + + def get_descriptions(agent_ids: list[UUID]) -> dict[UUID, list[str]] | None: """Get the description list for the given agent.""" supabase: Client = create_client(url, key) @@ -301,6 +369,20 @@ def delete_crew(crew_id: UUID) -> Crew: return Crew(**response.data[0]) +def get_api_key(api_key_id: UUID) -> APIKey: + supabase: Client = create_client(url, key) + response = ( + supabase.table("users_api_keys") + .select("*, api_key_types(*)") + .eq("id", api_key_id) + .single() + .execute() + ) + + api_key_type = APIKeyType(**response.data["api_key_types"]) + return APIKey(**response.data, api_key_type=api_key_type) + + def get_tool_api_keys( profile_id: UUID, api_key_type_ids: list[str] | None = None ) -> dict[str, str]: @@ -358,17 +440,26 @@ def get_api_keys( for data in response.data: api_key_type = APIKeyType(**data["api_key_types"]) api_keys.append(APIKey(**data, api_key_type=api_key_type)) - + return api_keys def insert_api_key(api_key: APIKeyInsertRequest) -> APIKey | None: supabase: Client = create_client(url, key) - type_response = supabase.table("api_key_types").select("*").eq("id", api_key.api_key_type_id).execute() + type_response = ( + supabase.table("api_key_types") + .select("*") + .eq("id", api_key.api_key_type_id) + .execute() + ) if len(type_response.data) == 0: return None - response = supabase.table("users_api_keys").insert(json.loads(api_key.model_dump_json())).execute() + response = ( + supabase.table("users_api_keys") + .insert(json.loads(api_key.model_dump_json())) + .execute() + ) api_key_type = APIKeyType(**type_response.data[0]) return APIKey(**response.data[0], api_key_type=api_key_type) @@ -380,15 +471,30 @@ def delete_api_key(api_key_id: UUID) -> APIKey | None: if not len(response.data): return None - type_response = supabase.table("api_key_types").select("*").eq("id", response.data[0]["api_key_type_id"]).execute() + type_response = ( + supabase.table("api_key_types") + .select("*") + .eq("id", response.data[0]["api_key_type_id"]) + .execute() + ) api_key_type = APIKeyType(**type_response.data[0]) return APIKey(**response.data[0], api_key_type=api_key_type) def update_api_key(api_key_id: UUID, api_key_update: APIKeyUpdateRequest) -> APIKey: supabase: Client = create_client(url, key) - response = supabase.table("users_api_keys").update(json.loads(api_key_update.model_dump_json())).eq("id", api_key_id).execute() - type_response = supabase.table("api_key_types").select("*").eq("id", response.data[0]["api_key_type_id"]).execute() + response = ( + supabase.table("users_api_keys") + .update(json.loads(api_key_update.model_dump_json())) + .eq("id", api_key_id) + .execute() + ) + type_response = ( + supabase.table("api_key_types") + .select("*") + .eq("id", response.data[0]["api_key_type_id"]) + .execute() + ) api_key_type = APIKeyType(**type_response.data[0]) return APIKey(**response.data[0], api_key_type=api_key_type) @@ -398,7 +504,7 @@ def get_api_key_types() -> list[APIKeyType]: supabase: Client = create_client(url, key) logger.debug("Getting all api key types") response = supabase.table("api_key_types").select("*").execute() - return [APIKeyType(**data) for data in response.data] + return [APIKeyType(**data) for data in response.data] def update_status(session_id: UUID, status: SessionStatus) -> None: @@ -410,7 +516,7 @@ def update_status(session_id: UUID, status: SessionStatus) -> None: def get_agents( profile_id: UUID | None = None, crew_id: UUID | None = None, - published: bool | None = None + published: bool | None = None, ) -> list[Agent] | None: """Gets agents, filtered by what parameters are given""" supabase: Client = create_client(url, key) @@ -427,9 +533,9 @@ def get_agents( response = get_agents_from_crew(crew_id) if not response: return None - + return response - + if published is not None: query = query.eq("published", published) @@ -484,18 +590,34 @@ def delete_agent(agent_id: UUID) -> Agent: return Agent(**response.data[0]) +def update_agent_tool(agent_id: UUID, tool_id: UUID) -> Agent: + supabase: Client = create_client(url, key) + agent_tools = supabase.table("agents").select("tools").eq("id", agent_id).execute() + tool: dict = {"id": tool_id, "parameter": {}} + + agent_tools.data[0]["tools"].append(tool) + formatted_tools = agent_tools.data[0]["tools"] + response = ( + supabase.table("agents") + .update(json.loads(json.dumps(formatted_tools, default=str))) + .eq("id", agent_id) + .execute() + ) + return Agent(**response.data[0]) + + def get_profiles( tier_id: UUID | None = None, display_name: str | None = None, - stripe_customer_id: str | None = None + stripe_customer_id: str | None = None, ) -> list[Profile]: - """Gets profiles, filtered by what parameters are given""" + """Gets profiles, filtered by what parameters are given""" supabase: Client = create_client(url, key) query = supabase.table("profiles").select("*") if tier_id: query = query.eq("tier_id", tier_id) - + if display_name: query = query.eq("display_name", display_name) @@ -515,9 +637,7 @@ def get_profile(profile_id: UUID) -> Profile | None: return Profile(**response.data[0]) -def update_profile( - profile_id: UUID, content: ProfileUpdateRequest -) -> Profile: +def update_profile(profile_id: UUID, content: ProfileUpdateRequest) -> Profile: supabase: Client = create_client(url, key) response = ( supabase.table("profiles") @@ -530,7 +650,11 @@ def update_profile( def insert_profile(profile: ProfileInsertRequest) -> Profile: supabase: Client = create_client(url, key) - response = supabase.table("profiles").insert(json.loads(profile.model_dump_json(exclude_none=True))).execute() + response = ( + supabase.table("profiles") + .insert(json.loads(profile.model_dump_json(exclude_none=True))) + .execute() + ) return Profile(**response.data[0]) @@ -540,26 +664,27 @@ def delete_profile(profile_id: UUID) -> Profile: return Profile(**response.data[0]) -if __name__ == "__main__": +if __name__ == "__main__": from src.models import Session -# print( -# insert_session( -# SessionRequest( -# crew_id=UUID("1c11a9bf-748f-482b-9746-6196f136401a"), -# profile_id=UUID("070c1d2e-9d72-4854-a55e-52ade5a42071"), -# title="hello", -# ) -# ) -# ) -# - #print(get_crew(UUID("bf9f1cdc-fb63-45e1-b1ff-9a1989373ce3"))) + + # print( + # insert_session( + # SessionRequest( + # crew_id=UUID("1c11a9bf-748f-482b-9746-6196f136401a"), + # profile_id=UUID("070c1d2e-9d72-4854-a55e-52ade5a42071"), + # title="hello", + # ) + # ) + # ) + # + # print(get_crew(UUID("bf9f1cdc-fb63-45e1-b1ff-9a1989373ce3"))) ##print(insert_message(MessageRequestModel( # session_id=UUID("ec4a9ae1-f4de-46cf-946d-956b3081c432"), # profile_id=UUID("070c1d2e-9d72-4854-a55e-52ade5a42071"), # content="hello test message", # recipient_id=UUID("7c707c30-2cfe-46a0-afa7-8bcc38f9687e"), - #))) + # ))) - #print(update_message(UUID("c3e4755b-141d-4f77-8ea8-924961ccf36d"), content=MessageUpdateRequest(content="wowzer"))) - #print(get_api_keys(api_key_type_id=UUID("3b64fe26-20b9-4064-907e-f2708b5f1656"))) - print(get_api_key_type_ids(["612ddae6-ecdd-4900-9314-1a2c9de6003d"])) \ No newline at end of file + # print(update_message(UUID("c3e4755b-141d-4f77-8ea8-924961ccf36d"), content=MessageUpdateRequest(content="wowzer"))) + # print(get_api_keys(api_key_type_id=UUID("3b64fe26-20b9-4064-907e-f2708b5f1656"))) + print(get_api_key_type_ids(["612ddae6-ecdd-4900-9314-1a2c9de6003d"])) diff --git a/apps/api/src/models/__init__.py b/apps/api/src/models/__init__.py index 17425541..d429627f 100644 --- a/apps/api/src/models/__init__.py +++ b/apps/api/src/models/__init__.py @@ -15,11 +15,17 @@ ) from .llm_config import LLMConfig from .message import ( - Message, - MessageInsertRequest, + Message, + MessageInsertRequest, MessageUpdateRequest, MessageGetRequest, ) +from .subscription import ( + Subscription, + SubscriptionInsertRequest, + SubscriptionUpdateRequest, + SubscriptionGetRequest, +) from .profile import ( ProfileInsertRequest, Profile, @@ -35,7 +41,7 @@ SessionUpdateRequest, SessionGetRequest, ) -from .api_key import( +from .api_key import ( APIKeyInsertRequest, APIKey, APIKeyType, @@ -43,6 +49,7 @@ APIKeyGetRequest, ) from .user import User + __all__ = [ "AgentConfig", "CodeExecutionConfig", @@ -77,4 +84,8 @@ "AgentGetRequest", "ProfileGetRequest", "APIKeyGetRequest", + "Subscription", + "SubscriptionInsertRequest", + "SubscriptionUpdateRequest", + "SubscriptionGetRequest", ] diff --git a/apps/api/src/models/subscription.py b/apps/api/src/models/subscription.py new file mode 100644 index 00000000..53451ece --- /dev/null +++ b/apps/api/src/models/subscription.py @@ -0,0 +1,25 @@ +from datetime import UTC, datetime +from uuid import UUID, uuid4 + +from pydantic import BaseModel, Field + + +class Subscription(BaseModel): + profile_id: UUID + stripe_subscription_id: str | None = None + created_at: datetime + + +class SubscriptionInsertRequest(BaseModel): + profile_id: UUID + stripe_subscription_id: str | None = None + + +class SubscriptionUpdateRequest(BaseModel): + stripe_subscription_id: str | None = None + + +class SubscriptionGetRequest(BaseModel): + profile_id: UUID | None = None + stripe_subscription_id: str | None = None + created_at: datetime diff --git a/apps/api/src/routers/subscriptions.py b/apps/api/src/routers/subscriptions.py new file mode 100644 index 00000000..88e155ed --- /dev/null +++ b/apps/api/src/routers/subscriptions.py @@ -0,0 +1,59 @@ +import logging +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException + +from src.dependencies import ( + RateLimitResponse, + rate_limit, + rate_limit_profile, + rate_limit_tiered, +) +from src.interfaces import db +from src.models import ( + Subscription, + SubscriptionInsertRequest, + SubscriptionUpdateRequest, + SubscriptionGetRequest, +) + +router = APIRouter(prefix="/subscriptions", tags=["subscriptions"]) + +logger = logging.getLogger("root") + + +@router.get("/") +def get_subscriptions(q: SubscriptionGetRequest = Depends()) -> list[Subscription]: + return db.get_subscriptions(q.profile_id, q.stripe_subscription_id) + + +@router.post("/") +def insert_subscription(subscription: SubscriptionInsertRequest) -> Subscription: + return db.insert_subscription(subscription) + + +@router.delete("/{profile_id}") +def delete_subscription(profile_id: UUID) -> Subscription: + response = db.delete_subscription(profile_id) + if not response: + raise HTTPException(404, "stripe subscription id not found") + + return response + + +@router.patch("/{profile_id}") +def update_subscription( + profile_id: UUID, content: SubscriptionUpdateRequest +) -> Subscription: + response = db.update_subscription(profile_id, content) + if not response: + raise HTTPException(404, "message not found") + + return response + + +# +# +# @router.get("/{message_id}") +# def get_message(message_id: UUID) -> Message: +# return db.get_message(message_id) diff --git a/apps/api/src/routers/tools.py b/apps/api/src/routers/tools.py new file mode 100644 index 00000000..6ae66632 --- /dev/null +++ b/apps/api/src/routers/tools.py @@ -0,0 +1,25 @@ +import logging +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException + +from src.interfaces import db +from src.models import ( + AgentInsertRequest, + AgentUpdateModel, + Agent, + AgentGetRequest, +) + +router = APIRouter( + prefix="/tools", + tags=["tools"], +) + + +@router.patch("/{agent_id}") +def add_tool(agent_id: UUID, tool_id: UUID) -> Agent: + if not db.get_agent(agent_id): + raise HTTPException(404, "agent not found") + + return db.update_agent_tool(agent_id, tool_id) From 36990211e55dee1982e2b4034d698787f74af10b Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:24:55 +0200 Subject: [PATCH 12/76] Fix the types of session and message models for the openapi code generator (#197) * fix the type on session * fix type on message * fix warning from edge class * clean up, also fix message model --- apps/api/src/mock.py | 2 +- apps/api/src/models/edge.py | 2 +- apps/api/src/models/message.py | 6 +++--- apps/api/src/models/session.py | 13 ++++++------- apps/api/src/routers/sessions.py | 11 ++++++++++- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/apps/api/src/mock.py b/apps/api/src/mock.py index 37432c51..b51e1e0b 100644 --- a/apps/api/src/mock.py +++ b/apps/api/src/mock.py @@ -81,7 +81,7 @@ # "created_at": "2024-01-01T00:00:00.000Z", # } -tool, prompt = "stack api tool", "what is openai?" +tool, prompt = "brave search tool", "what is openai?" test_tool: dict = { "id": "00000000-0000-0000-0000-000000000001", diff --git a/apps/api/src/models/edge.py b/apps/api/src/models/edge.py index 5ec54da4..7e82a997 100644 --- a/apps/api/src/models/edge.py +++ b/apps/api/src/models/edge.py @@ -17,7 +17,7 @@ class PathOptions(BaseModel): borderRadius: Optional[float] = None curvature: Optional[float] = None -class Edge(Generic[T], BaseModel): +class Edge(BaseModel, Generic[T]): id: str type: Optional[str] = None source: str diff --git a/apps/api/src/models/message.py b/apps/api/src/models/message.py index deceb4c3..0d3d8843 100644 --- a/apps/api/src/models/message.py +++ b/apps/api/src/models/message.py @@ -5,14 +5,14 @@ class Message(BaseModel): - id: UUID = Field(default_factory=lambda: uuid4()) + id: UUID session_id: UUID profile_id: UUID sender_id: UUID | None = None # None means admin here recipient_id: UUID | None = None # None means admin here aswell content: str - role: str = "user" - created_at: datetime = Field(default_factory=lambda: datetime.now(tz=UTC)) + role: str + created_at: datetime class MessageInsertRequest(BaseModel): diff --git a/apps/api/src/models/session.py b/apps/api/src/models/session.py index 8b48eaf4..82fc2021 100644 --- a/apps/api/src/models/session.py +++ b/apps/api/src/models/session.py @@ -12,16 +12,15 @@ class SessionStatus(StrEnum): IDLE = auto() - class Session(BaseModel): - id: UUID = Field(default_factory=lambda: uuid4()) - created_at: datetime = Field(default_factory=lambda: datetime.now(tz=UTC)) + id: UUID + created_at: datetime profile_id: UUID - reply: str = "" + reply: str crew_id: UUID - title: str = "Untitled" - last_opened_at: datetime = Field(default_factory=lambda: datetime.now(tz=UTC)) - status: SessionStatus = SessionStatus.RUNNING + title: str + last_opened_at: datetime + status: SessionStatus class SessionInsertRequest(BaseModel): diff --git a/apps/api/src/routers/sessions.py b/apps/api/src/routers/sessions.py index 18ca18e4..3e309f3f 100644 --- a/apps/api/src/routers/sessions.py +++ b/apps/api/src/routers/sessions.py @@ -1,6 +1,7 @@ +from datetime import UTC, datetime import logging from typing import cast -from uuid import UUID +from uuid import UUID, uuid4 from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException @@ -23,6 +24,7 @@ Session, SessionUpdateRequest, SessionGetRequest, + SessionStatus, ) from src.models.session import SessionInsertRequest from src.parser import process_crew, get_processed_crew_by_id @@ -121,9 +123,14 @@ async def run_crew( if session is None: session = Session( + id=uuid4(), + created_at=datetime.now(tz=UTC), crew_id=request.crew_id, profile_id=request.profile_id, title=request.session_title, + reply="", + last_opened_at=datetime.now(tz=UTC), + status=SessionStatus.RUNNING ) db.post_session(session) @@ -134,12 +141,14 @@ async def on_reply( role: str, ) -> None: message = Message( + id=uuid4(), session_id=session.id, profile_id=session.profile_id, recipient_id=recipient_id, sender_id=sender_id, content=content, role=role, + created_at=datetime.now(tz=UTC) ) logger.debug(f"on_reply: {message}") db.post_message(message) From 7f844a99197ad13456775ec3443dd97ba39ad184 Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:18:19 +0200 Subject: [PATCH 13/76] Gitignore cache and change api keys path to kebabcase (#199) --- apps/api/src/rest/.gitignore | 1 + apps/api/src/rest/cache/cache.db | Bin 282624 -> 0 bytes apps/api/src/routers/api_keys.py | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 apps/api/src/rest/.gitignore delete mode 100644 apps/api/src/rest/cache/cache.db diff --git a/apps/api/src/rest/.gitignore b/apps/api/src/rest/.gitignore new file mode 100644 index 00000000..fc61eafa --- /dev/null +++ b/apps/api/src/rest/.gitignore @@ -0,0 +1 @@ +/cache/ \ No newline at end of file diff --git a/apps/api/src/rest/cache/cache.db b/apps/api/src/rest/cache/cache.db deleted file mode 100644 index 223eaf3acecaf358f72ca438470523321983e584..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 282624 zcmeFa33yahw)b5pHP3(u2#66ufz6PrB$Wy(0s?{}B9o{HW~fRkm9eT)8AL)=sSSvL zW8=`MIJDBv;Dm^Z;ye#%J8Roc*iP+;Lx2CZbJmGnyYKz(_uPBm_rC8JpU3~=xAIR2 zCzYyQXYIB2{1a!#Qjx-FQ=*|FRak85V=5>xO)e}nnM?=Z|LORj|8wCF79AXj8h_y5 zi3ga*r`LG>KbYLk?IwSV|1n>UZ$IyLZ?)%U_jm5YU9Cv>{?~g2dapq573jSJy;q?3 z3iMuq-Yf7Qx&oQ7+diappd&jWm59~UL=y8OsZ^}7Cb=vb>x?X`j?_m|k)tcBY9mL_ zn?7a1^uh)6W*u|P^m&E<%2zmL#sYk3+Vt7e;XGkZq5Qz z^kZhtDO@;r8htVTB8Bs(FDOh`)VD?okJRJ1!V_js8&BUv;Yl;6&zoKtk96RJ!znZT z@WSbHre%(Hb${#A|K+#d+FV`nANkh1efqbqe_#K(Z(S75nSN6DxBegaSA?Da-VY$w zn2aP+|L;G5ZlC_Im^Ekq^mz;ZlRtpp{44&gA3%x2KBNqfoss!JfU2g}#?*i0!Sh?= zf9<0u@Xrq$`4{Prn-crK`)&URE_wI2{oirT|Lt#kfz38>+(0cEYpjm6%Ll}=WU46< zS(b`5bpM7r^k30gbEZvS-2J=v8%xi_VN}oOjXue08#rO0*7lpP8fkBi{r1b+|HYU6 zjpsLC_cz(m^DMT3hYi$PfAfX$8@w!0(I&rloBl-?&Y5-M!s&&-{g!o`@pVTbF}4t& zI67-L+XoIDsO1_`6_xe+(-J*5S^3Fn%GBA@^=F+?g^8xNST(-%g6Z^xHFw^uO;hYoj|H9d`3%f7B{-sAxD6kDY`asPje`d*+ zdc3D!R?(VjlDv$+(6RvkiQdQ4d-(1*@$#MgzY;4P)_)-m%1N=&pQPmZdOm6=i%9WKSD^O_^j?A9E6{rddapq573jSJ zy;q?33iMuq-Yf7w?+SQ*@0oR^RM6J+Bblm5#geI5RnoWWO!L87Rcn3yGWoZ;2CcT3OSS4)GQO-i zRu!+0ENf0QrJAam>aBxTo6P~U{7^%zaT(S8<=!jPO4I(U3(NthUWiY2G*;Cnni`v0 zlLJ?4=5ZE1-_TIeEI)y&@dvCnnTz++KT_A!nrN)3Uq;&t+A8V?tm-mPD9}GvMcXFi zrxlv^U$vs=uc3PXvUEjNYiq+{tIjZsvPe2sm5MbrE^BV8k5zTlM=Fx3afwJ(q%l?B zF;4E7sHRQ*eSB{e`0f5L{gwWi{zH7<`abpj>hJ4+&Hs@92LA>APJh_<24BA3*n0(f zuR!k==)D5HSD^O_^j?A9E6{rddapq573jSJy;tCW@fGl!4=(6=<8E3lnOdLZ8+X%M zpZTBy<9)uR(`7zD>%L9U$6?-IquT_2`UBl2@Hx!`HF-b5`_Es+vRoAOH;aP2x6+m~ z{`oJrbR1wVE%;YA2`py~GzYpr@=x~&EIG=nHwY}*{mtVz-*bZ?Gss-b+27tAu&f;L zukH+3x__+JCwKV*h&V3CQ`+^tYj#KkkqCm-$cj&-WkiDt6hNe|FyF>~hX? zj&%Isc*?QK(c+lq7-;|0e!qQ#y~-Z4J8f^;Znb4?3vHvUKUtr(UTsZTkFgH6{LS*9 z-!b1|KHIz)*ZkLl7YeQ|Xe&6j;6Uw5?P2W_Ev6lz`AzTte|wyXMPAbo zr`=?Cm>f>ikU(W!MMo+%<uY*YMD2AHb*ieElyC(vDPv&HC^`3R*qywTFg<*H5FkpH5NVcHAgZdEsj^r z(PDWO>TCPi$xM;VNQ>EuIno*54f~UQVV3uWla9k<3VoX{tHgN~Yr~PJEA} zG>2Qo(TcetCI9-F$ul1%Get5ZEv72wx^{UrX6(CgJ(($z8EG*^F-Kb)$TYoq?tG49 zMp{f(%#kMf*qGM;vTw;uk<3VoqZD&hiTs6~y6KOL$V`#UNQ+5|xiSv^ZQb2TR)MuRr3Q34i5C zW~9YL#TRVD9<;CJJa&pm^l1g3z;dxOlc8T%pDPF4$pfsLS~9& zMp~39=5#`uLJ!|pPiBf_Mp}dvb8C&f3Z)aibNnUNNys=26$OyiE7e-B4#E-Dfw ziaAv#p9;jLw?>hfBAJmE#fmvm(?q7xm$z1NBs02tB zTSM{{c3@Fx7?~-O8EJ8tVoo;IkZFLqLOvBxBs0?DP{rI*BOgHhu9!QEK8YfkkrpFW zbESMB^^HEdlgt#Qxw2i1P|Qu$C1i517&?a|nUNNUDCUN+eCBs-*>)kBDUum!FdOp(k;i-S~i znOvL{eC>IQ%oL@$tWFG5%#k|z*wE?{zauk6G9xVxRLoT!^3s|79p96gBAJmELshd} zBW-=4V=yhKWRzyCk%p+|D*8>?y3=g=j-xbJg~edS9Im28$<`em8(!x~W~9Xd`Q}h( zJ^fm3z4z(UCUJzB(qfQeZcP=F>7ETw(F00GG9xVpD(12pdXm|C_l!8b!pcZyq{RTm z9BQT)`mJ}B-n)w%=K!rbuR_g+Je1l1j_Je)Gn2tI13eW=ad6Vs37hKklo3`EEIxDUum! z;Z@9yi3&1px_A9;9LbEd@F?bZJVB;E)cSH9$&9pctL9RAV%&Q9`q#&El;+Zaa4F`x zCi;cldfA}HX&lLnv~a5CQhH+Cy0L1@;~b^Av`RP>bF4`|L@)Vq%avrNNM@vkT{YLW zlIh~iF}pcRb6u;jDduQD_%it$Ly^o#3#(#|#As!{_54@vq*pB&$&9qX8`G&5 zwnHahcnI{!3+6zNIKKmW`1vEC;SDE1L+d-C#p_2xgX`u(1LvIq9e>`T(6MVzgpNLU zIds&yhd~cpGY>jq^_kE^R*!-nylOsl*zZ{Y(9`{S*Di z`6u}U{t^CxewXhT-pi|%p-wxlczRkXieXD$D_!@l`z6HKxd=q`+e1*RKd^Yco z-p{=6cwhAH_TJ-pI8hUZz&L!ND( zKYA|noab5TNqVB5lRdLNM|pytk)A;wxBFN3SMCqouezUf-|xQ7eU1AP_iFcYcayu) zz0f_=eYktP`(Sr}x81eR^*7hMu9sYoy6$z|N?Ri%~j?a<2umQ z$7ObY=lsO^rt>-HF6W)j8=RLr*Ev@@6V7VqBIiu!MCVxNFlQfUf#Vy;hmO}APdauu zZgE`YxWI9iBkibloZ^`6nB*vO40rT**z7;x?#7$;XYCK#@33EMzr?=E-f6G5FSXCL zPqmlW548`nyKFz(KDWJVd(rlY?JnC5w##g5Z7Xcewo2Oq+YDRSHpVv8=ChfsUt2%0 z?y){@-EO_fy2-l1n#H}5sCBXRSnCni@zz3XKdZ&^o#kW8>z1c2J1w_aHd`*ToMUOX z)LE8T=2#|Mf|e1M0TzdOpZPQM+vexZyUg3n*PAz**O-@^8_lPi=b5LOL*`ND!DbKc ztbAGUe!K7wWPx}rho9qT3S0> zO~3X~al-VAK`jjprk@RJu1=eNGN>`sVA^L;Lusk$M}z9hOH4l)R8|`|eQ!`nU8Ctc zgNov{rf->=Tg%!_-x!pvt~34JpqAna)7J(y)F(|}8B~|-Fn!rWB_Y!n21RQ-OrIMR z3DukaW>95y-1M12<>@-p-X4laO`jSRE-g2GVo+IQiRoj5N`tMYj|?hqX)%4s)YRVG zVfw2<>Bf}l1B2>PanoN6iY1Co@AptJWqQw`+S0V?U8Y!lxZU(l4;6<^ZyOX#x0~KF zsHV8Z^kxqg6`S5Ls4@~Uz1~B`m8L%%gd0Pq*9;0(hfJ>;R8$u;?P03zY%VjsVo-Zs zjp=2B(yb}eOFdNFYI@P2)<~1-1%ndxrKab5sHn{JoIx$AYSXhl6iS+&F{q)w*7S4_ zg(Ie?42q?rrY8-m?Wi<8(L>3k>2ZTr~b{P~(l$#zhC|F)&deESvx(?F=Of~65nQ5m%sm?mn{XJ9^FzqlXfuG-f2F37O zwcVgdq}g<@LDj*4=^lfsI>V;B4Jt1Wo9;5GEM8%{vxh3nOxt=WRA<_1P_Ve!bO%$k zvn*k{-JrHah3PhfQYBH-tp>Gpw3u$`p=88#vq4RDRi>K^Y6zuFe=?{(U2odbL(NIk zjRs*^V!EM+iYiQhG^jQbHC=B|O?}98ok7vgPSdqLluVnhF(}elYT9g2b-2=WwL#(5 zI@47Kg~}RDR~l3rNtiYn6l~}){lTE3)_~~>rbwbKZMwXN8mmp0^-!$EbZHL-0;Y`y zwNx~jes557Yo+Ou9%`sJU2ITeqR4cSK@G76(}f1rH-}9Z7!(ms18RAhy_}z4X7=vt}>veE>LMeG*Mj91A*Y_ z22=;Dm-RrPbg2PV?e(YiKsvR=fYNCCR0B%Fb*C^?be2`0+ylX)#Rhb=hEM8&RBDj{ zs6Q<<0QIE>2B3a4-vHEy=Jh~2aiRgJ@60s-^_vq6Kz(M80jR$mZvg5mvkgG~;j0jOUbV*u(CGYmleVR{dQTc;U-`oYl#pgu6w04fU@fcyKC4Z!{T zqYS|P`AG)g{`-*z;Qsm%2H^hr;RfLT_(TS}|6OhX?r(<;!2Rno18{#j)B{CDr3T>s za)|-Be_U(;?hgkI!2REV0l2?gWB~5pPA~xXXU7|W`>*2+!2Q*+2GIRe18{$I3IuW~JK*g?gqT+0vP|G$1on&(tU5u}bq= zWcJrH@nj;|UT`roeK=DZZw_itBIDOHbk?vMH_{7Wz=V4nYY zbPybk`vv9x68{AM82?Crp?`>f0J;f0=rAb2{evHTfA@Xv`^5Kw?;YRkzE^zD`=0VW z>U#+H6Yloi;k(&)gYO#OCf}vLi+t;SYkX(>R^t9b+SlT%$H@VezSDe*ee->De6xJh zd`IDaL#eOGCwzzc4)zW84fOT%d3_F_+50Q*KYZi;!uzTBuikgPZ+Q23U+_NdeaySd zdq3_+Z1vvaz0rHE_e$?&-iy5(yytq)@viiCdQ;v;Z>_h|yTrQ)cPWnbPV-LkhP^@W zSnr|ULhoR2f3MH$z&(qfJ>Pl0^nB|1!1K1}HP4Hlr#+8)9`tO-9gJH%H+VLCuJByq z+2C2@Im@%c)9y)l>Ty5gbk8ZC1)e#cnVzYhBRnBbk!Or&gl8D;ZuIkbJT{NXz0duP z`*Zil?)Tkqy7#!B$Gwh6+&kU(xbJY^)ur)#*yP8eO%nO4kzCBG+8kvAAP0$rW}5U1ME`x(Z!` zUHx4?m%~-y{2BL8zI1--{J{CP^EKy-&ZnJ^Iv;dycW!gug1af3omV(7ac*#~ah~N| z;cUl!m3n8?dAjoy=K|*(++UgMJi-}r7CFZ_N8mooAZI_P$7yq#9Q$y;<#Wf!j`tmJ zI`%l8$9zlX_^t|;+>m$~k z)_bgX;C|5c)~l?SSue7#v#!E@q2<=Jwb@!{t+p=3{h@i*+144>$<~S165J;mWgTuE zY8_zhV|C$v(XW;tEMHqbvwUcI7x#@`wmfTj+_KBE!*UnyA8oN*YuRMkXt}_$7Wa`> zS~@K$OQWUMQi=OXi!5_3$6BUYCRxI`uQb+jsMU;PLHtsEQoT|=Qr%KrQk_yAQteW0 zQms-gQq58eq-s)4q}o5E{wnnssXt5oN$NhSKT7>U>i1H=llraHZ>0WR>eo`glKQ38 zFQk4h^>0!?le$;xr&2$W`mxlHq<$#%uTnpd`WLD1OMOr3yHekg`nJ@!q`oQj4XLk7 z{j=29q`oS3kJMMBzAW`6sV_=>LF)5TpOgBm)MunVE%hm>PfC44>f=%$llrLC-BKTs z`moepQXi7~pwtJX?v#4J)E!dqle%5%y;ARydbiZOq~0lYo7AmR?~r=C)Z3)qD)knr zH%q-q>Yt=;k$R)l8>IeG>h)5ulX|VxYouQEG$KdZ}@#by8ze zYo*pmjY^G3t(ICPwNh$@)YGLdle$#uX;PO+Jyq%{Qcsq;Sn5eq7fD?xb%E6RQs+rM zQR-Z&CrF(m^?0eXr5-2sSgEt5&XjtL)EQEzOPwb5XsJ`BPLVoU>QPcBNj*~P5mFDA zI#Fu5)UebtsUfMQQcI*3OASg5NG*~&LF#y^OQGIO8r6V_fo%;`mNM& zr2bv%*HXWd`lZw_q<${-Z&E*#x>xF_Qa_RUvDA;Gekk>?Qa_OT7pd<{eNXDUQs0sK zw$!(zzA5z$sjo}@v((q5zAAN()K{dwEcGR+FG_tu>hn^cllrXGXQVzY^(m=ON_|4= z<5C}!`l!_1QXi4}u+&{rACmf@)CZ*QlzP9^9a8U;x?SqMQty#^x753&-YIpP)U8tQ zkb1k++oawq^%ki&OT9_zpQLV)dZW}Er2bLr^-`~sdacxJq;8gawbZMmUMY2x)IUhQ zLh9vGFOzzy)QwVqFZB|s7fZcJ>V;A-kb1t<4N})jT_^QCscWU4D|L<3)lyeU{hicv zq@FGHEU7uES*aPRD=lV|){HAKr)Bqc#_#9$B`UMGK*v;$uT4|NT!oaBRQI6D#;X*$s|XSOd>gw zIhdr7-mc-w%HpPJgn}mVtrvC-VjP(*XLD_QG%K|I>Qw|GoA9y!yY{UVu$5 zdk-F3I0yBAorX=meGKaVIt|^o*n#@LPJ>4u`4Q^>It_Yb=XlirbsD&KR~zd8I`#j` zKNR(Uo%Z`(#SN(c>(uvca|HE&o&0^C9EbY9PTm_Er=tF^ljlO)D%AgVavt{No2dWm zWdBR-RMh`|;PWyhipaS)Ooql|7{6(n$>-0lz#d_5L zb^89OvHMW}*Xi4DpLzuKf1SQbKI%dJU#G9XxMV8o|2lnjLGhia|LgQ+-46|@|LgSm zqhGE@{a>fQHGc9P>i;@@7Vdl(^?#i{{blHxsQ>Hq$*9sjsQ>Hq(f6hIqyDechgZD3 z0`-5L{(9swzo7o#O}l>`HuGcD|8@GgY{^5Y|LgSPyZ?9!^?#jis4jj7^?#kNe}C&s zsQ>G9@~oTBMg3o=6Zbv24E2AVX1rQ(DeC_^6|7%;BkKR%^vI^fmsg?wuhZInmS0f+ z*QxGT|6fr5*Xj7a8y`XaU#BT&?Hr2wzfPr_jvJ5qzfJ`MPn?4Ke>Xk+-LmivsQ>Hq z&DW-HQ2*EIlNUc(g!;cuH@?b9J<1@(WOPFdZ$6ZLTY1cE_ClgWs*XgNOBRf(5*XfB>!~CfK z>vY*8o429$=KE0p@1}>|tvRw2^?#jqes$n()c;9{kqaZ#(M$I^Fj0-ubBi>-77(W*v|EzfKoDz3Ua!|8+X~_uGF&{a>fU z4|+9&`oB)0t8YFS^?#j82j0I8_5W^q;GKiU-HrOcPJcRWNf+w>I<2^K{fDUk>ojF> z@@CZkbvod}rvj+|>ooA&G9Z~DS! z)cfg(v{;yL?G(=GU*Qt8(g{`Rn>$K>R7iv-e*J+_+-8R(!b(-|b z9kWsY*J{BYF&bxM8q#P3o6*XcO(`*TtM z@22hd&p!DR)cG9Fwcjwt{4BF1~Pf6==_ugd} znOhkyk8l4V#ZdS9{_i9iP8>XcbAn;?#A)ZWFj%*LyQ5i$yY4HvzP*WIU02G{$k2LW z^t}d#nM=Puw_b-kFN)v3IL3jxi7oEpI?Vu+zP`l?`25RR#fq~jJ=P*zk=J5>FZaJHQ z+9;1>pmxb)8K@m{76Y|A&Sao=#$y<$U2z5jwIfbvpmxJ)4Ae$=Gy}B>PGykofDF{; zH<^Lj_>N+rcD+dq)P{E?1GU*5!9eYFhci%{+(ZUygDYpCHn%VXwXu~kP@7taf!fhZ z8K}*ygn`=0iW#U)EXY9ZU;zed^D1JXHm(T_)TT9_f!eUfF;JV;SO#jN5)9NPHHLxO zp++-Mo6{%;YGXQ#f!dS~WuP{skqp#sG=hQJhz?<(Hlg7R)CP1g1GV`SGEf`OK@8NU zGmL@Sa1PW#w%H72pmv%e4Ad?&n1R}14q%{mmq85F&N7gJ+EoTHP#enr4Af@QpMly* z_G6$nk$w!+4$_z5TD*sz)cx$8o$|u=;fKije|dK%^F_Gfm3gxMU!rGz-|weXm;Ebz z)&xCMcH8}@4wv=+G2NM!f4RQ-joq^TKT^-EuRHa{X|n!*ke&&z9x|a-*8hieXS(jL zerxGcS^w{^XXbt4u@o2l34fPQ&$w>7;+!qA{_pM1toT%azW~!BwAA}w!mj@g?Ds#& z_qA`gZ=)~no8;^3{lI&-cMW#!7kSN|J)Rpq%RMJ}hP%IYKkmNV-RPd;?(h1@wcT}| z>-66Ke>qv8xBvgQa~690|9^8edi(!>JA;E7{jt)Oeg7P>@wK=ApV|Yr_4fbMRp{;i zr`Hr}^rx%Q+y5`GMsNTBZ(dW%di(!>do_Cd|9^8esL>zK8@>Jia^@E``qS0u?f<7| zQEK$3tI^y4FR#XbRsX+585R(zE2HbY;rF#PpG8Kx{74J4VlJwriBVhEXLkR@k<3Vo zf_!svM|p}&>&DF9%n@cv3r#Vn+mmEk`^xLTawId-Uitq2&i{`0|9@~aIi@)Fv;Wn8 zw|%w!RQovFKWs19uCcY+j%Up5&r>4@Yt%Ei%f`p=fLLs9ghl8fq5 z9LbHe$S9MCqUcj47uBmck{fA}QAQ6%qscV6sGh}9x|3;a#1~vBe{_l8D;)Z6n(bj zqIw%gaw9D=$^fD$`f$lb^*D~?Mp|T)2}Du!>5_};bsWi!w8$tUh^UVjE?Ljx2sfog zMwvkrNi@V+JoJAm(7 z8AB97A2GS8p2(5hNQ;azhbV$RV{%cwkt4a078zv_QKY$nev5ZdJ(8nzH{dr-nM4#p zpE9|qUdfT%NQ;aziYS6UW^z$IlOws278zw0Q3QR?PJOMfFgQ zZKgXjkL%p zE~@u(BsbC`qYNdApbwl}R1fAzZlpyKj&M_2 zWR$r?)#x)P7uB0Nk{fA}Q3exLqYs^2RFCFJZlpyMp>LxqYs{3R1fD!Zlp!Vl)sdzt}mijse7qj z&QZFHLZVACqm7sGsNBzy%t(t4)m%z1PxsJv0FKgJnh@=Z z8Dj#-MB4>8k{M~yrkaEFBfN*U6L6H~V7*8yW{epi6Kyx(NM@u(t766&0+{4>1de1z zTBP#LG^T(|v|WKC%#;>b=>GE%=qijcAQNq8;7DeqMM5!S%mJBby8}luBQ07KGsYm0 ziMB&YSutZw0-0#L1V=I>Et(WF#wfrfw^MK=Gt#0_F=NaEnP|HOM=~QV8Wc0e zFp!D1V{jxh(xP55V@v~?XuAeSG9xYGiWy@ZV3ON8IFcD@QKy(O=7CJK-Gd{UkruIh zGmU|ONp1(>2s5Qct!gf!XWnhJU4)}F7nO<{#f&i$WTNdP9LbEdh$?1`nIIEwH{nQT zq(wwAV+;kEXgdl=G9xXj6*IYLNQ|u2AOC(3`a5}ElyX>0eX(xM%!gLN^>A6mMLb8(I69Tr{PFuq{ULz9FRXj z+HON;iqae?6{jg?jNu>?ZO7qAW~9Xu)tpX|iMH!-l;(6woT`{H#)C|>orfctkrt;Y zW{mkD6K(h5NM@wP$@yj)141U+4#W{=N{hv+Iaov{+AhRVnuA5+B*ly|B4ncNL>$SC zG`;^{XxeV_zv#c#pGNooVBcrHoxTm|wJ*UOzt_B5yvx0FyoH{xJ&&NTz1B0)<8i-@ zDSTP?0{5ZlFMrZ?1^UJ(yZWIY{4VDz^m&hU{EGhV&5jiMvIk*4-VXaZ`|0STw%GQd zKf2R4+cwPlrF9qjnWNUQ)n$3patr#8=UGOWzcW8>zRX;2o@DNW`E=U~&M8=2Fh=`X zdse$jOK8)y0j7`ft?K`Ytg@6y6esC%w3oJ)bHu-s(ju!YB@!4pM=siW&XL?mi;S|C zppkUsqOIv1;ik06D2oXiSw}9~y3Uc@NQ;cJnrLY)rl;z?w6&e1bQj}|qq3Z6!N@yu z(bjj4N+(?UzvaFzye{jjI{~Y0_w8$vyie`)iBp0;?a3nXDU1V?fsEi%diqq#gzi_cG~b%LXG$8k$cSz$C|q$0U!s}x6aBP}w@5`zY+kc(O` zIFcJ_kx|wd%^1l@E^5u-NN%J>Mp*M7vs11M8%DfqU561B97!nT4d%b zZj2ly7quR7BsbC`bAswFqH7{slQ>Fu5w6J`#f_1rHTXAFLDY>Zii6gm@7MbHzcbFcr4^wLtN9hjZ5qqrS#>iB1QR@^(aw9D=vlKT* zs*;OZt2mMyX_1+!x|8x>Nv&7prYPM>{40-9+!)D9E^5uW`^R%$X0Su>lR0H zBP}x1Rd=cUzNxi~+!Up|6yNtW#f_1#aLLv$j^svKWR6zd_4Je9MXg~RrMn(K`KhW~ z-j>}(tz+b-DBW~hc8cQ0NLg}GYZ*s!BP}wM6*orCl8ai;IFcJ_kvU3nVHhrA6jQ#f_1+l;VuE<#D;aK(+0 zxa6YNIF95-T4W|FZj8)@OSaB&BsbC`Q?9r%QkPuRTE~&xNQ(^K+Wqq#uNsWpB^R~c zaU?g=B2%WgF_M>D)SAbU+(?T|NO5CiFS)37k0ZH}7MW7Tjgh|OqSii+q0x z{VX4()<2HYU5TG%vFZ-d&+bY4VRBLHAxCl}Eiw}nH%1bZi&_&ok{fA}8Lzl8vY1@dy2z2-NQ=xk)t#j0 z*axV!k)w1cv2^@D_x-=Jis)zz(oge?)kohlf+PN&lonZK717ZUr)&2`r{!HYM{*-A zvdSu=qoIU;_Fps|_}Tj$rMn~{vdSu=BVJEG%`awU7VqUqZlpz4Sw(cj<*7|yOqyx> zn%oqn8>cp9l~qJXU8Id%qla8gj}#fnjkL%rtB8)OT6!({d}Z;o%Q=!8X^~Y{5giqk z^soGU=B(>p;7D$yMOIlwbcCAex$SR%x7_d&M{*-AvdSu=BOupde_K9m;GN{ANN%J> zR#`=K6t$L+tG=!O2OPB(ju#@BHD{e=#_r&n)^JPIg%S`kyTa^Z5{Hpd++L&ar8PR zBixi0S!ET`ma3#z`n{_>L+P1ZMsg!9vdSu=Eh(!ld(U}%;C1AtNN%J>R#`=~H8skw znTtLl|CJQUjkL%rtBAIy?)!2p-|YJ!eQk=;jr($0WfjrZ*j7reuC@JX6(J+Jkrr8H z717oxUorQd`ORxzlAEG*;}tWjtRmVXCGw8d^2Z*MKTC?_Mp|T*RYY5PO*?(f&hMvO z&XL?mi>$JWXbT18oz3?6!~$|tBsbC`tE?j0N}J`Qs?FOmnA{Y}jkL%rtB7=GW13v8 zKku5r5pGJ0tg?zocf=aVm3r=C2S;)vEwaigBHb=G0qjk-{wP0-BDs+kS!ETGZk20} zy$Q>y6uhc%dz+54}Y4?k=#g&>`293T}|u9y^HRcPWR4aBsbC`J3@7bs>!u*%ByoZ zN_VJQWDil?afjr&!h5F|y+`*!Wh6J!B71=1E-np|>*$LwlE1|i$&Iwg z4pQ8Kk|J_Xx%AUAj^svKWC!NElkMHLrpXgGUqNn)a8p`j2Pp1Dv;65yYTo`=a#JKX z(jvRR;%<_M3-3MRfZ9#urbuq2MYg}d4L8~3 z6{JXRq(!!$>JG|h;*xv)@+VJGx`S0B+gEW%%H?ZX@$l{ResnKIaw9FWeH3?<+|sZ& zu;Hll$W4*lNQccL>YAK#-aw_HGOif~g}WL=88 zEg+wLMsDc$IJqg38)=bsD(+-duB#4tcr?9x-Aj?&NQ-5h5!!twg{6Bp@mfXzZKhh=l`wP_J7^{KkLLPeRvq)=8fl8 z`x&nK<-6rRhE4abzs<`);}$#&m#=?)yqn>&L5&MqJnm$;gO{1)GLzK?Nc-_z(1xXrg2C-j};YxmXpmiXr2 z{I;(hAK=`!#~s^oUfU+e2AtEDazt@H+p&%#a4uV+qaV&=`_BF`&S87nz7yxKZMI*8 zbJyDKbvSQrj(sxv14h^f*d4Zgw$E^`+Vi$uI8W_*+eVzDw%pc;^V8-E+4?BXN84h(0_UQwv?g#K+9K;roP##jIt=HZ65%gEw;JnPa7U$|UJ1cRX z-VA3L=jaV}`h1gpLEi}90H4FV&-u{U*dhbR|Z(NRZ4Nv#Z!+C}w?Ydrn<$Np!XbDzf3kAHMJ+s0}u z^}qdxAMW_FPU~XYwqV3OZ3WZi7oWLKJCkYsYmF~y%b8XWzw21-44uAzcZTaqt&{2P zZ(a;*9ZZ)rj5=9sXUhKJnOn3rri$8EzSYu9C-%Q+oYu-z_SURdw3JTYUHbV$Z)-`W z%HLV9*Ah$>lLkJjwJ;T(_4XNBGt>Cc<5y@+O#9d0c)r%C)3@2(R+rYmRQkJpPOV<2 zZ@wBjKdi-d`uk7ScbulxG5z>j!&h32>Cr6@oS@Y*U9;}tN3PG9}#9QUGjI@5#uMqHvTW6HgF zVzaiCsr}uhJG9f7PQUl-gR~_~vu{mZqn*k$>%l#+A%uG%^%tf zCfeMgO=qIb8`?A`+MJ;s%|x3ow5d$Axk8)5M4KkG$xO5;A?o9()m_J6F1GF+GD*kIBCMxP{rA$<`*Yt_H z-9>q=m_J5EcP+?7MRhH}M8$IrGi~DRilUl6FSxttsSV?gQBhMnkcoGG=k1*Su(pFKJ7~zQ+I>vZ558ukww8-^(wd*D|?={pn-v8YcT!U)-c^*2&cJ%6l>GYNknp7rm=p)lDn@@x`EJ zd$cQ=-oD_Y54BB9*K7%_)&9V=M*C`^b_LU!*WB&ZE@x_pzW9)K8Poi)b6M?DoqnBn z$EX3?MyBxVgC}dhXBu+Az!BOdI{otWlM5f!E@o+IAnVmfWfzyj?;oqqnIVntZH zfa&%5_DS0LOwaxr9ItI)TD?Uq)z&kedDDYIZ5>nlL#1zN=P?~|+V+FAwL1OuxTf=nVxNjcOR+~)P9aH|?)kkFCcwhUt`(s`Ht$U6bq5Io`A24~>tX!`BMJL}&8}{6yz0dU6C8N&K-eY>;hU;c)?=s!J@s6PO z4%1B&ejcyA&2+`c)9bXin9lv;y+3MiGM#Hq5}Z4cAL#>Y<8USTSqux^<4GSld?fSxMMW(Cn z9^bCLz;s^y;3u@_nQF#;KNno$H({aZY`;b5Za4e|hKsS%x@i zFEH(J!HIuN*ujDm|Cq2t1tA|CrFnj}!lx(5H_R|CrE+j}!lx&}WYm{|qV#;lw{C^vUDIKPL3S zZ->1e+CtYasD3@x}tIZ z9}~KsasHn{Ma4M(j|pANIRDR};!2$V$Aqq9od3s!u40`3$Aqq7od2g2bp_-6KPGhj z;`~1*boJu=KZA-}asD3@x^i*;9}~K6asHn{MP)euj|p9~IRDR}P!i|=F`?@f=l>ZL zj^O-1CUmXh{68jirQ-ZQgOW*{|Hp)`Qk?(CgsxGX|7TEXCC>k2Lf0qG|1+q*8t4BR zR8@)d|CrE~iSz%M&~=IP|CrEKiSz$-qOM7t|Hp)`NSyy?P*DKq|1qJf5$FFgp=%N6 z|1qH}5$FFgq3aOm|1qJf5a<6fp=%K5|1qH}5a<6HR9S}e{|pM%;ru@)bnW5%Kb@#6 z59j|eq3aIk|1qJf4(ID|Bnd+MsfZh69$Ol{6C#&Kq$`tGpMl|=l>ZLYr*+{1_c5*|Bnd+ zI#K^;!T?U3|7TD`J3{vQ(tT;lvcCJeB|`F~6pP>J*Z z3<^eY{vQ(tOyc}MCJd0o`F~6p5Q+2um@ohm=l?Nbz$4E8W5NJOod2g24QRyqe@xgW zkMsYSFklhq|1n{JBF_I~!hl4a|Hp&@h&ca`2?Gvs{+~fbA)NmQ((rmq6AHTwzy!h- z24KSAnLW@@yW9Xw2t308OaSccfzm{W0hr*|-UGq?Lg0XVj4jsel)%Hs`)w8mx|P?@Ye&VZ6=?Xd;~OWJ2K(6L7| z4QTIdJjQ@@xOs*FiSqL4JrHi4WheYmYD>SkiX50f9(rB15<{U0ZHIN2E4vKspgAGoZC56zYMZqEZ7=WtAlc zBx;(94QMHD4;s)=k`5SvCeR`SYQoJE45%oNk2jz=5FTehFw{2IfIwNPFaXDy-M)Wfvl<4SdK%gVqhoK~u4*3meZf^4#(3q(38h~RLJUvhv za2tRDO0FI#t#TTGg@mIA>RRmv;MfA20g+gv)c~9?U@-va2bdY?e1HNsUS*tkm7)3n zF3%OR{_h<6pVi-7SL{b0Osi-5AK>eSoy`m2Ff2Ow15bFO1HPoa2&y*;sM*ZKQU^(jlOij%lsQ(*O z)Q0*$Q$sq4`oBSyO{o7f)z=rH{?AksDnb39DH85P{lAC8sQ)unHZ`IC&s0$yMg5q}7oXR1uLqW;fRQ65J9pQ)_29rb^vP$+=< zKT~N-J?j5VCFy3=|8;6BudP7+pFdWdPN4p;Q%7gG8ufpsRBbit|4fPMYSjOkFzo~N zegpKk_77iOqj-j`oBTpX4LeQy(=br~XTr1#)c=_<%>wm* zCQPe9{a+`VMuGZ26Q)g|{%=sA8TEfAOp8GMp9#|-Q2%Gbv|1)7)0_y)vn1+D*zd^+b)c=_<%>ea(gYa`d!XQi|K>eRT zhG_$+|1)8l0P6otm==KgzfLp_0QG++bo-gznkKLSaC`--rG?(JnH}KM7KNY{|1$|qyEo?ZgtfE4T`s-{;v~to1^~Egl=-w z|C!J&j`}|ny1`NZXF|6(>ii-7CYEb`YLboyM|4is6M*W`&-NLB<>qOnasQ)ve z+ZXkJCUo`bi1Pd&xCGP z)c={#t%~};PSlNx`acu8O;P`6LN_Vu|4ir>Mg2-An)hkkXN{Lu*R^18K=;SurIqO_ z>Dhk(NZ-7oE9kmJU4PZ*wwPJ68L9tHk4KS!Ch`j+!$<{db z1{f4<#NGg=rdTuf1~4_Wm0)jxL6Iix4PdHkYQ)|ErrKl>djps%!%^%FFsP&kdjpt4 z9YO33U@8tpus49Is49uQ0Xh|ThKsQ`fGM3W$KC*@M13pv1~4_Inz1*4sSdBqxAss` z1NH{+$6~=^>u0Hz359)B{Zx}g$#1NdX%L=bxe42pJOZvazSs1##R~DG{m1-T$|@64>;_;e$JPDNpb);Z zzZz81*oNHz>XO(EU{FyMy8)QmIx4Xn zz@ShVy8)Qec*siroNA@#diRq(PBj5q1M~e@u4MYj%TrYl-@Gp_$E`N$pycjPcaLJ8k9LbHe$mLHF zLOO~WW?coe5sjmCM>|9=e~M7N7%xKPqK#@C$&IwgTIBMl2*rbV z5k>=y+^ENq+(?UD{uH5j5HHf?qK$kU$&IwgcaxqyzFh zp^bp#rYPM3d?)!+gyKOg0?0)h1v!!%X_3pHB7}4q&8GSXZ6xF<-DUV$=1&od2eF7C z7i~1;NN%J>E`N$pJcvaGTyi5KM{*-Aa`{t);z2Az$VD3!Ig%S`k;|VVgmei_Ci;~& zGIEsek}{FYpCS|wVi5zE+~~-W+(?UD{uH5j5Q`jg(MCv)5}tT(l9BBe{_l zx%??Y@cccHcmOwW$wiG^9LbHe$Z2^qhvEU;;3XF|dT}H-(jsS4+_(WuE@}kh zNN%J>wo7%_(ASoYVjQKr2Gey{+ls#_jG`U5qpk(;7);|S7hr{cy9Y`A128%J^@EwUY|J4n9`-&3O- zN9hh?K3cot#tm?CQ6n5jaw9FWZK}J7=0<%_jdC2Ny9o2T(ux~5(8)!ObR5Zzw8*xq z?n;_u^*uG(ag^>#OtMNTZrp$;7d7H>BsbC`n^fGmK@XQ~)Z<8Qq(wHNxN!rYT-3SiT<4$9m!2mx@n$ht>Q)jgk01J$&uVhi)@YJMuCJ} z)F{c3+(?UTRB@w#LN02gB3q@n zQJ^6gHEMDsH_{?oskl+VAs01rawIp>B3q%jQQ#pLHF|O+H_{?|y5dFw2rk(O%8}ei zi|jJRjRFz5s8N(7xsevxrHUH`Byv$BDMxZ6EwZO6ZWNfvMUAE$$&IwgE>YYlK#_|Y zQ8|(uX^}lO-%SN7a#5oyN4P01vZv&`J5j(Q7d5hSq_2&%$ex_{pC z#flpRFmh2NEJt!9EwU#mZWPGil8v$)$&K{?!SnymQdSY=0XiJGtH1lT_1|;E^ADv( zPFY2SThn-ickQ=%(-Bz7c1O4=Epo~#BAlc%p1Sty8j_=Tm@<+ZX^~S_5#c1Qe!BKc z4t?b!j?zu5A7vF0PK5Bd>e_GVIa~4Gt2>e#X^~S_5#gqy6uCzI{cikJyCb=g7CB`V z5stUum8YxU7mtrPiX*v^7CB`V5sp`2wb|8g?-@6nIZAg0R-4KyA{=YOYe`qXSALG; z{ZV%$H_{@ftRlkEcD%lJ^}A~ShVwa+8)=bKRuS0!hgY7iewPe*Z7oOXjyH&$vWf^t zlK4ID>bK?$8=eunBe{_lIb{_Qt}3GI-EYYS>tE(bZlpy{Sw(~^5@~YH{QW_zIFcJ_ zkyBO?;WC~@?E(;dl;w8$x|h;VV5u6N%@BVS>4-yO+~w8$x|h;VTVYrL+$ zk8E+=!%@0Zc*moxBEo?hx`KT#J#ytxj^svK^>A zOitkL>bvabZCL$uN4P01a>^>AEKTP`boCwc@TMO)k{fA}Q&tgW=@8bBU42JheQ}bb zbcgUBCVv$XFKeLr=v{r*TzcMmj^svKMc-WhlGnIJmkXHg_K(ju3?ijai| za#K4ZM{=VcA#(Yvh&UA{;F9f%9LbHe$mOph;$BA364h?k-8K`v^C_TH_{@PzluOQ6ebt7gL0Ja5bpWquOi|h z6o$w}?V=pXjkL(+uOi|h6pqM6?W7#ZjkL(+uOi|h6qd+E?WP>bjkL(+uOg7Hp=UN9 zwWD&B?ixI^<*y>*Arz*_MeV8_$&IwgEy`PS#6u`t!6n;S{~z|=JIcx`Tlc2c`|g|& z5fKy-QIUmOxpqN`h=_=YNK#Re%4zS)*+6OSU>h)%2@@v700wAOv=wP{q%pMGw%SrA z+DNNyK)v&szO%mZ?RCZ-_uTWHGtL=b-#?ytpULl()w|Z-d(M?!iJ&R1`xY5AEo_0p zaaW0;DXse!nshZjt3o&qE0O7H`m9=D(6lfH3ddz7f~K_Yn{Uvxa7Gj#rzV1OHXiDq8 znFdW;JwV|)2#KI6t^1BPXxa(_3fDzQ1Wjq(H^ZQ5s|ZniorFZtl-7MmWzyJ60t(kn zNF*9*-8bE!X{!k+Tt^`hG^KUlktSV>n$3&rDkL&pOEudxldi_!(u?aXBr;u1f6F5b znzpil!gUuCK~q}yO*QFUyn0eI3$9mwC*c5XxfSc3fFZ=1Wjq(7d2?w zszVfC=OGa^rFCDCN#|o!xpCcxM5gm;R23RDZS?_#>p&!ernK%WFlgEeL=;~aA`vvD zbzirNzsrnK%m)TFafg;}@`MIzJLRD~U4 z(6ki_6s}8=2%6HmZ<0aNRw+=pPDLVUO8-yp|BWi5p^Mk(OC}c{hzf-x{qICtCyXkh zp&d^`U0zb0y~jQhK~q{Mj4Fcu#`rENDLP;bDq4=9DXkMm717X8htG(T!tDNlM9`Gh z38RW=sO`jit)yVmm0BWbO6!DCMKsjbVHB3+ebaS{M5gPSbi$}28mj8>tyYqI(-ruP z;|QA4I$=~14du-kvn4spj@%{@G^KUIs3IE5x|lvJumJsZ2_k4p>x5B7H00x%+RIBO zy?4;h5X`L{thTm8I5(3I8*ql$=EX7f93 z-%oz~y%9lES|^MuB3@pNo~vZc>kpzIo9y#SFTdjuiAGu{j4C3Y zU&-{|H=g|-el{Y0Hl=mKs3KzBZTMCz8NGS@%@T=5S|^MuBG%o69-w5@t2_8_iO6(Q zmrfW}M69)df8UV{zP{Yb@)GylmHY}Kf~K@i7*#}lC7wRIyu`KF&-~v&1Wjq3(3v$yePx{g zmg=&bQO}ehG99PCz z%LH(h@;aS|<+5r0aUH*1denPj{^NQX%@Tu-Ias!J>~mH`uR6P1Wjq3 zIKZHrx=}k!`RA(}@ZG=>G^KT7yg@g#;S*xYcUM(CC=oQJbz*;mt}Dm){FHB2%v&!J zG^KT7oIzK$@oVyr)B(?fMg&c1o!HNyOMCFWGv({1;=f7+O=+DNYtYedd;?DTs%$4d zV>yDRv`*}6&;=D3Ra3r9KaFp2j-V;66JrcIy9brhlrQq%n<5c3rFCMTOuDwcoqzAo z%L?uTjYu@oI24a|dl__dBR*rNeA2cM^IIH2Q(7lR8gx862h_(i8u87|5j3TBVo!sP zwejoxQQ>9$vk^g4S|>&rbmeb<`46-A*#kct5j3TBVh@8Zt4GB#Wnjc4%!zOWO=+DN zZqTKz{J(PhUa#T%X9^-{O6$b#23?qk{%FeI-bqfD2%6G5G0dO~TKTW?{v*p3XhhJI z)`{H=Ig?M-fuqoH+)M?K?F@{od}wAEq|W;*?Rl| z(1=Xe(&tIQpj&vgZpv$K+6zG=f~K@i_zgN<#Gh=hp1;>Qpbe@Q(7l%gO2iC<&+n07{{MNh@dI06P7{em!dwI z@_hAK{7ypzO=+D_nRIneIlmj8+t1J6R)|C+trJ-W-POYMGoKXjCmbSZO8djp`27EW z@c#M#(Czd8AKxAD|HG#T{73F?z}*3Z=l}VJ?B&NCeD~|Gsq>w?J!ih&@Q*uGTHI?b z4;`jb;%;8o{h&&UySU)~GL;ZFZBf@zs?TvpuRY8A4|Sfntn(_rR_8iy#v2dak*#{g z9pZBLtL2V6>VZeDN~&`lH~pJ*PM$hj+{$m;D%4rx4hr2hO`YkuBiqkA>sr+#Zr_(r zyh3%0+h>o+&#KFDN4)JFbF1nU_vXj%-mN;s#r9qJt!fun`PiFVRhzh3KR>uuwK{I< zqd%taRxRRocl~v-YIfY=JExD`uA0PcJ-2S0Y81Eb;lHj|4dQM+v8YhR#ohe$d43fW zw`$wizo>d~H_c!4f~pf&we{_rRIRwm)uT^RHR2){K76mLc3jB`zudcCRf(IsJvvoY ziaY-C&nBn}adWb=J*r&X?DcQAsxoo2`X@ZEO2r-1A8%I6#Lb-2xlWxS?&yMt-D;`0 zqkg<`qdHyO^ffnqqD~Wcbz)S2^O)YO8E< zXra|%;?N?iL&c#5R)>f~i>oGyLkp|4IJBs0qT{#)RR@bhtEnc4Lo2Bc5{DL19Via1 zpgKStT0J#h99lWGzc{pLYMeNacHH~zT(g-sWIZv0;zq(q191)i$e>e zMvFs>qDF~BE28!ihgL(46o(c(`75A^($emY$ zw`csfyp4SR^($1ly3_eR=bz^*o2J%?TfU<90(FPD(+^y*QLPp?@6M*bsM{TP;#Z&M zU!rbv+`RThyWOR3b=(Q75AoiuZV`9jcO6l6v*YGIz2u%*YL(-Te`o8MyVXtN{^Tu4 zs2jyyYQ1x@y1{XCu6=&#Me2HS=l{9#Xmy?Aj(g_rPnM{aj+=e)$7A+W*NQuR$CiJp zYsAfZ?7Uah)s8#%hCg1mTwNtD8G5NhT`BIoMYoSq{o;DRS3Y%xxY;>fPpQkrP57l^ zfx66bv(_)&r$JpRuJnSHMd}i9lh0m!y;>nI_~W0JsEft9kGi@-UF5i9uKjj#g}P8& z*VmKE)dk{Cdn9YQ`kmvr#Zz8!XyKGc99lKy7Kav0xx}HxQnom>P|6aA7D*{_Xn|Cg z<9Nfc8sa$K5S;a^IBfXM`b8Wz^k)4m4jXo}c8SA=+^nA*#~W_5eiVldwOK!i!-m9R8$PqX5Qhz&S)Yr;hRv+c#9>2b*54h+8!oeUI8SU?JS6q{A?i8j-xfWx`n%!k zS#dW%x#U;%jN=wQ{rBiZ^|ZLPf6LliJteMZYR72xq`1@0?k`n;bliduwp{m(+9K}q zvH3yugt+{fZ{DXii<>ZW|2FlwxbZhEpQs)ax8M8)*Qq~<8?)k@x$04IdzZP7Q;&!n z`Qy3;YLmD!8RU5=* zExrB>wcc^_f4TE_ed+;mKmG0Ml)7Ks4=XPortTB>-J=%|RriYf$A+I?R_nxlb;;*@ zsi-8_dnfh(gRVJF{r{kAYN!5RTxD?q_5Xt|+C}}pxYC>k>i@-McNS9r z@3_XUvJUG1#kJQrQ2#HkIaWpezqrP#2I~LC#T%Qc{~vTkE!6)Hx|}xZ|HZ{}%BlYs zSJzcX{lB={_G;??2VGSy_5b3kV;$80i>s2cUj`o&N|1XaAj!^$Ej`oI7|1XaAeo+4}j`ns? z|1XaAZczU(j`n6y|1XaAUQqupj`mhi|L?e_o{l`4*OGsuy%E&^I}UpvsQ({yOi@;j-T>(u{?qqTGD|HaYTIQ9SHXziQ&e{r<7P5u9%i+51}FOJrx zss9&8YtPjGi=(w=>i->wwPWi4#nIX@_5b2%?U(w0akREe{l7R`yQThL9Iee#|1XZ# zUa9{VM{BFp|BIuwQ|kZ4(b_2W|Bl1jC-wh>F0Y&Ve{r;SN&Wwz>n^4KUmUGHQvWZG z))uM%7e{M{)c=d4wL$9t#nIXy_5b2%ZIAkYakO?v{l7R`o1^|;9Id@k|1XZ#)~Nq? z9M;aL{~vTMRn-5BqqQ&U{|8-dBlZ8{Xzhyne{r-nMg6}xT6?1YUmUG1QU4*1){dzE z5Jzi6)PIPhwIAv~#L?Og^&jGB?S}df$6;-T`VVom_Co!Kmm>rpQxj!xrIFC>mm+fgqhj!x52FEr@dim4Y8N2lSa z7ZOLO-KZCG98R-QFC>mmt5GjB=n8YG7ZOLO&9Zig!=a~t-6n_icAP%>zqw7WC9koF zR(YIPw%+e~)pvx(wRUUDLc{Q}kBd&m|*bZ^k zZQW7o7@dEsZfU5aj&acCbuDP~|I!1Agdxer{Ct-+7hp!c`f-}ni>meUQ1kKT|LcfiL0+F zqIoTGH4UvauO+U!JVx_c;wsy6XkKg3)wR*QmblXT7|m;mE3T`hc`b3#`dXUT5?4t5 z!})_Que*WPRpsCEx~geiRa|aCHLa_P%c;e>s^eO^yDMp3Ra{$pEv>7HYp7|Vbyack zoG7iUimR%L(YmU*(#~>qj-MuQwz^ggiR_B}lRD1NBcDXJN8XLR6?rZ4O62*-Q<2S) zM|_ebuD+!47Yazo^r$Q6+lk>5oUk>!z|NPDCyQXi>`ltxaAoD`WKIX*Hga#Un$ zq&SivIV>_UazJEkWOQUiWVc8#;)$s6&*AUG{|J8({xm!gelPrX`1SDC@C)Im!%u`C z4L=xuAiOrbCVXr7#_+Y_{_rK?3&P28Z}`k`N4Pm03s;BB!l#E%4lke;>tn++!bgNB zhYP~lVI4j&ykB_l@Sfpe;ZWEcwnD#zeh7UN`ZBa5^kL}z&|gAtg#HwIG4u@0GyEa+ zP-uNTLaGro(wz|cqs5d;GV$hz^cH?K!0FG;QYXOfwKY~fu=xRpdzp|aB^UN zU`}9WU|L{uAU|+uU_xMAVDG?)z|ep{VEcdZfA8Pv|IGi9|9$`4{@463`=9l1@jvR{ z=)cc@m;W~Zjs9!=m-{dBr~JMC9)Fv^!C&Jq^PlEl?4ReK?VsVF>W}(!{geC$`p5c5 z`G@<%ey?BocKN>ZedXKX8}PmBd(*eg_oDA<-)7$?-v-}0-x}X7zUzHg`7ZTc;7j<< z@paL26=S|C-!k74-$LJ9dcNXxUx}~Km+hPA8}A$A8|fS73;NtNr}Lxt8}Aq1PrM&^ z-|@cT-Rgbb`=s|V??c`Py!Uuldslf^di%XAyytt*^Pc7H@HTntycOQ1-jluay>q-X zz0zU*^&@{&Yh3kCRd9Jfu9j+!mPPqm|Vu06><&}9u#D#99O4Y3AU1FU{l zAFG$u!|G;rvD&N_t76S!9RkhzmGu|apILXY{>1tt>kq8ov;LFyJJxSmzhV6c>rU3M zS-)calJyJL&sjfX{X6Rp)=ybKVf~o(Bi0XD2UxeWe!%)S*7sT8V||zPudMH|{)P2z z*0)&SWc@Si8?3LhzQ+10>o(Ruv2JC3h4p3Dmsnq9eS!6P*5_ECWqpSAY1XG$pJe?b z>lW50SU0mi&iWYZA6Oq{eS~!r>%*)Mu|CMUk@fei8(7z~KEQfE>wT>EvaVxY%X$y% z-K=-9-pRU#^$yn6thck?#(FF3Evz@Qu4283^+whkSg&Wjj&&vLwXD~$Ud?(H>y@ni ztXHsJ&UzW^rL32*u3){G^&-{_SubGy9qak5Y1R~Lk~P8F$9f*?xvagc%URE1J)89` z)-zdqSi4!fSUXueSle0KSX)_JSesd!SQ}XzSmUfQ)_T@D)>_sY)@s%&)=Jh2)^gS| z)>77GtY@$;Wj&qsG}cpDm$06~dNS)ttczI}u`Xm?z&fAxMAmt%C$P?CJ)U(A>v62J zS&wC%#d-|uOxB}WXRsc{I-T`M)@iIquuf$?oVA2?3hQLnV%8{Y5o;l90c$>M9&0XZ z4r?~+VXTL;9>O|_RkKcHJ(zU@>p`psvL3)Xo^^lLajg5Xj%D4Kbqwo1tb4PLW*x=4 z7wbsYJy}Pv?!h{ob$8Zbth=!eWsR_gSwpNr)&Q%Y)yL{(^{~2GU92{%#j04dScgD| z{L1(8vaSbt*uk@W}G?^*xJ`W@@HtlzNygLNnC*Q{T$e#!a;>*uVWvHqQP2kWP- zpRj(+`Vs4gtOKmuSwCR?8|(Y5@3Fqi`d8L>SpUNMHtSogZ?gWG^$ph7Szlv)m315I zpIEoDzQX!4>r1RJvcACjJnM6;&$2$l`ZViPtWUE3k#!5}6RewAA7_1x^$)C%vOdDP ziS=RDhgctE-N^cT)(x!dSs!4%pY=Z0ds)}9u4TQ4^={U?Snp(A!+HnnYS!CXZ)3fc z^%mBfSy!>%#Cjv^4XoF*UdOtU^;*_zSg&TiiuFp?e%32kFK4}s^-|VLSXZ!K%z6>) zg{&8_{*Lv0)--F1HOZP_?PEQU^<36o+ZvL!9C8liY{*%VGa)^YZb%oT6Vd@`hqOUj zAuW(*NE4(H(g2A=Vvu@B9i$dg1F42oK`J2?ka9>Fq!h9Yat356=Js4{`!zF64N~9LRBy*^px)vmnPnWmn7ArIC}V=bsaq8JQNDOdbEBkqMD;k-e$k9~$vT z?C>wt?e7eK7XB#wKK1&qgJcq;k&}OQJ;TJ`10^Y;go-f??>M^zAt>A z_&)Hx<9oxm)%U#bN#A3>hkOtC?(wbmt@5q(_4`)%&i9??JImKWdjjfw6~3julYR4j zb9^&>(|nVC`MyJa6MW-*d;3QChWh+I+xv_6d+$!~XWoyz?|a|&zUF<|`>c11_fhXg z?|t68ytjF8^j_n=+z5p?+ou$Z`7OXo#Z{xJJvhO zJKP)gdcDfC%k!P*E6)zkfahJ$o1Sf+7d=mVHhVUCHh9)~)_895T<^KcbE)S7Pr`GK zr_0mgiFv9#%REaw3q5l^vpmy1C7wc0wr8Seyl0GOq-U5X=y7|7xPNqi-(RGdMa@R$!l&ja(<7#s?xN2NwuG3tLUGrSCT{B!$T~SxAYm)0g*I3sm*Kk+Z z<#j20m;IgnmA%6ru-~=cw71zW+E3e??M?Oud!4<;zQw-YzRJGTzQ9h{=h$6#iygD8 z>}B>6d!aqoo@GzBOYA~B+n#8Tx5wBc?P2twN;;Mk{4w}V@QdIl!4HD(1m6g54L%=y zGWb~Vq2L3-dxEQjtAZp=b z^1wxbRG>G|6KD%G1Zo0hfztwu1M>p212bq>OEi!hm=riLFg7qMFgy?rcmvA6%m1DK zEB_Avfd5_poBnP77yVEBH~TmFH~822*Z6PoU+=%lf2schf5Lx`zsuj^kNK;q<@${=y%gBS5LSt+z_szIj+;fi^KE6vuTEFYB(Cs z4Ns!^t+C-z;o;#h&2FjCuF!X(uV`*-AoOnN&CoWQ*?Ky(IkYLXf#$W=gl-94AG(TW zwJr!HLg$3KLM@?Ks4BE9v?R1JG&eLWG(A)jDhy?ZCWgj`#)L+OhJ}J5H@=0ep{x;wn#Zm8ZVKe?@)C`UUIfte>&|oplH6r>vi_e$4t2>xZlZ ztlL>XVEr2_S9yx7JjGR>;wn#Zm8ZDMQ(WaKuJRODd5Wt%#Z{i-Do=5hr?|>fT;(aQ z^3+!Tue`$gGV4pMFS5SC`aJ7%tk1GO!}>JqQ>;(2{*iSH>l3V8;wn#Zm8ZDMQ}^+I&896jynQt31V3p5iJ`ah0dI%2QnBDX#JqS9yx7JjGR> z;wn#Zm8ZDMQ(Wb#OZmTY3F`{hi&-yXy^!?+*59$7&zfdUu_jp)tbMHKv7XD?%etKP z9M-d0&tg53wTHEvwTrcrwS%>twT-ovwS~2rwTZQnwShIx8e^?ztz)fatzoTZtzxZY ztza!@En_WZUB-F_>r&R!Sx;j*8_u+C&Xnso;2QLNKhk7S+3dIalK*27s#Sf{W~W-VrovKFxxvKFxB zv*xkpvgWX6vmVBJDC;4tlUOzDMAm~@C$JvGdLZiotm9etXC247AM04weObq_?!&q_ z>uA1nVBG!&!G{9mcvF)Z+1P@%XoR{98Q!Egt_CkAI8Dzs2L<;_+|s z__uicTRi?P9{(1Pe~ZVz#pB=N@o(|?w|M+pJpL^n{}zvbi^spkG&D z{w*H=7LR|6$G^qn-{SFa@%XoR{98Q!Egt_CkAI8Dzs2L<;_+|s__uicTRi?P9{(1P ze~ZVz#pB=N@o(|?w|M+pJpL^n{}zvbi^spkG&D{w*H=7LR|6$G^qn z-{SFa@%XoR{98Q!Egt_CkAI8Dzs2L<;_+|s__uicTRi?P9{(1Pe~ZVz#pB=N@o(|? zw|M+pJpL^n{}zvbi^spkG&D{w*H=7LR|6$G^qn-{SFa@%XoR{98Q! zEgt_CkAI8Dzs2L<;_+|s__uicTRi?P9{(1Pe~ZVz#pB=N@o(|?w|M+pJpL^n{}zvb zi^spkG&D{w*H=7LR|6$G^23ErRw~Tlrn^3hT?PFR{MJ`U30otk1DN z%lZuK)2vUiKFRt=)-9}0ux@63ob@r*Kd?T^`UvYL)`wXiVttTxBkS*3H?Xc}eSr0T z*85oRWnIU*mh~RiyIJpIy_0nf>m97CS#M{(jrCU6TUc*qUB!A6>y4~8uwKu49qUTg zYgw;hy_)qZ)+<^2S+8Kdob@uO8p;}B4YP(=gRB8oKdX<`%j#iuv$|MqR*O}!X0Z-| z{%e&f>otBIUS-|(KluK?q;ZQ-C2eG*I~3;QXoE!B3xl*y8n+0w)5da8I65YgXry)0 zxJ9U)HlBmR(K3mkDXo*nEkf<><+zh&K8~JAWV$>@ClAcLpP`*Lu7kqSG>M=ot&_$r zLhZD%9TbkPNd!%4oiuI{YNw6wMDfu!iJ&R1lg2GV?X)qTC_efo5j3TB(zr#aoi@%B z#Yf{Lf~K@i8n+0w)5dyGI65a0G^KUYxJ3vX?}_50brOk2S|^QLgxY9hK2d!1P9kVZ z>!fjuP+MyS?%FsWNAn~yT~Vf!#w|kFN(Bl>_auU*v`!kg2w|%gQGB#dB4|qMq;ZQ- z8*Rk`g`(v1$aI{>w{eS5D{UPEg`<%YK~q{Mja!6T zX=@oM9G#R1n$kLH+#=LUThEB%qm>dtQ(7mDTZCF^YZ@pVy_5)=(mH9}BGgJ-*FfQD zrbN(`)=A?Qp;p@31`0#QPKiv{(HJyt5o)EaaYXUaPl=!@ zt&_$rLanrQ4it`tN(4=5oiuI{YNf4ppm20lB4|qMq;ZQ-D{Z|4g{w^@f~K@i8n+0w z($+kp`05jhpee1BG+jB`=NaPh4)OYijOKI~?#`Tvt5GC6X`M7~5o)EaeV}l4ibT+q z)=A?Qp;p@Z2MSlKNCZu3oiuI{!qz}gxOzn*(Map0af?t3Z5K2KhDXo)3GGCJx+ImP7U+p3hG^KT7xk1y`L{PZ;MIvZQ>%=(*OqLh^(`IQqMJL=ix7Z1g_SR$aEh4qMhL z(~&<=xcWyTXiDougF(}gKv1|ENFr!T>qOk3>Bt}`Tpc74G^KSSX435#--qLBA&E@4 z)A+78>1NyNFr!T>qM17(~(G`_-Z7Hped~rm6aQ(7lZ zH)uLC3JO<8Nd!%4ojA>)=}0LkTrDLLG^KUoRFkg4H(&{_o|4FP72QO*#GvU&Dkxk{ zB@r~Gb>b9*rX#DMaCMbL(3IARlMR}Vw1UFbRuVx|S|?62Xgcx=3RhoA1Wjq3SZvUA zBo-8|#*zq{(*KkD|I8{PmQ95Y{qL)+UiapH5_8Hpt&^EmL@c|y3!k!;W2-A>NCZu3 zoy@EvC|!-ePvxEqW}#2w$aFPTR+&{qEW0ur-)a>*-d>K+PmZ7|t&^EmL@c|!9bI6> z>o1KDNd!%4oy@EvV%cSQLhJumYs`d$u6%L{dEmSI!Dly)=8s^=;^|!eXdbaz#v zA}n>y`?^me(Map0QAKpOx8rqQwzV*Qi$u_r)=8s^=>BaEYT1)(?ogl+nZ_KHQAKpO zR$;_0yICKA&j^m7DXo)6717;NkMF5vm&V4GNCZu3oiwV5?z$S(1!sI*KI%k?pee1B zMitRr$4~b<-mo zKK+~8&+&S5BpPX*G^&WM_Vz+hTi#pum_*Q&)=8s^=xWQwC)?@$ZC~PBjU#AE>!eXd zbhQ@Z6Yccnofmv25j3TB(x@W3TAJ_)ar)W0-(4pWG^KUYs3N-J{7kLW)n8BD1R4=E zrFGJ%BD$(7@J>5z(T6+kln9#AI%!l9U3ty;^f`6<{Zq0ef~K@i8dXGBP66tfB|lx# zy4v-|7_l5dQ(7nIn{*Vf+({R`uxg7$ zrlT~=aiT%zv|@apR6ou-Tq0;n>*PF>E=P5I(&=&EYKcsj)9-ykCf(7~(gvz1?>etU zqLJ3gxdz=;hW=>r&J)AL^G+lKB z3Ky731Wjq3oMF&(6%r_1a3&EnrFHTslg>dMyAT(kNn|>Q*0H7=G+m`c6km`g5j3TB z@<@ZGtCm3F0yT-CDXo*!GHG1J1PT|dNhBI+ojf9w#xZ(OxPVO}(Map$RD-5t_MmV< zn?%r**2%+7I){I6T;K*8k?9=zy-N(5j_HHK1#c2TQ(7md7&IN@2ZamZB!Z^2PEIyx zI_3`w7sN>fO=+DhHfXvA02D5elL(s9IvF)+x+VY=E|`-Dn$kL1WYWdxqZi-;I*Cjd z)31_J^rnd3_Jp+zw3P9n4JBdUit&@2M zP1hKJ!UcE|K~q{Ma}AoVIUtHJ$dd?~(mI)wN#hy>P`E%(BGE|eWVS)m9f~K@iYJ;xiX9&&51%RLtK~wsFaQ~mmtRiC7G5(b8e>&%k`Sib&BlV+5>r`eH z5v#6lMitS&<@MzwB!Z^2PGwdRvFgG~e75y(e(0}9N(4=5oyx2tVpW~Zc=z-_e#q@t zNF*9*oyx2tVpX+`s8IUgP_E2%6G5m03l^D!c3O z?a=?w(4EgoBpPX*%B&({l`U;CP#bTZfNvmurvbqMJ$^F0IZRbjfpee0W znN>urvW(Z!`|qFl2tJ26f~K@iWmXZfik=#L8~5Kk^PwpciAGwdGOLJKMRfr_H~ZJ# zyckskN6?hksmv-ORuScS>i)aG+IJghM9`Ghsmv;Z(!37Szh>qksFFD{P3thJ%qk*Q zQB;LGtbg@O-T0Q^2%6G5m03l^D)RIAFMr!FPoWO$M+8l2oyx2tV&&}xaZtCOc+mF} ziAGwdGOLJKc~d)&!BxlYIUO`2XiDo;W)%@Dr^X4?jmwU_P$Fnb>r`eH5i8G);nS-B zx@WH6OCo4W>r`eH5i8H;r^EDL<6VX7ha+f8>r`eH5i4tL$7fsr6>mN~Tq4m(>r`eH z5i4u#;aBjottXBIjR>03I+a;P#LA+z{MWf;x0h}OjR>03I+a;P#7aAA@!j2j@%92# zC>)7KTBkCrh*)V&6aVZB$0jhJ*pCRB(mIt{MZ}6b>)S#7Zgvs>9&uN+cR-oyx2tV$lwM(r^En z^Sr`eH5sS80^Ji7}-+Hmjp&t=6rFAN^iikz)_!&6;oexBYfkp&PX`RZf zB4W{k-#(Gs(~pb;jR>03I+a;P#EO~<_?x8Vp!)~SOt z>4Mri9QsUU-G*d5j3TB z>OhljMlaC6XrIvS5}9u9(WwJ6>HPMd22cyG-W8NcG}1aX-k{s^`EPmR!e>{3Mg&c1 zo!Z}^E1LPQGxyaXk3mGxl-8+nCe2SJ?>~OY1G)Iwh)mN{$y56obXhg}|Nhx6r@bf< zG^KTFtU>4G;;$3`I&?YuXpW#MtyBAE(s?~S_&kZf_fib&qa2AwTBpVsbXzs*s(8bz zUW{Chpee0W`xtanO9iMy6Sv`;gd=E5>(t&R9p#^WK=7A8fktFHN+rMd2jcFf5YP=can(o$#jyB^vt@i3!u@w?QQ(C7Y23=5$ zF0gj-)ULNAf~K@ig$+8ty$RHbt@|#P2%6G56*B1DR($%@9#%P@e}6>Kl-8+WCY{q! zhf!6tc1Qjki9{oW+cB;?)~4gTfIsrFF_{(3QOMTHQBq>^-0nK~q|%JO*7}UkB>ckN^CrM9`GhDYrpK z<9G$DN2^K0C4#23PPq)afS=Y~_4fSz&n228XiDppZO}PAsHm%MSbi10FFAsyv`$$j z-G;wT)ymoTohFg#Hu~$ROgg)*5#yxFz1~7c&yi@Pbt=oCn``iiT>0F!qu!PXn$kKo z#Go6i(Kl4CexSmV2%6G#{~z7|zj?^N>$dsF==}aIbVFY%+!d~)^U8DSl=ArSh_E;G zW9TzFmAv(Tf1`iqP51w?XAk~YJ`cbh{LgqIz`yU=3;))$7Q)l42dvwytE}^_9xG-o zwdPsV|F7=<|LysITb6%5fNc9JX`09)8pZfEP1xh6QSGx@|Gpf*4g~#Jry5X@@$>W?Kd9t zcT1kFvw2eOhNmofw$9`4ZCvQKopU%q_h3QL}?^Z1C%AG^VlXX`w^hv$VVOP;Os z*si_HkG164I*-krvG!w2o~`qT2j|VqwdC14e>i{6tLItrY@I)xHS*w5mONYM(O-5h zoMp+gbsl-8=?_m@@@$<)9zL&hv?b5hd8G27*Qzafw$3AJ`|F=r@@$<=skat9XUVg5 zHZ}gSaIGcJ*4Z>G>%#XfdA80&YaTt|JxiXg^U#qi&cDr)XX`vz@zknVuWtECcJ@@Wm)-uPf{PWsRZ?evC+_iU%zV0P!sklR0V<%Xr zJMPMo-M;>_b(-V)U)|dDwRNhvZNt`GVJ#82^^mXsYMmnP<>PMcwoVrJe9OH{tdqn& z=T78Vi^V;&{Fo1{MdC0qXe|_ni9c(BI85wW^TlD}&N@*XCg!Yp;xO@MogfYqYt~$G zm^ibJ7l(;4YmPWfd|Ahd!^D;~TO1~?tYgJtLdu#Y4iit-G2$?>WX%+Z2_x%hahMpg zW{AUtk9CwdOzc?G#bM&cI#L`aW~^!AF!5p?Ar2EN)>LtrFtH97hlvrZL>wkOtSRC! zp;?PiAhl)evY#kyF4Y4&z92#Cri$h~;O%#WQ)jC)l8dGb6I5eErLE_L@ zS_g_l<7gcq4h^9-UK|=eYkzTQ=&W(#(70LqIgT4LYpgglUe>EDC@d|vU(k6zNh}_INp}0z7vP-cj{Yl z*j}f;5r=Ja>L22;Jx=X(9B+G5UptPsx2dlj$J^J`m*TK3O?@E_+t1YJ;;_9;edajc zKBoRI4%@@j4##bLvFgQD)&=6$|N7oX*6+lnt`D_Y=Zo9#?YGxiX~+HkqsisJw^HIJ zc-z-lNylwC=gCKhS_yG8$7EGled6}-U%1^mPuzYx&%e+*SKJ=g-g}tU>$vs(n>Jiv zEf@E@(w!db9C6(ZpB-wQEiUA_{s-$U$35_2_V72XGsUegIQ@C6N8F*euH47!cHDir zx2E5-x*T`!)AkKFSe@d=UpI2S)#12xFI+xrgVpZ1ySJnkWm|2IyR+oww&$!?al_7D z|BBV(xHV6;y)?;ccHA9b?!V!Ft4Z7;qi-K$H9GG0i#(OzTMdr8?Y*O~f6I!CJN=3& z4_YzD-8z5&J&v>L9e2})5fgv3>KwH~4u%%=V(4x7}}`;OzyXzD%3@n$piuH$$!nfj|ZY!*}RIF2`i zslSNBW-s-&IBe!pZ;8WZE%m13coUZTv*UQPm3l)QHdCqB#bJ|_dQBWQL#bEAVY8Fk zCJvjK)Stv*vy$2>4x5qGD~{t$M(Sm8*hHjW5{Jz~>P2zb45VIg+{RBUE|_3lDF247 zKk9jL|9Uo{^Gfj63$;<)e}`uS{;U7@OrtyA$9qP2ymSZOXLP6gR`(XV%YC)`8oI;% zEO!Il-9FzvgYImf;2!nw>Hn>F=yts4>9+NC_A0t%Jz;my?dnVHIdrRfwmr@sZo94T ztsU0O*5?04{r_*zhKO}`SF}_AFRrVpllp>sOPg|BH*)w^9E;=n5OC{})%+UQYeL zxSF;G>i@-6R5nuoFRrw9F6#fqwRGoD|1Yk-K2H7r zpsUTM{$E^Ow21nDam7V3>i@-M#~Y~scU*f{XBGATgD#pw{lB>8(kklz#T8d~Q2#G3 znx9Mkzqq{mDE0r2YwNBkr2b!AOH(oR|Kgg<@~Hn8*I3a*{lB=J<_7Bj9oO1P|8;o= zNvyTLwv76J=ig#YRrS>Wi))BhQvdI`8vKo_#l`C5xzzs)S=rD+{lBu16r2b!AaaRrX|BkEaZ0Vr>UtD8OH}(IH!%iUT|HaWx zAL{?b(M}%f{~d>&I@JG*qn$X^|BIuYHq`$+4m)Y6{})F)WvKrbM>}Dt{})F)U8w(e z9Cor$|1XYqs!;zgj&`C@|3B!WE!6*uqn#ww|BIuYBGmso4m&}p{})F)J*fW|M>{#F z{})F)HK_j=M>{d7|92dAT2TKlj&@Q||1XYqN>KmrIP8R={$CvJbfEs(og-rI9kc4{$Cue)KmZO zIIP4||1XYK+Nu8+M=R;n|2qyV<<$R+qm^*#|HaWtH}(JGXeFEaf5%~^n)-inv=UAI zzc^ZHrv87>HTO{e?>MX!Q~xiHR)VSj7e_0-)c+4U`otVJ=xC*u`hWR1T8X9p-*H%J zrT$+Wt)x=_FOF79ssA5z(J1x*;%KFl`hRh>l1cr)I9jQs{$CueL{k6nIIJ{M|1XYK z5~=_He_RXo|KeyRkotddw9-fYzc^aSqyAqUt<+KfFOF8?sQ(v7D{a*Oi=&k^>i@;j zN*VS4j>AeA_5b2%rHlH1akP>}{l7R`siOX09IZrA|1XYKnyCL5M=MFx|BIuQBI^Ie z(Mk~Y|AVfrn)-joVI_z9e{r-@L;b%vT8W|lUmP7{r2bzVokyhpf6!G|QvWZG&J$Aq zFOJR&QvWZG&I3~aFD}|pLH)ltI?qS_zc@OtNB#eAj?d#!|1XZt+fn~7j?U9j|1XZt z%TfO?j?TkT|1XZtyHWq|IGksr{$CuOSEK%a(9tt|zZi6M-i-Qx`8PUGM*Y7yIxj~3 z|DdbRrvCpo7i%r=DWm>hTvBX|AXK-}$$e)|@Wt|Haic zR#N{jt|qsb`hRg%jjh!G54y@K>i@-6_B2udFRnPJiTZzW(O5n8|Kf@|8mRvlmzN)< z{$E^9O#$`)j%)62YNGyMTw6~w_5b3EE27l@iz_HP2KG+)c=d?sOzErUtDgq zhx&iVHCC0DQ~xinqCHOizqqoZ9_s(a<#jhv|L?eluJRV@|Haid~UmTsTqyFDe{poWi~4_Ybb5>We{pm=i~4_Yboz?=e{poWiu!+Xbb5;V|3ODjMSX41(dj4Z z|K;EEqP5iji=)#^)c+5<@@DG)9f#9L)c=d4(?!((54vap_5b4NbP)Cb;^_1b_5Z)Q zSZif@G4=n0|CZZ8{lB<>Jx$zsCH~K!CjMXc{6<>;Uo>RXkjS>kZFH~ytjH+3um7>| zrF0K@e%MX-i{BMGi|!2{8{A3vv0oLep?lVYfp_Wt^z#A>0|(Oc<({Ye&KvyG{KM#Z za2x4<{w2OibnpIF?=5tn{!H&kx+nip&kDN#KG$Q@z4mL|J#=6F7}r;H4}HI@itd;9 z+wV|^+-uLb$6Mc7&sr;K{d%f3RDGZ}sFXTcP0ZSr^>Ws#td^`9StEvgLcgl>|8&~e zMc7G=D(!FJ1#5}4&jD$jHg*wqQX>lr3)&JvQ(C8uU4)&~L=nXc-V#AmTBnU&gq`t1 z>>@;? zPZTfsOC%a;oi=t6cF;rsC~OFj2%6G5ZR{fKpos!d*f1awG^KUg*hSb;Uz-gI8ww;c zU7M}b#xBARnrI-3HylU=O=+Drb`f^aL$I_pu$?AaKw-m$M9`GhX=4{5CSpKgLxx16k=AKr z7hxMs)DXoRHY9?kv`!nl2-|2P2NX7RNCZu3oi=t6w$VfnC~WwU2%6G5ZR{d!qlqA* zcteOp(3I9`V;3PNia=q*h(w~1)@frGAtsWD;teGdK~q|%ja`KJq9=+c{3U{>v`!nl z2vL@U!t$I%(3I9`V;5m7mF=Lgd?yh!rFGiaMc7JZJt!>iNd!%4oi=t6wo=&-3d?^I zK~q|%ja`JT)D{rM%Yza@Q(C8uU4&>GKwo zM9`GhspXk_4qK@0A&QqjC4#23PMu@W)E0rl@~A}6l-8-U4Vu~}P*^^d2%6G5b(TR> zTLlWss}ey|TBpu5XllEN;^kL~pee0WJ()DxGEi8al}I$wI@N8^)V6`b@~uSBl-8*( zgQm8QC|=%`2%6G5)oIYw_7TO)zY;-HTBkZPX|#o)uskf0Xry(j-Jq#$B#M`hC4#23 zPPG{{wUtEi^0GwGl-8-%Od4$`QM~*tk!YlKs>PtGEd_<;X^EgIty9egO>HYtynHPY zG^KT_$)KsNC5o4~C4#23PBmuIXnR3n`CB5Yyck%B1RtSAvQrFE)0lg1(jC~RhwNHo$qRh3C&kpmPqJ4(dQrnF8~ z8Z<3}5XGAzC4#23PE{B*Es}u3W=V;lDXmlG22G17ps<-zB4|qMRGC53A`4Nx*-|2C zO6ydqLDM1(C~U@*2%6G5walPtkp>htYf1!7X`MPFlg1(rQM{Q`BGE|e)KY_{MINGf zv!_JRl-8-!4Vo5#Kw&eeM9`GhsnarPED{mLn?)rOjkHdkYS6TZL=m|H0?~)0tI7ysU>io*m;CeTUbOV@?^T zbvm<(h?li?;M?KTb5FeZGKrumt<#xRM7*r58=oj2|GK$vH;JGrt<#xRM7*rD5}#Hd z|Mj+2drAaNX`RljBI2d3<@gT#Xx6jaZkI?j(mI`4MZ`;+tC`-fZr3Exh@dI0)0tI7 zyfnKto2Y@#vOj$$5j3TBIu*xTz7NaG>p!kFJym zn$kL*Sw+N)<55&U11;}ef~t)pXiDpJW)(r{d~^;2&FP=g5}D4Y&LOjkh!@v2VuTMg zeq462M9`Gh>C7r3UR=|S6QKhQD}KNy3rEnD*6GYDB3@is+X*Uu+?=N*f~K@iXI2sM z;`|ssWe4gj*N>M7n$kL*Sw+O79oaZ}Hc;n3;U$SgBdyb!RYW}6Sd9v0pt^O(Oo^Z= zt<#xRL_Atm#lK0#F>l~gYXA{6rFA;9iik&ZD)=v7mbLyp(1@TZt<#xRL_C_EjnAEd zGu8zxiJ&R1)0tI7yr{d0>C;dCco=9zqLJ3=%qk*Y)XL}722PFLd>v>+(3IBc%qk*Y z)Yyr4@xUqD7X4EqXiDpJW)%@HD&rfW2Tr=~qEVm`K~q|%GpmSrQM7`8@5KlI_Io3O zrnF9HRuS={qBxJ(g*!bX@v{*@Q(C7ptB80}9`}p`^H0}a(1@TZt<#xRM7*%40Pp#M z6DKrdZh<4wNb7WF6%j9NFG3wQaKdv3rzC==v`%MM5%I#tW_$+@9Dm-Tq(sn^*6GYD zB3@Y6gX(8sPHq&RY#c#TTBkFsh9bFCK>TqXUSbDXr6)RYbg?E4K*LtkWLD zXDmmek=E(VDk5Ic(!wKl=Ffq*KqG>tv`%MM5%Gdp7iJ#^j{e6IRLdMeQ(C7ptB80( zO%&h812fiK^Q}bCl-B9YDk5G`(8#aJ^fil0KqG>tv`%MM5%K&ke*Ve85tnQagGMA8 zX`RljBI5Z~*{G}rrXGEGt3=S0*6GYDBA#E|$#lt$7yJSm5j3TBIh)oqLJ3=g&8$RJg=q@^A!V!HQ$0c5ssiKt5>ur>4Qi#(mH*jK}UI>e_-O$OOM9SMg&c1 zot|gVh5Rg@frGBt9tDjEn$kLbf zk!YlK`gntGkMsA=xV_eXjo$XhhJI*6CR$oy(uGBdaE_ z1C7XZE`7!xW6+fi{CP5BygdsvB4|qM^h}d3GYmSHZ;u)XZFgbrj3a1D>-15Xbaq!IzjDD*tuKH^BpPX*o^H^MdHlc9 z|84bf(1@TZtM2$Qbm z@jc|H{qF#c$aF1@@2Lh|AHyf|_FuoqT_F)PrFHsngRbT$Y;6Bo&%r7TN6?hk=@Nsk z;QMm6|J44$ZJ-fBQ(C8|m^9ZX+kZ&!+5#GpY1Ai^4LVwfakBlN2dF-Ypee1>#Ri>U zjZfn3-@bC^CW)Xat7q=!yD3%xYUh`a;IoP&(Maob zp+U!LQQ>X>dO;`Vi#UR&v`!ZobQM4OVf&Xi|M@l0h@dI0)Az!lJ`SrQ@nV;PM5k3bw zf~K@iXB%`*HQo)|Ki+eWmI#{CI(=9s-PPQPpZ#Rpf(SkbITDSuP9JK}mAQB~{PD7* z>~|%CrnF8UV$c=*yoEnrRP|^zXhhJI*6B$GUBGveZTaErANL@dBWOzNv^MEnywkSq zeAR__Ge@R#>76z)lg4&#P|N99w?v|m{@4Eh|E&H0|3|z3-}!I0|DVtQ_eP%!zSm(p zr+Ip#&&(fkhwYrL>y19u{L?1eIa}8o-SU?Sk6%}GitU`O z>y7?F9rLj5oUQAPZc0C0WIJc;dZQ106@Sil&erutH?C^QvYoSaz0viHrYyFdvvs}E z`#;%~ww<$ez0v!QdFejeIa}8oU0eO?iMDgLt~YwOb=fl8Ia}8oUGu|-58BSzy58vO zUEdyLJ7?>9qqle7{+#Wct?P~6`tU`ywsW?wH+svybqj6hY+Y~krWfo++c{g;8@=)5 z&wK2S-%j)NMz62Cd!y}~t?P|m`{kjB+RoX!-sm;QjlaWo&erutuiXAr*mlm=^+vB~ zZFJer*}C57<)OZO+c{g;8@(j@{a3bgwyrmN(S;|CwVktdz0u!|KCIn#&ert~|EOis zT6?zhyA1!!vK=e!W5sPLUNzaC<+$B1zQgmdeT?IVy?^Ik&)GA@{qeyuZ`ntS%g_D% zCwqqDcKbeZ<9hojakq7x^r1an+%2n~ZLyCOw`%#Wz3ge?Zrl_(&OSoib*nbNU{4jd zQoSFw4;OdMy7TY1OB@#tmxNxhr#LQj=UunlV^0=$;p=bp+r{F-v#G%R2YveeFEQ`JcP=vaNQmxLLdDNp_C7gTK1` z7&}|sh_;@c_F>|7TXOaH_MwjR-8|j}%va$qOgi zdphp>oy#BYv`2`0eZi2m_8yM==hu1rTx$;(_r<&OhuFJ|TibZb?)ETov4IL@@8-B~ zzvVwMLY6TG0Wz=wPo5s4kOjyfvH$@>XmakJoJ<%4hE8V4 zV3}+X0t5(=MHbPRC1gu#GG#uyW1jK8%?r^fHs``-K8zSn=M-c|Eh?=W+wd#~EH zcOT?TQMDkm*Wa9ks+qwR%bmEVzWC)w$G+^uJoVS7U%BNTC#q_6uZ5d95l?-7a)0+9 zov^B7o;hi@6Y|twK09aWdrnZ*?|N2V-~?3FzrXqo$FJ(hV`g0IxSslKX~$bx$MMvs z*KB)qyW{iJCkHpJeb|}osgHx7ezcRbiKjmLBER@7XOgP3danPw@1LHMmbmXbPf6?B z_YY4=Yuop&Dz>hDfA^HMrhOY!vE}Uh##7Q-_I<62tz+L;s@NL#eW{AAU*F$Uv9;^_ zLKR!LzQ3wsYu5L0hB^7MV8iY-mw$Ew)6^nIj? zElJ;ps@QV${Ye#Di@pz3v1RCcUlm(|zV}qI<>&jODz@}|@2X-m4^1ZH#Eh*n?s@QV!y{d|>CEqKm z*fR3{UKLwIzL!<8_2YX<6uEg9chRcyKVUQorBitl+Lo&mT+6!uPw4UmH!HnW|Xew5vMf{dw!0HdUt|bjKQ}Rn_PYn;z!0 zs5<$Md5<{Fs!lrYiWi+GRU^+VnC>*H8rpf*jZTBAfuH~K3#VRH--a*WcIs61wm!Y9 zQ>&_HFW=?P5>;LI-uq|gL{;hDhjw-rtLi*p)_%?js@nfN^$KT^sI15$P*H3=eIYw1o;-m+iqg5^X$IHu|qf{Mx?yhs41*(p^ zYst~hk*XG~*gWYRq3Vb^H?%m1t2%7=AGbJ%shV@@yQe#cs@mu2)mJ!&cxqZa^XtjZ z!JgXUu$u-_&U{tVuL_^w9JEnwY%uwrQpE<6@3*ShAo4w_iVYy&6ROzY@jb4J4IJNN zs@SOUJ*tWg7~dnR*kJLkQN;#|?_pJJkoX=_#RiD)K~G7e!}owHHZpwot73z~cb_UY zAbj_#Vxz&gS``}!zI#-$LEyVv6&nG*yHwHW`|eal1Mj;-6^**@c2zXuzS~sMVEb07 zqLKF9s)|P0x6)H$fPJ@kN{p`WW>qw>zMDKH2GzG>qZ&<~b}@RkWS| zy-f_p``_?3vH$x2|N8&QaXnMvo!IFdE@>Kq|KE6OrE{phu>}6#Q-giA1MvTjqv}fYU;Y+|5a5ad*J_7mA2Kx|EntLtAYRjm#TpO_tZca{y*s1y3T>tzDoFi z{aRyp7yQ4c`bWyE;Qv+ibvD8OtLmyw!T+mj>*#_1pHQt0@c*h>8yn&ORkhUC!vCwP z8fk_9S5?;83jgn^zQN{N_Z`;Qv)M50}CJt19bhf&ceZ@4#>={J*OH zbS3=1s=mrH_ zSJj!Sg8x@lQd0*1@2QUdo*MXnRefb;@c*hh@k}HqRI;H0{$IaVUEc`*KcOmn;Qv*X z)z!lPd#Zh~qyzq6RbOL2{J*Nsp%(amRUNfG@c*jXTRY(YCsbtv{J*NEmU8%iRW;3Z z@c*7_8?2~=|5w%D*9QNus;|Bb{$Eu`cQyRKsbt?uV3rysD}UdRLgLC5B$HXp{6SMe^srO)$sqG zY98qBhW}U9UDF2tuPWWr0spV6zB38`uPRwP1pn`;rh)EG_2~;kRjG;|_TiJmSJj(pfd5z3QP%_iuc|fG z3;(aGrmGVEUsbZM68>LRMXC(`UsZW+68_&)4I_BP^iQba!EX3}{aSCsApF0o+OjnK zzo+VlDhA>IRkbI};r~^&wN=Cat7+sxYer|L-ZzBEkQw!mJVezbecU!T+nm ztPuRaD$D}G|Et2R5B$F>%<{nhdy2C<@c*hXiv$0!3bQuw|Ee%c1OKlIvoi4ip5iPF z{J$#9y1@Ud!Ym8?zbeeC!2helEDHR;r#Nc@|E~(OB=G;LFe?K8uL`pu@c*9TtOxwR zD$H`g|Et2R2K>LLIEw-QuL`pk@c*hXO9B6{3bPXM|DNJ31pL1$%sRmTtHLY;{J$#9 zD!~7Hs<*v#5dL3P+h7~~|Agvqf&W+4g7=P=2~|^E)l>|@|EsFT`lWF~RW%I3 z|9fBS8Npw1{e&8BEQ9~ouMJnW!T(RFiaz*%Rdsj|IPqVqq!RvLzgC6!)D!-PDu@5q zuT>29!T+l&s~Ca*_f+>FRuIQdsQ$8k_<#LccWDd!zpAe87WjWv9o-%9|Eg+h+u;9I zRkSt0|EnrbrQ!com2{23|9h%ypt&0UUsVs*8i!7(meyYQfBjk|zL$elrTd#Y;s3p_ zrF-fI;Qu|v$rAW~RhS%s|DRB0fB1h@*x85wSB0H>_D)M)-eE{r5I8{YmhU?Z4S= zV*k14|1;JUVK-j1_I-6U$>ybIOhU12GS(DfH(u08vAL<4G|DDpO%ZnEMUNDlpPEUd zY%;X_QUInj%c6 z`FXFSvX!k_Xnfvl#+o8b!{Ujk3uUPZ4%@q6I*TqX3#o zqiiz8Q-qzJXc3U&sDNhDD4R_26k%s4S_q^#N}!oE$|h4hMc9eDeBT^3Ak9n~Ws@nM zBJAu$3j&mkB4{R!vdI)r5q7dg0ZK*{G=pZ@WQwNDn!chv% zLRaFixOj@NvjZ&_QXI9=Od4gADV`$iWDABAM=>;mX4zzlrwDQIvyuO%jB02mjk3uU zPZ4&uqlH6?qa2z^qiiz8Q-q!EXz`HZsE20KD4R_26k%sOT0o>Y3Zj`b$|h4hMTl}G z-=)GF711noCElfqrwBXS(Lw?xqa>P1qiiz8Q-q!EXfcuEsEKCMD4R_26k#V@P@rTK zMKfrYO{RE?u(J&Z5rhJ!mpNv}m*dNpTcNGij7fX6s^_EkaN-Dx?`S%O>*!i$)8P6i10PlSbKOwz6on z7_pHiqehxZqiizYFQ(ao1SO+LnnAN{GBYe1ElN-_s-&4T$|mzYi$)8R6i1mflSbKO zrdu>xoS~Q9aF|SvHwXEE+9* zP%_G=nKa5KGs&XS;s+(8ews<6Y|c8>qOk=)ilcyKl(xOH$*{OI^$@dM*?<9o-G_*}tV;xebQmc)*WEx;{?^I~&id&a6_C9$1j+sC$!O^;2DMPvT(q|k=Y7okr>AB5fsy%Bmj z^nB>4(4(OTLU)H&g;s=?g{}-O4P6jA8@C&t7CI?35b6rGg&IPOLkmMkgyx6#56uqk z9;yiK7TPg1GqhD`T4+ir9CC0A;@82?gC7Uq3%(V6Ex0cDZ1Bn8n&5rGJA*5OHw3Q< zULL$8cwVp&JTo{N9KmggsbEX6F1RRobnvj?fx)@Ky@SbMS#X!&tl&1m8Ntni@nA4G zIq+@Z%fM&2Rq@@x`oJrJwSlJtj|UzKtPb2BxH+&qaCP9)z(s*`0=d8$fl~rQfu2A| zpb57x9v4^;I3zGHFek8Qpej%j*cqRAuytU1U}_*5@CPR0lMlY|f9n6h|Bn9++|u~G z|0(~Y{s;Vb`&ao_;FA!p^e^>a;6K}+@t=lIL>TaQ`P=*r{>A=<_+*6n{{8*4{k!`s z{JY^35@!0h@=xgvUZhgGZz0+Ok-r!#2UhZDv zp63?aGu=^l#O-raZi`#zE^?1{4|5N6=em32cE~b!7k8GsjXT5L+>N_Ice3-X^QH5d z^P%&uvmPfb);do+k2?=JtDW1Oo1Nv()y}2PMb0@+4xhJhiZkT&I2}%tvjm^Ju)sOQ zndi)L_H?T7`3pNc+dEr3)19eK6uWPeq8p-LL_dvw5Pc{5M)c+A^U&WMkk0b9z-io{ySr>UW@?>O9@fO?;4eC-Fw&<;3%erxK4Q9!T7sSe00jSeCdlu{3c(;_O5waa!Ue+|t>VXiGFC z7AF=aj!4W;?4OvO*ga8^*e$VRVrF8i#I(eeL^$EZzl(nz{~Wh@z88Nh{#txp{Mq=E z@ip=L;&iQ;4cBe>8NQ_I2NsLO2NDNC1NeoI1Nc2l| zB{~v)5+_UCMB*ey=bsY4llTvb-%9+u#0?U^k@&U5uOxmc@oy5pkoZ@LpG*9U#Lp!D zS>mS>Kau#c#E&F?DDh7cKalvo#P=lrQR2H2$0fca@okB3Nqke{dWnCK_=d#SCB7!{ zRf(@i{Jq4NCB7taox~RSmr1-<;x!U~Bk^j9S4q55;uR7vmw1`POC|nV;!=sfl6Z;4 zizQwp@j{6gNIYNSc@oc+c#gy|iDygvrNn~7yu_Tuti+7Ovm~A=@fQ-$ka)Vp(XCh<^-he$kF;(Un*Njy;EPbJQic!0$HCGID2uEd{6oFj2xiL)i{BXMtudr90= z;vN!rmsle)DY05&mBdPk6%xxOmPss?SR(Pq5_glhtHfO-8i_kg+)3h&5`QFdmc$(- zZZB~=i8Cc`D{&i%Ka{w-l9O5*n=&XD*$iPI%+DRG*_EhKI(aWjciC2q>-dqLv! z5}%X!ti)#|J}vQg5}%UzTZvCfd_v;m5+9TJsKiGku95h##D^q4DDeS__e;D_;=K}A zOT0(o-4gGTc&EfWB;GFZHi@ew-YRjW#9JiZEb%6ZDfOyZ>ye=TvT#9v9gMB>E~FOqnn#0w;z&*&a5QJ#NSo_|-K ze^;J=SDt@Yo`0;1$jkHZ%Jc8a^Y6;@@5=L!l@l3x{#|+gU3vapdH!8_{;{?qBhSAp z&%Z0rzbntbE6+bxUu5L@cjfta<@tBz`FG{{$NG#+sYH4HU3vapdH!8_{;`51BhSAp z&%Z0rzbntbE6+dHcx2@Hcjfta<@tBz`FG{{$10GFJpZmd|E@g$t~~#)JpWiHl9A`% zmFM4;=iim*-<9VdD@ii){JZk}yPLA&Op%z77?&867?l{27?v247?c>0=$Gh9bR_yD zPL{Zd#7T_4e@gsL;y)yQEAj6VH%R>ze)T;;$J0xF7YoCKa==piJwaR zMB>L1Ka%*N#6L;=K;run-;?-9iSJ4rm-vpvwACH_I;8xmia_?pC5CB7o@ z_Yz;0_>#nR5?_?KcG9FxM%;7xf4k>M9Fusq#9vA*NX$#jNz6*jNIXm8nG$~?@eGNl zOFT{D&n1pZJXPW;5>J+RlEj}$9FaIIaY*8z!~u!@68j|fO6-x?EwM{tT4G9Kr^F74 z?GoE0wn}V~*etP0Vxz8mX`Pf!ws;pIRW@8-LTb`Uv;V9aG|MJi zyo-=38|dP`K=Pk8`#z$XG|DDhyo-=3>uca{YVzCk#m{Lbjk3uW?;@nidRn>bp4@QG zR`+Tqjk3uW?;@niTHE+2UP< zROxU(clDBAG;hbQykyWUn{4qeLaKC-H(ZP+KVSVB_b?@sM%iSGcM(#h?RD}K{49Oy zOw!DxQ8wA)U4&H0FmLxBO@8wB9d=w|3rHGij7f*4jlF>1{zraWwh%{-IAalSbKOtzCqX=6d;E zzS-Wnnlv+Mlug#!MHs0o<(_eJ{Smt+G?PZzWUXC%M3OIGcCT{L(kPp(wTm!ZUn9@p^Zp;4MVgs3$|h^=A`I8?cE-`<)4Mkxu9-B-CTr~?3|E%R z@A9dyR-H(inKa5KYwaTNun#F-`k|RL$|h^=BJeN}DP9Vq88pi#YwaTNun;L;8lo9A z%O-2>A`Id%5h-3OqM0TmFJ;jTnq`wY*`je+ixe+y(M%d;lR3$vahQt~FLlvO8fBCDnMLEU7b#x)qM02RAbdJW}8Nrw4QY`|9T{oM%iSGR}rcDLEg+cx@5=M&p)jh zG|MJiyoyLQ^bhm3?Zo_#H^)rY#tfQelPz9Fq-xt*_)dS~nJdraT1hf!mQA*J6_IM_ zZsRNXi8Y;@+2U0M%E@L@_pf_lo@Sww%_dvCibypy^3xed z7a#uRA^fkDOd4gAEnY>W8X9;<|LEfC_1E$*Q!;6kO}2Oyk!q;t{ko%zx0^J7m1fc? zn{4qaBGr(r;BWqf7sg|cX(o-b$ri67QVo@LToImd>5`v3p_w$wCR@CUNHvt#a7}%} z;JG*OJy0@flufpH6_KhRuHh^A3DaM0xnDDAmQA*J6_KhRYUMlT3Bi9J#8rf3(kPp3 z@hT!!-(SP`sYSotu<7TTNuzAC#jA)^eX53kJBv!sz33#(q)|56;#EYdzDZ_kkH2KI zExD4FOd4gAEnY>W>TBEh#2&xniTCcVnKa5KTfB-$)%BM1FYVZKVrLws88pi#TfB-$ z)wNgf8CWaOSv&)H73_;wzhE(kPp3@hT!!SJ%}@Dl)Py*9DSE zqinLptB6!xbr=6DkGbx$HzJxzqinLptB6!xc^BVHj+s06o#!-@M%iSGR}m;Dx$Zrt zW}llYGz*=C|1Vxeq-qCx_!@ikS&vsnHG^i^WQ$i3soFk%Cc@~^hc5~96+$v;lufpH z6_Kj#9jYRA=t(b4)=U~@lPz9Fq-s-XzK$IA=(O{>LXk`wWs@ylMWkx0oA{k9nDWSn zeASdp8fB9$UPYv8tGejD7HrbICD&n+NuzAC#jA)^ZCNY31xKEH&l`LKB$GzjWQ$i3 zshXY&z5^byc+pk|Xa>!)$ri67QZ>!|WTnx=%V*5~S~F>sO}2OyfpRyWlf!qrzj9c! z(A{`Wjx1Vpq-q*v9d_6sGO-UpOD2u7$zt2#`=P+3KyXqpH0k>+S5>kDe&|R0Wu|HN z$|ifbMVAcl)#uPd?k~AeGij7f_ON0)*`?0yzqTFLjc{hxdPAv!h5q)|56xfWeA)J^KyS-+P56*Fm+P4*|n zbk$HTUCI8nCsggH88pi#JIA62tNDEIzt73{^Yu_NX_QTNUyJT8<=SVzb7uY_p_w$w zCOg}r8{4_|nLB@^n$Ndn(kPqkJ~k~KtGNf>@cQYbnT1BjD!aEu*Yh(dM(1w6>mJ`~ zCXKSm?q$(6Z6%<7a>oJuoUx6WG|DEsr$txF>-SIg-R3<0b|jNV*<|-9rYi@ldZJq z#$Ntc&OY}Suf;TzM%iR5EV_D_zsr68wCnndHIqi!WXp@`igY!f)V;U5^)GydkPMn- zlP$C8_F=w4?Db+vIbYc%lSbKOOD(#si)*&M?z!R`{&pmjM%iRbEV{Xjzm>gO-YDTS zD48_MCi`QHu9aTpp6_3{j<4U6NuzACyIFLybcEE3+q&jxCXKSm?pjQj5A^XBVvkF1 zyse-aG|MKti$(W~8{Omd>jPhrW+siY$r_99ytea zhpgn&C7CqJCcBeGx5;_u-ItC|;@`Yv(kTD;{=fg;|Mx%c|J!)~|JV&r9`m*9-R3zu zw)`K-Nv__lJGSiZ_iuOgZr!nKXD|4>t9R>;{bug3R=aw)?$}j>Pvl&^TX*b=S598z z>fO3ym!GihVps3h9lLblH=nqAx9-@l7SDaq)w^}aE?)4rAG>)kp! zcJA>%%es2E?%3I7^U|)~tvi<6aLom--mN>9-8s_i>fO3yzqq6Ncdp*8J9hf#FYWE> z-MV8xpZkL+UAy8c0 z-Q-PI@75g~ID5f2uHLOX);Dxjv#WROj`du6<+rZhtvl9r@R9>vy<2xI9W42st9R>; zwSPJEgsXS!j;>yG_!<*F&J(Vxp!l~+dHomI^^=DdHpJE_|838&!hsA`KZ zuBmo^q-ygSi7nk(sy6-Wv!A#-sG4%XD}QjeR~5hb+l;%Ns_44tz3xm^;rsTfako_! z`cd_}?lzukZ~D=J|8Re(Dmwl1zq?y|s%^v5rylD5K-HBiF1pCwO4Vf#uUP1QU)8bS zyY4b~hN}5n@BOX&Jx{gXaMOlU-RY{zejfOvyQQaEK3ad{eeN_>H@$Yk+wK;s7Im-t zp}V=Ns(l7Na5wW*^EHFDo48Xw)wJTNhpu!t^;F}>&zH}4r>J_%*I(-kO)6Q|@ zs-Ae|dv~}oRY#4kU*kqS)$q;wv(~r~RnPpo>RdOh>hxLV$G9O?CC^PQaf7OMoBrL0 zZopIZ8;*K;j_X(T*m>`7;kv3e-TLMWT}M?ozc1$eJXN=0se86NSylCSYhQIYQT4rP zPhIRz@>J~yFRonU{8QCkuWos|^PMWTU7dfZVq4Yu)>G0pb^fl3ZBb`~Dz-hHZ&b0Z z>3r=eXM zRk1DSeCjD_yE&hzVq4AmSQXo5&PS@)7IQvS#kQC8Cr?RR%lSYR+g8r|o|1Ny^PVcU zot!^@!yPlG^ku$D}Z6W6!Rc!k>Z+lAGI?h|F*tT)rRK>Q8v))tEc5(ioift9= z4OMKLIInw3+9A$so|1Nl^QtPgHJn#GCG865_nwlrg!8her0w9mq>60?XPu{{UEsXv zDQOEhYgN(qJ1=-jY`ycmr^L29 s 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

3aQ!S@Ag3RV_;g1P$gf;S3YDR`ma>4JrruisN} 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 diff --git a/apps/api/src/routers/api_keys.py b/apps/api/src/routers/api_keys.py index 333b93ea..6b4bc24b 100644 --- a/apps/api/src/routers/api_keys.py +++ b/apps/api/src/routers/api_keys.py @@ -11,7 +11,7 @@ APIKeyGetRequest, ) -router = APIRouter(prefix="/api_keys", tags=["api keys"]) +router = APIRouter(prefix="/api-keys", tags=["api keys"]) @router.get("/") From 205c0165cf9907cc4f460b75cbd5fca7da8262d2 Mon Sep 17 00:00:00 2001 From: Daniel Aanensen <60237496+LVGrinder@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:22:22 +0200 Subject: [PATCH 14/76] Add billing endpoints (#198) * Add billing endpoints * Gitignore cache and change api keys path to kebabcase (#199) * comment fixes * change get request for billing info to use path param --------- Co-authored-by: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Co-authored-by: Leon Lam Nilsson --- apps/api/src/__init__.py | 2 + apps/api/src/interfaces/db.py | 62 +++++++++++++++++++++ apps/api/src/models/__init__.py | 8 +++ apps/api/src/models/billing_information.py | 23 ++++++++ apps/api/src/routers/billing_information.py | 60 ++++++++++++++++++++ 5 files changed, 155 insertions(+) create mode 100644 apps/api/src/models/billing_information.py create mode 100644 apps/api/src/routers/billing_information.py diff --git a/apps/api/src/__init__.py b/apps/api/src/__init__.py index 8b2d630b..234ba7a5 100644 --- a/apps/api/src/__init__.py +++ b/apps/api/src/__init__.py @@ -31,6 +31,7 @@ api_keys, tools, subscriptions, + billing_information, ) logger = logging.getLogger("root") @@ -48,6 +49,7 @@ app.include_router(rest.router) app.include_router(tools.router) app.include_router(subscriptions.router) +app.include_router(billing_information.router) app.add_middleware( CORSMiddleware, diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index d0e90a0d..44a28b82 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -37,6 +37,9 @@ SubscriptionInsertRequest, SubscriptionUpdateRequest, SubscriptionGetRequest, + Billing, + BillingInsertRequest, + BillingUpdateRequest, ) load_dotenv() @@ -270,6 +273,65 @@ def update_subscription( return Subscription(**response.data[0]) +def get_billing( + profile_id: UUID, +) -> Billing | None: + """Gets billings, filtered by what parameters are given""" + supabase: Client = create_client(url, key) + logger.debug(f"Getting billings") + response = ( + supabase.table("billing_information") + .select("*") + .eq("profile_id", profile_id) + .execute() + ) + if len(response.data) == 0: + return None + + return Billing(**response.data[0]) + + +def insert_billing(billing: BillingInsertRequest) -> Billing: + """Posts a billing to the db""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("billing_information") + .insert(json.loads(billing.model_dump_json(exclude_none=True))) + .execute() + ) + return Billing(**response.data[0]) + + +def delete_billing(profile_id: UUID) -> Billing | None: + """Deletes a billing by an id (the primary key)""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("billing_information") + .delete() + .eq("profile_id", profile_id) + .execute() + ) + if len(response.data) == 0: + return None + + return Billing(**response.data[0]) + + +def update_billing(profile_id: UUID, content: BillingUpdateRequest) -> Billing | None: + """Updates a billing by an id""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("billing_information") + .update(json.loads(content.model_dump_json(exclude_none=True))) + .eq("profile_id", profile_id) + .execute() + ) + if len(response.data) == 0: + return None + + return Billing(**response.data[0]) + + def get_descriptions(agent_ids: list[UUID]) -> dict[UUID, list[str]] | None: """Get the description list for the given agent.""" supabase: Client = create_client(url, key) diff --git a/apps/api/src/models/__init__.py b/apps/api/src/models/__init__.py index d429627f..c5c2c71f 100644 --- a/apps/api/src/models/__init__.py +++ b/apps/api/src/models/__init__.py @@ -26,6 +26,11 @@ SubscriptionUpdateRequest, SubscriptionGetRequest, ) +from .billing_information import ( + Billing, + BillingInsertRequest, + BillingUpdateRequest, +) from .profile import ( ProfileInsertRequest, Profile, @@ -88,4 +93,7 @@ "SubscriptionInsertRequest", "SubscriptionUpdateRequest", "SubscriptionGetRequest", + "Billing", + "BillingInsertRequest", + "BillingUpdateRequest", ] diff --git a/apps/api/src/models/billing_information.py b/apps/api/src/models/billing_information.py new file mode 100644 index 00000000..e9590672 --- /dev/null +++ b/apps/api/src/models/billing_information.py @@ -0,0 +1,23 @@ +from datetime import UTC, datetime +from uuid import UUID, uuid4 + +from pydantic import BaseModel, Field + + +class Billing(BaseModel): + profile_id: UUID + stripe_payment_method: str | None = None + description: str | None = None + created_at: datetime + + +class BillingInsertRequest(BaseModel): + profile_id: UUID + stripe_payment_method: str | None = None + description: str | None = None + + +class BillingUpdateRequest(BaseModel): + stripe_payment_method: str | None = None + description: str | None = None + diff --git a/apps/api/src/routers/billing_information.py b/apps/api/src/routers/billing_information.py new file mode 100644 index 00000000..81b47173 --- /dev/null +++ b/apps/api/src/routers/billing_information.py @@ -0,0 +1,60 @@ +import logging +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException + +from src.dependencies import ( + RateLimitResponse, + rate_limit, + rate_limit_profile, + rate_limit_tiered, +) +from src.interfaces import db +from src.models import ( + Billing, + BillingInsertRequest, + BillingUpdateRequest, +) + +router = APIRouter(prefix="/billing", tags=["billings"]) + +logger = logging.getLogger("root") + + +@router.get("/{id}") +def get_billings(id: UUID) -> Billing: + response = db.get_billing(id) + if not response: + raise HTTPException(404, "billing information not found") + + return response + + +@router.post("/") +def insert_billing(subscription: BillingInsertRequest) -> Billing: + return db.insert_billing(subscription) + + +@router.delete("/{profile_id}") +def delete_billing(profile_id: UUID) -> Billing: + response = db.delete_billing(profile_id) + if not response: + raise HTTPException(404, "stripe subscription id not found") + + return response + + +@router.patch("/{profile_id}") +def update_billing(profile_id: UUID, content: BillingUpdateRequest) -> Billing: + response = db.update_billing(profile_id, content) + if not response: + raise HTTPException(404, "message not found") + + return response + + +# +# +# @router.get("/{message_id}") +# def get_message(message_id: UUID) -> Message: +# return db.get_message(message_id) From 08026cea4f91be9e7839e3b15314e09bd9800a02 Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:23:04 +0200 Subject: [PATCH 15/76] Fix error output on inputting session (#202) --- apps/api/src/routers/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/api/src/routers/sessions.py b/apps/api/src/routers/sessions.py index 3e309f3f..9a075cdc 100644 --- a/apps/api/src/routers/sessions.py +++ b/apps/api/src/routers/sessions.py @@ -157,7 +157,7 @@ async def on_reply( crew = AutogenCrew(session.profile_id, session, crew_model, on_reply) except ValueError as e: logger.error(e) - raise HTTPException(400, "crew model bad input") + raise HTTPException(400, f"crew model bad input: {e}") background_tasks.add_task(crew.run, message, messages=cached_messages) From 787ecd69753e41d1a21d84dc333c64c26cbfc0fc Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:58:58 +0200 Subject: [PATCH 16/76] Fix error handling on sessions (#203) * fix error output on inputting session * fix more error handling in running crew * delete session if crew run errors so we don't create sessions with no messages --- apps/api/src/crew.py | 16 ---------------- apps/api/src/parser.py | 10 ++++++++++ apps/api/src/routers/sessions.py | 4 +++- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/apps/api/src/crew.py b/apps/api/src/crew.py index 27ff23de..1c5935e0 100644 --- a/apps/api/src/crew.py +++ b/apps/api/src/crew.py @@ -32,8 +32,6 @@ def __init__( self.profile_id = profile_id self.session = session self.on_reply = on_message - if not self._validate_crew_model(crew_model): - raise ValueError("composition is invalid") self.crew_model = crew_model self.valid_tools = [] @@ -137,20 +135,6 @@ async def _on_reply( await self.on_reply(recipient_id, sender_id, content, role) return False, None - def _validate_crew_model(self, crew_model: CrewProcessed) -> bool: - if len(crew_model.agents) == 0: - return False - - # Validate agents - for agent in crew_model.agents: - if agent.role == "": - return False - if agent.title == "": - return False - if agent.system_message == "": - return False - return True - def _extract_uuid(self, dictionary: dict[UUID, list[str]]) -> dict[UUID, list[str]]: new_dict = {} for key, value in dictionary.items(): diff --git a/apps/api/src/parser.py b/apps/api/src/parser.py index 70bb2c39..f75b4390 100644 --- a/apps/api/src/parser.py +++ b/apps/api/src/parser.py @@ -60,6 +60,16 @@ def process_crew(crew: Crew) -> tuple[str, CrewProcessed]: ) if not crew.prompt: raise HTTPException(400, "got no prompt") + if len(crew_model.agents) == 0: + raise ValueError("crew had no agents") + # Validate agents + for agent in crew_model.agents: + if agent.role == "": + raise ValueError(f"agent {agent.id} had no role") + if agent.title == "": + raise ValueError(f"agent {agent.id} had no title") + if agent.system_message == "": + raise ValueError(f"agent {agent.id} had no system message") message: str = crew.prompt["content"] return message, crew_model diff --git a/apps/api/src/routers/sessions.py b/apps/api/src/routers/sessions.py index 9a075cdc..bb161b88 100644 --- a/apps/api/src/routers/sessions.py +++ b/apps/api/src/routers/sessions.py @@ -95,6 +95,8 @@ async def run_crew( if mock: message, crew_model = process_crew(Crew(**mocks.crew_model)) + request.crew_id = UUID("1c11a9bf-748f-482b-9746-6196f136401a") + request.profile_id = UUID("070c1d2e-9d72-4854-a55e-52ade5a42071") else: message, crew_model = get_processed_crew_by_id(request.crew_id) @@ -120,7 +122,6 @@ async def run_crew( status_code=400, detail=f"Session with id {request.session_id} found, but has no messages", ) - if session is None: session = Session( id=uuid4(), @@ -156,6 +157,7 @@ async def on_reply( try: crew = AutogenCrew(session.profile_id, session, crew_model, on_reply) except ValueError as e: + db.delete_session(session.id) logger.error(e) raise HTTPException(400, f"crew model bad input: {e}") From 40f94de58466e468f8698634e4c9f9f73d177071 Mon Sep 17 00:00:00 2001 From: Daniel Aanensen <60237496+LVGrinder@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:44:56 +0200 Subject: [PATCH 17/76] Add tiers endpoints (#200) * add tiers endpoint * fixing up tier endpoints * tiers changes * tier change testing * changes tier endpoint and def * def get_tier change * fixed response --------- Signed-off-by: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Co-authored-by: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> --- apps/api/src/__init__.py | 2 ++ apps/api/src/interfaces/db.py | 56 +++++++++++++++++++++++++++++++-- apps/api/src/models/__init__.py | 10 ++++++ apps/api/src/models/tiers.py | 42 +++++++++++++++++++++++++ apps/api/src/routers/tiers.py | 54 +++++++++++++++++++++++++++++++ 5 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 apps/api/src/models/tiers.py create mode 100644 apps/api/src/routers/tiers.py diff --git a/apps/api/src/__init__.py b/apps/api/src/__init__.py index 234ba7a5..0c601b7b 100644 --- a/apps/api/src/__init__.py +++ b/apps/api/src/__init__.py @@ -31,6 +31,7 @@ api_keys, tools, subscriptions, + tiers, billing_information, ) @@ -49,6 +50,7 @@ app.include_router(rest.router) app.include_router(tools.router) app.include_router(subscriptions.router) +app.include_router(tiers.router) app.include_router(billing_information.router) app.add_middleware( diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index 44a28b82..32586dad 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -37,10 +37,15 @@ SubscriptionInsertRequest, SubscriptionUpdateRequest, SubscriptionGetRequest, + Tier, + TierInsertRequest, + TierUpdateRequest, Billing, BillingInsertRequest, BillingUpdateRequest, + ) +from src.models.tiers import TierGetRequest load_dotenv() url: str | None = os.environ.get("SUPABASE_URL") @@ -217,7 +222,7 @@ def get_subscriptions( profile_id: UUID | None = None, stripe_subscription_id: str | None = None, ) -> list[Subscription]: - """Gets messages, filtered by what parameters are given""" + """Gets subscriptions, filtered by what parameters are given""" supabase: Client = create_client(url, key) logger.debug(f"Getting subscriptions") query = supabase.table("subscriptions").select("*") @@ -234,7 +239,7 @@ def get_subscriptions( def insert_subscription(subscription: SubscriptionInsertRequest) -> Subscription: - """Posts a Subscription to the db""" + """Posts a subscription to the db""" supabase: Client = create_client(url, key) response = ( supabase.table("subscriptions") @@ -273,6 +278,48 @@ def update_subscription( return Subscription(**response.data[0]) + +def get_tier(id: UUID) -> Tier | None: + """Gets tiers, filtered by what parameters are given""" + supabase: Client = create_client(url, key) + response = supabase.table("tiers").select("*").eq("id", id).execute() + if len(response.data) == 0: + return None + + return Tier(**response.data[0]) + + +def insert_tier(tier: TierInsertRequest) -> Tier: + """Posts a tier to the db""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("tiers") + .insert(json.loads(tier.model_dump_json(exclude_none=True))) + .execute() + ) + return Tier(**response.data[0]) + + +def delete_tier(id: UUID) -> Tier | None: + """Deletes a tier by an id (the primary key)""" + supabase: Client = create_client(url, key) + response = supabase.table("tiers").delete().eq("id", id).execute() + if len(response.data) == 0: + return None + + return Tier(**response.data[0]) + + +def update_tier(id: UUID, content: TierUpdateRequest) -> Tier | None: + """Updates a tier by an id""" + supabase: Client = create_client(url, key) + response = ( + supabase.table("tiers") + .update(json.loads(content.model_dump_json(exclude_none=True))) + .eq("id", id) + .execute() + + return Tier(**response.data[0]) def get_billing( profile_id: UUID, ) -> Billing | None: @@ -299,6 +346,7 @@ def insert_billing(billing: BillingInsertRequest) -> Billing: .insert(json.loads(billing.model_dump_json(exclude_none=True))) .execute() ) + return Billing(**response.data[0]) @@ -324,14 +372,16 @@ def update_billing(profile_id: UUID, content: BillingUpdateRequest) -> Billing | supabase.table("billing_information") .update(json.loads(content.model_dump_json(exclude_none=True))) .eq("profile_id", profile_id) + .execute() ) if len(response.data) == 0: return None - + return Billing(**response.data[0]) + def get_descriptions(agent_ids: list[UUID]) -> dict[UUID, list[str]] | None: """Get the description list for the given agent.""" supabase: Client = create_client(url, key) diff --git a/apps/api/src/models/__init__.py b/apps/api/src/models/__init__.py index c5c2c71f..b49538d1 100644 --- a/apps/api/src/models/__init__.py +++ b/apps/api/src/models/__init__.py @@ -26,6 +26,12 @@ SubscriptionUpdateRequest, SubscriptionGetRequest, ) +from .tiers import ( + Tier, + TierInsertRequest, + TierUpdateRequest, + TierGetRequest, +) from .billing_information import ( Billing, BillingInsertRequest, @@ -93,6 +99,10 @@ "SubscriptionInsertRequest", "SubscriptionUpdateRequest", "SubscriptionGetRequest", + "Tier", + "TierInsertRequest", + "TierUpdateRequest", + "TierGetRequest", "Billing", "BillingInsertRequest", "BillingUpdateRequest", diff --git a/apps/api/src/models/tiers.py b/apps/api/src/models/tiers.py new file mode 100644 index 00000000..12df0ae1 --- /dev/null +++ b/apps/api/src/models/tiers.py @@ -0,0 +1,42 @@ +from datetime import UTC, datetime +from uuid import UUID, uuid4 + +from pydantic import BaseModel, Field + + +class Tier(BaseModel): + id: UUID + created_at: datetime + period: int + limit: int + stripe_price_id: str | None = None + name: str | None = None + description: str | None = None + slug: str | None = None + image: str | None = None + + +class TierInsertRequest(BaseModel): + period: int | None = None + limit: int | None = None + stripe_price_id: str | None = None + name: str | None = None + description: str | None = None + slug: str | None = None + image: str | None = None + + +class TierUpdateRequest(BaseModel): + period: int | None = None + limit: int | None = None + stripe_price_id: str | None = None + name: str | None = None + description: str | None = None + slug: str | None = None + image: str | None = None + + +class TierGetRequest(BaseModel): + id: UUID + stripe_price_id: str | None = None + name: str | None = None diff --git a/apps/api/src/routers/tiers.py b/apps/api/src/routers/tiers.py new file mode 100644 index 00000000..3eb0ff83 --- /dev/null +++ b/apps/api/src/routers/tiers.py @@ -0,0 +1,54 @@ +import logging +from uuid import UUID + +from fastapi import APIRouter, Depends, HTTPException + +from src.dependencies import ( + RateLimitResponse, + rate_limit, + rate_limit_profile, + rate_limit_tiered, +) +from src.interfaces import db +from src.models import ( + Tier, + TierInsertRequest, + TierUpdateRequest, + TierGetRequest, +) + +router = APIRouter(prefix="/tiers", tags=["tiers"]) + +logger = logging.getLogger("root") + + +@router.get("/{id}") +def get_tier(id: UUID) -> Tier: + response = db.get_tier(id) + if not response: + raise HTTPException(404, "tiers information not found") + + return response + + +@router.post("/") +def insert_tier(tier: TierInsertRequest) -> Tier: + return db.insert_tier(tier) + + +@router.delete("/{id}") +def delete_tier(id: UUID) -> Tier: + response = db.delete_tier(id) + if not response: + raise HTTPException(404, "stripe tier id not found") + + return response + + +@router.patch("/{id}") +def update_tier(id: UUID, content: TierUpdateRequest) -> Tier: + response = db.update_tier(id, content) + if not response: + raise HTTPException(404, "message not found") + + return response From b3f993fc2897120e92889babfe0e057383c5bb7b Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:49:29 +0200 Subject: [PATCH 18/76] Add one parenthesis (plus some empty lines) (#204) --- apps/api/src/interfaces/db.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index 32586dad..173315e1 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -318,8 +318,10 @@ def update_tier(id: UUID, content: TierUpdateRequest) -> Tier | None: .update(json.loads(content.model_dump_json(exclude_none=True))) .eq("id", id) .execute() + ) + return Tier(**response.data[0]) + - return Tier(**response.data[0]) def get_billing( profile_id: UUID, ) -> Billing | None: From 51c83b439afec8b18326862eddda98403898b5c9 Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 17:01:18 +0200 Subject: [PATCH 19/76] Fix code smell complaints (#205) --- apps/api/src/interfaces/db.py | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index 173315e1..e882164b 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -143,7 +143,7 @@ def get_messages( ) -> list[Message]: """Gets messages, filtered by what parameters are given""" supabase: Client = create_client(url, key) - logger.debug(f"Getting messages") + logger.debug("Getting messages") query = supabase.table("messages").select("*") if session_id: @@ -224,7 +224,7 @@ def get_subscriptions( ) -> list[Subscription]: """Gets subscriptions, filtered by what parameters are given""" supabase: Client = create_client(url, key) - logger.debug(f"Getting subscriptions") + logger.debug("Getting subscriptions") query = supabase.table("subscriptions").select("*") if profile_id: @@ -327,7 +327,7 @@ def get_billing( ) -> Billing | None: """Gets billings, filtered by what parameters are given""" supabase: Client = create_client(url, key) - logger.debug(f"Getting billings") + logger.debug("Getting billings") response = ( supabase.table("billing_information") .select("*") @@ -457,7 +457,7 @@ def get_crews( ) -> list[Crew]: """Gets crews, filtered by what parameters are given""" supabase: Client = create_client(url, key) - logger.debug(f"Getting crews") + logger.debug("Getting crews") query = supabase.table("crews").select("*") if profile_id: @@ -781,24 +781,4 @@ def delete_profile(profile_id: UUID) -> Profile: if __name__ == "__main__": from src.models import Session - # print( - # insert_session( - # SessionRequest( - # crew_id=UUID("1c11a9bf-748f-482b-9746-6196f136401a"), - # profile_id=UUID("070c1d2e-9d72-4854-a55e-52ade5a42071"), - # title="hello", - # ) - # ) - # ) - # - # print(get_crew(UUID("bf9f1cdc-fb63-45e1-b1ff-9a1989373ce3"))) - ##print(insert_message(MessageRequestModel( - # session_id=UUID("ec4a9ae1-f4de-46cf-946d-956b3081c432"), - # profile_id=UUID("070c1d2e-9d72-4854-a55e-52ade5a42071"), - # content="hello test message", - # recipient_id=UUID("7c707c30-2cfe-46a0-afa7-8bcc38f9687e"), - # ))) - - # print(update_message(UUID("c3e4755b-141d-4f77-8ea8-924961ccf36d"), content=MessageUpdateRequest(content="wowzer"))) - # print(get_api_keys(api_key_type_id=UUID("3b64fe26-20b9-4064-907e-f2708b5f1656"))) print(get_api_key_type_ids(["612ddae6-ecdd-4900-9314-1a2c9de6003d"])) From 4d02cbd55e5ae9c9a2b635161680dd9e8e165ecf Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 17:19:33 +0200 Subject: [PATCH 20/76] Add tool endpoints (#201) * add tools (untested) * change api key types endpoint name to kebab case * add error handling on delete tool --------- Signed-off-by: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> --- apps/api/src/__init__.py | 2 +- apps/api/src/interfaces/db.py | 147 +++++++++++++++++--------- apps/api/src/models/__init__.py | 10 ++ apps/api/src/models/subscription.py | 1 - apps/api/src/models/tool.py | 29 +++++ apps/api/src/routers/api_key_types.py | 2 +- apps/api/src/routers/subscriptions.py | 2 +- apps/api/src/routers/tools.py | 44 +++++++- 8 files changed, 179 insertions(+), 58 deletions(-) create mode 100644 apps/api/src/models/tool.py diff --git a/apps/api/src/__init__.py b/apps/api/src/__init__.py index 0c601b7b..c27f4b7f 100644 --- a/apps/api/src/__init__.py +++ b/apps/api/src/__init__.py @@ -47,9 +47,9 @@ app.include_router(api_keys.router) app.include_router(auth_router.router) app.include_router(api_key_types.router) -app.include_router(rest.router) app.include_router(tools.router) app.include_router(subscriptions.router) +app.include_router(rest.router) app.include_router(tiers.router) app.include_router(billing_information.router) diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index e882164b..757281bb 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -36,6 +36,9 @@ Subscription, SubscriptionInsertRequest, SubscriptionUpdateRequest, + Tool, + ToolInsertRequest, + ToolUpdateRequest, SubscriptionGetRequest, Tier, TierInsertRequest, @@ -43,7 +46,6 @@ Billing, BillingInsertRequest, BillingUpdateRequest, - ) from src.models.tiers import TierGetRequest @@ -483,39 +485,6 @@ def delete_crew(crew_id: UUID) -> Crew: return Crew(**response.data[0]) -def get_api_key(api_key_id: UUID) -> APIKey: - supabase: Client = create_client(url, key) - response = ( - supabase.table("users_api_keys") - .select("*, api_key_types(*)") - .eq("id", api_key_id) - .single() - .execute() - ) - - api_key_type = APIKeyType(**response.data["api_key_types"]) - return APIKey(**response.data, api_key_type=api_key_type) - - -def get_tool_api_keys( - profile_id: UUID, api_key_type_ids: list[str] | None = None -) -> dict[str, str]: - """Gets all api keys for a profile id, if api_key_type_ids is given, only give api keys corresponding to those key types.""" - supabase: Client = create_client(url, key) - # casted_ids = [str(api_key_type_id) for api_key_type_id in api_key_type_ids] - query = ( - supabase.table("users_api_keys") - .select("api_key", "api_key_type_id") - .eq("profile_id", profile_id) - ) - - if api_key_type_ids: - query = query.in_("api_key_type_id", api_key_type_ids) - - response = query.execute() - return {data["api_key_type_id"]: data["api_key"] for data in response.data} - - def get_api_key(api_key_id: UUID) -> APIKey | None: supabase: Client = create_client(url, key) response = ( @@ -627,6 +596,15 @@ def update_status(session_id: UUID, status: SessionStatus) -> None: supabase.table("sessions").update({"status": status}).eq("id", session_id).execute() +def get_agent(agent_id: UUID) -> Agent | None: + supabase: Client = create_client(url, key) + response = supabase.table("agents").select("*").eq("id", agent_id).execute() + if not response.data: + return None + + return Agent(**response.data[0]) + + def get_agents( profile_id: UUID | None = None, crew_id: UUID | None = None, @@ -658,15 +636,6 @@ def get_agents( return [Agent(**data) for data in response.data] -def get_agent(agent_id: UUID) -> Agent | None: - supabase: Client = create_client(url, key) - response = supabase.table("agents").select("*").eq("id", agent_id).execute() - if not response.data: - return None - - return Agent(**response.data[0]) - - def get_agents_from_crew(crew_id: UUID) -> list[Agent] | None: supabase: Client = create_client(url, key) nodes = supabase.table("crews").select("nodes").eq("id", crew_id).execute() @@ -704,6 +673,63 @@ def delete_agent(agent_id: UUID) -> Agent: return Agent(**response.data[0]) +def get_tool(tool_id: UUID) -> Tool | None: + supabase: Client = create_client(url, key) + response = supabase.table("tools").select("*").eq("id", tool_id).execute() + if len(response.data) == 0: + return None + + return Tool(**response.data[0]) + + +def get_tools( + name: str | None = None, + api_key_type_id: UUID | None = None, +) -> list[Tool]: + supabase: Client = create_client(url, key) + query = supabase.table("tools").select("*") + + if name: + query = query.eq("name", name) + + if api_key_type_id: + query = query.eq("api_key_type_id", api_key_type_id) + + response = query.execute() + + return [Tool(**data) for data in response.data] + + +def update_tool(tool_id: UUID, content: ToolUpdateRequest) -> Tool: + supabase: Client = create_client(url, key) + response = ( + supabase.table("tools") + .update(json.loads(content.model_dump_json(exclude_none=True))) + .eq("id", tool_id) + .execute() + ) + return Tool(**response.data[0]) + + +def insert_tool(tool: ToolInsertRequest) -> Tool: + supabase: Client = create_client(url, key) + response = ( + supabase.table("tools") + .insert(json.loads(tool.model_dump_json(exclude_none=True))) + .execute() + ) + return Tool(**response.data[0]) + + +def delete_tool(tool_id: UUID) -> Tool | None: + supabase: Client = create_client(url, key) + response = supabase.table("tools").delete().eq("id", tool_id).execute() + if len(response.data) == 0: + return None + + return Tool(**response.data[0]) + + def update_agent_tool(agent_id: UUID, tool_id: UUID) -> Agent: supabase: Client = create_client(url, key) agent_tools = supabase.table("agents").select("tools").eq("id", agent_id).execute() @@ -720,6 +746,33 @@ def update_agent_tool(agent_id: UUID, tool_id: UUID) -> Agent: return Agent(**response.data[0]) +def get_tool_api_keys( + profile_id: UUID, api_key_type_ids: list[str] | None = None +) -> dict[str, str]: + """Gets all api keys for a profile id, if api_key_type_ids is given, only give api keys corresponding to those key types.""" + supabase: Client = create_client(url, key) + # casted_ids = [str(api_key_type_id) for api_key_type_id in api_key_type_ids] + query = ( + supabase.table("users_api_keys") + .select("api_key", "api_key_type_id") + .eq("profile_id", profile_id) + ) + + if api_key_type_ids: + query = query.in_("api_key_type_id", api_key_type_ids) + + response = query.execute() + return {data["api_key_type_id"]: data["api_key"] for data in response.data} + + +def get_profile(profile_id: UUID) -> Profile | None: + supabase: Client = create_client(url, key) + response = supabase.table("profiles").select("*").eq("id", profile_id).execute() + if len(response.data) == 0: + return None + return Profile(**response.data[0]) + + def get_profiles( tier_id: UUID | None = None, display_name: str | None = None, @@ -743,14 +796,6 @@ def get_profiles( return [Profile(**data) for data in response.data] -def get_profile(profile_id: UUID) -> Profile | None: - supabase: Client = create_client(url, key) - response = supabase.table("profiles").select("*").eq("id", profile_id).execute() - if len(response.data) == 0: - return None - return Profile(**response.data[0]) - - def update_profile(profile_id: UUID, content: ProfileUpdateRequest) -> Profile: supabase: Client = create_client(url, key) response = ( diff --git a/apps/api/src/models/__init__.py b/apps/api/src/models/__init__.py index b49538d1..86012ec4 100644 --- a/apps/api/src/models/__init__.py +++ b/apps/api/src/models/__init__.py @@ -59,6 +59,12 @@ APIKeyUpdateRequest, APIKeyGetRequest, ) +from .tool import ( + Tool, + ToolInsertRequest, + ToolUpdateRequest, + ToolGetRequest, +) from .user import User __all__ = [ @@ -99,6 +105,10 @@ "SubscriptionInsertRequest", "SubscriptionUpdateRequest", "SubscriptionGetRequest", + "Tool", + "ToolInsertRequest", + "ToolUpdateRequest", + "ToolGetRequest", "Tier", "TierInsertRequest", "TierUpdateRequest", diff --git a/apps/api/src/models/subscription.py b/apps/api/src/models/subscription.py index 53451ece..3bbbd736 100644 --- a/apps/api/src/models/subscription.py +++ b/apps/api/src/models/subscription.py @@ -22,4 +22,3 @@ class SubscriptionUpdateRequest(BaseModel): class SubscriptionGetRequest(BaseModel): profile_id: UUID | None = None stripe_subscription_id: str | None = None - created_at: datetime diff --git a/apps/api/src/models/tool.py b/apps/api/src/models/tool.py new file mode 100644 index 00000000..45106133 --- /dev/null +++ b/apps/api/src/models/tool.py @@ -0,0 +1,29 @@ +from datetime import UTC, datetime +from uuid import UUID, uuid4 + +from pydantic import BaseModel, Field + + +class Tool(BaseModel): + id: UUID + created_at: datetime + name: str + description: str + api_key_type_id: UUID | None = None + + +class ToolInsertRequest(BaseModel): + name: str + description: str + api_key_type_id: UUID | None = None + + +class ToolUpdateRequest(BaseModel): + name: str | None = None + description: str | None = None + api_key_type_id: UUID | None = None + + +class ToolGetRequest(BaseModel): + name: str | None = None + api_key_type_id: UUID | None = None \ No newline at end of file diff --git a/apps/api/src/routers/api_key_types.py b/apps/api/src/routers/api_key_types.py index 741bf75f..6b31ecb4 100644 --- a/apps/api/src/routers/api_key_types.py +++ b/apps/api/src/routers/api_key_types.py @@ -8,7 +8,7 @@ APIKeyType, ) -router = APIRouter(prefix="/api_key_types", tags=["api key types"]) +router = APIRouter(prefix="/api-key-types", tags=["api key types"]) logger = logging.getLogger("root") diff --git a/apps/api/src/routers/subscriptions.py b/apps/api/src/routers/subscriptions.py index 88e155ed..801d5825 100644 --- a/apps/api/src/routers/subscriptions.py +++ b/apps/api/src/routers/subscriptions.py @@ -27,7 +27,7 @@ def get_subscriptions(q: SubscriptionGetRequest = Depends()) -> list[Subscriptio return db.get_subscriptions(q.profile_id, q.stripe_subscription_id) -@router.post("/") +@router.post("/", status_code=201) def insert_subscription(subscription: SubscriptionInsertRequest) -> Subscription: return db.insert_subscription(subscription) diff --git a/apps/api/src/routers/tools.py b/apps/api/src/routers/tools.py index 6ae66632..a85c6eb8 100644 --- a/apps/api/src/routers/tools.py +++ b/apps/api/src/routers/tools.py @@ -5,10 +5,11 @@ from src.interfaces import db from src.models import ( - AgentInsertRequest, - AgentUpdateModel, Agent, - AgentGetRequest, + Tool, + ToolGetRequest, + ToolInsertRequest, + ToolUpdateRequest, ) router = APIRouter( @@ -16,6 +17,43 @@ tags=["tools"], ) +@router.get("/") +def get_tools(q: ToolGetRequest = Depends()) -> list[Tool]: + return db.get_tools(q.name, q.api_key_type_id) + + +@router.get("/{tool_id}") +def get_tool(tool_id: UUID) -> Tool: + response = db.get_tool(tool_id) + if not response: + raise HTTPException(404, "tool not found") + + return response + + +@router.post("/", status_code=201) +def insert_tool(tool: ToolInsertRequest) -> Tool: + return db.insert_tool(tool) + + +@router.delete("/{tool_id}") +def delete_tool(tool_id: UUID) -> Tool: + response = db.delete_tool(tool_id) + if not response: + raise HTTPException(404, "could not find tool") + + return response + + +@router.patch("/{tool_id}") +def update_profile( + tool_id: UUID, tool_update_request: ToolUpdateRequest +) -> Tool: + if not db.get_tool(tool_id): + raise HTTPException(404, "tool not found") + + return db.update_tool(tool_id, tool_update_request) + @router.patch("/{agent_id}") def add_tool(agent_id: UUID, tool_id: UUID) -> Agent: From 0653daed8df533b13722983d39e0506ae4d6a21f Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 18:30:21 +0200 Subject: [PATCH 21/76] Fix sonarcloud issues (#206) fixed the issues in the code i wrote --- apps/api/src/crew.py | 3 +- apps/api/src/interfaces/db.py | 3 +- apps/api/src/mock.py | 13 +++++---- apps/api/src/models/rest_comment.py | 10 ------- apps/api/src/routers/api_keys.py | 5 ++-- apps/api/src/routers/billing_information.py | 6 ---- apps/api/src/routers/rest.py | 31 --------------------- apps/api/src/routers/subscriptions.py | 6 ---- apps/api/src/tools/__init__.py | 4 +-- apps/api/src/tools/scraper.py | 2 -- 10 files changed, 14 insertions(+), 69 deletions(-) delete mode 100644 apps/api/src/models/rest_comment.py diff --git a/apps/api/src/crew.py b/apps/api/src/crew.py index 1c5935e0..c071d23f 100644 --- a/apps/api/src/crew.py +++ b/apps/api/src/crew.py @@ -129,7 +129,7 @@ async def _on_reply( ] ): logger.error( - f"on_reply: both ids are none, sender is not admin and recipient is not chat manager" + "on_reply: both ids are none, sender is not admin and recipient is not chat manager" ) await self.on_reply(recipient_id, sender_id, content, role) @@ -192,6 +192,7 @@ def _create_agents( tool, api_key_types, profile_api_keys ) except TypeError as e: + logger.error(f"tried to generate tool, got error: {e}") raise e ( ( diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index 757281bb..b5452851 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -101,7 +101,7 @@ def get_sessions( def insert_session(content: SessionInsertRequest) -> Session: supabase: Client = create_client(url, key) - logger.info(f"inserting session") + logger.info("inserting session") response = ( supabase.table("sessions") .insert(json.loads(content.model_dump_json())) @@ -751,7 +751,6 @@ def get_tool_api_keys( ) -> dict[str, str]: """Gets all api keys for a profile id, if api_key_type_ids is given, only give api keys corresponding to those key types.""" supabase: Client = create_client(url, key) - # casted_ids = [str(api_key_type_id) for api_key_type_id in api_key_type_ids] query = ( supabase.table("users_api_keys") .select("api_key", "api_key_type_id") diff --git a/apps/api/src/mock.py b/apps/api/src/mock.py index b51e1e0b..4950a868 100644 --- a/apps/api/src/mock.py +++ b/apps/api/src/mock.py @@ -1,4 +1,5 @@ from .tools import get_file_path_of_example +DATE="2024-01-01T00:00:00.000Z" fizz_buzz: dict = { "id": "00000000-0000-0000-0000-000000000000", @@ -16,7 +17,7 @@ "title": "", "content": "Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”.", }, - "created_at": "2024-01-01T00:00:00.000Z", + "created_at": DATE, } markdown_table: dict = { @@ -35,7 +36,7 @@ "title": "", "content": "Create a markdown table of the top 10 large language models comparing their abilities by researching on the internet.", }, - "created_at": "2024-01-01T00:00:00.000Z", + "created_at": DATE, } # read_file: dict = { @@ -55,7 +56,7 @@ # "title": "", # "content": f"Get the file content of the file '{get_file_path_of_example()}', the 'agent python software' can call what function it has been", # }, -# "created_at": "2024-01-01T00:00:00.000Z", +# "created_at": DATE, # } # "6e541720-b4ac-4c47-abf3-f17147c9a32a", agent for code reviewing # "2ce0b7db-84f7-4d59-8c38-3fcc3fd7da98", agent for writing tables in markdown @@ -78,7 +79,7 @@ # "title": "", # "content": f"Move the file: '{get_file_path_of_example()}' to the destination: {get_file_path_of_example().replace('.txt', '_2.txt')} the 'agent python software' can call what function it has been", # }, -# "created_at": "2024-01-01T00:00:00.000Z", +# "created_at": DATE, # } tool, prompt = "brave search tool", "what is openai?" @@ -98,8 +99,8 @@ "title": "", "content": f"This is a tool testing environment, use the tool: {tool}, {prompt}. Suggest this function call", }, - "created_at": "2024-01-01T00:00:00.000Z", + "created_at": DATE, "edges": [], - "updated_at": "2024-01-01T00:00:00.000Z", + "updated_at": DATE, } crew_model = test_tool diff --git a/apps/api/src/models/rest_comment.py b/apps/api/src/models/rest_comment.py deleted file mode 100644 index 195ac3f2..00000000 --- a/apps/api/src/models/rest_comment.py +++ /dev/null @@ -1,10 +0,0 @@ -from uuid import UUID -from pydantic import BaseModel - -# TODO: This is placed here since the openapi schema of this model cant be generated if its in the src/rest/models directory for some reason -# will move this later on but this works for now -class PublishCommentRequest(BaseModel): - lead_id: UUID - comment: str - reddit_username: str - reddit_password: str diff --git a/apps/api/src/routers/api_keys.py b/apps/api/src/routers/api_keys.py index 6b4bc24b..cb7babde 100644 --- a/apps/api/src/routers/api_keys.py +++ b/apps/api/src/routers/api_keys.py @@ -17,9 +17,8 @@ @router.get("/") def get_api_keys(q: APIKeyGetRequest = Depends()) -> list[APIKey]: """Returns api keys with the api key type as an object with the id, name, description etc.""" - if q.profile_id: - if not db.get_profile(q.profile_id): - raise HTTPException(404, "profile not found") + if q.profile_id and not db.get_profile(q.profile_id): + raise HTTPException(404, "profile not found") return db.get_api_keys(q.profile_id, q.api_key_type_id, q.api_key) diff --git a/apps/api/src/routers/billing_information.py b/apps/api/src/routers/billing_information.py index 81b47173..d4e567ee 100644 --- a/apps/api/src/routers/billing_information.py +++ b/apps/api/src/routers/billing_information.py @@ -52,9 +52,3 @@ def update_billing(profile_id: UUID, content: BillingUpdateRequest) -> Billing: return response - -# -# -# @router.get("/{message_id}") -# def get_message(message_id: UUID) -> Message: -# return db.get_message(message_id) diff --git a/apps/api/src/routers/rest.py b/apps/api/src/routers/rest.py index 48e5dcbf..2e2dd201 100644 --- a/apps/api/src/routers/rest.py +++ b/apps/api/src/routers/rest.py @@ -1,34 +1,3 @@ -#import logging -#from uuid import UUID -# -#from fastapi import APIRouter, HTTPException -#from src.models import Crew, Message, Session -#from src.rest import comment_bot -#from src.rest.interfaces import db -#from src.rest.models import PublishCommentRequest, PublishCommentResponse -# -#router = APIRouter(prefix="/rest", tags=["rest"]) -# -#logger = logging.getLogger("root") -# -# -#@router.post("/") -#def publish_comment(publish_request: PublishCommentRequest): -# updated_content = comment_bot.publish_comment( -# publish_request.lead_id, -# publish_request.comment, -# publish_request.reddit_username, -# publish_request.reddit_password, -# ) -# if updated_content is None: -# raise HTTPException(404, "lead not found") -# -# return updated_content -# -#@router.get("/") -#def get_leads() -> list[PublishCommentResponse]: -# return db.get_all_leads() -# import os from dotenv import load_dotenv import logging diff --git a/apps/api/src/routers/subscriptions.py b/apps/api/src/routers/subscriptions.py index 801d5825..1f13b926 100644 --- a/apps/api/src/routers/subscriptions.py +++ b/apps/api/src/routers/subscriptions.py @@ -51,9 +51,3 @@ def update_subscription( return response - -# -# -# @router.get("/{message_id}") -# def get_message(message_id: UUID) -> Message: -# return db.get_message(message_id) diff --git a/apps/api/src/tools/__init__.py b/apps/api/src/tools/__init__.py index caf7193c..2d792261 100644 --- a/apps/api/src/tools/__init__.py +++ b/apps/api/src/tools/__init__.py @@ -104,13 +104,13 @@ def generate_tool_from_uuid( api_key = api_keys[tool_key_type] if has_param(tool_cls, "api_key"): - logger.info(f"has parameter 'api_key'") + logger.info("has parameter 'api_key'") if not api_key: raise TypeError( "api key should not be none when passed to tool that needs api key" ) tool_object = tools[tool_id](api_key=api_key) - logger.info(f"creating tool") + logger.info("creating tool") return tool_object logger.info("making tool without api_key") diff --git a/apps/api/src/tools/scraper.py b/apps/api/src/tools/scraper.py index eb2bb65a..454b7c23 100644 --- a/apps/api/src/tools/scraper.py +++ b/apps/api/src/tools/scraper.py @@ -12,8 +12,6 @@ ID = "4ac25953-dc41-42d5-b9f2-bcae3b2c1d9f" API_KEY_TYPE = "3b64fe26-20b9-4064-907e-f2708b5f1656" -# key = os.environ.get("SERPAPI_API_KEY") - class ScraperToolInput(BaseModel): query: str = Field( From d106a77018a5c0a01b33e439b91cb9c09c20d140 Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Wed, 17 Apr 2024 19:42:07 +0200 Subject: [PATCH 22/76] Format and fix typing (#207) * format * fixup on typing --- apps/api/poetry.lock | 2 +- apps/api/pyproject.toml | 1 + apps/api/src/__init__.py | 14 ++-- apps/api/src/auth.py | 11 ++- apps/api/src/crew.py | 8 ++- apps/api/src/dependencies/__init__.py | 1 + apps/api/src/interfaces/db.py | 42 +++++------- apps/api/src/mock.py | 3 +- apps/api/src/models/__init__.py | 68 ++++++++----------- apps/api/src/models/agent_model.py | 2 +- apps/api/src/models/api_key.py | 6 +- apps/api/src/models/billing_information.py | 1 - apps/api/src/models/crew_model.py | 7 +- apps/api/src/models/edge.py | 8 ++- apps/api/src/models/message.py | 10 +-- apps/api/src/models/profile.py | 5 +- apps/api/src/models/session.py | 12 ++-- apps/api/src/models/tool.py | 2 +- apps/api/src/models/user.py | 2 +- apps/api/src/parser.py | 3 +- apps/api/src/rest/__init__.py | 26 +++---- apps/api/src/rest/chat_bot.py | 14 ++-- apps/api/src/rest/comment_bot.py | 17 ++--- apps/api/src/rest/dm.py | 14 ++-- apps/api/src/rest/interfaces/db.py | 6 +- apps/api/src/rest/logging_utils.py | 4 +- apps/api/src/rest/mail.py | 12 ++-- apps/api/src/rest/models/__init__.py | 8 +-- apps/api/src/rest/models/dummy_submission.py | 3 +- .../src/rest/models/evaluated_submission.py | 1 + apps/api/src/rest/models/false_lead.py | 3 +- apps/api/src/rest/models/filter_output.py | 5 +- apps/api/src/rest/models/filter_question.py | 2 +- apps/api/src/rest/models/lead.py | 10 +-- apps/api/src/rest/models/publish_comment.py | 5 +- apps/api/src/rest/models/reddit_comment.py | 2 +- apps/api/src/rest/models/relevance_result.py | 9 ++- apps/api/src/rest/models/saved_submission.py | 7 +- apps/api/src/rest/prompts/__init__.py | 9 ++- apps/api/src/rest/prompts/commenting.py | 20 ++++-- apps/api/src/rest/prompts/relevance.py | 18 +++-- apps/api/src/rest/reddit_utils.py | 5 +- apps/api/src/rest/reddit_worker.py | 12 ++-- apps/api/src/rest/relevance_bot.py | 32 +++++---- apps/api/src/rest/saving.py | 3 +- apps/api/src/rest/utils.py | 9 ++- apps/api/src/routers/agents.py | 10 ++- apps/api/src/routers/api_key_types.py | 6 +- apps/api/src/routers/api_keys.py | 7 +- apps/api/src/routers/billing_information.py | 7 +- apps/api/src/routers/crews.py | 7 +- apps/api/src/routers/messages.py | 15 ++-- apps/api/src/routers/profiles.py | 7 +- apps/api/src/routers/rest.py | 26 ++++--- apps/api/src/routers/sessions.py | 29 ++++---- apps/api/src/routers/subscriptions.py | 3 +- apps/api/src/routers/tiers.py | 2 +- apps/api/src/routers/tools.py | 9 ++- apps/api/src/tools/__init__.py | 27 ++++---- apps/api/src/tools/alpha_vantage.py | 2 +- apps/api/src/tools/arxiv_tool.py | 5 +- apps/api/src/tools/bing.py | 22 +++--- apps/api/src/tools/brave_search.py | 2 +- apps/api/src/tools/duckduckgo_tool.py | 21 ++++-- apps/api/src/tools/google_serper.py | 52 ++++++++------ apps/api/src/tools/scraper.py | 2 +- apps/api/src/tools/stackapi_tool.py | 4 +- apps/api/src/tools/wikipedia_tool.py | 2 +- 68 files changed, 386 insertions(+), 345 deletions(-) diff --git a/apps/api/poetry.lock b/apps/api/poetry.lock index ef97f18c..5cf67919 100644 --- a/apps/api/poetry.lock +++ b/apps/api/poetry.lock @@ -4636,4 +4636,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.13" -content-hash = "0162a9621b5487162b64103aeb609b65901aecb2ee79b06d6f824b5a49c3cd62" +content-hash = "3be1bebffa9dce9a2cea13c7d5eea6ac68c50fc9f7b79a38b5d5011132cc15c5" diff --git a/apps/api/pyproject.toml b/apps/api/pyproject.toml index de01e355..09757254 100644 --- a/apps/api/pyproject.toml +++ b/apps/api/pyproject.toml @@ -40,6 +40,7 @@ mail = "^2.1.0" duckduckgo-search = "^5.2.2" langchain-exa = "^0.0.1" stackapi = "^0.3.0" +mypy = "^1.9.0" [tool.poetry.group.dev.dependencies] mypy = "^1.7.0" diff --git a/apps/api/src/__init__.py b/apps/api/src/__init__.py index c27f4b7f..83122438 100644 --- a/apps/api/src/__init__.py +++ b/apps/api/src/__init__.py @@ -18,21 +18,19 @@ ) from .improver import PromptType, improve_prompt from .interfaces import db -from .models import CrewProcessed +from .models import Profile +from .routers import agents, api_key_types, api_keys from .routers import auth as auth_router from .routers import ( - agents, + billing_information, crews, messages, - sessions, profiles, - api_key_types, rest, - api_keys, - tools, + sessions, subscriptions, tiers, - billing_information, + tools, ) logger = logging.getLogger("root") @@ -114,5 +112,5 @@ def auto_build_crew(general_task: str) -> str: @app.get("/me") -def get_profile_from_header(current_user=Depends(get_current_user)): +def get_profile_from_header(current_user=Depends(get_current_user)) -> Profile: return current_user diff --git a/apps/api/src/auth.py b/apps/api/src/auth.py index 50b1fd83..6c76261e 100644 --- a/apps/api/src/auth.py +++ b/apps/api/src/auth.py @@ -5,13 +5,10 @@ import jwt from dotenv import load_dotenv from fastapi import Depends, FastAPI, HTTPException, status -from fastapi.security import ( - HTTPAuthorizationCredentials, - HTTPBearer, - -) +from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer from src.interfaces import db +from src.models import Profile load_dotenv() @@ -21,7 +18,7 @@ logger = logging.getLogger("root") -async def get_current_user(token: HTTPAuthorizationCredentials = Depends(HTTPBearer())): +async def get_current_user(token: HTTPAuthorizationCredentials = Depends(HTTPBearer())) -> Profile: credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", @@ -43,4 +40,4 @@ async def get_current_user(token: HTTPAuthorizationCredentials = Depends(HTTPBea if not user_id or not profile: raise credentials_exception - return profile \ No newline at end of file + return profile diff --git a/apps/api/src/crew.py b/apps/api/src/crew.py index c071d23f..6cac7eb1 100644 --- a/apps/api/src/crew.py +++ b/apps/api/src/crew.py @@ -5,6 +5,7 @@ import autogen from autogen.cache import Cache +from langchain.tools import BaseTool from src.models.session import SessionStatus @@ -18,6 +19,7 @@ logger = logging.getLogger("root") + class AutogenCrew: def __init__( self, @@ -33,7 +35,7 @@ def __init__( self.session = session self.on_reply = on_message self.crew_model = crew_model - self.valid_tools = [] + self.valid_tools: list[BaseTool] = [] self.agents: list[autogen.ConversableAgent | autogen.Agent] = ( self._create_agents(crew_model) @@ -56,7 +58,7 @@ def __init__( ) if self.valid_tools else None - ) + ) self.user_proxy.register_reply([autogen.Agent, None], self._on_reply) self.base_config_list = autogen.config_list_from_json( @@ -174,7 +176,7 @@ def _create_agents( for agent in crew_model.agents: valid_agent_tools = [] - tool_schemas = {} + tool_schemas: list[dict] | None config_list = autogen.config_list_from_json( "OAI_CONFIG_LIST", filter_dict={ diff --git a/apps/api/src/dependencies/__init__.py b/apps/api/src/dependencies/__init__.py index 5e163b3b..c551020e 100644 --- a/apps/api/src/dependencies/__init__.py +++ b/apps/api/src/dependencies/__init__.py @@ -20,6 +20,7 @@ if url is None or key is None: raise ValueError("SUPABASE_URL and SUPABASE_ANON_KEY must be set") + @dataclass class RateLimitResponse: limit: int diff --git a/apps/api/src/interfaces/db.py b/apps/api/src/interfaces/db.py index b5452851..4675324c 100644 --- a/apps/api/src/interfaces/db.py +++ b/apps/api/src/interfaces/db.py @@ -13,39 +13,36 @@ Agent, AgentInsertRequest, AgentUpdateModel, - CrewInsertRequest, + APIKey, + APIKeyInsertRequest, + APIKeyType, + APIKeyUpdateRequest, + Billing, + BillingInsertRequest, + BillingUpdateRequest, Crew, + CrewInsertRequest, CrewUpdateRequest, Message, + MessageInsertRequest, + MessageUpdateRequest, Profile, + ProfileInsertRequest, ProfileUpdateRequest, Session, SessionInsertRequest, - Session, SessionStatus, SessionUpdateRequest, - ProfileInsertRequest, - APIKeyInsertRequest, - APIKey, - APIKeyType, - APIKeyUpdateRequest, - APIKeyType, - MessageInsertRequest, - Message, - MessageUpdateRequest, Subscription, + SubscriptionGetRequest, SubscriptionInsertRequest, SubscriptionUpdateRequest, - Tool, - ToolInsertRequest, - ToolUpdateRequest, - SubscriptionGetRequest, Tier, TierInsertRequest, TierUpdateRequest, - Billing, - BillingInsertRequest, - BillingUpdateRequest, + Tool, + ToolInsertRequest, + ToolUpdateRequest, ) from src.models.tiers import TierGetRequest @@ -280,7 +277,6 @@ def update_subscription( return Subscription(**response.data[0]) - def get_tier(id: UUID) -> Tier | None: """Gets tiers, filtered by what parameters are given""" supabase: Client = create_client(url, key) @@ -350,7 +346,7 @@ def insert_billing(billing: BillingInsertRequest) -> Billing: .insert(json.loads(billing.model_dump_json(exclude_none=True))) .execute() ) - + return Billing(**response.data[0]) @@ -376,14 +372,12 @@ def update_billing(profile_id: UUID, content: BillingUpdateRequest) -> Billing | supabase.table("billing_information") .update(json.loads(content.model_dump_json(exclude_none=True))) .eq("profile_id", profile_id) - .execute() ) if len(response.data) == 0: return None - - return Billing(**response.data[0]) + return Billing(**response.data[0]) def get_descriptions(agent_ids: list[UUID]) -> dict[UUID, list[str]] | None: @@ -679,7 +673,7 @@ def get_tool(tool_id: UUID) -> Tool | None: if len(response.data) == 0: return None - return Tool(**response.data[0]) + return Tool(**response.data[0]) def get_tools( diff --git a/apps/api/src/mock.py b/apps/api/src/mock.py index 4950a868..40600c41 100644 --- a/apps/api/src/mock.py +++ b/apps/api/src/mock.py @@ -1,5 +1,6 @@ from .tools import get_file_path_of_example -DATE="2024-01-01T00:00:00.000Z" + +DATE = "2024-01-01T00:00:00.000Z" fizz_buzz: dict = { "id": "00000000-0000-0000-0000-000000000000", diff --git a/apps/api/src/models/__init__.py b/apps/api/src/models/__init__.py index 86012ec4..f9361e0c 100644 --- a/apps/api/src/models/__init__.py +++ b/apps/api/src/models/__init__.py @@ -1,70 +1,60 @@ from .agent_config import AgentConfig from .agent_model import ( Agent, + AgentGetRequest, AgentInsertRequest, AgentUpdateModel, - AgentGetRequest, +) +from .api_key import ( + APIKey, + APIKeyGetRequest, + APIKeyInsertRequest, + APIKeyType, + APIKeyUpdateRequest, +) +from .billing_information import ( + Billing, + BillingInsertRequest, + BillingUpdateRequest, ) from .code_execution_config import CodeExecutionConfig from .crew_model import ( - CrewProcessed, - CrewInsertRequest, Crew, - CrewUpdateRequest, CrewGetRequest, + CrewInsertRequest, + CrewProcessed, + CrewUpdateRequest, ) from .llm_config import LLMConfig from .message import ( Message, + MessageGetRequest, MessageInsertRequest, MessageUpdateRequest, - MessageGetRequest, -) -from .subscription import ( - Subscription, - SubscriptionInsertRequest, - SubscriptionUpdateRequest, - SubscriptionGetRequest, -) -from .tiers import ( - Tier, - TierInsertRequest, - TierUpdateRequest, - TierGetRequest, -) -from .billing_information import ( - Billing, - BillingInsertRequest, - BillingUpdateRequest, ) from .profile import ( - ProfileInsertRequest, Profile, - ProfileUpdateRequest, ProfileGetRequest, + ProfileInsertRequest, + ProfileUpdateRequest, ) from .session import ( - SessionRunRequest, - SessionRunResponse, Session, + SessionGetRequest, SessionInsertRequest, + SessionRunRequest, + SessionRunResponse, SessionStatus, SessionUpdateRequest, - SessionGetRequest, -) -from .api_key import ( - APIKeyInsertRequest, - APIKey, - APIKeyType, - APIKeyUpdateRequest, - APIKeyGetRequest, ) -from .tool import ( - Tool, - ToolInsertRequest, - ToolUpdateRequest, - ToolGetRequest, +from .subscription import ( + Subscription, + SubscriptionGetRequest, + SubscriptionInsertRequest, + SubscriptionUpdateRequest, ) +from .tiers import Tier, TierGetRequest, TierInsertRequest, TierUpdateRequest +from .tool import Tool, ToolGetRequest, ToolInsertRequest, ToolUpdateRequest from .user import User __all__ = [ diff --git a/apps/api/src/models/agent_model.py b/apps/api/src/models/agent_model.py index 8a4c6a15..c4cc63f0 100644 --- a/apps/api/src/models/agent_model.py +++ b/apps/api/src/models/agent_model.py @@ -18,7 +18,7 @@ class Agent(BaseModel): model: Literal["gpt-3.5-turbo", "gpt-4-turbo-preview"] tools: list[dict] description: str | None = None - role: str + role: str version: str | None = None diff --git a/apps/api/src/models/api_key.py b/apps/api/src/models/api_key.py index 9ee5febe..b4c5a07d 100644 --- a/apps/api/src/models/api_key.py +++ b/apps/api/src/models/api_key.py @@ -1,6 +1,8 @@ from __future__ import annotations -from uuid import UUID, uuid4 + from datetime import datetime +from uuid import UUID, uuid4 + from pydantic import BaseModel @@ -32,4 +34,4 @@ class APIKeyType(BaseModel): id: UUID created_at: datetime name: str | None = None - description: str | None = None \ No newline at end of file + description: str | None = None diff --git a/apps/api/src/models/billing_information.py b/apps/api/src/models/billing_information.py index e9590672..95308c77 100644 --- a/apps/api/src/models/billing_information.py +++ b/apps/api/src/models/billing_information.py @@ -20,4 +20,3 @@ class BillingInsertRequest(BaseModel): class BillingUpdateRequest(BaseModel): stripe_payment_method: str | None = None description: str | None = None - diff --git a/apps/api/src/models/crew_model.py b/apps/api/src/models/crew_model.py index 65d274d1..08c99efe 100644 --- a/apps/api/src/models/crew_model.py +++ b/apps/api/src/models/crew_model.py @@ -11,12 +11,13 @@ class CrewProcessed(BaseModel): receiver_id: UUID - delegator_id: UUID | None = None + delegator_id: UUID | None = None # None means admin again, so its the original crew (has no parent crew) agents: list[Agent] - sub_crews: list[Crew] = [] + sub_crews: list[Crew] = [] # Must set delegator_id for each sub_crew in sub_crews + class Crew(BaseModel): id: UUID created_at: datetime @@ -58,4 +59,4 @@ class CrewGetRequest(BaseModel): profile_id: UUID | None = None receiver_id: UUID | None = None title: str | None = None - published: bool | None = None \ No newline at end of file + published: bool | None = None diff --git a/apps/api/src/models/edge.py b/apps/api/src/models/edge.py index 7e82a997..e7a4c8cf 100644 --- a/apps/api/src/models/edge.py +++ b/apps/api/src/models/edge.py @@ -1,8 +1,10 @@ -from typing import Optional, Union, Generic, TypeVar +from typing import Generic, Optional, TypeVar, Union + from pydantic import BaseModel, Field T = TypeVar("T") + class Marker(BaseModel): type: str color: Optional[str] = None @@ -12,11 +14,13 @@ class Marker(BaseModel): orient: Optional[str] = None strokeWidth: Optional[float] = None + class PathOptions(BaseModel): offset: Optional[float] = None borderRadius: Optional[float] = None curvature: Optional[float] = None + class Edge(BaseModel, Generic[T]): id: str type: Optional[str] = None @@ -42,4 +46,4 @@ class Edge(BaseModel, Generic[T]): pathOptions: Optional[PathOptions] = None class Config: - populate_by_name = True \ No newline at end of file + populate_by_name = True diff --git a/apps/api/src/models/message.py b/apps/api/src/models/message.py index 0d3d8843..ba567b5a 100644 --- a/apps/api/src/models/message.py +++ b/apps/api/src/models/message.py @@ -5,13 +5,13 @@ class Message(BaseModel): - id: UUID + id: UUID session_id: UUID profile_id: UUID sender_id: UUID | None = None # None means admin here recipient_id: UUID | None = None # None means admin here aswell content: str - role: str + role: str created_at: datetime @@ -28,13 +28,13 @@ class MessageUpdateRequest(BaseModel): session_id: UUID | None = None content: str | None = None role: str | None = None - recipient_id: UUID | None = None - sender_id: UUID | None = None + recipient_id: UUID | None = None + sender_id: UUID | None = None profile_id: UUID | None = None class MessageGetRequest(BaseModel): session_id: UUID | None = None profile_id: UUID | None = None - recipient_id: UUID | None = None + recipient_id: UUID | None = None sender_id: UUID | None = None diff --git a/apps/api/src/models/profile.py b/apps/api/src/models/profile.py index a269234d..cad8ca11 100644 --- a/apps/api/src/models/profile.py +++ b/apps/api/src/models/profile.py @@ -1,9 +1,8 @@ +from datetime import datetime from uuid import UUID, uuid4 from pydantic import BaseModel, Field -from datetime import datetime -# = Field(default_factory=lambda: uuid4()) class Profile(BaseModel): id: UUID @@ -14,7 +13,7 @@ class Profile(BaseModel): class ProfileInsertRequest(BaseModel): - # user id needs to be passed since its created from some "auth" table in the db + # user id needs to be passed since its created from some "auth" table in the db user_id: UUID tier_id: UUID display_name: str diff --git a/apps/api/src/models/session.py b/apps/api/src/models/session.py index 82fc2021..988ab3c6 100644 --- a/apps/api/src/models/session.py +++ b/apps/api/src/models/session.py @@ -13,14 +13,14 @@ class SessionStatus(StrEnum): class Session(BaseModel): - id: UUID + id: UUID created_at: datetime profile_id: UUID - reply: str + reply: str crew_id: UUID - title: str - last_opened_at: datetime - status: SessionStatus + title: str + last_opened_at: datetime + status: SessionStatus class SessionInsertRequest(BaseModel): @@ -54,4 +54,4 @@ class SessionGetRequest(BaseModel): profile_id: UUID | None = None crew_id: UUID | None = None title: str | None = None - status: SessionStatus | None = None \ No newline at end of file + status: SessionStatus | None = None diff --git a/apps/api/src/models/tool.py b/apps/api/src/models/tool.py index 45106133..2f13101a 100644 --- a/apps/api/src/models/tool.py +++ b/apps/api/src/models/tool.py @@ -26,4 +26,4 @@ class ToolUpdateRequest(BaseModel): class ToolGetRequest(BaseModel): name: str | None = None - api_key_type_id: UUID | None = None \ No newline at end of file + api_key_type_id: UUID | None = None diff --git a/apps/api/src/models/user.py b/apps/api/src/models/user.py index 50bdeb63..ad1649bd 100644 --- a/apps/api/src/models/user.py +++ b/apps/api/src/models/user.py @@ -4,4 +4,4 @@ class User: id: UUID name: str - email: str \ No newline at end of file + email: str diff --git a/apps/api/src/parser.py b/apps/api/src/parser.py index f75b4390..ba0e6aa7 100644 --- a/apps/api/src/parser.py +++ b/apps/api/src/parser.py @@ -46,12 +46,13 @@ def get_agents(agent_ids: list[UUID]) -> list[Agent]: response = supabase.table("agents").select("*").in_("id", agent_ids).execute() return [Agent(**agent) for agent in response.data] + def process_crew(crew: Crew) -> tuple[str, CrewProcessed]: logger.debug("Processing crew") agent_ids: list[UUID] = crew.nodes if not crew.receiver_id: raise HTTPException(400, "got no receiver id") - + receiver_id: UUID = crew.receiver_id crew_model = CrewProcessed( diff --git a/apps/api/src/rest/__init__.py b/apps/api/src/rest/__init__.py index 735ea8d6..364f2d9f 100644 --- a/apps/api/src/rest/__init__.py +++ b/apps/api/src/rest/__init__.py @@ -1,27 +1,21 @@ -import os -from dotenv import load_dotenv import logging -import diskcache as dc +import os import threading from uuid import uuid4 -from .saving import update_db_with_submission -from . import mail -from .reddit_utils import get_subreddits -from .relevance_bot import evaluate_relevance -from .interfaces import db -from . import comment_bot -from .models import ( - PublishCommentRequest, - GenerateCommentRequest, - FalseLead, -) -from .reddit_worker import RedditStreamWorker - +import diskcache as dc +from dotenv import load_dotenv from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import RedirectResponse +from . import comment_bot, mail +from .interfaces import db +from .models import FalseLead, GenerateCommentRequest, PublishCommentRequest +from .reddit_utils import get_subreddits +from .reddit_worker import RedditStreamWorker +from .relevance_bot import evaluate_relevance +from .saving import update_db_with_submission # Relevant subreddits to Startino SUBREDDIT_NAMES = ( diff --git a/apps/api/src/rest/chat_bot.py b/apps/api/src/rest/chat_bot.py index b480b463..4c32a7e7 100644 --- a/apps/api/src/rest/chat_bot.py +++ b/apps/api/src/rest/chat_bot.py @@ -2,24 +2,24 @@ from selenium.webdriver.common.keys import Keys # Set the path to your Chrome driver executable -driver_path = '/path/to/chromedriver' +driver_path = "/path/to/chromedriver" # Create a new instance of the Chrome driver driver = webdriver.Chrome(driver_path) # Open chat.reddit.com -driver.get('https://chat.reddit.com') +driver.get("https://chat.reddit.com") # Find the login button and click it login_button = driver.find_element_by_xpath('//button[contains(text(), "Log in")]') login_button.click() # Find the username and password input fields and enter your credentials -username_input = driver.find_element_by_name('username') -username_input.send_keys('your_username') +username_input = driver.find_element_by_name("username") +username_input.send_keys("your_username") -password_input = driver.find_element_by_name('password') -password_input.send_keys('your_password') +password_input = driver.find_element_by_name("password") +password_input.send_keys("your_password") # Submit the login form -password_input.send_keys(Keys.RETURN) \ No newline at end of file +password_input.send_keys(Keys.RETURN) diff --git a/apps/api/src/rest/comment_bot.py b/apps/api/src/rest/comment_bot.py index 5ffd7395..121b9e36 100644 --- a/apps/api/src/rest/comment_bot.py +++ b/apps/api/src/rest/comment_bot.py @@ -1,16 +1,17 @@ import logging -from langchain_openai import ChatOpenAI -from langchain_core.prompts import PromptTemplate +import os + +from dotenv import load_dotenv from langchain_core.output_parsers import JsonOutputParser -from .models import EvaluatedSubmission, RedditComment, PublishCommentResponse -from .dummy_submissions import relevant_submissions, irrelevant_submissions -from .prompts import generate_comment_prompt +from langchain_core.prompts import PromptTemplate +from langchain_openai import ChatOpenAI + +from .dummy_submissions import irrelevant_submissions, relevant_submissions from .interfaces import db +from .models import EvaluatedSubmission, PublishCommentResponse, RedditComment +from .prompts import generate_comment_prompt from .reddit_utils import get_reddit_instance -from dotenv import load_dotenv -import os - # Load Enviornment variables load_dotenv() OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") diff --git a/apps/api/src/rest/dm.py b/apps/api/src/rest/dm.py index 77853a82..76561033 100644 --- a/apps/api/src/rest/dm.py +++ b/apps/api/src/rest/dm.py @@ -1,9 +1,15 @@ -from reddit_utils import REDDIT_PASSWORD, get_subreddits, reply -from Reddit_ChatBot_Python import ChatBot, RedditAuthentication -from Reddit_ChatBot_Python import CustomType, Snoo, Reaction -from dotenv import load_dotenv import os +from dotenv import load_dotenv +from Reddit_ChatBot_Python import ( + ChatBot, + CustomType, + Reaction, + RedditAuthentication, + Snoo, +) +from reddit_utils import REDDIT_PASSWORD, get_subreddits, reply + load_dotenv() REDDIT_PASSWORD = os.getenv("REDDIT_PASSWORD") diff --git a/apps/api/src/rest/interfaces/db.py b/apps/api/src/rest/interfaces/db.py index a6e1745a..c558590b 100644 --- a/apps/api/src/rest/interfaces/db.py +++ b/apps/api/src/rest/interfaces/db.py @@ -1,6 +1,7 @@ import json import logging import os +from datetime import datetime, timedelta from typing import Literal from uuid import UUID @@ -8,10 +9,7 @@ from pydantic import ValidationError from supabase import Client, create_client -from src.rest.models import Lead, PublishCommentResponse -from datetime import datetime, timedelta - -from src.rest.models import SavedSubmission +from src.rest.models import Lead, PublishCommentResponse, SavedSubmission load_dotenv() diff --git a/apps/api/src/rest/logging_utils.py b/apps/api/src/rest/logging_utils.py index cf2dfdd3..fad61c9e 100644 --- a/apps/api/src/rest/logging_utils.py +++ b/apps/api/src/rest/logging_utils.py @@ -1,6 +1,7 @@ -from praw.models import Submission from datetime import datetime +from praw.models import Submission + def log_relevance_calculation( model: str, submission: Submission, is_relevant: bool, cost: float, reason: str @@ -18,4 +19,3 @@ def log_relevance_calculation( print(f"Is Relevant: {'Yes' if is_relevant else 'No'}") print(f"Reason: {reason}") print("\n\n") - diff --git a/apps/api/src/rest/mail.py b/apps/api/src/rest/mail.py index 5013c3a8..69327966 100644 --- a/apps/api/src/rest/mail.py +++ b/apps/api/src/rest/mail.py @@ -1,12 +1,14 @@ -import smtplib -from email.mime.text import MIMEText -from email.mime.multipart import MIMEMultipart import os -from dotenv import load_dotenv +import smtplib from datetime import datetime +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText + import diskcache as dc -from .models import EvaluatedSubmission import markdown +from dotenv import load_dotenv + +from .models import EvaluatedSubmission load_dotenv() diff --git a/apps/api/src/rest/models/__init__.py b/apps/api/src/rest/models/__init__.py index fbac0500..7077061e 100644 --- a/apps/api/src/rest/models/__init__.py +++ b/apps/api/src/rest/models/__init__.py @@ -1,13 +1,13 @@ -from .relevance_result import RelevanceResult from .dummy_submission import DummySubmission +from .evaluated_submission import EvaluatedSubmission +from .false_lead import FalseLead from .filter_output import FilterOutput from .filter_question import FilterQuestion -from .evaluated_submission import EvaluatedSubmission from .lead import Lead -from .reddit_comment import RedditComment, GenerateCommentRequest from .publish_comment import PublishCommentRequest, PublishCommentResponse +from .reddit_comment import GenerateCommentRequest, RedditComment +from .relevance_result import RelevanceResult from .saved_submission import SavedSubmission -from .false_lead import FalseLead __all__ = [ "RelevanceResult", diff --git a/apps/api/src/rest/models/dummy_submission.py b/apps/api/src/rest/models/dummy_submission.py index 2b2526cf..ebc03630 100644 --- a/apps/api/src/rest/models/dummy_submission.py +++ b/apps/api/src/rest/models/dummy_submission.py @@ -1,8 +1,9 @@ from pydantic import BaseModel, Field + class DummySubmission(BaseModel): id: str url: str created_utc: int title: str - selftext: str \ No newline at end of file + selftext: str diff --git a/apps/api/src/rest/models/evaluated_submission.py b/apps/api/src/rest/models/evaluated_submission.py index 8ae024fc..2f71eeef 100644 --- a/apps/api/src/rest/models/evaluated_submission.py +++ b/apps/api/src/rest/models/evaluated_submission.py @@ -1,4 +1,5 @@ from typing import Optional + from praw.models import Submission from pydantic import BaseModel, ConfigDict diff --git a/apps/api/src/rest/models/false_lead.py b/apps/api/src/rest/models/false_lead.py index e8f7a249..d643aef4 100644 --- a/apps/api/src/rest/models/false_lead.py +++ b/apps/api/src/rest/models/false_lead.py @@ -1,6 +1,7 @@ -from pydantic import BaseModel from uuid import UUID +from pydantic import BaseModel + class FalseLead(BaseModel): lead_id: UUID diff --git a/apps/api/src/rest/models/filter_output.py b/apps/api/src/rest/models/filter_output.py index 22fe05ec..7e3145e2 100644 --- a/apps/api/src/rest/models/filter_output.py +++ b/apps/api/src/rest/models/filter_output.py @@ -5,7 +5,10 @@ from langchain_core.pydantic_v1 import BaseModel, Field, validator from langchain_openai import ChatOpenAI + # Define your desired data structure. class FilterOutput(BaseModel): answer: bool = Field(description="Answer to the yes-no question.") - source: str = Field(description="Either the piece of text you used to answer the question or the logical reason behind it. Should be brief and only have the relevant information") + source: str = Field( + description="Either the piece of text you used to answer the question or the logical reason behind it. Should be brief and only have the relevant information" + ) diff --git a/apps/api/src/rest/models/filter_question.py b/apps/api/src/rest/models/filter_question.py index 66cb8609..36c8bb47 100644 --- a/apps/api/src/rest/models/filter_question.py +++ b/apps/api/src/rest/models/filter_question.py @@ -1,6 +1,6 @@ from pydantic import BaseModel + class FilterQuestion(BaseModel): question: str reject_on: bool - diff --git a/apps/api/src/rest/models/lead.py b/apps/api/src/rest/models/lead.py index 8082c90f..ce9c05c4 100644 --- a/apps/api/src/rest/models/lead.py +++ b/apps/api/src/rest/models/lead.py @@ -1,8 +1,9 @@ -from re import S -from pydantic import BaseModel, Field from datetime import UTC, datetime +from re import S from uuid import UUID, uuid4 +from pydantic import BaseModel, Field + class Lead(BaseModel): """ @@ -10,10 +11,9 @@ class Lead(BaseModel): """ id: UUID = Field(default_factory=lambda: uuid4()) - submission_id : UUID + submission_id: UUID reddit_id: str - discovered_at: datetime = Field( - default_factory=lambda: datetime.now(tz=UTC)) + discovered_at: datetime = Field(default_factory=lambda: datetime.now(tz=UTC)) last_contacted_at: datetime | None = None prospect_username: str source: str diff --git a/apps/api/src/rest/models/publish_comment.py b/apps/api/src/rest/models/publish_comment.py index 5633bfad..f6fbe816 100644 --- a/apps/api/src/rest/models/publish_comment.py +++ b/apps/api/src/rest/models/publish_comment.py @@ -1,13 +1,16 @@ from datetime import datetime from uuid import UUID + from pydantic import BaseModel + class PublishCommentRequest(BaseModel): lead_id: UUID comment: str reddit_username: str reddit_password: str + class PublishCommentDataObject(BaseModel): url: str body: str @@ -25,4 +28,4 @@ class PublishCommentResponse(BaseModel): data: PublishCommentDataObject | None = None last_event: str status: str - comment: str | None = None \ No newline at end of file + comment: str | None = None diff --git a/apps/api/src/rest/models/reddit_comment.py b/apps/api/src/rest/models/reddit_comment.py index b99184d7..b8823d42 100644 --- a/apps/api/src/rest/models/reddit_comment.py +++ b/apps/api/src/rest/models/reddit_comment.py @@ -4,11 +4,11 @@ from pydantic import BaseModel as PydanticBaseModel - class RedditComment(BaseModel): comment: str = Field(description="the text of the reddit comment") # Not sure if this should be a model or simply a string. + class GenerateCommentRequest(PydanticBaseModel): title: str selftext: str diff --git a/apps/api/src/rest/models/relevance_result.py b/apps/api/src/rest/models/relevance_result.py index 0c3caa0c..fc797ca7 100644 --- a/apps/api/src/rest/models/relevance_result.py +++ b/apps/api/src/rest/models/relevance_result.py @@ -1,6 +1,11 @@ from langchain_core.pydantic_v1 import BaseModel, Field + class RelevanceResult(BaseModel): - certainty: float = Field(description="A value between 0-1 to determine how certain you are that the is_relevant answer is factually correct.") + certainty: float = Field( + description="A value between 0-1 to determine how certain you are that the is_relevant answer is factually correct." + ) is_relevant: bool = Field(description="Determines if the post is relevant.") - reason: str = Field(description="Explain why you determined this post is relevant or irrelevant. Format: Post is [answer] because [reason]. Hence, it is not a lead and not relevant") + reason: str = Field( + description="Explain why you determined this post is relevant or irrelevant. Format: Post is [answer] because [reason]. Hence, it is not a lead and not relevant" + ) diff --git a/apps/api/src/rest/models/saved_submission.py b/apps/api/src/rest/models/saved_submission.py index 9e40fe8e..35b94d28 100644 --- a/apps/api/src/rest/models/saved_submission.py +++ b/apps/api/src/rest/models/saved_submission.py @@ -1,7 +1,8 @@ -from pydantic import BaseModel, Field -from datetime import datetime, UTC +from datetime import UTC, datetime from typing import Optional -from uuid import uuid4, UUID +from uuid import UUID, uuid4 + +from pydantic import BaseModel, Field class SavedSubmission(BaseModel): diff --git a/apps/api/src/rest/prompts/__init__.py b/apps/api/src/rest/prompts/__init__.py index 91ad6927..60e1a535 100644 --- a/apps/api/src/rest/prompts/__init__.py +++ b/apps/api/src/rest/prompts/__init__.py @@ -1,5 +1,12 @@ -from .relevance import calculate_relevance_prompt, purpose, ideal_customer_profile, context, good_examples, bad_examples from .commenting import generate_comment_prompt +from .relevance import ( + bad_examples, + calculate_relevance_prompt, + context, + good_examples, + ideal_customer_profile, + purpose, +) __all__ = [ "calculate_relevance_prompt", diff --git a/apps/api/src/rest/prompts/commenting.py b/apps/api/src/rest/prompts/commenting.py index 4bea145f..0e76dd8f 100644 --- a/apps/api/src/rest/prompts/commenting.py +++ b/apps/api/src/rest/prompts/commenting.py @@ -1,16 +1,21 @@ -from gptrim import trim import os +from gptrim import trim + # Get the directory of the current script file script_dir = os.path.dirname(os.path.realpath(__file__)) -with open(os.path.join(script_dir, "startino_business_plan.md"), "r", encoding='utf-8') as file: +with open( + os.path.join(script_dir, "startino_business_plan.md"), "r", encoding="utf-8" +) as file: company_context = file.read() -with open(os.path.join(script_dir, "good_comment_examples.md"), "r", encoding='utf-8') as file: +with open( + os.path.join(script_dir, "good_comment_examples.md"), "r", encoding="utf-8" +) as file: good_examples = file.read() -with open(os.path.join(script_dir, "bad_examples.md"), "r", encoding='utf-8') as file: +with open(os.path.join(script_dir, "bad_examples.md"), "r", encoding="utf-8") as file: bad_examples = file.read() purpose = """ @@ -53,7 +58,8 @@ writing comments that fulfill the purpose. """ -generate_comment_prompt = trim(f""" +generate_comment_prompt = trim( + f""" # INSTRUCTIONS {roleplay} # PURPOSE @@ -64,5 +70,5 @@ {context} # EXAMPLES {examples} -""") - +""" +) diff --git a/apps/api/src/rest/prompts/relevance.py b/apps/api/src/rest/prompts/relevance.py index f7ebafdc..c8152baf 100644 --- a/apps/api/src/rest/prompts/relevance.py +++ b/apps/api/src/rest/prompts/relevance.py @@ -1,16 +1,19 @@ -from gptrim import trim import os +from gptrim import trim + # Get the directory of the current script file script_dir = os.path.dirname(os.path.realpath(__file__)) -with open(os.path.join(script_dir, "startino_business_plan.md"), "r", encoding='utf-8') as file: +with open( + os.path.join(script_dir, "startino_business_plan.md"), "r", encoding="utf-8" +) as file: company_context = file.read() -with open(os.path.join(script_dir, "good_examples.md"), "r", encoding='utf-8') as file: +with open(os.path.join(script_dir, "good_examples.md"), "r", encoding="utf-8") as file: good_examples = file.read() -with open(os.path.join(script_dir, "bad_examples.md"), "r", encoding='utf-8') as file: +with open(os.path.join(script_dir, "bad_examples.md"), "r", encoding="utf-8") as file: bad_examples = file.read() purpose = """ @@ -70,7 +73,8 @@ relevant to look into for your boss. """ -calculate_relevance_prompt = trim(f""" +calculate_relevance_prompt = trim( + f""" # INSTRUCTIONS {roleplay} # PURPOSE @@ -85,5 +89,5 @@ {examples} -""") - +""" +) diff --git a/apps/api/src/rest/reddit_utils.py b/apps/api/src/rest/reddit_utils.py index 5190e1dc..f3d6182a 100644 --- a/apps/api/src/rest/reddit_utils.py +++ b/apps/api/src/rest/reddit_utils.py @@ -1,7 +1,8 @@ +import os + +from dotenv import load_dotenv from praw import Reddit from praw.models import Subreddits -from dotenv import load_dotenv -import os load_dotenv() diff --git a/apps/api/src/rest/reddit_worker.py b/apps/api/src/rest/reddit_worker.py index 20282fc4..15b74678 100644 --- a/apps/api/src/rest/reddit_worker.py +++ b/apps/api/src/rest/reddit_worker.py @@ -1,15 +1,15 @@ -from praw import Reddit -from praw.models import Subreddits, Submission import os -from dotenv import load_dotenv +from pathlib import Path from urllib.parse import quote_plus -import diskcache as dc -from pathlib import Path +import diskcache as dc +from dotenv import load_dotenv +from praw import Reddit +from praw.models import Submission, Subreddits +from .reddit_utils import get_reddit_instance, get_subreddits from .relevance_bot import evaluate_relevance from .saving import update_db_with_submission -from .reddit_utils import get_subreddits, get_reddit_instance load_dotenv() REDDIT_CLIENT_ID = os.getenv("REDDIT_CLIENT_ID") diff --git a/apps/api/src/rest/relevance_bot.py b/apps/api/src/rest/relevance_bot.py index 80f378f3..c8367ad9 100644 --- a/apps/api/src/rest/relevance_bot.py +++ b/apps/api/src/rest/relevance_bot.py @@ -1,21 +1,27 @@ +import os import time from typing import List -import os -from dotenv import load_dotenv +from dotenv import load_dotenv from gptrim import trim -from praw.models import Submission -from langchain_openai import ChatOpenAI -from langchain_core.prompts import PromptTemplate -from langchain_core.output_parsers import JsonOutputParser, PydanticOutputParser from langchain_community.callbacks import get_openai_callback +from langchain_core.output_parsers import JsonOutputParser, PydanticOutputParser +from langchain_core.prompts import PromptTemplate +from langchain_openai import ChatOpenAI +from praw.models import Submission -from .models import EvaluatedSubmission, RelevanceResult, FilterOutput, FilterQuestion -from .prompts import calculate_relevance_prompt, context as company_context, purpose -from .dummy_submissions import relevant_submissions, irrelevant_submissions -from .utils import majority_vote, calculate_certainty_from_bools +from .dummy_submissions import irrelevant_submissions, relevant_submissions from .logging_utils import log_relevance_calculation - +from .models import ( + EvaluatedSubmission, + FilterOutput, + FilterQuestion, + RelevanceResult, +) +from .prompts import calculate_relevance_prompt +from .prompts import context as company_context +from .prompts import purpose +from .utils import calculate_certainty_from_bools, majority_vote # Load Enviornment variables load_dotenv() @@ -77,8 +83,8 @@ def invoke_chain(chain, submission: Submission) -> tuple[RelevanceResult, float] time.sleep(10) # Wait for 10 seconds before trying again raise RuntimeError( - "Failed to invoke chain after 3 attempts. Most likely no more credits left or usage limit has been reached." -) + "Failed to invoke chain after 3 attempts. Most likely no more credits left or usage limit has been reached." + ) def summarize_submission(submission: Submission) -> Submission: diff --git a/apps/api/src/rest/saving.py b/apps/api/src/rest/saving.py index 066c2360..4e7f5125 100644 --- a/apps/api/src/rest/saving.py +++ b/apps/api/src/rest/saving.py @@ -1,9 +1,8 @@ import os from . import comment_bot -from .models import Lead from .interfaces import db -from .models import EvaluatedSubmission, SavedSubmission +from .models import EvaluatedSubmission, Lead, SavedSubmission # Get the current file's directory current_dir = os.path.dirname(os.path.realpath(__file__)) diff --git a/apps/api/src/rest/utils.py b/apps/api/src/rest/utils.py index 833d776a..6a758d41 100644 --- a/apps/api/src/rest/utils.py +++ b/apps/api/src/rest/utils.py @@ -1,16 +1,15 @@ - - from typing import List def majority_vote(bool_list: List[bool]) -> bool: return sum(bool_list) > len(bool_list) / 2 + def calculate_certainty_from_bools(bool_list: List[bool]) -> float: length = len(bool_list) total = sum(bool_list) - + true_certainty = total / length - false_certainty = (length-total) / length + false_certainty = (length - total) / length - return max(true_certainty, false_certainty) \ No newline at end of file + return max(true_certainty, false_certainty) diff --git a/apps/api/src/routers/agents.py b/apps/api/src/routers/agents.py index 4401c44d..e1ccdc68 100644 --- a/apps/api/src/routers/agents.py +++ b/apps/api/src/routers/agents.py @@ -5,10 +5,10 @@ from src.interfaces import db from src.models import ( - AgentInsertRequest, - AgentUpdateModel, Agent, AgentGetRequest, + AgentInsertRequest, + AgentUpdateModel, ) router = APIRouter( @@ -24,7 +24,7 @@ def get_agents(q: AgentGetRequest = Depends()) -> list[Agent]: response = db.get_agents(q.profile_id, q.crew_id, q.published) if not response: raise HTTPException(404, "crew not found or crew has no agents") - + return response @@ -46,9 +46,7 @@ def insert_agent(agent_request: AgentInsertRequest) -> Agent: @router.patch("/{agent_id}") -def patch_agent( - agent_id: UUID, agent_update_request: AgentUpdateModel -) -> Agent: +def patch_agent(agent_id: UUID, agent_update_request: AgentUpdateModel) -> Agent: if not db.get_agent(agent_id): raise HTTPException(404, "agent not found") diff --git a/apps/api/src/routers/api_key_types.py b/apps/api/src/routers/api_key_types.py index 6b31ecb4..a7017e52 100644 --- a/apps/api/src/routers/api_key_types.py +++ b/apps/api/src/routers/api_key_types.py @@ -4,9 +4,7 @@ from fastapi import APIRouter, HTTPException from src.interfaces import db -from src.models import ( - APIKeyType, -) +from src.models import APIKeyType router = APIRouter(prefix="/api-key-types", tags=["api key types"]) @@ -15,4 +13,4 @@ @router.get("/") def get_all_api_key_types() -> list[APIKeyType]: - return db.get_api_key_types() \ No newline at end of file + return db.get_api_key_types() diff --git a/apps/api/src/routers/api_keys.py b/apps/api/src/routers/api_keys.py index cb7babde..8c32f4e5 100644 --- a/apps/api/src/routers/api_keys.py +++ b/apps/api/src/routers/api_keys.py @@ -6,9 +6,9 @@ from src.interfaces import db from src.models import ( APIKey, + APIKeyGetRequest, APIKeyInsertRequest, APIKeyUpdateRequest, - APIKeyGetRequest, ) router = APIRouter(prefix="/api-keys", tags=["api keys"]) @@ -19,7 +19,7 @@ def get_api_keys(q: APIKeyGetRequest = Depends()) -> list[APIKey]: """Returns api keys with the api key type as an object with the id, name, description etc.""" if q.profile_id and not db.get_profile(q.profile_id): raise HTTPException(404, "profile not found") - + return db.get_api_keys(q.profile_id, q.api_key_type_id, q.api_key) @@ -40,6 +40,7 @@ def insert_api_key(api_key_request: APIKeyInsertRequest) -> APIKey: return response + @router.delete("/{api_key_id}") def delete_api_key(api_key_id: UUID) -> APIKey: deleted_key = db.delete_api_key(api_key_id) @@ -51,4 +52,4 @@ def delete_api_key(api_key_id: UUID) -> APIKey: @router.patch("/{api_key_id}") def update_api_key(api_key_id: UUID, api_key_update: APIKeyUpdateRequest) -> APIKey: - return db.update_api_key(api_key_id, api_key_update) \ No newline at end of file + return db.update_api_key(api_key_id, api_key_update) diff --git a/apps/api/src/routers/billing_information.py b/apps/api/src/routers/billing_information.py index d4e567ee..44f22b67 100644 --- a/apps/api/src/routers/billing_information.py +++ b/apps/api/src/routers/billing_information.py @@ -10,11 +10,7 @@ rate_limit_tiered, ) from src.interfaces import db -from src.models import ( - Billing, - BillingInsertRequest, - BillingUpdateRequest, -) +from src.models import Billing, BillingInsertRequest, BillingUpdateRequest router = APIRouter(prefix="/billing", tags=["billings"]) @@ -51,4 +47,3 @@ def update_billing(profile_id: UUID, content: BillingUpdateRequest) -> Billing: raise HTTPException(404, "message not found") return response - diff --git a/apps/api/src/routers/crews.py b/apps/api/src/routers/crews.py index 3a18cc29..a837b48a 100644 --- a/apps/api/src/routers/crews.py +++ b/apps/api/src/routers/crews.py @@ -4,7 +4,12 @@ from fastapi import APIRouter, Depends, HTTPException from src.interfaces import db -from src.models import CrewInsertRequest, Crew, CrewUpdateRequest, CrewGetRequest +from src.models import ( + Crew, + CrewGetRequest, + CrewInsertRequest, + CrewUpdateRequest, +) router = APIRouter( prefix="/crews", diff --git a/apps/api/src/routers/messages.py b/apps/api/src/routers/messages.py index 2c2ab76e..62fa88ae 100644 --- a/apps/api/src/routers/messages.py +++ b/apps/api/src/routers/messages.py @@ -2,6 +2,7 @@ from uuid import UUID from fastapi import APIRouter, Depends, HTTPException +from postgrest.exceptions import APIError from src.dependencies import ( RateLimitResponse, @@ -10,8 +11,12 @@ rate_limit_tiered, ) from src.interfaces import db -from src.models import Message, MessageInsertRequest, Message, MessageUpdateRequest, MessageGetRequest -from postgrest.exceptions import APIError +from src.models import ( + Message, + MessageGetRequest, + MessageInsertRequest, + MessageUpdateRequest, +) router = APIRouter(prefix="/messages", tags=["messages"]) @@ -33,7 +38,7 @@ def delete_message(message_id: UUID) -> Message: response = db.delete_message(message_id) if not response: raise HTTPException(404, "message not found") - + return response @@ -51,5 +56,5 @@ def get_message(message_id: UUID) -> Message: response = db.get_message(message_id) if not response: raise HTTPException(404, "message not found") - - return response \ No newline at end of file + + return response diff --git a/apps/api/src/routers/profiles.py b/apps/api/src/routers/profiles.py index e59dcced..e2540dc3 100644 --- a/apps/api/src/routers/profiles.py +++ b/apps/api/src/routers/profiles.py @@ -6,9 +6,9 @@ from src.interfaces import db from src.models import ( Profile, - ProfileUpdateRequest, + ProfileGetRequest, ProfileInsertRequest, - ProfileGetRequest + ProfileUpdateRequest, ) router = APIRouter(prefix="/profiles", tags=["profiles"]) @@ -31,7 +31,7 @@ def get_profile_by_id(profile_id: UUID) -> Profile: raise HTTPException(404, "profile not found") return profile - + @router.delete("/{profile_id}") def delete_profile(profile_id: UUID) -> Profile: @@ -46,4 +46,3 @@ def update_profile( raise HTTPException(404, "profile not found") return db.update_profile(profile_id, profile_update_request) - diff --git a/apps/api/src/routers/rest.py b/apps/api/src/routers/rest.py index 2e2dd201..fa928c59 100644 --- a/apps/api/src/routers/rest.py +++ b/apps/api/src/routers/rest.py @@ -1,26 +1,24 @@ -import os -from dotenv import load_dotenv import logging -import diskcache as dc +import os import threading from uuid import uuid4 -from src.rest.saving import update_db_with_submission -from src.rest import mail -from src.rest.reddit_utils import get_subreddits -from src.rest.relevance_bot import evaluate_relevance +import diskcache as dc +from dotenv import load_dotenv +from fastapi import APIRouter, HTTPException +from fastapi.responses import RedirectResponse + +from src.rest import comment_bot, mail from src.rest.interfaces import db -from src.rest import comment_bot from src.rest.models import ( - PublishCommentRequest, - GenerateCommentRequest, FalseLead, + GenerateCommentRequest, + PublishCommentRequest, ) +from src.rest.reddit_utils import get_subreddits from src.rest.reddit_worker import RedditStreamWorker - -from fastapi import APIRouter, HTTPException -from fastapi.responses import RedirectResponse - +from src.rest.relevance_bot import evaluate_relevance +from src.rest.saving import update_db_with_submission # Relevant subreddits to Startino SUBREDDIT_NAMES = ( diff --git a/apps/api/src/routers/sessions.py b/apps/api/src/routers/sessions.py index bb161b88..b928e69b 100644 --- a/apps/api/src/routers/sessions.py +++ b/apps/api/src/routers/sessions.py @@ -1,5 +1,5 @@ -from datetime import UTC, datetime import logging +from datetime import UTC, datetime from typing import cast from uuid import UUID, uuid4 @@ -15,19 +15,18 @@ ) from src.interfaces import db from src.models import ( - CrewProcessed, Crew, + CrewProcessed, Message, - SessionRunRequest, - SessionRunResponse, Session, - Session, - SessionUpdateRequest, SessionGetRequest, + SessionRunRequest, + SessionRunResponse, SessionStatus, + SessionUpdateRequest, ) from src.models.session import SessionInsertRequest -from src.parser import process_crew, get_processed_crew_by_id +from src.parser import get_processed_crew_by_id, process_crew router = APIRouter( prefix="/sessions", @@ -38,9 +37,7 @@ @router.get("/") -def get_sessions( - q: SessionGetRequest = Depends() -) -> list[Session]: +def get_sessions(q: SessionGetRequest = Depends()) -> list[Session]: return db.get_sessions(q.profile_id, q.crew_id, q.title, q.status) @@ -49,13 +46,13 @@ def get_session(session_id: UUID) -> Session: response = db.get_session(session_id) if response is None: raise HTTPException(500, "failed validation") - # not sure if 500 is correct, but this is failed validation on the returned data, so + # not sure if 500 is correct, but this is failed validation on the returned data, so # it makes sense in my mind to raise a server error for that - + return response # pretty sure this response object will always be a session, so casting it to stop typing errors - - + + @router.patch("/{session_id}") def update_session(session_id: UUID, content: SessionUpdateRequest) -> Session: return db.update_session(session_id, content) @@ -131,7 +128,7 @@ async def run_crew( title=request.session_title, reply="", last_opened_at=datetime.now(tz=UTC), - status=SessionStatus.RUNNING + status=SessionStatus.RUNNING, ) db.post_session(session) @@ -149,7 +146,7 @@ async def on_reply( sender_id=sender_id, content=content, role=role, - created_at=datetime.now(tz=UTC) + created_at=datetime.now(tz=UTC), ) logger.debug(f"on_reply: {message}") db.post_message(message) diff --git a/apps/api/src/routers/subscriptions.py b/apps/api/src/routers/subscriptions.py index 1f13b926..d8e73b08 100644 --- a/apps/api/src/routers/subscriptions.py +++ b/apps/api/src/routers/subscriptions.py @@ -12,9 +12,9 @@ from src.interfaces import db from src.models import ( Subscription, + SubscriptionGetRequest, SubscriptionInsertRequest, SubscriptionUpdateRequest, - SubscriptionGetRequest, ) router = APIRouter(prefix="/subscriptions", tags=["subscriptions"]) @@ -50,4 +50,3 @@ def update_subscription( raise HTTPException(404, "message not found") return response - diff --git a/apps/api/src/routers/tiers.py b/apps/api/src/routers/tiers.py index 3eb0ff83..a6de01ac 100644 --- a/apps/api/src/routers/tiers.py +++ b/apps/api/src/routers/tiers.py @@ -12,9 +12,9 @@ from src.interfaces import db from src.models import ( Tier, + TierGetRequest, TierInsertRequest, TierUpdateRequest, - TierGetRequest, ) router = APIRouter(prefix="/tiers", tags=["tiers"]) diff --git a/apps/api/src/routers/tools.py b/apps/api/src/routers/tools.py index a85c6eb8..eb430fd4 100644 --- a/apps/api/src/routers/tools.py +++ b/apps/api/src/routers/tools.py @@ -17,6 +17,7 @@ tags=["tools"], ) + @router.get("/") def get_tools(q: ToolGetRequest = Depends()) -> list[Tool]: return db.get_tools(q.name, q.api_key_type_id) @@ -27,7 +28,7 @@ def get_tool(tool_id: UUID) -> Tool: response = db.get_tool(tool_id) if not response: raise HTTPException(404, "tool not found") - + return response @@ -41,14 +42,12 @@ def delete_tool(tool_id: UUID) -> Tool: response = db.delete_tool(tool_id) if not response: raise HTTPException(404, "could not find tool") - + return response @router.patch("/{tool_id}") -def update_profile( - tool_id: UUID, tool_update_request: ToolUpdateRequest -) -> Tool: +def update_profile(tool_id: UUID, tool_update_request: ToolUpdateRequest) -> Tool: if not db.get_tool(tool_id): raise HTTPException(404, "tool not found") diff --git a/apps/api/src/tools/__init__.py b/apps/api/src/tools/__init__.py index 2d792261..3762d235 100644 --- a/apps/api/src/tools/__init__.py +++ b/apps/api/src/tools/__init__.py @@ -3,8 +3,8 @@ import os import random from typing import Any -from dotenv import load_dotenv +from dotenv import load_dotenv from langchain_core.tools import BaseTool from src.tools.alpha_vantage import ID as ALPHA_VANTAGE_TOOL_ID @@ -13,24 +13,23 @@ from src.tools.arxiv_tool import ArxivTool from src.tools.bing import ID as BING_SEARCH_TOOL_ID from src.tools.bing import BingTool +from src.tools.brave_search import ID as BRAVE_TOOL_ID +from src.tools.brave_search import BraveSearchTool +from src.tools.duckduckgo_tool import ID as DDGS_TOOL_ID +from src.tools.duckduckgo_tool import DuckDuckGoSearchTool +from src.tools.google_serper import RESULTS_ID as GOOGLE_SERPER_RESULTS_TOOL_ID +from src.tools.google_serper import RUN_ID as GOOGLE_SERPER_RUN_TOOL_ID +from src.tools.google_serper import GoogleSerperResultsTool, GoogleSerperRunTool from src.tools.move_file import ID as MOVE_TOOL_ID from src.tools.move_file import MoveFileTool from src.tools.read_file import ID as READ_TOOL_ID from src.tools.read_file import ReadFileTool from src.tools.scraper import ID as SCRAPER_TOOL_ID from src.tools.scraper import ScraperTool -from src.tools.wikipedia_tool import ID as WIKIPEDIA_TOOL_ID -from src.tools.wikipedia_tool import WikipediaTool -from src.tools.duckduckgo_tool import ID as DDGS_TOOL_ID -from src.tools.duckduckgo_tool import DuckDuckGoSearchTool -from src.tools.google_serper import RUN_ID as GOOGLE_SERPER_RUN_TOOL_ID -from src.tools.google_serper import GoogleSerperRunTool -from src.tools.google_serper import RESULTS_ID as GOOGLE_SERPER_RESULTS_TOOL_ID -from src.tools.google_serper import GoogleSerperResultsTool -from src.tools.brave_search import ID as BRAVE_TOOL_ID -from src.tools.brave_search import BraveSearchTool from src.tools.stackapi_tool import ID as STACKAPI_ID from src.tools.stackapi_tool import StackAPISearchTool +from src.tools.wikipedia_tool import ID as WIKIPEDIA_TOOL_ID +from src.tools.wikipedia_tool import WikipediaTool tools: dict = { ARXIV_TOOL_ID: ArxivTool, @@ -51,7 +50,7 @@ load_dotenv() -def get_file_path_of_example(): +def get_file_path_of_example() -> str: current_dir = os.getcwd() target_folder = os.path.join(current_dir, "src/tools/test_files") @@ -83,14 +82,14 @@ def get_tool_ids_from_agent(tools: list[dict[str, Any]]) -> list[str]: return [tool["id"] for tool in tools] -def has_param(cls, param_name): +def has_param(cls, param_name) -> bool: init_signature = inspect.signature(cls.__init__) return param_name in init_signature.parameters def generate_tool_from_uuid( tool: str, api_key_types: dict[str, str], api_keys: dict[str, str] -): +) -> BaseTool | None: for tool_id in tools: if tool_id == tool: tool_key_type = "" diff --git a/apps/api/src/tools/alpha_vantage.py b/apps/api/src/tools/alpha_vantage.py index 137cd34d..69a7a061 100644 --- a/apps/api/src/tools/alpha_vantage.py +++ b/apps/api/src/tools/alpha_vantage.py @@ -21,7 +21,7 @@ class AlphaVantageToolInput(BaseModel): class AlphaVantageTool(Tool, BaseTool): args_schema: Type[BaseModel] = AlphaVantageToolInput - def __init__(self, api_key): + def __init__(self, api_key: str) -> None: alpha_vantage = AlphaVantageAPIWrapper(alphavantage_api_key=api_key) super().__init__( name="alpha_vantage_tool", diff --git a/apps/api/src/tools/arxiv_tool.py b/apps/api/src/tools/arxiv_tool.py index 1caf2ff3..54bae5c1 100644 --- a/apps/api/src/tools/arxiv_tool.py +++ b/apps/api/src/tools/arxiv_tool.py @@ -18,7 +18,7 @@ class ArxivToolInput(BaseModel): class ArxivTool(Tool, BaseTool): args_schema: Type[BaseModel] = ArxivToolInput - def __init__(self): + def __init__(self) -> None: super().__init__( name="arxiv_tool", func=arxiv.run, @@ -27,6 +27,3 @@ def __init__(self): __all__ = ["ArxivTool"] - - - diff --git a/apps/api/src/tools/bing.py b/apps/api/src/tools/bing.py index a6a80912..97ffe3ae 100644 --- a/apps/api/src/tools/bing.py +++ b/apps/api/src/tools/bing.py @@ -2,25 +2,31 @@ from typing import Type from dotenv import load_dotenv -from langchain_community.tools import BingSearchRun -from langchain_community.utilities import BingSearchAPIWrapper from langchain.agents import Tool from langchain.pydantic_v1 import BaseModel, Field from langchain.tools import BaseTool +from langchain_community.tools import BingSearchRun from langchain_community.tools.bing_search.tool import BingSearchRun +from langchain_community.utilities import BingSearchAPIWrapper from langchain_community.utilities.bing_search import BingSearchAPIWrapper # TODO: Split this tool into 2 different tools, like I did with the Google Serper tool, so a BingSearchRun and a BingSearchResults -BING_SEARCH_URL="https://api.bing.microsoft.com/v7.0/search" +BING_SEARCH_URL = "https://api.bing.microsoft.com/v7.0/search" ID = "71e4ddcc-4475-46f2-9816-894173b1292e" class BingToolInput(BaseModel): - tool_input: str = Field(title="Query", description="Search query input to search bing") + tool_input: str = Field( + title="Query", description="Search query input to search bing" + ) - nr_of_results: int = Field(title="Number of results", description="The amount of returned results from the search", default=5) + nr_of_results: int = Field( + title="Number of results", + description="The amount of returned results from the search", + default=5, + ) class BingTool(Tool, BaseTool): @@ -28,7 +34,7 @@ class BingTool(Tool, BaseTool): api_key: str = "" # needs to be empty string or it throws validation errors - def __init__(self, api_key): + def __init__(self, api_key: str) -> None: super().__init__( name="bing_search", func=self._run, @@ -37,8 +43,8 @@ def __init__(self, api_key): Input should be a search query.""", ) self.api_key = api_key - - def _run(self, tool_input: str, nr_of_results: int = 5): + + def _run(self, tool_input: str, nr_of_results: int = 5) -> str: wrapper = BingSearchAPIWrapper( bing_subscription_key=self.api_key, bing_search_url=BING_SEARCH_URL, diff --git a/apps/api/src/tools/brave_search.py b/apps/api/src/tools/brave_search.py index 7cbad0dd..0bca14b0 100644 --- a/apps/api/src/tools/brave_search.py +++ b/apps/api/src/tools/brave_search.py @@ -20,7 +20,7 @@ class BraveSearchToolInput(BaseModel): class BraveSearchTool(Tool, BaseTool): args_schema: Type[BaseModel] = BraveSearchToolInput - def __init__(self, api_key): + def __init__(self, api_key: str) -> None: tool = BraveSearch.from_api_key(api_key=api_key, search_kwargs={"count": 3}) super().__init__( name="brave_search", diff --git a/apps/api/src/tools/duckduckgo_tool.py b/apps/api/src/tools/duckduckgo_tool.py index 232bf0cf..dc794abe 100644 --- a/apps/api/src/tools/duckduckgo_tool.py +++ b/apps/api/src/tools/duckduckgo_tool.py @@ -4,13 +4,16 @@ from langchain.agents import Tool from langchain.pydantic_v1 import BaseModel, Field from langchain.tools import BaseTool -from langchain_community.utilities.duckduckgo_search import DuckDuckGoSearchAPIWrapper from langchain_community.tools import DuckDuckGoSearchRun +from langchain_community.utilities.duckduckgo_search import ( + DuckDuckGoSearchAPIWrapper, +) -ID="7dc53d81-cdac-4320-8077-1a7ab9497551" +ID = "7dc53d81-cdac-4320-8077-1a7ab9497551" logger = logging.getLogger("root") + class DuckDuckGoSearchToolInput(BaseModel): tool_input: str = Field( title="query", description="Search query input to look up on duck duck go" @@ -19,25 +22,29 @@ class DuckDuckGoSearchToolInput(BaseModel): title="region", description="Region to use for the search", default="wt-wt" ) source: str = Field( - title="source", description="Source of information, ex 'text' or 'news'", default="text" + title="source", + description="Source of information, ex 'text' or 'news'", + default="text", ) class DuckDuckGoSearchTool(Tool, BaseTool): args_schema: Type[BaseModel] = DuckDuckGoSearchToolInput - def __init__(self): + def __init__(self) -> None: super().__init__( name="duck_duck_go_search", func=self._run, description="""search the internet through the search engine duck duck go""", ) - - def _run(self, tool_input: str, region: str = "wt-wt", source: str = "text") -> Callable: + + def _run( + self, tool_input: str, region: str = "wt-wt", source: str = "text" + ) -> str: """Method passed to agent so the agent can initialize the wrapper with additional args""" logger.debug("Creating DuckDuckGo wrapper") ddgs_tool = DuckDuckGoSearchRun( wrapper=DuckDuckGoSearchAPIWrapper(region=region, source=source) ) - return ddgs_tool.run(tool_input=tool_input) \ No newline at end of file + return ddgs_tool.run(tool_input=tool_input) diff --git a/apps/api/src/tools/google_serper.py b/apps/api/src/tools/google_serper.py index 37980c71..3319aec4 100644 --- a/apps/api/src/tools/google_serper.py +++ b/apps/api/src/tools/google_serper.py @@ -6,19 +6,30 @@ from langchain.tools import BaseTool from langchain_community.utilities.google_serper import GoogleSerperAPIWrapper -RUN_ID="3e2665a8-6d73-42ee-a64f-50ddcc0621c6" +RUN_ID = "3e2665a8-6d73-42ee-a64f-50ddcc0621c6" -RESULTS_ID="1046fefb-a540-498f-8b96-7292523559e0" +RESULTS_ID = "1046fefb-a540-498f-8b96-7292523559e0" logger = logging.getLogger("root") + class GoogleSerperRunToolInput(BaseModel): - query: str = Field(title="query", description="search query input, looks up on google search") + query: str = Field( + title="query", description="search query input, looks up on google search" + ) + class GoogleSerperResultsToolInput(BaseModel): - query: str = Field(title="query", description="search query input, looks up on google search and returns metadata") + query: str = Field( + title="query", + description="search query input, looks up on google search and returns metadata", + ) - nr_of_results: int = Field(title="number of results", description="number of results shown per page", default=10) + nr_of_results: int = Field( + title="number of results", + description="number of results shown per page", + default=10, + ) region: str = Field( title="region", @@ -27,7 +38,7 @@ class GoogleSerperResultsToolInput(BaseModel): ) language: str = Field( title="language", - description="sets the interface language of the search, given as a two letter code, for example English is 'en' and french is 'fr'", + description="sets the interface language of the search, given as a two letter code, for example English is 'en' and french is 'fr'", default="en", ) search_type: Literal["news", "search", "places", "images"] = Field( @@ -44,8 +55,8 @@ class GoogleSerperResultsToolInput(BaseModel): class GoogleSerperRunTool(Tool, BaseTool): args_schema: Type[BaseModel] = GoogleSerperRunToolInput - - def __init__(self, api_key): + + def __init__(self, api_key: str) -> None: search = GoogleSerperAPIWrapper(serper_api_key=api_key) super().__init__( name="google_serper_run_tool", @@ -53,12 +64,12 @@ def __init__(self, api_key): description="""search the web with serper's google search api""", ) - + class GoogleSerperResultsTool(Tool, BaseTool): args_schema: Type[BaseModel] = GoogleSerperResultsToolInput api_key: str = "" - def __init__(self, api_key): + def __init__(self, api_key: str) -> None: super().__init__( name="google_serper_results_tool", func=self._run, @@ -69,22 +80,21 @@ def __init__(self, api_key): def _run( self, query: str, - nr_of_results: int = 10, - region: str = "us", + nr_of_results: int = 10, + region: str = "us", language: str = "en", - search_type: Literal["news", "search", "places", "images"] = "search", + search_type: Literal["news", "search", "places", "images"] = "search", time_based_search: str | None = None, - ): + ) -> dict: """Method passed to the agent to allow it to pass additional optional parameters, similar to the DDG search tool""" search = GoogleSerperAPIWrapper( serper_api_key=self.api_key, - k=nr_of_results, - gl=region, - hl=language, - type=search_type, - tbs=time_based_search + k=nr_of_results, + gl=region, + hl=language, + type=search_type, + tbs=time_based_search, ) - return search.results(query) - \ No newline at end of file + return search.results(query) diff --git a/apps/api/src/tools/scraper.py b/apps/api/src/tools/scraper.py index 454b7c23..b78991fa 100644 --- a/apps/api/src/tools/scraper.py +++ b/apps/api/src/tools/scraper.py @@ -22,7 +22,7 @@ class ScraperToolInput(BaseModel): class ScraperTool(Tool, BaseTool): args_schema: Type[BaseModel] = ScraperToolInput - def __init__(self, api_key): + def __init__(self, api_key: str) -> None: web_scrape = SerpAPIWrapper(serpapi_api_key=api_key) super().__init__( name="scraper_tool", diff --git a/apps/api/src/tools/stackapi_tool.py b/apps/api/src/tools/stackapi_tool.py index 858a70c7..c5249281 100644 --- a/apps/api/src/tools/stackapi_tool.py +++ b/apps/api/src/tools/stackapi_tool.py @@ -4,8 +4,8 @@ from langchain.agents import Tool from langchain.pydantic_v1 import BaseModel, Field from langchain.tools import BaseTool -from langchain_community.utilities import StackExchangeAPIWrapper from langchain_community.tools.stackexchange.tool import StackExchangeTool +from langchain_community.utilities import StackExchangeAPIWrapper ID = "612ddae6-ecdd-4900-9314-1a2c9de6003d" @@ -21,7 +21,7 @@ class StackAPIToolInput(BaseModel): class StackAPISearchTool(Tool, BaseTool): args_schema: Type[BaseModel] = StackAPIToolInput - def __init__(self): + def __init__(self) -> None: tool = StackExchangeTool(api_wrapper=StackExchangeAPIWrapper()) super().__init__( name="stack_api_tool", diff --git a/apps/api/src/tools/wikipedia_tool.py b/apps/api/src/tools/wikipedia_tool.py index 2b402b10..a88e1014 100644 --- a/apps/api/src/tools/wikipedia_tool.py +++ b/apps/api/src/tools/wikipedia_tool.py @@ -18,7 +18,7 @@ class WikipediaToolInput(BaseModel): class WikipediaTool(Tool, BaseTool): args_schema: Type[BaseModel] = WikipediaToolInput - def __init__(self): + def __init__(self) -> None: wiki_tool = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper()) super().__init__( name="wikipedia", From 3dc7a545b3b7d8a8698b154f5435b85aa459299e Mon Sep 17 00:00:00 2001 From: Leon Nilsson <70595163+failandimprove1@users.noreply.github.com> Date: Thu, 18 Apr 2024 10:23:23 +0200 Subject: [PATCH 23/76] Add prompt type and fix typing of edges (#209) --- apps/api/src/models/crew_model.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/api/src/models/crew_model.py b/apps/api/src/models/crew_model.py index 08c99efe..83dd1da2 100644 --- a/apps/api/src/models/crew_model.py +++ b/apps/api/src/models/crew_model.py @@ -8,6 +8,10 @@ from .agent_model import Agent from .edge import Edge +class Prompt(BaseModel): + id: UUID + title: str + content: str class CrewProcessed(BaseModel): receiver_id: UUID @@ -30,14 +34,14 @@ class Crew(BaseModel): nodes: list[UUID] receiver_id: UUID | None = None avatar: str | None = None - prompt: dict | None = None + prompt: Prompt | None = None class CrewInsertRequest(BaseModel): receiver_id: UUID - prompt: dict + prompt: Prompt profile_id: UUID - edges: list[dict] + edges: list[Edge] published: bool title: str description: str @@ -46,9 +50,9 @@ class CrewInsertRequest(BaseModel): class CrewUpdateRequest(BaseModel): receiver_id: UUID | None = None - prompt: dict | None = None + prompt: Prompt | None = None profile_id: UUID | None = None - edges: list[dict] | None = None + edges: list[Edge] | None = None published: bool | None = None title: str | None = None description: str | None = None From f47784987d4b43140100183a6b2ac41486bf7255 Mon Sep 17 00:00:00 2001 From: Jonas Lindberg Date: Thu, 18 Apr 2024 11:34:17 +0200 Subject: [PATCH 24/76] Mostly implement OpenAPI fetch (#208) * remove past gen folder * packages * tsconfig * remove client * remove api.ts * create client * api things * sessions working like before with new system * update more from sessions to be using new system, SessionNavigator is working again * convert more to new system * update api types * work on converting crews to use api * update api types * work on converting crews * crews working I think * prep for tomorrow * partially convert api keys to new system * ts * correct type * validate session in hook * uncomment thing I'm gonna work on * api keys working I think * update api schema * work on converting sessions to using new system * fixup api interactions with new api schema * api keys kebab case * get api keys working again again and work on sessions * update api schema * working on crews * delete blog * finalize delete blog * work on crew * update api types * crews page is running at least now * remove unused var * fix sonarcloud issue * format * ignore generated file from prettier * please stop crying sonarcloud --- apps/api/src/parser.py | 8 +- apps/web/.env.example | 3 - apps/web/.prettierignore | 1 + apps/web/generated/core/ApiError.ts | 25 - apps/web/generated/core/ApiRequestOptions.ts | 17 - apps/web/generated/core/ApiResult.ts | 11 - apps/web/generated/core/CancelablePromise.ts | 131 - apps/web/generated/core/OpenAPI.ts | 32 - apps/web/generated/core/request.ts | 322 --- apps/web/generated/index.ts | 56 - .../generated/models/APIKeyRequestModel.ts | 10 - .../generated/models/APIKeyResponseModel.ts | 13 - apps/web/generated/models/APIKeyTypeModel.ts | 11 - .../models/APIKeyTypeResponseModel.ts | 11 - .../web/generated/models/APIKeyUpdateModel.ts | 8 - apps/web/generated/models/AgentModel.ts | 19 - .../web/generated/models/AgentRequestModel.ts | 22 - .../generated/models/AgentResponseModel.ts | 25 - apps/web/generated/models/AgentUpdateModel.ts | 16 - apps/web/generated/models/AuthResponse.ts | 11 - apps/web/generated/models/CrewModel.ts | 12 - apps/web/generated/models/CrewRequestModel.ts | 15 - .../web/generated/models/CrewResponseModel.ts | 19 - apps/web/generated/models/CrewUpdateModel.ts | 15 - apps/web/generated/models/Factor.ts | 22 - .../generated/models/HTTPValidationError.ts | 9 - apps/web/generated/models/Message.ts | 15 - apps/web/generated/models/OAuthResponse.ts | 32 - .../generated/models/ProfileRequestModel.ts | 11 - .../generated/models/ProfileResponseModel.ts | 12 - .../generated/models/ProfileUpdateModel.ts | 10 - apps/web/generated/models/RunRequestModel.ts | 12 - apps/web/generated/models/RunResponseModel.ts | 10 - apps/web/generated/models/SessionRequest.ts | 10 - apps/web/generated/models/SessionResponse.ts | 14 - apps/web/generated/models/SessionStatus.ts | 9 - apps/web/generated/models/SessionUpdate.ts | 12 - .../SignInWithEmailAndPasswordCredentials.ts | 11 - .../models/SignInWithOAuthCredentials.ts | 33 - .../SignInWithOAuthCredentialsOptions.ts | 10 - .../SignInWithPasswordCredentialsOptions.ts | 9 - .../SignUpWithEmailAndPasswordCredentials.ts | 11 - ...pWithEmailAndPasswordCredentialsOptions.ts | 10 - apps/web/generated/models/User.ts | 30 - apps/web/generated/models/UserIdentity.ts | 14 - apps/web/generated/models/ValidationError.ts | 10 - .../models/gotrue__types__Session.ts | 16 - .../models/src__models__session__Session.ts | 14 - apps/web/generated/services/AgentsService.ts | 146 - .../generated/services/ApiKeyTypesService.ts | 21 - .../services/AuthenticationService.ts | 72 - apps/web/generated/services/CrewsService.ts | 109 - apps/web/generated/services/DefaultService.ts | 107 - .../web/generated/services/MessagesService.ts | 30 - .../web/generated/services/ProfilesService.ts | 173 -- .../web/generated/services/SessionsService.ts | 146 - apps/web/package.json | 2 + apps/web/pnpm-lock.yaml | 344 +-- apps/web/src/app.d.ts | 2 +- apps/web/src/hooks.server.ts | 4 +- apps/web/src/lib/api.ts | 98 - apps/web/src/lib/api/index.ts | 14 + apps/web/src/lib/api/v0.d.ts | 2353 +++++++++++++++++ apps/web/src/lib/client/core/ApiError.ts | 25 - .../src/lib/client/core/ApiRequestOptions.ts | 17 - apps/web/src/lib/client/core/ApiResult.ts | 11 - .../src/lib/client/core/CancelablePromise.ts | 131 - apps/web/src/lib/client/core/OpenAPI.ts | 33 - apps/web/src/lib/client/core/request.ts | 322 --- apps/web/src/lib/client/index.ts | 56 - .../lib/client/models/APIKeyRequestModel.ts | 10 - .../lib/client/models/APIKeyResponseModel.ts | 13 - .../src/lib/client/models/APIKeyTypeModel.ts | 11 - .../client/models/APIKeyTypeResponseModel.ts | 11 - .../lib/client/models/APIKeyUpdateModel.ts | 8 - apps/web/src/lib/client/models/AgentModel.ts | 19 - .../lib/client/models/AgentRequestModel.ts | 22 - .../lib/client/models/AgentResponseModel.ts | 25 - .../src/lib/client/models/AgentUpdateModel.ts | 16 - .../web/src/lib/client/models/AuthResponse.ts | 11 - apps/web/src/lib/client/models/CrewModel.ts | 12 - .../src/lib/client/models/CrewRequestModel.ts | 15 - .../lib/client/models/CrewResponseModel.ts | 19 - .../src/lib/client/models/CrewUpdateModel.ts | 15 - apps/web/src/lib/client/models/Factor.ts | 22 - .../lib/client/models/HTTPValidationError.ts | 9 - apps/web/src/lib/client/models/Message.ts | 15 - .../src/lib/client/models/OAuthResponse.ts | 32 - .../lib/client/models/ProfileRequestModel.ts | 11 - .../lib/client/models/ProfileResponseModel.ts | 12 - .../lib/client/models/ProfileUpdateModel.ts | 10 - .../src/lib/client/models/RunRequestModel.ts | 12 - .../src/lib/client/models/RunResponseModel.ts | 10 - .../src/lib/client/models/SessionRequest.ts | 10 - .../src/lib/client/models/SessionResponse.ts | 14 - .../src/lib/client/models/SessionStatus.ts | 9 - .../src/lib/client/models/SessionUpdate.ts | 12 - .../SignInWithEmailAndPasswordCredentials.ts | 11 - .../models/SignInWithOAuthCredentials.ts | 33 - .../SignInWithOAuthCredentialsOptions.ts | 10 - .../SignInWithPasswordCredentialsOptions.ts | 9 - .../SignUpWithEmailAndPasswordCredentials.ts | 11 - ...pWithEmailAndPasswordCredentialsOptions.ts | 10 - apps/web/src/lib/client/models/User.ts | 30 - .../web/src/lib/client/models/UserIdentity.ts | 14 - .../src/lib/client/models/ValidationError.ts | 10 - .../client/models/gotrue__types__Session.ts | 16 - .../models/src__models__session__Session.ts | 14 - .../src/lib/client/services/AgentsService.ts | 146 - .../lib/client/services/ApiKeyTypesService.ts | 21 - .../client/services/AuthenticationService.ts | 72 - .../src/lib/client/services/CrewsService.ts | 109 - .../src/lib/client/services/DefaultService.ts | 107 - .../lib/client/services/MessagesService.ts | 30 - .../lib/client/services/ProfilesService.ts | 173 -- .../lib/client/services/SessionsService.ts | 146 - .../lib/components/RightEditorSidebar.svelte | 2 +- .../ui/community-details/agent-row.svelte | 11 +- .../ui/library/agent-library.svelte | 47 +- .../ui/prompt-editor/prompt-editor.svelte | 44 +- .../web/src/lib/components/ui/select/index.ts | 14 +- .../ui/select/select-content.svelte | 22 +- .../components/ui/select/select-item.svelte | 16 +- .../components/ui/select/select-label.svelte | 8 +- .../ui/select/select-separator.svelte | 8 +- .../ui/select/select-trigger.svelte | 10 +- .../components/ui/side-nav/side-nav.svelte | 8 +- apps/web/src/lib/server/blog/index.ts | 136 - apps/web/src/lib/server/blog/types.d.ts | 29 - apps/web/src/lib/server/env.ts | 20 - apps/web/src/lib/types/index.ts | 15 +- apps/web/src/lib/types/loads.ts | 37 - apps/web/src/lib/types/models.ts | 53 - .../blog/(blog-article)/+layout.svelte | 9 - .../blog/(blog-article)/+layout.ts | 5 - .../(blog-article)/[slug]/+page.server.ts | 17 - .../blog/(blog-article)/[slug]/+page.svelte | 67 - .../routes/(marketing)/blog/+layout.svelte | 5 - .../routes/(marketing)/blog/+page.server.ts | 9 - .../src/routes/(marketing)/blog/+page.svelte | 82 - apps/web/src/routes/+error.svelte | 8 +- apps/web/src/routes/app/+layout.server.ts | 3 +- apps/web/src/routes/app/account/+page.svelte | 2 +- .../app/account/api-keys/+page.server.ts | 83 +- .../routes/app/account/api-keys/+page.svelte | 8 +- .../app/account/subscription/+page.svelte | 2 +- .../src/routes/app/agents/editor/+page.svelte | 6 +- apps/web/src/routes/app/crews/+page.server.ts | 47 +- apps/web/src/routes/app/crews/+page.svelte | 2 +- .../src/routes/app/crews/[id]/+layout.svelte | 7 - .../src/routes/app/crews/[id]/+page.server.ts | 205 +- .../src/routes/app/crews/[id]/+page.svelte | 269 +- .../routes/app/crews/[id]/CrewPanel.svelte | 179 ++ .../src/routes/app/session/+page.server.ts | 80 +- apps/web/src/routes/app/session/+page.svelte | 63 +- .../routes/app/session/[slug]/+page.server.ts | 140 +- .../routes/app/session/[slug]/+page.svelte | 22 +- .../src/routes/app/session/[slug]/Chat.svelte | 18 +- .../routes/app/session/[slug]/Message.svelte | 14 +- .../session/[slug]/SessionNavigator.svelte | 62 +- apps/web/theme/typography.cjs | 20 - apps/web/tsconfig.json | 1 + 162 files changed, 3285 insertions(+), 5362 deletions(-) delete mode 100644 apps/web/.env.example delete mode 100644 apps/web/generated/core/ApiError.ts delete mode 100644 apps/web/generated/core/ApiRequestOptions.ts delete mode 100644 apps/web/generated/core/ApiResult.ts delete mode 100644 apps/web/generated/core/CancelablePromise.ts delete mode 100644 apps/web/generated/core/OpenAPI.ts delete mode 100644 apps/web/generated/core/request.ts delete mode 100644 apps/web/generated/index.ts delete mode 100644 apps/web/generated/models/APIKeyRequestModel.ts delete mode 100644 apps/web/generated/models/APIKeyResponseModel.ts delete mode 100644 apps/web/generated/models/APIKeyTypeModel.ts delete mode 100644 apps/web/generated/models/APIKeyTypeResponseModel.ts delete mode 100644 apps/web/generated/models/APIKeyUpdateModel.ts delete mode 100644 apps/web/generated/models/AgentModel.ts delete mode 100644 apps/web/generated/models/AgentRequestModel.ts delete mode 100644 apps/web/generated/models/AgentResponseModel.ts delete mode 100644 apps/web/generated/models/AgentUpdateModel.ts delete mode 100644 apps/web/generated/models/AuthResponse.ts delete mode 100644 apps/web/generated/models/CrewModel.ts delete mode 100644 apps/web/generated/models/CrewRequestModel.ts delete mode 100644 apps/web/generated/models/CrewResponseModel.ts delete mode 100644 apps/web/generated/models/CrewUpdateModel.ts delete mode 100644 apps/web/generated/models/Factor.ts delete mode 100644 apps/web/generated/models/HTTPValidationError.ts delete mode 100644 apps/web/generated/models/Message.ts delete mode 100644 apps/web/generated/models/OAuthResponse.ts delete mode 100644 apps/web/generated/models/ProfileRequestModel.ts delete mode 100644 apps/web/generated/models/ProfileResponseModel.ts delete mode 100644 apps/web/generated/models/ProfileUpdateModel.ts delete mode 100644 apps/web/generated/models/RunRequestModel.ts delete mode 100644 apps/web/generated/models/RunResponseModel.ts delete mode 100644 apps/web/generated/models/SessionRequest.ts delete mode 100644 apps/web/generated/models/SessionResponse.ts delete mode 100644 apps/web/generated/models/SessionStatus.ts delete mode 100644 apps/web/generated/models/SessionUpdate.ts delete mode 100644 apps/web/generated/models/SignInWithEmailAndPasswordCredentials.ts delete mode 100644 apps/web/generated/models/SignInWithOAuthCredentials.ts delete mode 100644 apps/web/generated/models/SignInWithOAuthCredentialsOptions.ts delete mode 100644 apps/web/generated/models/SignInWithPasswordCredentialsOptions.ts delete mode 100644 apps/web/generated/models/SignUpWithEmailAndPasswordCredentials.ts delete mode 100644 apps/web/generated/models/SignUpWithEmailAndPasswordCredentialsOptions.ts delete mode 100644 apps/web/generated/models/User.ts delete mode 100644 apps/web/generated/models/UserIdentity.ts delete mode 100644 apps/web/generated/models/ValidationError.ts delete mode 100644 apps/web/generated/models/gotrue__types__Session.ts delete mode 100644 apps/web/generated/models/src__models__session__Session.ts delete mode 100644 apps/web/generated/services/AgentsService.ts delete mode 100644 apps/web/generated/services/ApiKeyTypesService.ts delete mode 100644 apps/web/generated/services/AuthenticationService.ts delete mode 100644 apps/web/generated/services/CrewsService.ts delete mode 100644 apps/web/generated/services/DefaultService.ts delete mode 100644 apps/web/generated/services/MessagesService.ts delete mode 100644 apps/web/generated/services/ProfilesService.ts delete mode 100644 apps/web/generated/services/SessionsService.ts delete mode 100644 apps/web/src/lib/api.ts create mode 100644 apps/web/src/lib/api/index.ts create mode 100644 apps/web/src/lib/api/v0.d.ts delete mode 100644 apps/web/src/lib/client/core/ApiError.ts delete mode 100644 apps/web/src/lib/client/core/ApiRequestOptions.ts delete mode 100644 apps/web/src/lib/client/core/ApiResult.ts delete mode 100644 apps/web/src/lib/client/core/CancelablePromise.ts delete mode 100644 apps/web/src/lib/client/core/OpenAPI.ts delete mode 100644 apps/web/src/lib/client/core/request.ts delete mode 100644 apps/web/src/lib/client/index.ts delete mode 100644 apps/web/src/lib/client/models/APIKeyRequestModel.ts delete mode 100644 apps/web/src/lib/client/models/APIKeyResponseModel.ts delete mode 100644 apps/web/src/lib/client/models/APIKeyTypeModel.ts delete mode 100644 apps/web/src/lib/client/models/APIKeyTypeResponseModel.ts delete mode 100644 apps/web/src/lib/client/models/APIKeyUpdateModel.ts delete mode 100644 apps/web/src/lib/client/models/AgentModel.ts delete mode 100644 apps/web/src/lib/client/models/AgentRequestModel.ts delete mode 100644 apps/web/src/lib/client/models/AgentResponseModel.ts delete mode 100644 apps/web/src/lib/client/models/AgentUpdateModel.ts delete mode 100644 apps/web/src/lib/client/models/AuthResponse.ts delete mode 100644 apps/web/src/lib/client/models/CrewModel.ts delete mode 100644 apps/web/src/lib/client/models/CrewRequestModel.ts delete mode 100644 apps/web/src/lib/client/models/CrewResponseModel.ts delete mode 100644 apps/web/src/lib/client/models/CrewUpdateModel.ts delete mode 100644 apps/web/src/lib/client/models/Factor.ts delete mode 100644 apps/web/src/lib/client/models/HTTPValidationError.ts delete mode 100644 apps/web/src/lib/client/models/Message.ts delete mode 100644 apps/web/src/lib/client/models/OAuthResponse.ts delete mode 100644 apps/web/src/lib/client/models/ProfileRequestModel.ts delete mode 100644 apps/web/src/lib/client/models/ProfileResponseModel.ts delete mode 100644 apps/web/src/lib/client/models/ProfileUpdateModel.ts delete mode 100644 apps/web/src/lib/client/models/RunRequestModel.ts delete mode 100644 apps/web/src/lib/client/models/RunResponseModel.ts delete mode 100644 apps/web/src/lib/client/models/SessionRequest.ts delete mode 100644 apps/web/src/lib/client/models/SessionResponse.ts delete mode 100644 apps/web/src/lib/client/models/SessionStatus.ts delete mode 100644 apps/web/src/lib/client/models/SessionUpdate.ts delete mode 100644 apps/web/src/lib/client/models/SignInWithEmailAndPasswordCredentials.ts delete mode 100644 apps/web/src/lib/client/models/SignInWithOAuthCredentials.ts delete mode 100644 apps/web/src/lib/client/models/SignInWithOAuthCredentialsOptions.ts delete mode 100644 apps/web/src/lib/client/models/SignInWithPasswordCredentialsOptions.ts delete mode 100644 apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentials.ts delete mode 100644 apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentialsOptions.ts delete mode 100644 apps/web/src/lib/client/models/User.ts delete mode 100644 apps/web/src/lib/client/models/UserIdentity.ts delete mode 100644 apps/web/src/lib/client/models/ValidationError.ts delete mode 100644 apps/web/src/lib/client/models/gotrue__types__Session.ts delete mode 100644 apps/web/src/lib/client/models/src__models__session__Session.ts delete mode 100644 apps/web/src/lib/client/services/AgentsService.ts delete mode 100644 apps/web/src/lib/client/services/ApiKeyTypesService.ts delete mode 100644 apps/web/src/lib/client/services/AuthenticationService.ts delete mode 100644 apps/web/src/lib/client/services/CrewsService.ts delete mode 100644 apps/web/src/lib/client/services/DefaultService.ts delete mode 100644 apps/web/src/lib/client/services/MessagesService.ts delete mode 100644 apps/web/src/lib/client/services/ProfilesService.ts delete mode 100644 apps/web/src/lib/client/services/SessionsService.ts delete mode 100644 apps/web/src/lib/server/blog/index.ts delete mode 100644 apps/web/src/lib/server/blog/types.d.ts delete mode 100644 apps/web/src/lib/server/env.ts delete mode 100644 apps/web/src/lib/types/loads.ts delete mode 100644 apps/web/src/lib/types/models.ts delete mode 100644 apps/web/src/routes/(marketing)/blog/(blog-article)/+layout.svelte delete mode 100644 apps/web/src/routes/(marketing)/blog/(blog-article)/+layout.ts delete mode 100644 apps/web/src/routes/(marketing)/blog/(blog-article)/[slug]/+page.server.ts delete mode 100644 apps/web/src/routes/(marketing)/blog/(blog-article)/[slug]/+page.svelte delete mode 100644 apps/web/src/routes/(marketing)/blog/+layout.svelte delete mode 100644 apps/web/src/routes/(marketing)/blog/+page.server.ts delete mode 100644 apps/web/src/routes/(marketing)/blog/+page.svelte create mode 100644 apps/web/src/routes/app/crews/[id]/CrewPanel.svelte diff --git a/apps/api/src/parser.py b/apps/api/src/parser.py index ba0e6aa7..c5e2fa70 100644 --- a/apps/api/src/parser.py +++ b/apps/api/src/parser.py @@ -62,15 +62,15 @@ def process_crew(crew: Crew) -> tuple[str, CrewProcessed]: if not crew.prompt: raise HTTPException(400, "got no prompt") if len(crew_model.agents) == 0: - raise ValueError("crew had no agents") + raise HTTPException(400, "crew had no agents") # Validate agents for agent in crew_model.agents: if agent.role == "": - raise ValueError(f"agent {agent.id} had no role") + raise HTTPException(400, f"agent {agent.id} had no role") if agent.title == "": - raise ValueError(f"agent {agent.id} had no title") + raise HTTPException(400, f"agent {agent.id} had no title") if agent.system_message == "": - raise ValueError(f"agent {agent.id} had no system message") + raise HTTPException(400, f"agent {agent.id} had no system message") message: str = crew.prompt["content"] return message, crew_model diff --git a/apps/web/.env.example b/apps/web/.env.example deleted file mode 100644 index 2e45028d..00000000 --- a/apps/web/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -PUBLIC_SUPABASE_URL="" -PUBLIC_SUPABASE_ANON_KEY="" -PUBLIC_API_URL="" diff --git a/apps/web/.prettierignore b/apps/web/.prettierignore index cc41cea9..90640115 100644 --- a/apps/web/.prettierignore +++ b/apps/web/.prettierignore @@ -2,3 +2,4 @@ pnpm-lock.yaml package-lock.json yarn.lock +src/lib/api/*.d.ts diff --git a/apps/web/generated/core/ApiError.ts b/apps/web/generated/core/ApiError.ts deleted file mode 100644 index ec7b16af..00000000 --- a/apps/web/generated/core/ApiError.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; -import type { ApiResult } from './ApiResult'; - -export class ApiError extends Error { - public readonly url: string; - public readonly status: number; - public readonly statusText: string; - public readonly body: any; - public readonly request: ApiRequestOptions; - - constructor(request: ApiRequestOptions, response: ApiResult, message: string) { - super(message); - - this.name = 'ApiError'; - this.url = response.url; - this.status = response.status; - this.statusText = response.statusText; - this.body = response.body; - this.request = request; - } -} diff --git a/apps/web/generated/core/ApiRequestOptions.ts b/apps/web/generated/core/ApiRequestOptions.ts deleted file mode 100644 index 93143c3c..00000000 --- a/apps/web/generated/core/ApiRequestOptions.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ApiRequestOptions = { - readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly url: string; - readonly path?: Record; - readonly cookies?: Record; - readonly headers?: Record; - readonly query?: Record; - readonly formData?: Record; - readonly body?: any; - readonly mediaType?: string; - readonly responseHeader?: string; - readonly errors?: Record; -}; diff --git a/apps/web/generated/core/ApiResult.ts b/apps/web/generated/core/ApiResult.ts deleted file mode 100644 index ee1126e2..00000000 --- a/apps/web/generated/core/ApiResult.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ApiResult = { - readonly url: string; - readonly ok: boolean; - readonly status: number; - readonly statusText: string; - readonly body: any; -}; diff --git a/apps/web/generated/core/CancelablePromise.ts b/apps/web/generated/core/CancelablePromise.ts deleted file mode 100644 index d70de929..00000000 --- a/apps/web/generated/core/CancelablePromise.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export class CancelError extends Error { - - constructor(message: string) { - super(message); - this.name = 'CancelError'; - } - - public get isCancelled(): boolean { - return true; - } -} - -export interface OnCancel { - readonly isResolved: boolean; - readonly isRejected: boolean; - readonly isCancelled: boolean; - - (cancelHandler: () => void): void; -} - -export class CancelablePromise implements Promise { - #isResolved: boolean; - #isRejected: boolean; - #isCancelled: boolean; - readonly #cancelHandlers: (() => void)[]; - readonly #promise: Promise; - #resolve?: (value: T | PromiseLike) => void; - #reject?: (reason?: any) => void; - - constructor( - executor: ( - resolve: (value: T | PromiseLike) => void, - reject: (reason?: any) => void, - onCancel: OnCancel - ) => void - ) { - this.#isResolved = false; - this.#isRejected = false; - this.#isCancelled = false; - this.#cancelHandlers = []; - this.#promise = new Promise((resolve, reject) => { - this.#resolve = resolve; - this.#reject = reject; - - const onResolve = (value: T | PromiseLike): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isResolved = true; - if (this.#resolve) this.#resolve(value); - }; - - const onReject = (reason?: any): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isRejected = true; - if (this.#reject) this.#reject(reason); - }; - - const onCancel = (cancelHandler: () => void): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#cancelHandlers.push(cancelHandler); - }; - - Object.defineProperty(onCancel, 'isResolved', { - get: (): boolean => this.#isResolved, - }); - - Object.defineProperty(onCancel, 'isRejected', { - get: (): boolean => this.#isRejected, - }); - - Object.defineProperty(onCancel, 'isCancelled', { - get: (): boolean => this.#isCancelled, - }); - - return executor(onResolve, onReject, onCancel as OnCancel); - }); - } - - get [Symbol.toStringTag]() { - return "Cancellable Promise"; - } - - public then( - onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, - onRejected?: ((reason: any) => TResult2 | PromiseLike) | null - ): Promise { - return this.#promise.then(onFulfilled, onRejected); - } - - public catch( - onRejected?: ((reason: any) => TResult | PromiseLike) | null - ): Promise { - return this.#promise.catch(onRejected); - } - - public finally(onFinally?: (() => void) | null): Promise { - return this.#promise.finally(onFinally); - } - - public cancel(): void { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isCancelled = true; - if (this.#cancelHandlers.length) { - try { - for (const cancelHandler of this.#cancelHandlers) { - cancelHandler(); - } - } catch (error) { - console.warn('Cancellation threw an error', error); - return; - } - } - this.#cancelHandlers.length = 0; - if (this.#reject) this.#reject(new CancelError('Request aborted')); - } - - public get isCancelled(): boolean { - return this.#isCancelled; - } -} diff --git a/apps/web/generated/core/OpenAPI.ts b/apps/web/generated/core/OpenAPI.ts deleted file mode 100644 index 0cfae5db..00000000 --- a/apps/web/generated/core/OpenAPI.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; - -type Resolver = (options: ApiRequestOptions) => Promise; -type Headers = Record; - -export type OpenAPIConfig = { - BASE: string; - VERSION: string; - WITH_CREDENTIALS: boolean; - CREDENTIALS: 'include' | 'omit' | 'same-origin'; - TOKEN?: string | Resolver | undefined; - USERNAME?: string | Resolver | undefined; - PASSWORD?: string | Resolver | undefined; - HEADERS?: Headers | Resolver | undefined; - ENCODE_PATH?: ((path: string) => string) | undefined; -}; - -export const OpenAPI: OpenAPIConfig = { - BASE: '', - VERSION: '0.1.0', - WITH_CREDENTIALS: false, - CREDENTIALS: 'include', - TOKEN: undefined, - USERNAME: undefined, - PASSWORD: undefined, - HEADERS: undefined, - ENCODE_PATH: undefined, -}; diff --git a/apps/web/generated/core/request.ts b/apps/web/generated/core/request.ts deleted file mode 100644 index f83d7119..00000000 --- a/apps/web/generated/core/request.ts +++ /dev/null @@ -1,322 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import { ApiError } from './ApiError'; -import type { ApiRequestOptions } from './ApiRequestOptions'; -import type { ApiResult } from './ApiResult'; -import { CancelablePromise } from './CancelablePromise'; -import type { OnCancel } from './CancelablePromise'; -import type { OpenAPIConfig } from './OpenAPI'; - -export const isDefined = (value: T | null | undefined): value is Exclude => { - return value !== undefined && value !== null; -}; - -export const isString = (value: any): value is string => { - return typeof value === 'string'; -}; - -export const isStringWithValue = (value: any): value is string => { - return isString(value) && value !== ''; -}; - -export const isBlob = (value: any): value is Blob => { - return ( - typeof value === 'object' && - typeof value.type === 'string' && - typeof value.stream === 'function' && - typeof value.arrayBuffer === 'function' && - typeof value.constructor === 'function' && - typeof value.constructor.name === 'string' && - /^(Blob|File)$/.test(value.constructor.name) && - /^(Blob|File)$/.test(value[Symbol.toStringTag]) - ); -}; - -export const isFormData = (value: any): value is FormData => { - return value instanceof FormData; -}; - -export const base64 = (str: string): string => { - try { - return btoa(str); - } catch (err) { - // @ts-ignore - return Buffer.from(str).toString('base64'); - } -}; - -export const getQueryString = (params: Record): string => { - const qs: string[] = []; - - const append = (key: string, value: any) => { - qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); - }; - - const process = (key: string, value: any) => { - if (isDefined(value)) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(`${key}[${k}]`, v); - }); - } else { - append(key, value); - } - } - }; - - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); - - if (qs.length > 0) { - return `?${qs.join('&')}`; - } - - return ''; -}; - -const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { - const encoder = config.ENCODE_PATH || encodeURI; - - const path = options.url - .replace('{api-version}', config.VERSION) - .replace(/{(.*?)}/g, (substring: string, group: string) => { - if (options.path?.hasOwnProperty(group)) { - return encoder(String(options.path[group])); - } - return substring; - }); - - const url = `${config.BASE}${path}`; - if (options.query) { - return `${url}${getQueryString(options.query)}`; - } - return url; -}; - -export const getFormData = (options: ApiRequestOptions): FormData | undefined => { - if (options.formData) { - const formData = new FormData(); - - const process = (key: string, value: any) => { - if (isString(value) || isBlob(value)) { - formData.append(key, value); - } else { - formData.append(key, JSON.stringify(value)); - } - }; - - Object.entries(options.formData) - .filter(([_, value]) => isDefined(value)) - .forEach(([key, value]) => { - if (Array.isArray(value)) { - value.forEach(v => process(key, v)); - } else { - process(key, value); - } - }); - - return formData; - } - return undefined; -}; - -type Resolver = (options: ApiRequestOptions) => Promise; - -export const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => { - if (typeof resolver === 'function') { - return (resolver as Resolver)(options); - } - return resolver; -}; - -export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { - const [token, username, password, additionalHeaders] = await Promise.all([ - resolve(options, config.TOKEN), - resolve(options, config.USERNAME), - resolve(options, config.PASSWORD), - resolve(options, config.HEADERS), - ]); - - const headers = Object.entries({ - Accept: 'application/json', - ...additionalHeaders, - ...options.headers, - }) - .filter(([_, value]) => isDefined(value)) - .reduce((headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), {} as Record); - - if (isStringWithValue(token)) { - headers['Authorization'] = `Bearer ${token}`; - } - - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers['Authorization'] = `Basic ${credentials}`; - } - - if (options.body !== undefined) { - if (options.mediaType) { - headers['Content-Type'] = options.mediaType; - } else if (isBlob(options.body)) { - headers['Content-Type'] = options.body.type || 'application/octet-stream'; - } else if (isString(options.body)) { - headers['Content-Type'] = 'text/plain'; - } else if (!isFormData(options.body)) { - headers['Content-Type'] = 'application/json'; - } - } - - return new Headers(headers); -}; - -export const getRequestBody = (options: ApiRequestOptions): any => { - if (options.body !== undefined) { - if (options.mediaType?.includes('/json')) { - return JSON.stringify(options.body) - } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { - return options.body; - } else { - return JSON.stringify(options.body); - } - } - return undefined; -}; - -export const sendRequest = async ( - config: OpenAPIConfig, - options: ApiRequestOptions, - url: string, - body: any, - formData: FormData | undefined, - headers: Headers, - onCancel: OnCancel -): Promise => { - const controller = new AbortController(); - - const request: RequestInit = { - headers, - body: body ?? formData, - method: options.method, - signal: controller.signal, - }; - - if (config.WITH_CREDENTIALS) { - request.credentials = config.CREDENTIALS; - } - - onCancel(() => controller.abort()); - - return await fetch(url, request); -}; - -export const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => { - if (responseHeader) { - const content = response.headers.get(responseHeader); - if (isString(content)) { - return content; - } - } - return undefined; -}; - -export const getResponseBody = async (response: Response): Promise => { - if (response.status !== 204) { - try { - const contentType = response.headers.get('Content-Type'); - if (contentType) { - const jsonTypes = ['application/json', 'application/problem+json'] - const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type)); - if (isJSON) { - return await response.json(); - } else { - return await response.text(); - } - } - } catch (error) { - console.error(error); - } - } - return undefined; -}; - -export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { - const errors: Record = { - 400: 'Bad Request', - 401: 'Unauthorized', - 403: 'Forbidden', - 404: 'Not Found', - 500: 'Internal Server Error', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - ...options.errors, - } - - const error = errors[result.status]; - if (error) { - throw new ApiError(options, result, error); - } - - if (!result.ok) { - const errorStatus = result.status ?? 'unknown'; - const errorStatusText = result.statusText ?? 'unknown'; - const errorBody = (() => { - try { - return JSON.stringify(result.body, null, 2); - } catch (e) { - return undefined; - } - })(); - - throw new ApiError(options, result, - `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}` - ); - } -}; - -/** - * Request method - * @param config The OpenAPI configuration object - * @param options The request options from the service - * @returns CancelablePromise - * @throws ApiError - */ -export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(config, options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(config, options); - - if (!onCancel.isCancelled) { - const response = await sendRequest(config, options, url, body, formData, headers, onCancel); - const responseBody = await getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); - - const result: ApiResult = { - url, - ok: response.ok, - status: response.status, - statusText: response.statusText, - body: responseHeader ?? responseBody, - }; - - catchErrorCodes(options, result); - - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); -}; diff --git a/apps/web/generated/index.ts b/apps/web/generated/index.ts deleted file mode 100644 index 4f85ba2d..00000000 --- a/apps/web/generated/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export { ApiError } from './core/ApiError'; -export { CancelablePromise, CancelError } from './core/CancelablePromise'; -export { OpenAPI } from './core/OpenAPI'; -export type { OpenAPIConfig } from './core/OpenAPI'; - -export { AgentModel } from './models/AgentModel'; -export { AgentRequestModel } from './models/AgentRequestModel'; -export { AgentResponseModel } from './models/AgentResponseModel'; -export type { AgentUpdateModel } from './models/AgentUpdateModel'; -export type { APIKeyRequestModel } from './models/APIKeyRequestModel'; -export type { APIKeyResponseModel } from './models/APIKeyResponseModel'; -export type { APIKeyTypeModel } from './models/APIKeyTypeModel'; -export type { APIKeyTypeResponseModel } from './models/APIKeyTypeResponseModel'; -export type { APIKeyUpdateModel } from './models/APIKeyUpdateModel'; -export type { AuthResponse } from './models/AuthResponse'; -export type { CrewModel } from './models/CrewModel'; -export type { CrewRequestModel } from './models/CrewRequestModel'; -export type { CrewResponseModel } from './models/CrewResponseModel'; -export type { CrewUpdateModel } from './models/CrewUpdateModel'; -export { Factor } from './models/Factor'; -export type { gotrue__types__Session } from './models/gotrue__types__Session'; -export type { HTTPValidationError } from './models/HTTPValidationError'; -export type { Message } from './models/Message'; -export { OAuthResponse } from './models/OAuthResponse'; -export type { ProfileRequestModel } from './models/ProfileRequestModel'; -export type { ProfileResponseModel } from './models/ProfileResponseModel'; -export type { ProfileUpdateModel } from './models/ProfileUpdateModel'; -export type { RunRequestModel } from './models/RunRequestModel'; -export type { RunResponseModel } from './models/RunResponseModel'; -export type { SessionRequest } from './models/SessionRequest'; -export type { SessionResponse } from './models/SessionResponse'; -export { SessionStatus } from './models/SessionStatus'; -export type { SessionUpdate } from './models/SessionUpdate'; -export type { SignInWithEmailAndPasswordCredentials } from './models/SignInWithEmailAndPasswordCredentials'; -export { SignInWithOAuthCredentials } from './models/SignInWithOAuthCredentials'; -export type { SignInWithOAuthCredentialsOptions } from './models/SignInWithOAuthCredentialsOptions'; -export type { SignInWithPasswordCredentialsOptions } from './models/SignInWithPasswordCredentialsOptions'; -export type { SignUpWithEmailAndPasswordCredentials } from './models/SignUpWithEmailAndPasswordCredentials'; -export type { SignUpWithEmailAndPasswordCredentialsOptions } from './models/SignUpWithEmailAndPasswordCredentialsOptions'; -export type { src__models__session__Session } from './models/src__models__session__Session'; -export type { User } from './models/User'; -export type { UserIdentity } from './models/UserIdentity'; -export type { ValidationError } from './models/ValidationError'; - -export { AgentsService } from './services/AgentsService'; -export { ApiKeyTypesService } from './services/ApiKeyTypesService'; -export { AuthenticationService } from './services/AuthenticationService'; -export { CrewsService } from './services/CrewsService'; -export { DefaultService } from './services/DefaultService'; -export { MessagesService } from './services/MessagesService'; -export { ProfilesService } from './services/ProfilesService'; -export { SessionsService } from './services/SessionsService'; diff --git a/apps/web/generated/models/APIKeyRequestModel.ts b/apps/web/generated/models/APIKeyRequestModel.ts deleted file mode 100644 index a40c30fc..00000000 --- a/apps/web/generated/models/APIKeyRequestModel.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyRequestModel = { - profile_id: string; - api_key_type_id: string; - api_key: string; -}; - diff --git a/apps/web/generated/models/APIKeyResponseModel.ts b/apps/web/generated/models/APIKeyResponseModel.ts deleted file mode 100644 index babd1e1f..00000000 --- a/apps/web/generated/models/APIKeyResponseModel.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { APIKeyTypeModel } from './APIKeyTypeModel'; -export type APIKeyResponseModel = { - id: string; - created_at: string; - profile_id: string; - api_key_type?: (APIKeyTypeModel | null); - api_key: string; -}; - diff --git a/apps/web/generated/models/APIKeyTypeModel.ts b/apps/web/generated/models/APIKeyTypeModel.ts deleted file mode 100644 index 67630945..00000000 --- a/apps/web/generated/models/APIKeyTypeModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyTypeModel = { - id: string; - name: string; - created_at: string; - description: string; -}; - diff --git a/apps/web/generated/models/APIKeyTypeResponseModel.ts b/apps/web/generated/models/APIKeyTypeResponseModel.ts deleted file mode 100644 index c0680933..00000000 --- a/apps/web/generated/models/APIKeyTypeResponseModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyTypeResponseModel = { - id: string; - created_at: string; - name?: (string | null); - description?: (string | null); -}; - diff --git a/apps/web/generated/models/APIKeyUpdateModel.ts b/apps/web/generated/models/APIKeyUpdateModel.ts deleted file mode 100644 index 0670cda5..00000000 --- a/apps/web/generated/models/APIKeyUpdateModel.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyUpdateModel = { - api_key: string; -}; - diff --git a/apps/web/generated/models/AgentModel.ts b/apps/web/generated/models/AgentModel.ts deleted file mode 100644 index 76accc13..00000000 --- a/apps/web/generated/models/AgentModel.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentModel = { - title: string; - role: string; - system_message: string; - tools: Array>; - model: AgentModel.model; - id: string; -}; -export namespace AgentModel { - export enum model { - GPT_3_5_TURBO = 'gpt-3.5-turbo', - GPT_4_TURBO_PREVIEW = 'gpt-4-turbo-preview', - } -} - diff --git a/apps/web/generated/models/AgentRequestModel.ts b/apps/web/generated/models/AgentRequestModel.ts deleted file mode 100644 index 068943c7..00000000 --- a/apps/web/generated/models/AgentRequestModel.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentRequestModel = { - title: string; - role: string; - system_message: string; - tools: Array>; - model: AgentRequestModel.model; - description?: (string | null); - profile_id: string; - version?: (string | null); - avatar: string; -}; -export namespace AgentRequestModel { - export enum model { - GPT_3_5_TURBO = 'gpt-3.5-turbo', - GPT_4_TURBO_PREVIEW = 'gpt-4-turbo-preview', - } -} - diff --git a/apps/web/generated/models/AgentResponseModel.ts b/apps/web/generated/models/AgentResponseModel.ts deleted file mode 100644 index 0a6cb220..00000000 --- a/apps/web/generated/models/AgentResponseModel.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentResponseModel = { - title: string; - role: string; - system_message: string; - tools: Array>; - model: AgentResponseModel.model; - description?: (string | null); - profile_id: string; - version?: (string | null); - avatar: string; - id: string; - created_at: string; - published: boolean; -}; -export namespace AgentResponseModel { - export enum model { - GPT_3_5_TURBO = 'gpt-3.5-turbo', - GPT_4_TURBO_PREVIEW = 'gpt-4-turbo-preview', - } -} - diff --git a/apps/web/generated/models/AgentUpdateModel.ts b/apps/web/generated/models/AgentUpdateModel.ts deleted file mode 100644 index ed007e46..00000000 --- a/apps/web/generated/models/AgentUpdateModel.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentUpdateModel = { - title?: (string | null); - role?: (string | null); - system_message?: (string | null); - tools?: null; - model?: ('gpt-3.5-turbo' | 'gpt-4-turbo-preview' | null); - description?: (string | null); - profile_id?: (string | null); - version?: (string | null); - avatar?: (string | null); -}; - diff --git a/apps/web/generated/models/AuthResponse.ts b/apps/web/generated/models/AuthResponse.ts deleted file mode 100644 index 4f96377e..00000000 --- a/apps/web/generated/models/AuthResponse.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { gotrue__types__Session } from './gotrue__types__Session'; -import type { User } from './User'; -export type AuthResponse = { - user?: (User | null); - session?: (gotrue__types__Session | null); -}; - diff --git a/apps/web/generated/models/CrewModel.ts b/apps/web/generated/models/CrewModel.ts deleted file mode 100644 index 080b5dc4..00000000 --- a/apps/web/generated/models/CrewModel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { AgentModel } from './AgentModel'; -export type CrewModel = { - receiver_id: string; - delegator_id?: (string | null); - agents: Array; - sub_crews?: Array; -}; - diff --git a/apps/web/generated/models/CrewRequestModel.ts b/apps/web/generated/models/CrewRequestModel.ts deleted file mode 100644 index e9a9744c..00000000 --- a/apps/web/generated/models/CrewRequestModel.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type CrewRequestModel = { - receiver_id: string; - prompt: Record; - profile_id: string; - edges: Array>; - published: boolean; - title: string; - description: string; - nodes: Array; -}; - diff --git a/apps/web/generated/models/CrewResponseModel.ts b/apps/web/generated/models/CrewResponseModel.ts deleted file mode 100644 index 0716da86..00000000 --- a/apps/web/generated/models/CrewResponseModel.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type CrewResponseModel = { - id: string; - created_at: string; - profile_id: string; - edges: Array>; - published: boolean; - title: string; - description: string; - updated_at: string; - nodes: Array; - receiver_id?: (string | null); - avatar?: (string | null); - prompt?: (Record | null); -}; - diff --git a/apps/web/generated/models/CrewUpdateModel.ts b/apps/web/generated/models/CrewUpdateModel.ts deleted file mode 100644 index 202c9f92..00000000 --- a/apps/web/generated/models/CrewUpdateModel.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type CrewUpdateModel = { - receiver_id?: (string | null); - prompt?: (Record | null); - profile_id?: (string | null); - edges?: null; - published?: (boolean | null); - title?: (string | null); - description?: (string | null); - nodes?: (Array | null); -}; - diff --git a/apps/web/generated/models/Factor.ts b/apps/web/generated/models/Factor.ts deleted file mode 100644 index 586e9e82..00000000 --- a/apps/web/generated/models/Factor.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -/** - * A MFA factor. - */ -export type Factor = { - id: string; - friendly_name?: (string | null); - factor_type: string; - status: Factor.status; - created_at: string; - updated_at: string; -}; -export namespace Factor { - export enum status { - VERIFIED = 'verified', - UNVERIFIED = 'unverified', - } -} - diff --git a/apps/web/generated/models/HTTPValidationError.ts b/apps/web/generated/models/HTTPValidationError.ts deleted file mode 100644 index f9b1a79e..00000000 --- a/apps/web/generated/models/HTTPValidationError.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ValidationError } from './ValidationError'; -export type HTTPValidationError = { - detail?: Array; -}; - diff --git a/apps/web/generated/models/Message.ts b/apps/web/generated/models/Message.ts deleted file mode 100644 index 992a4dde..00000000 --- a/apps/web/generated/models/Message.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type Message = { - id?: string; - session_id: string; - profile_id: string; - sender_id?: (string | null); - recipient_id?: (string | null); - content: string; - role?: string; - created_at?: string; -}; - diff --git a/apps/web/generated/models/OAuthResponse.ts b/apps/web/generated/models/OAuthResponse.ts deleted file mode 100644 index 9369453c..00000000 --- a/apps/web/generated/models/OAuthResponse.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type OAuthResponse = { - provider: OAuthResponse.provider; - url: string; -}; -export namespace OAuthResponse { - export enum provider { - APPLE = 'apple', - AZURE = 'azure', - BITBUCKET = 'bitbucket', - DISCORD = 'discord', - FACEBOOK = 'facebook', - FIGMA = 'figma', - GITHUB = 'github', - GITLAB = 'gitlab', - GOOGLE = 'google', - KAKAO = 'kakao', - KEYCLOAK = 'keycloak', - LINKEDIN = 'linkedin', - NOTION = 'notion', - SLACK = 'slack', - SPOTIFY = 'spotify', - TWITCH = 'twitch', - TWITTER = 'twitter', - WORKOS = 'workos', - ZOOM = 'zoom', - } -} - diff --git a/apps/web/generated/models/ProfileRequestModel.ts b/apps/web/generated/models/ProfileRequestModel.ts deleted file mode 100644 index d456b6e7..00000000 --- a/apps/web/generated/models/ProfileRequestModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ProfileRequestModel = { - user_id: string; - tier_id: string; - display_name: string; - stripe_customer_id?: (string | null); -}; - diff --git a/apps/web/generated/models/ProfileResponseModel.ts b/apps/web/generated/models/ProfileResponseModel.ts deleted file mode 100644 index 02d108cf..00000000 --- a/apps/web/generated/models/ProfileResponseModel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ProfileResponseModel = { - id: string; - tier_id: string; - created_at: string; - display_name: string; - stripe_customer_id: (string | null); -}; - diff --git a/apps/web/generated/models/ProfileUpdateModel.ts b/apps/web/generated/models/ProfileUpdateModel.ts deleted file mode 100644 index 8471aeb0..00000000 --- a/apps/web/generated/models/ProfileUpdateModel.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ProfileUpdateModel = { - tier_id?: (string | null); - display_name?: (string | null); - stripe_customer_id?: (string | null); -}; - diff --git a/apps/web/generated/models/RunRequestModel.ts b/apps/web/generated/models/RunRequestModel.ts deleted file mode 100644 index 4e3920da..00000000 --- a/apps/web/generated/models/RunRequestModel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type RunRequestModel = { - id: string; - profile_id: string; - session_title?: string; - session_id?: (string | null); - reply?: (string | null); -}; - diff --git a/apps/web/generated/models/RunResponseModel.ts b/apps/web/generated/models/RunResponseModel.ts deleted file mode 100644 index 9bc0397c..00000000 --- a/apps/web/generated/models/RunResponseModel.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { src__models__session__Session } from './src__models__session__Session'; -export type RunResponseModel = { - status: ; - session: src__models__session__Session; -}; - diff --git a/apps/web/generated/models/SessionRequest.ts b/apps/web/generated/models/SessionRequest.ts deleted file mode 100644 index 6a398967..00000000 --- a/apps/web/generated/models/SessionRequest.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SessionRequest = { - crew_id: string; - profile_id: string; - title: (string | null); -}; - diff --git a/apps/web/generated/models/SessionResponse.ts b/apps/web/generated/models/SessionResponse.ts deleted file mode 100644 index 56bf4c6a..00000000 --- a/apps/web/generated/models/SessionResponse.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SessionStatus } from './SessionStatus'; -export type SessionResponse = { - crew_id: string; - profile_id: string; - title: (string | null); - id?: string; - created_at?: string; - status?: SessionStatus; -}; - diff --git a/apps/web/generated/models/SessionStatus.ts b/apps/web/generated/models/SessionStatus.ts deleted file mode 100644 index fbbf267b..00000000 --- a/apps/web/generated/models/SessionStatus.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export enum SessionStatus { - RUNNING = 'running', - FINISHED = 'finished', - IDLE = 'idle', -} diff --git a/apps/web/generated/models/SessionUpdate.ts b/apps/web/generated/models/SessionUpdate.ts deleted file mode 100644 index 51845c2c..00000000 --- a/apps/web/generated/models/SessionUpdate.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SessionStatus } from './SessionStatus'; -export type SessionUpdate = { - crew_id?: (string | null); - profile_id?: (string | null); - title?: (string | null); - status?: (SessionStatus | null); -}; - diff --git a/apps/web/generated/models/SignInWithEmailAndPasswordCredentials.ts b/apps/web/generated/models/SignInWithEmailAndPasswordCredentials.ts deleted file mode 100644 index 4450a63d..00000000 --- a/apps/web/generated/models/SignInWithEmailAndPasswordCredentials.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SignInWithPasswordCredentialsOptions } from './SignInWithPasswordCredentialsOptions'; -export type SignInWithEmailAndPasswordCredentials = { - email: string; - password: string; - options?: SignInWithPasswordCredentialsOptions; -}; - diff --git a/apps/web/generated/models/SignInWithOAuthCredentials.ts b/apps/web/generated/models/SignInWithOAuthCredentials.ts deleted file mode 100644 index b5f7a18c..00000000 --- a/apps/web/generated/models/SignInWithOAuthCredentials.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SignInWithOAuthCredentialsOptions } from './SignInWithOAuthCredentialsOptions'; -export type SignInWithOAuthCredentials = { - provider: SignInWithOAuthCredentials.provider; - options?: SignInWithOAuthCredentialsOptions; -}; -export namespace SignInWithOAuthCredentials { - export enum provider { - APPLE = 'apple', - AZURE = 'azure', - BITBUCKET = 'bitbucket', - DISCORD = 'discord', - FACEBOOK = 'facebook', - FIGMA = 'figma', - GITHUB = 'github', - GITLAB = 'gitlab', - GOOGLE = 'google', - KAKAO = 'kakao', - KEYCLOAK = 'keycloak', - LINKEDIN = 'linkedin', - NOTION = 'notion', - SLACK = 'slack', - SPOTIFY = 'spotify', - TWITCH = 'twitch', - TWITTER = 'twitter', - WORKOS = 'workos', - ZOOM = 'zoom', - } -} - diff --git a/apps/web/generated/models/SignInWithOAuthCredentialsOptions.ts b/apps/web/generated/models/SignInWithOAuthCredentialsOptions.ts deleted file mode 100644 index fd2b0a18..00000000 --- a/apps/web/generated/models/SignInWithOAuthCredentialsOptions.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SignInWithOAuthCredentialsOptions = { - redirect_to?: string; - scopes?: string; - query_params?: Record; -}; - diff --git a/apps/web/generated/models/SignInWithPasswordCredentialsOptions.ts b/apps/web/generated/models/SignInWithPasswordCredentialsOptions.ts deleted file mode 100644 index e6445aa3..00000000 --- a/apps/web/generated/models/SignInWithPasswordCredentialsOptions.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SignInWithPasswordCredentialsOptions = { - data?: any; - captcha_token?: string; -}; - diff --git a/apps/web/generated/models/SignUpWithEmailAndPasswordCredentials.ts b/apps/web/generated/models/SignUpWithEmailAndPasswordCredentials.ts deleted file mode 100644 index 8d051b63..00000000 --- a/apps/web/generated/models/SignUpWithEmailAndPasswordCredentials.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SignUpWithEmailAndPasswordCredentialsOptions } from './SignUpWithEmailAndPasswordCredentialsOptions'; -export type SignUpWithEmailAndPasswordCredentials = { - email: string; - password: string; - options?: SignUpWithEmailAndPasswordCredentialsOptions; -}; - diff --git a/apps/web/generated/models/SignUpWithEmailAndPasswordCredentialsOptions.ts b/apps/web/generated/models/SignUpWithEmailAndPasswordCredentialsOptions.ts deleted file mode 100644 index ab535861..00000000 --- a/apps/web/generated/models/SignUpWithEmailAndPasswordCredentialsOptions.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SignUpWithEmailAndPasswordCredentialsOptions = { - email_redirect_to?: string; - data?: any; - captcha_token?: string; -}; - diff --git a/apps/web/generated/models/User.ts b/apps/web/generated/models/User.ts deleted file mode 100644 index 9aac1bb6..00000000 --- a/apps/web/generated/models/User.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { Factor } from './Factor'; -import type { UserIdentity } from './UserIdentity'; -export type User = { - id: string; - app_metadata: Record; - user_metadata: Record; - aud: string; - confirmation_sent_at?: (string | null); - recovery_sent_at?: (string | null); - email_change_sent_at?: (string | null); - new_email?: (string | null); - invited_at?: (string | null); - action_link?: (string | null); - email?: (string | null); - phone?: (string | null); - created_at: string; - confirmed_at?: (string | null); - email_confirmed_at?: (string | null); - phone_confirmed_at?: (string | null); - last_sign_in_at?: (string | null); - role?: (string | null); - updated_at?: (string | null); - identities?: (Array | null); - factors?: (Array | null); -}; - diff --git a/apps/web/generated/models/UserIdentity.ts b/apps/web/generated/models/UserIdentity.ts deleted file mode 100644 index 92317cd4..00000000 --- a/apps/web/generated/models/UserIdentity.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UserIdentity = { - id: string; - user_id: string; - identity_data: Record; - provider: string; - created_at: string; - last_sign_in_at?: (string | null); - updated_at?: (string | null); -}; - diff --git a/apps/web/generated/models/ValidationError.ts b/apps/web/generated/models/ValidationError.ts deleted file mode 100644 index aaf1c921..00000000 --- a/apps/web/generated/models/ValidationError.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ValidationError = { - loc: Array<(string | number)>; - msg: string; - type: string; -}; - diff --git a/apps/web/generated/models/gotrue__types__Session.ts b/apps/web/generated/models/gotrue__types__Session.ts deleted file mode 100644 index e6bd9cfd..00000000 --- a/apps/web/generated/models/gotrue__types__Session.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { User } from './User'; -export type gotrue__types__Session = { - provider_token?: (string | null); - provider_refresh_token?: (string | null); - access_token: string; - refresh_token: string; - expires_in: number; - expires_at?: (number | null); - token_type: string; - user: User; -}; - diff --git a/apps/web/generated/models/src__models__session__Session.ts b/apps/web/generated/models/src__models__session__Session.ts deleted file mode 100644 index 3c4f9ca3..00000000 --- a/apps/web/generated/models/src__models__session__Session.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SessionStatus } from './SessionStatus'; -export type src__models__session__Session = { - crew_id: string; - profile_id: string; - title: (string | null); - id?: string; - created_at?: string; - status?: SessionStatus; -}; - diff --git a/apps/web/generated/services/AgentsService.ts b/apps/web/generated/services/AgentsService.ts deleted file mode 100644 index edd9dc09..00000000 --- a/apps/web/generated/services/AgentsService.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { AgentRequestModel } from '../models/AgentRequestModel'; -import type { AgentResponseModel } from '../models/AgentResponseModel'; -import type { AgentUpdateModel } from '../models/AgentUpdateModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class AgentsService { - /** - * Get Published Agents - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getPublishedAgentsAgentsPublishedGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/published', - }); - } - /** - * Get Users Agents - * @param profileId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getUsersAgentsAgentsByProfileGet( - profileId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/by_profile', - query: { - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Agents From Crew - * @param crewId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getAgentsFromCrewAgentsByCrewGet( - crewId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/by_crew', - query: { - 'crew_id': crewId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Agent By Id - * @param agentId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getAgentByIdAgentsAgentIdGet( - agentId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/{agent_id}', - path: { - 'agent_id': agentId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Patch Agent - * @param agentId - * @param requestBody - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static patchAgentAgentsAgentIdPatch( - agentId: string, - requestBody: AgentUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/agents/{agent_id}', - path: { - 'agent_id': agentId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Delete Agent - * @param agentId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static deleteAgentAgentsAgentIdDelete( - agentId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/agents/{agent_id}', - path: { - 'agent_id': agentId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Insert Agent - * @param requestBody - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static insertAgentAgentsPost( - requestBody: AgentRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/agents/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/generated/services/ApiKeyTypesService.ts b/apps/web/generated/services/ApiKeyTypesService.ts deleted file mode 100644 index 75f7f111..00000000 --- a/apps/web/generated/services/ApiKeyTypesService.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { APIKeyTypeResponseModel } from '../models/APIKeyTypeResponseModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class ApiKeyTypesService { - /** - * Get All Api Key Types - * @returns APIKeyTypeResponseModel Successful Response - * @throws ApiError - */ - public static getAllApiKeyTypesApiKeyTypesGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/api_key_types/', - }); - } -} diff --git a/apps/web/generated/services/AuthenticationService.ts b/apps/web/generated/services/AuthenticationService.ts deleted file mode 100644 index 95800c02..00000000 --- a/apps/web/generated/services/AuthenticationService.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { AuthResponse } from '../models/AuthResponse'; -import type { OAuthResponse } from '../models/OAuthResponse'; -import type { SignInWithEmailAndPasswordCredentials } from '../models/SignInWithEmailAndPasswordCredentials'; -import type { SignInWithOAuthCredentials } from '../models/SignInWithOAuthCredentials'; -import type { SignUpWithEmailAndPasswordCredentials } from '../models/SignUpWithEmailAndPasswordCredentials'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class AuthenticationService { - /** - * Email Sign Up - * format for passing display name: 'options': {'data':{'display_name': 'name'}} - * @param requestBody - * @returns AuthResponse Successful Response - * @throws ApiError - */ - public static emailSignUpAuthSignUpPost( - requestBody: SignUpWithEmailAndPasswordCredentials, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/auth/sign_up', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Email Sign In - * @param requestBody - * @returns AuthResponse Successful Response - * @throws ApiError - */ - public static emailSignInAuthSignInPost( - requestBody: SignInWithEmailAndPasswordCredentials, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/auth/sign_in', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Provider Sign In - * @param requestBody - * @returns OAuthResponse Successful Response - * @throws ApiError - */ - public static providerSignInAuthSignInProviderPost( - requestBody: SignInWithOAuthCredentials, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/auth/sign_in/provider', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/generated/services/CrewsService.ts b/apps/web/generated/services/CrewsService.ts deleted file mode 100644 index 02e3926d..00000000 --- a/apps/web/generated/services/CrewsService.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CrewRequestModel } from '../models/CrewRequestModel'; -import type { CrewResponseModel } from '../models/CrewResponseModel'; -import type { CrewUpdateModel } from '../models/CrewUpdateModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class CrewsService { - /** - * Insert Crew - * @param requestBody - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static insertCrewCrewsPost( - requestBody: CrewRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/crews/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Crews Of User - * @param byProfile - * @param ascending - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static getCrewsOfUserCrewsGet( - byProfile: string, - ascending: boolean = false, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/crews/', - query: { - 'by_profile': byProfile, - 'ascending': ascending, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Crew - * @param crewId - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static getCrewCrewsCrewIdGet( - crewId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/crews/{crew_id}', - path: { - 'crew_id': crewId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Crew - * @param crewId - * @param requestBody - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static updateCrewCrewsCrewIdPatch( - crewId: string, - requestBody: CrewUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/crews/{crew_id}', - path: { - 'crew_id': crewId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Published Crews - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static getPublishedCrewsCrewsPublishedGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/crews/published', - }); - } -} diff --git a/apps/web/generated/services/DefaultService.ts b/apps/web/generated/services/DefaultService.ts deleted file mode 100644 index 65f4bd40..00000000 --- a/apps/web/generated/services/DefaultService.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CrewModel } from '../models/CrewModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class DefaultService { - /** - * Redirect To Docs - * @returns any Successful Response - * @throws ApiError - */ - public static redirectToDocsGet(): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/', - }); - } - /** - * Compile - * @param id - * @returns any Successful Response - * @throws ApiError - */ - public static compileCompileGet( - id: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/compile', - query: { - 'id': id, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Improve - * @param wordLimit - * @param prompt - * @param promptType - * @param temperature - * @param profileId - * @returns string Successful Response - * @throws ApiError - */ - public static improveImproveGet( - wordLimit: number, - prompt: string, - promptType: 'generic' | 'system' | 'user', - temperature: number, - profileId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/improve', - query: { - 'word_limit': wordLimit, - 'prompt': prompt, - 'prompt_type': promptType, - 'temperature': temperature, - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Auto Build Crew - * @param generalTask - * @param profileId - * @returns string Successful Response - * @throws ApiError - */ - public static autoBuildCrewAutoBuildGet( - generalTask: string, - profileId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/auto-build', - query: { - 'general_task': generalTask, - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Profile From Header - * @returns any Successful Response - * @throws ApiError - */ - public static getProfileFromHeaderMeGet(): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/me', - }); - } -} diff --git a/apps/web/generated/services/MessagesService.ts b/apps/web/generated/services/MessagesService.ts deleted file mode 100644 index 6542df70..00000000 --- a/apps/web/generated/services/MessagesService.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { Message } from '../models/Message'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class MessagesService { - /** - * Get Messages - * @param sessionId - * @returns Message Successful Response - * @throws ApiError - */ - public static getMessagesSessionsMessagesGet( - sessionId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/sessions/messages/', - query: { - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/generated/services/ProfilesService.ts b/apps/web/generated/services/ProfilesService.ts deleted file mode 100644 index 229942db..00000000 --- a/apps/web/generated/services/ProfilesService.ts +++ /dev/null @@ -1,173 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { APIKeyRequestModel } from '../models/APIKeyRequestModel'; -import type { APIKeyResponseModel } from '../models/APIKeyResponseModel'; -import type { APIKeyUpdateModel } from '../models/APIKeyUpdateModel'; -import type { ProfileRequestModel } from '../models/ProfileRequestModel'; -import type { ProfileResponseModel } from '../models/ProfileResponseModel'; -import type { ProfileUpdateModel } from '../models/ProfileUpdateModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class ProfilesService { - /** - * Get Profiles - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static getProfilesProfilesGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/profiles/', - }); - } - /** - * Insert Profile - * @param requestBody - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static insertProfileProfilesPost( - requestBody: ProfileRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/profiles/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Profile - * @param profileId - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static getProfileProfilesProfileIdGet( - profileId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/profiles/{profile_id}', - path: { - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Profile - * @param profileId - * @param requestBody - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static updateProfileProfilesProfileIdPatch( - profileId: string, - requestBody: ProfileUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/profiles/{profile_id}', - path: { - 'profile_id': profileId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Api Keys - * Returns api keys with the api key type as an object with the id, name, description etc. - * @param profileId - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static getApiKeysProfilesProfileIdApiKeysGet( - profileId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/profiles/{profile_id}/api_keys', - path: { - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Insert Api Key - * @param requestBody - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static insertApiKeyProfilesApiKeysPost( - requestBody: APIKeyRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/profiles/api_keys', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Delete Api Key - * @param apiKeyId - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static deleteApiKeyProfilesApiKeysApiKeyIdDelete( - apiKeyId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/profiles/api_keys/{api_key_id}', - path: { - 'api_key_id': apiKeyId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Api Key - * @param apiKeyId - * @param requestBody - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static updateApiKeyProfilesApiKeysApiKeyIdPatch( - apiKeyId: string, - requestBody: APIKeyUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/profiles/api_keys/{api_key_id}', - path: { - 'api_key_id': apiKeyId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/generated/services/SessionsService.ts b/apps/web/generated/services/SessionsService.ts deleted file mode 100644 index d3351d2a..00000000 --- a/apps/web/generated/services/SessionsService.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { Message } from '../models/Message'; -import type { RunRequestModel } from '../models/RunRequestModel'; -import type { RunResponseModel } from '../models/RunResponseModel'; -import type { SessionRequest } from '../models/SessionRequest'; -import type { SessionResponse } from '../models/SessionResponse'; -import type { SessionUpdate } from '../models/SessionUpdate'; -import type { src__models__session__Session } from '../models/src__models__session__Session'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class SessionsService { - /** - * Get Sessions - * @param profileId - * @param sessionId - * @returns src__models__session__Session Successful Response - * @throws ApiError - */ - public static getSessionsSessionsGet( - profileId?: (string | null), - sessionId?: (string | null), - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/sessions/', - query: { - 'profile_id': profileId, - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Insert Session - * @param requestBody - * @returns SessionResponse Successful Response - * @throws ApiError - */ - public static insertSessionSessionsPost( - requestBody: SessionRequest, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/sessions/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Session - * @param sessionId - * @param requestBody - * @returns SessionResponse Successful Response - * @throws ApiError - */ - public static updateSessionSessionsSessionIdPatch( - sessionId: string, - requestBody: SessionUpdate, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/sessions/{session_id}', - path: { - 'session_id': sessionId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Delete Session - * @param sessionId - * @returns void - * @throws ApiError - */ - public static deleteSessionSessionsSessionIdDelete( - sessionId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/sessions/{session_id}', - path: { - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Run Crew - * @param requestBody - * @param mock - * @returns RunResponseModel Successful Response - * @throws ApiError - */ - public static runCrewSessionsRunPost( - requestBody: RunRequestModel, - mock: boolean = false, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/sessions/run', - query: { - 'mock': mock, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Messages - * @param sessionId - * @returns Message Successful Response - * @throws ApiError - */ - public static getMessagesSessionsMessagesGet( - sessionId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/sessions/messages/', - query: { - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/package.json b/apps/web/package.json index 87c9d84e..0460e3bc 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -25,6 +25,7 @@ "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-svelte": "^2.35.1", + "openapi-typescript": "^6.7.5", "openapi-typescript-codegen": "^0.28.0", "postcss": "^8.4.35", "postcss-load-config": "^5.0.3", @@ -66,6 +67,7 @@ "mdsvex": "^0.11.0", "mode-watcher": "^0.2.1", "object-hash": "^3.0.0", + "openapi-fetch": "^0.9.3", "stripe": "^14.19.0", "svelte-markdown": "^0.4.1", "svelte-sonner": "^0.3.19", diff --git a/apps/web/pnpm-lock.yaml b/apps/web/pnpm-lock.yaml index 34ed1abb..7c60b748 100644 --- a/apps/web/pnpm-lock.yaml +++ b/apps/web/pnpm-lock.yaml @@ -59,7 +59,6 @@ dependencies: formsnap: specifier: ^0.4.4 version: 0.4.4(svelte@4.2.12)(sveltekit-superforms@2.12.2)(zod@3.22.4) - version: 0.4.4(svelte@4.2.12)(sveltekit-superforms@2.12.2)(zod@3.22.4) lucide-svelte: specifier: ^0.321.0 version: 0.321.0(svelte@4.2.12) @@ -72,6 +71,9 @@ dependencies: object-hash: specifier: ^3.0.0 version: 3.0.0 + openapi-fetch: + specifier: ^0.9.3 + version: 0.9.3 stripe: specifier: ^14.19.0 version: 14.19.0 @@ -134,9 +136,9 @@ devDependencies: eslint-plugin-svelte: specifier: ^2.35.1 version: 2.35.1(eslint@8.57.0)(svelte@4.2.12) - openapi-typescript-codegen: - specifier: ^0.28.0 - version: 0.28.0 + openapi-typescript: + specifier: ^6.7.5 + version: 6.7.5 openapi-typescript-codegen: specifier: ^0.28.0 version: 0.28.0 @@ -166,7 +168,7 @@ devDependencies: version: 1.1.3(svelte@4.2.12) sveltekit-superforms: specifier: ^2.12.2 - version: 2.12.2(@sveltejs/kit@2.5.2)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(svelte@4.2.12) + version: 2.12.2(@sveltejs/kit@2.5.2)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(svelte@4.2.12) tailwindcss: specifier: ^3.4.1 version: 3.4.1 @@ -213,15 +215,6 @@ packages: js-yaml: 4.1.0 dev: true - /@apidevtools/json-schema-ref-parser@11.5.4: - resolution: {integrity: sha512-o2fsypTGU0WxRxbax8zQoHiIB4dyrkwYfcm8TxZ+bx9pCzcWZbQtiMqpgBvWA/nJ2TrGjK5adCLfTH8wUeU/Wg==} - engines: {node: '>= 16'} - dependencies: - '@jsdevtools/ono': 7.1.3 - '@types/json-schema': 7.0.15 - js-yaml: 4.1.0 - dev: true - /@babel/runtime@7.24.0: resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} engines: {node: '>=6.9.0'} @@ -259,14 +252,6 @@ packages: requiresBuild: true optional: true - /@esbuild/aix-ppc64@0.20.2: - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - optional: true - /@esbuild/android-arm64@0.19.12: resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} engines: {node: '>=12'} @@ -275,14 +260,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm64@0.20.2: - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-arm@0.19.12: resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} engines: {node: '>=12'} @@ -291,14 +268,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-arm@0.20.2: - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - /@esbuild/android-x64@0.19.12: resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} engines: {node: '>=12'} @@ -307,14 +276,6 @@ packages: requiresBuild: true optional: true - /@esbuild/android-x64@0.20.2: - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - optional: true - /@esbuild/darwin-arm64@0.19.12: resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} engines: {node: '>=12'} @@ -323,14 +284,6 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-arm64@0.20.2: - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - /@esbuild/darwin-x64@0.19.12: resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} engines: {node: '>=12'} @@ -339,14 +292,6 @@ packages: requiresBuild: true optional: true - /@esbuild/darwin-x64@0.20.2: - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - /@esbuild/freebsd-arm64@0.19.12: resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} engines: {node: '>=12'} @@ -355,14 +300,6 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-arm64@0.20.2: - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/freebsd-x64@0.19.12: resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} engines: {node: '>=12'} @@ -371,14 +308,6 @@ packages: requiresBuild: true optional: true - /@esbuild/freebsd-x64@0.20.2: - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - /@esbuild/linux-arm64@0.19.12: resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} engines: {node: '>=12'} @@ -387,14 +316,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm64@0.20.2: - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-arm@0.19.12: resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} engines: {node: '>=12'} @@ -403,14 +324,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-arm@0.20.2: - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ia32@0.19.12: resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} engines: {node: '>=12'} @@ -419,14 +332,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ia32@0.20.2: - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-loong64@0.19.12: resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} @@ -435,14 +340,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-loong64@0.20.2: - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-mips64el@0.19.12: resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} engines: {node: '>=12'} @@ -451,14 +348,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-mips64el@0.20.2: - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-ppc64@0.19.12: resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} @@ -467,14 +356,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-ppc64@0.20.2: - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-riscv64@0.19.12: resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} @@ -483,14 +364,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-riscv64@0.20.2: - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-s390x@0.19.12: resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} @@ -499,14 +372,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-s390x@0.20.2: - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/linux-x64@0.19.12: resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} @@ -515,14 +380,6 @@ packages: requiresBuild: true optional: true - /@esbuild/linux-x64@0.20.2: - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - /@esbuild/netbsd-x64@0.19.12: resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} engines: {node: '>=12'} @@ -531,14 +388,6 @@ packages: requiresBuild: true optional: true - /@esbuild/netbsd-x64@0.20.2: - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - optional: true - /@esbuild/openbsd-x64@0.19.12: resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} engines: {node: '>=12'} @@ -547,14 +396,6 @@ packages: requiresBuild: true optional: true - /@esbuild/openbsd-x64@0.20.2: - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - optional: true - /@esbuild/sunos-x64@0.19.12: resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} engines: {node: '>=12'} @@ -563,14 +404,6 @@ packages: requiresBuild: true optional: true - /@esbuild/sunos-x64@0.20.2: - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - optional: true - /@esbuild/win32-arm64@0.19.12: resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} @@ -579,14 +412,6 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-arm64@0.20.2: - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-ia32@0.19.12: resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} @@ -595,14 +420,6 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-ia32@0.20.2: - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - /@esbuild/win32-x64@0.19.12: resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} @@ -611,14 +428,6 @@ packages: requiresBuild: true optional: true - /@esbuild/win32-x64@0.20.2: - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -656,6 +465,11 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true + /@fastify/busboy@2.1.1: + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} + dev: true + /@floating-ui/core@1.6.0: resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} dependencies: @@ -673,7 +487,7 @@ packages: resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} dev: false - /@gcornut/valibot-json-schema@0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(valibot@0.30.0): + /@gcornut/valibot-json-schema@0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(valibot@0.30.0): resolution: {integrity: sha512-xcMaUStVgQzPrK3d7PuLFbQ+3qSp6LzaLExAm52E3FKmUfjQa7Sw5cDK6Hfu/8WT0yfGsuSCuJ5uT1sosjR9Qg==} hasBin: true requiresBuild: true @@ -684,8 +498,8 @@ packages: valibot: '>= 0.21.0' dependencies: '@types/json-schema': 7.0.15 - esbuild: 0.20.2 - esbuild-runner: 2.2.2(esbuild@0.20.2) + esbuild: 0.19.12 + esbuild-runner: 2.2.2(esbuild@0.19.12) valibot: 0.30.0 optional: true @@ -779,7 +593,7 @@ packages: npmlog: 5.0.1 rimraf: 3.0.2 semver: 7.6.0 - tar: 6.2.1 + tar: 6.2.0 transitivePeerDependencies: - encoding - supports-color @@ -1665,6 +1479,11 @@ packages: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + /ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + dev: true + /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2203,13 +2022,13 @@ packages: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} dev: true - /esbuild-runner@2.2.2(esbuild@0.20.2): + /esbuild-runner@2.2.2(esbuild@0.19.12): resolution: {integrity: sha512-fRFVXcmYVmSmtYm2mL8RlUASt2TDkGh3uRcvHFOKNr/T58VrfVeKD9uT9nlgxk96u0LS0ehS/GY7Da/bXWKkhw==} hasBin: true peerDependencies: esbuild: '*' dependencies: - esbuild: 0.20.2 + esbuild: 0.19.12 source-map-support: 0.5.21 tslib: 2.4.0 optional: true @@ -2244,37 +2063,6 @@ packages: '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 - /esbuild@0.20.2: - resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.20.2 - '@esbuild/android-arm': 0.20.2 - '@esbuild/android-arm64': 0.20.2 - '@esbuild/android-x64': 0.20.2 - '@esbuild/darwin-arm64': 0.20.2 - '@esbuild/darwin-x64': 0.20.2 - '@esbuild/freebsd-arm64': 0.20.2 - '@esbuild/freebsd-x64': 0.20.2 - '@esbuild/linux-arm': 0.20.2 - '@esbuild/linux-arm64': 0.20.2 - '@esbuild/linux-ia32': 0.20.2 - '@esbuild/linux-loong64': 0.20.2 - '@esbuild/linux-mips64el': 0.20.2 - '@esbuild/linux-ppc64': 0.20.2 - '@esbuild/linux-riscv64': 0.20.2 - '@esbuild/linux-s390x': 0.20.2 - '@esbuild/linux-x64': 0.20.2 - '@esbuild/netbsd-x64': 0.20.2 - '@esbuild/openbsd-x64': 0.20.2 - '@esbuild/sunos-x64': 0.20.2 - '@esbuild/win32-arm64': 0.20.2 - '@esbuild/win32-ia32': 0.20.2 - '@esbuild/win32-x64': 0.20.2 - optional: true - /escalade@3.1.2: resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} engines: {node: '>=6'} @@ -2581,7 +2369,6 @@ packages: mime-types: 2.1.35 dev: false - /formsnap@0.4.4(svelte@4.2.12)(sveltekit-superforms@2.12.2)(zod@3.22.4): /formsnap@0.4.4(svelte@4.2.12)(sveltekit-superforms@2.12.2)(zod@3.22.4): resolution: {integrity: sha512-O+Cf4GneR4CLP48J0c5AJY6eowc+1N3DYZz9uIJ3Mk57AjdL5l8DQEA+HmRfse4UEPepizEPl+M4vFg8cON2BQ==} peerDependencies: @@ -2590,7 +2377,7 @@ packages: zod: ^3.22.2 dependencies: svelte: 4.2.12 - sveltekit-superforms: 2.12.2(@sveltejs/kit@2.5.2)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(svelte@4.2.12) + sveltekit-superforms: 2.12.2(@sveltejs/kit@2.5.2)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(svelte@4.2.12) zod: 3.22.4 dev: false @@ -2607,15 +2394,6 @@ packages: universalify: 2.0.1 dev: true - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - /fs-minipass@2.1.0: resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} engines: {node: '>= 8'} @@ -3299,12 +3077,6 @@ packages: requiresBuild: true optional: true - /normalize-url@8.0.1: - resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} - engines: {node: '>=14.16'} - requiresBuild: true - optional: true - /npmlog@5.0.1: resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} dependencies: @@ -3335,6 +3107,12 @@ packages: dependencies: wrappy: 1.0.2 + /openapi-fetch@0.9.3: + resolution: {integrity: sha512-tC1NDn71vJHeCzu+lYdrnIpgRt4GxR0B4eSwXNb15ypWpZcpaEOwHFkoz8FcfG5Fvqkz2P0Fl9zQF1JJwBjuvA==} + dependencies: + openapi-typescript-helpers: 0.0.7 + dev: false + /openapi-typescript-codegen@0.28.0: resolution: {integrity: sha512-BZTsMUwhA/h2zCzisjagLUPQNHE64N1EN074yGB+WqA0LFlJwy8sKQYrXH5G4phbjj9KSPx7xuWKO4hkPIOARw==} hasBin: true @@ -3346,6 +3124,22 @@ packages: handlebars: 4.7.8 dev: true + /openapi-typescript-helpers@0.0.7: + resolution: {integrity: sha512-7nwlAtdA1fULipibFRBWE/rnF114q6ejRYzNvhdA/x+qTWAZhXGLc/368dlwMlyJDvCQMCnADjpzb5BS5ZmNSA==} + dev: false + + /openapi-typescript@6.7.5: + resolution: {integrity: sha512-ZD6dgSZi0u1QCP55g8/2yS5hNJfIpgqsSGHLxxdOjvY7eIrXzj271FJEQw33VwsZ6RCtO/NOuhxa7GBWmEudyA==} + hasBin: true + dependencies: + ansi-colors: 4.1.3 + fast-glob: 3.3.2 + js-yaml: 4.1.0 + supports-color: 9.4.0 + undici: 5.28.4 + yargs-parser: 21.1.1 + dev: true + /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -4007,6 +3801,11 @@ packages: has-flag: 4.0.0 dev: true + /supports-color@9.4.0: + resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} + engines: {node: '>=12'} + dev: true + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} @@ -4184,7 +3983,7 @@ packages: magic-string: 0.30.7 periscopic: 3.1.0 - /sveltekit-superforms@2.12.2(@sveltejs/kit@2.5.2)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(svelte@4.2.12): + /sveltekit-superforms@2.12.2(@sveltejs/kit@2.5.2)(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(svelte@4.2.12): resolution: {integrity: sha512-fFOXaluP1os/Tamx7gzwhT3tXPAfqZ8KYRC0UfXdXeUtlUIUfiGrIifDJ26/9uePmF8Zhqy2M0XjG8W9kQnJpg==} peerDependencies: '@sveltejs/kit': 1.x || 2.x @@ -4194,12 +3993,10 @@ packages: devalue: 4.3.2 just-clone: 6.2.0 memoize-weak: 1.0.2 - just-clone: 6.2.0 - memoize-weak: 1.0.2 svelte: 4.2.12 ts-deepmerge: 7.0.0 optionalDependencies: - '@gcornut/valibot-json-schema': 0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.20.2)(valibot@0.30.0) + '@gcornut/valibot-json-schema': 0.0.27(@types/json-schema@7.0.15)(esbuild-runner@2.2.2)(esbuild@0.19.12)(valibot@0.30.0) '@sinclair/typebox': 0.32.20 '@sodaru/yup-to-json-schema': 2.0.1 '@vinejs/vine': 1.8.0 @@ -4269,8 +4066,8 @@ packages: transitivePeerDependencies: - ts-node - /tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} + /tar@6.2.0: + resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} engines: {node: '>=10'} dependencies: chownr: 2.0.0 @@ -4413,6 +4210,13 @@ packages: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: false + /undici@5.28.4: + resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} + engines: {node: '>=14.0'} + dependencies: + '@fastify/busboy': 2.1.1 + dev: true + /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} dependencies: @@ -4612,6 +4416,11 @@ packages: engines: {node: '>= 14'} hasBin: true + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -4636,24 +4445,5 @@ packages: zod: 3.22.4 optional: true - /yup@1.4.0: - resolution: {integrity: sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==} - requiresBuild: true - dependencies: - property-expr: 2.0.6 - tiny-case: 1.0.3 - toposort: 2.0.2 - type-fest: 2.19.0 - optional: true - - /zod-to-json-schema@3.22.5(zod@3.22.4): - resolution: {integrity: sha512-+akaPo6a0zpVCCseDed504KBJUQpEW5QZw7RMneNmKw+fGaML1Z9tUNLnHHAC8x6dzVRO1eB2oEMyZRnuBZg7Q==} - requiresBuild: true - peerDependencies: - zod: ^3.22.4 - dependencies: - zod: 3.22.4 - optional: true - /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} diff --git a/apps/web/src/app.d.ts b/apps/web/src/app.d.ts index d13a021b..21b066cc 100644 --- a/apps/web/src/app.d.ts +++ b/apps/web/src/app.d.ts @@ -9,7 +9,7 @@ declare global { // interface Error {} interface Locals { supabase: SupabaseClient; - getSession(): Promise; + getSession(): Promise; stripe: Stripe; } interface PageData { diff --git a/apps/web/src/hooks.server.ts b/apps/web/src/hooks.server.ts index b3c98b14..a5f5ac1c 100644 --- a/apps/web/src/hooks.server.ts +++ b/apps/web/src/hooks.server.ts @@ -3,7 +3,7 @@ import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/publi import { STRIPE_SECRET_KEY } from '$env/static/private'; import { createSupabaseServerClient } from '@supabase/auth-helpers-sveltekit'; -import { redirect } from '@sveltejs/kit'; +import { error, redirect } from '@sveltejs/kit'; export const handle = async ({ event, resolve }) => { event.locals.supabase = createSupabaseServerClient({ @@ -23,6 +23,8 @@ export const handle = async ({ event, resolve }) => { const { data: { session } } = await event.locals.supabase.auth.getSession(); + + if (!session) throw error(401, 'You are not logged in. Please log in and try again.'); return session; }; diff --git a/apps/web/src/lib/api.ts b/apps/web/src/lib/api.ts deleted file mode 100644 index 57bcf49c..00000000 --- a/apps/web/src/lib/api.ts +++ /dev/null @@ -1,98 +0,0 @@ -import type { UUID } from '$lib/types'; -import * as models from '$lib/types/models'; -import { PUBLIC_API_URL } from '$env/static/public'; - -export const upsertSession = async (sessionId: UUID, content: object): Promise => { - console.log('upsertSession', sessionId, content); - const success: boolean = await fetch( - `${PUBLIC_API_URL}/sessions/upsert?session_id=${sessionId}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify(content) - } - ) - .then(async (response) => { - if (!response.ok) { - console.error(`Failed to upsert session. Bad response`, response, await response.json()); - return false; - } - return true; - }) - .catch((error) => { - console.error('upsertSession: error', error); - return false; - }); - - return success; -}; - -export const startSession = async ( - profileId: UUID, - crewId: UUID, - title: string -): Promise => { - console.log('startSession', profileId, crewId, title); - try { - const response: models.Session | false = await fetch(`${PUBLIC_API_URL}/sessions/run`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - id: crewId, - profile_id: profileId, - title - }) - }) - .then(async (response) => { - if (!response.ok) { - console.error(`Failed to start session. Bad response`, response, await response.json()); - return false; - } - const { - data: { session } - } = (await response.json()) as { data: { session: models.Session } }; - return session; - }) - .catch((error) => { - console.error(`startSession: error`, error); - return false; - }); - - return response; - } catch (error) { - console.error(`deleteSession: error`, error); - return false; - } -}; - -export const deleteSession = async (sessionId: UUID): Promise => { - console.log('deleteSession', sessionId); - try { - const success: boolean = await fetch( - `${PUBLIC_API_URL}/sessions/delete?session_id=${sessionId}`, - { - method: 'POST' - } - ) - .then(async (response) => { - if (!response.ok) { - console.error(`Failed to upsert session. Bad response`, response, await response.json()); - return false; - } - console.log('deleteSession: success', response, await response.json()); - return true; - }) - .catch((error) => { - console.error(`deleteSession: error`, error); - return false; - }); - return success; - } catch (error) { - console.error(`deleteSession: error`, error); - return false; - } -}; diff --git a/apps/web/src/lib/api/index.ts b/apps/web/src/lib/api/index.ts new file mode 100644 index 00000000..60a7d166 --- /dev/null +++ b/apps/web/src/lib/api/index.ts @@ -0,0 +1,14 @@ +import createClient from 'openapi-fetch'; +import type { paths, components } from '$lib/api/v0.d.ts'; +import { PUBLIC_API_URI } from '$env/static/public'; + +const api = createClient({ baseUrl: PUBLIC_API_URI }); +export default api; + +type schemas = components['schemas']; +type headers = components['headers']; +type responses = components['responses']; +type parameters = components['parameters']; +type requestBodies = components['requestBodies']; +type pathItems = components['pathItems']; +export type { paths, schemas, headers, responses, parameters, requestBodies, pathItems }; diff --git a/apps/web/src/lib/api/v0.d.ts b/apps/web/src/lib/api/v0.d.ts new file mode 100644 index 00000000..2960b124 --- /dev/null +++ b/apps/web/src/lib/api/v0.d.ts @@ -0,0 +1,2353 @@ +/** + * This file was auto-generated by openapi-typescript. + * Do not make direct changes to the file. + */ + + +export interface paths { + "/sessions/": { + /** Get Sessions */ + get: operations["get_sessions_sessions__get"]; + /** Insert Session */ + post: operations["insert_session_sessions__post"]; + }; + "/sessions/{session_id}": { + /** Get Session */ + get: operations["get_session_sessions__session_id__get"]; + /** Delete Session */ + delete: operations["delete_session_sessions__session_id__delete"]; + /** Update Session */ + patch: operations["update_session_sessions__session_id__patch"]; + }; + "/sessions/run": { + /** Run Crew */ + post: operations["run_crew_sessions_run_post"]; + }; + "/messages/": { + /** Get Messages */ + get: operations["get_messages_messages__get"]; + /** Insert Message */ + post: operations["insert_message_messages__post"]; + }; + "/messages/{message_id}": { + /** Get Message */ + get: operations["get_message_messages__message_id__get"]; + /** Delete Message */ + delete: operations["delete_message_messages__message_id__delete"]; + /** Update Message */ + patch: operations["update_message_messages__message_id__patch"]; + }; + "/crews/": { + /** Get Crews */ + get: operations["get_crews_crews__get"]; + /** Insert Crew */ + post: operations["insert_crew_crews__post"]; + }; + "/crews/{crew_id}": { + /** Get Crew By Id */ + get: operations["get_crew_by_id_crews__crew_id__get"]; + /** Delete Crew */ + delete: operations["delete_crew_crews__crew_id__delete"]; + /** Update Crew */ + patch: operations["update_crew_crews__crew_id__patch"]; + }; + "/agents/": { + /** Get Agents */ + get: operations["get_agents_agents__get"]; + /** Insert Agent */ + post: operations["insert_agent_agents__post"]; + }; + "/agents/{agent_id}": { + /** Get Agent By Id */ + get: operations["get_agent_by_id_agents__agent_id__get"]; + /** Delete Agent */ + delete: operations["delete_agent_agents__agent_id__delete"]; + /** Patch Agent */ + patch: operations["patch_agent_agents__agent_id__patch"]; + }; + "/profiles/": { + /** Get Profiles */ + get: operations["get_profiles_profiles__get"]; + /** Insert Profile */ + post: operations["insert_profile_profiles__post"]; + }; + "/profiles/{profile_id}": { + /** Get Profile By Id */ + get: operations["get_profile_by_id_profiles__profile_id__get"]; + /** Delete Profile */ + delete: operations["delete_profile_profiles__profile_id__delete"]; + /** Update Profile */ + patch: operations["update_profile_profiles__profile_id__patch"]; + }; + "/api-keys/": { + /** + * Get Api Keys + * @description Returns api keys with the api key type as an object with the id, name, description etc. + */ + get: operations["get_api_keys_api_keys__get"]; + /** Insert Api Key */ + post: operations["insert_api_key_api_keys__post"]; + }; + "/api-keys/{api_key_id}": { + /** Get Api Key */ + get: operations["get_api_key_api_keys__api_key_id__get"]; + /** Delete Api Key */ + delete: operations["delete_api_key_api_keys__api_key_id__delete"]; + /** Update Api Key */ + patch: operations["update_api_key_api_keys__api_key_id__patch"]; + }; + "/auth/sign_in/provider": { + /** Provider Sign In */ + post: operations["provider_sign_in_auth_sign_in_provider_post"]; + }; + "/api-key-types/": { + /** Get All Api Key Types */ + get: operations["get_all_api_key_types_api_key_types__get"]; + }; + "/tools/": { + /** Get Tools */ + get: operations["get_tools_tools__get"]; + /** Insert Tool */ + post: operations["insert_tool_tools__post"]; + }; + "/tools/{tool_id}": { + /** Get Tool */ + get: operations["get_tool_tools__tool_id__get"]; + /** Delete Tool */ + delete: operations["delete_tool_tools__tool_id__delete"]; + /** Update Profile */ + patch: operations["update_profile_tools__tool_id__patch"]; + }; + "/tools/{agent_id}": { + /** Add Tool */ + patch: operations["add_tool_tools__agent_id__patch"]; + }; + "/subscriptions/": { + /** Get Subscriptions */ + get: operations["get_subscriptions_subscriptions__get"]; + /** Insert Subscription */ + post: operations["insert_subscription_subscriptions__post"]; + }; + "/subscriptions/{profile_id}": { + /** Delete Subscription */ + delete: operations["delete_subscription_subscriptions__profile_id__delete"]; + /** Update Subscription */ + patch: operations["update_subscription_subscriptions__profile_id__patch"]; + }; + "/rest/": { + /** Redirect To Docs */ + get: operations["redirect_to_docs_rest__get"]; + }; + "/rest/test": { + /** Test */ + get: operations["test_rest_test_get"]; + }; + "/rest/stop/{worker_id}": { + /** Stop Stream */ + post: operations["stop_stream_rest_stop__worker_id__post"]; + }; + "/rest/generate-comment": { + /** Generate Comment */ + post: operations["generate_comment_rest_generate_comment_post"]; + }; + "/rest/mark-lead-as-irrelevant": { + /** Mark Lead As Irrelevant */ + post: operations["mark_lead_as_irrelevant_rest_mark_lead_as_irrelevant_post"]; + }; + "/rest/publish-comment": { + /** Publish Comment */ + post: operations["publish_comment_rest_publish_comment_post"]; + }; + "/tiers/{id}": { + /** Get Tier */ + get: operations["get_tier_tiers__id__get"]; + /** Delete Tier */ + delete: operations["delete_tier_tiers__id__delete"]; + /** Update Tier */ + patch: operations["update_tier_tiers__id__patch"]; + }; + "/tiers/": { + /** Insert Tier */ + post: operations["insert_tier_tiers__post"]; + }; + "/billing/{id}": { + /** Get Billings */ + get: operations["get_billings_billing__id__get"]; + }; + "/billing/": { + /** Insert Billing */ + post: operations["insert_billing_billing__post"]; + }; + "/billing/{profile_id}": { + /** Delete Billing */ + delete: operations["delete_billing_billing__profile_id__delete"]; + /** Update Billing */ + patch: operations["update_billing_billing__profile_id__patch"]; + }; + "/": { + /** Redirect To Docs */ + get: operations["redirect_to_docs__get"]; + }; + "/improve": { + /** Improve */ + get: operations["improve_improve_get"]; + }; + "/auto-build": { + /** Auto Build Crew */ + get: operations["auto_build_crew_auto_build_get"]; + }; + "/me": { + /** Get Profile From Header */ + get: operations["get_profile_from_header_me_get"]; + }; +} + +export type webhooks = Record; + +export interface components { + schemas: { + /** APIKey */ + APIKey: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + api_key_type?: components["schemas"]["APIKeyType"] | null; + /** Api Key */ + api_key: string; + }; + /** APIKeyInsertRequest */ + APIKeyInsertRequest: { + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** + * Api Key Type Id + * Format: uuid + */ + api_key_type_id: string; + /** Api Key */ + api_key: string; + }; + /** APIKeyType */ + APIKeyType: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** Name */ + name?: string | null; + /** Description */ + description?: string | null; + }; + /** APIKeyUpdateRequest */ + APIKeyUpdateRequest: { + /** Api Key */ + api_key: string; + }; + /** Agent */ + Agent: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** Title */ + title: string; + /** Published */ + published: boolean; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Avatar */ + avatar: string; + /** System Message */ + system_message: string; + /** + * Model + * @enum {string} + */ + model: "gpt-3.5-turbo" | "gpt-4-turbo-preview"; + /** Tools */ + tools: Record[]; + /** Description */ + description?: string | null; + /** Role */ + role: string; + /** Version */ + version?: string | null; + }; + /** AgentInsertRequest */ + AgentInsertRequest: { + /** Title */ + title: string; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Avatar */ + avatar: string; + /** System Message */ + system_message: string; + /** + * Model + * @enum {string} + */ + model: "gpt-3.5-turbo" | "gpt-4-turbo-preview"; + /** Tools */ + tools: Record[]; + /** Description */ + description?: string | null; + /** Role */ + role: string; + /** Version */ + version?: string | null; + }; + /** AgentUpdateModel */ + AgentUpdateModel: { + /** Title */ + title?: string | null; + /** Published */ + published?: boolean | null; + /** Profile Id */ + profile_id?: string | null; + /** Avatar */ + avatar?: string | null; + /** System Message */ + system_message?: string | null; + /** Model */ + model?: ("gpt-3.5-turbo" | "gpt-4-turbo-preview") | null; + /** Tools */ + tools?: Record[] | null; + /** Version */ + version?: string | null; + /** Description */ + description?: string | null; + /** Role */ + role?: string | null; + }; + /** Billing */ + Billing: { + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Stripe Payment Method */ + stripe_payment_method?: string | null; + /** Description */ + description?: string | null; + /** + * Created At + * Format: date-time + */ + created_at: string; + }; + /** BillingInsertRequest */ + BillingInsertRequest: { + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Stripe Payment Method */ + stripe_payment_method?: string | null; + /** Description */ + description?: string | null; + }; + /** BillingUpdateRequest */ + BillingUpdateRequest: { + /** Stripe Payment Method */ + stripe_payment_method?: string | null; + /** Description */ + description?: string | null; + }; + /** Crew */ + Crew: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Edges */ + edges: components["schemas"]["Edge"][]; + /** Published */ + published: boolean; + /** Title */ + title: string; + /** Description */ + description: string; + /** + * Updated At + * Format: date-time + */ + updated_at: string; + /** Nodes */ + nodes: string[]; + /** Receiver Id */ + receiver_id?: string | null; + /** Avatar */ + avatar?: string | null; + prompt?: components["schemas"]["Prompt"] | null; + }; + /** CrewInsertRequest */ + CrewInsertRequest: { + /** + * Receiver Id + * Format: uuid + */ + receiver_id: string; + prompt: components["schemas"]["Prompt"]; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Edges */ + edges: components["schemas"]["Edge"][]; + /** Published */ + published: boolean; + /** Title */ + title: string; + /** Description */ + description: string; + /** Nodes */ + nodes: string[]; + }; + /** CrewUpdateRequest */ + CrewUpdateRequest: { + /** Receiver Id */ + receiver_id?: string | null; + prompt?: components["schemas"]["Prompt"] | null; + /** Profile Id */ + profile_id?: string | null; + /** Edges */ + edges?: components["schemas"]["Edge"][] | null; + /** Published */ + published?: boolean | null; + /** Title */ + title?: string | null; + /** Description */ + description?: string | null; + /** Nodes */ + nodes?: string[] | null; + }; + /** Edge */ + Edge: { + /** Id */ + id: string; + /** Type */ + type?: string | null; + /** Source */ + source: string; + /** Target */ + target: string; + /** Sourcehandle */ + sourceHandle?: string | null; + /** Targethandle */ + targetHandle?: string | null; + /** Animated */ + animated?: boolean | null; + /** Hidden */ + hidden?: boolean | null; + /** Deletable */ + deletable?: boolean | null; + /** Selectable */ + selectable?: boolean | null; + /** Data */ + data?: unknown; + /** Selected */ + selected?: boolean | null; + /** Markerstart */ + markerStart?: string | components["schemas"]["Marker"] | null; + /** Markerend */ + markerEnd?: string | components["schemas"]["Marker"] | null; + /** Zindex */ + zIndex?: number | null; + /** Arialabel */ + ariaLabel?: string | null; + /** Interactionwidth */ + interactionWidth?: number | null; + /** Label */ + label?: string | null; + /** Labelstyle */ + labelStyle?: string | null; + /** Style */ + style?: string | null; + /** Class */ + class?: string | null; + pathOptions?: components["schemas"]["PathOptions"] | null; + }; + /** FalseLead */ + FalseLead: { + /** + * Lead Id + * Format: uuid + */ + lead_id: string; + /** + * Submission Id + * Format: uuid + */ + submission_id: string; + /** Correct Reason */ + correct_reason: string; + }; + /** GenerateCommentRequest */ + GenerateCommentRequest: { + /** Title */ + title: string; + /** Selftext */ + selftext: string; + }; + /** HTTPValidationError */ + HTTPValidationError: { + /** Detail */ + detail?: components["schemas"]["ValidationError"][]; + }; + /** Marker */ + Marker: { + /** Type */ + type: string; + /** Color */ + color?: string | null; + /** Width */ + width?: number | null; + /** Height */ + height?: number | null; + /** Markerunits */ + markerUnits?: string | null; + /** Orient */ + orient?: string | null; + /** Strokewidth */ + strokeWidth?: number | null; + }; + /** Message */ + Message: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Session Id + * Format: uuid + */ + session_id: string; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Sender Id */ + sender_id?: string | null; + /** Recipient Id */ + recipient_id?: string | null; + /** Content */ + content: string; + /** Role */ + role: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + }; + /** MessageInsertRequest */ + MessageInsertRequest: { + /** + * Session Id + * Format: uuid + */ + session_id: string; + /** Content */ + content: string; + /** + * Role + * @default user + */ + role?: string; + /** Recipient Id */ + recipient_id?: string | null; + /** Sender Id */ + sender_id?: string | null; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + }; + /** MessageUpdateRequest */ + MessageUpdateRequest: { + /** Session Id */ + session_id?: string | null; + /** Content */ + content?: string | null; + /** Role */ + role?: string | null; + /** Recipient Id */ + recipient_id?: string | null; + /** Sender Id */ + sender_id?: string | null; + /** Profile Id */ + profile_id?: string | null; + }; + /** OAuthResponse */ + OAuthResponse: { + /** + * Provider + * @enum {string} + */ + provider: "apple" | "azure" | "bitbucket" | "discord" | "facebook" | "figma" | "github" | "gitlab" | "google" | "kakao" | "keycloak" | "linkedin" | "notion" | "slack" | "spotify" | "twitch" | "twitter" | "workos" | "zoom"; + /** Url */ + url: string; + }; + /** PathOptions */ + PathOptions: { + /** Offset */ + offset?: number | null; + /** Borderradius */ + borderRadius?: number | null; + /** Curvature */ + curvature?: number | null; + }; + /** Profile */ + Profile: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Tier Id + * Format: uuid + */ + tier_id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** Display Name */ + display_name: string; + /** Stripe Customer Id */ + stripe_customer_id: string | null; + }; + /** ProfileInsertRequest */ + ProfileInsertRequest: { + /** + * User Id + * Format: uuid + */ + user_id: string; + /** + * Tier Id + * Format: uuid + */ + tier_id: string; + /** Display Name */ + display_name: string; + /** Stripe Customer Id */ + stripe_customer_id?: string | null; + }; + /** ProfileUpdateRequest */ + ProfileUpdateRequest: { + /** Tier Id */ + tier_id?: string | null; + /** Display Name */ + display_name?: string | null; + /** Stripe Customer Id */ + stripe_customer_id?: string | null; + }; + /** Prompt */ + Prompt: { + /** + * Id + * Format: uuid + */ + id: string; + /** Title */ + title: string; + /** Content */ + content: string; + }; + /** PublishCommentRequest */ + PublishCommentRequest: { + /** + * Lead Id + * Format: uuid + */ + lead_id: string; + /** Comment */ + comment: string; + /** Reddit Username */ + reddit_username: string; + /** Reddit Password */ + reddit_password: string; + }; + /** Session */ + Session: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Reply */ + reply: string; + /** + * Crew Id + * Format: uuid + */ + crew_id: string; + /** Title */ + title: string; + /** + * Last Opened At + * Format: date-time + */ + last_opened_at: string; + status: components["schemas"]["SessionStatus"]; + }; + /** SessionInsertRequest */ + SessionInsertRequest: { + /** + * Crew Id + * Format: uuid + */ + crew_id: string; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Title */ + title: string | null; + }; + /** SessionRunRequest */ + SessionRunRequest: { + /** + * Crew Id + * Format: uuid + */ + crew_id: string; + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** + * Session Title + * @default Untitled + */ + session_title?: string; + /** Session Id */ + session_id?: string | null; + /** Reply */ + reply?: string | null; + }; + /** + * SessionStatus + * @enum {string} + */ + SessionStatus: "running" | "finished" | "idle"; + /** SessionUpdateRequest */ + SessionUpdateRequest: { + /** Crew Id */ + crew_id?: string | null; + /** Reply */ + reply?: string | null; + /** Profile Id */ + profile_id?: string | null; + /** Title */ + title?: string | null; + status?: components["schemas"]["SessionStatus"] | null; + }; + /** SignInWithOAuthCredentials */ + SignInWithOAuthCredentials: { + /** + * Provider + * @enum {string} + */ + provider: "apple" | "azure" | "bitbucket" | "discord" | "facebook" | "figma" | "github" | "gitlab" | "google" | "kakao" | "keycloak" | "linkedin" | "notion" | "slack" | "spotify" | "twitch" | "twitter" | "workos" | "zoom"; + options?: components["schemas"]["SignInWithOAuthCredentialsOptions"]; + }; + /** SignInWithOAuthCredentialsOptions */ + SignInWithOAuthCredentialsOptions: { + /** Redirect To */ + redirect_to?: string; + /** Scopes */ + scopes?: string; + /** Query Params */ + query_params?: { + [key: string]: string; + }; + }; + /** Subscription */ + Subscription: { + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Stripe Subscription Id */ + stripe_subscription_id?: string | null; + /** + * Created At + * Format: date-time + */ + created_at: string; + }; + /** SubscriptionInsertRequest */ + SubscriptionInsertRequest: { + /** + * Profile Id + * Format: uuid + */ + profile_id: string; + /** Stripe Subscription Id */ + stripe_subscription_id?: string | null; + }; + /** SubscriptionUpdateRequest */ + SubscriptionUpdateRequest: { + /** Stripe Subscription Id */ + stripe_subscription_id?: string | null; + }; + /** Tier */ + Tier: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** Period */ + period: number; + /** Limit */ + limit: number; + /** Stripe Price Id */ + stripe_price_id?: string | null; + /** Name */ + name?: string | null; + /** Description */ + description?: string | null; + /** Slug */ + slug?: string | null; + /** Image */ + image?: string | null; + }; + /** TierInsertRequest */ + TierInsertRequest: { + /** Period */ + period?: number | null; + /** Limit */ + limit?: number | null; + /** Stripe Price Id */ + stripe_price_id?: string | null; + /** Name */ + name?: string | null; + /** Description */ + description?: string | null; + /** Slug */ + slug?: string | null; + /** Image */ + image?: string | null; + }; + /** TierUpdateRequest */ + TierUpdateRequest: { + /** Period */ + period?: number | null; + /** Limit */ + limit?: number | null; + /** Stripe Price Id */ + stripe_price_id?: string | null; + /** Name */ + name?: string | null; + /** Description */ + description?: string | null; + /** Slug */ + slug?: string | null; + /** Image */ + image?: string | null; + }; + /** Tool */ + Tool: { + /** + * Id + * Format: uuid + */ + id: string; + /** + * Created At + * Format: date-time + */ + created_at: string; + /** Name */ + name: string; + /** Description */ + description: string; + /** Api Key Type Id */ + api_key_type_id?: string | null; + }; + /** ToolInsertRequest */ + ToolInsertRequest: { + /** Name */ + name: string; + /** Description */ + description: string; + /** Api Key Type Id */ + api_key_type_id?: string | null; + }; + /** ToolUpdateRequest */ + ToolUpdateRequest: { + /** Name */ + name?: string | null; + /** Description */ + description?: string | null; + /** Api Key Type Id */ + api_key_type_id?: string | null; + }; + /** ValidationError */ + ValidationError: { + /** Location */ + loc: (string | number)[]; + /** Message */ + msg: string; + /** Error Type */ + type: string; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; +} + +export type $defs = Record; + +export type external = Record; + +export interface operations { + + /** Get Sessions */ + get_sessions_sessions__get: { + parameters: { + query?: { + profile_id?: string | null; + crew_id?: string | null; + title?: string | null; + status?: components["schemas"]["SessionStatus"] | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Session"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Session */ + insert_session_sessions__post: { + requestBody: { + content: { + "application/json": components["schemas"]["SessionInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["Session"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Session */ + get_session_sessions__session_id__get: { + parameters: { + path: { + session_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Session"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Session */ + delete_session_sessions__session_id__delete: { + parameters: { + path: { + session_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Session"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Session */ + update_session_sessions__session_id__patch: { + parameters: { + path: { + session_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SessionUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Session"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Run Crew */ + run_crew_sessions_run_post: { + parameters: { + query?: { + mock?: boolean; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SessionRunRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Session"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Messages */ + get_messages_messages__get: { + parameters: { + query?: { + session_id?: string | null; + profile_id?: string | null; + recipient_id?: string | null; + sender_id?: string | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Message"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Message */ + insert_message_messages__post: { + requestBody: { + content: { + "application/json": components["schemas"]["MessageInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["Message"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Message */ + get_message_messages__message_id__get: { + parameters: { + path: { + message_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Message"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Message */ + delete_message_messages__message_id__delete: { + parameters: { + path: { + message_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Message"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Message */ + update_message_messages__message_id__patch: { + parameters: { + path: { + message_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["MessageUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Message"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Crews */ + get_crews_crews__get: { + parameters: { + query?: { + profile_id?: string | null; + receiver_id?: string | null; + title?: string | null; + published?: boolean | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Crew"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Crew */ + insert_crew_crews__post: { + requestBody: { + content: { + "application/json": components["schemas"]["CrewInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["Crew"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Crew By Id */ + get_crew_by_id_crews__crew_id__get: { + parameters: { + path: { + crew_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Crew"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Crew */ + delete_crew_crews__crew_id__delete: { + parameters: { + path: { + crew_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Crew"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Crew */ + update_crew_crews__crew_id__patch: { + parameters: { + path: { + crew_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["CrewUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Crew"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Agents */ + get_agents_agents__get: { + parameters: { + query?: { + profile_id?: string | null; + crew_id?: string | null; + published?: boolean | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Agent"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Agent */ + insert_agent_agents__post: { + requestBody: { + content: { + "application/json": components["schemas"]["AgentInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["Agent"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Agent By Id */ + get_agent_by_id_agents__agent_id__get: { + parameters: { + path: { + agent_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Agent"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Agent */ + delete_agent_agents__agent_id__delete: { + parameters: { + path: { + agent_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Agent"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Patch Agent */ + patch_agent_agents__agent_id__patch: { + parameters: { + path: { + agent_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["AgentUpdateModel"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Agent"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Profiles */ + get_profiles_profiles__get: { + parameters: { + query?: { + tier_id?: string | null; + display_name?: string | null; + stripe_customer_id?: string | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Profile"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Profile */ + insert_profile_profiles__post: { + requestBody: { + content: { + "application/json": components["schemas"]["ProfileInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["Profile"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Profile By Id */ + get_profile_by_id_profiles__profile_id__get: { + parameters: { + path: { + profile_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Profile"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Profile */ + delete_profile_profiles__profile_id__delete: { + parameters: { + path: { + profile_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Profile"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Profile */ + update_profile_profiles__profile_id__patch: { + parameters: { + path: { + profile_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ProfileUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Profile"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** + * Get Api Keys + * @description Returns api keys with the api key type as an object with the id, name, description etc. + */ + get_api_keys_api_keys__get: { + parameters: { + query?: { + profile_id?: string | null; + api_key_type_id?: string | null; + api_key?: string | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["APIKey"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Api Key */ + insert_api_key_api_keys__post: { + requestBody: { + content: { + "application/json": components["schemas"]["APIKeyInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["APIKey"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Api Key */ + get_api_key_api_keys__api_key_id__get: { + parameters: { + path: { + api_key_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["APIKey"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Api Key */ + delete_api_key_api_keys__api_key_id__delete: { + parameters: { + path: { + api_key_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["APIKey"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Api Key */ + update_api_key_api_keys__api_key_id__patch: { + parameters: { + path: { + api_key_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["APIKeyUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["APIKey"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Provider Sign In */ + provider_sign_in_auth_sign_in_provider_post: { + requestBody: { + content: { + "application/json": components["schemas"]["SignInWithOAuthCredentials"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["OAuthResponse"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get All Api Key Types */ + get_all_api_key_types_api_key_types__get: { + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["APIKeyType"][]; + }; + }; + }; + }; + /** Get Tools */ + get_tools_tools__get: { + parameters: { + query?: { + name?: string | null; + api_key_type_id?: string | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tool"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Tool */ + insert_tool_tools__post: { + requestBody: { + content: { + "application/json": components["schemas"]["ToolInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["Tool"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Tool */ + get_tool_tools__tool_id__get: { + parameters: { + path: { + tool_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tool"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Tool */ + delete_tool_tools__tool_id__delete: { + parameters: { + path: { + tool_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tool"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Profile */ + update_profile_tools__tool_id__patch: { + parameters: { + path: { + tool_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["ToolUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tool"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Add Tool */ + add_tool_tools__agent_id__patch: { + parameters: { + query: { + tool_id: string; + }; + path: { + agent_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Agent"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Subscriptions */ + get_subscriptions_subscriptions__get: { + parameters: { + query?: { + profile_id?: string | null; + stripe_subscription_id?: string | null; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Subscription"][]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Subscription */ + insert_subscription_subscriptions__post: { + requestBody: { + content: { + "application/json": components["schemas"]["SubscriptionInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 201: { + content: { + "application/json": components["schemas"]["Subscription"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Subscription */ + delete_subscription_subscriptions__profile_id__delete: { + parameters: { + path: { + profile_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Subscription"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Subscription */ + update_subscription_subscriptions__profile_id__patch: { + parameters: { + path: { + profile_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["SubscriptionUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Subscription"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Redirect To Docs */ + redirect_to_docs_rest__get: { + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": unknown; + }; + }; + }; + }; + /** Test */ + test_rest_test_get: { + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": unknown; + }; + }; + }; + }; + /** Stop Stream */ + stop_stream_rest_stop__worker_id__post: { + parameters: { + path: { + worker_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Generate Comment */ + generate_comment_rest_generate_comment_post: { + requestBody: { + content: { + "application/json": components["schemas"]["GenerateCommentRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Mark Lead As Irrelevant */ + mark_lead_as_irrelevant_rest_mark_lead_as_irrelevant_post: { + requestBody: { + content: { + "application/json": components["schemas"]["FalseLead"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Publish Comment */ + publish_comment_rest_publish_comment_post: { + requestBody: { + content: { + "application/json": components["schemas"]["PublishCommentRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": unknown; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Tier */ + get_tier_tiers__id__get: { + parameters: { + path: { + id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tier"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Tier */ + delete_tier_tiers__id__delete: { + parameters: { + path: { + id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tier"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Tier */ + update_tier_tiers__id__patch: { + parameters: { + path: { + id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["TierUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tier"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Tier */ + insert_tier_tiers__post: { + requestBody: { + content: { + "application/json": components["schemas"]["TierInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Tier"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Billings */ + get_billings_billing__id__get: { + parameters: { + path: { + id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Billing"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Insert Billing */ + insert_billing_billing__post: { + requestBody: { + content: { + "application/json": components["schemas"]["BillingInsertRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Billing"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Delete Billing */ + delete_billing_billing__profile_id__delete: { + parameters: { + path: { + profile_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Billing"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Update Billing */ + update_billing_billing__profile_id__patch: { + parameters: { + path: { + profile_id: string; + }; + }; + requestBody: { + content: { + "application/json": components["schemas"]["BillingUpdateRequest"]; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Billing"]; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Redirect To Docs */ + redirect_to_docs__get: { + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": unknown; + }; + }; + }; + }; + /** Improve */ + improve_improve_get: { + parameters: { + query: { + word_limit: number; + prompt: string; + prompt_type: "generic" | "system" | "user"; + temperature: number; + profile_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": string; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Auto Build Crew */ + auto_build_crew_auto_build_get: { + parameters: { + query: { + general_task: string; + profile_id: string; + }; + }; + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": string; + }; + }; + /** @description Validation Error */ + 422: { + content: { + "application/json": components["schemas"]["HTTPValidationError"]; + }; + }; + }; + }; + /** Get Profile From Header */ + get_profile_from_header_me_get: { + responses: { + /** @description Successful Response */ + 200: { + content: { + "application/json": components["schemas"]["Profile"]; + }; + }; + }; + }; +} diff --git a/apps/web/src/lib/client/core/ApiError.ts b/apps/web/src/lib/client/core/ApiError.ts deleted file mode 100644 index ec7b16af..00000000 --- a/apps/web/src/lib/client/core/ApiError.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; -import type { ApiResult } from './ApiResult'; - -export class ApiError extends Error { - public readonly url: string; - public readonly status: number; - public readonly statusText: string; - public readonly body: any; - public readonly request: ApiRequestOptions; - - constructor(request: ApiRequestOptions, response: ApiResult, message: string) { - super(message); - - this.name = 'ApiError'; - this.url = response.url; - this.status = response.status; - this.statusText = response.statusText; - this.body = response.body; - this.request = request; - } -} diff --git a/apps/web/src/lib/client/core/ApiRequestOptions.ts b/apps/web/src/lib/client/core/ApiRequestOptions.ts deleted file mode 100644 index 93143c3c..00000000 --- a/apps/web/src/lib/client/core/ApiRequestOptions.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ApiRequestOptions = { - readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly url: string; - readonly path?: Record; - readonly cookies?: Record; - readonly headers?: Record; - readonly query?: Record; - readonly formData?: Record; - readonly body?: any; - readonly mediaType?: string; - readonly responseHeader?: string; - readonly errors?: Record; -}; diff --git a/apps/web/src/lib/client/core/ApiResult.ts b/apps/web/src/lib/client/core/ApiResult.ts deleted file mode 100644 index ee1126e2..00000000 --- a/apps/web/src/lib/client/core/ApiResult.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ApiResult = { - readonly url: string; - readonly ok: boolean; - readonly status: number; - readonly statusText: string; - readonly body: any; -}; diff --git a/apps/web/src/lib/client/core/CancelablePromise.ts b/apps/web/src/lib/client/core/CancelablePromise.ts deleted file mode 100644 index d70de929..00000000 --- a/apps/web/src/lib/client/core/CancelablePromise.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export class CancelError extends Error { - - constructor(message: string) { - super(message); - this.name = 'CancelError'; - } - - public get isCancelled(): boolean { - return true; - } -} - -export interface OnCancel { - readonly isResolved: boolean; - readonly isRejected: boolean; - readonly isCancelled: boolean; - - (cancelHandler: () => void): void; -} - -export class CancelablePromise implements Promise { - #isResolved: boolean; - #isRejected: boolean; - #isCancelled: boolean; - readonly #cancelHandlers: (() => void)[]; - readonly #promise: Promise; - #resolve?: (value: T | PromiseLike) => void; - #reject?: (reason?: any) => void; - - constructor( - executor: ( - resolve: (value: T | PromiseLike) => void, - reject: (reason?: any) => void, - onCancel: OnCancel - ) => void - ) { - this.#isResolved = false; - this.#isRejected = false; - this.#isCancelled = false; - this.#cancelHandlers = []; - this.#promise = new Promise((resolve, reject) => { - this.#resolve = resolve; - this.#reject = reject; - - const onResolve = (value: T | PromiseLike): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isResolved = true; - if (this.#resolve) this.#resolve(value); - }; - - const onReject = (reason?: any): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isRejected = true; - if (this.#reject) this.#reject(reason); - }; - - const onCancel = (cancelHandler: () => void): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#cancelHandlers.push(cancelHandler); - }; - - Object.defineProperty(onCancel, 'isResolved', { - get: (): boolean => this.#isResolved, - }); - - Object.defineProperty(onCancel, 'isRejected', { - get: (): boolean => this.#isRejected, - }); - - Object.defineProperty(onCancel, 'isCancelled', { - get: (): boolean => this.#isCancelled, - }); - - return executor(onResolve, onReject, onCancel as OnCancel); - }); - } - - get [Symbol.toStringTag]() { - return "Cancellable Promise"; - } - - public then( - onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, - onRejected?: ((reason: any) => TResult2 | PromiseLike) | null - ): Promise { - return this.#promise.then(onFulfilled, onRejected); - } - - public catch( - onRejected?: ((reason: any) => TResult | PromiseLike) | null - ): Promise { - return this.#promise.catch(onRejected); - } - - public finally(onFinally?: (() => void) | null): Promise { - return this.#promise.finally(onFinally); - } - - public cancel(): void { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isCancelled = true; - if (this.#cancelHandlers.length) { - try { - for (const cancelHandler of this.#cancelHandlers) { - cancelHandler(); - } - } catch (error) { - console.warn('Cancellation threw an error', error); - return; - } - } - this.#cancelHandlers.length = 0; - if (this.#reject) this.#reject(new CancelError('Request aborted')); - } - - public get isCancelled(): boolean { - return this.#isCancelled; - } -} diff --git a/apps/web/src/lib/client/core/OpenAPI.ts b/apps/web/src/lib/client/core/OpenAPI.ts deleted file mode 100644 index 16da0e60..00000000 --- a/apps/web/src/lib/client/core/OpenAPI.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ApiRequestOptions } from './ApiRequestOptions'; -import { PUBLIC_API_URL } from '$env/static/public'; - -type Resolver = (options: ApiRequestOptions) => Promise; -type Headers = Record; - -export type OpenAPIConfig = { - BASE: string; - VERSION: string; - WITH_CREDENTIALS: boolean; - CREDENTIALS: 'include' | 'omit' | 'same-origin'; - TOKEN?: string | Resolver | undefined; - USERNAME?: string | Resolver | undefined; - PASSWORD?: string | Resolver | undefined; - HEADERS?: Headers | Resolver | undefined; - ENCODE_PATH?: ((path: string) => string) | undefined; -}; - -export const OpenAPI: OpenAPIConfig = { - BASE: PUBLIC_API_URL, - VERSION: '0.1.0', - WITH_CREDENTIALS: false, - CREDENTIALS: 'include', - TOKEN: undefined, - USERNAME: undefined, - PASSWORD: undefined, - HEADERS: undefined, - ENCODE_PATH: undefined -}; diff --git a/apps/web/src/lib/client/core/request.ts b/apps/web/src/lib/client/core/request.ts deleted file mode 100644 index f83d7119..00000000 --- a/apps/web/src/lib/client/core/request.ts +++ /dev/null @@ -1,322 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import { ApiError } from './ApiError'; -import type { ApiRequestOptions } from './ApiRequestOptions'; -import type { ApiResult } from './ApiResult'; -import { CancelablePromise } from './CancelablePromise'; -import type { OnCancel } from './CancelablePromise'; -import type { OpenAPIConfig } from './OpenAPI'; - -export const isDefined = (value: T | null | undefined): value is Exclude => { - return value !== undefined && value !== null; -}; - -export const isString = (value: any): value is string => { - return typeof value === 'string'; -}; - -export const isStringWithValue = (value: any): value is string => { - return isString(value) && value !== ''; -}; - -export const isBlob = (value: any): value is Blob => { - return ( - typeof value === 'object' && - typeof value.type === 'string' && - typeof value.stream === 'function' && - typeof value.arrayBuffer === 'function' && - typeof value.constructor === 'function' && - typeof value.constructor.name === 'string' && - /^(Blob|File)$/.test(value.constructor.name) && - /^(Blob|File)$/.test(value[Symbol.toStringTag]) - ); -}; - -export const isFormData = (value: any): value is FormData => { - return value instanceof FormData; -}; - -export const base64 = (str: string): string => { - try { - return btoa(str); - } catch (err) { - // @ts-ignore - return Buffer.from(str).toString('base64'); - } -}; - -export const getQueryString = (params: Record): string => { - const qs: string[] = []; - - const append = (key: string, value: any) => { - qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); - }; - - const process = (key: string, value: any) => { - if (isDefined(value)) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(`${key}[${k}]`, v); - }); - } else { - append(key, value); - } - } - }; - - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); - - if (qs.length > 0) { - return `?${qs.join('&')}`; - } - - return ''; -}; - -const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { - const encoder = config.ENCODE_PATH || encodeURI; - - const path = options.url - .replace('{api-version}', config.VERSION) - .replace(/{(.*?)}/g, (substring: string, group: string) => { - if (options.path?.hasOwnProperty(group)) { - return encoder(String(options.path[group])); - } - return substring; - }); - - const url = `${config.BASE}${path}`; - if (options.query) { - return `${url}${getQueryString(options.query)}`; - } - return url; -}; - -export const getFormData = (options: ApiRequestOptions): FormData | undefined => { - if (options.formData) { - const formData = new FormData(); - - const process = (key: string, value: any) => { - if (isString(value) || isBlob(value)) { - formData.append(key, value); - } else { - formData.append(key, JSON.stringify(value)); - } - }; - - Object.entries(options.formData) - .filter(([_, value]) => isDefined(value)) - .forEach(([key, value]) => { - if (Array.isArray(value)) { - value.forEach(v => process(key, v)); - } else { - process(key, value); - } - }); - - return formData; - } - return undefined; -}; - -type Resolver = (options: ApiRequestOptions) => Promise; - -export const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => { - if (typeof resolver === 'function') { - return (resolver as Resolver)(options); - } - return resolver; -}; - -export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { - const [token, username, password, additionalHeaders] = await Promise.all([ - resolve(options, config.TOKEN), - resolve(options, config.USERNAME), - resolve(options, config.PASSWORD), - resolve(options, config.HEADERS), - ]); - - const headers = Object.entries({ - Accept: 'application/json', - ...additionalHeaders, - ...options.headers, - }) - .filter(([_, value]) => isDefined(value)) - .reduce((headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), {} as Record); - - if (isStringWithValue(token)) { - headers['Authorization'] = `Bearer ${token}`; - } - - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers['Authorization'] = `Basic ${credentials}`; - } - - if (options.body !== undefined) { - if (options.mediaType) { - headers['Content-Type'] = options.mediaType; - } else if (isBlob(options.body)) { - headers['Content-Type'] = options.body.type || 'application/octet-stream'; - } else if (isString(options.body)) { - headers['Content-Type'] = 'text/plain'; - } else if (!isFormData(options.body)) { - headers['Content-Type'] = 'application/json'; - } - } - - return new Headers(headers); -}; - -export const getRequestBody = (options: ApiRequestOptions): any => { - if (options.body !== undefined) { - if (options.mediaType?.includes('/json')) { - return JSON.stringify(options.body) - } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { - return options.body; - } else { - return JSON.stringify(options.body); - } - } - return undefined; -}; - -export const sendRequest = async ( - config: OpenAPIConfig, - options: ApiRequestOptions, - url: string, - body: any, - formData: FormData | undefined, - headers: Headers, - onCancel: OnCancel -): Promise => { - const controller = new AbortController(); - - const request: RequestInit = { - headers, - body: body ?? formData, - method: options.method, - signal: controller.signal, - }; - - if (config.WITH_CREDENTIALS) { - request.credentials = config.CREDENTIALS; - } - - onCancel(() => controller.abort()); - - return await fetch(url, request); -}; - -export const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => { - if (responseHeader) { - const content = response.headers.get(responseHeader); - if (isString(content)) { - return content; - } - } - return undefined; -}; - -export const getResponseBody = async (response: Response): Promise => { - if (response.status !== 204) { - try { - const contentType = response.headers.get('Content-Type'); - if (contentType) { - const jsonTypes = ['application/json', 'application/problem+json'] - const isJSON = jsonTypes.some(type => contentType.toLowerCase().startsWith(type)); - if (isJSON) { - return await response.json(); - } else { - return await response.text(); - } - } - } catch (error) { - console.error(error); - } - } - return undefined; -}; - -export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { - const errors: Record = { - 400: 'Bad Request', - 401: 'Unauthorized', - 403: 'Forbidden', - 404: 'Not Found', - 500: 'Internal Server Error', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - ...options.errors, - } - - const error = errors[result.status]; - if (error) { - throw new ApiError(options, result, error); - } - - if (!result.ok) { - const errorStatus = result.status ?? 'unknown'; - const errorStatusText = result.statusText ?? 'unknown'; - const errorBody = (() => { - try { - return JSON.stringify(result.body, null, 2); - } catch (e) { - return undefined; - } - })(); - - throw new ApiError(options, result, - `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}` - ); - } -}; - -/** - * Request method - * @param config The OpenAPI configuration object - * @param options The request options from the service - * @returns CancelablePromise - * @throws ApiError - */ -export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(config, options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(config, options); - - if (!onCancel.isCancelled) { - const response = await sendRequest(config, options, url, body, formData, headers, onCancel); - const responseBody = await getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); - - const result: ApiResult = { - url, - ok: response.ok, - status: response.status, - statusText: response.statusText, - body: responseHeader ?? responseBody, - }; - - catchErrorCodes(options, result); - - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); -}; diff --git a/apps/web/src/lib/client/index.ts b/apps/web/src/lib/client/index.ts deleted file mode 100644 index 4f85ba2d..00000000 --- a/apps/web/src/lib/client/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export { ApiError } from './core/ApiError'; -export { CancelablePromise, CancelError } from './core/CancelablePromise'; -export { OpenAPI } from './core/OpenAPI'; -export type { OpenAPIConfig } from './core/OpenAPI'; - -export { AgentModel } from './models/AgentModel'; -export { AgentRequestModel } from './models/AgentRequestModel'; -export { AgentResponseModel } from './models/AgentResponseModel'; -export type { AgentUpdateModel } from './models/AgentUpdateModel'; -export type { APIKeyRequestModel } from './models/APIKeyRequestModel'; -export type { APIKeyResponseModel } from './models/APIKeyResponseModel'; -export type { APIKeyTypeModel } from './models/APIKeyTypeModel'; -export type { APIKeyTypeResponseModel } from './models/APIKeyTypeResponseModel'; -export type { APIKeyUpdateModel } from './models/APIKeyUpdateModel'; -export type { AuthResponse } from './models/AuthResponse'; -export type { CrewModel } from './models/CrewModel'; -export type { CrewRequestModel } from './models/CrewRequestModel'; -export type { CrewResponseModel } from './models/CrewResponseModel'; -export type { CrewUpdateModel } from './models/CrewUpdateModel'; -export { Factor } from './models/Factor'; -export type { gotrue__types__Session } from './models/gotrue__types__Session'; -export type { HTTPValidationError } from './models/HTTPValidationError'; -export type { Message } from './models/Message'; -export { OAuthResponse } from './models/OAuthResponse'; -export type { ProfileRequestModel } from './models/ProfileRequestModel'; -export type { ProfileResponseModel } from './models/ProfileResponseModel'; -export type { ProfileUpdateModel } from './models/ProfileUpdateModel'; -export type { RunRequestModel } from './models/RunRequestModel'; -export type { RunResponseModel } from './models/RunResponseModel'; -export type { SessionRequest } from './models/SessionRequest'; -export type { SessionResponse } from './models/SessionResponse'; -export { SessionStatus } from './models/SessionStatus'; -export type { SessionUpdate } from './models/SessionUpdate'; -export type { SignInWithEmailAndPasswordCredentials } from './models/SignInWithEmailAndPasswordCredentials'; -export { SignInWithOAuthCredentials } from './models/SignInWithOAuthCredentials'; -export type { SignInWithOAuthCredentialsOptions } from './models/SignInWithOAuthCredentialsOptions'; -export type { SignInWithPasswordCredentialsOptions } from './models/SignInWithPasswordCredentialsOptions'; -export type { SignUpWithEmailAndPasswordCredentials } from './models/SignUpWithEmailAndPasswordCredentials'; -export type { SignUpWithEmailAndPasswordCredentialsOptions } from './models/SignUpWithEmailAndPasswordCredentialsOptions'; -export type { src__models__session__Session } from './models/src__models__session__Session'; -export type { User } from './models/User'; -export type { UserIdentity } from './models/UserIdentity'; -export type { ValidationError } from './models/ValidationError'; - -export { AgentsService } from './services/AgentsService'; -export { ApiKeyTypesService } from './services/ApiKeyTypesService'; -export { AuthenticationService } from './services/AuthenticationService'; -export { CrewsService } from './services/CrewsService'; -export { DefaultService } from './services/DefaultService'; -export { MessagesService } from './services/MessagesService'; -export { ProfilesService } from './services/ProfilesService'; -export { SessionsService } from './services/SessionsService'; diff --git a/apps/web/src/lib/client/models/APIKeyRequestModel.ts b/apps/web/src/lib/client/models/APIKeyRequestModel.ts deleted file mode 100644 index a40c30fc..00000000 --- a/apps/web/src/lib/client/models/APIKeyRequestModel.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyRequestModel = { - profile_id: string; - api_key_type_id: string; - api_key: string; -}; - diff --git a/apps/web/src/lib/client/models/APIKeyResponseModel.ts b/apps/web/src/lib/client/models/APIKeyResponseModel.ts deleted file mode 100644 index babd1e1f..00000000 --- a/apps/web/src/lib/client/models/APIKeyResponseModel.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { APIKeyTypeModel } from './APIKeyTypeModel'; -export type APIKeyResponseModel = { - id: string; - created_at: string; - profile_id: string; - api_key_type?: (APIKeyTypeModel | null); - api_key: string; -}; - diff --git a/apps/web/src/lib/client/models/APIKeyTypeModel.ts b/apps/web/src/lib/client/models/APIKeyTypeModel.ts deleted file mode 100644 index 67630945..00000000 --- a/apps/web/src/lib/client/models/APIKeyTypeModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyTypeModel = { - id: string; - name: string; - created_at: string; - description: string; -}; - diff --git a/apps/web/src/lib/client/models/APIKeyTypeResponseModel.ts b/apps/web/src/lib/client/models/APIKeyTypeResponseModel.ts deleted file mode 100644 index c0680933..00000000 --- a/apps/web/src/lib/client/models/APIKeyTypeResponseModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyTypeResponseModel = { - id: string; - created_at: string; - name?: (string | null); - description?: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/APIKeyUpdateModel.ts b/apps/web/src/lib/client/models/APIKeyUpdateModel.ts deleted file mode 100644 index 0670cda5..00000000 --- a/apps/web/src/lib/client/models/APIKeyUpdateModel.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type APIKeyUpdateModel = { - api_key: string; -}; - diff --git a/apps/web/src/lib/client/models/AgentModel.ts b/apps/web/src/lib/client/models/AgentModel.ts deleted file mode 100644 index 76accc13..00000000 --- a/apps/web/src/lib/client/models/AgentModel.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentModel = { - title: string; - role: string; - system_message: string; - tools: Array>; - model: AgentModel.model; - id: string; -}; -export namespace AgentModel { - export enum model { - GPT_3_5_TURBO = 'gpt-3.5-turbo', - GPT_4_TURBO_PREVIEW = 'gpt-4-turbo-preview', - } -} - diff --git a/apps/web/src/lib/client/models/AgentRequestModel.ts b/apps/web/src/lib/client/models/AgentRequestModel.ts deleted file mode 100644 index 068943c7..00000000 --- a/apps/web/src/lib/client/models/AgentRequestModel.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentRequestModel = { - title: string; - role: string; - system_message: string; - tools: Array>; - model: AgentRequestModel.model; - description?: (string | null); - profile_id: string; - version?: (string | null); - avatar: string; -}; -export namespace AgentRequestModel { - export enum model { - GPT_3_5_TURBO = 'gpt-3.5-turbo', - GPT_4_TURBO_PREVIEW = 'gpt-4-turbo-preview', - } -} - diff --git a/apps/web/src/lib/client/models/AgentResponseModel.ts b/apps/web/src/lib/client/models/AgentResponseModel.ts deleted file mode 100644 index 0a6cb220..00000000 --- a/apps/web/src/lib/client/models/AgentResponseModel.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentResponseModel = { - title: string; - role: string; - system_message: string; - tools: Array>; - model: AgentResponseModel.model; - description?: (string | null); - profile_id: string; - version?: (string | null); - avatar: string; - id: string; - created_at: string; - published: boolean; -}; -export namespace AgentResponseModel { - export enum model { - GPT_3_5_TURBO = 'gpt-3.5-turbo', - GPT_4_TURBO_PREVIEW = 'gpt-4-turbo-preview', - } -} - diff --git a/apps/web/src/lib/client/models/AgentUpdateModel.ts b/apps/web/src/lib/client/models/AgentUpdateModel.ts deleted file mode 100644 index ed007e46..00000000 --- a/apps/web/src/lib/client/models/AgentUpdateModel.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type AgentUpdateModel = { - title?: (string | null); - role?: (string | null); - system_message?: (string | null); - tools?: null; - model?: ('gpt-3.5-turbo' | 'gpt-4-turbo-preview' | null); - description?: (string | null); - profile_id?: (string | null); - version?: (string | null); - avatar?: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/AuthResponse.ts b/apps/web/src/lib/client/models/AuthResponse.ts deleted file mode 100644 index 4f96377e..00000000 --- a/apps/web/src/lib/client/models/AuthResponse.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { gotrue__types__Session } from './gotrue__types__Session'; -import type { User } from './User'; -export type AuthResponse = { - user?: (User | null); - session?: (gotrue__types__Session | null); -}; - diff --git a/apps/web/src/lib/client/models/CrewModel.ts b/apps/web/src/lib/client/models/CrewModel.ts deleted file mode 100644 index 080b5dc4..00000000 --- a/apps/web/src/lib/client/models/CrewModel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { AgentModel } from './AgentModel'; -export type CrewModel = { - receiver_id: string; - delegator_id?: (string | null); - agents: Array; - sub_crews?: Array; -}; - diff --git a/apps/web/src/lib/client/models/CrewRequestModel.ts b/apps/web/src/lib/client/models/CrewRequestModel.ts deleted file mode 100644 index e9a9744c..00000000 --- a/apps/web/src/lib/client/models/CrewRequestModel.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type CrewRequestModel = { - receiver_id: string; - prompt: Record; - profile_id: string; - edges: Array>; - published: boolean; - title: string; - description: string; - nodes: Array; -}; - diff --git a/apps/web/src/lib/client/models/CrewResponseModel.ts b/apps/web/src/lib/client/models/CrewResponseModel.ts deleted file mode 100644 index 0716da86..00000000 --- a/apps/web/src/lib/client/models/CrewResponseModel.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type CrewResponseModel = { - id: string; - created_at: string; - profile_id: string; - edges: Array>; - published: boolean; - title: string; - description: string; - updated_at: string; - nodes: Array; - receiver_id?: (string | null); - avatar?: (string | null); - prompt?: (Record | null); -}; - diff --git a/apps/web/src/lib/client/models/CrewUpdateModel.ts b/apps/web/src/lib/client/models/CrewUpdateModel.ts deleted file mode 100644 index 202c9f92..00000000 --- a/apps/web/src/lib/client/models/CrewUpdateModel.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type CrewUpdateModel = { - receiver_id?: (string | null); - prompt?: (Record | null); - profile_id?: (string | null); - edges?: null; - published?: (boolean | null); - title?: (string | null); - description?: (string | null); - nodes?: (Array | null); -}; - diff --git a/apps/web/src/lib/client/models/Factor.ts b/apps/web/src/lib/client/models/Factor.ts deleted file mode 100644 index 586e9e82..00000000 --- a/apps/web/src/lib/client/models/Factor.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -/** - * A MFA factor. - */ -export type Factor = { - id: string; - friendly_name?: (string | null); - factor_type: string; - status: Factor.status; - created_at: string; - updated_at: string; -}; -export namespace Factor { - export enum status { - VERIFIED = 'verified', - UNVERIFIED = 'unverified', - } -} - diff --git a/apps/web/src/lib/client/models/HTTPValidationError.ts b/apps/web/src/lib/client/models/HTTPValidationError.ts deleted file mode 100644 index f9b1a79e..00000000 --- a/apps/web/src/lib/client/models/HTTPValidationError.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { ValidationError } from './ValidationError'; -export type HTTPValidationError = { - detail?: Array; -}; - diff --git a/apps/web/src/lib/client/models/Message.ts b/apps/web/src/lib/client/models/Message.ts deleted file mode 100644 index 992a4dde..00000000 --- a/apps/web/src/lib/client/models/Message.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type Message = { - id?: string; - session_id: string; - profile_id: string; - sender_id?: (string | null); - recipient_id?: (string | null); - content: string; - role?: string; - created_at?: string; -}; - diff --git a/apps/web/src/lib/client/models/OAuthResponse.ts b/apps/web/src/lib/client/models/OAuthResponse.ts deleted file mode 100644 index 9369453c..00000000 --- a/apps/web/src/lib/client/models/OAuthResponse.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type OAuthResponse = { - provider: OAuthResponse.provider; - url: string; -}; -export namespace OAuthResponse { - export enum provider { - APPLE = 'apple', - AZURE = 'azure', - BITBUCKET = 'bitbucket', - DISCORD = 'discord', - FACEBOOK = 'facebook', - FIGMA = 'figma', - GITHUB = 'github', - GITLAB = 'gitlab', - GOOGLE = 'google', - KAKAO = 'kakao', - KEYCLOAK = 'keycloak', - LINKEDIN = 'linkedin', - NOTION = 'notion', - SLACK = 'slack', - SPOTIFY = 'spotify', - TWITCH = 'twitch', - TWITTER = 'twitter', - WORKOS = 'workos', - ZOOM = 'zoom', - } -} - diff --git a/apps/web/src/lib/client/models/ProfileRequestModel.ts b/apps/web/src/lib/client/models/ProfileRequestModel.ts deleted file mode 100644 index d456b6e7..00000000 --- a/apps/web/src/lib/client/models/ProfileRequestModel.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ProfileRequestModel = { - user_id: string; - tier_id: string; - display_name: string; - stripe_customer_id?: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/ProfileResponseModel.ts b/apps/web/src/lib/client/models/ProfileResponseModel.ts deleted file mode 100644 index 02d108cf..00000000 --- a/apps/web/src/lib/client/models/ProfileResponseModel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ProfileResponseModel = { - id: string; - tier_id: string; - created_at: string; - display_name: string; - stripe_customer_id: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/ProfileUpdateModel.ts b/apps/web/src/lib/client/models/ProfileUpdateModel.ts deleted file mode 100644 index 8471aeb0..00000000 --- a/apps/web/src/lib/client/models/ProfileUpdateModel.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ProfileUpdateModel = { - tier_id?: (string | null); - display_name?: (string | null); - stripe_customer_id?: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/RunRequestModel.ts b/apps/web/src/lib/client/models/RunRequestModel.ts deleted file mode 100644 index 4e3920da..00000000 --- a/apps/web/src/lib/client/models/RunRequestModel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type RunRequestModel = { - id: string; - profile_id: string; - session_title?: string; - session_id?: (string | null); - reply?: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/RunResponseModel.ts b/apps/web/src/lib/client/models/RunResponseModel.ts deleted file mode 100644 index 9bc0397c..00000000 --- a/apps/web/src/lib/client/models/RunResponseModel.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { src__models__session__Session } from './src__models__session__Session'; -export type RunResponseModel = { - status: ; - session: src__models__session__Session; -}; - diff --git a/apps/web/src/lib/client/models/SessionRequest.ts b/apps/web/src/lib/client/models/SessionRequest.ts deleted file mode 100644 index 6a398967..00000000 --- a/apps/web/src/lib/client/models/SessionRequest.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SessionRequest = { - crew_id: string; - profile_id: string; - title: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/SessionResponse.ts b/apps/web/src/lib/client/models/SessionResponse.ts deleted file mode 100644 index 56bf4c6a..00000000 --- a/apps/web/src/lib/client/models/SessionResponse.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SessionStatus } from './SessionStatus'; -export type SessionResponse = { - crew_id: string; - profile_id: string; - title: (string | null); - id?: string; - created_at?: string; - status?: SessionStatus; -}; - diff --git a/apps/web/src/lib/client/models/SessionStatus.ts b/apps/web/src/lib/client/models/SessionStatus.ts deleted file mode 100644 index fbbf267b..00000000 --- a/apps/web/src/lib/client/models/SessionStatus.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export enum SessionStatus { - RUNNING = 'running', - FINISHED = 'finished', - IDLE = 'idle', -} diff --git a/apps/web/src/lib/client/models/SessionUpdate.ts b/apps/web/src/lib/client/models/SessionUpdate.ts deleted file mode 100644 index 51845c2c..00000000 --- a/apps/web/src/lib/client/models/SessionUpdate.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SessionStatus } from './SessionStatus'; -export type SessionUpdate = { - crew_id?: (string | null); - profile_id?: (string | null); - title?: (string | null); - status?: (SessionStatus | null); -}; - diff --git a/apps/web/src/lib/client/models/SignInWithEmailAndPasswordCredentials.ts b/apps/web/src/lib/client/models/SignInWithEmailAndPasswordCredentials.ts deleted file mode 100644 index 4450a63d..00000000 --- a/apps/web/src/lib/client/models/SignInWithEmailAndPasswordCredentials.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SignInWithPasswordCredentialsOptions } from './SignInWithPasswordCredentialsOptions'; -export type SignInWithEmailAndPasswordCredentials = { - email: string; - password: string; - options?: SignInWithPasswordCredentialsOptions; -}; - diff --git a/apps/web/src/lib/client/models/SignInWithOAuthCredentials.ts b/apps/web/src/lib/client/models/SignInWithOAuthCredentials.ts deleted file mode 100644 index b5f7a18c..00000000 --- a/apps/web/src/lib/client/models/SignInWithOAuthCredentials.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SignInWithOAuthCredentialsOptions } from './SignInWithOAuthCredentialsOptions'; -export type SignInWithOAuthCredentials = { - provider: SignInWithOAuthCredentials.provider; - options?: SignInWithOAuthCredentialsOptions; -}; -export namespace SignInWithOAuthCredentials { - export enum provider { - APPLE = 'apple', - AZURE = 'azure', - BITBUCKET = 'bitbucket', - DISCORD = 'discord', - FACEBOOK = 'facebook', - FIGMA = 'figma', - GITHUB = 'github', - GITLAB = 'gitlab', - GOOGLE = 'google', - KAKAO = 'kakao', - KEYCLOAK = 'keycloak', - LINKEDIN = 'linkedin', - NOTION = 'notion', - SLACK = 'slack', - SPOTIFY = 'spotify', - TWITCH = 'twitch', - TWITTER = 'twitter', - WORKOS = 'workos', - ZOOM = 'zoom', - } -} - diff --git a/apps/web/src/lib/client/models/SignInWithOAuthCredentialsOptions.ts b/apps/web/src/lib/client/models/SignInWithOAuthCredentialsOptions.ts deleted file mode 100644 index fd2b0a18..00000000 --- a/apps/web/src/lib/client/models/SignInWithOAuthCredentialsOptions.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SignInWithOAuthCredentialsOptions = { - redirect_to?: string; - scopes?: string; - query_params?: Record; -}; - diff --git a/apps/web/src/lib/client/models/SignInWithPasswordCredentialsOptions.ts b/apps/web/src/lib/client/models/SignInWithPasswordCredentialsOptions.ts deleted file mode 100644 index e6445aa3..00000000 --- a/apps/web/src/lib/client/models/SignInWithPasswordCredentialsOptions.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SignInWithPasswordCredentialsOptions = { - data?: any; - captcha_token?: string; -}; - diff --git a/apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentials.ts b/apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentials.ts deleted file mode 100644 index 8d051b63..00000000 --- a/apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentials.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SignUpWithEmailAndPasswordCredentialsOptions } from './SignUpWithEmailAndPasswordCredentialsOptions'; -export type SignUpWithEmailAndPasswordCredentials = { - email: string; - password: string; - options?: SignUpWithEmailAndPasswordCredentialsOptions; -}; - diff --git a/apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentialsOptions.ts b/apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentialsOptions.ts deleted file mode 100644 index ab535861..00000000 --- a/apps/web/src/lib/client/models/SignUpWithEmailAndPasswordCredentialsOptions.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type SignUpWithEmailAndPasswordCredentialsOptions = { - email_redirect_to?: string; - data?: any; - captcha_token?: string; -}; - diff --git a/apps/web/src/lib/client/models/User.ts b/apps/web/src/lib/client/models/User.ts deleted file mode 100644 index 9aac1bb6..00000000 --- a/apps/web/src/lib/client/models/User.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { Factor } from './Factor'; -import type { UserIdentity } from './UserIdentity'; -export type User = { - id: string; - app_metadata: Record; - user_metadata: Record; - aud: string; - confirmation_sent_at?: (string | null); - recovery_sent_at?: (string | null); - email_change_sent_at?: (string | null); - new_email?: (string | null); - invited_at?: (string | null); - action_link?: (string | null); - email?: (string | null); - phone?: (string | null); - created_at: string; - confirmed_at?: (string | null); - email_confirmed_at?: (string | null); - phone_confirmed_at?: (string | null); - last_sign_in_at?: (string | null); - role?: (string | null); - updated_at?: (string | null); - identities?: (Array | null); - factors?: (Array | null); -}; - diff --git a/apps/web/src/lib/client/models/UserIdentity.ts b/apps/web/src/lib/client/models/UserIdentity.ts deleted file mode 100644 index 92317cd4..00000000 --- a/apps/web/src/lib/client/models/UserIdentity.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type UserIdentity = { - id: string; - user_id: string; - identity_data: Record; - provider: string; - created_at: string; - last_sign_in_at?: (string | null); - updated_at?: (string | null); -}; - diff --git a/apps/web/src/lib/client/models/ValidationError.ts b/apps/web/src/lib/client/models/ValidationError.ts deleted file mode 100644 index aaf1c921..00000000 --- a/apps/web/src/lib/client/models/ValidationError.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -export type ValidationError = { - loc: Array<(string | number)>; - msg: string; - type: string; -}; - diff --git a/apps/web/src/lib/client/models/gotrue__types__Session.ts b/apps/web/src/lib/client/models/gotrue__types__Session.ts deleted file mode 100644 index e6bd9cfd..00000000 --- a/apps/web/src/lib/client/models/gotrue__types__Session.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { User } from './User'; -export type gotrue__types__Session = { - provider_token?: (string | null); - provider_refresh_token?: (string | null); - access_token: string; - refresh_token: string; - expires_in: number; - expires_at?: (number | null); - token_type: string; - user: User; -}; - diff --git a/apps/web/src/lib/client/models/src__models__session__Session.ts b/apps/web/src/lib/client/models/src__models__session__Session.ts deleted file mode 100644 index 3c4f9ca3..00000000 --- a/apps/web/src/lib/client/models/src__models__session__Session.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { SessionStatus } from './SessionStatus'; -export type src__models__session__Session = { - crew_id: string; - profile_id: string; - title: (string | null); - id?: string; - created_at?: string; - status?: SessionStatus; -}; - diff --git a/apps/web/src/lib/client/services/AgentsService.ts b/apps/web/src/lib/client/services/AgentsService.ts deleted file mode 100644 index edd9dc09..00000000 --- a/apps/web/src/lib/client/services/AgentsService.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { AgentRequestModel } from '../models/AgentRequestModel'; -import type { AgentResponseModel } from '../models/AgentResponseModel'; -import type { AgentUpdateModel } from '../models/AgentUpdateModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class AgentsService { - /** - * Get Published Agents - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getPublishedAgentsAgentsPublishedGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/published', - }); - } - /** - * Get Users Agents - * @param profileId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getUsersAgentsAgentsByProfileGet( - profileId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/by_profile', - query: { - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Agents From Crew - * @param crewId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getAgentsFromCrewAgentsByCrewGet( - crewId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/by_crew', - query: { - 'crew_id': crewId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Agent By Id - * @param agentId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static getAgentByIdAgentsAgentIdGet( - agentId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/agents/{agent_id}', - path: { - 'agent_id': agentId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Patch Agent - * @param agentId - * @param requestBody - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static patchAgentAgentsAgentIdPatch( - agentId: string, - requestBody: AgentUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/agents/{agent_id}', - path: { - 'agent_id': agentId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Delete Agent - * @param agentId - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static deleteAgentAgentsAgentIdDelete( - agentId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/agents/{agent_id}', - path: { - 'agent_id': agentId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Insert Agent - * @param requestBody - * @returns AgentResponseModel Successful Response - * @throws ApiError - */ - public static insertAgentAgentsPost( - requestBody: AgentRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/agents/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/src/lib/client/services/ApiKeyTypesService.ts b/apps/web/src/lib/client/services/ApiKeyTypesService.ts deleted file mode 100644 index 75f7f111..00000000 --- a/apps/web/src/lib/client/services/ApiKeyTypesService.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { APIKeyTypeResponseModel } from '../models/APIKeyTypeResponseModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class ApiKeyTypesService { - /** - * Get All Api Key Types - * @returns APIKeyTypeResponseModel Successful Response - * @throws ApiError - */ - public static getAllApiKeyTypesApiKeyTypesGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/api_key_types/', - }); - } -} diff --git a/apps/web/src/lib/client/services/AuthenticationService.ts b/apps/web/src/lib/client/services/AuthenticationService.ts deleted file mode 100644 index 95800c02..00000000 --- a/apps/web/src/lib/client/services/AuthenticationService.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { AuthResponse } from '../models/AuthResponse'; -import type { OAuthResponse } from '../models/OAuthResponse'; -import type { SignInWithEmailAndPasswordCredentials } from '../models/SignInWithEmailAndPasswordCredentials'; -import type { SignInWithOAuthCredentials } from '../models/SignInWithOAuthCredentials'; -import type { SignUpWithEmailAndPasswordCredentials } from '../models/SignUpWithEmailAndPasswordCredentials'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class AuthenticationService { - /** - * Email Sign Up - * format for passing display name: 'options': {'data':{'display_name': 'name'}} - * @param requestBody - * @returns AuthResponse Successful Response - * @throws ApiError - */ - public static emailSignUpAuthSignUpPost( - requestBody: SignUpWithEmailAndPasswordCredentials, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/auth/sign_up', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Email Sign In - * @param requestBody - * @returns AuthResponse Successful Response - * @throws ApiError - */ - public static emailSignInAuthSignInPost( - requestBody: SignInWithEmailAndPasswordCredentials, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/auth/sign_in', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Provider Sign In - * @param requestBody - * @returns OAuthResponse Successful Response - * @throws ApiError - */ - public static providerSignInAuthSignInProviderPost( - requestBody: SignInWithOAuthCredentials, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/auth/sign_in/provider', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/src/lib/client/services/CrewsService.ts b/apps/web/src/lib/client/services/CrewsService.ts deleted file mode 100644 index 02e3926d..00000000 --- a/apps/web/src/lib/client/services/CrewsService.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CrewRequestModel } from '../models/CrewRequestModel'; -import type { CrewResponseModel } from '../models/CrewResponseModel'; -import type { CrewUpdateModel } from '../models/CrewUpdateModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class CrewsService { - /** - * Insert Crew - * @param requestBody - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static insertCrewCrewsPost( - requestBody: CrewRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/crews/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Crews Of User - * @param byProfile - * @param ascending - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static getCrewsOfUserCrewsGet( - byProfile: string, - ascending: boolean = false, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/crews/', - query: { - 'by_profile': byProfile, - 'ascending': ascending, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Crew - * @param crewId - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static getCrewCrewsCrewIdGet( - crewId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/crews/{crew_id}', - path: { - 'crew_id': crewId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Crew - * @param crewId - * @param requestBody - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static updateCrewCrewsCrewIdPatch( - crewId: string, - requestBody: CrewUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/crews/{crew_id}', - path: { - 'crew_id': crewId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Published Crews - * @returns CrewResponseModel Successful Response - * @throws ApiError - */ - public static getPublishedCrewsCrewsPublishedGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/crews/published', - }); - } -} diff --git a/apps/web/src/lib/client/services/DefaultService.ts b/apps/web/src/lib/client/services/DefaultService.ts deleted file mode 100644 index 65f4bd40..00000000 --- a/apps/web/src/lib/client/services/DefaultService.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { CrewModel } from '../models/CrewModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class DefaultService { - /** - * Redirect To Docs - * @returns any Successful Response - * @throws ApiError - */ - public static redirectToDocsGet(): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/', - }); - } - /** - * Compile - * @param id - * @returns any Successful Response - * @throws ApiError - */ - public static compileCompileGet( - id: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/compile', - query: { - 'id': id, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Improve - * @param wordLimit - * @param prompt - * @param promptType - * @param temperature - * @param profileId - * @returns string Successful Response - * @throws ApiError - */ - public static improveImproveGet( - wordLimit: number, - prompt: string, - promptType: 'generic' | 'system' | 'user', - temperature: number, - profileId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/improve', - query: { - 'word_limit': wordLimit, - 'prompt': prompt, - 'prompt_type': promptType, - 'temperature': temperature, - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Auto Build Crew - * @param generalTask - * @param profileId - * @returns string Successful Response - * @throws ApiError - */ - public static autoBuildCrewAutoBuildGet( - generalTask: string, - profileId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/auto-build', - query: { - 'general_task': generalTask, - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Profile From Header - * @returns any Successful Response - * @throws ApiError - */ - public static getProfileFromHeaderMeGet(): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/me', - }); - } -} diff --git a/apps/web/src/lib/client/services/MessagesService.ts b/apps/web/src/lib/client/services/MessagesService.ts deleted file mode 100644 index 6542df70..00000000 --- a/apps/web/src/lib/client/services/MessagesService.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { Message } from '../models/Message'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class MessagesService { - /** - * Get Messages - * @param sessionId - * @returns Message Successful Response - * @throws ApiError - */ - public static getMessagesSessionsMessagesGet( - sessionId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/sessions/messages/', - query: { - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/src/lib/client/services/ProfilesService.ts b/apps/web/src/lib/client/services/ProfilesService.ts deleted file mode 100644 index 229942db..00000000 --- a/apps/web/src/lib/client/services/ProfilesService.ts +++ /dev/null @@ -1,173 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { APIKeyRequestModel } from '../models/APIKeyRequestModel'; -import type { APIKeyResponseModel } from '../models/APIKeyResponseModel'; -import type { APIKeyUpdateModel } from '../models/APIKeyUpdateModel'; -import type { ProfileRequestModel } from '../models/ProfileRequestModel'; -import type { ProfileResponseModel } from '../models/ProfileResponseModel'; -import type { ProfileUpdateModel } from '../models/ProfileUpdateModel'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class ProfilesService { - /** - * Get Profiles - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static getProfilesProfilesGet(): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/profiles/', - }); - } - /** - * Insert Profile - * @param requestBody - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static insertProfileProfilesPost( - requestBody: ProfileRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/profiles/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Profile - * @param profileId - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static getProfileProfilesProfileIdGet( - profileId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/profiles/{profile_id}', - path: { - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Profile - * @param profileId - * @param requestBody - * @returns ProfileResponseModel Successful Response - * @throws ApiError - */ - public static updateProfileProfilesProfileIdPatch( - profileId: string, - requestBody: ProfileUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/profiles/{profile_id}', - path: { - 'profile_id': profileId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Api Keys - * Returns api keys with the api key type as an object with the id, name, description etc. - * @param profileId - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static getApiKeysProfilesProfileIdApiKeysGet( - profileId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/profiles/{profile_id}/api_keys', - path: { - 'profile_id': profileId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Insert Api Key - * @param requestBody - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static insertApiKeyProfilesApiKeysPost( - requestBody: APIKeyRequestModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/profiles/api_keys', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Delete Api Key - * @param apiKeyId - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static deleteApiKeyProfilesApiKeysApiKeyIdDelete( - apiKeyId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/profiles/api_keys/{api_key_id}', - path: { - 'api_key_id': apiKeyId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Api Key - * @param apiKeyId - * @param requestBody - * @returns APIKeyResponseModel Successful Response - * @throws ApiError - */ - public static updateApiKeyProfilesApiKeysApiKeyIdPatch( - apiKeyId: string, - requestBody: APIKeyUpdateModel, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/profiles/api_keys/{api_key_id}', - path: { - 'api_key_id': apiKeyId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/src/lib/client/services/SessionsService.ts b/apps/web/src/lib/client/services/SessionsService.ts deleted file mode 100644 index d3351d2a..00000000 --- a/apps/web/src/lib/client/services/SessionsService.ts +++ /dev/null @@ -1,146 +0,0 @@ -/* generated using openapi-typescript-codegen -- do not edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ -import type { Message } from '../models/Message'; -import type { RunRequestModel } from '../models/RunRequestModel'; -import type { RunResponseModel } from '../models/RunResponseModel'; -import type { SessionRequest } from '../models/SessionRequest'; -import type { SessionResponse } from '../models/SessionResponse'; -import type { SessionUpdate } from '../models/SessionUpdate'; -import type { src__models__session__Session } from '../models/src__models__session__Session'; -import type { CancelablePromise } from '../core/CancelablePromise'; -import { OpenAPI } from '../core/OpenAPI'; -import { request as __request } from '../core/request'; -export class SessionsService { - /** - * Get Sessions - * @param profileId - * @param sessionId - * @returns src__models__session__Session Successful Response - * @throws ApiError - */ - public static getSessionsSessionsGet( - profileId?: (string | null), - sessionId?: (string | null), - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/sessions/', - query: { - 'profile_id': profileId, - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Insert Session - * @param requestBody - * @returns SessionResponse Successful Response - * @throws ApiError - */ - public static insertSessionSessionsPost( - requestBody: SessionRequest, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/sessions/', - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Update Session - * @param sessionId - * @param requestBody - * @returns SessionResponse Successful Response - * @throws ApiError - */ - public static updateSessionSessionsSessionIdPatch( - sessionId: string, - requestBody: SessionUpdate, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'PATCH', - url: '/sessions/{session_id}', - path: { - 'session_id': sessionId, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Delete Session - * @param sessionId - * @returns void - * @throws ApiError - */ - public static deleteSessionSessionsSessionIdDelete( - sessionId: string, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'DELETE', - url: '/sessions/{session_id}', - path: { - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Run Crew - * @param requestBody - * @param mock - * @returns RunResponseModel Successful Response - * @throws ApiError - */ - public static runCrewSessionsRunPost( - requestBody: RunRequestModel, - mock: boolean = false, - ): CancelablePromise { - return __request(OpenAPI, { - method: 'POST', - url: '/sessions/run', - query: { - 'mock': mock, - }, - body: requestBody, - mediaType: 'application/json', - errors: { - 422: `Validation Error`, - }, - }); - } - /** - * Get Messages - * @param sessionId - * @returns Message Successful Response - * @throws ApiError - */ - public static getMessagesSessionsMessagesGet( - sessionId: string, - ): CancelablePromise> { - return __request(OpenAPI, { - method: 'GET', - url: '/sessions/messages/', - query: { - 'session_id': sessionId, - }, - errors: { - 422: `Validation Error`, - }, - }); - } -} diff --git a/apps/web/src/lib/components/RightEditorSidebar.svelte b/apps/web/src/lib/components/RightEditorSidebar.svelte index e79ca80f..57fedf82 100644 --- a/apps/web/src/lib/components/RightEditorSidebar.svelte +++ b/apps/web/src/lib/components/RightEditorSidebar.svelte @@ -14,7 +14,7 @@

- - - diff --git a/apps/web/src/routes/(marketing)/(auth)/register/+page.server.ts b/apps/web/src/routes/(marketing)/(auth)/register/+page.server.ts deleted file mode 100644 index f93213af..00000000 --- a/apps/web/src/routes/(marketing)/(auth)/register/+page.server.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { fail, redirect } from '@sveltejs/kit'; -import { superValidate } from 'sveltekit-superforms/server'; -import { zod } from 'sveltekit-superforms/adapters'; -import { formSchema } from '$lib/schema'; -import { type Provider } from '@supabase/supabase-js'; - -export const load = async () => { - return { - registerForm: await superValidate(zod(formSchema)) - }; -}; - -// TODO: Passwordless auth -export const actions = { - register: async ({ request, locals: { stripe, supabase }, url }) => { - const body = Object.fromEntries(await request.formData()); - - const provider = url.searchParams.get('provider') as Provider; - - try { - const customer = await stripe.customers.create({ - email: body.email as string, - name: body.display_name as string - }); - - if (provider) { - const { data, error: err } = await supabase.auth.signInWithOAuth({ - provider: provider - }); - - console.log(data, 'data from'); - - if (err) { - console.log(err); - return fail(400, { - message: 'Something went wrong' - }); - } - - const user = data.user; - - if (user) { - const { error: profileError } = await supabase.from('profiles').upsert({ - id: user.id, - display_name: body.display_name as string, - stripe_customer_id: customer.id - }); - - if (profileError) { - console.error('Failed to create user profile:', profileError); - return fail(500, { error: 'Failed to create user profile', profileError }); - } - } - - throw redirect(307, data.url); - } - - const form = await superValidate(body, formSchema); - - if (!provider) { - if (!form.valid) { - return fail(400, { - form, - success: false, - errors: form.errors - }); - } - } - - const { data, error: err } = await supabase.auth.signUp({ - email: body.email as string, - password: body.password as string, - options: { - data: { - display_name: body.display_name as string - } - } - }); - - if (err) { - return fail(400, { - error: err.message - }); - } - - console.log(body, 'body from register +page.server.ts'); - const user = data.user; - - if (user) { - const { error: profileError } = await supabase.from('profiles').upsert({ - id: user.id, - display_name: body.display_name as string, - stripe_customer_id: customer.id - }); - - if (profileError) { - console.error('email already registered!', profileError); - return fail(500, { error: 'email already registered!' }); - } - } - - throw redirect(302, ''); - } catch (error) { - console.error('Unexpected server error:', error); - return fail(500, { error: 'An unexpected error occurred. Please try again.' }); - } - } -}; diff --git a/apps/web/src/routes/(marketing)/(auth)/register/+page.svelte b/apps/web/src/routes/(marketing)/(auth)/register/+page.svelte deleted file mode 100644 index be2dfa3a..00000000 --- a/apps/web/src/routes/(marketing)/(auth)/register/+page.svelte +++ /dev/null @@ -1,202 +0,0 @@ - - -{#if isSubmittedSuccessfully} - - - Check Your Email - - -

- We've sent a confirmation email to you. Please check your inbox to complete the registration - process. -

- -
-
-{:else} - - - Create an account - Enter your email below to create your account - - -
-
- - -
- -
-
- -
-
- Or continue with -
-
-
-
- - - {#if $errors.display_name} - - {$errors.display_name} - - {/if} -
-
- - - {#if $errors.email} - - {$errors.email} - - {/if} -
-
- - - {#if $errors.password && $errors.password.length > 0} - - - {#each $errors.password as error} -
{error}
- {/each} -
-
- {/if} -
- {#if form?.error} - - {form?.error} - - {/if} - -
-
-
-
- -

- Already have an account? Sign in -

-
-
-{/if} diff --git a/apps/web/src/routes/(marketing)/+layout.svelte b/apps/web/src/routes/(marketing)/+layout.svelte index 28c08a67..96c4a014 100644 --- a/apps/web/src/routes/(marketing)/+layout.svelte +++ b/apps/web/src/routes/(marketing)/+layout.svelte @@ -12,7 +12,7 @@ export let CTAButtons: { [label: string]: { href: string; highlight: boolean }; } = { - 'Sign In': { href: '/register', highlight: true } + 'Sign In': { href: '/auth', highlight: true } }; diff --git a/apps/web/src/routes/(marketing)/(auth)/+layout.svelte b/apps/web/src/routes/(marketing)/auth/+layout.svelte similarity index 100% rename from apps/web/src/routes/(marketing)/(auth)/+layout.svelte rename to apps/web/src/routes/(marketing)/auth/+layout.svelte diff --git a/apps/web/src/routes/(marketing)/auth/+page.server.ts b/apps/web/src/routes/(marketing)/auth/+page.server.ts new file mode 100644 index 00000000..9210839d --- /dev/null +++ b/apps/web/src/routes/(marketing)/auth/+page.server.ts @@ -0,0 +1,70 @@ +import { fail, redirect } from '@sveltejs/kit'; +import { superValidate } from 'sveltekit-superforms/server'; +import { zod } from 'sveltekit-superforms/adapters'; +import { emailAuthSchema } from '$lib/schema'; +import { type Provider } from '@supabase/supabase-js'; + +export async function load({ locals: { safeGetSession } }) { + const auth = await safeGetSession(); + if (auth) { + redirect(303, '/app'); + } + + const form = await superValidate(zod(emailAuthSchema)); + + return { + form + }; +} + +export const actions = { + authEmail: async ({ request, locals: { supabase }, url }) => { + const form = await superValidate(request, zod(emailAuthSchema)); + if (!form.valid) { + return fail(400, { form }); + } + const { data } = form; + + const { error: e } = await supabase.auth.signInWithOtp({ + email: data.email, + options: { + emailRedirectTo: `https://${url.host}/app` + } + }); + + if (e) { + return fail(500, { + error: e.message + }); + } + + throw redirect(303, '/auth/verify-email'); + }, + authProvider: async ({ locals: { supabase }, url }) => { + const validProviders = ['google', 'github']; + + if (!url.searchParams.has('provider')) { + return fail(400, { + message: 'No provider given.' + }); + } + if (!validProviders.includes(url.searchParams.get('provider') as string)) { + return fail(400, { + message: 'Invalid provider' + }); + } + + const { data, error: err } = await supabase.auth.signInWithOAuth({ + provider: url.searchParams.get('provider') as Provider + }); + + if (err) { + console.error('Failed to sign in with OAuth:', err); + return fail(500, { + message: 'Failed to sign in with OAuth' + }); + } + + throw redirect(307, data.url); + } +}; diff --git a/apps/web/src/routes/(marketing)/auth/+page.svelte b/apps/web/src/routes/(marketing)/auth/+page.svelte new file mode 100644 index 00000000..d9b8853a --- /dev/null +++ b/apps/web/src/routes/(marketing)/auth/+page.svelte @@ -0,0 +1,58 @@ + + + + + Authenticate + + +
+ + + Google + + + + GitHub + +
+ +
+
+ +
+
+ Or continue with +
+
+ + +
+
diff --git a/apps/web/src/routes/(marketing)/auth/EmailForm.svelte b/apps/web/src/routes/(marketing)/auth/EmailForm.svelte new file mode 100644 index 00000000..40c37769 --- /dev/null +++ b/apps/web/src/routes/(marketing)/auth/EmailForm.svelte @@ -0,0 +1,31 @@ + + +
+ + + E-Mail + + + + + + Submit +
diff --git a/apps/web/src/routes/(marketing)/auth/ProviderButton.svelte b/apps/web/src/routes/(marketing)/auth/ProviderButton.svelte new file mode 100644 index 00000000..6e8be738 --- /dev/null +++ b/apps/web/src/routes/(marketing)/auth/ProviderButton.svelte @@ -0,0 +1,11 @@ + + +
+ + + +
diff --git a/apps/web/src/routes/(marketing)/auth/verify-email/+page.svelte b/apps/web/src/routes/(marketing)/auth/verify-email/+page.svelte new file mode 100644 index 00000000..8e0c5895 --- /dev/null +++ b/apps/web/src/routes/(marketing)/auth/verify-email/+page.svelte @@ -0,0 +1,17 @@ + + + + + Check Your Email + + +

+ We've sent a confirmation email to you. Please check your inbox to complete the registration + process. +

+ +
+
diff --git a/apps/web/src/routes/app/+layout.server.ts b/apps/web/src/routes/app/+layout.server.ts index bcb9217b..740578be 100644 --- a/apps/web/src/routes/app/+layout.server.ts +++ b/apps/web/src/routes/app/+layout.server.ts @@ -1,8 +1,9 @@ import type Stripe from 'stripe'; import { error } from '@sveltejs/kit'; -export const load = async ({ locals: { supabase, stripe, authGetSession, safeGetSession } }) => { - const userSession = await authGetSession(); +export const load = async ({ locals: { supabase, stripe, authGetUser } }) => { + const user = await authGetUser(); + console.log('user', user); // TODO: convert to using api @@ -16,25 +17,19 @@ export const load = async ({ locals: { supabase, stripe, authGetSession, safeGet const { data: subscription } = await supabase .from('subscriptions') .select() - .eq('profile_id', userSession?.user.id) - .single(); - - const { data: profile } = await supabase - .from('profiles') - .select('tiers ( * )') - .eq('id', userSession?.user.id) + .eq('profile_id', user.id) .single(); const { data: tiersList } = await supabase.from('tiers').select(); data.tiersList = tiersList ?? []; - data.userTier = profile?.tiers as any; // TODO: don't use any + data.userTier = user?.tiers as any; // TODO: don't use any const { data: billing } = await supabase .from('billing_information') .select() - .eq('profile_id', userSession?.user.id) + .eq('profile_id', user.id) .single(); try { @@ -53,5 +48,8 @@ export const load = async ({ locals: { supabase, stripe, authGetSession, safeGet data.stripeSub = null; } - return data; + return { + user, + ...data + }; }; diff --git a/apps/web/src/routes/app/+layout.svelte b/apps/web/src/routes/app/+layout.svelte index 82442413..a13ad41a 100644 --- a/apps/web/src/routes/app/+layout.svelte +++ b/apps/web/src/routes/app/+layout.svelte @@ -2,7 +2,7 @@ import { writable } from 'svelte/store'; import { Shell } from '$lib/components/layout/shell'; - import { SideNav } from '$lib/components/ui/side-nav'; + import SideNav from './SideNav.svelte'; import { CircleUserRound, Dna, LogOut, MessagesSquare, UsersRound, Zap } from 'lucide-svelte'; import type { ComponentType } from 'svelte'; @@ -78,7 +78,7 @@ {#key subscribed} - + {/key} diff --git a/apps/web/src/lib/components/ui/side-nav/side-nav.svelte b/apps/web/src/routes/app/SideNav.svelte similarity index 80% rename from apps/web/src/lib/components/ui/side-nav/side-nav.svelte rename to apps/web/src/routes/app/SideNav.svelte index c1f370f8..4ae0a130 100644 --- a/apps/web/src/lib/components/ui/side-nav/side-nav.svelte +++ b/apps/web/src/routes/app/SideNav.svelte @@ -3,12 +3,11 @@ import { LogOut, Zap } from 'lucide-svelte'; import type { ComponentType } from 'svelte'; import type { Icon } from 'lucide-svelte'; - import { Logo } from '../logo'; - import * as Dialog from '$lib/components/ui/dialog'; - import PricingTiers from '$lib/components/pricing/PricingTiers.svelte'; - import { Button } from '$lib/components/ui/button'; + import { Logo } from '$lib/components/ui/logo'; + import type { schemas } from '$lib/api'; + import type { User } from '@supabase/supabase-js'; - export let subscribed = false; + export let user: User & schemas['Profile']; export let navigations: { name: string; @@ -33,8 +32,6 @@ } ]; export let bottomNavigation = [{ name: 'Logout', href: '/', icon: LogOut, current: false }]; // TODO: Make this button actually log out the user - - let tiersOpen = false; @@ -44,13 +41,22 @@ class="flex grow flex-col gap-y-5 overflow-hidden rounded-2xl border bg-primary-950/30 px-6 pb-6 text-white" > + +