holmesgpt 0.12.6__py3-none-any.whl → 0.13.1__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.

Potentially problematic release.


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

Files changed (125) hide show
  1. holmes/__init__.py +1 -1
  2. holmes/clients/robusta_client.py +19 -1
  3. holmes/common/env_vars.py +17 -0
  4. holmes/config.py +69 -9
  5. holmes/core/conversations.py +11 -0
  6. holmes/core/investigation.py +16 -3
  7. holmes/core/investigation_structured_output.py +12 -0
  8. holmes/core/llm.py +13 -1
  9. holmes/core/models.py +9 -1
  10. holmes/core/openai_formatting.py +72 -12
  11. holmes/core/prompt.py +13 -0
  12. holmes/core/supabase_dal.py +3 -0
  13. holmes/core/todo_manager.py +88 -0
  14. holmes/core/tool_calling_llm.py +230 -157
  15. holmes/core/tools.py +10 -1
  16. holmes/core/tools_utils/tool_executor.py +7 -2
  17. holmes/core/tools_utils/toolset_utils.py +7 -2
  18. holmes/core/toolset_manager.py +1 -5
  19. holmes/core/tracing.py +4 -3
  20. holmes/interactive.py +1 -0
  21. holmes/main.py +9 -2
  22. holmes/plugins/prompts/__init__.py +7 -1
  23. holmes/plugins/prompts/_current_date_time.jinja2 +1 -0
  24. holmes/plugins/prompts/_default_log_prompt.jinja2 +4 -2
  25. holmes/plugins/prompts/_fetch_logs.jinja2 +10 -1
  26. holmes/plugins/prompts/_general_instructions.jinja2 +14 -0
  27. holmes/plugins/prompts/_permission_errors.jinja2 +1 -1
  28. holmes/plugins/prompts/_toolsets_instructions.jinja2 +4 -4
  29. holmes/plugins/prompts/generic_ask.jinja2 +4 -3
  30. holmes/plugins/prompts/investigation_procedure.jinja2 +210 -0
  31. holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +2 -0
  32. holmes/plugins/runbooks/CLAUDE.md +85 -0
  33. holmes/plugins/runbooks/README.md +24 -0
  34. holmes/plugins/toolsets/__init__.py +19 -6
  35. holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +27 -0
  36. holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +2 -2
  37. holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +2 -1
  38. holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +3 -1
  39. holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +2 -1
  40. holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +2 -1
  41. holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +3 -1
  42. holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +2 -1
  43. holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +2 -1
  44. holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +2 -1
  45. holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +2 -1
  46. holmes/plugins/toolsets/bash/argocd/__init__.py +65 -0
  47. holmes/plugins/toolsets/bash/argocd/constants.py +120 -0
  48. holmes/plugins/toolsets/bash/aws/__init__.py +66 -0
  49. holmes/plugins/toolsets/bash/aws/constants.py +529 -0
  50. holmes/plugins/toolsets/bash/azure/__init__.py +56 -0
  51. holmes/plugins/toolsets/bash/azure/constants.py +339 -0
  52. holmes/plugins/toolsets/bash/bash_instructions.jinja2 +6 -7
  53. holmes/plugins/toolsets/bash/bash_toolset.py +47 -13
  54. holmes/plugins/toolsets/bash/common/bash_command.py +131 -0
  55. holmes/plugins/toolsets/bash/common/stringify.py +14 -1
  56. holmes/plugins/toolsets/bash/common/validators.py +91 -0
  57. holmes/plugins/toolsets/bash/docker/__init__.py +59 -0
  58. holmes/plugins/toolsets/bash/docker/constants.py +255 -0
  59. holmes/plugins/toolsets/bash/helm/__init__.py +61 -0
  60. holmes/plugins/toolsets/bash/helm/constants.py +92 -0
  61. holmes/plugins/toolsets/bash/kubectl/__init__.py +80 -79
  62. holmes/plugins/toolsets/bash/kubectl/constants.py +0 -14
  63. holmes/plugins/toolsets/bash/kubectl/kubectl_describe.py +38 -56
  64. holmes/plugins/toolsets/bash/kubectl/kubectl_events.py +28 -76
  65. holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +39 -99
  66. holmes/plugins/toolsets/bash/kubectl/kubectl_logs.py +34 -15
  67. holmes/plugins/toolsets/bash/kubectl/kubectl_run.py +1 -1
  68. holmes/plugins/toolsets/bash/kubectl/kubectl_top.py +38 -77
  69. holmes/plugins/toolsets/bash/parse_command.py +106 -32
  70. holmes/plugins/toolsets/bash/utilities/__init__.py +0 -0
  71. holmes/plugins/toolsets/bash/utilities/base64_util.py +12 -0
  72. holmes/plugins/toolsets/bash/utilities/cut.py +12 -0
  73. holmes/plugins/toolsets/bash/utilities/grep/__init__.py +10 -0
  74. holmes/plugins/toolsets/bash/utilities/head.py +12 -0
  75. holmes/plugins/toolsets/bash/utilities/jq.py +79 -0
  76. holmes/plugins/toolsets/bash/utilities/sed.py +164 -0
  77. holmes/plugins/toolsets/bash/utilities/sort.py +15 -0
  78. holmes/plugins/toolsets/bash/utilities/tail.py +12 -0
  79. holmes/plugins/toolsets/bash/utilities/tr.py +57 -0
  80. holmes/plugins/toolsets/bash/utilities/uniq.py +12 -0
  81. holmes/plugins/toolsets/bash/utilities/wc.py +12 -0
  82. holmes/plugins/toolsets/coralogix/api.py +6 -6
  83. holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +7 -1
  84. holmes/plugins/toolsets/datadog/datadog_api.py +20 -8
  85. holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +8 -1
  86. holmes/plugins/toolsets/datadog/datadog_rds_instructions.jinja2 +82 -0
  87. holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +12 -5
  88. holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +20 -11
  89. holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +735 -0
  90. holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +18 -11
  91. holmes/plugins/toolsets/git.py +15 -15
  92. holmes/plugins/toolsets/grafana/grafana_api.py +12 -1
  93. holmes/plugins/toolsets/grafana/toolset_grafana.py +5 -1
  94. holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +9 -4
  95. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +12 -5
  96. holmes/plugins/toolsets/internet/internet.py +2 -1
  97. holmes/plugins/toolsets/internet/notion.py +2 -1
  98. holmes/plugins/toolsets/investigator/__init__.py +0 -0
  99. holmes/plugins/toolsets/investigator/core_investigation.py +157 -0
  100. holmes/plugins/toolsets/investigator/investigator_instructions.jinja2 +253 -0
  101. holmes/plugins/toolsets/investigator/model.py +15 -0
  102. holmes/plugins/toolsets/kafka.py +14 -7
  103. holmes/plugins/toolsets/kubernetes_logs.py +454 -25
  104. holmes/plugins/toolsets/logging_utils/logging_api.py +115 -55
  105. holmes/plugins/toolsets/mcp/toolset_mcp.py +1 -1
  106. holmes/plugins/toolsets/newrelic.py +8 -3
  107. holmes/plugins/toolsets/opensearch/opensearch.py +8 -4
  108. holmes/plugins/toolsets/opensearch/opensearch_logs.py +9 -2
  109. holmes/plugins/toolsets/opensearch/opensearch_traces.py +6 -2
  110. holmes/plugins/toolsets/prometheus/prometheus.py +179 -44
  111. holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +8 -2
  112. holmes/plugins/toolsets/robusta/robusta.py +4 -4
  113. holmes/plugins/toolsets/runbook/runbook_fetcher.py +6 -5
  114. holmes/plugins/toolsets/servicenow/servicenow.py +18 -3
  115. holmes/plugins/toolsets/utils.py +8 -1
  116. holmes/utils/console/logging.py +6 -1
  117. holmes/utils/llms.py +20 -0
  118. holmes/utils/stream.py +90 -0
  119. {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/METADATA +47 -34
  120. {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/RECORD +123 -91
  121. holmes/plugins/toolsets/bash/grep/__init__.py +0 -52
  122. holmes/utils/robusta.py +0 -9
  123. {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/LICENSE.txt +0 -0
  124. {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/WHEEL +0 -0
  125. {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/entry_points.txt +0 -0
@@ -1,9 +1,10 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from datetime import datetime, timedelta
3
3
  import logging
4
- from typing import Optional
4
+ from typing import Optional, Set
5
+ from enum import Enum
5
6
 
6
- from pydantic import BaseModel
7
+ from pydantic import BaseModel, field_validator
7
8
  from datetime import timezone
8
9
  from holmes.core.tools import (
9
10
  StructuredToolResult,
@@ -14,12 +15,20 @@ from holmes.core.tools import (
14
15
  from holmes.plugins.toolsets.utils import get_param_or_raise
15
16
 
16
17
  # Default values for log fetching
17
- DEFAULT_LOG_LIMIT = 2000
18
- DEFAULT_TIME_SPAN_SECONDS = 3600
18
+ DEFAULT_LOG_LIMIT = 100
19
+ SECONDS_PER_DAY = 24 * 60 * 60
20
+ DEFAULT_TIME_SPAN_SECONDS = 7 * SECONDS_PER_DAY # 1 week in seconds
19
21
 
20
22
  POD_LOGGING_TOOL_NAME = "fetch_pod_logs"
21
23
 
22
24
 
25
+ class LoggingCapability(str, Enum):
26
+ """Optional advanced logging capabilities"""
27
+
28
+ REGEX_FILTER = "regex_filter" # If not supported, falls back to substring matching
29
+ EXCLUDE_FILTER = "exclude_filter" # If not supported, parameter is not shown at all
30
+
31
+
23
32
  class LoggingConfig(BaseModel):
24
33
  """Base configuration for all logging backends"""
25
34
 
@@ -32,12 +41,27 @@ class FetchPodLogsParams(BaseModel):
32
41
  start_time: Optional[str] = None
33
42
  end_time: Optional[str] = None
34
43
  filter: Optional[str] = None
44
+ exclude_filter: Optional[str] = None
35
45
  limit: Optional[int] = None
36
46
 
47
+ @field_validator("start_time", mode="before")
48
+ @classmethod
49
+ def convert_start_time_to_string(cls, v):
50
+ """Convert integer start_time values to strings."""
51
+ if v is not None and isinstance(v, int):
52
+ return str(v)
53
+ return v
54
+
37
55
 
38
56
  class BasePodLoggingToolset(Toolset, ABC):
39
57
  """Base class for all logging toolsets"""
40
58
 
59
+ @property
60
+ @abstractmethod
61
+ def supported_capabilities(self) -> Set[LoggingCapability]:
62
+ """Return the set of optional capabilities supported by this provider"""
63
+ pass
64
+
41
65
  @abstractmethod
42
66
  def fetch_pod_logs(self, params: FetchPodLogsParams) -> StructuredToolResult:
43
67
  pass
@@ -50,42 +74,96 @@ class PodLoggingTool(Tool):
50
74
  """Common tool for fetching pod logs across different logging backends"""
51
75
 
52
76
  def __init__(self, toolset: BasePodLoggingToolset):
77
+ # Get parameters dynamically based on what the toolset supports
78
+ parameters = self._get_tool_parameters(toolset)
79
+
80
+ # Build description based on capabilities
81
+ description = "Fetch logs for a Kubernetes pod"
82
+ capabilities = toolset.supported_capabilities
83
+
84
+ if (
85
+ LoggingCapability.REGEX_FILTER in capabilities
86
+ and LoggingCapability.EXCLUDE_FILTER in capabilities
87
+ ):
88
+ description += " with support for regex filtering and exclusion patterns"
89
+ elif LoggingCapability.REGEX_FILTER in capabilities:
90
+ description += " with support for regex filtering"
91
+
92
+ # Add default information
93
+ description += f". Defaults: Fetches last {DEFAULT_TIME_SPAN_SECONDS // SECONDS_PER_DAY} days of logs, limited to {DEFAULT_LOG_LIMIT} most recent entries"
94
+
53
95
  super().__init__(
54
96
  name=POD_LOGGING_TOOL_NAME,
55
- description="Fetch logs for a Kubernetes pod",
56
- parameters={
57
- "pod_name": ToolParameter(
58
- description="The exact kubernetes pod name",
59
- type="string",
60
- required=True,
61
- ),
62
- "namespace": ToolParameter(
63
- description="Kubernetes namespace", type="string", required=True
64
- ),
65
- "start_time": ToolParameter(
66
- description="Start time for logs. Can be an RFC3339 formatted datetime (e.g. '2023-03-01T10:30:00Z') for absolute time or a negative integer (e.g. -3600) for relative seconds before end_time.",
67
- type="string",
68
- required=False,
69
- ),
70
- "end_time": ToolParameter(
71
- description="End time for logs. Must be an RFC3339 formatted datetime (e.g. '2023-03-01T12:30:00Z'). If not specified, defaults to current time.",
72
- type="string",
73
- required=False,
74
- ),
75
- "limit": ToolParameter(
76
- description="Maximum number of logs to return",
77
- type="integer",
78
- required=False,
79
- ),
80
- "filter": ToolParameter(
81
- description="An optional keyword or sentence to filter the logs",
82
- type="string",
83
- required=False,
84
- ),
85
- },
97
+ description=description,
98
+ parameters=parameters,
86
99
  )
87
100
  self._toolset = toolset
88
101
 
102
+ def _get_tool_parameters(self, toolset: BasePodLoggingToolset) -> dict:
103
+ """Generate parameters based on what this provider supports"""
104
+ # Base parameters always available
105
+ params = {
106
+ "pod_name": ToolParameter(
107
+ description="The exact kubernetes pod name",
108
+ type="string",
109
+ required=True,
110
+ ),
111
+ "namespace": ToolParameter(
112
+ description="Kubernetes namespace", type="string", required=True
113
+ ),
114
+ "start_time": ToolParameter(
115
+ description=f"Start time for logs. Can be an RFC3339 formatted datetime (e.g. '2023-03-01T10:30:00Z') for absolute time or a negative string number (e.g. -3600) for relative seconds before end_time. Default: -{DEFAULT_TIME_SPAN_SECONDS} (last {DEFAULT_TIME_SPAN_SECONDS // SECONDS_PER_DAY} days)",
116
+ type="string",
117
+ required=False,
118
+ ),
119
+ "end_time": ToolParameter(
120
+ description="End time for logs. Must be an RFC3339 formatted datetime (e.g. '2023-03-01T12:30:00Z'). If not specified, defaults to current time.",
121
+ type="string",
122
+ required=False,
123
+ ),
124
+ "limit": ToolParameter(
125
+ description=f"Maximum number of logs to return. Default: {DEFAULT_LOG_LIMIT}",
126
+ type="integer",
127
+ required=False,
128
+ ),
129
+ }
130
+
131
+ # Add filter - description changes based on regex support
132
+ if LoggingCapability.REGEX_FILTER in toolset.supported_capabilities:
133
+ params["filter"] = ToolParameter(
134
+ description="""An optional filter for logs - can be a simple keyword/phrase or a regex pattern (case-insensitive).
135
+ Examples of useful filters:
136
+ - For errors: filter='err|error|fatal|critical|fail|exception|panic|crash'
137
+ - For warnings: filter='warn|warning|caution'
138
+ - For specific HTTP errors: filter='5[0-9]{2}|404|403'
139
+ - For Java exceptions: filter='Exception|Error|Throwable|StackTrace'
140
+ - For timeouts: filter='timeout|timed out|deadline exceeded'
141
+ If you get no results with a filter, try a broader pattern or drop the filter.""",
142
+ type="string",
143
+ required=False,
144
+ )
145
+ else:
146
+ params["filter"] = ToolParameter(
147
+ description="An optional keyword to filter logs - matches logs containing this text (case-insensitive)",
148
+ type="string",
149
+ required=False,
150
+ )
151
+
152
+ # ONLY add exclude_filter if supported - otherwise it doesn't exist
153
+ if LoggingCapability.EXCLUDE_FILTER in toolset.supported_capabilities:
154
+ params["exclude_filter"] = ToolParameter(
155
+ description="""An optional exclusion filter - logs matching this pattern will be excluded. Can be a simple keyword or regex pattern (case-insensitive).
156
+ Examples of useful exclude filters:
157
+ - Exclude HTTP 200s: exclude_filter='GET.*200|POST.*200'
158
+ - Exclude health/metrics: exclude_filter='health|metrics|ping|heartbeat'
159
+ - Exclude specific log levels: exclude_filter='"level": "INFO"'
160
+ If you hit the log limit and see lots of repetitive INFO logs, use exclude_filter to remove the noise and focus on what matters.""",
161
+ type="string",
162
+ required=False,
163
+ )
164
+
165
+ return params
166
+
89
167
  def _invoke(self, params: dict) -> StructuredToolResult:
90
168
  structured_params = FetchPodLogsParams(
91
169
  namespace=get_param_or_raise(params, "namespace"),
@@ -93,6 +171,7 @@ class PodLoggingTool(Tool):
93
171
  start_time=params.get("start_time"),
94
172
  end_time=params.get("end_time"),
95
173
  filter=params.get("filter"),
174
+ exclude_filter=params.get("exclude_filter"),
96
175
  limit=params.get("limit"),
97
176
  )
98
177
 
@@ -107,29 +186,10 @@ class PodLoggingTool(Tool):
107
186
  namespace = params.get("namespace", "unknown-namespace")
108
187
  pod_name = params.get("pod_name", "unknown-pod")
109
188
 
110
- start_time = params.get("start_time")
111
- end_time = params.get("end_time")
112
- filter = params.get("filter")
113
- limit = params.get("limit")
114
-
115
- extra_params_str = ""
116
-
117
- if start_time and not end_time:
118
- extra_params_str += f" start_time={start_time}"
119
- elif not start_time and end_time:
120
- extra_params_str += f" end_time={end_time}"
121
- elif start_time and end_time:
122
- extra_params_str += f" time range={start_time}/{end_time}"
123
-
124
- if filter:
125
- extra_params_str += f" filter={filter}"
126
- if limit:
127
- extra_params_str += f" limit={limit}"
128
-
129
189
  logger_name = (
130
190
  f"{self._toolset.logger_name()}: " if self._toolset.logger_name() else ""
131
191
  )
132
- return f"{logger_name}Fetching logs for pod {pod_name} in namespace {namespace}.{extra_params_str}"
192
+ return f"{logger_name}Fetch Logs (pod={pod_name}, namespace={namespace})"
133
193
 
134
194
 
135
195
  def process_time_parameters(
@@ -83,7 +83,7 @@ class RemoteMCPTool(Tool):
83
83
  return parameters
84
84
 
85
85
  def get_parameterized_one_liner(self, params: Dict) -> str:
86
- return f"Call mcp server {self.url} tool {self.name} with params {str(params)}"
86
+ return f"Call MCP Server ({self.url} - {self.name})"
87
87
 
88
88
 
89
89
  class RemoteMCPToolset(Toolset):
@@ -10,6 +10,7 @@ from holmes.core.tools import (
10
10
  )
11
11
  from pydantic import BaseModel
12
12
  from holmes.core.tools import StructuredToolResult, ToolResultStatus
13
+ from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
13
14
 
14
15
 
15
16
  class BaseNewRelicTool(Tool):
@@ -89,7 +90,9 @@ class GetLogs(BaseNewRelicTool):
89
90
  return error(f"Error while fetching logs: {str(e)}")
90
91
 
91
92
  def get_parameterized_one_liner(self, params) -> str:
92
- return f"newrelic GetLogs(app='{params.get('app')}', since='{params.get('since')}')"
93
+ app = params.get("app", "")
94
+ since = params.get("since", "")
95
+ return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Logs ({app} - {since})"
93
96
 
94
97
 
95
98
  class GetTraces(BaseNewRelicTool):
@@ -171,8 +174,10 @@ class GetTraces(BaseNewRelicTool):
171
174
 
172
175
  def get_parameterized_one_liner(self, params) -> str:
173
176
  if "trace_id" in params and params["trace_id"]:
174
- return f"newrelic GetTraces(trace_id='{params.get('trace_id')}')"
175
- return f"newrelic GetTraces(duration={params.get('duration')})"
177
+ trace_id = params.get("trace_id", "")
178
+ return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Trace Details ({trace_id})"
179
+ duration = params.get("duration", "")
180
+ return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Traces (>{duration}s)"
176
181
 
177
182
 
178
183
  class NewrelicConfig(BaseModel):
@@ -14,6 +14,7 @@ from holmes.core.tools import (
14
14
  ToolsetTag,
15
15
  )
16
16
  from holmes.plugins.toolsets.consts import TOOLSET_CONFIG_MISSING_ERROR
17
+ from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
17
18
 
18
19
 
19
20
  class OpenSearchHttpAuth(BaseModel):
@@ -102,7 +103,8 @@ class ListShards(BaseOpenSearchTool):
102
103
  )
103
104
 
104
105
  def get_parameterized_one_liner(self, params: Dict) -> str:
105
- return f"opensearch ListShards({params.get('host')})"
106
+ host = params.get("host", "")
107
+ return f"{toolset_name_for_one_liner(self.toolset.name)}: List Shards ({host})"
106
108
 
107
109
 
108
110
  class GetClusterSettings(BaseOpenSearchTool):
@@ -132,7 +134,8 @@ class GetClusterSettings(BaseOpenSearchTool):
132
134
  )
133
135
 
134
136
  def get_parameterized_one_liner(self, params) -> str:
135
- return f"opensearch GetClusterSettings({params.get('host')})"
137
+ host = params.get("host", "")
138
+ return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Cluster Settings ({host})"
136
139
 
137
140
 
138
141
  class GetClusterHealth(BaseOpenSearchTool):
@@ -160,7 +163,8 @@ class GetClusterHealth(BaseOpenSearchTool):
160
163
  )
161
164
 
162
165
  def get_parameterized_one_liner(self, params) -> str:
163
- return f"opensearch GetClusterHealth({params.get('host')})"
166
+ host = params.get("host", "")
167
+ return f"{toolset_name_for_one_liner(self.toolset.name)}: Check Cluster Health ({host})"
164
168
 
165
169
 
166
170
  class ListOpenSearchHosts(BaseOpenSearchTool):
@@ -181,7 +185,7 @@ class ListOpenSearchHosts(BaseOpenSearchTool):
181
185
  )
182
186
 
183
187
  def get_parameterized_one_liner(self, params: Dict) -> str:
184
- return "opensearch ListOpenSearchHosts()"
188
+ return f"{toolset_name_for_one_liner(self.toolset.name)}: List OpenSearch Hosts"
185
189
 
186
190
 
187
191
  class OpenSearchToolset(Toolset):
@@ -1,5 +1,5 @@
1
1
  import logging
2
- from typing import Any, Dict, Optional, Tuple
2
+ from typing import Any, Dict, Optional, Tuple, Set
3
3
 
4
4
  import requests # type: ignore
5
5
  from requests import RequestException # type: ignore
@@ -14,8 +14,10 @@ from holmes.core.tools import (
14
14
  from holmes.plugins.toolsets.logging_utils.logging_api import (
15
15
  BasePodLoggingToolset,
16
16
  FetchPodLogsParams,
17
+ LoggingCapability,
17
18
  PodLoggingTool,
18
19
  process_time_parameters,
20
+ DEFAULT_TIME_SPAN_SECONDS,
19
21
  )
20
22
  from holmes.plugins.toolsets.opensearch.opensearch_utils import (
21
23
  OpenSearchLoggingConfig,
@@ -31,6 +33,11 @@ LOGS_FIELDS_CACHE_KEY = "cached_logs_fields"
31
33
  class OpenSearchLogsToolset(BasePodLoggingToolset):
32
34
  """Implementation of the unified logging API for OpenSearch logs"""
33
35
 
36
+ @property
37
+ def supported_capabilities(self) -> Set[LoggingCapability]:
38
+ """OpenSearch only supports phrase matching, not regex or exclude filters"""
39
+ return set() # No regex support, no exclude filter
40
+
34
41
  def __init__(self):
35
42
  super().__init__(
36
43
  name="opensearch/logs",
@@ -82,7 +89,7 @@ class OpenSearchLogsToolset(BasePodLoggingToolset):
82
89
  end_time = None
83
90
  if params.start_time or params.end_time:
84
91
  start_time, end_time = process_time_parameters(
85
- params.start_time, params.end_time
92
+ params.start_time, params.end_time, DEFAULT_TIME_SPAN_SECONDS
86
93
  )
87
94
 
88
95
  query = build_query(
@@ -20,6 +20,7 @@ from holmes.plugins.toolsets.opensearch.opensearch_utils import (
20
20
  get_search_url,
21
21
  )
22
22
  from holmes.core.tools import StructuredToolResult, ToolResultStatus
23
+ from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
23
24
 
24
25
  TRACES_FIELDS_CACHE_KEY = "cached_traces_fields"
25
26
 
@@ -108,7 +109,7 @@ class GetTracesFields(Tool):
108
109
  )
109
110
 
110
111
  def get_parameterized_one_liner(self, params) -> str:
111
- return "list traces documents fields"
112
+ return f"{toolset_name_for_one_liner(self._toolset.name)}: List Trace Fields"
112
113
 
113
114
 
114
115
  class TracesSearchQuery(Tool):
@@ -184,7 +185,10 @@ class TracesSearchQuery(Tool):
184
185
  )
185
186
 
186
187
  def get_parameterized_one_liner(self, params) -> str:
187
- return f'search traces: query="{params.get("query")}"'
188
+ query = params.get("query", "")
189
+ return (
190
+ f"{toolset_name_for_one_liner(self._toolset.name)}: Search Traces ({query})"
191
+ )
188
192
 
189
193
 
190
194
  class OpenSearchTracesToolset(BaseOpenSearchToolset):