holmesgpt 0.12.0__tar.gz → 0.12.1__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.

Potentially problematic release.


This version of holmesgpt might be problematic. Click here for more details.

Files changed (194) hide show
  1. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/PKG-INFO +3 -2
  2. holmesgpt-0.12.1/holmes/__init__.py +8 -0
  3. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/clients/robusta_client.py +1 -1
  4. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/common/env_vars.py +1 -0
  5. holmesgpt-0.12.1/holmes/common/openshift.py +15 -0
  6. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/config.py +2 -28
  7. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/llm.py +5 -8
  8. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/supabase_dal.py +4 -0
  9. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/tool_calling_llm.py +12 -3
  10. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/tools.py +2 -1
  11. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/toolset_manager.py +1 -1
  12. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/tracing.py +5 -4
  13. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/interactive.py +46 -16
  14. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/main.py +6 -2
  15. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/prometheus/prometheus.py +21 -2
  16. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/console/logging.py +3 -0
  17. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/robusta.py +2 -3
  18. holmesgpt-0.12.1/holmes/version.py +178 -0
  19. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/pyproject.toml +18 -3
  20. holmesgpt-0.12.0/holmes/__init__.py +0 -76
  21. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/LICENSE.txt +0 -0
  22. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/README.md +0 -0
  23. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/.git_archival.json +0 -0
  24. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/__init__.py +0 -0
  25. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/conversations.py +0 -0
  26. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/investigation.py +0 -0
  27. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/investigation_structured_output.py +0 -0
  28. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/issue.py +0 -0
  29. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/models.py +0 -0
  30. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/openai_formatting.py +0 -0
  31. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/performance_timing.py +0 -0
  32. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/prompt.py +0 -0
  33. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/resource_instruction.py +0 -0
  34. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/runbooks.py +0 -0
  35. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/safeguards.py +0 -0
  36. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/tools_utils/__init__.py +0 -0
  37. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/tools_utils/tool_executor.py +0 -0
  38. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/core/tools_utils/toolset_utils.py +0 -0
  39. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/__init__.py +0 -0
  40. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/destinations/__init__.py +0 -0
  41. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/destinations/slack/__init__.py +0 -0
  42. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/destinations/slack/plugin.py +0 -0
  43. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/interfaces.py +0 -0
  44. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/__init__.py +0 -0
  45. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/_current_date_time.jinja2 +0 -0
  46. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/_default_log_prompt.jinja2 +0 -0
  47. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/_fetch_logs.jinja2 +0 -0
  48. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/_general_instructions.jinja2 +0 -0
  49. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/_global_instructions.jinja2 +0 -0
  50. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/_runbook_instructions.jinja2 +0 -0
  51. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/_toolsets_instructions.jinja2 +0 -0
  52. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/generic_ask.jinja2 +0 -0
  53. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/generic_ask_conversation.jinja2 +0 -0
  54. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +0 -0
  55. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/generic_investigation.jinja2 +0 -0
  56. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/generic_post_processing.jinja2 +0 -0
  57. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/generic_ticket.jinja2 +0 -0
  58. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/investigation_output_format.jinja2 +0 -0
  59. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +0 -0
  60. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +0 -0
  61. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/runbooks/README.md +0 -0
  62. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/runbooks/__init__.py +0 -0
  63. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/runbooks/catalog.json +0 -0
  64. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/runbooks/jira.yaml +0 -0
  65. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/runbooks/kube-prometheus-stack.yaml +0 -0
  66. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/runbooks/networking/dns_troubleshooting_instructions.md +0 -0
  67. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/runbooks/upgrade/upgrade_troubleshooting_instructions.md +0 -0
  68. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/sources/github/__init__.py +0 -0
  69. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/sources/jira/__init__.py +0 -0
  70. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/sources/opsgenie/__init__.py +0 -0
  71. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/sources/pagerduty/__init__.py +0 -0
  72. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/sources/prometheus/__init__.py +0 -0
  73. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/sources/prometheus/models.py +0 -0
  74. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/sources/prometheus/plugin.py +0 -0
  75. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/__init__.py +0 -0
  76. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/aks-node-health.yaml +0 -0
  77. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/aks.yaml +0 -0
  78. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/argocd.yaml +0 -0
  79. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/atlas_mongodb/instructions.jinja2 +0 -0
  80. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +0 -0
  81. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/aws.yaml +0 -0
  82. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/__init__.py +0 -0
  83. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/apis/alert_monitoring_api.py +0 -0
  84. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/apis/azure_sql_api.py +0 -0
  85. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/apis/connection_failure_api.py +0 -0
  86. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/apis/connection_monitoring_api.py +0 -0
  87. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/apis/storage_analysis_api.py +0 -0
  88. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/azure_base_toolset.py +0 -0
  89. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/azure_sql_instructions.jinja2 +0 -0
  90. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +0 -0
  91. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/install.md +0 -0
  92. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/__init__.py +0 -0
  93. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +0 -0
  94. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +0 -0
  95. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +0 -0
  96. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +0 -0
  97. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +0 -0
  98. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +0 -0
  99. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +0 -0
  100. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +0 -0
  101. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +0 -0
  102. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +0 -0
  103. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/azure_sql/utils.py +0 -0
  104. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/__init__.py +0 -0
  105. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/bash_instructions.jinja2 +0 -0
  106. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/bash_toolset.py +0 -0
  107. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/common/bash.py +0 -0
  108. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/common/config.py +0 -0
  109. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/common/stringify.py +0 -0
  110. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/common/validators.py +0 -0
  111. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/grep/__init__.py +0 -0
  112. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/__init__.py +0 -0
  113. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/constants.py +0 -0
  114. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/kubectl_describe.py +0 -0
  115. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/kubectl_events.py +0 -0
  116. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +0 -0
  117. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/kubectl_logs.py +0 -0
  118. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/kubectl_run.py +0 -0
  119. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/kubectl/kubectl_top.py +0 -0
  120. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/bash/parse_command.py +0 -0
  121. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/confluence.yaml +0 -0
  122. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/consts.py +0 -0
  123. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/coralogix/api.py +0 -0
  124. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +0 -0
  125. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/coralogix/utils.py +0 -0
  126. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/datadog/datadog_api.py +0 -0
  127. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +0 -0
  128. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/datadog/datadog_traces_formatter.py +0 -0
  129. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/datadog/instructions_datadog_traces.jinja2 +0 -0
  130. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +0 -0
  131. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +0 -0
  132. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +0 -0
  133. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/docker.yaml +0 -0
  134. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/git.py +0 -0
  135. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/__init__.py +0 -0
  136. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/base_grafana_toolset.py +0 -0
  137. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/common.py +0 -0
  138. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/grafana_api.py +0 -0
  139. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/loki_api.py +0 -0
  140. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/tempo_api.py +0 -0
  141. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/toolset_grafana.py +0 -0
  142. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +0 -0
  143. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +0 -0
  144. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +0 -0
  145. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/grafana/trace_parser.py +0 -0
  146. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/helm.yaml +0 -0
  147. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/internet/internet.py +0 -0
  148. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/internet/notion.py +0 -0
  149. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/kafka.py +0 -0
  150. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/kubernetes.yaml +0 -0
  151. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/kubernetes_logs.py +0 -0
  152. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/kubernetes_logs.yaml +0 -0
  153. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/logging_utils/__init__.py +0 -0
  154. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/logging_utils/logging_api.py +0 -0
  155. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/logging_utils/types.py +0 -0
  156. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/mcp/toolset_mcp.py +0 -0
  157. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/newrelic.py +0 -0
  158. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/opensearch/__init__.py +0 -0
  159. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/opensearch/opensearch.py +0 -0
  160. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/opensearch/opensearch_logs.py +0 -0
  161. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/opensearch/opensearch_traces.py +0 -0
  162. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/opensearch/opensearch_traces_instructions.jinja2 +0 -0
  163. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/opensearch/opensearch_utils.py +0 -0
  164. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +0 -0
  165. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/rabbitmq/api.py +0 -0
  166. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/rabbitmq/rabbitmq_instructions.jinja2 +0 -0
  167. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +0 -0
  168. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/robusta/__init__.py +0 -0
  169. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/robusta/robusta.py +0 -0
  170. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/robusta/robusta_instructions.jinja2 +0 -0
  171. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/runbook/__init__.py +0 -0
  172. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/runbook/runbook_fetcher.py +0 -0
  173. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/service_discovery.py +0 -0
  174. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/servicenow/install.md +0 -0
  175. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/servicenow/instructions.jinja2 +0 -0
  176. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/servicenow/servicenow.py +0 -0
  177. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/slab.yaml +0 -0
  178. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/toolsets/utils.py +0 -0
  179. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/plugins/utils.py +0 -0
  180. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/__init__.py +0 -0
  181. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/cache.py +0 -0
  182. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/cert_utils.py +0 -0
  183. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/console/consts.py +0 -0
  184. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/console/result.py +0 -0
  185. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/default_toolset_installation_guide.jinja2 +0 -0
  186. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/definitions.py +0 -0
  187. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/env.py +0 -0
  188. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/file_utils.py +0 -0
  189. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/global_instructions.py +0 -0
  190. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/holmes_status.py +0 -0
  191. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/holmes_sync_toolsets.py +0 -0
  192. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/markdown_utils.py +0 -0
  193. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/pydantic_utils.py +0 -0
  194. {holmesgpt-0.12.0 → holmesgpt-0.12.1}/holmes/utils/tags.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: holmesgpt
