sunholo 0.143.1__tar.gz → 0.143.7__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 (196) hide show
  1. {sunholo-0.143.1/src/sunholo.egg-info → sunholo-0.143.7}/PKG-INFO +4 -2
  2. {sunholo-0.143.1 → sunholo-0.143.7}/pyproject.toml +4 -2
  3. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/__init__.py +4 -1
  4. sunholo-0.143.7/src/sunholo/a2a/__init__.py +27 -0
  5. sunholo-0.143.7/src/sunholo/a2a/agent_card.py +345 -0
  6. sunholo-0.143.7/src/sunholo/a2a/task_manager.py +480 -0
  7. sunholo-0.143.7/src/sunholo/a2a/vac_a2a_agent.py +383 -0
  8. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/flask/vac_routes.py +256 -19
  9. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/mcp/__init__.py +11 -2
  10. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/mcp/mcp_manager.py +66 -28
  11. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/mcp/vac_mcp_server.py +3 -9
  12. {sunholo-0.143.1 → sunholo-0.143.7/src/sunholo.egg-info}/PKG-INFO +4 -2
  13. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo.egg-info/SOURCES.txt +5 -2
  14. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo.egg-info/requires.txt +2 -0
  15. sunholo-0.143.1/tests/test_vac_routes_mcp.py +0 -339
  16. {sunholo-0.143.1 → sunholo-0.143.7}/LICENSE.txt +0 -0
  17. {sunholo-0.143.1 → sunholo-0.143.7}/MANIFEST.in +0 -0
  18. {sunholo-0.143.1 → sunholo-0.143.7}/README.md +0 -0
  19. {sunholo-0.143.1 → sunholo-0.143.7}/setup.cfg +0 -0
  20. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/__init__.py +0 -0
  21. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/chat_history.py +0 -0
  22. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/dispatch_to_qa.py +0 -0
  23. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/fastapi/__init__.py +0 -0
  24. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/fastapi/base.py +0 -0
  25. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
  26. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/flask/__init__.py +0 -0
  27. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/flask/base.py +0 -0
  28. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/langserve.py +0 -0
  29. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/pubsub.py +0 -0
  30. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/route.py +0 -0
  31. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/special_commands.py +0 -0
  32. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/agents/swagger.py +0 -0
  33. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/archive/__init__.py +0 -0
  34. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/archive/archive.py +0 -0
  35. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/auth/__init__.py +0 -0
  36. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/auth/gcloud.py +0 -0
  37. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/auth/refresh.py +0 -0
  38. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/auth/run.py +0 -0
  39. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/azure/__init__.py +0 -0
  40. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/azure/auth.py +0 -0
  41. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/azure/blobs.py +0 -0
  42. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/azure/event_grid.py +0 -0
  43. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/bots/__init__.py +0 -0
  44. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/bots/discord.py +0 -0
  45. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/bots/github_webhook.py +0 -0
  46. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/bots/webapp.py +0 -0
  47. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/__init__.py +0 -0
  48. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/azure.py +0 -0
  49. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/doc_handling.py +0 -0
  50. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/encode_metadata.py +0 -0
  51. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/images.py +0 -0
  52. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/loaders.py +0 -0
  53. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/message_data.py +0 -0
  54. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/pdfs.py +0 -0
  55. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/process_chunker_data.py +0 -0
  56. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/publish.py +0 -0
  57. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/pubsub.py +0 -0
  58. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/chunker/splitter.py +0 -0
  59. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/__init__.py +0 -0
  60. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/chat_vac.py +0 -0
  61. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/cli.py +0 -0
  62. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/cli_init.py +0 -0
  63. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/configs.py +0 -0
  64. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/deploy.py +0 -0
  65. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/embedder.py +0 -0
  66. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/merge_texts.py +0 -0
  67. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/run_proxy.py +0 -0
  68. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/sun_rich.py +0 -0
  69. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/swagger.py +0 -0
  70. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/cli/vertex.py +0 -0
  71. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/components/__init__.py +0 -0
  72. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/components/llm.py +0 -0
  73. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/components/retriever.py +0 -0
  74. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/components/vectorstore.py +0 -0
  75. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/custom_logging.py +0 -0
  76. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/__init__.py +0 -0
  77. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/alloydb.py +0 -0
  78. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/alloydb_client.py +0 -0
  79. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/database.py +0 -0
  80. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/lancedb.py +0 -0
  81. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/sql/sb/create_function.sql +0 -0
  82. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
  83. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/sql/sb/create_table.sql +0 -0
  84. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  85. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
  86. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/sql/sb/setup.sql +0 -0
  87. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/static_dbs.py +0 -0
  88. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/database/uuid.py +0 -0
  89. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/discovery_engine/__init__.py +0 -0
  90. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
  91. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/discovery_engine/cli.py +0 -0
  92. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/discovery_engine/create_new.py +0 -0
  93. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  94. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  95. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/embedder/__init__.py +0 -0
  96. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/embedder/embed_chunk.py +0 -0
  97. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/embedder/embed_metadata.py +0 -0
  98. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/excel/__init__.py +0 -0
  99. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/excel/plugin.py +0 -0
  100. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/gcs/__init__.py +0 -0
  101. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/gcs/add_file.py +0 -0
  102. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/gcs/download_folder.py +0 -0
  103. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/gcs/download_gcs_text.py +0 -0
  104. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/gcs/download_url.py +0 -0
  105. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/gcs/extract_and_sign.py +0 -0
  106. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/gcs/metadata.py +0 -0
  107. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/genai/__init__.py +0 -0
  108. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/genai/file_handling.py +0 -0
  109. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/genai/genaiv2.py +0 -0
  110. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/genai/images.py +0 -0
  111. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/genai/init.py +0 -0
  112. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/genai/process_funcs_cls.py +0 -0
  113. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/genai/safety.py +0 -0
  114. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/invoke/__init__.py +0 -0
  115. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/invoke/async_class.py +0 -0
  116. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/invoke/direct_vac_func.py +0 -0
  117. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
  118. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/langchain_types.py +0 -0
  119. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/langfuse/__init__.py +0 -0
  120. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/langfuse/callback.py +0 -0
  121. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/langfuse/evals.py +0 -0
  122. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/langfuse/prompts.py +0 -0
  123. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/llamaindex/__init__.py +0 -0
  124. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/llamaindex/get_files.py +0 -0
  125. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/llamaindex/import_files.py +0 -0
  126. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
  127. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/llamaindex/user_history.py +0 -0
  128. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/lookup/__init__.py +0 -0
  129. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/lookup/model_lookup.yaml +0 -0
  130. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/mcp/cli.py +0 -0
  131. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/ollama/__init__.py +0 -0
  132. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/ollama/ollama_images.py +0 -0
  133. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/pubsub/__init__.py +0 -0
  134. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/pubsub/process_pubsub.py +0 -0
  135. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/pubsub/pubsub_manager.py +0 -0
  136. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/qna/__init__.py +0 -0
  137. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/qna/parsers.py +0 -0
  138. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/qna/retry.py +0 -0
  139. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/senses/__init__.py +0 -0
  140. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/senses/stream_voice.py +0 -0
  141. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/streaming/__init__.py +0 -0
  142. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/streaming/content_buffer.py +0 -0
  143. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/streaming/langserve.py +0 -0
  144. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/streaming/stream_lookup.py +0 -0
  145. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/streaming/streaming.py +0 -0
  146. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/summarise/__init__.py +0 -0
  147. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/summarise/summarise.py +0 -0
  148. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/agent/__init__.py +0 -0
  149. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/agent/agent_service.py +0 -0
  150. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/agent/app.py +0 -0
  151. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/agent/my_log.py +0 -0
  152. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/agent/tools/__init__.py +0 -0
  153. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
  154. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/agent/vac_service.py +0 -0
  155. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/project/__init__.py +0 -0
  156. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/project/app.py +0 -0
  157. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/project/my_log.py +0 -0
  158. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/project/vac_service.py +0 -0
  159. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/system_services/__init__.py +0 -0
  160. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/system_services/app.py +0 -0
  161. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/templates/system_services/my_log.py +0 -0
  162. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/terraform/__init__.py +0 -0
  163. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/terraform/tfvars_editor.py +0 -0
  164. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/tools/__init__.py +0 -0
  165. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/tools/web_browser.py +0 -0
  166. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/__init__.py +0 -0
  167. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/api_key.py +0 -0
  168. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/big_context.py +0 -0
  169. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/config.py +0 -0
  170. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/config_class.py +0 -0
  171. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/config_schema.py +0 -0
  172. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/gcp.py +0 -0
  173. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/gcp_project.py +0 -0
  174. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/mime.py +0 -0
  175. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/parsers.py +0 -0
  176. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/proto_convert.py +0 -0
  177. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/timedelta.py +0 -0
  178. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/user_ids.py +0 -0
  179. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/utils/version.py +0 -0
  180. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/__init__.py +0 -0
  181. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/extensions_call.py +0 -0
  182. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/extensions_class.py +0 -0
  183. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/genai_functions.py +0 -0
  184. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/init.py +0 -0
  185. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/memory_tools.py +0 -0
  186. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/safety.py +0 -0
  187. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo/vertex/type_dict_to_json.py +0 -0
  188. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo.egg-info/dependency_links.txt +0 -0
  189. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo.egg-info/entry_points.txt +0 -0
  190. {sunholo-0.143.1 → sunholo-0.143.7}/src/sunholo.egg-info/top_level.txt +0 -0
  191. {sunholo-0.143.1 → sunholo-0.143.7}/tests/test_async.py +0 -0
  192. {sunholo-0.143.1 → sunholo-0.143.7}/tests/test_async_genai2.py +0 -0
  193. {sunholo-0.143.1 → sunholo-0.143.7}/tests/test_chat_history.py +0 -0
  194. {sunholo-0.143.1 → sunholo-0.143.7}/tests/test_config.py +0 -0
  195. {sunholo-0.143.1 → sunholo-0.143.7}/tests/test_genai2.py +0 -0
  196. {sunholo-0.143.1 → sunholo-0.143.7}/tests/test_unstructured.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.143.1
