holmesgpt 0.13.0__tar.gz → 0.13.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 (241) hide show
  1. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/PKG-INFO +1 -1
  2. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/__init__.py +1 -1
  3. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/common/env_vars.py +4 -0
  4. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/llm.py +3 -1
  5. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/tool_calling_llm.py +112 -11
  6. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/toolset_manager.py +1 -5
  7. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/tracing.py +1 -1
  8. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/main.py +7 -1
  9. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_fetch_logs.jinja2 +4 -0
  10. holmesgpt-0.13.1/holmes/plugins/runbooks/CLAUDE.md +85 -0
  11. holmesgpt-0.13.1/holmes/plugins/runbooks/README.md +46 -0
  12. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/argocd/__init__.py +65 -0
  13. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/argocd/constants.py +120 -0
  14. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/aws/__init__.py +66 -0
  15. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/aws/constants.py +529 -0
  16. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/azure/__init__.py +56 -0
  17. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/azure/constants.py +339 -0
  18. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/bash_instructions.jinja2 +13 -0
  19. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/bash/bash_toolset.py +47 -13
  20. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/common/bash_command.py +131 -0
  21. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/bash/common/stringify.py +14 -1
  22. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/common/validators.py +115 -0
  23. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/docker/__init__.py +59 -0
  24. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/docker/constants.py +255 -0
  25. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/helm/__init__.py +61 -0
  26. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/helm/constants.py +92 -0
  27. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/kubectl/__init__.py +101 -0
  28. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/bash/kubectl/constants.py +0 -14
  29. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/kubectl/kubectl_describe.py +48 -0
  30. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/kubectl/kubectl_events.py +40 -0
  31. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +48 -0
  32. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/kubectl/kubectl_logs.py +39 -0
  33. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/bash/kubectl/kubectl_run.py +1 -1
  34. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/kubectl/kubectl_top.py +42 -0
  35. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/parse_command.py +177 -0
  36. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/base64_util.py +12 -0
  37. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/cut.py +12 -0
  38. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/grep/__init__.py +10 -0
  39. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/head.py +12 -0
  40. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/jq.py +79 -0
  41. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/sed.py +164 -0
  42. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/sort.py +15 -0
  43. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/tail.py +12 -0
  44. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/tr.py +57 -0
  45. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/uniq.py +12 -0
  46. holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities/wc.py +12 -0
  47. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/prometheus/prometheus.py +42 -12
  48. holmesgpt-0.13.1/holmes/utils/__init__.py +0 -0
  49. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/console/logging.py +6 -1
  50. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/pyproject.toml +3 -2
  51. holmesgpt-0.13.0/holmes/plugins/runbooks/README.md +0 -22
  52. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/bash_instructions.jinja2 +0 -14
  53. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/common/validators.py +0 -24
  54. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/grep/__init__.py +0 -52
  55. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/kubectl/__init__.py +0 -100
  56. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/kubectl/kubectl_describe.py +0 -66
  57. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/kubectl/kubectl_events.py +0 -88
  58. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +0 -108
  59. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/kubectl/kubectl_logs.py +0 -20
  60. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/kubectl/kubectl_top.py +0 -81
  61. holmesgpt-0.13.0/holmes/plugins/toolsets/bash/parse_command.py +0 -103
  62. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/LICENSE.txt +0 -0
  63. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/README.md +0 -0
  64. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/.git_archival.json +0 -0
  65. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/clients/robusta_client.py +0 -0
  66. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/common/openshift.py +0 -0
  67. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/config.py +0 -0
  68. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/__init__.py +0 -0
  69. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/config.py +0 -0
  70. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/conversations.py +0 -0
  71. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/investigation.py +0 -0
  72. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/investigation_structured_output.py +0 -0
  73. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/issue.py +0 -0
  74. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/models.py +0 -0
  75. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/openai_formatting.py +0 -0
  76. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/performance_timing.py +0 -0
  77. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/prompt.py +0 -0
  78. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/resource_instruction.py +0 -0
  79. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/runbooks.py +0 -0
  80. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/safeguards.py +0 -0
  81. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/supabase_dal.py +0 -0
  82. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/todo_manager.py +0 -0
  83. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/tools.py +0 -0
  84. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/tools_utils/__init__.py +0 -0
  85. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/tools_utils/tool_executor.py +0 -0
  86. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/core/tools_utils/toolset_utils.py +0 -0
  87. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/interactive.py +0 -0
  88. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/__init__.py +0 -0
  89. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/destinations/__init__.py +0 -0
  90. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/destinations/slack/__init__.py +0 -0
  91. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/destinations/slack/plugin.py +0 -0
  92. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/interfaces.py +0 -0
  93. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/__init__.py +0 -0
  94. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_ai_safety.jinja2 +0 -0
  95. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_current_date_time.jinja2 +0 -0
  96. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_default_log_prompt.jinja2 +0 -0
  97. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_general_instructions.jinja2 +0 -0
  98. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_global_instructions.jinja2 +0 -0
  99. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_permission_errors.jinja2 +0 -0
  100. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_runbook_instructions.jinja2 +0 -0
  101. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/_toolsets_instructions.jinja2 +0 -0
  102. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/generic_ask.jinja2 +0 -0
  103. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/generic_ask_conversation.jinja2 +0 -0
  104. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +0 -0
  105. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/generic_investigation.jinja2 +0 -0
  106. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/generic_post_processing.jinja2 +0 -0
  107. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/generic_ticket.jinja2 +0 -0
  108. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/investigation_output_format.jinja2 +0 -0
  109. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/investigation_procedure.jinja2 +0 -0
  110. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +0 -0
  111. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +0 -0
  112. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/runbooks/__init__.py +0 -0
  113. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/runbooks/catalog.json +0 -0
  114. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/runbooks/jira.yaml +0 -0
  115. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/runbooks/kube-prometheus-stack.yaml +0 -0
  116. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/runbooks/networking/dns_troubleshooting_instructions.md +0 -0
  117. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/runbooks/upgrade/upgrade_troubleshooting_instructions.md +0 -0
  118. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/sources/github/__init__.py +0 -0
  119. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/sources/jira/__init__.py +0 -0
  120. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/sources/opsgenie/__init__.py +0 -0
  121. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/sources/pagerduty/__init__.py +0 -0
  122. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/sources/prometheus/__init__.py +0 -0
  123. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/sources/prometheus/models.py +0 -0
  124. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/sources/prometheus/plugin.py +0 -0
  125. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/__init__.py +0 -0
  126. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/aks-node-health.yaml +0 -0
  127. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/aks.yaml +0 -0
  128. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/argocd.yaml +0 -0
  129. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/atlas_mongodb/instructions.jinja2 +0 -0
  130. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +0 -0
  131. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/aws.yaml +0 -0
  132. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/__init__.py +0 -0
  133. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/apis/alert_monitoring_api.py +0 -0
  134. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/apis/azure_sql_api.py +0 -0
  135. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/apis/connection_failure_api.py +0 -0
  136. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/apis/connection_monitoring_api.py +0 -0
  137. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/apis/storage_analysis_api.py +0 -0
  138. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/azure_base_toolset.py +0 -0
  139. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/azure_sql_instructions.jinja2 +0 -0
  140. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +0 -0
  141. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/install.md +0 -0
  142. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/__init__.py +0 -0
  143. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +0 -0
  144. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +0 -0
  145. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +0 -0
  146. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +0 -0
  147. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +0 -0
  148. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +0 -0
  149. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +0 -0
  150. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +0 -0
  151. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +0 -0
  152. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +0 -0
  153. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/azure_sql/utils.py +0 -0
  154. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/bash/__init__.py +0 -0
  155. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/bash/common/bash.py +0 -0
  156. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/bash/common/config.py +0 -0
  157. {holmesgpt-0.13.0/holmes/plugins/toolsets/grafana → holmesgpt-0.13.1/holmes/plugins/toolsets/bash/utilities}/__init__.py +0 -0
  158. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/confluence.yaml +0 -0
  159. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/consts.py +0 -0
  160. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/coralogix/api.py +0 -0
  161. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +0 -0
  162. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/coralogix/utils.py +0 -0
  163. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/datadog_api.py +0 -0
  164. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +0 -0
  165. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/datadog_rds_instructions.jinja2 +0 -0
  166. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/datadog_traces_formatter.py +0 -0
  167. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/instructions_datadog_traces.jinja2 +0 -0
  168. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +0 -0
  169. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +0 -0
  170. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +0 -0
  171. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +0 -0
  172. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/docker.yaml +0 -0
  173. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/git.py +0 -0
  174. {holmesgpt-0.13.0/holmes/plugins/toolsets/investigator → holmesgpt-0.13.1/holmes/plugins/toolsets/grafana}/__init__.py +0 -0
  175. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/base_grafana_toolset.py +0 -0
  176. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/common.py +0 -0
  177. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/grafana_api.py +0 -0
  178. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/loki_api.py +0 -0
  179. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/tempo_api.py +0 -0
  180. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/toolset_grafana.py +0 -0
  181. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +0 -0
  182. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +0 -0
  183. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +0 -0
  184. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/grafana/trace_parser.py +0 -0
  185. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/helm.yaml +0 -0
  186. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/internet/internet.py +0 -0
  187. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/internet/notion.py +0 -0
  188. {holmesgpt-0.13.0/holmes/plugins/toolsets/logging_utils → holmesgpt-0.13.1/holmes/plugins/toolsets/investigator}/__init__.py +0 -0
  189. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/investigator/core_investigation.py +0 -0
  190. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/investigator/investigator_instructions.jinja2 +0 -0
  191. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/investigator/model.py +0 -0
  192. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/kafka.py +0 -0
  193. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/kubernetes.yaml +0 -0
  194. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/kubernetes_logs.py +0 -0
  195. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/kubernetes_logs.yaml +0 -0
  196. {holmesgpt-0.13.0/holmes/plugins/toolsets/opensearch → holmesgpt-0.13.1/holmes/plugins/toolsets/logging_utils}/__init__.py +0 -0
  197. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/logging_utils/logging_api.py +0 -0
  198. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/logging_utils/types.py +0 -0
  199. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/mcp/toolset_mcp.py +0 -0
  200. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/newrelic.py +0 -0
  201. {holmesgpt-0.13.0/holmes/plugins/toolsets/robusta → holmesgpt-0.13.1/holmes/plugins/toolsets/opensearch}/__init__.py +0 -0
  202. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/opensearch/opensearch.py +0 -0
  203. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/opensearch/opensearch_logs.py +0 -0
  204. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/opensearch/opensearch_traces.py +0 -0
  205. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/opensearch/opensearch_traces_instructions.jinja2 +0 -0
  206. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/opensearch/opensearch_utils.py +0 -0
  207. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +0 -0
  208. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/rabbitmq/api.py +0 -0
  209. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/rabbitmq/rabbitmq_instructions.jinja2 +0 -0
  210. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +0 -0
  211. {holmesgpt-0.13.0/holmes/plugins/toolsets/runbook → holmesgpt-0.13.1/holmes/plugins/toolsets/robusta}/__init__.py +0 -0
  212. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/robusta/robusta.py +0 -0
  213. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/robusta/robusta_instructions.jinja2 +0 -0
  214. {holmesgpt-0.13.0/holmes/utils → holmesgpt-0.13.1/holmes/plugins/toolsets/runbook}/__init__.py +0 -0
  215. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/runbook/runbook_fetcher.py +0 -0
  216. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/service_discovery.py +0 -0
  217. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/servicenow/install.md +0 -0
  218. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/servicenow/instructions.jinja2 +0 -0
  219. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/servicenow/servicenow.py +0 -0
  220. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/slab.yaml +0 -0
  221. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/toolsets/utils.py +0 -0
  222. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/plugins/utils.py +0 -0
  223. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/cache.py +0 -0
  224. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/cert_utils.py +0 -0
  225. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/colors.py +0 -0
  226. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/console/consts.py +0 -0
  227. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/console/result.py +0 -0
  228. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/default_toolset_installation_guide.jinja2 +0 -0
  229. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/definitions.py +0 -0
  230. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/env.py +0 -0
  231. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/file_utils.py +0 -0
  232. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/global_instructions.py +0 -0
  233. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/holmes_status.py +0 -0
  234. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/holmes_sync_toolsets.py +0 -0
  235. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/keygen_utils.py +0 -0
  236. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/llms.py +0 -0
  237. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/markdown_utils.py +0 -0
  238. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/pydantic_utils.py +0 -0
  239. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/stream.py +0 -0
  240. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/utils/tags.py +0 -0
  241. {holmesgpt-0.13.0 → holmesgpt-0.13.1}/holmes/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: holmesgpt