3
- Version: 0.12.0
3
+ Version: 0.12.1
4
4
  Summary:
5
5
  Author: Natan Yellin
6
6
  Author-email: natan@robusta.dev
@@ -28,7 +28,7 @@ Requires-Dist: google-api-python-client (>=2.156.0,<3.0.0)
28
28
  Requires-Dist: humanize (>=4.9.0,<5.0.0)
29
29
  Requires-Dist: jinja2 (>=3.1.2,<4.0.0)
30
30
  Requires-Dist: kubernetes (>=32.0.1,<33.0.0)
31
- Requires-Dist: litellm (==1.66.0)
31
+ Requires-Dist: litellm (==1.74.7)
32
32
  Requires-Dist: markdown (>=3.6,<4.0)
33
33
  Requires-Dist: markdownify (>=1.1.0,<2.0.0)
34
34
  Requires-Dist: mcp (==v1.9.0)
@@ -40,6 +40,7 @@ Requires-Dist: pydantic (>=2.7,<3.0)
40
40
  Requires-Dist: pydantic-settings (>=2.1.0,<3.0.0)
41
41
  Requires-Dist: pydash (>=8.0.1,<9.0.0)
42
42
  Requires-Dist: pyodbc (>=5.0.1,<6.0.0)
43
+ Requires-Dist: pytest-shared-session-scope (>=0.4.0,<0.5.0)
43
44
  Requires-Dist: python-benedict (>=0.33.1,<0.34.0)
