holmesgpt 0.16.2a0__py3-none-any.whl → 0.18.4__py3-none-any.whl

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 (162) hide show
  1. holmes/__init__.py +3 -5
  2. holmes/clients/robusta_client.py +4 -3
  3. holmes/common/env_vars.py +18 -2
  4. holmes/common/openshift.py +1 -1
  5. holmes/config.py +11 -6
  6. holmes/core/conversations.py +30 -13
  7. holmes/core/investigation.py +21 -25
  8. holmes/core/investigation_structured_output.py +3 -3
  9. holmes/core/issue.py +1 -1
  10. holmes/core/llm.py +50 -31
  11. holmes/core/models.py +19 -17
  12. holmes/core/openai_formatting.py +1 -1
  13. holmes/core/prompt.py +47 -2
  14. holmes/core/runbooks.py +1 -0
  15. holmes/core/safeguards.py +4 -2
  16. holmes/core/supabase_dal.py +4 -2
  17. holmes/core/tool_calling_llm.py +102 -141
  18. holmes/core/tools.py +19 -28
  19. holmes/core/tools_utils/token_counting.py +9 -2
  20. holmes/core/tools_utils/tool_context_window_limiter.py +13 -30
  21. holmes/core/tools_utils/tool_executor.py +0 -18
  22. holmes/core/tools_utils/toolset_utils.py +1 -0
  23. holmes/core/toolset_manager.py +37 -2
  24. holmes/core/tracing.py +13 -2
  25. holmes/core/transformers/__init__.py +1 -1
  26. holmes/core/transformers/base.py +1 -0
  27. holmes/core/transformers/llm_summarize.py +3 -2
  28. holmes/core/transformers/registry.py +2 -1
  29. holmes/core/transformers/transformer.py +1 -0
  30. holmes/core/truncation/compaction.py +37 -2
  31. holmes/core/truncation/input_context_window_limiter.py +3 -2
  32. holmes/interactive.py +52 -8
  33. holmes/main.py +17 -37
  34. holmes/plugins/interfaces.py +2 -1
  35. holmes/plugins/prompts/__init__.py +2 -1
  36. holmes/plugins/prompts/_fetch_logs.jinja2 +5 -5
  37. holmes/plugins/prompts/_runbook_instructions.jinja2 +2 -1
  38. holmes/plugins/prompts/base_user_prompt.jinja2 +7 -0
  39. holmes/plugins/prompts/conversation_history_compaction.jinja2 +2 -1
  40. holmes/plugins/prompts/generic_ask.jinja2 +0 -2
  41. holmes/plugins/prompts/generic_ask_conversation.jinja2 +0 -2
  42. holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +0 -2
  43. holmes/plugins/prompts/generic_investigation.jinja2 +0 -2
  44. holmes/plugins/prompts/investigation_procedure.jinja2 +2 -1
  45. holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +0 -2
  46. holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +0 -2
  47. holmes/plugins/runbooks/__init__.py +32 -3
  48. holmes/plugins/sources/github/__init__.py +4 -2
  49. holmes/plugins/sources/prometheus/models.py +1 -0
  50. holmes/plugins/toolsets/__init__.py +30 -26
  51. holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +13 -12
  52. holmes/plugins/toolsets/azure_sql/apis/alert_monitoring_api.py +3 -2
  53. holmes/plugins/toolsets/azure_sql/apis/azure_sql_api.py +2 -1
  54. holmes/plugins/toolsets/azure_sql/apis/connection_failure_api.py +3 -2
  55. holmes/plugins/toolsets/azure_sql/apis/connection_monitoring_api.py +3 -1
  56. holmes/plugins/toolsets/azure_sql/apis/storage_analysis_api.py +3 -1
  57. holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +12 -12
  58. holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +7 -7
  59. holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +7 -7
  60. holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +3 -5
  61. holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +3 -3
  62. holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +7 -7
  63. holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +6 -8
  64. holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +3 -3
  65. holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +3 -3
  66. holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +3 -3
  67. holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +3 -3
  68. holmes/plugins/toolsets/azure_sql/utils.py +0 -32
  69. holmes/plugins/toolsets/bash/argocd/__init__.py +3 -3
  70. holmes/plugins/toolsets/bash/aws/__init__.py +4 -4
  71. holmes/plugins/toolsets/bash/azure/__init__.py +4 -4
  72. holmes/plugins/toolsets/bash/bash_toolset.py +2 -3
  73. holmes/plugins/toolsets/bash/common/bash.py +19 -9
  74. holmes/plugins/toolsets/bash/common/bash_command.py +1 -1
  75. holmes/plugins/toolsets/bash/common/stringify.py +1 -1
  76. holmes/plugins/toolsets/bash/kubectl/__init__.py +2 -1
  77. holmes/plugins/toolsets/bash/kubectl/constants.py +0 -1
  78. holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +3 -4
  79. holmes/plugins/toolsets/bash/parse_command.py +12 -13
  80. holmes/plugins/toolsets/connectivity_check.py +124 -0
  81. holmes/plugins/toolsets/coralogix/api.py +132 -119
  82. holmes/plugins/toolsets/coralogix/coralogix.jinja2 +14 -0
  83. holmes/plugins/toolsets/coralogix/toolset_coralogix.py +219 -0
  84. holmes/plugins/toolsets/coralogix/utils.py +15 -79
  85. holmes/plugins/toolsets/datadog/datadog_api.py +36 -3
  86. holmes/plugins/toolsets/datadog/datadog_logs_instructions.jinja2 +34 -1
  87. holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +3 -3
  88. holmes/plugins/toolsets/datadog/datadog_models.py +59 -0
  89. holmes/plugins/toolsets/datadog/datadog_url_utils.py +213 -0
  90. holmes/plugins/toolsets/datadog/instructions_datadog_traces.jinja2 +165 -28
  91. holmes/plugins/toolsets/datadog/toolset_datadog_general.py +71 -28
  92. holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +224 -375
  93. holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +67 -36
  94. holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +360 -343
  95. holmes/plugins/toolsets/elasticsearch/__init__.py +6 -0
  96. holmes/plugins/toolsets/elasticsearch/elasticsearch.py +834 -0
  97. holmes/plugins/toolsets/git.py +7 -8
  98. holmes/plugins/toolsets/grafana/base_grafana_toolset.py +16 -4
  99. holmes/plugins/toolsets/grafana/common.py +2 -30
  100. holmes/plugins/toolsets/grafana/grafana_tempo_api.py +2 -1
  101. holmes/plugins/toolsets/grafana/loki/instructions.jinja2 +18 -2
  102. holmes/plugins/toolsets/grafana/loki/toolset_grafana_loki.py +92 -18
  103. holmes/plugins/toolsets/grafana/loki_api.py +4 -0
  104. holmes/plugins/toolsets/grafana/toolset_grafana.py +109 -25
  105. holmes/plugins/toolsets/grafana/toolset_grafana_dashboard.jinja2 +22 -0
  106. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +201 -33
  107. holmes/plugins/toolsets/grafana/trace_parser.py +3 -2
  108. holmes/plugins/toolsets/internet/internet.py +10 -10
  109. holmes/plugins/toolsets/internet/notion.py +5 -6
  110. holmes/plugins/toolsets/investigator/core_investigation.py +3 -3
  111. holmes/plugins/toolsets/investigator/model.py +3 -1
  112. holmes/plugins/toolsets/json_filter_mixin.py +134 -0
  113. holmes/plugins/toolsets/kafka.py +12 -7
  114. holmes/plugins/toolsets/kubernetes.yaml +260 -30
  115. holmes/plugins/toolsets/kubernetes_logs.py +3 -3
  116. holmes/plugins/toolsets/logging_utils/logging_api.py +16 -6
  117. holmes/plugins/toolsets/mcp/toolset_mcp.py +88 -60
  118. holmes/plugins/toolsets/newrelic/new_relic_api.py +41 -1
  119. holmes/plugins/toolsets/newrelic/newrelic.jinja2 +24 -0
  120. holmes/plugins/toolsets/newrelic/newrelic.py +212 -55
  121. holmes/plugins/toolsets/prometheus/prometheus.py +358 -102
  122. holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +11 -3
  123. holmes/plugins/toolsets/rabbitmq/api.py +23 -4
  124. holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +5 -5
  125. holmes/plugins/toolsets/robusta/robusta.py +5 -5
  126. holmes/plugins/toolsets/runbook/runbook_fetcher.py +25 -6
  127. holmes/plugins/toolsets/servicenow_tables/servicenow_tables.py +1 -1
  128. holmes/plugins/toolsets/utils.py +1 -1
  129. holmes/utils/config_utils.py +1 -1
  130. holmes/utils/connection_utils.py +31 -0
  131. holmes/utils/console/result.py +10 -0
  132. holmes/utils/file_utils.py +2 -1
  133. holmes/utils/global_instructions.py +10 -26
  134. holmes/utils/holmes_status.py +4 -3
  135. holmes/utils/log.py +15 -0
  136. holmes/utils/markdown_utils.py +2 -3
  137. holmes/utils/memory_limit.py +58 -0
  138. holmes/utils/sentry_helper.py +23 -0
  139. holmes/utils/stream.py +12 -5
  140. holmes/utils/tags.py +4 -3
  141. holmes/version.py +3 -1
  142. {holmesgpt-0.16.2a0.dist-info → holmesgpt-0.18.4.dist-info}/METADATA +12 -10
  143. holmesgpt-0.18.4.dist-info/RECORD +258 -0
  144. holmes/plugins/toolsets/aws.yaml +0 -80
  145. holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +0 -114
  146. holmes/plugins/toolsets/datadog/datadog_traces_formatter.py +0 -310
  147. holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +0 -736
  148. holmes/plugins/toolsets/grafana/grafana_api.py +0 -64
  149. holmes/plugins/toolsets/opensearch/__init__.py +0 -0
  150. holmes/plugins/toolsets/opensearch/opensearch.py +0 -250
  151. holmes/plugins/toolsets/opensearch/opensearch_logs.py +0 -161
  152. holmes/plugins/toolsets/opensearch/opensearch_traces.py +0 -215
  153. holmes/plugins/toolsets/opensearch/opensearch_traces_instructions.jinja2 +0 -12
  154. holmes/plugins/toolsets/opensearch/opensearch_utils.py +0 -166
  155. holmes/utils/keygen_utils.py +0 -6
  156. holmesgpt-0.16.2a0.dist-info/RECORD +0 -258
  157. holmes/plugins/toolsets/{opensearch → elasticsearch}/opensearch_ppl_query_docs.jinja2 +0 -0
  158. holmes/plugins/toolsets/{opensearch → elasticsearch}/opensearch_query_assist.py +2 -2
  159. /holmes/plugins/toolsets/{opensearch → elasticsearch}/opensearch_query_assist_instructions.jinja2 +0 -0
  160. {holmesgpt-0.16.2a0.dist-info → holmesgpt-0.18.4.dist-info}/LICENSE +0 -0
  161. {holmesgpt-0.16.2a0.dist-info → holmesgpt-0.18.4.dist-info}/WHEEL +0 -0
  162. {holmesgpt-0.16.2a0.dist-info → holmesgpt-0.18.4.dist-info}/entry_points.txt +0 -0