3
- Version: 0.13.0
3
+ Version: 0.13.1
4
4
  Summary:
5
5
  Author: Natan Yellin
6
6
  Author-email: natan@robusta.dev
@@ -1,5 +1,5 @@
1
1
  # This is patched by github actions during release
2
- __version__ = "0.13.0"
2
+ __version__ = "0.13.1"
3
3
 
4
4
  # Re-export version functions from version module for backward compatibility
5
5
  from .version import (
@@ -34,6 +34,7 @@ LOG_PERFORMANCE = os.environ.get("LOG_PERFORMANCE", None)
34
34
 
35
35
 
36
36
  ENABLE_TELEMETRY = load_bool("ENABLE_TELEMETRY", False)
37
+ DEVELOPMENT_MODE = load_bool("DEVELOPMENT_MODE", False)
37
38
  SENTRY_DSN = os.environ.get("SENTRY_DSN", "")
38
39
  SENTRY_TRACES_SAMPLE_RATE = float(os.environ.get("SENTRY_TRACES_SAMPLE_RATE", "0.0"))
39
40
 
@@ -63,3 +64,6 @@ TOOL_SCHEMA_NO_PARAM_OBJECT_IF_NO_PARAMS = load_bool(
63
64
  MAX_OUTPUT_TOKEN_RESERVATION = int(
64
65
  os.environ.get("MAX_OUTPUT_TOKEN_RESERVATION", 16384)
65
66
  ) ## 16k
67
+
68
+ # When using the bash tool, setting BASH_TOOL_UNSAFE_ALLOW_ALL will skip any command validation and run any command requested by the LLM
69
+ BASH_TOOL_UNSAFE_ALLOW_ALL = load_bool("BASH_TOOL_UNSAFE_ALLOW_ALL", False)
@@ -119,7 +119,9 @@ class DefaultLLM(LLM):
119
119
  "environment variable for proper functionality. For more information, refer to the documentation: "
120
120
  "https://docs.litellm.ai/docs/providers/watsonx#usage---models-in-deployment-spaces"
121
121
  )
122
- elif provider == "bedrock" and os.environ.get("AWS_PROFILE"):
122
+ elif provider == "bedrock" and (
123
+ os.environ.get("AWS_PROFILE") or os.environ.get("AWS_BEARER_TOKEN_BEDROCK")
124
+ ):
123
125
  model_requirements = {"keys_in_environment": True, "missing_keys": []}
124
126
  else:
125
127
  #
@@ -10,7 +10,7 @@ from openai import BadRequestError
10
10
  from openai.types.chat.chat_completion_message_tool_call import (
11
11
  ChatCompletionMessageToolCall,
12
12
  )
13
- from pydantic import BaseModel
13
+ from pydantic import BaseModel, Field
14
14
  from rich.console import Console
15
15
 
16
16
  from holmes.common.env_vars import TEMPERATURE, MAX_OUTPUT_TOKEN_RESERVATION
@@ -43,6 +43,78 @@ from holmes.core.todo_manager import (
43
43
  get_todo_manager,
44
44
  )
45
45
 
46
+ # Create a named logger for cost tracking
47
+ cost_logger = logging.getLogger("holmes.costs")
48
+
49
+
50
+ class LLMCosts(BaseModel):
51
+ """Tracks cost and token usage for LLM calls."""
52
+
53
+ total_cost: float = 0.0
54
+ total_tokens: int = 0
55
+ prompt_tokens: int = 0
56
+ completion_tokens: int = 0
57
+
58
+
59
+ def _extract_cost_from_response(full_response) -> float:
60
+ """Extract cost value from LLM response.
61
+
62
+ Args:
63
+ full_response: The raw LLM response object
64
+
65
+ Returns:
66
+ The cost as a float, or 0.0 if not available
67
+ """
68
+ try:
69
+ cost_value = (
70
+ full_response._hidden_params.get("response_cost", 0)
71
+ if hasattr(full_response, "_hidden_params")
72
+ else 0
73
+ )
74
+ # Ensure cost is a float
75
+ return float(cost_value) if cost_value is not None else 0.0
76
+ except Exception:
77
+ return 0.0
78
+
79
+
80
+ def _process_cost_info(
81
+ full_response, costs: Optional[LLMCosts] = None, log_prefix: str = "LLM call"
82
+ ) -> None:
83
+ """Process cost and token information from LLM response.
84
+
85
+ Logs the cost information and optionally accumulates it into a costs object.
86
+
87
+ Args:
88
+ full_response: The raw LLM response object
89
+ costs: Optional LLMCosts object to accumulate costs into
90
+ log_prefix: Prefix for logging messages (e.g., "LLM call", "Post-processing")
91
+ """
92
+ try:
93
+ cost = _extract_cost_from_response(full_response)
94
+ usage = getattr(full_response, "usage", {})
95
+
96
+ if usage:
97
+ prompt_toks = usage.get("prompt_tokens", 0)
98
+ completion_toks = usage.get("completion_tokens", 0)
99
+ total_toks = usage.get("total_tokens", 0)
100
+ cost_logger.debug(
101
+ f"{log_prefix} cost: ${cost:.6f} | Tokens: {prompt_toks} prompt + {completion_toks} completion = {total_toks} total"
102
+ )
103
+ # Accumulate costs and tokens if costs object provided
104
+ if costs:
105
+ costs.total_cost += cost
106
+ costs.prompt_tokens += prompt_toks
107
+ costs.completion_tokens += completion_toks
108
+ costs.total_tokens += total_toks
109
+ elif cost > 0:
110
+ cost_logger.debug(
111
+ f"{log_prefix} cost: ${cost:.6f} | Token usage not available"
112
+ )
113
+ if costs:
114
+ costs.total_cost += cost
115
+ except Exception as e:
116
+ logging.debug(f"Could not extract cost information: {e}")
117
+
46
118
 
47
119
  def format_tool_result_data(tool_result: StructuredToolResult) -> str:
48
120
  tool_response = tool_result.data
@@ -186,11 +258,11 @@ class ToolCallResult(BaseModel):
186
258
  }