44
45
  Requires-Dist: python_multipart (>=0.0.18,<0.0.19)
45
46
  Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
@@ -0,0 +1,8 @@
1
+ # This is patched by github actions during release
2
+ __version__ = "0.12.1"
3
+
4
+ # Re-export version functions from version module for backward compatibility
5
+ from .version import (
6
+ get_version as get_version,
7
+ is_official_release as is_official_release,
8
+ )
@@ -5,7 +5,7 @@ from pydantic import BaseModel, ConfigDict
5
5
  from holmes.common.env_vars import ROBUSTA_API_ENDPOINT
6
6
 
7
7
  HOLMES_GET_INFO_URL = f"{ROBUSTA_API_ENDPOINT}/api/holmes/get_info"
8
- TIMEOUT = 0.3
8
+ TIMEOUT = 0.5
9
9
 
10
10
 
11
11
  class HolmesInfo(BaseModel):
@@ -49,3 +49,4 @@ KUBERNETES_LOGS_TIMEOUT_SECONDS = int(
49
49
  )
50
50
 
51
51
  TOOL_CALL_SAFEGUARDS_ENABLED = load_bool("TOOL_CALL_SAFEGUARDS_ENABLED", True)
52
+ IS_OPENSHIFT = load_bool("IS_OPENSHIFT", False)
@@ -0,0 +1,15 @@
1
+ from typing import Optional
2
+ import os
3
+
4
+ # NOTE: This one will be mounted if openshift is enabled in values.yaml
5
+ TOKEN_LOCATION = os.environ.get(
6
+ "TOKEN_LOCATION", "/var/run/secrets/kubernetes.io/serviceaccount/token"
7
+ )
8
+
9
+
10
+ def load_openshift_token() -> Optional[str]:
11
+ try:
12
+ with open(TOKEN_LOCATION, "r") as file:
13
+ return file.read()
14
+ except FileNotFoundError:
15
+ return None
@@ -9,8 +9,6 @@ from typing import Any, List, Optional, Union
9
9
  import yaml # type: ignore
10
10
  from pydantic import BaseModel, ConfigDict, FilePath, SecretStr
11
11
 
