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
@@ -1,23 +1,21 @@
1
1
  import logging
2
- from typing import Dict
3
2
  from datetime import datetime, timezone
3
+ from typing import Dict, Tuple
4
4
 
5
5
  from holmes.core.tools import (
6
6
  StructuredToolResult,
7
7
  StructuredToolResultStatus,
8
8
  ToolInvokeContext,
9
9
  )
10
+ from holmes.plugins.toolsets.azure_sql.apis.alert_monitoring_api import (
11
+ AlertMonitoringAPI,
12
+ )
13
+ from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
10
14
  from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
15
+ AzureSQLDatabaseConfig,
11
16
  BaseAzureSQLTool,
12
17
  BaseAzureSQLToolset,
13
- AzureSQLDatabaseConfig,
14
18
  )
15
- from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
16
- from holmes.plugins.toolsets.azure_sql.apis.alert_monitoring_api import (
17
- AlertMonitoringAPI,
18
- )
19
- from typing import Tuple
20
-
21
19
  from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
22
20
 
23
21
 
@@ -3,16 +3,16 @@ from typing import Dict, List, Tuple
3
3
 
4
4
  from holmes.core.tools import (
5
5
  StructuredToolResult,
6
+ StructuredToolResultStatus,
6
7
  ToolInvokeContext,
7
8
  ToolParameter,
8
- StructuredToolResultStatus,
9
9
  )
10
+ from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
10
11
  from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
12
+ AzureSQLDatabaseConfig,
11
13
  BaseAzureSQLTool,
12
14
  BaseAzureSQLToolset,
13
- AzureSQLDatabaseConfig,
14
15
  )
15
- from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
16
16
  from holmes.plugins.toolsets.azure_sql.utils import format_timing
17
17
  from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
18
18
 
@@ -3,16 +3,16 @@ from typing import Dict, List, Tuple
3
3
 
4
4
  from holmes.core.tools import (
5
5
  StructuredToolResult,
6
+ StructuredToolResultStatus,
6
7
  ToolInvokeContext,
7
8
  ToolParameter,
8
- StructuredToolResultStatus,
9
9
  )
10
+ from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
10
11
  from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
12
+ AzureSQLDatabaseConfig,
11
13
  BaseAzureSQLTool,
12
14
  BaseAzureSQLToolset,
13
- AzureSQLDatabaseConfig,
14
15
  )
15
- from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
16
16
  from holmes.plugins.toolsets.azure_sql.utils import format_timing
17
17
  from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
18
18
 
@@ -3,16 +3,16 @@ from typing import Dict, List, Tuple
3
3
 
4
4
  from holmes.core.tools import (
5
5
  StructuredToolResult,
6
+ StructuredToolResultStatus,
6
7
  ToolInvokeContext,
7
8
  ToolParameter,
8
- StructuredToolResultStatus,
9
9
  )
10
+ from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
10
11
  from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
12
+ AzureSQLDatabaseConfig,
11
13
  BaseAzureSQLTool,
12
14
  BaseAzureSQLToolset,
13
- AzureSQLDatabaseConfig,
14
15
  )
15
- from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
16
16
  from holmes.plugins.toolsets.azure_sql.utils import format_timing
17
17
  from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
18
18
 
@@ -3,16 +3,16 @@ from typing import Dict, List, Tuple
3
3
 
4
4
  from holmes.core.tools import (
5
5
  StructuredToolResult,
6
+ StructuredToolResultStatus,
6
7
  ToolInvokeContext,
7
8
  ToolParameter,
8
- StructuredToolResultStatus,
9
9
  )
10
+ from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
10
11
  from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
12
+ AzureSQLDatabaseConfig,
11
13
  BaseAzureSQLTool,
12
14
  BaseAzureSQLToolset,
13
- AzureSQLDatabaseConfig,
14
15
  )
15
- from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
16
16
  from holmes.plugins.toolsets.azure_sql.utils import format_timing
17
17
  from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
18
18
 
@@ -20,38 +20,6 @@ def format_timing(microseconds: float) -> str:
20
20
  return f"{microseconds:.0f} μs"
