holmesgpt 0.13.2__py3-none-any.whl → 0.16.2a0__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.
- holmes/__init__.py +1 -1
- holmes/clients/robusta_client.py +17 -4
- holmes/common/env_vars.py +40 -1
- holmes/config.py +114 -144
- holmes/core/conversations.py +53 -14
- holmes/core/feedback.py +191 -0
- holmes/core/investigation.py +18 -22
- holmes/core/llm.py +489 -88
- holmes/core/models.py +103 -1
- holmes/core/openai_formatting.py +13 -0
- holmes/core/prompt.py +1 -1
- holmes/core/safeguards.py +4 -4
- holmes/core/supabase_dal.py +293 -100
- holmes/core/tool_calling_llm.py +423 -323
- holmes/core/tools.py +311 -33
- holmes/core/tools_utils/token_counting.py +14 -0
- holmes/core/tools_utils/tool_context_window_limiter.py +57 -0
- holmes/core/tools_utils/tool_executor.py +13 -8
- holmes/core/toolset_manager.py +155 -4
- holmes/core/tracing.py +6 -1
- holmes/core/transformers/__init__.py +23 -0
- holmes/core/transformers/base.py +62 -0
- holmes/core/transformers/llm_summarize.py +174 -0
- holmes/core/transformers/registry.py +122 -0
- holmes/core/transformers/transformer.py +31 -0
- holmes/core/truncation/compaction.py +59 -0
- holmes/core/truncation/dal_truncation_utils.py +23 -0
- holmes/core/truncation/input_context_window_limiter.py +218 -0
- holmes/interactive.py +177 -24
- holmes/main.py +7 -4
- holmes/plugins/prompts/_fetch_logs.jinja2 +26 -1
- holmes/plugins/prompts/_general_instructions.jinja2 +1 -2
- holmes/plugins/prompts/_runbook_instructions.jinja2 +23 -12
- holmes/plugins/prompts/conversation_history_compaction.jinja2 +88 -0
- holmes/plugins/prompts/generic_ask.jinja2 +2 -4
- holmes/plugins/prompts/generic_ask_conversation.jinja2 +2 -1
- holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +2 -1
- holmes/plugins/prompts/generic_investigation.jinja2 +2 -1
- holmes/plugins/prompts/investigation_procedure.jinja2 +48 -0
- holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +2 -1
- holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +2 -1
- holmes/plugins/runbooks/__init__.py +117 -18
- holmes/plugins/runbooks/catalog.json +2 -0
- holmes/plugins/toolsets/__init__.py +21 -8
- holmes/plugins/toolsets/aks-node-health.yaml +46 -0
- holmes/plugins/toolsets/aks.yaml +64 -0
- holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +26 -36
- holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +0 -1
- holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +10 -7
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +9 -6
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +8 -6
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +8 -6
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +9 -6
- holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +9 -7
- holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +9 -6
- holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +9 -6
- holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +9 -6
- holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +9 -6
- holmes/plugins/toolsets/bash/bash_toolset.py +10 -13
- holmes/plugins/toolsets/bash/common/bash.py +7 -7
- holmes/plugins/toolsets/cilium.yaml +284 -0
- holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +5 -3
- holmes/plugins/toolsets/datadog/datadog_api.py +490 -24
- holmes/plugins/toolsets/datadog/datadog_logs_instructions.jinja2 +21 -10
- holmes/plugins/toolsets/datadog/toolset_datadog_general.py +349 -216
- holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +190 -19
- holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +101 -44
- holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +13 -16
- holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +25 -31
- holmes/plugins/toolsets/git.py +51 -46
- holmes/plugins/toolsets/grafana/common.py +15 -3
- holmes/plugins/toolsets/grafana/grafana_api.py +46 -24
- holmes/plugins/toolsets/grafana/grafana_tempo_api.py +454 -0
- holmes/plugins/toolsets/grafana/loki/instructions.jinja2 +9 -0
- holmes/plugins/toolsets/grafana/loki/toolset_grafana_loki.py +117 -0
- holmes/plugins/toolsets/grafana/toolset_grafana.py +211 -91
- holmes/plugins/toolsets/grafana/toolset_grafana_dashboard.jinja2 +27 -0
- holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +246 -11
- holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +653 -293
- holmes/plugins/toolsets/grafana/trace_parser.py +1 -1
- holmes/plugins/toolsets/internet/internet.py +6 -7
- holmes/plugins/toolsets/internet/notion.py +5 -6
- holmes/plugins/toolsets/investigator/core_investigation.py +42 -34
- holmes/plugins/toolsets/kafka.py +25 -36
- holmes/plugins/toolsets/kubernetes.yaml +58 -84
- holmes/plugins/toolsets/kubernetes_logs.py +6 -6
- holmes/plugins/toolsets/kubernetes_logs.yaml +32 -0
- holmes/plugins/toolsets/logging_utils/logging_api.py +80 -4
- holmes/plugins/toolsets/mcp/toolset_mcp.py +181 -55
- holmes/plugins/toolsets/newrelic/__init__.py +0 -0
- holmes/plugins/toolsets/newrelic/new_relic_api.py +125 -0
- holmes/plugins/toolsets/newrelic/newrelic.jinja2 +41 -0
- holmes/plugins/toolsets/newrelic/newrelic.py +163 -0
- holmes/plugins/toolsets/opensearch/opensearch.py +10 -17
- holmes/plugins/toolsets/opensearch/opensearch_logs.py +7 -7
- holmes/plugins/toolsets/opensearch/opensearch_ppl_query_docs.jinja2 +1616 -0
- holmes/plugins/toolsets/opensearch/opensearch_query_assist.py +78 -0
- holmes/plugins/toolsets/opensearch/opensearch_query_assist_instructions.jinja2 +223 -0
- holmes/plugins/toolsets/opensearch/opensearch_traces.py +13 -16
- holmes/plugins/toolsets/openshift.yaml +283 -0
- holmes/plugins/toolsets/prometheus/prometheus.py +915 -390
- holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +43 -2
- holmes/plugins/toolsets/prometheus/utils.py +28 -0
- holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +9 -10
- holmes/plugins/toolsets/robusta/robusta.py +236 -65
- holmes/plugins/toolsets/robusta/robusta_instructions.jinja2 +26 -9
- holmes/plugins/toolsets/runbook/runbook_fetcher.py +137 -26
- holmes/plugins/toolsets/service_discovery.py +1 -1
- holmes/plugins/toolsets/servicenow_tables/instructions.jinja2 +83 -0
- holmes/plugins/toolsets/servicenow_tables/servicenow_tables.py +426 -0
- holmes/plugins/toolsets/utils.py +88 -0
- holmes/utils/config_utils.py +91 -0
- holmes/utils/default_toolset_installation_guide.jinja2 +1 -22
- holmes/utils/env.py +7 -0
- holmes/utils/global_instructions.py +75 -10
- holmes/utils/holmes_status.py +2 -1
- holmes/utils/holmes_sync_toolsets.py +0 -2
- holmes/utils/krr_utils.py +188 -0
- holmes/utils/sentry_helper.py +41 -0
- holmes/utils/stream.py +61 -7
- holmes/version.py +34 -14
- holmesgpt-0.16.2a0.dist-info/LICENSE +178 -0
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/METADATA +29 -27
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/RECORD +126 -102
- holmes/core/performance_timing.py +0 -72
- holmes/plugins/toolsets/grafana/tempo_api.py +0 -124
- holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +0 -110
- holmes/plugins/toolsets/newrelic.py +0 -231
- holmes/plugins/toolsets/servicenow/install.md +0 -37
- holmes/plugins/toolsets/servicenow/instructions.jinja2 +0 -3
- holmes/plugins/toolsets/servicenow/servicenow.py +0 -219
- holmesgpt-0.13.2.dist-info/LICENSE.txt +0 -21
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/WHEEL +0 -0
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.16.2a0.dist-info}/entry_points.txt +0 -0
holmes/core/models.py
CHANGED
|
@@ -1,15 +1,94 @@
|
|
|
1
|
+
import json
|
|
1
2
|
from holmes.core.investigation_structured_output import InputSectionsDataType
|
|
2
|
-
from holmes.core.tool_calling_llm import ToolCallResult
|
|
3
3
|
from typing import Optional, List, Dict, Any, Union
|
|
4
4
|
from pydantic import BaseModel, model_validator, Field
|
|
5
5
|
from enum import Enum
|
|
6
6
|
|
|
7
|
+
from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TruncationMetadata(BaseModel):
|
|
11
|
+
tool_call_id: str
|
|
12
|
+
start_index: int
|
|
13
|
+
end_index: int
|
|
14
|
+
tool_name: str
|
|
15
|
+
original_token_count: int
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TruncationResult(BaseModel):
|
|
19
|
+
truncated_messages: list[dict]
|
|
20
|
+
truncations: list[TruncationMetadata]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ToolCallResult(BaseModel):
|
|
24
|
+
tool_call_id: str
|
|
25
|
+
tool_name: str
|
|
26
|
+
description: str
|
|
27
|
+
result: StructuredToolResult
|
|
28
|
+
size: Optional[int] = None
|
|
29
|
+
|
|
30
|
+
def as_tool_call_message(self):
|
|
31
|
+
return {
|
|
32
|
+
"tool_call_id": self.tool_call_id,
|
|
33
|
+
"role": "tool",
|
|
34
|
+
"name": self.tool_name,
|
|
35
|
+
"content": format_tool_result_data(self.result),
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def as_tool_result_response(self):
|
|
39
|
+
result_dump = self.result.model_dump()
|
|
40
|
+
result_dump["data"] = self.result.get_stringified_data()
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
"tool_call_id": self.tool_call_id,
|
|
44
|
+
"tool_name": self.tool_name,
|
|
45
|
+
"description": self.description,
|
|
46
|
+
"role": "tool",
|
|
47
|
+
"result": result_dump,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def as_streaming_tool_result_response(self):
|
|
51
|
+
result_dump = self.result.model_dump()
|
|
52
|
+
result_dump["data"] = self.result.get_stringified_data()
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
"tool_call_id": self.tool_call_id,
|
|
56
|
+
"role": "tool",
|
|
57
|
+
"description": self.description,
|
|
58
|
+
"name": self.tool_name,
|
|
59
|
+
"result": result_dump,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def format_tool_result_data(tool_result: StructuredToolResult) -> str:
|
|
64
|
+
tool_response = tool_result.data
|
|
65
|
+
if isinstance(tool_result.data, str):
|
|
66
|
+
tool_response = tool_result.data
|
|
67
|
+
else:
|
|
68
|
+
try:
|
|
69
|
+
if isinstance(tool_result.data, BaseModel):
|
|
70
|
+
tool_response = tool_result.data.model_dump_json(indent=2)
|
|
71
|
+
else:
|
|
72
|
+
tool_response = json.dumps(tool_result.data, indent=2)
|
|
73
|
+
except Exception:
|
|
74
|
+
tool_response = str(tool_result.data)
|
|
75
|
+
if tool_result.status == StructuredToolResultStatus.ERROR:
|
|
76
|
+
tool_response = f"{tool_result.error or 'Tool execution failed'}:\n\n{tool_result.data or ''}".strip()
|
|
77
|
+
|
|
78
|
+
if tool_result.params:
|
|
79
|
+
tool_response = (
|
|
80
|
+
f"Params used for the tool call: {json.dumps(tool_result.params)}. The tool call output follows on the next line.\n"
|
|
81
|
+
+ tool_response
|
|
82
|
+
)
|
|
83
|
+
return tool_response
|
|
84
|
+
|
|
7
85
|
|
|
8
86
|
class InvestigationResult(BaseModel):
|
|
9
87
|
analysis: Optional[str] = None
|
|
10
88
|
sections: Optional[Dict[str, Union[str, None]]] = None
|
|
11
89
|
tool_calls: List[ToolCallResult] = []
|
|
12
90
|
instructions: List[str] = []
|
|
91
|
+
metadata: Optional[Dict[Any, Any]] = None
|
|
13
92
|
|
|
14
93
|
|
|
15
94
|
class InvestigateRequest(BaseModel):
|
|
@@ -86,10 +165,31 @@ class ConversationRequest(BaseModel):
|
|
|
86
165
|
include_tool_call_results: bool = False
|
|
87
166
|
|
|
88
167
|
|
|
168
|
+
class PendingToolApproval(BaseModel):
|
|
169
|
+
"""Represents a tool call that requires user approval."""
|
|
170
|
+
|
|
171
|
+
tool_call_id: str
|
|
172
|
+
tool_name: str
|
|
173
|
+
description: str
|
|
174
|
+
params: Dict[str, Any]
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class ToolApprovalDecision(BaseModel):
|
|
178
|
+
"""Represents a user's decision on a tool approval."""
|
|
179
|
+
|
|
180
|
+
tool_call_id: str
|
|
181
|
+
approved: bool
|
|
182
|
+
|
|
183
|
+
|
|
89
184
|
class ChatRequestBaseModel(BaseModel):
|
|
90
185
|
conversation_history: Optional[list[dict]] = None
|
|
91
186
|
model: Optional[str] = None
|
|
92
187
|
stream: bool = Field(default=False)
|
|
188
|
+
enable_tool_approval: Optional[bool] = (
|
|
189
|
+
False # Optional boolean for backwards compatibility
|
|
190
|
+
)
|
|
191
|
+
tool_decisions: Optional[List[ToolApprovalDecision]] = None
|
|
192
|
+
additional_system_prompt: Optional[str] = None
|
|
93
193
|
|
|
94
194
|
# In our setup with litellm, the first message in conversation_history
|
|
95
195
|
# should follow the structure [{"role": "system", "content": ...}],
|
|
@@ -145,6 +245,8 @@ class ChatResponse(BaseModel):
|
|
|
145
245
|
conversation_history: list[dict]
|
|
146
246
|
tool_calls: Optional[List[ToolCallResult]] = []
|
|
147
247
|
follow_up_actions: Optional[List[FollowUpAction]] = []
|
|
248
|
+
pending_approvals: Optional[List[PendingToolApproval]] = None
|
|
249
|
+
metadata: Optional[Dict[Any, Any]] = None
|
|
148
250
|
|
|
149
251
|
|
|
150
252
|
class WorkloadHealthInvestigationResult(BaseModel):
|
holmes/core/openai_formatting.py
CHANGED
|
@@ -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
|
@@ -57,7 +57,7 @@ def build_initial_ask_messages(
|
|
|
57
57
|
system_prompt_template = "builtin://generic_ask.jinja2"
|
|
58
58
|
template_context = {
|
|
59
59
|
"toolsets": tool_executor.toolsets,
|
|
60
|
-
"
|
|
60
|
+
"runbooks_enabled": True if runbooks else False,
|
|
61
61
|
"system_prompt_additions": system_prompt_additions or "",
|
|
62
62
|
}
|
|
63
63
|
system_prompt_rendered = load_and_render_prompt(
|
holmes/core/safeguards.py
CHANGED
|
@@ -5,7 +5,7 @@ from pydantic import ValidationError
|
|
|
5
5
|
|
|
6
6
|
from holmes.common.env_vars import TOOL_CALL_SAFEGUARDS_ENABLED
|
|
7
7
|
from holmes.plugins.toolsets.logging_utils.logging_api import POD_LOGGING_TOOL_NAME
|
|
8
|
-
from holmes.core.tools import StructuredToolResult,
|
|
8
|
+
from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
|
|
9
9
|
from holmes.plugins.toolsets.logging_utils.logging_api import FetchPodLogsParams
|
|
10
10
|
|
|
11
11
|
|
|
@@ -39,7 +39,7 @@ def _has_previous_unfiltered_pod_logs_call(
|
|
|
39
39
|
result = tool_call.get("result", {})
|
|
40
40
|
if (
|
|
41
41
|
tool_call.get("tool_name") == POD_LOGGING_TOOL_NAME
|
|
42
|
-
and result.get("status") ==
|
|
42
|
+
and result.get("status") == StructuredToolResultStatus.NO_DATA
|
|
43
43
|
and result.get("params")
|
|
44
44
|
):
|
|
45
45
|
params = FetchPodLogsParams(**result.get("params"))
|
|
@@ -94,7 +94,7 @@ def prevent_overly_repeated_tool_call(
|
|
|
94
94
|
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
95
|
"""
|
|
96
96
|
return StructuredToolResult(
|
|
97
|
-
status=
|
|
97
|
+
status=StructuredToolResultStatus.ERROR,
|
|
98
98
|
error=(
|
|
99
99
|
"Refusing to run this tool call because it has already been called during this session with the exact same parameters.\n"
|
|
100
100
|
"Move on with your investigation to a different tool or change the parameter values."
|
|
@@ -106,7 +106,7 @@ def prevent_overly_repeated_tool_call(
|
|
|
106
106
|
tool_name=tool_name, tool_params=tool_params, tool_calls=tool_calls
|
|
107
107
|
):
|
|
108
108
|
return StructuredToolResult(
|
|
109
|
-
status=
|
|
109
|
+
status=StructuredToolResultStatus.ERROR,
|
|
110
110
|
error=(
|
|
111
111
|
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
112
|
"This tool call would also have returned no data.\n"
|