12
- from holmes import get_version # type: ignore
13
- from holmes.clients.robusta_client import HolmesInfo, fetch_holmes_info
14
12
  from holmes.common.env_vars import ROBUSTA_AI, ROBUSTA_API_ENDPOINT, ROBUSTA_CONFIG_PATH
15
13
  from holmes.core.llm import LLM, DefaultLLM
16
14
  from holmes.core.runbooks import RunbookManager
@@ -39,6 +37,7 @@ DEFAULT_CONFIG_LOCATION = os.path.expanduser("~/.holmes/config.yaml")
39
37
  MODEL_LIST_FILE_LOCATION = os.environ.get(
40
38
  "MODEL_LIST_FILE_LOCATION", "/etc/holmes/config/model_list.yaml"
41
39
  )
40
+ ROBUSTA_AI_MODEL_NAME = "Robusta"
42
41
 
43
42
 
44
43
  class SupportedTicketSources(str, Enum):
@@ -115,26 +114,8 @@ class Config(RobustaBaseConfig):
115
114
 
116
115
  _server_tool_executor: Optional[ToolExecutor] = None
117
116
 
118
- _version: Optional[str] = None
119
- _holmes_info: Optional[HolmesInfo] = None
120
-
121
117
  _toolset_manager: Optional[ToolsetManager] = None
122
118
 
123
- @property
124
- def is_latest_version(self) -> bool:
125
- if (
126
- not self._holmes_info
127
- or not self._holmes_info.latest_version
128
- or not self._version
129
- ):
130
- # We couldn't resolve version, assume we are running the latest version
131
- return True
132
- if self._version.startswith("dev-"):
133
- # dev versions are considered to be the latest version
134
- return True
135
-
136
- return self._version.startswith(self._holmes_info.latest_version)
137
-
138
119
  @property
139
120
  def toolset_manager(self) -> ToolsetManager:
140
121
  if not self._toolset_manager:
@@ -146,12 +127,10 @@ class Config(RobustaBaseConfig):
146
127
  return self._toolset_manager
147
128
 
148
129
  def model_post_init(self, __context: Any) -> None:
149
- self._version = get_version()
150
- self._holmes_info = fetch_holmes_info()
151
130
  self._model_list = parse_models_file(MODEL_LIST_FILE_LOCATION)
152
131
  if self._should_load_robusta_ai():
153
132
  logging.info("Loading Robusta AI model")
154
- self._model_list["Robusta"] = {
133
+ self._model_list[ROBUSTA_AI_MODEL_NAME] = {
155
134
  "base_url": ROBUSTA_API_ENDPOINT,
156
135
  }
157
136
 
@@ -178,11 +157,6 @@ class Config(RobustaBaseConfig):
178
157
  if self._model_list:
179
158
  logging.info(f"loaded models: {list(self._model_list.keys())}")
180
159
 
181
- if not self.is_latest_version and self._holmes_info:
182
- logging.warning(
183
- f"You are running version {self._version} of holmes, but the latest version is {self._holmes_info.latest_version}. Please update.",
184
- )
185
-
186
160
  @classmethod
187
161
  def load_from_file(cls, config_file: Optional[Path], **kwargs) -> "Config":
188
162
  """
@@ -140,14 +140,11 @@ class DefaultLLM(LLM):
140
140
  https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json
141
141
  """
142
142
  model_name = self.model
143
- if model_name.startswith("openai/"):
144
- model_name = model_name[len("openai/") :] # Strip the 'openai/' prefix
145
- elif model_name.startswith("bedrock/"):
146
- model_name = model_name[len("bedrock/") :] # Strip the 'bedrock/' prefix
147
- elif model_name.startswith("vertex_ai/"):
148
- model_name = model_name[
149
- len("vertex_ai/") :
150
- ] # Strip the 'vertex_ai/' prefix
143
+ prefixes = ["openai/", "bedrock/", "vertex_ai/", "anthropic/"]
144
+
145
+ for prefix in prefixes:
146
+ if model_name.startswith(prefix):
147
+ return model_name[len(prefix) :]
151
148
 
152
149
  return model_name
153
150
 
@@ -182,6 +182,10 @@ class SupabaseDal:
182
182
  res = self.client.auth.sign_in_with_password(
183
183
  {"email": self.email, "password": self.password}
184
184
  )
185
+ if not res.session:
186
+ raise ValueError("Authentication failed: no session returned")
187
+ if not res.user:
188
+ raise ValueError("Authentication failed: no user returned")
185
189
  self.client.auth.set_session(
186
190
  res.session.access_token, res.session.refresh_token
187
191
  )
@@ -39,7 +39,7 @@ from holmes.utils.global_instructions import (
39
39
  )
40
40
  from holmes.utils.tags import format_tags_in_string, parse_messages_tags
41
41
  from holmes.core.tools_utils.tool_executor import ToolExecutor
42
- from holmes.core.tracing import DummySpan, SpanType
42
+ from holmes.core.tracing import DummySpan
43
43
 
44
44
 
45
45
  def format_tool_result_data(tool_result: StructuredToolResult) -> str:
@@ -249,6 +249,7 @@ class ToolCallingLLM:
249
249
  user_prompt: Optional[str] = None,
250
250
  sections: Optional[InputSectionsDataType] = None,
251
251
  trace_span=DummySpan(),
252
+ tool_number_offset: int = 0,
252
253
  ) -> LLMResult:
253
254
  perf_timing = PerformanceTiming("tool_calling_llm.call")
254
255
  tool_calls = [] # type: ignore
@@ -367,7 +368,7 @@ class ToolCallingLLM:
367
368
  tool_to_call=t,
368
369
  previous_tool_calls=tool_calls,
369
370
  trace_span=trace_span,
370
- tool_number=tool_index,
371
+ tool_number=tool_number_offset + tool_index,
371
372
  )
372
373
  )
373
374
 
@@ -383,6 +384,8 @@ class ToolCallingLLM:
383
384
  if tools_to_call:
384
385
  logging.info("")
385
386
 
387
+ raise Exception(f"Too many LLM calls - exceeded max_steps: {i}/{max_steps}")
388
+
386
389
  def _invoke_tool(
387
390
  self,
388
391
  tool_to_call: ChatCompletionMessageToolCall,
@@ -419,7 +422,7 @@ class ToolCallingLLM:
419
422
  tool_response = None
420
423
 
421
424
  # Create tool span if tracing is enabled
422
- tool_span = trace_span.start_span(name=tool_name, type=SpanType.TOOL)
425
+ tool_span = trace_span.start_span(name=tool_name, type="tool")
423
426
 
424
427
  try:
425
428
  tool_response = prevent_overly_repeated_tool_call(
@@ -448,6 +451,8 @@ class ToolCallingLLM:
448
451
  metadata={
449
452
  "status": tool_response.status.value,
450
453
  "error": tool_response.error,
454
+ "description": tool.get_parameterized_one_liner(tool_params),
455
+ "structured_tool_result": tool_response,
451
456
  },
452
457
  )
453
458
 
@@ -720,6 +725,10 @@ class ToolCallingLLM:
720
725
  "tool_calling_result", streaming_result_dict
721
726
  )
722
727
 
728
+ raise Exception(
729
+ f"Too many LLM calls - exceeded max_steps: {i}/{self.max_steps}"
730
+ )
731
+
723
732
 
724
733
  # TODO: consider getting rid of this entirely and moving templating into the cmds in holmes_cli.py
725
734
  class IssueInvestigator(ToolCallingLLM):
@@ -154,8 +154,9 @@ class Tool(ABC, BaseModel):
154
154
  if hasattr(result, "get_stringified_data")
155
155
  else str(result)
156
156
  )
157
+ show_hint = f"/show {tool_number}" if tool_number else "/show"
157
158
  logging.info(
158
- f" [dim]Finished {tool_number_str}in {elapsed:.2f}s, output length: {len(output_str):,} characters - /show to view contents[/dim]"
159
+ f" [dim]Finished {tool_number_str}in {elapsed:.2f}s, output length: {len(output_str):,} characters - {show_hint} to view contents[/dim]"
159
160
  )
160
161
  return result
161
162
 
@@ -290,7 +290,7 @@ class ToolsetManager:
290
290
  [toolset for toolset in all_toolsets_with_status if toolset.enabled]
291
291
  )
292
292
  logging.info(
293
- f"Using {num_available_toolsets} datasources (toolsets). To refresh: `holmes toolset refresh`"
293
+ f"Using {num_available_toolsets} datasources (toolsets). To refresh: use flag `--refresh-toolsets`"
294
294
  )
295
295
  return all_toolsets_with_status
296
296
 
@@ -32,12 +32,13 @@ class SpanType(Enum):
32
32
  TOOL = "tool"
33
33
  TASK = "task"
34
34
  SCORE = "score"
35
+ EVAL = "eval"
35
36
 
36
37
 