187
259
 
188
260
 
189
- class LLMResult(BaseModel):
261
+ class LLMResult(LLMCosts):
190
262
  tool_calls: Optional[List[ToolCallResult]] = None
191
263
  result: Optional[str] = None
192
264
  unprocessed_result: Optional[str] = None
193
- instructions: List[str] = []
265
+ instructions: List[str] = Field(default_factory=list)
194
266
  # TODO: clean up these two
195
267
  prompt: Optional[str] = None
196
268
  messages: Optional[List[dict]] = None
@@ -259,6 +331,8 @@ class ToolCallingLLM:
259
331
  ) -> LLMResult:
260
332
  perf_timing = PerformanceTiming("tool_calling_llm.call")
261
333
  tool_calls = [] # type: ignore
334
+ costs = LLMCosts()
335
+
262
336
  tools = self.tool_executor.get_all_tools_openai_format(
263
337
  target_model=self.llm.model
264
338
  )
@@ -299,6 +373,9 @@ class ToolCallingLLM:
299
373
  )
300
374
  logging.debug(f"got response {full_response.to_json()}") # type: ignore
301
375
 
376
+ # Extract and accumulate cost information
377
+ _process_cost_info(full_response, costs, "LLM call")
378
+
302
379
  perf_timing.measure("llm.completion")
