holmesgpt 0.13.3a0__py3-none-any.whl → 0.14.1a0__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 (82) hide show
  1. holmes/__init__.py +1 -1
  2. holmes/clients/robusta_client.py +10 -2
  3. holmes/common/env_vars.py +8 -1
  4. holmes/config.py +66 -139
  5. holmes/core/investigation.py +1 -2
  6. holmes/core/llm.py +256 -51
  7. holmes/core/models.py +2 -0
  8. holmes/core/safeguards.py +4 -4
  9. holmes/core/supabase_dal.py +14 -8
  10. holmes/core/tool_calling_llm.py +193 -176
  11. holmes/core/tools.py +260 -25
  12. holmes/core/tools_utils/data_types.py +81 -0
  13. holmes/core/tools_utils/tool_context_window_limiter.py +33 -0
  14. holmes/core/tools_utils/tool_executor.py +2 -2
  15. holmes/core/toolset_manager.py +150 -3
  16. holmes/core/tracing.py +6 -1
  17. holmes/core/transformers/__init__.py +23 -0
  18. holmes/core/transformers/base.py +62 -0
  19. holmes/core/transformers/llm_summarize.py +174 -0
  20. holmes/core/transformers/registry.py +122 -0
  21. holmes/core/transformers/transformer.py +31 -0
  22. holmes/main.py +5 -0
  23. holmes/plugins/toolsets/aks-node-health.yaml +46 -0
  24. holmes/plugins/toolsets/aks.yaml +64 -0
  25. holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +17 -15
  26. holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +8 -4
  27. holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +7 -3
  28. holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +3 -3
  29. holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +3 -3
  30. holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +7 -3
  31. holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +4 -4
  32. holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +7 -3
  33. holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +7 -3
  34. holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +7 -3
  35. holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +7 -3
  36. holmes/plugins/toolsets/bash/bash_toolset.py +6 -6
  37. holmes/plugins/toolsets/bash/common/bash.py +7 -7
  38. holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +5 -3
  39. holmes/plugins/toolsets/datadog/toolset_datadog_general.py +16 -17
  40. holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +9 -10
  41. holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +21 -22
  42. holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +8 -8
  43. holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +18 -19
  44. holmes/plugins/toolsets/git.py +22 -22
  45. holmes/plugins/toolsets/grafana/common.py +14 -2
  46. holmes/plugins/toolsets/grafana/grafana_tempo_api.py +473 -0
  47. holmes/plugins/toolsets/grafana/toolset_grafana.py +4 -4
  48. holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +3 -3
  49. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.jinja2 +246 -11
  50. holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +662 -290
  51. holmes/plugins/toolsets/grafana/trace_parser.py +1 -1
  52. holmes/plugins/toolsets/internet/internet.py +3 -3
  53. holmes/plugins/toolsets/internet/notion.py +3 -3
  54. holmes/plugins/toolsets/investigator/core_investigation.py +3 -3
  55. holmes/plugins/toolsets/kafka.py +18 -18
  56. holmes/plugins/toolsets/kubernetes.yaml +58 -0
  57. holmes/plugins/toolsets/kubernetes_logs.py +6 -6
  58. holmes/plugins/toolsets/kubernetes_logs.yaml +32 -0
  59. holmes/plugins/toolsets/mcp/toolset_mcp.py +4 -4
  60. holmes/plugins/toolsets/newrelic.py +8 -8
  61. holmes/plugins/toolsets/opensearch/opensearch.py +5 -5
  62. holmes/plugins/toolsets/opensearch/opensearch_logs.py +7 -7
  63. holmes/plugins/toolsets/opensearch/opensearch_traces.py +10 -10
  64. holmes/plugins/toolsets/prometheus/prometheus.py +172 -39
  65. holmes/plugins/toolsets/prometheus/prometheus_instructions.jinja2 +25 -0
  66. holmes/plugins/toolsets/prometheus/utils.py +28 -0
  67. holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +6 -4
  68. holmes/plugins/toolsets/robusta/robusta.py +10 -10
  69. holmes/plugins/toolsets/runbook/runbook_fetcher.py +4 -4
  70. holmes/plugins/toolsets/servicenow/servicenow.py +6 -6
  71. holmes/plugins/toolsets/utils.py +88 -0
  72. holmes/utils/config_utils.py +91 -0
  73. holmes/utils/env.py +7 -0
  74. holmes/utils/holmes_status.py +2 -1
  75. holmes/utils/sentry_helper.py +41 -0
  76. holmes/utils/stream.py +9 -0
  77. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/METADATA +10 -14
  78. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/RECORD +81 -71
  79. holmes/plugins/toolsets/grafana/tempo_api.py +0 -124
  80. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/LICENSE.txt +0 -0
  81. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/WHEEL +0 -0
  82. {holmesgpt-0.13.3a0.dist-info → holmesgpt-0.14.1a0.dist-info}/entry_points.txt +0 -0