@@ -5,34 +5,37 @@ import logging
5
5
  import os
6
6
  import re
7
7
  from typing import Any, Dict, Optional, Tuple
8
- from urllib.parse import urlparse
8
+ from urllib.parse import urlencode, urlparse
9
9
 
10
10
  from holmes.core.tools import (
11
11
  CallablePrerequisite,
12
+ StructuredToolResult,
13
+ StructuredToolResultStatus,
12
14
  Tool,
13
15
  ToolInvokeContext,
14
16
  ToolParameter,
15
17
  Toolset,
16
- StructuredToolResult,
17
- StructuredToolResultStatus,
18
18
  ToolsetTag,
19
19
  )
20
20
  from holmes.plugins.toolsets.consts import TOOLSET_CONFIG_MISSING_ERROR
21
21
  from holmes.plugins.toolsets.datadog.datadog_api import (
22
- DatadogBaseConfig,
22
+ MAX_RETRY_COUNT_ON_RATE_LIMIT,
23
23
  DataDogRequestError,
24
+ enhance_error_message,
24
25
  execute_datadog_http_request,
26
+ fetch_openapi_spec,
25
27
  get_headers,
26
- MAX_RETRY_COUNT_ON_RATE_LIMIT,
27
28
  preprocess_time_fields,
28
- enhance_error_message,
29
- fetch_openapi_spec,
29
+ )
30
+ from holmes.plugins.toolsets.datadog.datadog_models import (
31
+ MAX_RESPONSE_SIZE,
32
+ DatadogGeneralConfig,
33
+ )
34
+ from holmes.plugins.toolsets.datadog.datadog_url_utils import (
35
+ generate_datadog_general_url,
30
36
  )
