kanha-upadhyay commited on
Commit
3345ea7
·
0 Parent(s):

Add initial project setup with email proposal generation functionality

Browse files
.env.example ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ SMTP_SERVER=
2
+ SMTP_PORT=
3
+ SMTP_USERNAME=
4
+ SMTP_PASSWORD=
5
+ SENDER_EMAIL=
6
+ RECIPIENT_EMAIL=
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
98
+ __pypackages__/
99
+
100
+ # Celery stuff
101
+ celerybeat-schedule
102
+ celerybeat.pid
103
+
104
+ # SageMath parsed files
105
+ *.sage.py
106
+
107
+ # Environments
108
+ .env
109
+ .venv
110
+ env/
111
+ venv/
112
+ ENV/
113
+ env.bak/
114
+ venv.bak/
115
+
116
+ # Spyder project settings
117
+ .spyderproject
118
+ .spyproject
119
+
120
+ # Rope project settings
121
+ .ropeproject
122
+
123
+ # mkdocs documentation
124
+ /site
125
+
126
+ # mypy
127
+ .mypy_cache/
128
+ .dmypy.json
129
+ dmypy.json
130
+
131
+ # Pyre type checker
132
+ .pyre/
133
+
134
+ # pytype static type analyzer
135
+ .pytype/
136
+
137
+ # Cython debug symbols
138
+ cython_debug/
139
+
140
+ .vscode
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12
2
+
3
+ WORKDIR /app
4
+
5
+ RUN pip install poetry
6
+
7
+ RUN poetry config virtualenvs.create false
8
+
9
+ COPY pyproject.toml poetry.lock /app/
10
+
11
+ RUN poetry install --only main --no-root
12
+
13
+ RUN useradd -m -u 1000 user
14
+
15
+ RUN chown -R user /app
16
+
17
+ USER user
18
+
19
+ COPY --chown=user src /app/src
20
+
21
+ EXPOSE 7860
22
+
23
+ ENV PYTHONUNBUFFERED=1
24
+
25
+ CMD ["uvicorn", "src.app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Proposal Generator
3
+ emoji: 🌍
4
+ colorFrom: yellow
5
+ colorTo: gray
6
+ sdk: docker
7
+ # sdk: streamlit
8
+ sdk_version: 1.41.1
9
+ app_file: app.py
10
+ pinned: false
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
custom-gpt-action.yaml ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Proposal Generation API
4
+ description: This API generates project proposals based on user input.
5
+ version: 1.0.0
6
+ servers:
7
+ - url: https://sifars-proposal-generator.hf.space
8
+ description: Main server for proposal generation.
9
+ paths:
10
+ /proposals/:
11
+ post:
12
+ operationId: generateProposal
13
+ summary: Generates a project proposal
14
+ requestBody:
15
+ required: true
16
+ content:
17
+ application/json:
18
+ schema:
19
+ $ref: "#/components/schemas/ProposalRequest"
20
+ responses:
21
+ "200":
22
+ description: Successfully generated proposal
23
+ content:
24
+ application/json:
25
+ schema:
26
+ type: object
27
+ properties:
28
+ proposal:
29
+ type: string
30
+ example: "Generated proposal content here."
31
+ "500":
32
+ description: Internal server error
33
+ content:
34
+ application/json:
35
+ schema:
36
+ type: object
37
+ properties:
38
+ detail:
39
+ type: string
40
+ example: "Internal Server Error."
41
+ components:
42
+ schemas:
43
+ ProposalRequest:
44
+ type: object
45
+ required:
46
+ - project_name
47
+ - project_overview
48
+ - project_introduction
49
+ - about_us
50
+ - background_of_the_project
51
+ - scope_of_work
52
+ - technical_approach
53
+ - deployment_and_integration
54
+ - timeline
55
+ - team_structure
56
+ - platform
57
+ - licensing_model
58
+ - risk_analysis
59
+ - past_projects
60
+ properties:
61
+ project_name:
62
+ type: string
63
+ description: "Generate a name of the project. In response, provide only the name and do not include any other information."
64
+ project_overview:
65
+ type: string
66
+ description: "Generate an overview section that improves the project overview from the client requirements. Keep the text up to 15 lines and write the text without using pronouns."
67
+ project_introduction:
68
+ type: string
69
+ description: "Address the client formally and thank them for considering Sifars for the project. Briefly describe Sifars, mentioning its mission, values, and focus on delivering state-of-the-art AI or software solutions."
70
+ about_us:
71
+ type: string
72
+ description: "Provide a short introduction to Sifars, focusing on our team's expertise, technologies, and successful solutions we have developed. Mention how long Sifars has been in operation and our experience with similar projects."
73
+ background_of_the_project:
74
+ type: string
75
+ description: "Describe the key challenge the client is facing in their industry (replace with the client's field, e.g., healthcare, finance). Present the problem and how Sifars will address it using advanced technologies (AI, software development, automation, etc.)."
76
+ scope_of_work:
77
+ type: string
78
+ description: "Detail the tasks that will be performed. Example structure: Data Collection and Preprocessing, Solution Development (e.g., AI model, software system), Integration and API development, Testing and validation, Deployment on scalable infrastructure."
79
+ technical_approach:
80
+ type: string
81
+ description: "Explain the approach in detail. Include methodologies like content-based and collaborative filtering if relevant, or other techniques used by Sifars. Customize this to reflect the [Techstack] that's going to be used by Sifars."
82
+ deployment_and_integration:
83
+ type: string
84
+ description: "Specify the deployment method, such as using cloud services like AWS, GCP, or any other infrastructure that Sifars uses or defined in the [Techstack]. Mention how Sifars ensures seamless integration with the client’s platform using APIs."
85
+ timeline:
86
+ timeline:
87
+ type: string
88
+ description: "Create a timeline with project milestones in the following table format, like:
89
+ | Week | Milestone | Estimated Pricing |
90
+ |------|------------------------------------|-------------------------|
91
+ | 1 | Initial Setup and Data Collection | $1,000 |
92
+ | 2-3 | Development of Core Components | $2,000 |
93
+ | 4 | Final Deployment and Testing | $1,500 |
94
+ Add estimated pricing in a flexible structure, allowing payments at each milestone."
95
+ team_structure:
96
+ type: string
97
+ description: "Generate a detailed breakdown of a project team's structure, including roles and responsibilities. The team may consist of members like Project Manager, UI/UX Designer, Full Stack Developers, AI Developers, Quality Assurance Specialists, DevOps Engineers, etc. For each role, provide the number of members and describe their key responsibilities. Ensure that the responsibilities align with typical tasks for each role in a software development project. Use clear, professional language and ensure that the descriptions are concise yet comprehensive."
98
+ platform:
99
+ type: string
100
+ description: "Generate text explaining each [Techstack] the application will be built upon."
101
+ licensing_model:
102
+ type: string
103
+ description: "Based on the [Techstack] and other potential tooling that will be involved to build the project, generate the Licensing Model section."
104
+ risk_analysis:
105
+ type: string
106
+ description: "List potential risks (e.g., data availability, bias in the system) and propose mitigations."
107
+ past_projects:
108
+ type: string
109
+ description: "Provide case studies of similar projects Sifars has worked on, showcasing the impact and results achieved. Refer to the knowledge files to find 2 relevant projects that could be similar to the provided requirements."
instructions.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "project_name": "Generate a name of the project. In response provide only name and do not include any other information.",
3
+ "project_overview": "Generate an overview section that just improves the project overview from the client requirements. Keep the text up to 15 lines and Please write the text without using pronouns.",
4
+ "project_introduction": "Address the client formally and thank them for considering Sifars for the project. Briefly describe Sifars, mentioning its mission, values, and focus on delivering state-of-the-art AI or software solutions.",
5
+ "about_us": "Provide a short introduction to Sifars, focusing on our team's expertise, technologies, and the successful solutions we have developed. Mention how long Sifars has been in operation and our experience with similar projects.",
6
+ "background_of_the_project": "Describe the key challenge the client is facing in their industry (replace with the client's field, e.g., healthcare, finance). Present the problem and how Sifars will address it using advanced technologies (AI, software development, automation, etc.).",
7
+ "scope_of_work": "Detail the tasks that will be performed. Example structure: Data Collection and Preprocessing. Solution Development (e.g., AI model, software system). Integration and API development. Testing and validation. Deployment on scalable infrastructure.",
8
+ "technical_approach": "Explain the approach in detail. Include methodologies like content-based and collaborative filtering if relevant, or other techniques used by Sifars. Customize this to reflect the [ Techstack ] that's going to be used by Sifars.",
9
+ "deployment_and_integration": "Specify the deployment method, such as using cloud services like AWS, GCP, or any other infrastructure that Sifars uses or defined in the [ Techstack ]. Mention how Sifars ensures seamless integration with the client’s platform using APIs.",
10
+ "timeline": "Create a timeline with project milestones in the following table format, like: Week 1: Initial Setup and Data Collection. Week 2-3: Development of Core Components. Week 4: Final Deployment and Testing. Add estimated pricing in a flexible structure, allowing payments at each milestone.",
11
+ "team_structure": "Generate a detailed breakdown of a project team's structure, including roles and responsibilities. The team may consists of members like Project Manager, UI/UX Designer, Full Stack Developers, AI Developers, Quality Assurance Specialists, DevOps Engineers, etc. For each role, provide the number of members and describe their key responsibilities. Ensure that the responsibilities align with typical tasks for each role in a software development project. Use clear, professional language and ensure that the descriptions are concise yet comprehensive.",
12
+ "platform": "Generate text explaining each [ techstack ] the application will be built upon.",
13
+ "licensing_model": "Based on the [ Techstack ] and other potential tooling that will be involved to build the project, generate the Licensing Model section. ",
14
+ "risk_analysis": "List potential risks (e.g., data availability, bias in the system) and propose mitigations.",
15
+ "past_projects": "Provide case studies of similar projects Sifars has worked on, showcasing the impact and results achieved. Refer to the knowledge files to find 2 relevant projects that could be similar to the provided requirements."
16
+ }
instructions.md ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ You are an AI-powered proposal generator for Sifars, responsible for crafting professional, structured, and tailored project proposals. Follow these instructions carefully to generate a compelling and precise document:
2
+
3
+ ### **1. Project Name**
4
+
5
+ Generate a concise, relevant project name. Provide only the name, without additional details or explanations.
6
+
7
+ ### **2. Project Overview**
8
+
9
+ Refine the client's project overview while maintaining their core requirements. Improve clarity and readability within a limit of 15 lines. Avoid using pronouns.
10
+
11
+ ### **3. Project Introduction**
12
+
13
+ Address the client formally and thank them for considering Sifars. Briefly introduce Sifars, highlighting its mission, values, and expertise in AI and software solutions.
14
+
15
+ ### **4. About Us**
16
+
17
+ Summarize Sifars' background, including team expertise, technology focus, and past successes. Mention years of experience and relevant industry accomplishments.
18
+
19
+ ### **5. Background of the Project**
20
+
21
+ Describe the client’s key industry challenge and how Sifars’ advanced technologies (AI, automation, software development, etc.) will address it. Clearly outline the problem and Sifars' tailored solution.
22
+
23
+ ### **6. Scope of Work**
24
+
25
+ Define project tasks in a structured format, including but not limited to:
26
+
27
+ - Data Collection & Preprocessing
28
+ - Solution Development (AI model/software)
29
+ - Integration & API Development
30
+ - Testing & Validation
31
+ - Deployment on scalable infrastructure
32
+
33
+ ### **7. Technical Approach**
34
+
35
+ Describe the technical methodologies and strategies that will be used. Align the approach with the specified [Techstack] and include techniques such as AI/ML models, collaborative filtering, or other relevant methods.
36
+
37
+ ### **8. Deployment and Integration**
38
+
39
+ Detail the deployment strategy, specifying cloud infrastructure (AWS, GCP, etc.) and integration methods. Ensure that API integration is seamless and aligns with Sifars' best practices.
40
+
41
+ ### **9. Timeline & Pricing**
42
+
43
+ Generate a project timeline with milestone-based breakdowns. Provide a flexible pricing structure linked to milestone completions in markdown table format. Ensure the timeline and pricing are realistic and competitive.
44
+
45
+ ### **10. Team Structure**
46
+
47
+ Define project roles and responsibilities, ensuring alignment with typical software development tasks. The team may include:
48
+
49
+ - Project Manager
50
+ - UI/UX Designer
51
+ - Full Stack Developers
52
+ - AI Developers
53
+ - Quality Assurance Specialists
54
+ - DevOps Engineers
55
+
56
+ For each role, specify the number of members and their core responsibilities. Use clear, professional language.
57
+
58
+ ### **11. Platform**
59
+
60
+ Describe the [Techstack] used for the project, explaining its relevance and benefits.
61
+
62
+ ### **12. Licensing Model**
63
+
64
+ Generate the appropriate licensing model based on the [Techstack] and other tools required.
65
+
66
+ ### **13. Risk Analysis**
67
+
68
+ Identify key project risks (e.g., data availability, security concerns, AI biases) and propose mitigation strategies.
69
+
70
+ ### **14. Past Projects**
71
+
72
+ Select two relevant case studies from Sifars’ past projects that align with the client’s requirements. Highlight their impact and results.
73
+
74
+ Ensure the proposal maintains a professional, clear, and structured format. Keep responses concise, factual, and aligned with Sifars' expertise.
poetry.lock ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
2
+
3
+ [[package]]
4
+ name = "aiosmtplib"
5
+ version = "3.0.2"
6
+ description = "asyncio SMTP client"
7
+ optional = false
8
+ python-versions = ">=3.8"
9
+ files = [
10
+ {file = "aiosmtplib-3.0.2-py3-none-any.whl", hash = "sha256:8783059603a34834c7c90ca51103c3aa129d5922003b5ce98dbaa6d4440f10fc"},
11
+ {file = "aiosmtplib-3.0.2.tar.gz", hash = "sha256:08fd840f9dbc23258025dca229e8a8f04d2ccf3ecb1319585615bfc7933f7f47"},
12
+ ]
13
+
14
+ [package.extras]
15
+ docs = ["furo (>=2023.9.10)", "sphinx (>=7.0.0)", "sphinx-autodoc-typehints (>=1.24.0)", "sphinx-copybutton (>=0.5.0)"]
16
+ uvloop = ["uvloop (>=0.18)"]
17
+
18
+ [[package]]
19
+ name = "annotated-types"
20
+ version = "0.7.0"
21
+ description = "Reusable constraint types to use with typing.Annotated"
22
+ optional = false
23
+ python-versions = ">=3.8"
24
+ files = [
25
+ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
26
+ {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
27
+ ]
28
+
29
+ [[package]]
30
+ name = "anyio"
31
+ version = "4.8.0"
32
+ description = "High level compatibility layer for multiple asynchronous event loop implementations"
33
+ optional = false
34
+ python-versions = ">=3.9"
35
+ files = [
36
+ {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"},
37
+ {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"},
38
+ ]
39
+
40
+ [package.dependencies]
41
+ idna = ">=2.8"
42
+ sniffio = ">=1.1"
43
+ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
44
+
45
+ [package.extras]
46
+ doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"]
47
+ test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"]
48
+ trio = ["trio (>=0.26.1)"]
49
+
50
+ [[package]]
51
+ name = "click"
52
+ version = "8.1.8"
53
+ description = "Composable command line interface toolkit"
54
+ optional = false
55
+ python-versions = ">=3.7"
56
+ files = [
57
+ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"},
58
+ {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"},
59
+ ]
60
+
61
+ [package.dependencies]
62
+ colorama = {version = "*", markers = "platform_system == \"Windows\""}
63
+
64
+ [[package]]
65
+ name = "colorama"
66
+ version = "0.4.6"
67
+ description = "Cross-platform colored terminal text."
68
+ optional = false
69
+ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
70
+ files = [
71
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
72
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
73
+ ]
74
+
75
+ [[package]]
76
+ name = "fastapi"
77
+ version = "0.115.7"
78
+ description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
79
+ optional = false
80
+ python-versions = ">=3.8"
81
+ files = [
82
+ {file = "fastapi-0.115.7-py3-none-any.whl", hash = "sha256:eb6a8c8bf7f26009e8147111ff15b5177a0e19bb4a45bc3486ab14804539d21e"},
83
+ {file = "fastapi-0.115.7.tar.gz", hash = "sha256:0f106da6c01d88a6786b3248fb4d7a940d071f6f488488898ad5d354b25ed015"},
84
+ ]
85
+
86
+ [package.dependencies]
87
+ 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"
88
+ starlette = ">=0.40.0,<0.46.0"
89
+ typing-extensions = ">=4.8.0"
90
+
91
+ [package.extras]
92
+ all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "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)"]
93
+ standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.5)", "httpx (>=0.23.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
94
+
95
+ [[package]]
96
+ name = "h11"
97
+ version = "0.14.0"
98
+ description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
99
+ optional = false
100
+ python-versions = ">=3.7"
101
+ files = [
102
+ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
103
+ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
104
+ ]
105
+
106
+ [[package]]
107
+ name = "idna"
108
+ version = "3.10"
109
+ description = "Internationalized Domain Names in Applications (IDNA)"
110
+ optional = false
111
+ python-versions = ">=3.6"
112
+ files = [
113
+ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
114
+ {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
115
+ ]
116
+
117
+ [package.extras]
118
+ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
119
+
120
+ [[package]]
121
+ name = "loguru"
122
+ version = "0.7.3"
123
+ description = "Python logging made (stupidly) simple"
124
+ optional = false
125
+ python-versions = "<4.0,>=3.5"
126
+ files = [
127
+ {file = "loguru-0.7.3-py3-none-any.whl", hash = "sha256:31a33c10c8e1e10422bfd431aeb5d351c7cf7fa671e3c4df004162264b28220c"},
128
+ {file = "loguru-0.7.3.tar.gz", hash = "sha256:19480589e77d47b8d85b2c827ad95d49bf31b0dcde16593892eb51dd18706eb6"},
129
+ ]
130
+
131
+ [package.dependencies]
132
+ colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
133
+ win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
134
+
135
+ [package.extras]
136
+ dev = ["Sphinx (==8.1.3)", "build (==1.2.2)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.5.0)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.13.0)", "mypy (==v1.4.1)", "myst-parser (==4.0.0)", "pre-commit (==4.0.1)", "pytest (==6.1.2)", "pytest (==8.3.2)", "pytest-cov (==2.12.1)", "pytest-cov (==5.0.0)", "pytest-cov (==6.0.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.1.0)", "sphinx-rtd-theme (==3.0.2)", "tox (==3.27.1)", "tox (==4.23.2)", "twine (==6.0.1)"]
137
+
138
+ [[package]]
139
+ name = "pydantic"
140
+ version = "2.10.6"
141
+ description = "Data validation using Python type hints"
142
+ optional = false
143
+ python-versions = ">=3.8"
144
+ files = [
145
+ {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"},
146
+ {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"},
147
+ ]
148
+
149
+ [package.dependencies]
150
+ annotated-types = ">=0.6.0"
151
+ pydantic-core = "2.27.2"
152
+ typing-extensions = ">=4.12.2"
153
+
154
+ [package.extras]
155
+ email = ["email-validator (>=2.0.0)"]
156
+ timezone = ["tzdata"]
157
+
158
+ [[package]]
159
+ name = "pydantic-core"
160
+ version = "2.27.2"
161
+ description = "Core functionality for Pydantic validation and serialization"
162
+ optional = false
163
+ python-versions = ">=3.8"
164
+ files = [
165
+ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"},
166
+ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"},
167
+ {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"},
168
+ {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"},
169
+ {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"},
170
+ {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"},
171
+ {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"},
172
+ {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"},
173
+ {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"},
174
+ {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"},
175
+ {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"},
176
+ {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"},
177
+ {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"},
178
+ {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"},
179
+ {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"},
180
+ {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"},
181
+ {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"},
182
+ {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"},
183
+ {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"},
184
+ {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"},
185
+ {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"},
186
+ {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"},
187
+ {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"},
188
+ {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"},
189
+ {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"},
190
+ {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"},
191
+ {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"},
192
+ {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"},
193
+ {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"},
194
+ {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"},
195
+ {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"},
196
+ {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"},
197
+ {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"},
198
+ {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"},
199
+ {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"},
200
+ {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"},
201
+ {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"},
202
+ {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"},
203
+ {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"},
204
+ {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"},
205
+ {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"},
206
+ {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"},
207
+ {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"},
208
+ {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"},
209
+ {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"},
210
+ {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"},
211
+ {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"},
212
+ {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"},
213
+ {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"},
214
+ {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"},
215
+ {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"},
216
+ {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"},
217
+ {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"},
218
+ {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"},
219
+ {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"},
220
+ {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"},
221
+ {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"},
222
+ {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"},
223
+ {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"},
224
+ {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"},
225
+ {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"},
226
+ {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"},
227
+ {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"},
228
+ {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"},
229
+ {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"},
230
+ {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"},
231
+ {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"},
232
+ {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"},
233
+ {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"},
234
+ {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"},
235
+ {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"},
236
+ {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"},
237
+ {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"},
238
+ {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"},
239
+ {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"},
240
+ {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"},
241
+ {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"},
242
+ {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"},
243
+ {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"},
244
+ {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"},
245
+ {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"},
246
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"},
247
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"},
248
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"},
249
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"},
250
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"},
251
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"},
252
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"},
253
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"},
254
+ {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"},
255
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"},
256
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"},
257
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"},
258
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"},
259
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"},
260
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"},
261
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"},
262
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"},
263
+ {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"},
264
+ {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"},
265
+ ]
266
+
267
+ [package.dependencies]
268
+ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
269
+
270
+ [[package]]
271
+ name = "python-dotenv"
272
+ version = "1.0.1"
273
+ description = "Read key-value pairs from a .env file and set them as environment variables"
274
+ optional = false
275
+ python-versions = ">=3.8"
276
+ files = [
277
+ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"},
278
+ {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"},
279
+ ]
280
+
281
+ [package.extras]
282
+ cli = ["click (>=5.0)"]
283
+
284
+ [[package]]
285
+ name = "sniffio"
286
+ version = "1.3.1"
287
+ description = "Sniff out which async library your code is running under"
288
+ optional = false
289
+ python-versions = ">=3.7"
290
+ files = [
291
+ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
292
+ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
293
+ ]
294
+
295
+ [[package]]
296
+ name = "starlette"
297
+ version = "0.45.3"
298
+ description = "The little ASGI library that shines."
299
+ optional = false
300
+ python-versions = ">=3.9"
301
+ files = [
302
+ {file = "starlette-0.45.3-py3-none-any.whl", hash = "sha256:dfb6d332576f136ec740296c7e8bb8c8a7125044e7c6da30744718880cdd059d"},
303
+ {file = "starlette-0.45.3.tar.gz", hash = "sha256:2cbcba2a75806f8a41c722141486f37c28e30a0921c5f6fe4346cb0dcee1302f"},
304
+ ]
305
+
306
+ [package.dependencies]
307
+ anyio = ">=3.6.2,<5"
308
+
309
+ [package.extras]
310
+ full = ["httpx (>=0.27.0,<0.29.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.18)", "pyyaml"]
311
+
312
+ [[package]]
313
+ name = "typing-extensions"
314
+ version = "4.12.2"
315
+ description = "Backported and Experimental Type Hints for Python 3.8+"
316
+ optional = false
317
+ python-versions = ">=3.8"
318
+ files = [
319
+ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
320
+ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
321
+ ]
322
+
323
+ [[package]]
324
+ name = "uvicorn"
325
+ version = "0.34.0"
326
+ description = "The lightning-fast ASGI server."
327
+ optional = false
328
+ python-versions = ">=3.9"
329
+ files = [
330
+ {file = "uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4"},
331
+ {file = "uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9"},
332
+ ]
333
+
334
+ [package.dependencies]
335
+ click = ">=7.0"
336
+ h11 = ">=0.8"
337
+
338
+ [package.extras]
339
+ standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
340
+
341
+ [[package]]
342
+ name = "win32-setctime"
343
+ version = "1.2.0"
344
+ description = "A small Python utility to set file creation time on Windows"
345
+ optional = false
346
+ python-versions = ">=3.5"
347
+ files = [
348
+ {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"},
349
+ {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"},
350
+ ]
351
+
352
+ [package.extras]
353
+ dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
354
+
355
+ [metadata]
356
+ lock-version = "2.0"
357
+ python-versions = "3.12.*"
358
+ content-hash = "347e22360bbf6bffd7da2466e4c3ef4ec5d60bbc03a8257b64ce72165f7653e7"
pyproject.toml ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [tool.poetry]
2
+ name = "proposal-generator"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = ["Kanha Upadhyay <kanha.upadhyay@sifars.com>"]
6
+ readme = "README.md"
7
+
8
+ [tool.poetry.dependencies]
9
+ python = "3.12.*"
10
+ fastapi = "^0.115.7"
11
+ uvicorn = "^0.34.0"
12
+ loguru = "^0.7.3"
13
+ python-dotenv = "^1.0.1"
14
+ aiosmtplib = "^3.0.2"
15
+
16
+
17
+ [build-system]
18
+ requires = ["poetry-core"]
19
+ build-backend = "poetry.core.masonry.api"
src/__init__.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from dotenv import load_dotenv
4
+
5
+ from .app import app
6
+
7
+ load_dotenv()
8
+
9
+ if not os.getenv("SMTP_SERVER"):
10
+ raise ValueError("SMTP_SERVER environment not set.")
11
+
12
+ if not os.getenv("SMTP_PORT"):
13
+ raise ValueError("SMTP_PORT environment not set.")
14
+
15
+ if not os.getenv("SMTP_USERNAME"):
16
+ raise ValueError("SMTP_USERNAME environment not set.")
17
+
18
+ if not os.getenv("SMTP_PASSWORD"):
19
+ raise ValueError("SMTP_PASSWORD environment not set.")
20
+
21
+ if not os.getenv("SENDER_EMAIL"):
22
+ raise ValueError("SENDER_EMAIL environment not set.")
23
+
24
+ if not os.getenv("RECIPIENT_EMAIL"):
25
+ raise ValueError("RECIPIENT_EMAIL environment not set.")
26
+
27
+ __all__ = ["app"]
28
+ __version__ = "0.1.0"
29
+ __author__ = "Kanha Upadhyay"
src/app.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import tempfile
4
+
5
+ from fastapi import FastAPI, HTTPException
6
+ from pydantic import BaseModel
7
+
8
+ from src.utils import EmailClient
9
+
10
+ app = FastAPI()
11
+
12
+ TEMPLATE = ""
13
+ with open("src/proposal_template.md", "r") as file:
14
+ TEMPLATE = file.read()
15
+
16
+ TEMPLATE = TEMPLATE.replace("`", "")
17
+ VARIABLES = re.findall(r"\{(.*?)\}", TEMPLATE)
18
+
19
+
20
+ class ProposalRequest(BaseModel):
21
+ project_name: str
22
+ project_overview: str
23
+ project_introduction: str
24
+ about_us: str
25
+ background_of_the_project: str
26
+ scope_of_work: str
27
+ technical_approach: str
28
+ deployment_and_integration: str
29
+ timeline: str
30
+ team_structure: str
31
+ platform: str
32
+ licensing_model: str
33
+ risk_analysis: str
34
+ past_projects: str
35
+
36
+
37
+ async def generate_proposal(data: dict):
38
+ proposal = TEMPLATE
39
+ for variable in VARIABLES:
40
+ proposal = proposal.replace(
41
+ f"{{{variable}}}",
42
+ data.get(variable, f"DATA NOT FOUND FOR {variable}. FIXME."),
43
+ )
44
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".md") as temp_file:
45
+ temp_file.write(proposal.encode())
46
+ attachments = [temp_file.name]
47
+ recipient_email = os.getenv("RECIPIENT_EMAIL")
48
+ subject = f"Proposal for {data.get('project_name')}"
49
+ body = f"Hello,\n\nPlease find the proposal attached.\n\nBest,\nProposal Bot"
50
+ async with EmailClient() as email_client:
51
+ await email_client.send_email(
52
+ subject=subject,
53
+ body=body,
54
+ to_emails=[recipient_email],
55
+ attachments=attachments,
56
+ )
57
+ return {"message": "Proposal sent successfully"}
58
+
59
+
60
+ @app.get("/")
61
+ async def check_health():
62
+ return {"response": "Service is healthy!"}
63
+
64
+
65
+ @app.post("/proposals/")
66
+ async def generate_proposal_endpoint(request: ProposalRequest):
67
+ try:
68
+ proposal = await generate_proposal(data=request.model_dump())
69
+ return {"proposal": proposal}
70
+ except Exception as e:
71
+ raise HTTPException(status_code=500, detail=f"{e}")
src/proposal_template.md ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # `{project_name}` Proposal
2
+
3
+ ## Table of Contents
4
+
5
+ | Section |
6
+ | ---------------------------------------------------------------- |
7
+ | [Introduction](#1-introduction) |
8
+ | [Project Timeline and Pricing](#2-project-timeline--pricing) |
9
+ | [Platform](#3-platform) |
10
+ | [Licensing Model](#4-licensing-model) |
11
+ | [Risk Analysis](#5-risk-analysis) |
12
+ | [Past Projects](#6-past-projects) |
13
+ | [Service Level Matrix](#7-service-level-matrix) |
14
+ | [Future Requirements](#8-future-requirements) |
15
+ | [Ownership](#9-ownership) |
16
+ | [Additional Information](#10-additional-information) |
17
+ | [Dependencies and Assumptions](#11-dependencies-and-assumptions) |
18
+ | [Change Management](#12-change-management) |
19
+ | [Terms and Conditions](#13-terms--conditions) |
20
+ | [Estimation Disclaimer](#14-estimation-disclaimer) |
21
+
22
+ # 1. Introduction
23
+
24
+ ### Company Overview
25
+
26
+ Sifars is pleased to present a comprehensive proposal for the development and implementation of the `{project_name}`. As a leading provider of innovative software solutions, Sifars brings a wealth of experience and expertise to this project. With a proven track record of delivering tailored solutions that address our clients' unique needs, we are confident in our ability to successfully execute this project and exceed expectations.
27
+
28
+ ### Project Overview
29
+
30
+ `{project_overview}`
31
+
32
+ ### Inroduction
33
+
34
+ `{project_introduction}`
35
+
36
+ ### About Us
37
+
38
+ `{about_us}`
39
+
40
+ ### Background of the Project
41
+
42
+ `{background_of_the_project}`
43
+
44
+ ### Scope of Work
45
+
46
+ `{scope_of_work}`
47
+
48
+ ### Technical Approach
49
+
50
+ `{technical_approach}`
51
+
52
+ ### Deployment and Integration
53
+
54
+ `{deployment_and_integration}`
55
+
56
+ # 2. Project Timeline & Pricing
57
+
58
+ The successful implementation of the `{project_name}` will follow a structured timeline, ensuring timely delivery of milestones and alignment with project objectives. Below is the proposed timeline outlining key milestones and their respective durations.
59
+
60
+ Efforts (Man Days): The number of days it will take for a single person to deliver the milestone, with a working day consisting of 8 hours.
61
+
62
+ Time (Days): The duration required for our team to deliver the milestone, considering a working day of 8 hours and involving multiple team members.
63
+
64
+ ### Timeline
65
+
66
+ `{timeline}`
67
+
68
+ | S.No. | Milestone | Efforts (ManDays) | Time (Days) | Price |
69
+ | ----- | ---------------------------- | ----------------- | ----------- | ----- |
70
+ | 1 | High-Level Design Document | | | |
71
+ | 2 | Low-Level Design Document | | | |
72
+ | 3 | Proof of Concept | | | |
73
+ | 4 | Minimum Viable Product (MVP) | | | |
74
+ | 5 | Release of Application | | | |
75
+ | | **Total** | | | |
76
+
77
+ ### Team Structure
78
+
79
+ `{team_structure}`
80
+
81
+ # 3. Platform
82
+
83
+ `{platform}`
84
+
85
+ # 4. Licensing Model
86
+
87
+ `{licensing_model}`
88
+
89
+ As the project progresses and potential additional tools or services are incorporated, there may be further licensing considerations based on specific needs and agreements with respective vendors. Therefore, the Licensing Model for the project will evolve accordingly to accommodate any future requirements and ensure compliance with all relevant licenses and regulations.
90
+
91
+ # 5. Risk Analysis
92
+
93
+ `{risk_analysis}`
94
+
95
+ # 6. Past Projects
96
+
97
+ `{past_projects}`
98
+
99
+ # 7. Service Level Matrix
100
+
101
+ Respond to service-related incidents submitted by customers within the following time frames. Please note that these only cover any bugs or service-related incidents. In case, there is a major change/upgrade required such as training the AI models on new data, or improving performance, we would need to set up a separate contract for it.
102
+
103
+ We provide one-month complimentary support once the project concludes.
104
+
105
+ | Severity Level | Description of risk level | Maximu m respons e time | Maximum solution to the problem |
106
+ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------- | ------------------------------- |
107
+ | Level One (S1) | 1. Severe problems that cause the system to stop functioning, preventing users from interacting with the system. 2. There is a problem that causes an error in the validity or accuracy of the data processed by the system. | 1 hour | 2 hour |
108
+ | Level Two (S2) | 1. There is a highly important problem that affects the workflow in the system, but does not stop or prevent the completion of interactions and does not affect the validity or accuracy of the data. | 4 hours | 1 day |
109
+ | Level Three (S3) | 1. There is a problem of moderate importance that does not affect the functioning of the system. 2. It stops or prevents the completion of the interaction but does not affect the validity or accuracy of the data and has no financial impact. | 2 days | 5 days |
110
+ | Level Four (S4) | 1. The presence of a minor problem related to cosmetic matters helps improve a user’s interaction with the system. 2. Or need to improve the overall accuracy of the system | 5 days | 10 days |
111
+
112
+ # 8. Future Requirements
113
+
114
+ We understand the importance of futureproofing your investment in the `{project_name}`, and we're committed to ensuring that the solution remains adaptable and scalable to meet your evolving needs. As part of our development approach, we'll build the system with modularity and flexibility in mind, allowing for seamless integration of new features and enhancements as your requirements change over time.
115
+
116
+ 1. Scalability: As your organization grows or your `{project_name}` needs expand, the system should be able to accommodate increased user loads and data volumes without sacrificing performance. We'll design the architecture with scalability in mind, utilizing cloud technologies or scalable infrastructure where applicable.
117
+ 2. Customization: Your workflows and processes may evolve over time, necessitating customizations or additional features within the system. We'll ensure that the architecture supports easy customization and extension, allowing for the incorporation of new modules or functionality as needed.
118
+ 3. Integration: As your IT ecosystem evolves, you may require integration with other systems or platforms to streamline operations and improve data flow. We'll design the system with integration capabilities, making it easier to connect with third-party applications such as CRM systems, accounting software, or external databases.
119
+
120
+ Throughout our partnership, we'll maintain open lines of communication to discuss your evolving needs and explore opportunities for further development. Our goal is to build a long-term partnership focused on delivering solutions that drive your organization's success.
121
+
122
+ # 9. Ownership
123
+
124
+ Ensuring clear ownership of the source code is a crucial aspect of our partnership. We believe in transparency and empowering our clients with full control over their intellectual property. Upon completion of the project and full payment of fees, you will retain full ownership of the source code developed for the `{project_name}`. This means you will have the right to modify, enhance, and distribute the code as you see fit without any restrictions from our end. In addition to providing you with the source code, we will also document the architecture, design decisions, and any relevant technical documentation to facilitate future maintenance and development efforts. Our goal is to ensure that you have the necessary resources and knowledge to independently manage and evolve the system over time. Furthermore, we're committed to fostering a collaborative relationship where you have the freedom to engage with other vendors or developers for ongoing support or further enhancements if desired. We believe in building long-term partnerships based on trust, mutual respect, and a shared commitment to your success.
125
+
126
+ # 10. Additional Information
127
+
128
+ In addition to the technical aspects mentioned above, there are several other factors worth considering ensuring the success and smooth execution of the `{project_name}` development
129
+
130
+ - **Data Migration and Integration:** If you're migrating from an existing system or integrating with other platforms, careful planning and execution are required to ensure seamless data migration and integration. We'll work closely with your team to assess data requirements, identify any potential challenges, and develop a strategy to mitigate risks. This process may necessitate substantial effort and expenditure beyond the proposed budget.
131
+ - **Regulatory Compliance:** Depending on your industry and geographic location, there may be specific regulatory requirements that the `{project_name}` needs to comply with. It's important to factor in compliance considerations from the outset to avoid costly delays or setbacks later. It's crucial that you inform us about any regulatory requirements upfront.
132
+
133
+ # 11. Dependencies and Assumptions
134
+
135
+ - **Third-Party API Integration:** To enhance functionality, we may require third-party integrations. We'll request access to necessary accounts for these integrations from the client during the development process to ensure seamless implementation and operation.
136
+ - **Environment Access:** Access to development, testing, and production environments is assumed throughout the project. The client will provide necessary infrastructure resources such as servers and domains for setting up these environments.
137
+
138
+ # 12. Change Management
139
+
140
+ - **What is a change request** - A change request is a proposal to alter a product or system, often brought up by the client or another team member. During a project, this can happen when a client wants to change or alter the agreed upon deliverables.
141
+ - **Change requests** - can also be initiated internally as well and can include things like changing or upgrading software. In general, there are two types of change requests: those that are within the scope and those that are outside the scope of the project.
142
+ - **Within the scope** – change requests that are inside the scope involve small corrections to an existing requirement. They usually have minimal impact on the budget or the rest of the team.
143
+ - **Outside the scope** – on the other hand, change requests that are outside the scope take a considerable amount of time to implement and have a more sizable impact on the budget. Change requests must be dealt with in an appropriate and timely manner.
144
+
145
+ # 13. Terms & Conditions
146
+
147
+ - The scope will be contained to the line items mentioned in milestones. While creating the proposal, it has been assumed that the requirements given by the client form the complete scope of the application. Any requirement, not explicitly mentioned in this document, does not form a part of this estimate.
148
+ - Client shall provide all third-party software and hardware components. This includes hosting details, hardware environment etc. The cost of all these components will be borne by the client and does not form the part of the proposed estimated cost.
149
+ - If required, the client shall provide all the test data to run the test cases. The client shall be available to solve the queries, which the development team may have, to ensure that project timelines are met.
150
+ - Client shall perform timely review of the deliveries, as per the schedule of deliveries defined at the project initiation. Any delays from the client end would lead to subsequent delays in development of the project, which will be communicated at that time itself.
151
+ - All quotations and estimates provided by Sifars are valid for a period of 30 days from the date of issue. Quotations not accepted within this timeframe need to be re-issued.
152
+ - Upon acceptance, Sifars will perform the services described in the quotation. Any additional services that are later requested by the client and/or not defined under the scope-of-work in this quotation may incur additional charges.
153
+ - The services will be completed, and/or delivery of products will be made according to the estimated timeline, agreed upon mutually by both parties. Sifars reserves the right to modify timelines in response to unforeseen circumstances or changes in project requirements.
154
+ - Changes to the delivery and performance of any products or services, including quantity, specifications, and scheduling, do not become binding until approved in writing by both parties. Any changes may result in additional or increased charges.
155
+ - All information related to the project will be considered confidential, and may only be released if necessary after mutual approval by the client and Sifars.
156
+ - Once the project formally starts, the client or Sifars may terminate the agreement at any time by providing written notice via email or certified mail to the other party. In the event of termination, Sifars may issue a final invoice according to terms of the contract for any unbilled time or work.
157
+ - An advance payment of 10% of the proposed project cost is to be made before the first milestone. This will be adjusted towards the last milestone/deliverable.
158
+ - Each milestone’s payment will be made after the completion.
159
+ - Payment terms will be NET15.
160
+
161
+ # 14. Estimation Disclaimer
162
+
163
+ This proposal provides a time and cost estimate based on a range of days required to complete the project. These estimates are derived from initial discussions and assumptions about the project scope. While we strive for accuracy, it's important to note that software development inherently involves many variables and unforeseen complexities. As such, this estimate cannot be 100% precise. However, we have a high degree of confidence that the final cost will remain within the provided estimate.
164
+
165
+ Once the low-level design document of the project is ready, we will revisit the pricing, allowing us to refine our estimates and provide a more accurate projection. This detailed document will be exceptionally valuable, as it surfaces all the essential questions and details about the project, ensuring that every aspect is thoroughly understood and planned for.
166
+
167
+ Engaging in this comprehensive estimation process not only helps us deliver a realistic understanding of the project's timeline and budget but also provides you with valuable insights into the project's development phases. This empowers you to make informed decisions, ensuring the best use of your resources and investments.
src/utils/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from ._email_client import EmailClient
2
+
3
+ __all__ = ["EmailClient"]
4
+ __version__ = "0.1.0"
5
+ __author__ = "Kanha Upadhyay"
src/utils/_email_client.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from email.message import EmailMessage
3
+
4
+ import aiosmtplib
5
+
6
+
7
+ class EmailClient:
8
+ def __init__(self):
9
+ self.smtp_server = os.getenv("SMTP_SERVER")
10
+ self.smtp_port = int(os.getenv("SMTP_PORT"))
11
+ self.username = os.getenv("SMTP_USERNAME")
12
+ self.password = os.getenv("SMTP_PASSWORD")
13
+
14
+ async def __aenter__(self):
15
+ return self
16
+
17
+ async def __aexit__(self, exc_type, exc, tb):
18
+ pass
19
+
20
+ async def send_email(
21
+ self,
22
+ subject: str,
23
+ body: str,
24
+ to_emails: list,
25
+ attachments: list = None,
26
+ ):
27
+ message = EmailMessage()
28
+ message["From"] = os.getenv("SENDER_EMAIL")
29
+ message["To"] = ", ".join(to_emails)
30
+ message["Subject"] = subject
31
+ message.set_content(body)
32
+ if attachments:
33
+ for attachment in attachments:
34
+ with open(attachment, "rb") as file:
35
+ file_data = file.read()
36
+ file_name = file.name
37
+ message.add_attachment(
38
+ file_data,
39
+ maintype="application",
40
+ subtype="octet-stream",
41
+ filename=file_name,
42
+ )
43
+ await aiosmtplib.send(
44
+ message,
45
+ hostname=self.smtp_server,
46
+ port=self.smtp_port,
47
+ username=self.username,
48
+ password=self.password,
49
+ start_tls=True,
50
+ )