sunholo 0.142.0__tar.gz → 0.143.3__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.
Files changed (197) hide show
  1. {sunholo-0.142.0/src/sunholo.egg-info → sunholo-0.143.3}/PKG-INFO +9 -6
  2. {sunholo-0.142.0 → sunholo-0.143.3}/pyproject.toml +9 -6
  3. sunholo-0.143.3/src/sunholo/a2a/__init__.py +27 -0
  4. sunholo-0.143.3/src/sunholo/a2a/agent_card.py +345 -0
  5. sunholo-0.143.3/src/sunholo/a2a/task_manager.py +480 -0
  6. sunholo-0.143.3/src/sunholo/a2a/vac_a2a_agent.py +383 -0
  7. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/flask/vac_routes.py +545 -1
  8. sunholo-0.143.3/src/sunholo/mcp/__init__.py +20 -0
  9. sunholo-0.143.3/src/sunholo/mcp/mcp_manager.py +98 -0
  10. sunholo-0.143.3/src/sunholo/mcp/vac_mcp_server.py +259 -0
  11. {sunholo-0.142.0 → sunholo-0.143.3/src/sunholo.egg-info}/PKG-INFO +9 -6
  12. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo.egg-info/SOURCES.txt +8 -1
  13. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo.egg-info/requires.txt +7 -4
  14. sunholo-0.143.3/tests/test_vac_routes_mcp.py +339 -0
  15. sunholo-0.142.0/src/sunholo/templates/system_services/__init__.py +0 -0
  16. {sunholo-0.142.0 → sunholo-0.143.3}/LICENSE.txt +0 -0
  17. {sunholo-0.142.0 → sunholo-0.143.3}/MANIFEST.in +0 -0
  18. {sunholo-0.142.0 → sunholo-0.143.3}/README.md +0 -0
  19. {sunholo-0.142.0 → sunholo-0.143.3}/setup.cfg +0 -0
  20. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/__init__.py +0 -0
  21. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/__init__.py +0 -0
  22. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/chat_history.py +0 -0
  23. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/dispatch_to_qa.py +0 -0
  24. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/fastapi/__init__.py +0 -0
  25. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/fastapi/base.py +0 -0
  26. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
  27. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/flask/__init__.py +0 -0
  28. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/flask/base.py +0 -0
  29. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/langserve.py +0 -0
  30. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/pubsub.py +0 -0
  31. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/route.py +0 -0
  32. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/special_commands.py +0 -0
  33. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/agents/swagger.py +0 -0
  34. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/archive/__init__.py +0 -0
  35. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/archive/archive.py +0 -0
  36. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/auth/__init__.py +0 -0
  37. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/auth/gcloud.py +0 -0
  38. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/auth/refresh.py +0 -0
  39. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/auth/run.py +0 -0
  40. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/azure/__init__.py +0 -0
  41. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/azure/auth.py +0 -0
  42. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/azure/blobs.py +0 -0
  43. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/azure/event_grid.py +0 -0
  44. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/bots/__init__.py +0 -0
  45. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/bots/discord.py +0 -0
  46. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/bots/github_webhook.py +0 -0
  47. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/bots/webapp.py +0 -0
  48. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/__init__.py +0 -0
  49. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/azure.py +0 -0
  50. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/doc_handling.py +0 -0
  51. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/encode_metadata.py +0 -0
  52. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/images.py +0 -0
  53. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/loaders.py +0 -0
  54. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/message_data.py +0 -0
  55. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/pdfs.py +0 -0
  56. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/process_chunker_data.py +0 -0
  57. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/publish.py +0 -0
  58. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/pubsub.py +0 -0
  59. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/chunker/splitter.py +0 -0
  60. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/__init__.py +0 -0
  61. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/chat_vac.py +0 -0
  62. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/cli.py +0 -0
  63. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/cli_init.py +0 -0
  64. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/configs.py +0 -0
  65. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/deploy.py +0 -0
  66. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/embedder.py +0 -0
  67. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/merge_texts.py +0 -0
  68. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/run_proxy.py +0 -0
  69. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/sun_rich.py +0 -0
  70. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/swagger.py +0 -0
  71. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/cli/vertex.py +0 -0
  72. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/components/__init__.py +0 -0
  73. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/components/llm.py +0 -0
  74. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/components/retriever.py +0 -0
  75. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/components/vectorstore.py +0 -0
  76. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/custom_logging.py +0 -0
  77. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/__init__.py +0 -0
  78. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/alloydb.py +0 -0
  79. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/alloydb_client.py +0 -0
  80. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/database.py +0 -0
  81. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/lancedb.py +0 -0
  82. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/sql/sb/create_function.sql +0 -0
  83. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
  84. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/sql/sb/create_table.sql +0 -0
  85. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  86. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
  87. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/sql/sb/setup.sql +0 -0
  88. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/static_dbs.py +0 -0
  89. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/database/uuid.py +0 -0
  90. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/discovery_engine/__init__.py +0 -0
  91. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
  92. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/discovery_engine/cli.py +0 -0
  93. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/discovery_engine/create_new.py +0 -0
  94. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  95. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  96. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/embedder/__init__.py +0 -0
  97. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/embedder/embed_chunk.py +0 -0
  98. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/embedder/embed_metadata.py +0 -0
  99. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/excel/__init__.py +0 -0
  100. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/excel/plugin.py +0 -0
  101. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/gcs/__init__.py +0 -0
  102. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/gcs/add_file.py +0 -0
  103. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/gcs/download_folder.py +0 -0
  104. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/gcs/download_gcs_text.py +0 -0
  105. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/gcs/download_url.py +0 -0
  106. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/gcs/extract_and_sign.py +0 -0
  107. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/gcs/metadata.py +0 -0
  108. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/genai/__init__.py +0 -0
  109. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/genai/file_handling.py +0 -0
  110. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/genai/genaiv2.py +0 -0
  111. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/genai/images.py +0 -0
  112. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/genai/init.py +0 -0
  113. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/genai/process_funcs_cls.py +0 -0
  114. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/genai/safety.py +0 -0
  115. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/invoke/__init__.py +0 -0
  116. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/invoke/async_class.py +0 -0
  117. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/invoke/direct_vac_func.py +0 -0
  118. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
  119. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/langchain_types.py +0 -0
  120. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/langfuse/__init__.py +0 -0
  121. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/langfuse/callback.py +0 -0
  122. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/langfuse/evals.py +0 -0
  123. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/langfuse/prompts.py +0 -0
  124. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/llamaindex/__init__.py +0 -0
  125. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/llamaindex/get_files.py +0 -0
  126. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/llamaindex/import_files.py +0 -0
  127. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
  128. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/llamaindex/user_history.py +0 -0
  129. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/lookup/__init__.py +0 -0
  130. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/lookup/model_lookup.yaml +0 -0
  131. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/mcp/cli.py +0 -0
  132. {sunholo-0.142.0/src/sunholo/mcp → sunholo-0.143.3/src/sunholo/ollama}/__init__.py +0 -0
  133. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/ollama/ollama_images.py +0 -0
  134. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/pubsub/__init__.py +0 -0
  135. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/pubsub/process_pubsub.py +0 -0
  136. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/pubsub/pubsub_manager.py +0 -0
  137. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/qna/__init__.py +0 -0
  138. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/qna/parsers.py +0 -0
  139. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/qna/retry.py +0 -0
  140. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/senses/__init__.py +0 -0
  141. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/senses/stream_voice.py +0 -0
  142. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/streaming/__init__.py +0 -0
  143. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/streaming/content_buffer.py +0 -0
  144. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/streaming/langserve.py +0 -0
  145. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/streaming/stream_lookup.py +0 -0
  146. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/streaming/streaming.py +0 -0
  147. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/summarise/__init__.py +0 -0
  148. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/summarise/summarise.py +0 -0
  149. {sunholo-0.142.0/src/sunholo/ollama → sunholo-0.143.3/src/sunholo/templates/agent}/__init__.py +0 -0
  150. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/agent/agent_service.py +0 -0
  151. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/agent/app.py +0 -0
  152. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/agent/my_log.py +0 -0
  153. {sunholo-0.142.0/src/sunholo/templates/agent → sunholo-0.143.3/src/sunholo/templates/agent/tools}/__init__.py +0 -0
  154. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
  155. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/agent/vac_service.py +0 -0
  156. {sunholo-0.142.0/src/sunholo/templates/agent/tools → sunholo-0.143.3/src/sunholo/templates/project}/__init__.py +0 -0
  157. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/project/app.py +0 -0
  158. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/project/my_log.py +0 -0
  159. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/project/vac_service.py +0 -0
  160. {sunholo-0.142.0/src/sunholo/templates/project → sunholo-0.143.3/src/sunholo/templates/system_services}/__init__.py +0 -0
  161. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/system_services/app.py +0 -0
  162. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/templates/system_services/my_log.py +0 -0
  163. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/terraform/__init__.py +0 -0
  164. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/terraform/tfvars_editor.py +0 -0
  165. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/tools/__init__.py +0 -0
  166. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/tools/web_browser.py +0 -0
  167. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/__init__.py +0 -0
  168. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/api_key.py +0 -0
  169. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/big_context.py +0 -0
  170. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/config.py +0 -0
  171. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/config_class.py +0 -0
  172. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/config_schema.py +0 -0
  173. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/gcp.py +0 -0
  174. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/gcp_project.py +0 -0
  175. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/mime.py +0 -0
  176. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/parsers.py +0 -0
  177. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/proto_convert.py +0 -0
  178. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/timedelta.py +0 -0
  179. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/user_ids.py +0 -0
  180. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/utils/version.py +0 -0
  181. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/__init__.py +0 -0
  182. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/extensions_call.py +0 -0
  183. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/extensions_class.py +0 -0
  184. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/genai_functions.py +0 -0
  185. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/init.py +0 -0
  186. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/memory_tools.py +0 -0
  187. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/safety.py +0 -0
  188. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo/vertex/type_dict_to_json.py +0 -0
  189. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo.egg-info/dependency_links.txt +0 -0
  190. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo.egg-info/entry_points.txt +0 -0
  191. {sunholo-0.142.0 → sunholo-0.143.3}/src/sunholo.egg-info/top_level.txt +0 -0
  192. {sunholo-0.142.0 → sunholo-0.143.3}/tests/test_async.py +0 -0
  193. {sunholo-0.142.0 → sunholo-0.143.3}/tests/test_async_genai2.py +0 -0
  194. {sunholo-0.142.0 → sunholo-0.143.3}/tests/test_chat_history.py +0 -0
  195. {sunholo-0.142.0 → sunholo-0.143.3}/tests/test_config.py +0 -0
  196. {sunholo-0.142.0 → sunholo-0.143.3}/tests/test_genai2.py +0 -0
  197. {sunholo-0.142.0 → sunholo-0.143.3}/tests/test_unstructured.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.142.0
