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.
- holmes/__init__.py +3 -5
- holmes/clients/robusta_client.py +20 -6
- holmes/common/env_vars.py +58 -3
- holmes/common/openshift.py +1 -1
- holmes/config.py +123 -148
- holmes/core/conversations.py +71 -15
- holmes/core/feedback.py +191 -0
- holmes/core/investigation.py +31 -39
- holmes/core/investigation_structured_output.py +3 -3
- holmes/core/issue.py +1 -1
- holmes/core/llm.py +508 -88
- holmes/core/models.py +108 -4
- holmes/core/openai_formatting.py +14 -1
- holmes/core/prompt.py +48 -3
- holmes/core/runbooks.py +1 -0
- holmes/core/safeguards.py +8 -6
- holmes/core/supabase_dal.py +295 -100
- holmes/core/tool_calling_llm.py +489 -428
- holmes/core/tools.py +325 -56
- holmes/core/tools_utils/token_counting.py +21 -0
- holmes/core/tools_utils/tool_context_window_limiter.py +40 -0
- holmes/core/tools_utils/tool_executor.py +0 -13
- holmes/core/tools_utils/toolset_utils.py +1 -0
- holmes/core/toolset_manager.py +191 -5
- holmes/core/tracing.py +19 -3
- holmes/core/transformers/__init__.py +23 -0
- holmes/core/transformers/base.py +63 -0
- holmes/core/transformers/llm_summarize.py +175 -0
- holmes/core/transformers/registry.py +123 -0
- holmes/core/transformers/transformer.py +32 -0
- holmes/core/truncation/compaction.py +94 -0
- holmes/core/truncation/dal_truncation_utils.py +23 -0
- holmes/core/truncation/input_context_window_limiter.py +219 -0
- holmes/interactive.py +228 -31
- holmes/main.py +23 -40
- holmes/plugins/interfaces.py +2 -1
- holmes/plugins/prompts/__init__.py +2 -1
- holmes/plugins/prompts/_fetch_logs.jinja2 +31 -6
- holmes/plugins/prompts/_general_instructions.jinja2 +1 -2
- holmes/plugins/prompts/_runbook_instructions.jinja2 +24 -12
- holmes/plugins/prompts/base_user_prompt.jinja2 +7 -0
- holmes/plugins/prompts/conversation_history_compaction.jinja2 +89 -0
- holmes/plugins/prompts/generic_ask.jinja2 +0 -4
- holmes/plugins/prompts/generic_ask_conversation.jinja2 +0 -1
- holmes/plugins/prompts/generic_ask_for_issue_conversation.jinja2 +0 -1
- holmes/plugins/prompts/generic_investigation.jinja2 +0 -1
- holmes/plugins/prompts/investigation_procedure.jinja2 +50 -1
- holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +0 -1
- holmes/plugins/prompts/kubernetes_workload_chat.jinja2 +0 -1
- holmes/plugins/runbooks/__init__.py +145 -17
- holmes/plugins/runbooks/catalog.json +2 -0
- holmes/plugins/sources/github/__init__.py +4 -2
- holmes/plugins/sources/prometheus/models.py +1 -0
- holmes/plugins/toolsets/__init__.py +44 -27
- holmes/plugins/toolsets/aks-node-health.yaml +46 -0
- holmes/plugins/toolsets/aks.yaml +64 -0
- holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +38 -47
- holmes/plugins/toolsets/azure_sql/apis/alert_monitoring_api.py +3 -2
- holmes/plugins/toolsets/azure_sql/apis/azure_sql_api.py +2 -1
- holmes/plugins/toolsets/azure_sql/apis/connection_failure_api.py +3 -2
- holmes/plugins/toolsets/azure_sql/apis/connection_monitoring_api.py +3 -1
- holmes/plugins/toolsets/azure_sql/apis/storage_analysis_api.py +3 -1
- holmes/plugins/toolsets/azure_sql/azure_sql_toolset.py +12 -13
- holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +15 -12
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +15 -12
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +11 -11
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +11 -9
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +15 -12
- holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +15 -15
- holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +11 -8
- holmes/plugins/toolsets/azure_sql/utils.py +0 -32
- holmes/plugins/toolsets/bash/argocd/__init__.py +3 -3
- holmes/plugins/toolsets/bash/aws/__init__.py +4 -4
- holmes/plugins/toolsets/bash/azure/__init__.py +4 -4
- holmes/plugins/toolsets/bash/bash_toolset.py +11 -15
- holmes/plugins/toolsets/bash/common/bash.py +23 -13
- holmes/plugins/toolsets/bash/common/bash_command.py +1 -1
- holmes/plugins/toolsets/bash/common/stringify.py +1 -1
- holmes/plugins/toolsets/bash/kubectl/__init__.py +2 -1
- holmes/plugins/toolsets/bash/kubectl/constants.py +0 -1
- holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +3 -4
- holmes/plugins/toolsets/bash/parse_command.py +12 -13
- holmes/plugins/toolsets/cilium.yaml +284 -0
- holmes/plugins/toolsets/connectivity_check.py +124 -0
- holmes/plugins/toolsets/coralogix/api.py +132 -119
- holmes/plugins/toolsets/coralogix/coralogix.jinja2 +14 -0
- holmes/plugins/toolsets/coralogix/toolset_coralogix.py +219 -0
- holmes/plugins/toolsets/coralogix/utils.py +15 -79
- holmes/plugins/toolsets/datadog/datadog_api.py +525 -26
- holmes/plugins/toolsets/datadog/datadog_logs_instructions.jinja2 +55 -11
- holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +3 -3
- holmes/plugins/toolsets/datadog/datadog_models.py +59 -0
- holmes/plugins/toolsets/datadog/datadog_url_utils.py +213 -0
- holmes/plugins/toolsets/datadog/instructions_datadog_traces.jinja2 +165 -28
- holmes/plugins/toolsets/datadog/toolset_datadog_general.py +417 -241
- holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +234 -214
- holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +167 -79
- holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +374 -363
- holmes/plugins/toolsets/elasticsearch/__init__.py +6 -0
- holmes/plugins/toolsets/elasticsearch/elasticsearch.py +834 -0
- holmes/plugins/toolsets/elasticsearch/opensearch_ppl_query_docs.jinja2 +1616 -0
- holmes/plugins/toolsets/elasticsearch/opensearch_query_assist.py +78 -0
- holmes/plugins/toolsets/elasticsearch/opensearch_query_assist_instructions.jinja2 +223 -0
- holmes/plugins/toolsets/git.py +54 -50
- holmes/plugins/toolsets/grafana/base_grafana_toolset.py +16 -4
- holmes/plugins/toolsets/grafana/common.py +13 -29
- holmes/plugins/toolsets/grafana/grafana_tempo_api.py +455 -0
- holmes/plugins/toolsets/grafana/loki/instructions.jinja2 +25 -0
- holmes/plugins/toolsets/grafana/loki/toolset_grafana_loki.py +191 -0
- holmes/plugins/toolsets/grafana/loki_api.py +4 -0
- holmes/plugins/toolsets/grafana/toolset_grafana.py +293 -89
- holmes/plugins/toolsets/grafana/toolset_grafana_dashboard.jinja2 +49 -0
- holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +246 -11
- holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +820 -292
- holmes/plugins/toolsets/grafana/trace_parser.py +4 -3
- holmes/plugins/toolsets/internet/internet.py +15 -16
- holmes/plugins/toolsets/internet/notion.py +9 -11
- holmes/plugins/toolsets/investigator/core_investigation.py +44 -36
- holmes/plugins/toolsets/investigator/model.py +3 -1
- holmes/plugins/toolsets/json_filter_mixin.py +134 -0
- holmes/plugins/toolsets/kafka.py +36 -42
- holmes/plugins/toolsets/kubernetes.yaml +317 -113
- holmes/plugins/toolsets/kubernetes_logs.py +9 -9
- holmes/plugins/toolsets/kubernetes_logs.yaml +32 -0
- holmes/plugins/toolsets/logging_utils/logging_api.py +94 -8
- holmes/plugins/toolsets/mcp/toolset_mcp.py +218 -64
- holmes/plugins/toolsets/newrelic/new_relic_api.py +165 -0
- holmes/plugins/toolsets/newrelic/newrelic.jinja2 +65 -0
- holmes/plugins/toolsets/newrelic/newrelic.py +320 -0
- holmes/plugins/toolsets/openshift.yaml +283 -0
- holmes/plugins/toolsets/prometheus/prometheus.py +1202 -421
- holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +54 -5
- holmes/plugins/toolsets/prometheus/utils.py +28 -0
- holmes/plugins/toolsets/rabbitmq/api.py +23 -4
- holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +13 -14
- holmes/plugins/toolsets/robusta/robusta.py +239 -68
- holmes/plugins/toolsets/robusta/robusta_instructions.jinja2 +26 -9
- holmes/plugins/toolsets/runbook/runbook_fetcher.py +157 -27
- 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/connection_utils.py +31 -0
- holmes/utils/console/result.py +10 -0
- holmes/utils/default_toolset_installation_guide.jinja2 +1 -22
- holmes/utils/env.py +7 -0
- holmes/utils/file_utils.py +2 -1
- holmes/utils/global_instructions.py +60 -11
- holmes/utils/holmes_status.py +6 -4
- holmes/utils/holmes_sync_toolsets.py +0 -2
- holmes/utils/krr_utils.py +188 -0
- holmes/utils/log.py +15 -0
- holmes/utils/markdown_utils.py +2 -3
- holmes/utils/memory_limit.py +58 -0
- holmes/utils/sentry_helper.py +64 -0
- holmes/utils/stream.py +69 -8
- holmes/utils/tags.py +4 -3
- holmes/version.py +37 -15
- holmesgpt-0.18.4.dist-info/LICENSE +178 -0
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/METADATA +35 -31
- holmesgpt-0.18.4.dist-info/RECORD +258 -0
- holmes/core/performance_timing.py +0 -72
- holmes/plugins/toolsets/aws.yaml +0 -80
- holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +0 -112
- holmes/plugins/toolsets/datadog/datadog_traces_formatter.py +0 -310
- holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +0 -739
- holmes/plugins/toolsets/grafana/grafana_api.py +0 -42
- 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/opensearch/opensearch.py +0 -257
- holmes/plugins/toolsets/opensearch/opensearch_logs.py +0 -161
- holmes/plugins/toolsets/opensearch/opensearch_traces.py +0 -218
- holmes/plugins/toolsets/opensearch/opensearch_traces_instructions.jinja2 +0 -12
- holmes/plugins/toolsets/opensearch/opensearch_utils.py +0 -166
- holmes/plugins/toolsets/servicenow/install.md +0 -37
- holmes/plugins/toolsets/servicenow/instructions.jinja2 +0 -3
- holmes/plugins/toolsets/servicenow/servicenow.py +0 -219
- holmes/utils/keygen_utils.py +0 -6
- holmesgpt-0.13.2.dist-info/LICENSE.txt +0 -21
- holmesgpt-0.13.2.dist-info/RECORD +0 -234
- /holmes/plugins/toolsets/{opensearch → newrelic}/__init__.py +0 -0
- {holmesgpt-0.13.2.dist-info → holmesgpt-0.18.4.dist-info}/WHEEL +0 -0
- {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
|
-
|
|
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):
|
holmes/core/openai_formatting.py
CHANGED
|
@@ -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
|
-
"
|
|
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
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.
|
|
8
|
-
from holmes.
|
|
9
|
-
|
|
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") ==
|
|
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=
|
|
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=
|
|
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"
|