303
380
  # catch a known error that occurs with Azure and replace the error message with something more obvious to the user
304
381
  except BadRequestError as e:
@@ -352,11 +429,14 @@ class ToolCallingLLM:
352
429
  if post_process_prompt and user_prompt:
353
430
  logging.info("Running post processing on investigation.")
354
431
  raw_response = text_response
355
- post_processed_response = self._post_processing_call(
356
- prompt=user_prompt,
357
- investigation=raw_response,
358
- user_prompt=post_process_prompt,
432
+ post_processed_response, post_processing_cost = (
433
+ self._post_processing_call(
434
+ prompt=user_prompt,
435
+ investigation=raw_response,
436
+ user_prompt=post_process_prompt,
437
+ )
359
438
  )
439
+ costs.total_cost += post_processing_cost
360
440
 
361
441
  perf_timing.end(f"- completed in {i} iterations -")
362
442
  return LLMResult(
@@ -365,6 +445,7 @@ class ToolCallingLLM:
365
445
  tool_calls=tool_calls,
366
446
  prompt=json.dumps(messages, indent=2),
367
447
  messages=messages,
448
+ **costs.model_dump(), # Include all cost fields
368
449
  )
369
450
 
370
451
  perf_timing.end(f"- completed in {i} iterations -")
@@ -373,6 +454,7 @@ class ToolCallingLLM:
373
454
  tool_calls=tool_calls,
374
455
  prompt=json.dumps(messages, indent=2),
375
456
  messages=messages,
457
+ **costs.model_dump(), # Include all cost fields
376
458
  )
377
459
 
378
460
  if text_response and text_response.strip():
@@ -403,6 +485,9 @@ class ToolCallingLLM:
403
485
 
404
486
  perf_timing.measure(f"tool completed {tool_call_result.tool_name}")
405
487
 