3
+ Version: 0.143.3
4
4
  Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
5
5
  Author-email: Holosun ApS <multivac@sunholo.com>
6
6
  License: Apache License, Version 2.0
@@ -15,14 +15,16 @@ Classifier: Programming Language :: Python :: 3
15
15
  Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
- Requires-Python: >=3.10
18
+ Requires-Python: >=3.11
19
19
  Description-Content-Type: text/markdown
20
20
  License-File: LICENSE.txt
21
+ Requires-Dist: a2a-python>=0.0.1
21
22
  Requires-Dist: aiohttp
23
+ Requires-Dist: flask>=3.1.0
22
24
  Requires-Dist: google-auth
23
- Requires-Dist: ollama>=0.4.7
24
- Requires-Dist: pillow>=11.0.0
25
+ Requires-Dist: mcp>=1.1.1
25
26
  Requires-Dist: pydantic
27
+ Requires-Dist: pytest-asyncio>=1.0.0
26
28
  Requires-Dist: requests
27
29
  Requires-Dist: ruamel.yaml
28
30
  Requires-Dist: tenacity
@@ -69,7 +71,7 @@ Requires-Dist: langchain-anthropic>=0.1.23; extra == "all"
69
71
  Requires-Dist: langchain-google-vertexai; extra == "all"
