holmesgpt 0.13.2__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 (188) hide show
  1. holmes/__init__.py +3 -5
  2. holmes/clients/robusta_client.py +20 -6
  3. holmes/common/env_vars.py +58 -3
  4. holmes/common/openshift.py +1 -1
  5. holmes/config.py +123 -148
  6. holmes/core/conversations.py +71 -15
  7. holmes/core/feedback.py +191 -0
  8. holmes/core/investigation.py +31 -39
  9. holmes/core/investigation_structured_output.py +3 -3
  10. holmes/core/issue.py +1 -1
  11. holmes/core/llm.py +508 -88
  12. holmes/core/models.py +108 -4
  13. holmes/core/openai_formatting.py +14 -1
  14. holmes/core/prompt.py +48 -3
  15. holmes/core/runbooks.py +1 -0
  16. holmes/core/safeguards.py +8 -6
  17. holmes/core/supabase_dal.py +295 -100
  18. holmes/core/tool_calling_llm.py +489 -428
  19. holmes/core/tools.py +325 -56
  20. holmes/core/tools_utils/token_counting.py +21 -0
  21. holmes/core/tools_utils/tool_context_window_limiter.py +40 -0
  22. holmes/core/tools_utils/tool_executor.py +0 -13
  23. holmes/core/tools_utils/toolset_utils.py +1 -0
  24. holmes/core/toolset_manager.py +191 -5
  25. holmes/core/tracing.py +19 -3
  26. holmes/core/transformers/__init__.py +23 -0
  27. holmes/core/transformers/base.py +63 -0
  28. holmes/core/transformers/llm_summarize.py +175 -0
  29. holmes/core/transformers/registry.py +123 -0
  30. holmes/core/transformers/transformer.py +32 -0
  31. holmes/core/truncation/compaction.py +94 -0
  32. holmes/core/truncation/dal_truncation_utils.py +23 -0
  33. holmes/core/truncation/input_context_window_limiter.py +219 -0
  34. holmes/interactive.py +228 -31
  35. holmes/main.py +23 -40
  36. holmes/plugins/interfaces.py +2 -1
  37. holmes/plugins/prompts/__init__.py +2 -1
  38. holmes/plugins/prompts/_fetch_logs.jinja2 +31 -6
  39. holmes/plugins/prompts/_general_instructions.jinja2 +1 -2
  40. holmes/plugins/prompts/_runbook_instructions.jinja2 +24 -12
  41. holmes/plugins/prompts/base_user_prompt.jinja2 +7 -0
  42. holmes/plugins/prompts/conversation_history_compaction.jinja2 +89 -0
  43. holmes/plugins/prompts/generic_ask.jinja2 +0 -4
  44. holmes/plugins/prompts/generic_ask_conversation.jinja2 +0 -1
  45. holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +0 -1
  46. holmes/plugins/prompts/generic_investigation.jinja2 +0 -1
  47. holmes/plugins/prompts/investigation_procedure.jinja2 +50 -1
  48. holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +0 -1
  49. holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +0 -1
  50. holmes/plugins/runbooks/__init__.py +145 -17
  51. holmes/plugins/runbooks/catalog.json +2 -0
  52. holmes/plugins/sources/github/__init__.py +4 -2
  53. holmes/plugins/sources/prometheus/models.py +1 -0
  54. holmes/plugins/toolsets/__init__.py +44 -27
  55. holmes/plugins/toolsets/aks-node-health.yaml +46 -0
  56. holmes/plugins/toolsets/aks.yaml +64 -0
  57. holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +38 -47
  58. holmes/plugins/toolsets/azure_sql/apis/alert_monitoring_api.py +3 -2
  59. holmes/plugins/toolsets/azure_sql/apis/azure_sql_api.py +2 -1
  60. holmes/plugins/toolsets/azure_sql/apis/connection_failure_api.py +3 -2
  61. holmes/plugins/toolsets/azure_sql/apis/connection_monitoring_api.py +3 -1
  62. holmes/plugins/toolsets/azure_sql/apis/storage_analysis_api.py +3 -1
  63. holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +12 -13
  64. holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +15 -12
  65. holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +15 -12
  66. holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +11 -11
  67. holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +11 -9
  68. holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +15 -12
  69. holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +15 -15
  70. holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +11 -8
  71. holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +11 -8
  72. holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +11 -8
  73. holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +11 -8
  74. holmes/plugins/toolsets/azure_sql/utils.py +0 -32
  75. holmes/plugins/toolsets/bash/argocd/__init__.py +3 -3
  76. holmes/plugins/toolsets/bash/aws/__init__.py +4 -4
  77. holmes/plugins/toolsets/bash/azure/__init__.py +4 -4
  78. holmes/plugins/toolsets/bash/bash_toolset.py +11 -15
  79. holmes/plugins/toolsets/bash/common/bash.py +23 -13
  80. holmes/plugins/toolsets/bash/common/bash_command.py +1 -1
  81. holmes/plugins/toolsets/bash/common/stringify.py +1 -1
  82. holmes/plugins/toolsets/bash/kubectl/__init__.py +2 -1
  83. holmes/plugins/toolsets/bash/kubectl/constants.py +0 -1
  84. holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +3 -4
  85. holmes/plugins/toolsets/bash/parse_command.py +12 -13
  86. holmes/plugins/toolsets/cilium.yaml +284 -0
  87. holmes/plugins/toolsets/connectivity_check.py +124 -0
  88. holmes/plugins/toolsets/coralogix/api.py +132 -119
  89. holmes/plugins/toolsets/coralogix/coralogix.jinja2 +14 -0
  90. holmes/plugins/toolsets/coralogix/toolset_coralogix.py +219 -0
  91. holmes/plugins/toolsets/coralogix/utils.py +15 -79
  92. holmes/plugins/toolsets/datadog/datadog_api.py +525 -26
  93. holmes/plugins/toolsets/datadog/datadog_logs_instructions.jinja2 +55 -11
  94. holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +3 -3
  95. holmes/plugins/toolsets/datadog/datadog_models.py +59 -0
  96. holmes/plugins/toolsets/datadog/datadog_url_utils.py +213 -0
  97. holmes/plugins/toolsets/datadog/instructions_datadog_traces.jinja2 +165 -28
  98. holmes/plugins/toolsets/datadog/toolset_datadog_general.py +417 -241
  99. holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +234 -214
  100. holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +167 -79
  101. holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +374 -363
  102. holmes/plugins/toolsets/elasticsearch/__init__.py +6 -0
  103. holmes/plugins/toolsets/elasticsearch/elasticsearch.py +834 -0
  104. holmes/plugins/toolsets/elasticsearch/opensearch_ppl_query_docs.jinja2 +1616 -0
  105. holmes/plugins/toolsets/elasticsearch/opensearch_query_assist.py +78 -0
  106. holmes/plugins/toolsets/elasticsearch/opensearch_query_assist_instructions.jinja2 +223 -0
  107. holmes/plugins/toolsets/git.py +54 -50
  108. holmes/plugins/toolsets/grafana/base_grafana_toolset.py +16 -4
  109. holmes/plugins/toolsets/grafana/common.py +13 -29
  110. holmes/plugins/toolsets/grafana/grafana_tempo_api.py +455 -0
  111. holmes/plugins/toolsets/grafana/loki/instructions.jinja2 +25 -0
  112. holmes/plugins/toolsets/grafana/loki/toolset_grafana_loki.py +191 -0
  113. holmes/plugins/toolsets/grafana/loki_api.py +4 -0
  114. holmes/plugins/toolsets/grafana/toolset_grafana.py +293 -89
  115. holmes/plugins/toolsets/grafana/toolset_grafana_dashboard.jinja2 +49 -0
  116. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +246 -11
  117. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +820 -292
  118. holmes/plugins/toolsets/grafana/trace_parser.py +4 -3
  119. holmes/plugins/toolsets/internet/internet.py +15 -16
  120. holmes/plugins/toolsets/internet/notion.py +9 -11
  121. holmes/plugins/toolsets/investigator/core_investigation.py +44 -36
  122. holmes/plugins/toolsets/investigator/model.py +3 -1
  123. holmes/plugins/toolsets/json_filter_mixin.py +134 -0
  124. holmes/plugins/toolsets/kafka.py +36 -42
  125. holmes/plugins/toolsets/kubernetes.yaml +317 -113
  126. holmes/plugins/toolsets/kubernetes_logs.py +9 -9
  127. holmes/plugins/toolsets/kubernetes_logs.yaml +32 -0
  128. holmes/plugins/toolsets/logging_utils/logging_api.py +94 -8
  129. holmes/plugins/toolsets/mcp/toolset_mcp.py +218 -64
  130. holmes/plugins/toolsets/newrelic/new_relic_api.py +165 -0
  131. holmes/plugins/toolsets/newrelic/newrelic.jinja2 +65 -0
  132. holmes/plugins/toolsets/newrelic/newrelic.py +320 -0
  133. holmes/plugins/toolsets/openshift.yaml +283 -0
  134. holmes/plugins/toolsets/prometheus/prometheus.py +1202 -421
  135. holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +54 -5
  136. holmes/plugins/toolsets/prometheus/utils.py +28 -0
  137. holmes/plugins/toolsets/rabbitmq/api.py +23 -4
  138. holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +13 -14
  139. holmes/plugins/toolsets/robusta/robusta.py +239 -68
  140. holmes/plugins/toolsets/robusta/robusta_instructions.jinja2 +26 -9
  141. holmes/plugins/toolsets/runbook/runbook_fetcher.py +157 -27
  142. holmes/plugins/toolsets/service_discovery.py +1 -1
  143. holmes/plugins/toolsets/servicenow_tables/instructions.jinja2 +83 -0
  144. holmes/plugins/toolsets/servicenow_tables/servicenow_tables.py +426 -0
  145. holmes/plugins/toolsets/utils.py +88 -0
  146. holmes/utils/config_utils.py +91 -0
  147. holmes/utils/connection_utils.py +31 -0
  148. holmes/utils/console/result.py +10 -0
  149. holmes/utils/default_toolset_installation_guide.jinja2 +1 -22
  150. holmes/utils/env.py +7 -0
  151. holmes/utils/file_utils.py +2 -1
  152. holmes/utils/global_instructions.py +60 -11
  153. holmes/utils/holmes_status.py +6 -4
  154. holmes/utils/holmes_sync_toolsets.py +0 -2
  155. holmes/utils/krr_utils.py +188 -0
  156. holmes/utils/log.py +15 -0
  157. holmes/utils/markdown_utils.py +2 -3
  158. holmes/utils/memory_limit.py +58 -0
  159. holmes/utils/sentry_helper.py +64 -0
  160. holmes/utils/stream.py +69 -8
  161. holmes/utils/tags.py +4 -3
  162. holmes/version.py +37 -15
  163. holmesgpt-0.18.4.dist-info/LICENSE +178 -0
  164. {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/METADATA +35 -31
  165. holmesgpt-0.18.4.dist-info/RECORD +258 -0
  166. holmes/core/performance_timing.py +0 -72
  167. holmes/plugins/toolsets/aws.yaml +0 -80
  168. holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +0 -112
  169. holmes/plugins/toolsets/datadog/datadog_traces_formatter.py +0 -310
  170. holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +0 -739
  171. holmes/plugins/toolsets/grafana/grafana_api.py +0 -42
  172. holmes/plugins/toolsets/grafana/tempo_api.py +0 -124
  173. holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +0 -110
  174. holmes/plugins/toolsets/newrelic.py +0 -231
  175. holmes/plugins/toolsets/opensearch/opensearch.py +0 -257
  176. holmes/plugins/toolsets/opensearch/opensearch_logs.py +0 -161
  177. holmes/plugins/toolsets/opensearch/opensearch_traces.py +0 -218
  178. holmes/plugins/toolsets/opensearch/opensearch_traces_instructions.jinja2 +0 -12
  179. holmes/plugins/toolsets/opensearch/opensearch_utils.py +0 -166
  180. holmes/plugins/toolsets/servicenow/install.md +0 -37
  181. holmes/plugins/toolsets/servicenow/instructions.jinja2 +0 -3
  182. holmes/plugins/toolsets/servicenow/servicenow.py +0 -219
  183. holmes/utils/keygen_utils.py +0 -6
  184. holmesgpt-0.13.2.dist-info/LICENSE.txt +0 -21
  185. holmesgpt-0.13.2.dist-info/RECORD +0 -234
  186. /holmes/plugins/toolsets/{opensearch → newrelic}/__init__.py +0 -0
  187. {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/WHEEL +0 -0
  188. {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/entry_points.txt +0 -0
holmes/core/models.py CHANGED
@@ -1,15 +1,96 @@
1
- from holmes.core.investigation_structured_output import InputSectionsDataType
2
- from holmes.core.tool_calling_llm import ToolCallResult
3
- from typing import Optional, List, Dict, Any, Union
4
- from pydantic import BaseModel, model_validator, Field
1
+ import json
5
2
  from enum import Enum
3
+ from typing import Any, Dict, List, Optional, Union
4
+
5
+ from pydantic import BaseModel, Field, model_validator
6
+
7
+ from holmes.core.investigation_structured_output import InputSectionsDataType
8
+ from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
9
+
10
+
11
+ class TruncationMetadata(BaseModel):
12
+ tool_call_id: str
13
+ start_index: int
14
+ end_index: int
15
+ tool_name: str
16
+ original_token_count: int
17
+
18
+
19
+ class TruncationResult(BaseModel):
20
+ truncated_messages: list[dict]
21
+ truncations: list[TruncationMetadata]
22
+
23
+
24
+ class ToolCallResult(BaseModel):
25
+ tool_call_id: str
26
+ tool_name: str
27
+ description: str
28
+ result: StructuredToolResult
29
+ size: Optional[int] = None
30
+
31
+ def as_tool_call_message(self):
32
+ return {
33
+ "tool_call_id": self.tool_call_id,
34
+ "role": "tool",
35
+ "name": self.tool_name,
36
+ "content": format_tool_result_data(
37
+ tool_result=self.result,
38
+ tool_call_id=self.tool_call_id,
39
+ tool_name=self.tool_name,
40
+ ),
41
+ }
42
+
43
+ def as_tool_result_response(self):
44
+ result_dump = self.result.model_dump()
45
+ result_dump["data"] = self.result.get_stringified_data()
46
+
47
+ return {
48
+ "tool_call_id": self.tool_call_id,
49
+ "tool_name": self.tool_name,
50
+ "description": self.description,
51
+ "role": "tool",
52
+ "result": result_dump,
53
+ }
54
+
55
+ def as_streaming_tool_result_response(self):
56
+ result_dump = self.result.model_dump()
57
+ result_dump["data"] = self.result.get_stringified_data()
58
+
59
+ return {
60
+ "tool_call_id": self.tool_call_id,
61
+ "role": "tool",
62
+ "description": self.description,
63
+ "name": self.tool_name,
64
+ "result": result_dump,
65
+ }
66
+
67
+
68
+ def format_tool_result_data(
69
+ tool_result: StructuredToolResult, tool_call_id: str, tool_name: str
70
+ ) -> str:
71
+ tool_call_metadata = {"tool_name": tool_name, "tool_call_id": tool_call_id}
72
+ tool_response = f"tool_call_metadata={json.dumps(tool_call_metadata)}"
73
+
74
+ if tool_result.status == StructuredToolResultStatus.ERROR:
75
+ tool_response += f"{tool_result.error or 'Tool execution failed'}:\n\n"
76
+
77
+ tool_response += tool_result.get_stringified_data()
78
+
79
+ if tool_result.params:
80
+ tool_response = (
81
+ f"Params used for the tool call: {json.dumps(tool_result.params)}. The tool call output follows on the next line.\n"
82
+ + tool_response
83
+ )
84
+ return tool_response
6
85
 
7
86
 
8
87
  class InvestigationResult(BaseModel):
9
88
  analysis: Optional[str] = None
10
89
  sections: Optional[Dict[str, Union[str, None]]] = None
11
90
  tool_calls: List[ToolCallResult] = []
91
+ num_llm_calls: Optional[int] = None # Number of LLM API calls (turns)
12
92
  instructions: List[str] = []
93
+ metadata: Optional[Dict[Any, Any]] = None
13
94
 
14
95
 
15
96
  class InvestigateRequest(BaseModel):
@@ -86,10 +167,31 @@ class ConversationRequest(BaseModel):
86
167
  include_tool_call_results: bool = False
87
168
 
88
169
 
170
+ class PendingToolApproval(BaseModel):
171
+ """Represents a tool call that requires user approval."""
172
+
173
+ tool_call_id: str
174
+ tool_name: str
175
+ description: str
176
+ params: Dict[str, Any]
177
+
178
+
179
+ class ToolApprovalDecision(BaseModel):
180
+ """Represents a user's decision on a tool approval."""
181
+
182
+ tool_call_id: str
183
+ approved: bool
184
+
185
+
89
186
  class ChatRequestBaseModel(BaseModel):
90
187
  conversation_history: Optional[list[dict]] = None
91
188
  model: Optional[str] = None
92
189
  stream: bool = Field(default=False)
190
+ enable_tool_approval: Optional[bool] = (
191
+ False # Optional boolean for backwards compatibility
192
+ )
193
+ tool_decisions: Optional[List[ToolApprovalDecision]] = None
194
+ additional_system_prompt: Optional[str] = None
93
195
 
94
196
  # In our setup with litellm, the first message in conversation_history
95
197
  # should follow the structure [{"role": "system", "content": ...}],
@@ -145,6 +247,8 @@ class ChatResponse(BaseModel):
145
247
  conversation_history: list[dict]
146
248
  tool_calls: Optional[List[ToolCallResult]] = []
147
249
  follow_up_actions: Optional[List[FollowUpAction]] = []
250
+ pending_approvals: Optional[List[PendingToolApproval]] = None
251
+ metadata: Optional[Dict[Any, Any]] = None
148
252
 
149
253
 
150
254
  class WorkloadHealthInvestigationResult(BaseModel):
@@ -2,8 +2,8 @@ import re
2
2
  from typing import Any, Optional
3
3
 
4
4
  from holmes.common.env_vars import (
5
- TOOL_SCHEMA_NO_PARAM_OBJECT_IF_NO_PARAMS,
6
5
  LLMS_WITH_STRICT_TOOL_CALLS,
6
+ TOOL_SCHEMA_NO_PARAM_OBJECT_IF_NO_PARAMS,
7
7
  )
8
8
  from holmes.utils.llms import model_matches_list
9
9
 
@@ -80,6 +80,19 @@ def format_tool_to_open_ai_standard(
80
80
  )
81
81
  if param_attributes.description is not None:
82
82
  tool_properties[param_name]["description"] = param_attributes.description
83
+ # Add enum constraint if specified
84
+ if hasattr(param_attributes, "enum") and param_attributes.enum:
85
+ enum_values = list(
86
+ param_attributes.enum
87
+ ) # Create a copy to avoid modifying original
88
+ # In strict mode, optional parameters need None in their enum to match the type allowing null
89
+ if (
90
+ strict_mode
91
+ and not param_attributes.required
92
+ and None not in enum_values
93
+ ):
94
+ enum_values.append(None)
95
+ tool_properties[param_name]["enum"] = enum_values
83
96
 
84
97
  result: dict[str, Any] = {
85
98
  "type": "function",
holmes/core/prompt.py CHANGED
@@ -1,8 +1,11 @@
1
- from rich.console import Console
2
- from typing import Optional, List, Dict, Any, Union
3
1
  from pathlib import Path
2
+ from typing import Any, Dict, List, Optional, Union
3
+
4
+ from rich.console import Console
5
+
4
6
  from holmes.plugins.prompts import load_and_render_prompt
5
7
  from holmes.plugins.runbooks import RunbookCatalog
8
+ from holmes.utils.global_instructions import generate_runbooks_args
6
9
 
7
10
 
8
11
  def append_file_to_user_prompt(user_prompt: str, file_path: Path) -> str:
@@ -35,6 +38,39 @@ def get_tasks_management_system_reminder() -> str:
35
38
  )
36
39
 
37
40
 
41
+ def _has_content(value: Optional[str]) -> bool:
42
+ """
43
+ Check if the value is a non-empty string and not None.
44
+ """
45
+ return bool(value and isinstance(value, str) and value.strip())
46
+
47
+
48
+ def _should_enable_runbooks(context: Dict[str, str]) -> bool:
49
+ return any(
50
+ (
51
+ _has_content(context.get("runbook_catalog")),
52
+ _has_content(context.get("custom_instructions")),
53
+ _has_content(context.get("global_instructions")),
54
+ )
55
+ )
56
+
57
+
58
+ def generate_user_prompt(
59
+ user_prompt: str,
60
+ context: Dict[str, str],
61
+ ) -> str:
62
+ runbooks_enabled = _should_enable_runbooks(context)
63
+
64
+ return load_and_render_prompt(
65
+ "builtin://base_user_prompt.jinja2",
66
+ context={
67
+ "user_prompt": user_prompt,
68
+ "runbooks_enabled": runbooks_enabled,
69
+ **context,
70
+ },
71
+ )
72
+
73
+
38
74
  def build_initial_ask_messages(
39
75
  console: Console,
40
76
  initial_user_prompt: str,
@@ -57,7 +93,7 @@ def build_initial_ask_messages(
57
93
  system_prompt_template = "builtin://generic_ask.jinja2"
58
94
  template_context = {
59
95
  "toolsets": tool_executor.toolsets,
60
- "runbooks": runbooks or {},
96
+ "runbooks_enabled": True if runbooks else False,
61
97
  "system_prompt_additions": system_prompt_additions or "",
62
98
  }
63
99
  system_prompt_rendered = load_and_render_prompt(
@@ -70,6 +106,15 @@ def build_initial_ask_messages(
70
106
  )
71
107
 
72
108
  user_prompt_with_files += get_tasks_management_system_reminder()
109
+
110
+ runbooks_ctx = generate_runbooks_args(
111
+ runbook_catalog=runbooks, # type: ignore
112
+ )
113
+ user_prompt_with_files = generate_user_prompt(
114
+ user_prompt_with_files,
115
+ runbooks_ctx,
116
+ )
117
+
73
118
  messages = [
74
119
  {"role": "system", "content": system_prompt_rendered},
75
120
  {"role": "user", "content": user_prompt_with_files},
holmes/core/runbooks.py CHANGED
@@ -1,4 +1,5 @@
1
1
  from typing import List
2
+
2
3
  from holmes.core.issue import Issue
3
4
  from holmes.plugins.runbooks import Runbook
4
5
 
holmes/core/safeguards.py CHANGED
@@ -4,9 +4,11 @@ from typing import Optional
4
4
  from pydantic import ValidationError
5
5
 
6
6
  from holmes.common.env_vars import TOOL_CALL_SAFEGUARDS_ENABLED
7
- from holmes.plugins.toolsets.logging_utils.logging_api import POD_LOGGING_TOOL_NAME
8
- from holmes.core.tools import StructuredToolResult, ToolResultStatus
9
- from holmes.plugins.toolsets.logging_utils.logging_api import FetchPodLogsParams
7
+ from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
8
+ from holmes.plugins.toolsets.logging_utils.logging_api import (
9
+ POD_LOGGING_TOOL_NAME,
10
+ FetchPodLogsParams,
11
+ )
10
12
 
11
13
 
12
14
  def _is_redundant_fetch_pod_logs(
@@ -39,7 +41,7 @@ def _has_previous_unfiltered_pod_logs_call(
39
41
  result = tool_call.get("result", {})
40
42
  if (
41
43
  tool_call.get("tool_name") == POD_LOGGING_TOOL_NAME
42
- and result.get("status") == ToolResultStatus.NO_DATA
44
+ and result.get("status") == StructuredToolResultStatus.NO_DATA
43
45
  and result.get("params")
44
46
  ):
45
47
  params = FetchPodLogsParams(**result.get("params"))
@@ -94,7 +96,7 @@ def prevent_overly_repeated_tool_call(
94
96
  For example if Holmes checks if a resource is deployed, runs a command to deploy it and then checks again if it has deployed properly.
95
97
  """
96
98
  return StructuredToolResult(
97
- status=ToolResultStatus.ERROR,
99
+ status=StructuredToolResultStatus.ERROR,
98
100
  error=(
99
101
  "Refusing to run this tool call because it has already been called during this session with the exact same parameters.\n"
100
102
  "Move on with your investigation to a different tool or change the parameter values."
@@ -106,7 +108,7 @@ def prevent_overly_repeated_tool_call(
106
108
  tool_name=tool_name, tool_params=tool_params, tool_calls=tool_calls
107
109
  ):
108
110
  return StructuredToolResult(
109
- status=ToolResultStatus.ERROR,
111
+ status=StructuredToolResultStatus.ERROR,
110
112
  error=(
111
113
  f"Refusing to run this tool call because the exact same {POD_LOGGING_TOOL_NAME} tool call without filter has already run and returned no data.\n"
112
114
  "This tool call would also have returned no data.\n"