sunholo 0.140.10__tar.gz → 0.140.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sunholo-0.140.12/PKG-INFO +522 -0
- sunholo-0.140.12/README.md +336 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/pyproject.toml +1 -1
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/flask/vac_routes.py +105 -149
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/config_class.py +94 -2
- sunholo-0.140.12/src/sunholo.egg-info/PKG-INFO +522 -0
- sunholo-0.140.10/PKG-INFO +0 -249
- sunholo-0.140.10/README.md +0 -63
- sunholo-0.140.10/src/sunholo.egg-info/PKG-INFO +0 -249
- {sunholo-0.140.10 → sunholo-0.140.12}/LICENSE.txt +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/MANIFEST.in +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/setup.cfg +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/langserve.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/route.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/agents/swagger.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/archive/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/archive/archive.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/auth/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/auth/refresh.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/auth/run.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/azure/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/azure/auth.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/azure/blobs.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/bots/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/bots/discord.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/bots/webapp.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/azure.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/images.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/publish.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/cli.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/configs.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/deploy.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/embedder.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/swagger.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/cli/vertex.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/components/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/components/llm.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/components/retriever.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/custom_logging.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/alloydb.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/database.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/lancedb.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/database/uuid.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/discovery_engine/cli.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/embedder/embed_metadata.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/excel/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/excel/plugin.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/gcs/download_gcs_text.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/gcs/extract_and_sign.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/genai/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/genai/file_handling.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/genai/genaiv2.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/genai/images.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/genai/init.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/genai/process_funcs_cls.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/genai/safety.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/langchain_types.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/langfuse/evals.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/mcp/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/mcp/cli.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/ollama/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/ollama/ollama_images.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/qna/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/qna/parsers.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/qna/retry.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/senses/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/senses/stream_voice.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/agent/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/agent/agent_service.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/agent/app.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/agent/my_log.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/agent/tools/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/agent/vac_service.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/project/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/project/app.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/project/my_log.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/project/vac_service.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/system_services/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/system_services/app.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/templates/system_services/my_log.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/terraform/tfvars_editor.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/tools/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/api_key.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/big_context.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/config.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/gcp.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/mime.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/parsers.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/utils/version.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/init.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/safety.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo.egg-info/SOURCES.txt +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/src/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/tests/test_async.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/tests/test_async_genai2.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/tests/test_chat_history.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/tests/test_config.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/tests/test_genai2.py +0 -0
- {sunholo-0.140.10 → sunholo-0.140.12}/tests/test_unstructured.py +0 -0
@@ -0,0 +1,522 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: sunholo
|
3
|
+
Version: 0.140.12
|
4
|
+
Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
|
5
|
+
Author-email: Holosun ApS <multivac@sunholo.com>
|
6
|
+
License: Apache License, Version 2.0
|
7
|
+
Project-URL: Homepage, https://github.com/sunholo-data/sunholo-py
|
8
|
+
Project-URL: Download, https://github.com/sunholo-data/sunholo-py/archive/refs/tags/v0.118.0.tar.gz
|
9
|
+
Keywords: llms,devops,google_cloud_platform
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
11
|
+
Classifier: Intended Audience :: Developers
|
12
|
+
Classifier: Topic :: Software Development :: Build Tools
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
18
|
+
Requires-Python: >=3.10
|
19
|
+
Description-Content-Type: text/markdown
|
20
|
+
License-File: LICENSE.txt
|
21
|
+
Requires-Dist: aiohttp
|
22
|
+
Requires-Dist: google-auth
|
23
|
+
Requires-Dist: ollama>=0.4.7
|
24
|
+
Requires-Dist: pillow>=11.0.0
|
25
|
+
Requires-Dist: pydantic
|
26
|
+
Requires-Dist: requests
|
27
|
+
Requires-Dist: ruamel.yaml
|
28
|
+
Requires-Dist: tenacity
|
29
|
+
Provides-Extra: test
|
30
|
+
Requires-Dist: pytest; extra == "test"
|
31
|
+
Requires-Dist: pytest-cov; extra == "test"
|
32
|
+
Provides-Extra: all
|
33
|
+
Requires-Dist: aiofiles; extra == "all"
|
34
|
+
Requires-Dist: aiohttp; extra == "all"
|
35
|
+
Requires-Dist: anthropic[vertex]; extra == "all"
|
36
|
+
Requires-Dist: asyncpg; extra == "all"
|
37
|
+
Requires-Dist: azure-identity; extra == "all"
|
38
|
+
Requires-Dist: azure-storage-blob; extra == "all"
|
39
|
+
Requires-Dist: fastapi; extra == "all"
|
40
|
+
Requires-Dist: flask; extra == "all"
|
41
|
+
Requires-Dist: google-auth; extra == "all"
|
42
|
+
Requires-Dist: google-auth-httplib2; extra == "all"
|
43
|
+
Requires-Dist: google-auth-oauthlib; extra == "all"
|
44
|
+
Requires-Dist: google-cloud-aiplatform>=1.58.0; extra == "all"
|
45
|
+
Requires-Dist: google-api-python-client; extra == "all"
|
46
|
+
Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "all"
|
47
|
+
Requires-Dist: google-cloud-bigquery; extra == "all"
|
48
|
+
Requires-Dist: google-cloud-build; extra == "all"
|
49
|
+
Requires-Dist: google-cloud-service-control; extra == "all"
|
50
|
+
Requires-Dist: google-cloud-logging; extra == "all"
|
51
|
+
Requires-Dist: google-cloud-storage; extra == "all"
|
52
|
+
Requires-Dist: google-cloud-pubsub; extra == "all"
|
53
|
+
Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "all"
|
54
|
+
Requires-Dist: google-cloud-texttospeech; extra == "all"
|
55
|
+
Requires-Dist: google-generativeai>=0.7.1; extra == "all"
|
56
|
+
Requires-Dist: google-genai>=0.2.2; extra == "all"
|
57
|
+
Requires-Dist: gunicorn; extra == "all"
|
58
|
+
Requires-Dist: httpcore; extra == "all"
|
59
|
+
Requires-Dist: httpx; extra == "all"
|
60
|
+
Requires-Dist: jsonschema; extra == "all"
|
61
|
+
Requires-Dist: lancedb; extra == "all"
|
62
|
+
Requires-Dist: langchain>=0.2.16; extra == "all"
|
63
|
+
Requires-Dist: langchain-experimental>=0.0.61; extra == "all"
|
64
|
+
Requires-Dist: langchain-community>=0.2.11; extra == "all"
|
65
|
+
Requires-Dist: langchain-openai>=0.3.2; extra == "all"
|
66
|
+
Requires-Dist: langchain-google-genai>=2.0.9; extra == "all"
|
67
|
+
Requires-Dist: langchain_google_alloydb_pg; extra == "all"
|
68
|
+
Requires-Dist: langchain-anthropic>=0.1.23; extra == "all"
|
69
|
+
Requires-Dist: langchain-google-vertexai; extra == "all"
|
70
|
+
Requires-Dist: langchain-unstructured; extra == "all"
|
71
|
+
Requires-Dist: langfuse; extra == "all"
|
72
|
+
Requires-Dist: mcp; extra == "all"
|
73
|
+
Requires-Dist: numpy; extra == "all"
|
74
|
+
Requires-Dist: opencv-python; extra == "all"
|
75
|
+
Requires-Dist: pg8000; extra == "all"
|
76
|
+
Requires-Dist: pgvector; extra == "all"
|
77
|
+
Requires-Dist: pillow; extra == "all"
|
78
|
+
Requires-Dist: playwright; extra == "all"
|
79
|
+
Requires-Dist: psutil; extra == "all"
|
80
|
+
Requires-Dist: psycopg2-binary; extra == "all"
|
81
|
+
Requires-Dist: pydantic; extra == "all"
|
82
|
+
Requires-Dist: pypdf; extra == "all"
|
83
|
+
Requires-Dist: python-hcl2; extra == "all"
|
84
|
+
Requires-Dist: python-socketio; extra == "all"
|
85
|
+
Requires-Dist: pytesseract; extra == "all"
|
86
|
+
Requires-Dist: requests; extra == "all"
|
87
|
+
Requires-Dist: rich; extra == "all"
|
88
|
+
Requires-Dist: sounddevice; extra == "all"
|
89
|
+
Requires-Dist: supabase; extra == "all"
|
90
|
+
Requires-Dist: tabulate; extra == "all"
|
91
|
+
Requires-Dist: tantivy; extra == "all"
|
92
|
+
Requires-Dist: tenacity; extra == "all"
|
93
|
+
Requires-Dist: tiktoken; extra == "all"
|
94
|
+
Requires-Dist: unstructured[all-docs,local-inference]; extra == "all"
|
95
|
+
Requires-Dist: xlwings; extra == "all"
|
96
|
+
Provides-Extra: langchain
|
97
|
+
Requires-Dist: langchain; extra == "langchain"
|
98
|
+
Requires-Dist: langchain_experimental; extra == "langchain"
|
99
|
+
Requires-Dist: langchain-community; extra == "langchain"
|
100
|
+
Requires-Dist: langsmith; extra == "langchain"
|
101
|
+
Requires-Dist: langchain-unstructured; extra == "langchain"
|
102
|
+
Provides-Extra: azure
|
103
|
+
Requires-Dist: azure-identity; extra == "azure"
|
104
|
+
Requires-Dist: azure-storage-blob; extra == "azure"
|
105
|
+
Provides-Extra: cli
|
106
|
+
Requires-Dist: jsonschema>=4.21.1; extra == "cli"
|
107
|
+
Requires-Dist: rich; extra == "cli"
|
108
|
+
Provides-Extra: database
|
109
|
+
Requires-Dist: asyncpg; extra == "database"
|
110
|
+
Requires-Dist: supabase; extra == "database"
|
111
|
+
Requires-Dist: sqlalchemy; extra == "database"
|
112
|
+
Requires-Dist: pg8000; extra == "database"
|
113
|
+
Requires-Dist: pgvector; extra == "database"
|
114
|
+
Requires-Dist: psycopg2-binary; extra == "database"
|
115
|
+
Requires-Dist: lancedb; extra == "database"
|
116
|
+
Requires-Dist: tantivy; extra == "database"
|
117
|
+
Provides-Extra: pipeline
|
118
|
+
Requires-Dist: GitPython; extra == "pipeline"
|
119
|
+
Requires-Dist: lark; extra == "pipeline"
|
120
|
+
Requires-Dist: langchain>=0.2.16; extra == "pipeline"
|
121
|
+
Requires-Dist: langchain-unstructured; extra == "pipeline"
|
122
|
+
Requires-Dist: psutil; extra == "pipeline"
|
123
|
+
Requires-Dist: pypdf; extra == "pipeline"
|
124
|
+
Requires-Dist: pytesseract; extra == "pipeline"
|
125
|
+
Requires-Dist: tabulate; extra == "pipeline"
|
126
|
+
Requires-Dist: unstructured[all-docs,local-inference]; extra == "pipeline"
|
127
|
+
Provides-Extra: gcp
|
128
|
+
Requires-Dist: aiofiles; extra == "gcp"
|
129
|
+
Requires-Dist: anthropic[vertex]; extra == "gcp"
|
130
|
+
Requires-Dist: google-api-python-client; extra == "gcp"
|
131
|
+
Requires-Dist: google-auth-httplib2; extra == "gcp"
|
132
|
+
Requires-Dist: google-auth-oauthlib; extra == "gcp"
|
133
|
+
Requires-Dist: google-cloud-alloydb-connector[pg8000]; extra == "gcp"
|
134
|
+
Requires-Dist: google-cloud-aiplatform>=1.58.0; extra == "gcp"
|
135
|
+
Requires-Dist: google-cloud-bigquery; extra == "gcp"
|
136
|
+
Requires-Dist: google-cloud-build; extra == "gcp"
|
137
|
+
Requires-Dist: google-cloud-service-control; extra == "gcp"
|
138
|
+
Requires-Dist: google-cloud-storage; extra == "gcp"
|
139
|
+
Requires-Dist: google-cloud-logging; extra == "gcp"
|
140
|
+
Requires-Dist: google-cloud-pubsub; extra == "gcp"
|
141
|
+
Requires-Dist: google-cloud-discoveryengine>=0.13.4; extra == "gcp"
|
142
|
+
Requires-Dist: google-cloud-texttospeech; extra == "gcp"
|
143
|
+
Requires-Dist: google-genai>=0.2.2; extra == "gcp"
|
144
|
+
Requires-Dist: google-generativeai>=0.8.3; extra == "gcp"
|
145
|
+
Requires-Dist: langchain; extra == "gcp"
|
146
|
+
Requires-Dist: langchain-google-genai>=2.0.0; extra == "gcp"
|
147
|
+
Requires-Dist: langchain_google_alloydb_pg>=0.2.2; extra == "gcp"
|
148
|
+
Requires-Dist: langchain-google-vertexai; extra == "gcp"
|
149
|
+
Requires-Dist: pillow; extra == "gcp"
|
150
|
+
Provides-Extra: ollama
|
151
|
+
Requires-Dist: pillow; extra == "ollama"
|
152
|
+
Requires-Dist: ollama>=0.4.7; extra == "ollama"
|
153
|
+
Provides-Extra: openai
|
154
|
+
Requires-Dist: langchain-openai>=0.3.2; extra == "openai"
|
155
|
+
Requires-Dist: tiktoken; extra == "openai"
|
156
|
+
Provides-Extra: anthropic
|
157
|
+
Requires-Dist: langchain-anthropic>=0.1.23; extra == "anthropic"
|
158
|
+
Requires-Dist: mcp; extra == "anthropic"
|
159
|
+
Provides-Extra: tools
|
160
|
+
Requires-Dist: openapi-spec-validator; extra == "tools"
|
161
|
+
Requires-Dist: playwright; extra == "tools"
|
162
|
+
Provides-Extra: http
|
163
|
+
Requires-Dist: fastapi; extra == "http"
|
164
|
+
Requires-Dist: flask; extra == "http"
|
165
|
+
Requires-Dist: gunicorn; extra == "http"
|
166
|
+
Requires-Dist: httpcore; extra == "http"
|
167
|
+
Requires-Dist: httpx; extra == "http"
|
168
|
+
Requires-Dist: langchain; extra == "http"
|
169
|
+
Requires-Dist: langfuse; extra == "http"
|
170
|
+
Requires-Dist: python-socketio; extra == "http"
|
171
|
+
Requires-Dist: requests; extra == "http"
|
172
|
+
Requires-Dist: tenacity; extra == "http"
|
173
|
+
Provides-Extra: excel
|
174
|
+
Requires-Dist: xlwings; extra == "excel"
|
175
|
+
Requires-Dist: requests; extra == "excel"
|
176
|
+
Requires-Dist: rich; extra == "excel"
|
177
|
+
Provides-Extra: iac
|
178
|
+
Requires-Dist: python-hcl2; extra == "iac"
|
179
|
+
Provides-Extra: tts
|
180
|
+
Requires-Dist: google-cloud-texttospeech; extra == "tts"
|
181
|
+
Requires-Dist: numpy; extra == "tts"
|
182
|
+
Requires-Dist: sounddevice; extra == "tts"
|
183
|
+
Provides-Extra: video
|
184
|
+
Requires-Dist: opencv-python; extra == "video"
|
185
|
+
Dynamic: license-file
|
186
|
+
|
187
|
+
# Sunholo Python Library
|
188
|
+
|
189
|
+
[](https://pypi.python.org/pypi/sunholo/)
|
190
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
191
|
+
[](https://pypi.python.org/pypi/sunholo/)
|
192
|
+
|
193
|
+
🚀 **AI DevOps framework for building GenAI applications on Google Cloud Platform**
|
194
|
+
|
195
|
+
Sunholo is a comprehensive Python framework that streamlines the development, deployment, and management of Generative AI applications (VACs - Virtual Agent Computers). It provides a configuration-driven approach with deep integration into Google Cloud services while supporting multiple AI providers.
|
196
|
+
|
197
|
+
## 🎯 What is Sunholo?
|
198
|
+
|
199
|
+
Sunholo helps you:
|
200
|
+
- 🤖 Build conversational AI agents with any LLM provider (Vertex AI, OpenAI, Anthropic, Ollama)
|
201
|
+
- ☁️ Deploy to Google Cloud Run with automatic scaling
|
202
|
+
- 🗄️ Use AlloyDB and Discovery Engine for vector storage and search
|
203
|
+
- 🔄 Handle streaming responses and async processing
|
204
|
+
- 📄 Process documents with chunking and embedding pipelines
|
205
|
+
- 🔧 Manage complex configurations with YAML files
|
206
|
+
- 🎨 Create APIs, web apps, and chat bots
|
207
|
+
|
208
|
+
## 🚀 Quick Start
|
209
|
+
|
210
|
+
### Prerequisites
|
211
|
+
|
212
|
+
Install [uv](https://docs.astral.sh/uv/) - a fast, modern Python package manager:
|
213
|
+
|
214
|
+
```bash
|
215
|
+
# macOS/Linux
|
216
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
217
|
+
|
218
|
+
# Windows
|
219
|
+
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
|
220
|
+
```
|
221
|
+
|
222
|
+
### Installation
|
223
|
+
|
224
|
+
```bash
|
225
|
+
# Install with CLI tools (recommended)
|
226
|
+
uv tool install --from "sunholo[cli]" sunholo
|
227
|
+
|
228
|
+
# Install with all features including GCP
|
229
|
+
uv tool install --from "sunholo[cli]" sunholo --with "sunholo[all]"
|
230
|
+
```
|
231
|
+
|
232
|
+
### Your First VAC
|
233
|
+
|
234
|
+
1. **Initialize a new project:**
|
235
|
+
```bash
|
236
|
+
sunholo init my-ai-agent
|
237
|
+
cd my-ai-agent
|
238
|
+
```
|
239
|
+
|
240
|
+
2. **Configure your AI agent:**
|
241
|
+
Edit `config/vac_config.yaml`:
|
242
|
+
```yaml
|
243
|
+
kind: vacConfig
|
244
|
+
apiVersion: v1
|
245
|
+
vac:
|
246
|
+
my-agent:
|
247
|
+
llm: vertex
|
248
|
+
model: gemini-1.5-pro
|
249
|
+
agent: simple
|
250
|
+
description: "My AI agent powered by Google Cloud"
|
251
|
+
```
|
252
|
+
|
253
|
+
3. **Chat with your agent locally:**
|
254
|
+
```bash
|
255
|
+
sunholo vac chat my-agent
|
256
|
+
```
|
257
|
+
|
258
|
+
4. **Deploy to Google Cloud Run:**
|
259
|
+
```bash
|
260
|
+
sunholo deploy my-agent
|
261
|
+
```
|
262
|
+
|
263
|
+
## 📋 Features
|
264
|
+
|
265
|
+
### Core Capabilities
|
266
|
+
|
267
|
+
- **Multi-Model Support**: Integrate Vertex AI, OpenAI, Anthropic, Ollama in one app
|
268
|
+
- **Document Processing**: Chunk, embed, and index documents with Discovery Engine
|
269
|
+
- **Vector Databases**: Native support for AlloyDB, LanceDB, Supabase
|
270
|
+
- **Streaming**: Real-time response streaming for chat applications
|
271
|
+
- **Async Processing**: Pub/Sub integration for background tasks
|
272
|
+
- **Authentication**: Built-in Google Cloud IAM and custom auth
|
273
|
+
|
274
|
+
### Google Cloud Integration
|
275
|
+
|
276
|
+
- **Vertex AI**: Access Gemini, PaLM, and custom models
|
277
|
+
- **AlloyDB**: PostgreSQL-compatible vector database
|
278
|
+
- **Discovery Engine**: Enterprise search and RAG
|
279
|
+
- **Cloud Run**: Serverless deployment
|
280
|
+
- **Cloud Storage**: Document and file management
|
281
|
+
- **Pub/Sub**: Asynchronous message processing
|
282
|
+
- **Cloud Logging**: Centralized logging
|
283
|
+
|
284
|
+
### Framework Support
|
285
|
+
|
286
|
+
- **Web Frameworks**: Flask and FastAPI templates
|
287
|
+
- **AI Frameworks**: LangChain and LlamaIndex integration
|
288
|
+
- **Observability**: Langfuse for tracing and monitoring
|
289
|
+
- **API Standards**: OpenAI-compatible endpoints
|
290
|
+
|
291
|
+
## 🛠 Installation Options
|
292
|
+
|
293
|
+
### Using uv
|
294
|
+
|
295
|
+
```bash
|
296
|
+
# Core CLI features
|
297
|
+
uv tool install --from "sunholo[cli]" sunholo
|
298
|
+
|
299
|
+
# With Google Cloud Platform integration
|
300
|
+
uv tool install --from "sunholo[cli]" sunholo --with "sunholo[gcp]"
|
301
|
+
|
302
|
+
# With specific LLM providers
|
303
|
+
uv tool install --from "sunholo[cli]" sunholo --with "sunholo[openai]"
|
304
|
+
uv tool install --from "sunholo[cli]" sunholo --with "sunholo[anthropic]"
|
305
|
+
|
306
|
+
# With database support
|
307
|
+
uv tool install --from "sunholo[cli]" sunholo --with "sunholo[database]"
|
308
|
+
|
309
|
+
# Everything
|
310
|
+
uv tool install --from "sunholo[cli]" sunholo --with "sunholo[all]"
|
311
|
+
```
|
312
|
+
|
313
|
+
### Managing Installations
|
314
|
+
|
315
|
+
```bash
|
316
|
+
# Upgrade
|
317
|
+
uv tool upgrade sunholo
|
318
|
+
|
319
|
+
# List installed
|
320
|
+
uv tool list
|
321
|
+
|
322
|
+
# Uninstall
|
323
|
+
uv tool uninstall sunholo
|
324
|
+
```
|
325
|
+
|
326
|
+
### Development Setup
|
327
|
+
|
328
|
+
```bash
|
329
|
+
# Clone repository
|
330
|
+
git clone https://github.com/sunholo-data/sunholo-py.git
|
331
|
+
cd sunholo-py
|
332
|
+
|
333
|
+
# Install in development mode
|
334
|
+
uv venv
|
335
|
+
uv pip install -e ".[all]"
|
336
|
+
|
337
|
+
# Run tests
|
338
|
+
pytest tests/
|
339
|
+
```
|
340
|
+
|
341
|
+
## ⚙️ Configuration
|
342
|
+
|
343
|
+
Sunholo uses YAML configuration files:
|
344
|
+
|
345
|
+
```yaml
|
346
|
+
# config/vac_config.yaml
|
347
|
+
kind: vacConfig
|
348
|
+
apiVersion: v1
|
349
|
+
gcp_config:
|
350
|
+
project_id: my-gcp-project
|
351
|
+
location: us-central1
|
352
|
+
vac:
|
353
|
+
my-agent:
|
354
|
+
llm: vertex
|
355
|
+
model: gemini-1.5-pro
|
356
|
+
agent: langchain
|
357
|
+
memory:
|
358
|
+
- alloydb:
|
359
|
+
project_id: my-gcp-project
|
360
|
+
region: us-central1
|
361
|
+
cluster: my-cluster
|
362
|
+
instance: my-instance
|
363
|
+
tools:
|
364
|
+
- search
|
365
|
+
- calculator
|
366
|
+
```
|
367
|
+
|
368
|
+
## 🔧 CLI Commands
|
369
|
+
|
370
|
+
```bash
|
371
|
+
# Project Management
|
372
|
+
sunholo init <project-name> # Create new project
|
373
|
+
sunholo list-configs # List all configurations
|
374
|
+
sunholo list-configs --validate # Validate configs
|
375
|
+
|
376
|
+
# Development
|
377
|
+
sunholo vac chat <vac-name> # Chat with a VAC locally
|
378
|
+
sunholo vac list # List available VACs
|
379
|
+
sunholo proxy start <service> # Start local proxy to cloud service
|
380
|
+
|
381
|
+
# Deployment
|
382
|
+
sunholo deploy <vac-name> # Deploy to Cloud Run
|
383
|
+
sunholo deploy <vac-name> --dev # Deploy to dev environment
|
384
|
+
|
385
|
+
# Document Processing
|
386
|
+
sunholo embed <vac-name> # Embed documents
|
387
|
+
sunholo merge-text <folder> <output> # Merge files for context
|
388
|
+
|
389
|
+
# Cloud Services
|
390
|
+
sunholo discovery-engine create <name> # Create Discovery Engine
|
391
|
+
sunholo proxy list # List running proxies
|
392
|
+
```
|
393
|
+
|
394
|
+
## 📝 Examples
|
395
|
+
|
396
|
+
### Vertex AI Chat with Memory
|
397
|
+
|
398
|
+
```python
|
399
|
+
from sunholo.utils import ConfigManager
|
400
|
+
from sunholo.components import pick_llm
|
401
|
+
from sunholo.agents import memory_client
|
402
|
+
|
403
|
+
config = ConfigManager('my-agent')
|
404
|
+
llm = pick_llm(config=config)
|
405
|
+
memory = memory_client(config=config)
|
406
|
+
|
407
|
+
# Chat with context
|
408
|
+
response = llm.invoke("What is Google Cloud?")
|
409
|
+
memory.add_message("user", "What is Google Cloud?")
|
410
|
+
memory.add_message("assistant", response)
|
411
|
+
```
|
412
|
+
|
413
|
+
### Document Processing with Discovery Engine
|
414
|
+
|
415
|
+
```python
|
416
|
+
from sunholo.discovery_engine import DiscoveryEngineClient
|
417
|
+
from sunholo.chunker import chunk_doc
|
418
|
+
|
419
|
+
# Initialize client
|
420
|
+
client = DiscoveryEngineClient(
|
421
|
+
project_id='my-project',
|
422
|
+
data_store_id='my-datastore'
|
423
|
+
)
|
424
|
+
|
425
|
+
# Process and index document
|
426
|
+
chunks = chunk_doc.chunk_file("document.pdf", chunk_size=1000)
|
427
|
+
client.import_documents(chunks)
|
428
|
+
|
429
|
+
# Search
|
430
|
+
results = client.search("What is the main topic?")
|
431
|
+
```
|
432
|
+
|
433
|
+
### Streaming Flask API
|
434
|
+
|
435
|
+
```python
|
436
|
+
from sunholo.agents import dispatch_to_qa
|
437
|
+
|
438
|
+
@app.route('/vac/streaming/<vac_name>', methods=['POST'])
|
439
|
+
def streaming_endpoint(vac_name):
|
440
|
+
question = request.json.get('user_input')
|
441
|
+
|
442
|
+
def generate():
|
443
|
+
for chunk in dispatch_to_qa(
|
444
|
+
question,
|
445
|
+
vac_name=vac_name,
|
446
|
+
stream=True
|
447
|
+
):
|
448
|
+
yield f"data: {chunk}\n\n"
|
449
|
+
|
450
|
+
return Response(generate(), content_type='text/event-stream')
|
451
|
+
```
|
452
|
+
|
453
|
+
### Deploy from Template
|
454
|
+
|
455
|
+
```bash
|
456
|
+
# Create from template
|
457
|
+
sunholo init my-api --template agent
|
458
|
+
|
459
|
+
# Customize configuration
|
460
|
+
cd my-api
|
461
|
+
vi config/vac_config.yaml
|
462
|
+
|
463
|
+
# Test locally
|
464
|
+
sunholo vac chat my-agent --local
|
465
|
+
|
466
|
+
# Deploy to production
|
467
|
+
sunholo deploy my-agent
|
468
|
+
```
|
469
|
+
|
470
|
+
## 🧪 Testing
|
471
|
+
|
472
|
+
```bash
|
473
|
+
# Run all tests
|
474
|
+
pytest tests/
|
475
|
+
|
476
|
+
# Run specific test file
|
477
|
+
pytest tests/test_config.py
|
478
|
+
|
479
|
+
# Run with coverage
|
480
|
+
pytest --cov=src/sunholo tests/
|
481
|
+
|
482
|
+
# Run async tests
|
483
|
+
pytest tests/test_async_genai2.py
|
484
|
+
```
|
485
|
+
|
486
|
+
## 📚 Documentation
|
487
|
+
|
488
|
+
- 📖 **Full Documentation**: https://dev.sunholo.com/
|
489
|
+
- 🎓 **Tutorials**: https://dev.sunholo.com/docs/howto/
|
490
|
+
- 🤖 **VAC Examples**: https://github.com/sunholo-data/vacs-public
|
491
|
+
- 🎧 **Audio Overview**: [Listen to the NotebookLM podcast](https://drive.google.com/file/d/1GvwRmiYDjPjN2hXQ8plhnVDByu6TmgCQ/view?usp=drive_link)
|
492
|
+
|
493
|
+
## 🤝 Contributing
|
494
|
+
|
495
|
+
We welcome contributions! See our [Contributing Guidelines](CONTRIBUTING.md).
|
496
|
+
|
497
|
+
1. Fork the repository
|
498
|
+
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
499
|
+
3. Commit your changes (`git commit -m 'Add AmazingFeature'`)
|
500
|
+
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
501
|
+
5. Open a Pull Request
|
502
|
+
|
503
|
+
## 📜 License
|
504
|
+
|
505
|
+
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE.txt) file for details.
|
506
|
+
|
507
|
+
```
|
508
|
+
Copyright [2024] [Holosun ApS]
|
509
|
+
|
510
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
511
|
+
you may not use this file except in compliance with the License.
|
512
|
+
You may obtain a copy of the License at
|
513
|
+
|
514
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
515
|
+
```
|
516
|
+
|
517
|
+
## 🙏 Support
|
518
|
+
|
519
|
+
- 📧 Email: multivac@sunholo.com
|
520
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/sunholo-data/sunholo-py/issues)
|
521
|
+
- 💬 Discussions: [GitHub Discussions](https://github.com/sunholo-data/sunholo-py/discussions)
|
522
|
+
- 📖 Documentation: https://dev.sunholo.com/
|