@@ -12,7 +12,7 @@ from holmes.core.tools import (
12
12
  ToolParameter,
13
13
  Toolset,
14
14
  StructuredToolResult,
15
- ToolResultStatus,
15
+ StructuredToolResultStatus,
16
16
  ToolsetTag,
17
17
  )
18
18
  from holmes.plugins.toolsets.datadog.datadog_api import (
@@ -49,7 +49,7 @@ class DatadogTracesToolset(Toolset):
49
49
  super().__init__(
50
50
  name="datadog/traces",
51
51
  description="Toolset for interacting with Datadog APM to fetch and analyze traces",
52
- docs_url="https://docs.datadoghq.com/api/latest/spans/",
52
+ docs_url="https://holmesgpt.dev/data-sources/builtin-toolsets/datadog/",
53
53
  icon_url="https://imgix.datadoghq.com//img/about/presskit/DDlogo.jpg",
54
54
  prerequisites=[CallablePrerequisite(callable=self.prerequisites_callable)],
55
55
  tools=[
@@ -57,7 +57,6 @@ class DatadogTracesToolset(Toolset):
57
57
  FetchDatadogTraceById(toolset=self),
58
58
  FetchDatadogSpansByFilter(toolset=self),
59
59
  ],
60
- experimental=True,
61
60
  tags=[ToolsetTag.CORE],
62
61
  )
63
62
  self._reload_instructions()
@@ -217,7 +216,7 @@ class FetchDatadogTracesList(BaseDatadogTracesTool):
217
216
  """Execute the tool to fetch traces."""
218
217
  if not self.toolset.dd_config:
219
218
  return StructuredToolResult(
220
- status=ToolResultStatus.ERROR,
219
+ status=StructuredToolResultStatus.ERROR,
221
220
  error="Datadog configuration not initialized",
222
221
  params=params,
223
222
  )
@@ -306,13 +305,13 @@ class FetchDatadogTracesList(BaseDatadogTracesTool):
306
305
  formatted_output = format_traces_list(spans, limit=params.get("limit", 50))
307
306
  if not formatted_output:
308
307
  return StructuredToolResult(
309
- status=ToolResultStatus.NO_DATA,
308
+ status=StructuredToolResultStatus.NO_DATA,
310
309
  params=params,
311
310
  data="No matching traces found.",
312
311
  )
313
312
 
314
313
  return StructuredToolResult(
315
- status=ToolResultStatus.SUCCESS,
314
+ status=StructuredToolResultStatus.SUCCESS,
316
315
  data=formatted_output,
317
316
  params=params,
318
317
  )
@@ -331,7 +330,7 @@ class FetchDatadogTracesList(BaseDatadogTracesTool):
331
330
  error_msg = f"Exception while querying Datadog: {str(e)}"
332
331
 
333
332
  return StructuredToolResult(
334
- status=ToolResultStatus.ERROR,
333
+ status=StructuredToolResultStatus.ERROR,
335
334
  error=error_msg,
336
335
  params=params,
337
336
  invocation=(
@@ -344,7 +343,7 @@ class FetchDatadogTracesList(BaseDatadogTracesTool):
344
343
  except Exception as e:
345
344
  logging.exception(e, exc_info=True)
346
345
  return StructuredToolResult(
347
- status=ToolResultStatus.ERROR,
346
+ status=StructuredToolResultStatus.ERROR,
348
347
  error=f"Unexpected error: {str(e)}",
349
348
  params=params,
350
349
  invocation=(
@@ -383,7 +382,7 @@ class FetchDatadogTraceById(BaseDatadogTracesTool):
383
382
  """Execute the tool to fetch trace details."""
384
383
  if not self.toolset.dd_config:
385
384
  return StructuredToolResult(
386
- status=ToolResultStatus.ERROR,
385
+ status=StructuredToolResultStatus.ERROR,
387
386
  error="Datadog configuration not initialized",
388
387
  params=params,
389
388
  )
@@ -391,7 +390,7 @@ class FetchDatadogTraceById(BaseDatadogTracesTool):
391
390
  trace_id = params.get("trace_id")
392
391
  if not trace_id:
393
392
  return StructuredToolResult(
394
- status=ToolResultStatus.ERROR,
393
+ status=StructuredToolResultStatus.ERROR,
395
394
  error="trace_id parameter is required",
396
395
  params=params,
397
396
  )
@@ -445,13 +444,13 @@ class FetchDatadogTraceById(BaseDatadogTracesTool):
445
444
  formatted_output = format_trace_hierarchy(trace_id, spans)
446
445
  if not formatted_output:
447
446
  return StructuredToolResult(
448
- status=ToolResultStatus.NO_DATA,
447
+ status=StructuredToolResultStatus.NO_DATA,
449
448
  params=params,
450
449
  data=f"No trace found for trace_id: {trace_id}",
451
450
  )
452
451
 
453
452
  return StructuredToolResult(
454
- status=ToolResultStatus.SUCCESS,
453
+ status=StructuredToolResultStatus.SUCCESS,
455
454
  data=formatted_output,
456
455
  params=params,
457
456
  )
@@ -470,7 +469,7 @@ class FetchDatadogTraceById(BaseDatadogTracesTool):
470
469
  error_msg = f"Exception while querying Datadog: {str(e)}"
471
470
 
472
471
  return StructuredToolResult(
473
- status=ToolResultStatus.ERROR,
472
+ status=StructuredToolResultStatus.ERROR,
474
473
  error=error_msg,
475
474
  params=params,
476
475
  invocation=(
@@ -483,7 +482,7 @@ class FetchDatadogTraceById(BaseDatadogTracesTool):
483
482
  except Exception as e:
484
483
  logging.exception(e, exc_info=True)
485
484
  return StructuredToolResult(
486
- status=ToolResultStatus.ERROR,
485
+ status=StructuredToolResultStatus.ERROR,
487
486
  error=f"Unexpected error: {str(e)}",
488
487
  params=params,
489
488
  invocation=(
@@ -566,7 +565,7 @@ class FetchDatadogSpansByFilter(BaseDatadogTracesTool):
566
565
  """Execute the tool to search spans."""
567
566
  if not self.toolset.dd_config:
568
567
  return StructuredToolResult(
569
- status=ToolResultStatus.ERROR,
568
+ status=StructuredToolResultStatus.ERROR,
570
569
  error="Datadog configuration not initialized",
571
570
  params=params,
572
571
  )
@@ -654,13 +653,13 @@ class FetchDatadogSpansByFilter(BaseDatadogTracesTool):
654
653
  formatted_output = format_spans_search(spans)
655
654
  if not formatted_output:
656
655
  return StructuredToolResult(
657
- status=ToolResultStatus.NO_DATA,
656
+ status=StructuredToolResultStatus.NO_DATA,
658
657
  params=params,
659
658
  data="No matching spans found.",
660
659
  )
661
660
 
662
661
  return StructuredToolResult(
663
- status=ToolResultStatus.SUCCESS,
662
+ status=StructuredToolResultStatus.SUCCESS,
664
663
  data=formatted_output,
665
664
  params=params,
666
665
  )
@@ -678,7 +677,7 @@ class FetchDatadogSpansByFilter(BaseDatadogTracesTool):
678
677
  error_msg = f"Exception while querying Datadog: {str(e)}"
679
678
 
680
679
  return StructuredToolResult(
681
- status=ToolResultStatus.ERROR,
680
+ status=StructuredToolResultStatus.ERROR,
682
681
  error=error_msg,
683
682
  params=params,
684
683
  invocation=(
@@ -691,7 +690,7 @@ class FetchDatadogSpansByFilter(BaseDatadogTracesTool):
691
690
  except Exception as e:
692
691
  logging.exception(e, exc_info=True)
693
692
  return StructuredToolResult(
694
- status=ToolResultStatus.ERROR,
693
+ status=StructuredToolResultStatus.ERROR,
695
694
  error=f"Unexpected error: {str(e)}",
696
695
  params=params,
697
696
  invocation=(
@@ -4,7 +4,7 @@ import requests # type: ignore
4
4
  import os
5
5
  from typing import Any, Optional, Dict, List, Tuple
6
6
  from pydantic import BaseModel
7
- from holmes.core.tools import StructuredToolResult, ToolResultStatus
7
+ from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
8
8
 
9
9
  from holmes.core.tools import (
10
10
  Toolset,
@@ -33,7 +33,7 @@ class GitToolset(Toolset):
33
33
  super().__init__(
34
34
  name="git",
35
35
  description="Runs git commands to read repos and create PRs",
36
- docs_url="https://docs.github.com/en/rest",
36
+ docs_url="https://holmesgpt.dev/data-sources/builtin-toolsets/github/",
37
37
  icon_url="https://upload.wikimedia.org/wikipedia/commons/9/91/Octicons-mark-github.svg",
38
38
  prerequisites=[CallablePrerequisite(callable=self.prerequisites_callable)],
39
39
  tools=[
@@ -259,7 +259,7 @@ class GitReadFileWithLineNumbers(Tool):
259
259
  resp = requests.get(url, headers=headers)
260
260
  if resp.status_code != 200:
261
261
  return StructuredToolResult(
262
- status=ToolResultStatus.ERROR,
262
+ status=StructuredToolResultStatus.ERROR,
263
263
  data=self.toolset._sanitize_error(
264
264
  f"Error fetching file: {resp.text}"
265
265
  ),
@@ -268,13 +268,13 @@ class GitReadFileWithLineNumbers(Tool):
268
268
  content = base64.b64decode(resp.json()["content"]).decode().splitlines()
269
269
  numbered = "\n".join(f"{i+1}: {line}" for i, line in enumerate(content))
270
270
  return StructuredToolResult(
271
- status=ToolResultStatus.SUCCESS,
271
+ status=StructuredToolResultStatus.SUCCESS,
272
272
  data=numbered,
273
273
  params=params,
274
274
  )
275
275
  except Exception as e:
276
276
  return StructuredToolResult(
277
- status=ToolResultStatus.ERROR,
277
+ status=StructuredToolResultStatus.ERROR,
278
278
  data=self.toolset._sanitize_error(str(e)),
279
279
  params=params,
280
280
  )
@@ -304,7 +304,7 @@ class GitListFiles(Tool):
304
304
  resp = requests.get(url, headers=headers)
305
305
  if resp.status_code != 200:
306
306
  return StructuredToolResult(
307
- status=ToolResultStatus.ERROR,
307
+ status=StructuredToolResultStatus.ERROR,
308
308
  data=self.toolset._sanitize_error(
309
309
  f"Error listing files: {resp.text}"
310
310
  ),
@@ -312,13 +312,13 @@ class GitListFiles(Tool):
312
312
  )
313
313
  paths = [entry["path"] for entry in resp.json()["tree"]]
314
314
  return StructuredToolResult(
315
- status=ToolResultStatus.SUCCESS,
315
+ status=StructuredToolResultStatus.SUCCESS,
316
316
  data=paths,
317
317
  params=params,
318
318
  )
319
319
  except Exception as e:
320
320
  return StructuredToolResult(
321
- status=ToolResultStatus.ERROR,
321
+ status=StructuredToolResultStatus.ERROR,
322
322
  data=self.toolset._sanitize_error(str(e)),
323
323
  params=params,
324
324
  )
@@ -353,13 +353,13 @@ class GitListOpenPRs(Tool):
353
353
  for pr in prs
354
354
  ]
355
355
  return StructuredToolResult(
356
- status=ToolResultStatus.SUCCESS,
356
+ status=StructuredToolResultStatus.SUCCESS,
357
357
  data=formatted,
358
358
  params=params,
359
359
  )
360
360
  except Exception as e:
361
361
  return StructuredToolResult(
362
- status=ToolResultStatus.ERROR,
362
+ status=StructuredToolResultStatus.ERROR,
363
363
  data=self.toolset._sanitize_error(str(e)),
364
364
  params=params,
365
365
  )
@@ -413,14 +413,14 @@ class GitExecuteChanges(Tool):
413
413
  ) -> StructuredToolResult:
414
414
  def error(msg: str) -> StructuredToolResult:
415
415
  return StructuredToolResult(
416
- status=ToolResultStatus.ERROR,
416
+ status=StructuredToolResultStatus.ERROR,
417
417
  data=self.toolset._sanitize_error(msg),
418
418
  params=params,
419
419
  )
420
420
 
421
421
  def success(msg: Any) -> StructuredToolResult:
422
422
  return StructuredToolResult(
423
- status=ToolResultStatus.SUCCESS, data=msg, params=params
423
+ status=StructuredToolResultStatus.SUCCESS, data=msg, params=params
424
424
  )
425
425
 
426
426
  def modify_lines(lines: List[str]) -> List[str]:
@@ -643,24 +643,24 @@ class GitUpdatePR(Tool):
643
643
  # Validate inputs
644
644
  if not commit_message.strip():
645
645
  return StructuredToolResult(
646
- status=ToolResultStatus.ERROR,
646
+ status=StructuredToolResultStatus.ERROR,
647
647
  error="Tool call failed to run: Commit message cannot be empty",
648
648
  )
649
649
  if not filename.strip():
650
650
  return StructuredToolResult(
651
- status=ToolResultStatus.ERROR,
651
+ status=StructuredToolResultStatus.ERROR,
652
652
  error="Tool call failed to run: Filename cannot be empty",
653
653
  )
654
654
  if line < 1:
655
655
  return StructuredToolResult(
656
- status=ToolResultStatus.ERROR,
656
+ status=StructuredToolResultStatus.ERROR,
657
657
  error="Tool call failed to run: Line number must be positive",
658
658
  )
659
659
 
660
660
  # Verify this is a PR created by our tool
661
661
  if not self.toolset.is_created_pr(pr_number):
662
662
  return StructuredToolResult(
663
- status=ToolResultStatus.ERROR,
663
+ status=StructuredToolResultStatus.ERROR,
664
664
  error=f"Tool call failed to run: PR #{pr_number} was not created by this tool. Only PRs created using git_execute_changes can be updated.",
665
665
  )
666
666
 
@@ -714,7 +714,7 @@ class GitUpdatePR(Tool):
714
714
  del content_lines[line - 1]
715
715
  else:
716
716
  return StructuredToolResult(
717
- status=ToolResultStatus.ERROR,
717
+ status=StructuredToolResultStatus.ERROR,
718
718
  error=f"Tool call failed to run: Invalid command: {command}",
719
719
  )
720
720
 
@@ -722,7 +722,7 @@ class GitUpdatePR(Tool):
722
722
 
723
723
  if dry_run:
724
724
  return StructuredToolResult(
725
- status=ToolResultStatus.SUCCESS,
725
+ status=StructuredToolResultStatus.SUCCESS,
726
726
  data=f"DRY RUN: Updated content for PR #{pr_number}:\n\n{updated_content}",
727
727
  )
728
728
 
@@ -731,13 +731,13 @@ class GitUpdatePR(Tool):
731
731
  pr_number, filename, updated_content, commit_message
732
732
  )
733
733
  return StructuredToolResult(
734
- status=ToolResultStatus.SUCCESS,
734
+ status=StructuredToolResultStatus.SUCCESS,
735
735
  data=f"Added commit to PR #{pr_number} successfully",
736
736
  )
737
737
 
738
738
  except Exception as e:
739
739
  return StructuredToolResult(
740
- status=ToolResultStatus.ERROR,
740
+ status=StructuredToolResultStatus.ERROR,
741
741
  error=self.toolset._sanitize_error(
742
742
  f"Tool call failed to run: Error updating PR: {str(e)}"
743
743
  ),
@@ -745,14 +745,14 @@ class GitUpdatePR(Tool):
745
745
 
746
746
  except requests.exceptions.RequestException as e:
747
747
  return StructuredToolResult(
748
- status=ToolResultStatus.ERROR,
748
+ status=StructuredToolResultStatus.ERROR,
749
749
  error=self.toolset._sanitize_error(
750
750
  f"Tool call failed to run: Network error: {str(e)}"
751
751
  ),
752
752
  )
753
753
  except Exception as e:
754
754
  return StructuredToolResult(
755
- status=ToolResultStatus.ERROR,
755
+ status=StructuredToolResultStatus.ERROR,
756
756
  error=self.toolset._sanitize_error(
757
757
  f"Tool call failed to run: Unexpected error: {str(e)}"
758
758
  ),
@@ -3,7 +3,7 @@ from typing import Dict, Optional
3
3
  from pydantic import BaseModel
4
4
  import datetime
5
5
 
6
- from holmes.core.tools import StructuredToolResult, ToolResultStatus
6
+ from holmes.core.tools import StructuredToolResult, StructuredToolResultStatus
7
7
 
8
8
 
9
9
  class GrafanaConfig(BaseModel):
@@ -61,8 +61,20 @@ def ensure_grafana_uid_or_return_error_result(
61
61
  ) -> Optional[StructuredToolResult]:
62
62
  if not config.grafana_datasource_uid:
63
63
  return StructuredToolResult(
64
- status=ToolResultStatus.ERROR,
64
+ status=StructuredToolResultStatus.ERROR,
65
65
  error="This tool only works when the toolset is configued ",
66
66
  )
67
67
  else:
68
68
  return None
69
+
70
+
71
+ class GrafanaTempoLabelsConfig(BaseModel):
72
+ pod: str = "k8s.pod.name"
73
+ namespace: str = "k8s.namespace.name"
74
+ deployment: str = "k8s.deployment.name"
75
+ node: str = "k8s.node.name"
76
+ service: str = "service.name"
77
+
78
+
79
+ class GrafanaTempoConfig(GrafanaConfig):
80
+ labels: GrafanaTempoLabelsConfig = GrafanaTempoLabelsConfig()