37
38
  class DummySpan:
38
39
  """A no-op span implementation for when tracing is disabled."""
39
40
 
40
- def start_span(self, name: str, span_type: Optional[SpanType] = None, **kwargs):
41
+ def start_span(self, name: str, span_type=None, **kwargs):
41
42
  return DummySpan()
42
43
 
43
44
  def log(self, *args, **kwargs):
@@ -121,17 +122,17 @@ class BraintrustTracer:
121
122
  # Add span type to kwargs if provided
122
123
  kwargs = {}
123
124
  if span_type:
124
- kwargs["type"] = getattr(SpanTypeAttribute, span_type.name)
125
+ kwargs["type"] = span_type.value
125
126
 
126
127
  # Use current Braintrust context (experiment or parent span)
127
128
  current_span = braintrust.current_span()
128
129
  if not _is_noop_span(current_span):
129
- return current_span.start_span(name=name, **kwargs)
130
+ return current_span.start_span(name=name, **kwargs) # type: ignore
130
131
 
131
132
  # Fallback to current experiment
132
133
  current_experiment = braintrust.current_experiment()
133
134
  if current_experiment:
134
- return current_experiment.start_span(name=name, **kwargs)
135
+ return current_experiment.start_span(name=name, **kwargs) # type: ignore
135
136
 
136
137
  return DummySpan()
137
138
 
@@ -6,15 +6,15 @@ import threading
6
6
  from collections import defaultdict
7
7
  from enum import Enum
8
8
  from pathlib import Path
9
- from typing import Optional, List, DefaultDict
9
+ from typing import DefaultDict, List, Optional
10
10
 
11
11
  import typer
12
12
  from prompt_toolkit import PromptSession
13
13
  from prompt_toolkit.application import Application
14
14
  from prompt_toolkit.completion import Completer, Completion, merge_completers
15
15
  from prompt_toolkit.completion.filesystem import ExecutableCompleter, PathCompleter
16
- from prompt_toolkit.history import InMemoryHistory, FileHistory
17
16
  from prompt_toolkit.document import Document
17
+ from prompt_toolkit.history import FileHistory, InMemoryHistory
18
18
  from prompt_toolkit.key_binding import KeyBindings
19
19
  from prompt_toolkit.layout import Layout
20
20
  from prompt_toolkit.layout.containers import HSplit, Window
@@ -22,27 +22,26 @@ from prompt_toolkit.layout.controls import FormattedTextControl
22
22
  from prompt_toolkit.shortcuts.prompt import CompleteStyle
23
23
  from prompt_toolkit.styles import Style
24
24
  from prompt_toolkit.widgets import TextArea
25
-
26
25
  from rich.console import Console
27
26
  from rich.markdown import Markdown, Panel
28
27
 
29
28
  from holmes.core.prompt import build_initial_ask_messages
30
29
  from holmes.core.tool_calling_llm import ToolCallingLLM, ToolCallResult
31
30
  from holmes.core.tools import pretty_print_toolset_status
32
- from holmes.core.tracing import DummySpan
31
+ from holmes.version import check_version_async
32
+ from holmes.core.tracing import DummyTracer
33
33
 
34
34
 
35
35
  class SlashCommands(Enum):
36
36
  EXIT = ("/exit", "Exit interactive mode")
37
37
  HELP = ("/help", "Show help message with all commands")
38
- RESET = ("/reset", "Reset the conversation context")
38
+ CLEAR = ("/clear", "Clear screen and reset conversation context")
39
39
  TOOLS_CONFIG = ("/tools", "Show available toolsets and their status")
40
40
  TOGGLE_TOOL_OUTPUT = (
41
41
  "/auto",
42
42
  "Toggle auto-display of tool outputs after responses",
43
43
  )
44
44
  LAST_OUTPUT = ("/last", "Show all tool outputs from last response")
45
- CLEAR = ("/clear", "Clear the terminal screen")
46
45
  RUN = ("/run", "Run a bash command and optionally share with LLM")