70
72
  Requires-Dist: langchain-unstructured; extra == "all"
71
73
  Requires-Dist: langfuse; extra == "all"
72
- Requires-Dist: mcp; extra == "all"
74
+ Requires-Dist: mcp>=1.1.1; extra == "all"
73
75
  Requires-Dist: numpy; extra == "all"
74
76
  Requires-Dist: opencv-python; extra == "all"
75
77
  Requires-Dist: pg8000; extra == "all"
@@ -125,6 +127,7 @@ Requires-Dist: pytesseract; extra == "pipeline"
125
127
  Requires-Dist: tabulate; extra == "pipeline"
126
128
  Requires-Dist: unstructured[all-docs,local-inference]; extra == "pipeline"
127
129
  Provides-Extra: gcp
130
+ Requires-Dist: a2a-python; extra == "gcp"
128
131
  Requires-Dist: aiofiles; extra == "gcp"
129
132
  Requires-Dist: anthropic[vertex]; extra == "gcp"
130
133
  Requires-Dist: google-api-python-client; extra == "gcp"
@@ -155,7 +158,7 @@ Requires-Dist: langchain-openai>=0.3.2; extra == "openai"
155
158
  Requires-Dist: tiktoken; extra == "openai"
156
159
  Provides-Extra: anthropic
