sunholo 0.144.2__tar.gz → 0.144.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 (203) hide show
  1. {sunholo-0.144.2/src/sunholo.egg-info → sunholo-0.144.3}/PKG-INFO +1 -1
  2. {sunholo-0.144.2 → sunholo-0.144.3}/pyproject.toml +1 -1
  3. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/fastapi/vac_routes.py +229 -13
  4. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/vac_mcp_server_fastmcp.py +1 -1
  5. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/vac_tools.py +5 -4
  6. {sunholo-0.144.2 → sunholo-0.144.3/src/sunholo.egg-info}/PKG-INFO +1 -1
  7. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_vac_routes_mcp.py +24 -3
  8. {sunholo-0.144.2 → sunholo-0.144.3}/LICENSE.txt +0 -0
  9. {sunholo-0.144.2 → sunholo-0.144.3}/MANIFEST.in +0 -0
  10. {sunholo-0.144.2 → sunholo-0.144.3}/README.md +0 -0
  11. {sunholo-0.144.2 → sunholo-0.144.3}/setup.cfg +0 -0
  12. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/__init__.py +0 -0
  13. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/a2a/__init__.py +0 -0
  14. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/a2a/agent_card.py +0 -0
  15. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/a2a/task_manager.py +0 -0
  16. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/a2a/vac_a2a_agent.py +0 -0
  17. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/__init__.py +0 -0
  18. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/chat_history.py +0 -0
  19. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/dispatch_to_qa.py +0 -0
  20. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/fastapi/__init__.py +0 -0
  21. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/fastapi/base.py +0 -0
  22. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
  23. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/flask/__init__.py +0 -0
  24. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/flask/base.py +0 -0
  25. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/flask/vac_routes.py +0 -0
  26. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/langserve.py +0 -0
  27. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/pubsub.py +0 -0
  28. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/route.py +0 -0
  29. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/special_commands.py +0 -0
  30. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/agents/swagger.py +0 -0
  31. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/archive/__init__.py +0 -0
  32. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/archive/archive.py +0 -0
  33. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/auth/__init__.py +0 -0
  34. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/auth/gcloud.py +0 -0
  35. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/auth/refresh.py +0 -0
  36. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/auth/run.py +0 -0
  37. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/azure/__init__.py +0 -0
  38. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/azure/auth.py +0 -0
  39. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/azure/blobs.py +0 -0
  40. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/azure/event_grid.py +0 -0
  41. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/bots/__init__.py +0 -0
  42. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/bots/discord.py +0 -0
  43. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/bots/github_webhook.py +0 -0
  44. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/bots/webapp.py +0 -0
  45. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/__init__.py +0 -0
  46. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/azure.py +0 -0
  47. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/doc_handling.py +0 -0
  48. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/encode_metadata.py +0 -0
  49. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/images.py +0 -0
  50. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/loaders.py +0 -0
  51. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/message_data.py +0 -0
  52. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/pdfs.py +0 -0
  53. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/process_chunker_data.py +0 -0
  54. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/publish.py +0 -0
  55. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/pubsub.py +0 -0
  56. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/chunker/splitter.py +0 -0
  57. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/__init__.py +0 -0
  58. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/chat_vac.py +0 -0
  59. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/cli.py +0 -0
  60. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/cli_init.py +0 -0
  61. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/configs.py +0 -0
  62. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/deploy.py +0 -0
  63. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/embedder.py +0 -0
  64. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/merge_texts.py +0 -0
  65. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/run_proxy.py +0 -0
  66. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/sun_rich.py +0 -0
  67. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/swagger.py +0 -0
  68. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/cli/vertex.py +0 -0
  69. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/components/__init__.py +0 -0
  70. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/components/llm.py +0 -0
  71. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/components/retriever.py +0 -0
  72. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/components/vectorstore.py +0 -0
  73. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/custom_logging.py +0 -0
  74. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/__init__.py +0 -0
  75. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/alloydb.py +0 -0
  76. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/alloydb_client.py +0 -0
  77. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/database.py +0 -0
  78. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/lancedb.py +0 -0
  79. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/sql/sb/create_function.sql +0 -0
  80. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
  81. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/sql/sb/create_table.sql +0 -0
  82. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  83. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
  84. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/sql/sb/setup.sql +0 -0
  85. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/static_dbs.py +0 -0
  86. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/database/uuid.py +0 -0
  87. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/discovery_engine/__init__.py +0 -0
  88. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
  89. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/discovery_engine/cli.py +0 -0
  90. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/discovery_engine/create_new.py +0 -0
  91. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  92. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  93. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/embedder/__init__.py +0 -0
  94. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/embedder/embed_chunk.py +0 -0
  95. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/embedder/embed_metadata.py +0 -0
  96. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/excel/__init__.py +0 -0
  97. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/excel/plugin.py +0 -0
  98. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/gcs/__init__.py +0 -0
  99. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/gcs/add_file.py +0 -0
  100. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/gcs/download_folder.py +0 -0
  101. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/gcs/download_gcs_text.py +0 -0
  102. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/gcs/download_url.py +0 -0
  103. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/gcs/extract_and_sign.py +0 -0
  104. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/gcs/metadata.py +0 -0
  105. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/genai/__init__.py +0 -0
  106. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/genai/file_handling.py +0 -0
  107. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/genai/genaiv2.py +0 -0
  108. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/genai/images.py +0 -0
  109. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/genai/init.py +0 -0
  110. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/genai/process_funcs_cls.py +0 -0
  111. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/genai/safety.py +0 -0
  112. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/invoke/__init__.py +0 -0
  113. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/invoke/async_class.py +0 -0
  114. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/invoke/direct_vac_func.py +0 -0
  115. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
  116. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/langchain_types.py +0 -0
  117. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/langfuse/__init__.py +0 -0
  118. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/langfuse/callback.py +0 -0
  119. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/langfuse/evals.py +0 -0
  120. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/langfuse/prompts.py +0 -0
  121. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/llamaindex/__init__.py +0 -0
  122. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/llamaindex/get_files.py +0 -0
  123. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/llamaindex/import_files.py +0 -0
  124. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
  125. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/llamaindex/user_history.py +0 -0
  126. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/lookup/__init__.py +0 -0
  127. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/lookup/model_lookup.yaml +0 -0
  128. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/__init__.py +0 -0
  129. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/cli.py +0 -0
  130. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/cli_fastmcp.py +0 -0
  131. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/extensible_mcp_server.py +0 -0
  132. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/mcp_manager.py +0 -0
  133. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/stdio_http_bridge.py +0 -0
  134. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/mcp/vac_mcp_server.py +0 -0
  135. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/ollama/__init__.py +0 -0
  136. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/ollama/ollama_images.py +0 -0
  137. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/pubsub/__init__.py +0 -0
  138. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/pubsub/process_pubsub.py +0 -0
  139. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/pubsub/pubsub_manager.py +0 -0
  140. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/qna/__init__.py +0 -0
  141. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/qna/parsers.py +0 -0
  142. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/qna/retry.py +0 -0
  143. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/senses/__init__.py +0 -0
  144. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/senses/stream_voice.py +0 -0
  145. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/streaming/__init__.py +0 -0
  146. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/streaming/content_buffer.py +0 -0
  147. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/streaming/langserve.py +0 -0
  148. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/streaming/stream_lookup.py +0 -0
  149. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/streaming/streaming.py +0 -0
  150. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/summarise/__init__.py +0 -0
  151. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/summarise/summarise.py +0 -0
  152. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/agent/__init__.py +0 -0
  153. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/agent/agent_service.py +0 -0
  154. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/agent/app.py +0 -0
  155. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/agent/my_log.py +0 -0
  156. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/agent/tools/__init__.py +0 -0
  157. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
  158. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/agent/vac_service.py +0 -0
  159. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/project/__init__.py +0 -0
  160. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/project/app.py +0 -0
  161. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/project/my_log.py +0 -0
  162. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/project/vac_service.py +0 -0
  163. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/system_services/__init__.py +0 -0
  164. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/system_services/app.py +0 -0
  165. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/templates/system_services/my_log.py +0 -0
  166. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/terraform/__init__.py +0 -0
  167. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/terraform/tfvars_editor.py +0 -0
  168. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/tools/__init__.py +0 -0
  169. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/tools/web_browser.py +0 -0
  170. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/__init__.py +0 -0
  171. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/api_key.py +0 -0
  172. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/big_context.py +0 -0
  173. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/config.py +0 -0
  174. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/config_class.py +0 -0
  175. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/config_schema.py +0 -0
  176. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/gcp.py +0 -0
  177. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/gcp_project.py +0 -0
  178. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/mime.py +0 -0
  179. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/parsers.py +0 -0
  180. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/proto_convert.py +0 -0
  181. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/timedelta.py +0 -0
  182. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/user_ids.py +0 -0
  183. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/utils/version.py +0 -0
  184. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/__init__.py +0 -0
  185. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/extensions_call.py +0 -0
  186. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/extensions_class.py +0 -0
  187. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/genai_functions.py +0 -0
  188. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/init.py +0 -0
  189. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/memory_tools.py +0 -0
  190. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/safety.py +0 -0
  191. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo/vertex/type_dict_to_json.py +0 -0
  192. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo.egg-info/SOURCES.txt +0 -0
  193. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo.egg-info/dependency_links.txt +0 -0
  194. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo.egg-info/entry_points.txt +0 -0
  195. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo.egg-info/requires.txt +0 -0
  196. {sunholo-0.144.2 → sunholo-0.144.3}/src/sunholo.egg-info/top_level.txt +0 -0
  197. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_async.py +0 -0
  198. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_async_genai2.py +0 -0
  199. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_chat_history.py +0 -0
  200. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_config.py +0 -0
  201. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_genai2.py +0 -0
  202. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_unstructured.py +0 -0
  203. {sunholo-0.144.2 → sunholo-0.144.3}/tests/test_vac_routes_fastapi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.144.2