47
46
  SHELL = (
48
47
  "/shell",
@@ -722,9 +721,9 @@ def run_interactive_loop(
722
721
  show_tool_output: bool,
723
722
  tracer=None,
724
723
  ) -> None:
725
- # Initialize tracer - use DummySpan if no tracer provided
724
+ # Initialize tracer - use DummyTracer if no tracer provided
726
725
  if tracer is None:
727
- tracer = DummySpan()
726
+ tracer = DummyTracer()
728
727
 
729
728
  style = Style.from_dict(
730
729
  {
@@ -753,6 +752,23 @@ def run_interactive_loop(
753
752
  # Create custom key bindings for Ctrl+C behavior
754
753
  bindings = KeyBindings()
755
754
  status_message = ""
755
+ version_message = ""
756
+
757
+ def clear_version_message():
758
+ nonlocal version_message
759
+ version_message = ""
760
+ session.app.invalidate()
761
+
762
+ def on_version_check_complete(result):
763
+ """Callback when background version check completes"""
764
+ nonlocal version_message
765
+ if not result.is_latest and result.update_message:
766
+ version_message = result.update_message
767
+ session.app.invalidate()
768
+
769
+ # Auto-clear after 10 seconds
770
+ timer = threading.Timer(10, clear_version_message)
771
+ timer.start()
756
772
 
757
773
  @bindings.add("c-c")
758
774
  def _(event):
@@ -776,9 +792,19 @@ def run_interactive_loop(
776
792
  raise KeyboardInterrupt()
777
793
 
778
794
  def get_bottom_toolbar():
795
+ messages = []
796
+
797
+ # Ctrl-c status message (red background)
779
798
  if status_message:
780
- return [("bg:#ff0000 fg:#000000", status_message)]
781
- return None
799
+ messages.append(("bg:#ff0000 fg:#000000", status_message))
800
+
801
+ # Version message (yellow background)
802
+ if version_message:
803
+ if messages:
804
+ messages.append(("", " | "))
805
+ messages.append(("bg:#ffff00 fg:#000000", version_message))
806
+
807
+ return messages if messages else None
782
808
 
783
809
  session = PromptSession(
784
810
  completer=command_completer,
@@ -789,6 +815,9 @@ def run_interactive_loop(
789
815
  bottom_toolbar=get_bottom_toolbar,
790
816
  ) # type: ignore
791
817
 
818
+ # Start background version check
819
+ check_version_async(on_version_check_complete)
820
+
792
821
  input_prompt = [("class:prompt", "User: ")]
793
822
 
794
823
  console.print(WELCOME_BANNER)
@@ -833,9 +862,10 @@ def run_interactive_loop(
833
862
  for cmd, description in SLASH_COMMANDS_REFERENCE.items():
834
863
  console.print(f" [bold]{cmd}[/bold] - {description}")
835
864
  continue
836
- elif command == SlashCommands.RESET.value:
865
+ elif command == SlashCommands.CLEAR.command:
866
+ console.clear()
837
867
  console.print(
838
- f"[bold {STATUS_COLOR}]Context reset. You can now ask a new question.[/bold {STATUS_COLOR}]"
868
+ f"[bold {STATUS_COLOR}]Screen cleared and context reset. You can now ask a new question.[/bold {STATUS_COLOR}]"
839
869
  )
840
870
  messages = None
841
871
  last_response = None
@@ -854,9 +884,6 @@ def run_interactive_loop(
854
884
  elif command == SlashCommands.LAST_OUTPUT.command:
855
885
  handle_last_command(last_response, console, all_tool_calls_history)
856
886
  continue
857
- elif command == SlashCommands.CLEAR.command:
858
- console.clear()
859
- continue
860
887
  elif command == SlashCommands.CONTEXT.command:
861
888
  handle_context_command(messages, ai, console)
862
889
  continue
@@ -902,7 +929,10 @@ def run_interactive_loop(
902
929
  metadata={"type": "user_question"},
903
930
  )
904
931
  response = ai.call(
905
- messages, post_processing_prompt, trace_span=trace_span
932
+ messages,
933
+ post_processing_prompt,
934
+ trace_span=trace_span,
935
+ tool_number_offset=len(all_tool_calls_history),
906
936
  )
907
937
  trace_span.log(
908
938
  output=response.result,
@@ -219,16 +219,20 @@ def ask(
219
219
  Ask any question and answer using available tools
220
220
  """
221
221
  console = init_logging(verbose) # type: ignore
222
-
223
222
  # Detect and read piped input
224
223
  piped_data = None
225
- if not sys.stdin.isatty():
224
+
225
+ # when attaching a pycharm debugger sys.stdin.isatty() returns false and sys.stdin.read() is stuck
226
+ running_from_pycharm = os.environ.get("PYCHARM_HOSTED", False)
227
+
228
+ if not sys.stdin.isatty() and not running_from_pycharm:
226
229
  piped_data = sys.stdin.read().strip()
227
230
  if interactive:
228
231
  console.print(
229
232
  "[bold yellow]Interactive mode disabled when reading piped input[/bold yellow]"
230
233
  )
231
234
  interactive = False
235
+
232
236
  config = Config.load_from_file(
233
237
  config_file,
234
238
  api_key=api_key,
@@ -9,7 +9,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union
9
9
  from urllib.parse import urljoin
10
10
 
11
11
  import requests # type: ignore
12
- from pydantic import BaseModel, field_validator
12
+ from pydantic import BaseModel, field_validator, Field, model_validator
13
13
  from requests import RequestException
14
14
 
15
15
  from holmes.core.tools import (
@@ -29,6 +29,8 @@ from holmes.plugins.toolsets.utils import (
29
29
  standard_start_datetime_tool_param_description,
30
30
  )
31
31
  from holmes.utils.cache import TTLCache
32
+ from holmes.common.env_vars import IS_OPENSHIFT
33
+ from holmes.common.openshift import load_openshift_token
32
34
 
33
35
  PROMETHEUS_RULES_CACHE_KEY = "cached_prometheus_rules"
34
36
  DEFAULT_TIME_SPAN_SECONDS = 3600
@@ -45,7 +47,7 @@ class PrometheusConfig(BaseModel):
45
47
  fetch_labels_with_labels_api: bool = False
46
48
  fetch_metadata_with_series_api: bool = False
47
49
  tool_calls_return_data: bool = True
48
- headers: Dict = {}
50
+ headers: Dict = Field(default_factory=dict)
49
51
  rules_cache_duration_seconds: Union[int, None] = 1800 # 30 minutes
50
52
  additional_labels: Optional[Dict[str, str]] = None
51
53
 
@@ -55,6 +57,23 @@ class PrometheusConfig(BaseModel):
55
57
  return v + "/"
56
58
  return v
57
59
 
60
+ @model_validator(mode="after")
61
+ def validate_prom_config(self):
62
+ # If openshift is enabled, and the user didn't configure auth headers, we will try to load the token from the service account.
63
+ if IS_OPENSHIFT:
64
+ if self.healthcheck == "-/healthy":
65
+ self.healthcheck = "api/v1/query?query=up"
66
+
67
+ if self.headers.get("Authorization"):
68
+ return self
69
+
70
+ openshift_token = load_openshift_token()
71
+ if openshift_token:
72
+ logging.info("Using openshift token for prometheus toolset auth")
73
+ self.headers["Authorization"] = f"Bearer {openshift_token}"
74
+
75
+ return self
76
+
58
77
 
59
78
  class BasePrometheusTool(Tool):
60
79
  toolset: "PrometheusToolset"
@@ -46,6 +46,7 @@ def init_logging(verbose_flags: Optional[List[bool]] = None):
46
46
 
47
47
  if verbosity == Verbosity.VERY_VERBOSE:
48
48
  logging.basicConfig(
49
+ force=True,
49
50
  level=logging.DEBUG,
50
51
  format="%(message)s",
51
52
  handlers=[
@@ -60,6 +61,7 @@ def init_logging(verbose_flags: Optional[List[bool]] = None):
60
61
  )
61
62
  elif verbosity == Verbosity.VERBOSE:
62
63
  logging.basicConfig(
64
+ force=True,
63
65
  level=logging.INFO,
64
66
  format="%(message)s",
65
67
  handlers=[
@@ -76,6 +78,7 @@ def init_logging(verbose_flags: Optional[List[bool]] = None):
76
78
  suppress_noisy_logs()
77
79
  else:
78
80
  logging.basicConfig(
81
+ force=True,
79
82
  level=logging.INFO,
80
83
  format="%(message)s",
81
84
  handlers=[
@@ -1,10 +1,9 @@
1
- from holmes.config import Config
1
+ from holmes.config import Config, ROBUSTA_AI_MODEL_NAME
2
2
  from holmes.core.supabase_dal import SupabaseDal
3
3
  from pydantic import SecretStr
4
- from holmes.common.env_vars import load_bool
5
4
 
6
5
 
7
6
  def load_robusta_api_key(dal: SupabaseDal, config: Config):
8
- if load_bool("ROBUSTA_AI", False):
7
+ if ROBUSTA_AI_MODEL_NAME in config._model_list:
9
8
  account_id, token = dal.get_ai_credentials()
10
9
  config.api_key = SecretStr(f"{account_id} {token}")