31
37
  from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
32
38
 
33
- # Maximum response size in bytes (10MB)
34
- MAX_RESPONSE_SIZE = 10 * 1024 * 1024
35
-
36
39
  # Whitelisted API endpoint patterns with optional hints
37
40
  # Format: (pattern, hint) - hint is empty string if no special instructions
38
41
  WHITELISTED_ENDPOINTS = [
@@ -192,15 +195,6 @@ WHITELISTED_POST_ENDPOINTS = [
192
195
  ]
193
196
 
194
197
 
195
- class DatadogGeneralConfig(DatadogBaseConfig):
196
- """Configuration for general-purpose Datadog toolset."""
197
-
198
- max_response_size: int = MAX_RESPONSE_SIZE
199
- allow_custom_endpoints: bool = (
200
- False # If True, allows endpoints not in whitelist (still filtered for safety)
201
- )
202
-
203
-
204
198
  class DatadogGeneralToolset(Toolset):
205
199
  """General-purpose Datadog API toolset for read-only operations not covered by specialized toolsets."""
206
200
 
@@ -402,20 +396,22 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
402
396
 
403
397
  def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
404
398
  """Execute the GET request."""
399
+ params_return = params.copy()
400
+ params_return["query_params"] = json.dumps(
401
+ params.get("query_params", {}), indent=2
402
+ )
405
403
  logging.info("=" * 60)
406
404
  logging.info("DatadogAPIGet Tool Invocation:")
407
405
  logging.info(f" Description: {params.get('description', 'No description')}")
408
406
  logging.info(f" Endpoint: {params.get('endpoint', '')}")
409
- logging.info(
410
- f" Query Params: {json.dumps(params.get('query_params', {}), indent=2)}"
411
- )
407
+ logging.info(f" Query Params: {params_return['query_params']}")
412
408
  logging.info("=" * 60)
413
409
 
414
410
  if not self.toolset.dd_config:
415
411
  return StructuredToolResult(
416
412
  status=StructuredToolResultStatus.ERROR,
417
413
  error=TOOLSET_CONFIG_MISSING_ERROR,
418
- params=params,
414
+ params=params_return,
419
415
  )
420
416
 
421
417
  endpoint = params.get("endpoint", "")
@@ -432,7 +428,7 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
432
428
  return StructuredToolResult(
433
429
  status=StructuredToolResultStatus.ERROR,
434
430
  error=f"Endpoint validation failed: {error_msg}",
435
- params=params,
431
+ params=params_return,
436
432
  )
437
433
 
438
434
  url = None
@@ -466,13 +462,20 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
466
462
  return StructuredToolResult(
467
463
  status=StructuredToolResultStatus.ERROR,
468
464
  error=f"Response too large (>{self.toolset.dd_config.max_response_size} bytes)",
469
- params=params,
465
+ params=params_return,
470
466
  )
471
467
 
468
+ web_url = generate_datadog_general_url(
469
+ self.toolset.dd_config,
470
+ endpoint,
471
+ query_params,
472
+ )
473
+
472
474
  return StructuredToolResult(
473
475
  status=StructuredToolResultStatus.SUCCESS,
474
476
  data=response_str,
475
- params=params,
477
+ params=params_return,
478
+ url=web_url,
476
479
  )
477
480
 
478
481
  except DataDogRequestError as e:
@@ -497,7 +500,7 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
497
500
  return StructuredToolResult(
498
501
  status=StructuredToolResultStatus.ERROR,
499
502
  error=error_msg,
500
- params=params,
503
+ params=params_return,
501
504
  invocation=json.dumps({"url": url, "params": query_params})
502
505
  if url
503
506
  else None,
@@ -508,7 +511,7 @@ class DatadogAPIGet(BaseDatadogGeneralTool):
508
511
  return StructuredToolResult(
509
512
  status=StructuredToolResultStatus.ERROR,
510
513
  error=f"Unexpected error: {str(e)}",
511
- params=params,
514
+ params=params_return,
512
515
  )
513
516
 
514
517
 
@@ -566,6 +569,31 @@ class DatadogAPIPostSearch(BaseDatadogGeneralTool):
566
569
  description = params.get("description", "Search")
567
570
  return f"{toolset_name_for_one_liner(self.toolset.name)}: {description}"
568
571
 
572
+ def _body_to_query_params(self, body: dict) -> Optional[Dict[str, Any]]:
573
+ body_query_params = {}
574
+ if not isinstance(body, dict):
575
+ return None
576
+ if "filter" not in body:
577
+ return None
578
+ filter_data = body["filter"]
579
+ if "from" in filter_data:
580
+ try:
581
+ body_query_params["from"] = int(filter_data["from"]) // 1000
582
+ except (ValueError, TypeError):
583
+ pass
584
+ if "to" in filter_data:
585
+ try:
586
+ body_query_params["to"] = int(filter_data["to"]) // 1000
587
+ except (ValueError, TypeError):
588
+ pass
589
+ if "query" in filter_data:
590
+ body_query_params["query"] = filter_data["query"]
591
+
592
+ if not body_query_params:
593
+ return None
594
+
595
+ return body_query_params
596
+
569
597
  def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
570
598
  """Execute the POST search request."""
571
599
  logging.info("=" * 60)
@@ -633,10 +661,18 @@ class DatadogAPIPostSearch(BaseDatadogGeneralTool):
633
661
  params=params,
634
662
  )
635
663
 
664
+ body_query_params = self._body_to_query_params(body)
665
+ web_url = generate_datadog_general_url(
666
+ self.toolset.dd_config,
667
+ endpoint,
668
+ body_query_params,
669
+ )
670
+
636
671
  return StructuredToolResult(
637
672
  status=StructuredToolResultStatus.SUCCESS,
638
673
  data=response_str,
639
674
  params=params,
675
+ url=web_url,
640
676
  )
641
677
 
642
678
  except DataDogRequestError as e:
@@ -717,6 +753,7 @@ class ListDatadogAPIResources(BaseDatadogGeneralTool):
717
753
  status=StructuredToolResultStatus.ERROR,
718
754
  error=f"Invalid regex pattern: {e}",
719
755
  params=params,
756
+ url="",
720
757
  )
721
758
  else:
722
759
  search_pattern = None
@@ -847,9 +884,15 @@ class ListDatadogAPIResources(BaseDatadogGeneralTool):
847
884
  output.append(" • 'logs|metrics' - find logs OR metrics endpoints")
848
885
  output.append(" • 'v2.*search$' - find all v2 search endpoints")
849
886
  output.append(" • 'security.*signals' - find security signals endpoints")
887
+ doc_url = "https://docs.datadoghq.com/api/latest/"
888
+ if search_regex:
889
+ # URL encode the search parameter - spaces become + in query strings
890
+ search_params = urlencode({"s": search_regex})
891
+ doc_url = f"{doc_url}?{search_params}"
850
892
 
851
893
  return StructuredToolResult(
852
894
  status=StructuredToolResultStatus.SUCCESS,
853
895
  data="\n".join(output),
854
896
  params=params,
897
+ url=doc_url,
855
898
  )