488
+ # Update the tool number offset for the next iteration
489
+ tool_number_offset += len(tools_to_call)
490
+
406
491
  # Add a blank line after all tools in this batch complete
407
492
  if tools_to_call:
408
493
  logging.info("")
@@ -540,7 +625,7 @@ class ToolCallingLLM:
540
625
  investigation,
541
626
  user_prompt: Optional[str] = None,
542
627
  system_prompt: str = "You are an AI assistant summarizing Kubernetes issues.",
543
- ) -> Optional[str]:
628
+ ) -> tuple[Optional[str], float]:
544
629
  try:
545
630
  user_prompt = ToolCallingLLM.__load_post_processing_user_prompt(
546
631
  prompt, investigation, user_prompt
@@ -559,10 +644,18 @@ class ToolCallingLLM:
559
644
  ]
560
645
  full_response = self.llm.completion(messages=messages, temperature=0)
561
646
  logging.debug(f"Post processing response {full_response}")
562
- return full_response.choices[0].message.content # type: ignore
647
+
648
+ # Extract and log cost information for post-processing
649
+ post_processing_cost = _extract_cost_from_response(full_response)
650
+ if post_processing_cost > 0:
651
+ cost_logger.debug(
652
+ f"Post-processing LLM cost: ${post_processing_cost:.6f}"
653
+ )
654
+
655
+ return full_response.choices[0].message.content, post_processing_cost # type: ignore
563
656
  except Exception:
564
657
  logging.exception("Failed to run post processing", exc_info=True)
565
- return investigation
658
+ return investigation, 0.0
566
659
 
567
660
  @sentry_sdk.trace
568
661
  def truncate_messages_to_fit_context(
@@ -602,6 +695,7 @@ class ToolCallingLLM:
602
695
  perf_timing.measure("get_all_tools_openai_format")
603
696
  max_steps = self.max_steps
604
697
  i = 0
698
+ tool_number_offset = 0
605
699
 
606
700
  while i < max_steps:
607
701
  i += 1
@@ -634,6 +728,10 @@ class ToolCallingLLM:
634
728
  stream=False,
635
729
  drop_params=True,
636
730
  )
731
+
732
+ # Log cost information for this iteration (no accumulation in streaming)
733
+ _process_cost_info(full_response, log_prefix="LLM iteration")
734
+
637
735
  perf_timing.measure("llm.completion")
638
736
  # catch a known error that occurs with Azure and replace the error message with something more obvious to the user
639
737
  except BadRequestError as e:
@@ -695,7 +793,7 @@ class ToolCallingLLM:
695
793
  tool_to_call=t, # type: ignore
696
794
  previous_tool_calls=tool_calls,
697
795
  trace_span=DummySpan(), # Streaming mode doesn't support tracing yet
698
- tool_number=tool_index,
796
+ tool_number=tool_number_offset + tool_index,
699
797
  )
700
798
  )
701
799
  yield StreamMessage(
@@ -716,6 +814,9 @@ class ToolCallingLLM:
716
814
  data=tool_call_result.as_streaming_tool_result_response(),
717
815
  )
718
816
 
817
+ # Update the tool number offset for the next iteration
818
+ tool_number_offset += len(tools_to_call)
819
+
719
820
  raise Exception(
720
821
  f"Too many LLM calls - exceeded max_steps: {i}/{self.max_steps}"
721
822
  )
@@ -266,11 +266,7 @@ class ToolsetManager:
266
266
  toolset.path = cached_status.get("path", None)
267
267
  # check prerequisites for only enabled toolset when the toolset is loaded from cache. When the toolset is
268
268
  # not loaded from cache, the prerequisites are checked in the refresh_toolset_status method.
269
- if (
270
- toolset.enabled
271
- and toolset.status == ToolsetStatusEnum.ENABLED
272
- and using_cached
273
- ):
269
+ if toolset.enabled and toolset.status == ToolsetStatusEnum.ENABLED:
274
270
  enabled_toolsets_from_cache.append(toolset)
275
271
  self.check_toolset_prerequisites(enabled_toolsets_from_cache)
276
272
 
@@ -120,7 +120,7 @@ class DummySpan:
120
120
  class DummyTracer:
121
121
  """A no-op tracer implementation for when tracing is disabled."""
122
122
 
123
- def start_experiment(self, experiment_name=None, metadata=None):
123
+ def start_experiment(self, experiment_name=None, additional_metadata=None):
124
124
  """No-op experiment creation."""
125
125
  return None
126
126
 
@@ -104,6 +104,11 @@ opt_verbose: Optional[List[bool]] = typer.Option(
104
104
  "-v",
105
105
  help="Verbose output. You can pass multiple times to increase the verbosity. e.g. -v or -vv or -vvv",
106
106
  )