3
+ Version: 0.143.7
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,9 +15,10 @@ 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
22
23
  Requires-Dist: flask>=3.1.0
23
24
  Requires-Dist: google-auth
@@ -126,6 +127,7 @@ Requires-Dist: pytesseract; extra == "pipeline"
126
127
  Requires-Dist: tabulate; extra == "pipeline"
127
128
  Requires-Dist: unstructured[all-docs,local-inference]; extra == "pipeline"
128
129
  Provides-Extra: gcp
130
+ Requires-Dist: a2a-python; extra == "gcp"
129
131
  Requires-Dist: aiofiles; extra == "gcp"
130
132
  Requires-Dist: anthropic[vertex]; extra == "gcp"
131
133
  Requires-Dist: google-api-python-client; extra == "gcp"
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sunholo"
7
- version = "0.143.1"
7
+ version = "0.143.7"
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,6 +25,7 @@ classifiers = [
25
25
  ]
26
26
 
27
27
  dependencies = [
28
+ "a2a-python>=0.0.1",
28
29
  "aiohttp",
29
30
  "flask>=3.1.0",
30
31
  "google-auth",
@@ -163,6 +164,7 @@ pipeline = [
163
164
  "unstructured[local-inference,all-docs]"
164
165
  ]
165
166
  gcp = [
167
+ "a2a-python",
166
168
  "aiofiles",
167
169
  "anthropic[vertex]",
168
170
  "google-api-python-client",
@@ -15,7 +15,10 @@ from . import invoke
15
15
  from . import langfuse
16
16
  from . import llamaindex
17
17
  from . import lookup
18
- from . import mcp
18
+ try:
19
+ from . import mcp
20
+ except ImportError:
21
+ mcp = None
19
22
  from . import ollama
20
23
  from . import pubsub
21
24
  from . import qna
@@ -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
+ }