3
+ Version: 0.144.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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sunholo"
7
- version = "0.144.2"
7
+ version = "0.144.3"
8
8
  description = "AI DevOps - a package to help deploy GenAI to the Cloud."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -113,31 +113,92 @@ class VACRoutesFastAPI:
113
113
 
114
114
  ## Basic Usage
115
115
 
116
+ ### Simplified Setup (Recommended)
117
+
118
+ Use the helper method for automatic lifespan management:
119
+
116
120
  ```python
117
- from fastapi import FastAPI
118
121
  from sunholo.agents.fastapi import VACRoutesFastAPI
119
122
 
120
- app = FastAPI()
121
-
122
123
  async def my_stream_interpreter(question, vector_name, chat_history, callback, **kwargs):
123
124
  # Your streaming VAC logic here
124
125
  # Use callback.async_on_llm_new_token(token) for streaming
125
- # Return final result with sources
126
126
  return {"answer": "Response", "sources": []}
127
127
 
128
- # Create VAC routes with MCP server enabled
128
+ # Single call sets up everything with MCP server and proper lifespan management
129
+ app, vac_routes = VACRoutesFastAPI.create_app_with_mcp(
130
+ title="My VAC Application",
131
+ stream_interpreter=my_stream_interpreter
132
+ # MCP server is automatically enabled when using this method
133
+ )
134
+
135
+ # Add custom endpoints if needed
136
+ @app.get("/custom")
137
+ async def custom_endpoint():
138
+ return {"message": "Hello"}
139
+
140
+ # Run the app
141
+ if __name__ == "__main__":
142
+ import uvicorn
143
+ uvicorn.run(app, host="0.0.0.0", port=8000)
144
+ ```
145
+
146
+ ### Manual Setup (Advanced)
147
+
148
+ For more control over lifespan management:
149
+
150
+ ```python
151
+ from contextlib import asynccontextmanager
152
+ from fastapi import FastAPI
153
+ from sunholo.agents.fastapi import VACRoutesFastAPI
154
+
155
+ async def my_stream_interpreter(question, vector_name, chat_history, callback, **kwargs):
156
+ return {"answer": "Response", "sources": []}
157
+
158
+ # Define your app's lifespan
159
+ @asynccontextmanager
160
+ async def app_lifespan(app: FastAPI):
161
+ print("Starting up...")
162
+ yield
163
+ print("Shutting down...")
164
+
165
+ # Create temp app to get MCP lifespan
166
+ temp_app = FastAPI()
167
+ vac_routes_temp = VACRoutesFastAPI(
168
+ temp_app,
169
+ stream_interpreter=my_stream_interpreter,
170
+ enable_mcp_server=True
171
+ )
172
+
173
+ # Get MCP lifespan
174
+ mcp_lifespan = vac_routes_temp.get_mcp_lifespan()
175
+
176
+ # Combine lifespans
177
+ @asynccontextmanager
178
+ async def combined_lifespan(app: FastAPI):
179
+ async with app_lifespan(app):
180
+ if mcp_lifespan:
181
+ async with mcp_lifespan(app):
182
+ yield
183
+ else:
184
+ yield
185
+
186
+ # Create app with combined lifespan
187
+ app = FastAPI(title="My VAC Application", lifespan=combined_lifespan)
188
+
189
+ # Initialize VAC routes
129
190
  vac_routes = VACRoutesFastAPI(
130
191
  app=app,
131
192
  stream_interpreter=my_stream_interpreter,
132
- enable_mcp_server=True # Enable MCP server for Claude Desktop/Code
193
+ enable_mcp_server=True
133
194
  )
134
-
135
- # Your FastAPI app now includes:
136
- # - All VAC endpoints
137
- # - MCP server at /mcp (for Claude Desktop/Code to connect)
138
- # - Built-in VAC tools: vac_stream, vac_query, list_available_vacs, get_vac_info
139
195
  ```