21
21
 
22
22
 
23
- def format_size_bytes(bytes_value: float) -> str:
24
- """Format byte values with appropriate units.
25
-
26
- Args:
27
- bytes_value: Size value in bytes
28
-
29
- Returns:
30
- Formatted string with appropriate units (GB, MB, KB, or B)
31
- """
32
- if bytes_value >= 1_073_741_824: # >= 1 GB
33
- return f"{bytes_value / 1_073_741_824:.2f} GB"
34
- elif bytes_value >= 1_048_576: # >= 1 MB
35
- return f"{bytes_value / 1_048_576:.2f} MB"
36
- elif bytes_value >= 1_024: # >= 1 KB
37
- return f"{bytes_value / 1_024:.2f} KB"
38
- else: # < 1 KB
39
- return f"{bytes_value:.0f} B"
40
-
41
-
42
- def format_percentage(value: float, decimal_places: int = 2) -> str:
43
- """Format percentage values.
44
-
45
- Args:
46
- value: Percentage value (0-100)
47
- decimal_places: Number of decimal places to show
48
-
49
- Returns:
50
- Formatted percentage string
51
- """
52
- return f"{value:.{decimal_places}f}%"
53
-
54
-
55
23
  def safe_divide(numerator: float, denominator: float, default: float = 0.0) -> float:
56
24
  """Safely divide two numbers, handling division by zero.
57
25
 
@@ -1,13 +1,13 @@
1
1
  import argparse
2
2
  from typing import Any, Optional
3
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
4
  from holmes.plugins.toolsets.bash.argocd.constants import (
8
5
  ALLOWED_ARGOCD_COMMANDS,
9
6
  DENIED_ARGOCD_COMMANDS,
10
7
  )
8
+ from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
9
+ from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
10
+ from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
11
11
  from holmes.plugins.toolsets.bash.common.validators import (
12
12
  validate_command_and_operations,
13
13
  )
@@ -1,16 +1,16 @@
1
1
  import argparse
2
2
  from typing import Any, Optional
3
3
 
4
+ from holmes.plugins.toolsets.bash.aws.constants import (
5
+ ALLOWED_AWS_COMMANDS,
6
+ DENIED_AWS_COMMANDS,
7
+ )
4
8
  from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
5
9
  from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
6
10
  from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
7
11
  from holmes.plugins.toolsets.bash.common.validators import (
8
12
  validate_command_and_operations,
9
13
  )
10
- from holmes.plugins.toolsets.bash.aws.constants import (
11
- ALLOWED_AWS_COMMANDS,
12
- DENIED_AWS_COMMANDS,
13
- )
14
14
 
15
15
 
16
16
  class AWSCommand(BashCommand):
@@ -1,16 +1,16 @@
1
1
  import argparse
2
2
  from typing import Any, Optional
3
3
 
4
+ from holmes.plugins.toolsets.bash.azure.constants import (
5
+ ALLOWED_AZURE_COMMANDS,
6
+ DENIED_AZURE_COMMANDS,
7
+ )
4
8
  from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
5
9
  from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
6
10
  from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
7
11
  from holmes.plugins.toolsets.bash.common.validators import (
8
12
  validate_command_and_operations,
9
13
  )
10
- from holmes.plugins.toolsets.bash.azure.constants import (
11
- ALLOWED_AZURE_COMMANDS,
12
- DENIED_AZURE_COMMANDS,
13
- )
14
14
 
15
15
 
16
16
  class AzureCommand(BashCommand):
@@ -4,21 +4,20 @@ import os
4
4
  import random
5
5
  import re
6
6
  import string
7
- from typing import Dict, Any, Optional
7
+ from typing import Any, Dict, Optional
8
8
 
9
9
  import sentry_sdk
10
10
 
11
-
12
11
  from holmes.common.env_vars import (
13
12
  BASH_TOOL_UNSAFE_ALLOW_ALL,
14
13
  )
15
14
  from holmes.core.tools import (
16
15
  CallablePrerequisite,
17
16
  StructuredToolResult,
17
+ StructuredToolResultStatus,
18
18
  Tool,
19
19
  ToolInvokeContext,
20
20
  ToolParameter,
21
- StructuredToolResultStatus,
22
21
  Toolset,
23
22
  ToolsetTag,
24
23
  )
@@ -1,11 +1,14 @@
1
1
  import subprocess
2
+
2
3
  from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
4
+ from holmes.utils.memory_limit import check_oom_and_append_hint, get_ulimit_prefix
3
5
 
4
6
 
5
7
  def execute_bash_command(cmd: str, timeout: int, params: dict) -> StructuredToolResult:
6
8
  try:
9
+ protected_cmd = get_ulimit_prefix() + cmd
7
10
  process = subprocess.run(
8
- cmd,
11
+ protected_cmd,
9
12
  shell=True,
10
13
  executable="/bin/bash",
11
14
  stdout=subprocess.PIPE,
@@ -16,16 +19,23 @@ def execute_bash_command(cmd: str, timeout: int, params: dict) -> StructuredTool
16
19
  )
17
20
 
18
21
  stdout = process.stdout.strip() if process.stdout else ""
19
- result_data = f"{cmd}\n" f"{stdout}"
22
+ stdout = check_oom_and_append_hint(stdout, process.returncode)
23
+ result_data = f"{cmd}\n{stdout}"
20
24
 
21
- status = StructuredToolResultStatus.ERROR
22
- if process.returncode == 0 and stdout:
23
- status = StructuredToolResultStatus.SUCCESS
24
- elif not stdout:
25
- status = StructuredToolResultStatus.NO_DATA
25
+ if process.returncode == 0:
26
+ status = (
27
+ StructuredToolResultStatus.SUCCESS
28
+ if stdout
29
+ else StructuredToolResultStatus.NO_DATA
30
+ )
31
+ error = None
32
+ else:
33
+ status = StructuredToolResultStatus.ERROR
34
+ error = f'Error: Command "{cmd}" returned non-zero exit status {process.returncode}'
26
35
 
27
36
  return StructuredToolResult(
28
37
  status=status,
38
+ error=error,
29
39
  data=result_data,
30
40
  params=params,
31
41
  invocation=cmd,
@@ -38,10 +48,10 @@ def execute_bash_command(cmd: str, timeout: int, params: dict) -> StructuredTool
38
48
  params=params,
39
49
  )
40
50
  except FileNotFoundError:
41
- # This might occur if /bin/bash is not found, or if shell=False and command is not found
51
+ # This might occur if /bin/bash is not found, or command is not found
42
52
  return StructuredToolResult(
43
53
  status=StructuredToolResultStatus.ERROR,
44
- error="Error: Bash executable or command not found. Ensure bash is installed and the command is valid.",
54
+ error="Error: Bash executable or command not found.",
45
55
  params=params,
46
56
  )
47
57
  except Exception as e:
@@ -1,5 +1,5 @@
1
- from abc import ABC, abstractmethod
2
1
  import argparse
2
+ from abc import ABC, abstractmethod
3
3
  from typing import Any, Optional
4
4
 
5
5
  from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
@@ -1,5 +1,5 @@
1
- import shlex
2
1
  import re
2
+ import shlex
3
3
 
4
4
  SAFE_SHELL_CHARS = frozenset(".-_=/,:")
5
5
 
@@ -1,4 +1,5 @@
1
1
  from typing import Any, Optional
2
+
2
3
  from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
3
4
  from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
4
5
  from holmes.plugins.toolsets.bash.kubectl.constants import (
@@ -9,9 +10,9 @@ from holmes.plugins.toolsets.bash.kubectl.constants import (
9
10
  )
10
11
  from holmes.plugins.toolsets.bash.kubectl.kubectl_describe import KubectlDescribeCommand
11
12
  from holmes.plugins.toolsets.bash.kubectl.kubectl_events import KubectlEventsCommand
13
+ from holmes.plugins.toolsets.bash.kubectl.kubectl_get import KubectlGetCommand
12
14
  from holmes.plugins.toolsets.bash.kubectl.kubectl_logs import KubectlLogsCommand
13
15
  from holmes.plugins.toolsets.bash.kubectl.kubectl_top import KubectlTopCommand
14
- from holmes.plugins.toolsets.bash.kubectl.kubectl_get import KubectlGetCommand
15
16
 
16
17
 
17
18
  class KubectlCommand(BashCommand):
@@ -1,6 +1,5 @@
1
1
  import re
2
2
 
3
-
4
3
  SAFE_NAME_PATTERN = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9\-_.]*$")
5
4
  SAFE_NAMESPACE_PATTERN = re.compile(r"^[a-z0-9][a-z0-9\-]*$")
6
5
  SAFE_SELECTOR_PATTERN = re.compile(r"^[a-zA-Z0-9\-_.=,!()]+$")
@@ -1,6 +1,8 @@
1
+ import argparse
1
2
  from typing import Any, Optional
2
3
 
3
- import argparse
4
+ from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
5
+ from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
4
6
  from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
5
7
  from holmes.plugins.toolsets.bash.common.validators import (
6
8
  whitelist_validator,
@@ -9,9 +11,6 @@ from holmes.plugins.toolsets.bash.kubectl.constants import (
9
11
  VALID_RESOURCE_TYPES,
10
12
  )
11
13
 
12
- from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
13
- from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
14
-
15
14
 
16
15
  class KubectlGetCommand(BashCommand):
17
16
  def __init__(self):
@@ -3,28 +3,27 @@ import logging
3
3
  import shlex
4
4
  from typing import Any, Optional
5
5
 
6
- from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
7
- from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
8
- from holmes.plugins.toolsets.bash.kubectl import KubectlCommand
6
+ from holmes.plugins.toolsets.bash.argocd import ArgocdCommand
9
7
  from holmes.plugins.toolsets.bash.aws import AWSCommand
10
8
  from holmes.plugins.toolsets.bash.azure import AzureCommand
11
- from holmes.plugins.toolsets.bash.argocd import ArgocdCommand
9
+ from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
10
+ from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
12
11
  from holmes.plugins.toolsets.bash.docker import DockerCommand
13
12
  from holmes.plugins.toolsets.bash.helm import HelmCommand
14
-
15
- # Utilities imports - all now use Command classes
16
- from holmes.plugins.toolsets.bash.utilities.wc import WCCommand
13
+ from holmes.plugins.toolsets.bash.kubectl import KubectlCommand
14
+ from holmes.plugins.toolsets.bash.utilities.base64_util import Base64Command
17
15
  from holmes.plugins.toolsets.bash.utilities.cut import CutCommand
18
- from holmes.plugins.toolsets.bash.utilities.sort import SortCommand
19
- from holmes.plugins.toolsets.bash.utilities.uniq import UniqCommand
16
+ from holmes.plugins.toolsets.bash.utilities.grep import GrepCommand
20
17
  from holmes.plugins.toolsets.bash.utilities.head import HeadCommand
21
- from holmes.plugins.toolsets.bash.utilities.tail import TailCommand
22
- from holmes.plugins.toolsets.bash.utilities.tr import TrCommand
23
- from holmes.plugins.toolsets.bash.utilities.base64_util import Base64Command
24
18
  from holmes.plugins.toolsets.bash.utilities.jq import JqCommand
25
19
  from holmes.plugins.toolsets.bash.utilities.sed import SedCommand
26
- from holmes.plugins.toolsets.bash.utilities.grep import GrepCommand
20
+ from holmes.plugins.toolsets.bash.utilities.sort import SortCommand
21
+ from holmes.plugins.toolsets.bash.utilities.tail import TailCommand
22
+ from holmes.plugins.toolsets.bash.utilities.tr import TrCommand
23
+ from holmes.plugins.toolsets.bash.utilities.uniq import UniqCommand
27
24
 
25
+ # Utilities imports - all now use Command classes
26
+ from holmes.plugins.toolsets.bash.utilities.wc import WCCommand
28
27
 
29
28
  # All commands now use BashCommand classes
30
29
  AVAILABLE_COMMANDS: list[BashCommand] = [
@@ -0,0 +1,124 @@
1
+ import socket
2
+ from typing import Any, Dict, Literal
3
+
4
+ from holmes.core.tools import (
5
+ StructuredToolResult,
6
+ StructuredToolResultStatus,
7
+ Tool,
8
+ ToolInvokeContext,
9
+ ToolParameter,
10
+ Toolset,
11
+ ToolsetTag,
12
+ )
13
+ from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
14
+
15
+ BROWSER_LIKE_UA = (
16
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
17
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
18
+ "Chrome/120.0.0.0 Safari/537.36"
19
+ )
20
+
21
+ UserAgentMode = Literal["none", "browser"]
22
+
23
+
24
+ def tcp_check(host: str, port: int, timeout: float) -> Dict[str, Any]:
25
+ if not (1 <= port <= 65535):
26
+ return {
27
+ "ok": False,
28
+ "error": "invalid port (must be 1-65535)",
29
+ }
30
+
31
+ try:
32
+ with socket.create_connection((host, port), timeout=timeout):
33
+ return {
34
+ "ok": True,
35
+ }
36
+ except (OSError, socket.timeout) as e:
37
+ return {
38
+ "ok": False,
39
+ "error": str(e),
40
+ }
41
+
42
+
43
+ class TcpCheckTool(Tool):
44
+ toolset: "ConnectivityCheckToolset" = None # type: ignore
45
+
46
+ def __init__(self, toolset: "ConnectivityCheckToolset"):
47
+ super().__init__(
48
+ name="tcp_check",
49
+ description="Check if a TCP socket can be opened to a host and port.",
50
+ parameters={
51
+ "host": ToolParameter(
52
+ description="The hostname or IP address to connect to",
53
+ type="string",
54
+ required=True,
55
+ ),
56
+ "port": ToolParameter(
57
+ description="The port to connect to",
58
+ type="integer",
59
+ required=True,
60
+ ),
61
+ "timeout": ToolParameter(
62
+ description="Timeout in seconds (default: 3.0)",
63
+ type="number",
64
+ required=False,
65
+ ),
66
+ },
67
+ )
68
+ self.toolset = toolset
69
+
70
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
71
+ host = params.get("host")
72
+ port = params.get("port")
73
+ if host is None:
74
+ return StructuredToolResult(
75
+ status=StructuredToolResultStatus.ERROR,
76
+ data={"error": "host parameter is required"},
77
+ params=params,
78
+ )
79
+ if port is None:
80
+ return StructuredToolResult(
81
+ status=StructuredToolResultStatus.ERROR,
82
+ data={"error": "port parameter is required"},
83
+ params=params,
84
+ )
85
+
86
+ result = tcp_check(
87
+ host=host,
88
+ port=int(port),
89
+ timeout=float(params.get("timeout", 3.0)),
90
+ )
91
+ return StructuredToolResult(
92
+ status=StructuredToolResultStatus.SUCCESS,
93
+ data=result,
94
+ params=params,
95
+ )
96
+
97
+ def get_parameterized_one_liner(self, params) -> str:
98
+ host = params.get("host", "<missing host>")
99
+ port = params.get("port", "<missing port>")
100
+ return (
101
+ f"{toolset_name_for_one_liner(self.toolset.name)}: "
102
+ f"TCP check {host}:{port}"
103
+ )
104
+
105
+
106
+ class ConnectivityCheckToolset(Toolset):
107
+ def __init__(self):
108
+ super().__init__(
109
+ name="connectivity_check",
110
+ description="Check TCP connectivity to endpoints",
111
+ icon_url="https://platform.robusta.dev/demos/internet-access.svg",
112
+ tools=[
113
+ TcpCheckTool(self),
114
+ ],
115
+ tags=[
116
+ ToolsetTag.CORE,
117
+ ],
118
+ is_default=True,
119
+ enabled=True,
120
+ docs_url="https://holmesgpt.dev/data-sources/builtin-toolsets/connectivity-check/",
121
+ )
122
+
123
+ def get_example_config(self) -> Dict[str, Any]:
124
+ return {}