157
160
  Requires-Dist: langchain-anthropic>=0.1.23; extra == "anthropic"
158
- Requires-Dist: mcp; extra == "anthropic"
161
+ Requires-Dist: mcp>=1.1.1; extra == "anthropic"
159
162
  Provides-Extra: tools
160
163
  Requires-Dist: openapi-spec-validator; extra == "tools"
161
164
  Requires-Dist: playwright; extra == "tools"
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sunholo"
7
- version = "0.142.0"
7
+ version = "0.143.3"
8
8
  description = "AI DevOps - a package to help deploy GenAI to the Cloud."
9
9
  readme = "README.md"
10
- requires-python = ">=3.10"
10
+ requires-python = ">=3.11"
11
11
  license = { text = "Apache License, Version 2.0" }
12
12
  authors = [
13
13
  { name = "Holosun ApS", email = "multivac@sunholo.com" },
@@ -25,11 +25,13 @@ classifiers = [
25
25
  ]
26
26
 
27
27
  dependencies = [
28
+ "a2a-python>=0.0.1",
28
29
  "aiohttp",
30
+ "flask>=3.1.0",
29
31
  "google-auth",
30
- "ollama>=0.4.7",
31
- "pillow>=11.0.0",
32
+ "mcp>=1.1.1",
32
33
  "pydantic",
34
+ "pytest-asyncio>=1.0.0",
33
35
  "requests",
34
36
  "ruamel.yaml",
35
37
  "tenacity",
@@ -100,7 +102,7 @@ all = [
100
102
  "langchain-google-vertexai",
101
103
  "langchain-unstructured",
102
104
  "langfuse",
103
- "mcp",
105
+ "mcp>=1.1.1",
104
106
  "numpy",
105
107
  "opencv-python",
106
108
  "pg8000",
@@ -162,6 +164,7 @@ pipeline = [
162
164
  "unstructured[local-inference,all-docs]"
163
165
  ]
164
166
  gcp = [
167
+ "a2a-python",
165
168
  "aiofiles",
166
169
  "anthropic[vertex]",
167
170
  "google-api-python-client",
@@ -195,7 +198,7 @@ openai = [
195
198
  ]
196
199
  anthropic = [
197
200
  "langchain-anthropic>=0.1.23",
198
- "mcp"
201
+ "mcp>=1.1.1"
199
202
  ]
200
203
  tools = [
201
204
  "openapi-spec-validator",
@@ -0,0 +1,27 @@
1
+ # Copyright [2024] [Holosun ApS]
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """A2A (Agent-to-Agent) protocol integration for Sunholo."""
16
+
17
+ try:
18
+ from .agent_card import AgentCardGenerator
19
+ from .task_manager import A2ATaskManager
20
+ from .vac_a2a_agent import VACA2AAgent
21
+ except (ImportError, SyntaxError) as e:
22
+ # Handle missing dependencies or syntax errors gracefully
23
+ AgentCardGenerator = None
24
+ VACA2AAgent = None
25
+ A2ATaskManager = None
26
+
27
+ __all__ = ['AgentCardGenerator', 'VACA2AAgent', 'A2ATaskManager']
@@ -0,0 +1,345 @@
1
+ # Copyright [2024] [Holosun ApS]
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """
16
+ Agent Card generation for A2A protocol.
17
+ Generates agent.json discovery documents for VACs.
18
+ """
19
+
20
+ from typing import Dict, List, Any, Optional
21
+ import os
22
+ from ..utils import ConfigManager
23
+ from ..custom_logging import log
24
+ from ..utils.version import sunholo_version
25
+
26
+
27
+ class AgentCardGenerator:
28
+ """Generates A2A Agent Cards for VAC discovery."""
29
+
30
+ def __init__(self, base_url: str, config_manager: Optional[ConfigManager] = None):
31
+ """
32
+ Initialize the Agent Card generator.
33
+
34
+ Args:
35
+ base_url: The base URL where the A2A agent is hosted
36
+ config_manager: Optional ConfigManager for global configs
37
+ """
38
+ self.base_url = base_url.rstrip('/')
39
+ self.config_manager = config_manager or ConfigManager('global', validate=False)
40
+
41
+ def generate_agent_card(self, vac_names: List[str] = None) -> Dict[str, Any]:
42
+ """
43
+ Generate the Agent Card JSON for A2A discovery.
44
+
45
+ Args:
46
+ vac_names: List of VAC names to include. If None, discovers all configured VACs.
47
+
48
+ Returns:
49
+ Dict containing the Agent Card JSON structure
50
+ """
51
+ if vac_names is None:
52
+ vac_names = self._discover_vacs()
53
+
54
+ skills = []
55
+ agent_name = "Sunholo VAC Agent"
56
+ agent_description = "Multi-VAC agent providing access to Sunholo Virtual Agent Computers"
57
+
58
+ # Generate skills for each VAC
59
+ for vac_name in vac_names:
60
+ try:
61
+ vac_config = ConfigManager(vac_name, validate=False)
62
+ vac_skills = self._generate_vac_skills(vac_name, vac_config)
63
+ skills.extend(vac_skills)
64
+
65
+ # Use first VAC display name as primary agent name if available
66
+ if len(skills) == len(vac_skills): # First VAC
67
+ display_name = vac_config.vacConfig('display_name')
68
+ if display_name:
69
+ agent_name = f"{display_name} Agent"
70
+
71
+ except Exception as e:
72
+ log.warning(f"Failed to process VAC {vac_name}: {e}")
73
+ continue
74
+
75
+ # If we have multiple VACs, use a generic name
76
+ if len(vac_names) > 1:
77
+ agent_name = "Sunholo Multi-VAC Agent"
78
+ agent_description = f"Agent providing access to {len(vac_names)} Sunholo VACs: {', '.join(vac_names)}"
79
+
80
+ agent_card = {
81
+ "name": agent_name,
82
+ "description": agent_description,
83
+ "url": self.base_url,
84
+ "version": sunholo_version(),
85
+ "capabilities": [
86
+ "task_management",
87
+ "streaming",
88
+ "conversation",
89
+ "document_retrieval"
90
+ ],
91
+ "skills": skills,
92
+ "metadata": {
93
+ "framework": "sunholo",
94
+ "protocol_version": "a2a-v1",
95
+ "supported_formats": ["text", "json"],
96
+ "max_context_length": self._get_max_context_length(vac_names),
97
+ "languages": ["en"], # TODO: Make configurable
98
+ "created_at": self._get_current_timestamp()
99
+ }
100
+ }
101
+
102
+ return agent_card
103
+
104
+ def _discover_vacs(self) -> List[str]:
105
+ """
106
+ Discover all configured VACs from the configuration.
107
+
108
+ Returns:
109
+ List of VAC names found in the configuration
110
+ """
111
+ try:
112
+ vac_configs = self.config_manager.configs_by_kind.get('vacConfig', {})
113
+ if 'vac' in vac_configs:
114
+ return list(vac_configs['vac'].keys())
115
+ return []
116
+ except Exception as e:
117
+ log.error(f"Failed to discover VACs: {e}")
118
+ return []
119
+
120
+ def _generate_vac_skills(self, vac_name: str, vac_config: ConfigManager) -> List[Dict[str, Any]]:
121
+ """
122
+ Generate A2A skills for a specific VAC.
123
+
124
+ Args:
125
+ vac_name: Name of the VAC
126
+ vac_config: ConfigManager instance for the VAC
127
+
128
+ Returns:
129
+ List of skill definitions for this VAC
130
+ """
131
+ skills = []
132
+
133
+ # Get VAC metadata
134
+ display_name = vac_config.vacConfig('display_name') or vac_name
135
+ model = vac_config.vacConfig('model') or 'unknown'
136
+ agent_type = vac_config.vacConfig('agent') or 'unknown'
137
+ memory_config = vac_config.vacConfig('memory') or []
138
+
139
+ # Skill 1: VAC Query (static response)
140
+ query_skill = {
141
+ "name": f"vac_query_{vac_name}",
142
+ "description": f"Send a query to {display_name} and get a complete response using {model}",
143
+ "input_schema": {
144
+ "type": "object",
145
+ "properties": {
146
+ "query": {
147
+ "type": "string",
148
+ "description": "The question or instruction to send to the VAC"
149
+ },
150
+ "chat_history": {
151
+ "type": "array",
152
+ "description": "Previous conversation history",
153
+ "items": {
154
+ "type": "object",
155
+ "properties": {
156
+ "role": {"type": "string", "enum": ["user", "assistant"]},
157
+ "content": {"type": "string"}
158
+ }
159
+ },
160
+ "default": []
161
+ },
162
+ "context": {
163
+ "type": "object",
164
+ "description": "Additional context or parameters",
165
+ "default": {}
166
+ }
167
+ },
168
+ "required": ["query"]
169
+ },
170
+ "output_schema": {
171
+ "type": "object",
172
+ "properties": {
173
+ "answer": {"type": "string"},
174
+ "source_documents": {"type": "array"},
175
+ "metadata": {"type": "object"}
176
+ }
177
+ },
178
+ "metadata": {
179
+ "vac_name": vac_name,
180
+ "model": model,
181
+ "agent_type": agent_type,
182
+ "memory_enabled": len(memory_config) > 0,
183
+ "response_type": "complete"
184
+ }
185
+ }
186
+ skills.append(query_skill)
187
+
188
+ # Skill 2: VAC Stream (streaming response)
189
+ stream_skill = {
190
+ "name": f"vac_stream_{vac_name}",
191
+ "description": f"Start a streaming conversation with {display_name} using {model}",
192
+ "input_schema": {
193
+ "type": "object",
194
+ "properties": {
195
+ "query": {
196
+ "type": "string",
197
+ "description": "The question or instruction to send to the VAC"
198
+ },
199
+ "chat_history": {
200
+ "type": "array",
201
+ "description": "Previous conversation history",
202
+ "items": {
203
+ "type": "object",
204
+ "properties": {
205
+ "role": {"type": "string", "enum": ["user", "assistant"]},
206
+ "content": {"type": "string"}
207
+ }
208
+ },
209
+ "default": []
210
+ },
211
+ "stream_settings": {
212
+ "type": "object",
213
+ "properties": {
214
+ "wait_time": {"type": "number", "default": 7},
215
+ "timeout": {"type": "number", "default": 120}
216
+ },
217
+ "default": {}
218
+ }
219
+ },
220
+ "required": ["query"]
221
+ },
222
+ "output_schema": {
223
+ "type": "object",
224
+ "properties": {
225
+ "stream_url": {"type": "string"},
226
+ "task_id": {"type": "string"},
227
+ "estimated_duration": {"type": "number"}
228
+ }
229
+ },
230
+ "metadata": {
231
+ "vac_name": vac_name,
232
+ "model": model,
233
+ "agent_type": agent_type,
234
+ "memory_enabled": len(memory_config) > 0,
235
+ "response_type": "streaming",
236
+ "supports_sse": True
237
+ }
238
+ }
239
+ skills.append(stream_skill)
240
+
241
+ # Skill 3: Memory Search (if VAC has memory configured)
242
+ if memory_config:
243
+ memory_skill = {
244
+ "name": f"vac_memory_search_{vac_name}",
245
+ "description": f"Search through {display_name}'s knowledge base and memory",
246
+ "input_schema": {
247
+ "type": "object",
248
+ "properties": {
249
+ "search_query": {
250
+ "type": "string",
251
+ "description": "The search query for the knowledge base"
252
+ },
253
+ "limit": {
254
+ "type": "integer",
255
+ "description": "Maximum number of results to return",
256
+ "default": 10,
257
+ "minimum": 1,
258
+ "maximum": 50
259
+ },
260
+ "similarity_threshold": {
261
+ "type": "number",
262
+ "description": "Minimum similarity score for results",
263
+ "default": 0.7,
264
+ "minimum": 0.0,
265
+ "maximum": 1.0
266
+ }
267
+ },
268
+ "required": ["search_query"]
269
+ },
270
+ "output_schema": {
271
+ "type": "object",
272
+ "properties": {
273
+ "results": {
274
+ "type": "array",
275
+ "items": {
276
+ "type": "object",
277
+ "properties": {
278
+ "content": {"type": "string"},
279
+ "score": {"type": "number"},
280
+ "metadata": {"type": "object"}
281
+ }
282
+ }
283
+ },
284
+ "total_results": {"type": "integer"}
285
+ }
286
+ }
287
+ }
288
+ skills.append(memory_skill)
289
+
290
+ return skills
291
+
292
+ def _get_max_context_length(self, vac_names: List[str]) -> int:
293
+ """
294
+ Determine the maximum context length based on configured models.
295
+
296
+ Args:
297
+ vac_names: List of VAC names to check
298
+
299
+ Returns:
300
+ Maximum context length in tokens
301
+ """
302
+ max_length = 8192 # Default
303
+
304
+ for vac_name in vac_names:
305
+ try:
306
+ vac_config = ConfigManager(vac_name, validate=False)
307
+ model = vac_config.vacConfig('model')
308
+
309
+ # Map known models to context lengths
310
+ if model:
311
+ if 'gemini-1.5' in model:
312
+ max_length = max(max_length, 2000000) # Gemini 1.5 Pro
313
+ elif 'gpt-4' in model:
314
+ max_length = max(max_length, 128000) # GPT-4 Turbo
315
+ elif 'claude-3' in model:
316
+ max_length = max(max_length, 200000) # Claude 3
317
+ elif 'gemini' in model:
318
+ max_length = max(max_length, 32768) # Other Gemini models
319
+
320
+ except Exception as e:
321
+ log.debug(f"Could not determine context length for {vac_name}: {e}")
322
+ continue
323
+
324
+ return max_length
325
+
326
+ def _get_current_timestamp(self) -> str:
327
+ """Get current timestamp in ISO format."""
328
+ from datetime import datetime
329
+ return datetime.now().isoformat()
330
+
331
+ def generate_discovery_endpoints(self) -> Dict[str, str]:
332
+ """
333
+ Generate the A2A discovery endpoint paths.
334
+
335
+ Returns:
336
+ Dictionary mapping endpoint names to their paths
337
+ """
338
+ return {
339
+ "agent_card": "/.well-known/agent.json",
340
+ "task_send": "/a2a/tasks/send",
341
+ "task_send_subscribe": "/a2a/tasks/sendSubscribe",
342
+ "task_get": "/a2a/tasks/get",
343
+ "task_cancel": "/a2a/tasks/cancel",
344
+ "task_notification": "/a2a/tasks/pushNotification/set"
345
+ }