140
196
 
197
+ Your FastAPI app now includes:
198
+ - All VAC endpoints
199
+ - MCP server at /mcp (for Claude Desktop/Code to connect)
200
+ - Built-in VAC tools: vac_stream, vac_query, list_available_vacs, get_vac_info
201
+
141
202
  ## Adding Custom MCP Tools
142
203
 
143
204
  ### Method 1: Using Decorators
@@ -416,6 +477,138 @@ class VACRoutesFastAPI:
416
477
 
417
478
  self.register_routes()
418
479
 
480
+ @staticmethod
481
+ def create_app_with_mcp(
482
+ title: str = "VAC Application",
483
+ stream_interpreter: Optional[callable] = None,
484
+ vac_interpreter: Optional[callable] = None,
485
+ app_lifespan: Optional[callable] = None,
486
+ **kwargs
487
+ ) -> tuple[FastAPI, 'VACRoutesFastAPI']:
488
+ """
489
+ Helper method to create a FastAPI app with proper MCP lifespan management.
490
+
491
+ This method simplifies the setup process by handling the lifespan combination
492
+ automatically, avoiding the need for the double initialization pattern.
493
+ MCP server is automatically enabled when using this method.
494
+
495
+ Args:
496
+ title: Title for the FastAPI app
497
+ stream_interpreter: Streaming interpreter function
498
+ vac_interpreter: Non-streaming interpreter function
499
+ app_lifespan: Optional app lifespan context manager
500
+ **kwargs: Additional arguments passed to VACRoutesFastAPI (except enable_mcp_server)
501
+
502
+ Returns:
503
+ Tuple of (FastAPI app, VACRoutesFastAPI instance)
504
+
505
+ Example:
506
+ ```python
507
+ from sunholo.agents.fastapi import VACRoutesFastAPI
508
+
509
+ async def my_interpreter(question, vector_name, chat_history, callback, **kwargs):
510
+ # Your logic here
511
+ return {"answer": "response", "sources": []}
512
+
513
+ # Single call to set up everything (MCP is automatically enabled)
514
+ app, vac_routes = VACRoutesFastAPI.create_app_with_mcp(
515
+ title="My VAC App",
516
+ stream_interpreter=my_interpreter
517
+ )
518
+
519
+ # Add custom endpoints
520
+ @app.get("/custom")
521
+ async def custom_endpoint():
522
+ return {"message": "Custom endpoint"}
523
+
524
+ if __name__ == "__main__":
525
+ import uvicorn
526
+ uvicorn.run(app, host="0.0.0.0", port=8000)
527
+ ```
528
+ """
529
+ from contextlib import asynccontextmanager
530
+
531
+ # Default app lifespan if not provided
532
+ if app_lifespan is None:
533
+ @asynccontextmanager
534
+ async def app_lifespan(app: FastAPI):
535
+ yield
536
+
537
+ # Create temporary app to get MCP app (always enabled for this method)
538
+ temp_app = FastAPI()
539
+ temp_routes = VACRoutesFastAPI(
540
+ temp_app,
541
+ stream_interpreter=stream_interpreter,
542
+ vac_interpreter=vac_interpreter,
543
+ enable_mcp_server=True, # Always enabled for create_app_with_mcp
544
+ **kwargs
545
+ )
546
+
547
+ mcp_app = None
548
+ if temp_routes.vac_mcp_server:
549
+ mcp_app = temp_routes.vac_mcp_server.get_http_app()
550
+
551
+ # Create combined lifespan
552
+ @asynccontextmanager
553
+ async def combined_lifespan(app: FastAPI):
554
+ async with app_lifespan(app):
555
+ if mcp_app:
556
+ async with mcp_app.lifespan(app):
557
+ yield
558
+ else:
559
+ yield
560
+
561
+ # Create the actual app with combined lifespan
562
+ app = FastAPI(
563
+ title=title,
564
+ lifespan=combined_lifespan if mcp_app else app_lifespan
565
+ )
566
+
567
+ # Initialize VAC routes (MCP always enabled for this method)
568
+ vac_routes = VACRoutesFastAPI(
569
+ app,
570
+ stream_interpreter=stream_interpreter,
571
+ vac_interpreter=vac_interpreter,
572
+ enable_mcp_server=True, # Always enabled for create_app_with_mcp
573
+ **kwargs
574
+ )
575
+
576
+ return app, vac_routes
577
+
578
+ def get_mcp_lifespan(self):
579
+ """
580
+ Get the MCP app's lifespan for manual lifespan management.
581
+
582
+ Returns:
583
+ The MCP app's lifespan if MCP server is enabled, None otherwise.
584
+
585
+ Example:
586
+ ```python
587
+ from contextlib import asynccontextmanager
588
+
589
+ # Create temp app to get MCP lifespan
590
+ temp_app = FastAPI()
591
+ vac_routes = VACRoutesFastAPI(temp_app, ..., enable_mcp_server=True)
592
+ mcp_lifespan = vac_routes.get_mcp_lifespan()
593
+
594
+ # Combine with your app's lifespan
595
+ @asynccontextmanager
596
+ async def combined_lifespan(app: FastAPI):
597
+ async with my_app_lifespan(app):
598
+ if mcp_lifespan:
599
+ async with mcp_lifespan(app):
600
+ yield
601
+ else:
602
+ yield
603
+
604
+ app = FastAPI(lifespan=combined_lifespan)
605
+ ```
606
+ """
607
+ if self.vac_mcp_server:
608
+ mcp_app = self.vac_mcp_server.get_http_app()
609
+ return mcp_app.lifespan
610
+ return None
611
+
419
612
  async def vac_interpreter_default(self, question: str, vector_name: str, chat_history=None, **kwargs):