107
+ opt_log_costs: bool = typer.Option(
108
+ False,
109
+ "--log-costs",
110
+ help="Show LLM cost information in the output",
111
+ )
107
112
  opt_echo_request: bool = typer.Option(
108
113
  True,
109
114
  "--echo/--no-echo",
@@ -176,6 +181,7 @@ def ask(
176
181
  custom_toolsets: Optional[List[Path]] = opt_custom_toolsets,
177
182
  max_steps: Optional[int] = opt_max_steps,
178
183
  verbose: Optional[List[bool]] = opt_verbose,
184
+ log_costs: bool = opt_log_costs,
179
185
  # semi-common options
180
186
  destination: Optional[DestinationType] = opt_destination,
181
187
  slack_token: Optional[str] = opt_slack_token,
@@ -219,7 +225,7 @@ def ask(
219
225
  """
220
226
  Ask any question and answer using available tools
221
227
  """
222
- console = init_logging(verbose) # type: ignore
228
+ console = init_logging(verbose, log_costs) # type: ignore
223
229
  # Detect and read piped input
224
230
  piped_data = None
225
231
 
@@ -4,6 +4,7 @@
4
4
  {%- set k8s_yaml_ts = toolsets | selectattr("name", "equalto", "kubernetes/logs") | rejectattr("fetch_pod_logs", "defined") | first -%}
5
5
  {%- set opensearch_ts = toolsets | selectattr("name", "equalto", "opensearch/logs") | first -%}
6
6
  {%- set datadog_ts = toolsets | selectattr("name", "equalto", "datadog/logs") | first -%}
7
+ {%- set bash_ts = toolsets | selectattr("name", "equalto", "bash") | first -%}
7
8
 
8
9
  ## Logs
9
10
 
@@ -44,6 +45,9 @@ Tools to search and fetch logs from Kubernetes.
44
45
  * Check both kubectl_logs and kubectl_previous_logs because a pod restart mean kubectl_logs may not have relevant logs
45
46
  {%- elif opensearch_ts and opensearch_ts.status == "enabled" -%}
46
47
  {% include '_default_log_prompt.jinja2' %}
48
+ {%- elif bash_ts and bash_ts.status == "enabled" -%}
49
+ Use the tool `run_bash_command` to run `kubectl logs` commands and fetch any relevant pod logs.
50
+ DO NOT use `--tail` or `| tail` when calling `kubectl logs` because you may miss critical information.
47
51
  {%- else -%}
48
52
  * You have not been given access to tools to fetch kubernetes logs for nodes, pods, services or apps. This is likely a misconfiguration.
49
53
  * If you need logs to answer questions or investigate issues, tell the user to configure the documentation and enable one of these toolsets:
@@ -0,0 +1,85 @@
1
+ You are an expert in automated diagnostics and runbook creation for an AI-driven troubleshooting agents. I will provide you with one or more issue descriptions or test scenarios.
2
+
3
+ Your task is to generate a strictly executable runbook for AI Agent to follow. The runbook should be machine-readable but human-understandable, and must include the following sections:
4
+
5
+ # Runbook Content Structure
6
+
7
+ ## 1. Goal
8
+ - **Primary Objective:** Clearly define the specific category of issues this runbook addresses (e.g., "diagnose network connectivity problems", "troubleshoot pod startup failures", "investigate performance degradation").
9
+ - **Scope:** Specify the environment, technology stack, or system components covered by this runbook.
10
+ - **Agent Mandate:** Explicitly state that the AI agent must follow the workflow steps sequentially and systematically without deviation to ensure consistent, thorough troubleshooting.
11
+ - **Expected Outcome:** Define what successful completion of this runbook should achieve (root cause identification, issue resolution, or escalation criteria).
12
+
13
+ ## 2. Workflow for [Issue Category] Diagnosis
14
+ - Provide numbered, sequential steps the AI agent must execute in order.
15
+ - Each step should specify:
16
+ - **Action:** Describe the diagnostic function conceptually (e.g., "retrieve container logs from specified pod", "check service connectivity between components", "examine resource utilization metrics")
17
+ - **Function Description:** Explain what the function should accomplish rather than naming specific tools (e.g., "query the cluster to list all pods in a namespace and their current status" instead of "kubectl_get_pods()")
18
+ - **Parameters:** What data/arguments to pass to the function (namespace, pod name, time range, etc.)
19
+ - **Expected Output:** What information to gather from the result (status codes, error messages, metrics, configurations)
20
+ - **Success/Failure Criteria:** How to interpret the output and what indicates normal vs. problematic conditions
21
+ - Use conditional logic (IF/ELSE) when branching is required based on findings.
22
+ - Describe functions generically so they can be mapped to available tools (e.g., "execute a command to test network connectivity" rather than "ping_host()")
23
+ - Include verification steps to confirm each diagnostic action was successful.
24
+
25
+ ## 3. Synthesize Findings
26
+ - **Data Correlation:** Describe how the AI agent should combine outputs from multiple workflow steps.
27
+ - **Pattern Recognition:** Specify what patterns, error messages, or metrics indicate specific root causes.
28
+ - **Prioritization Logic:** Provide criteria for ranking potential causes by likelihood or severity.
29
+ - **Evidence Requirements:** Define what evidence is needed to confidently identify each potential root cause.
30
+ - **Example Scenarios:** Include sample synthesis statements showing how findings should be summarized.
31
+
32
+ ## 4. Recommended Remediation Steps
33
+ - **Immediate Actions:** List temporary workarounds or urgent fixes for critical issues.
34
+ - **Permanent Solutions:** Provide step-by-step permanent remediation procedures.
35
+ - **Verification Steps:** Define how to confirm each remediation action was successful.
36
+ - **Documentation References:** Include links to official documentation, best practices, or vendor guidance.
37
+ - **Escalation Criteria:** Specify when and how to escalate if remediation steps fail.
38
+ - **Post-Remediation Monitoring:** Describe what to monitor to prevent recurrence.
39
+
40
+ # File Organization Guidelines
41
+
42
+ ## Folder Structure
43
+ *Category folders are used to distinguish and categorize different runbooks based on their focus area or technology domain. Each runbook must be placed into a specific category folder under `holmes/plugins/runbooks/` for better organization and discoverability. Create a new category folder if your runbook doesn't fit into existing categories.*
44
+
45
+ ## File Naming
46
+ *Use consistent naming conventions for runbook files:*
47
+
48
+ - Use descriptive, lowercase names with hyphens: `dns-resolution-troubleshooting.md`
49
+ - Include the issue type or technology: `redis-connection-issues.md`
50
+ - Avoid generic names like `troubleshooting.md` or `debug.md`
51
+
52
+ ### Catalog Registration
53
+ After creating your runbook, you must add an entry to `catalog.json` in the runbooks directory to make it discoverable by AI agents.
54
+
55
+ **Steps to add a new catalog entry:**
56
+
57
+ 1. **Open** `holmes/plugins/runbooks/catalog.json`
58
+ 2. **Add your entry** to the JSON array following this structure:
59
+ ```json
60
+ {
61
+ "name": "Brief, descriptive name of the runbook",
62
+ "path": "category-folder/your-runbook-filename.md",
63
+ "description": "Clear description of what issues this runbook addresses",
64
+ "tags": ["relevant", "tags", "for", "search"]
65
+ }
66
+ ```
67
+
68
+ 3. **Ensure proper JSON formatting** - add a comma after the previous entry if needed
69
+ 4. **Validate the JSON** is properly formatted before committing
70
+
71
+ **Field Guidelines:**
72
+ - `name`: Keep concise but descriptive (e.g., "Redis Connection Issues")
73
+ - `path`: Always include the category folder (e.g., "database/redis-connection-issues.md")
74
+ - `description`: Explain what specific problems this runbook solves
75
+ - `tags`: Include technology names, issue types, and relevant keywords
76
+
77
+ Example catalog entry:
78
+ ```json
79
+ {
80
+ "name": "DNS Resolution Troubleshooting",
81
+ "path": "networking/dns-resolution-troubleshooting.md",
82
+ "description": "Comprehensive guide for diagnosing and resolving DNS resolution issues in Kubernetes clusters",
83
+ "tags": ["dns", "networking", "kubernetes", "troubleshooting"]
84
+ }
85
+ ```
@@ -0,0 +1,46 @@
1
+ # Runbooks
2
+
3
+ Runbooks folder contains operational runbooks for the HolmesGPT project. Runbooks provide step-by-step instructions for common tasks, troubleshooting, and maintenance procedures related to the plugins in this directory.
4
+
5
+ ## Purpose
6
+
7
+ - Standardize operational processes
8
+ - Enable quick onboarding for new team members
9
+ - Reduce downtime by providing clear troubleshooting steps
10
+
11
+ ## Structure
12
+
13
+ ### Structured Runbook
14
+
15
+ Structured runbooks are designed for specific issues when conditions like issue name, id or source match, the corresponding instructions will be returned for investigation.
16
+ For example, the investigation in [kube-prometheus-stack.yaml](kube-prometheus-stack.yaml) will be returned when the issue to be investigated match either KubeSchedulerDown or KubeControllerManagerDown.
17
+ This runbook is mainly used for `holmes investigate`
18
+
19
+ ### Catalog
20
+
21
+ Catalog specified in [catalog.json](catalog.json) contains a collection of runbooks written in markdown.
22
+ During runtime, LLM will compare the runbook description with the user question and return the most matched runbook for investigation. It's possible no runbook is returned for no match.
23
+
24
+ ## Generating Runbooks
25
+
26
+ To ensure all runbooks follow a consistent format and improve troubleshooting accuracy, contributors should use the standardized [runbook format prompt](runbook-format.prompt.md) when creating new runbooks.
27
+
28
+ ### Using the Runbook Format Prompt
29
+
30
+ 1. **Start with the Template**: Use `prompt.md` as your guide when creating new runbooks
31
+ 2. **Follow the Structure**: Ensure your runbook includes all required sections:
32
+ - **Goal**: Clear definition of issues addressed and agent mandate
33
+ - **Workflow**: Sequential diagnostic steps with detailed function descriptions
34
+ - **Synthesize Findings**: Logic for combining outputs and identifying root causes
35
+ - **Recommended Remediation Steps**: Both immediate and permanent solutions
36
+
37
+ ### Benefits of Using the Standard Format
38
+
39
+ - **Consistency**: All runbooks follow the same structure and terminology
40
+ - **AI Agent Compatibility**: Ensures runbooks are machine-readable and executable by AI agents
41
+ - **Improved Accuracy**: Standardized format reduces ambiguity and improves diagnostic success rates
42
+ - **Maintainability**: Easier to update and maintain runbooks across the project
43
+
44
+ ### Example Usage
45
+
46
+ When creating a runbook for a new issue category (e.g., storage problems, authentication failures), provide the issue description to an LLM along with the prompt template to generate a properly formatted runbook that follows the established patterns.
@@ -0,0 +1,65 @@
1
+ import argparse
2
+ from typing import Any, Optional
3
+
4
+ from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
5
+ from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
6
+ from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
7
+ from holmes.plugins.toolsets.bash.argocd.constants import (
8
+ ALLOWED_ARGOCD_COMMANDS,
9
+ DENIED_ARGOCD_COMMANDS,
10
+ )
11
+ from holmes.plugins.toolsets.bash.common.validators import (
12
+ validate_command_and_operations,
13
+ )
14
+
15
+
16
+ class ArgocdCommand(BashCommand):
17
+ def __init__(self):
18
+ super().__init__("argocd")
19
+
20
+ def add_parser(self, parent_parser: Any):
21
+ """Create Argo CD CLI parser with safe command validation."""
22
+ argocd_parser = parent_parser.add_parser(
23
+ "argocd", help="Argo CD Command Line Interface", exit_on_error=False
24
+ )
25
+
26
+ # Add command subparser
27
+ argocd_parser.add_argument(
28
+ "command", help="Argo CD command (e.g., app, cluster, proj, repo)"
29
+ )
30
+
31
+ # Capture remaining arguments
32
+ argocd_parser.add_argument(
33
+ "options",
34
+ nargs=argparse.REMAINDER,
35
+ default=[],
36
+ help="Argo CD CLI subcommands, operations, and options",
37
+ )
38
+ return argocd_parser
39
+
40
+ def validate_command(
41
+ self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
42
+ ) -> None:
43
+ if hasattr(command, "options"):
44
+ validate_command_and_operations(
45
+ command.command,
46
+ command.options,
47
+ ALLOWED_ARGOCD_COMMANDS,
48
+ DENIED_ARGOCD_COMMANDS,
49
+ )
50
+
51
+ def stringify_command(
52
+ self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
53
+ ) -> str:
54
+ """Convert parsed Argo CD command back to safe command string."""
55
+ parts = ["argocd", command.command]
56
+
57
+ if hasattr(command, "options") and command.options:
58
+ parts.extend(command.options)
59
+
60
+ return " ".join(escape_shell_args(parts))
61
+
62
+
63
+ def create_argocd_parser(parent_parser: Any):
64
+ argocd_command = ArgocdCommand()
65
+ return argocd_command.add_parser(parent_parser)
@@ -0,0 +1,120 @@
1
+ ALLOWED_ARGOCD_COMMANDS: dict[str, dict] = {
2
+ # Application management (read-only)
3
+ "app": {
4
+ "list": {},
5
+ "get": {},
6
+ "resources": {},
7
+ "diff": {},
8
+ "history": {},
9
+ "manifests": {},
10
+ "logs": {},
11
+ "wait": {}, # Wait for app to reach desired state (read-only monitoring)
12
+ },
13
+ # Cluster management (read-only)
14
+ "cluster": {
15
+ "list": {},
16
+ "get": {},
17
+ },
18
+ # Project management (read-only)
19
+ "proj": {
20
+ "list": {},
21
+ "get": {},
22
+ },
23
+ # Repository management (read-only)
24
+ "repo": {
25
+ "list": {},
26
+ "get": {},
27
+ },
28
+ # Context management (read-only operations)
29
+ "context": {},
30
+ # Version information (completely safe)
31
+ "version": {},
32
+ # Account information (read-only)
33
+ "account": {
34
+ "list": {},
35
+ "get": {},
36
+ "get-user-info": {},
37
+ "can-i": {},
38
+ },
39
+ # Administrative commands (limited read-only)
40
+ "admin": {
41
+ "dashboard": {}, # Starts read-only web UI
42
+ "settings": {}, # Shows/validates settings (read-only)
43
+ },
44
+ }
45
+
46
+ DENIED_ARGOCD_COMMANDS: dict[str, dict] = {
47
+ # Authentication operations (sensitive)
48
+ "login": {},
49
+ "logout": {},
50
+ "relogin": {},
51
+ # Application lifecycle operations (state-modifying)
52
+ "app": {
53
+ "create": {},
54
+ "delete": {},
55
+ "sync": {},
56
+ "rollback": {},
57
+ "edit": {},
58
+ "set": {},
59
+ "unset": {},
60
+ "patch": {},
61
+ "delete-resource": {},
62
+ "terminate-op": {},
63
+ "actions": {}, # Custom resource actions
64
+ },
65
+ # Account management (sensitive)
66
+ "account": {
67
+ "generate-token": {},
68
+ "delete-token": {},
69
+ "update-password": {},
70
+ "bcrypt": {},
71
+ },
72
+ # Cluster management (state-modifying)
73
+ "cluster": {
74
+ "add": {},
75
+ "rm": {},
76
+ "set": {},
77
+ "rotate-auth": {},
78
+ },
79
+ # Project management (state-modifying)
80
+ "proj": {
81
+ "create": {},
82
+ "delete": {},
83
+ "edit": {},
84
+ "add-source": {},
85
+ "remove-source": {},
86
+ "add-destination": {},
87
+ "remove-destination": {},
88
+ "add-cluster-resource-whitelist": {},
89
+ "remove-cluster-resource-whitelist": {},
90
+ "add-namespace-resource-blacklist": {},
91
+ "remove-namespace-resource-blacklist": {},
92
+ "add-cluster-resource-blacklist": {},
93
+ "remove-cluster-resource-blacklist": {},
94
+ "add-namespace-resource-whitelist": {},
95
+ "remove-namespace-resource-whitelist": {},
96
+ "add-orphaned-ignore": {},
97
+ "remove-orphaned-ignore": {},
98
+ "add-signature-key": {},
99
+ "remove-signature-key": {},
100
+ "set-orphaned-ignore": {},
101
+ "add-role": {},
102
+ "remove-role": {},
103
+ "add-role-token": {},
104
+ "delete-role-token": {},
105
+ "set-role": {},
106
+ },
107
+ # Repository management (state-modifying)
108
+ "repo": {
109
+ "add": {},
110
+ "rm": {},
111
+ },
112
+ # Certificate management
113
+ "cert": {},
114
+ # GPG key management
115
+ "gpg": {},
116
+ # Application set operations
117
+ "appset": {},
118
+ # Notification operations
119
+ "notifications": {},
120
+ }