420
613
  """Default VAC interpreter that uses the stream interpreter without streaming."""
421
614
  class NoOpCallback:
@@ -484,11 +677,34 @@ class VACRoutesFastAPI:
484
677
  if self.enable_mcp_server and self.vac_mcp_server:
485
678
  try:
486
679
  mcp_app = self.vac_mcp_server.get_http_app()
680
+
681
+ # Note: FastAPI doesn't expose lifespan as a public attribute,
682
+ # so we can't easily check if it's configured. The error will be
683
+ # caught below if lifespan is missing.
684
+
487
685
  self.app.mount("/mcp", mcp_app)
488
- log.info("MCP server mounted at /mcp endpoint")
686
+ log.info("MCP server mounted at /mcp endpoint")
687
+
688
+ except RuntimeError as e:
689
+ if "Task group is not initialized" in str(e):
690
+ error_msg = (
691
+ "MCP server initialization failed: Lifespan not configured properly.\n"
692
+ "The FastAPI app must be created with the MCP lifespan.\n\n"
693
+ "Quick fix: Use the helper method:\n"
694
+ " app, vac_routes = VACRoutesFastAPI.create_app_with_mcp(\n"
695
+ " stream_interpreter=your_interpreter,\n"
696
+ " enable_mcp_server=True\n"
697
+ " )\n\n"
698
+ "Or manually configure the lifespan - see documentation for details."
699
+ )
700
+ log.error(error_msg)
701
+ raise RuntimeError(error_msg) from e
702
+ else:
703
+ log.error(f"Failed to mount MCP server: {e}")
704
+ raise RuntimeError(f"MCP server initialization failed: {e}") from e
489
705
  except Exception as e:
490
706
  log.error(f"Failed to mount MCP server: {e}")
491
- raise RuntimeError(f"MCP server initialization failed: {e}")
707
+ raise RuntimeError(f"MCP server initialization failed: {e}") from e
492
708
 
493
709
  # A2A agent endpoints
494
710
  if self.enable_a2a_agent:
@@ -73,7 +73,7 @@ class VACMCPServer:
73
73
 
74
74
  def get_http_app(self):
75
75
  """Get the HTTP app for mounting in FastAPI."""
76
- return self.server.get_app()
76
+ return self.server.http_app()
77
77
 
78
78
  def add_tool(self, func: Callable, name: str = None, description: str = None):
79
79
  """
@@ -241,9 +241,10 @@ def register_vac_tools(server: 'FastMCP', registry: 'MCPToolRegistry' = None):
241
241
 
242
242
  # Register tools in registry if provided
243
243
  if registry:
244
- registry.register_tool("vac_stream", vac_stream)
245
- registry.register_tool("vac_query", vac_query)
246
- registry.register_tool("list_available_vacs", list_available_vacs)
247
- registry.register_tool("get_vac_info", get_vac_info)
244
+ # Extract the underlying function from FunctionTool objects
245
+ registry.register_tool("vac_stream", vac_stream.fn if hasattr(vac_stream, 'fn') else vac_stream)
246
+ registry.register_tool("vac_query", vac_query.fn if hasattr(vac_query, 'fn') else vac_query)
247
+ registry.register_tool("list_available_vacs", list_available_vacs.fn if hasattr(list_available_vacs, 'fn') else list_available_vacs)
248
+ registry.register_tool("get_vac_info", get_vac_info.fn if hasattr(get_vac_info, 'fn') else get_vac_info)
248
249
 
249
250
  log.info("Registered built-in VAC tools with MCP server")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.144.2
3
+ Version: 0.144.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
@@ -200,19 +200,40 @@ class MockMCPClientManager:
200
200
  @pytest.fixture
201
201
  def mcp_server_app():
202
202
  """Create a FastAPI app with MCP server enabled."""
203
- app = FastAPI()
203
+ from contextlib import asynccontextmanager
204
+
205
+ # Create a simple lifespan for the test
206
+ @asynccontextmanager
207
+ async def test_lifespan(app: FastAPI):
208
+ yield
209
+
210
+ app = FastAPI(lifespan=test_lifespan)
211
+
212
+ # First disable MCP server to avoid initialization issues
204
213
  vac_routes = VACRoutesFastAPI(
205
214
  app,
206
215
  stream_interpreter=mock_async_stream_interpreter,
207
216
  vac_interpreter=mock_async_vac_interpreter,
208
- enable_mcp_server=True,
217
+ enable_mcp_server=False, # Disable initially
209
218
  add_langfuse_eval=False
210
219
  )
211
- # Replace with mock MCP server
220
+
221
+ # Add a mock MCP endpoint manually for testing
222
+ @app.post("/mcp")
223
+ async def mock_mcp_endpoint(request: dict):
224
+ """Mock MCP endpoint for testing."""
225
+ mock_server = MockVACMCPServer(
226
+ mock_async_stream_interpreter,
227
+ mock_async_vac_interpreter
228
+ )
229
+ return await mock_server.handle_request(request)
230
+
231
+ # Set the mock server for other tests that might need it
212
232
  vac_routes.vac_mcp_server = MockVACMCPServer(
213
233
  mock_async_stream_interpreter,
214
234
  mock_async_vac_interpreter
215
235
  )
236
+
216
237
  return app
217
238
 
218
239
 
File without changes
File without changes
File without changes
File without changes
File without changes