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
@@ -1,7 +1,10 @@
1
1
  import logging
2
+ from enum import Enum
2
3
  from typing import Any, Dict, List, Optional, Tuple, Union
3
4
 
4
5
  import yaml # type: ignore
6
+ from confluent_kafka import Consumer
7
+ from confluent_kafka._model import Node
5
8
  from confluent_kafka.admin import (
6
9
  AdminClient,
7
10
  BrokerMetadata,
@@ -17,18 +20,16 @@ from confluent_kafka.admin import (
17
20
  PartitionMetadata,
18
21
  TopicMetadata,
19
22
  )
20
- from confluent_kafka import Consumer
21
- from confluent_kafka._model import Node
22
- from enum import Enum
23
23
  from confluent_kafka.admin import _TopicPartition as TopicPartition
24
24
  from pydantic import BaseModel, ConfigDict
25
25
 
26
26
  from holmes.core.tools import (
27
27
  CallablePrerequisite,
28
28
  StructuredToolResult,
29
+ StructuredToolResultStatus,
29
30
  Tool,
31
+ ToolInvokeContext,
30
32
  ToolParameter,
31
- ToolResultStatus,
32
33
  Toolset,
33
34
  ToolsetTag,
34
35
  )
@@ -153,15 +154,13 @@ class ListKafkaConsumers(BaseKafkaTool):
153
154
  toolset=toolset,
154
155
  )
155
156
 
156
- def _invoke(
157
- self, params: dict, user_approved: bool = False
158
- ) -> StructuredToolResult:
157
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
159
158
  try:
160
159
  kafka_cluster_name = get_param_or_raise(params, "kafka_cluster_name")
161
160
  client = self.get_kafka_client(kafka_cluster_name)
162
161
  if client is None:
163
162
  return StructuredToolResult(
164
- status=ToolResultStatus.ERROR,
163
+ status=StructuredToolResultStatus.ERROR,
165
164
  error="No admin_client on toolset. This toolset is misconfigured.",
166
165
  params=params,
167
166
  )
@@ -190,7 +189,7 @@ class ListKafkaConsumers(BaseKafkaTool):
190
189
  if errors_text:
191
190
  result_text = result_text + "\n\n" + errors_text
192
191
  return StructuredToolResult(
193
- status=ToolResultStatus.SUCCESS,
192
+ status=StructuredToolResultStatus.SUCCESS,
194
193
  data=result_text,
195
194
  params=params,
196
195
  )
@@ -198,7 +197,7 @@ class ListKafkaConsumers(BaseKafkaTool):
198
197
  error_msg = f"Failed to list consumer groups: {str(e)}"
199
198
  logging.error(error_msg)
200
199
  return StructuredToolResult(
201
- status=ToolResultStatus.ERROR,
200
+ status=StructuredToolResultStatus.ERROR,
202
201
  error=error_msg,
203
202
  params=params,
204
203
  )
@@ -228,16 +227,14 @@ class DescribeConsumerGroup(BaseKafkaTool):
228
227
  toolset=toolset,
229
228
  )
230
229
 
231
- def _invoke(
232
- self, params: dict, user_approved: bool = False
233
- ) -> StructuredToolResult:
230
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
234
231
  group_id = params["group_id"]
235
232
  try:
236
233
  kafka_cluster_name = get_param_or_raise(params, "kafka_cluster_name")
237
234
  client = self.get_kafka_client(kafka_cluster_name)
238
235
  if client is None:
239
236
  return StructuredToolResult(
240
- status=ToolResultStatus.ERROR,
237
+ status=StructuredToolResultStatus.ERROR,
241
238
  error="No admin_client on toolset. This toolset is misconfigured.",
242
239
  params=params,
243
240
  )
@@ -247,13 +244,13 @@ class DescribeConsumerGroup(BaseKafkaTool):
247
244
  if futures.get(group_id):
248
245
  group_metadata = futures.get(group_id).result()
249
246
  return StructuredToolResult(
250
- status=ToolResultStatus.SUCCESS,
251
- data=yaml.dump(convert_to_dict(group_metadata)),
247
+ status=StructuredToolResultStatus.SUCCESS,
248
+ data=convert_to_dict(group_metadata),
252
249
  params=params,
253
250
  )
254
251
  else:
255
252
  return StructuredToolResult(
256
- status=ToolResultStatus.ERROR,
253
+ status=StructuredToolResultStatus.ERROR,
257
254
  error="Group not found",
258
255
  params=params,
259
256
  )
@@ -261,7 +258,7 @@ class DescribeConsumerGroup(BaseKafkaTool):
261
258
  error_msg = f"Failed to describe consumer group {group_id}: {str(e)}"
262
259
  logging.error(error_msg)
263
260
  return StructuredToolResult(
264
- status=ToolResultStatus.ERROR,
261
+ status=StructuredToolResultStatus.ERROR,
265
262
  error=error_msg,
266
263
  params=params,
267
264
  )
@@ -286,30 +283,28 @@ class ListTopics(BaseKafkaTool):
286
283
  toolset=toolset,
287
284
  )
288
285
 
289
- def _invoke(
290
- self, params: dict, user_approved: bool = False
291
- ) -> StructuredToolResult:
286
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
292
287
  try:
293
288
  kafka_cluster_name = get_param_or_raise(params, "kafka_cluster_name")
294
289
  client = self.get_kafka_client(kafka_cluster_name)
295
290
  if client is None:
296
291
  return StructuredToolResult(
297
- status=ToolResultStatus.ERROR,
292
+ status=StructuredToolResultStatus.ERROR,
298
293
  error="No admin_client on toolset. This toolset is misconfigured.",
299
294
  params=params,
300
295
  )
301
296
 
302
297
  topics = client.list_topics()
303
298
  return StructuredToolResult(
304
- status=ToolResultStatus.SUCCESS,
305
- data=yaml.dump(convert_to_dict(topics)),
299
+ status=StructuredToolResultStatus.SUCCESS,
300
+ data=convert_to_dict(topics),
306
301
  params=params,
307
302
  )
308
303
  except Exception as e:
309
304
  error_msg = f"Failed to list topics: {str(e)}"
310
305
  logging.error(error_msg)
311
306
  return StructuredToolResult(
312
- status=ToolResultStatus.ERROR,
307
+ status=StructuredToolResultStatus.ERROR,
313
308
  error=error_msg,
314
309
  params=params,
315
310
  )
@@ -344,16 +339,14 @@ class DescribeTopic(BaseKafkaTool):
344
339
  toolset=toolset,
345
340
  )
346
341
 
347
- def _invoke(
348
- self, params: dict, user_approved: bool = False
349
- ) -> StructuredToolResult:
342
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
350
343
  topic_name = params["topic_name"]
351
344
  try:
352
345
  kafka_cluster_name = get_param_or_raise(params, "kafka_cluster_name")
353
346
  client = self.get_kafka_client(kafka_cluster_name)
354
347
  if client is None:
355
348
  return StructuredToolResult(
356
- status=ToolResultStatus.ERROR,
349
+ status=StructuredToolResultStatus.ERROR,
357
350
  error="No admin_client on toolset. This toolset is misconfigured.",
358
351
  params=params,
359
352
  )
@@ -373,15 +366,15 @@ class DescribeTopic(BaseKafkaTool):
373
366
  result["configuration"] = convert_to_dict(config)
374
367
 
375
368
  return StructuredToolResult(
376
- status=ToolResultStatus.SUCCESS,
377
- data=yaml.dump(result),
369
+ status=StructuredToolResultStatus.SUCCESS,
370
+ data=result,
378
371
  params=params,
379
372
  )
380
373
  except Exception as e:
381
374
  error_msg = f"Failed to describe topic {topic_name}: {str(e)}"
382
375
  logging.error(error_msg, exc_info=True)
383
376
  return StructuredToolResult(
384
- status=ToolResultStatus.ERROR,
377
+ status=StructuredToolResultStatus.ERROR,
385
378
  error=error_msg,
386
379
  params=params,
387
380
  )
@@ -469,16 +462,14 @@ class FindConsumerGroupsByTopic(BaseKafkaTool):
469
462
  toolset=toolset,
470
463
  )
471
464
 
472
- def _invoke(
473
- self, params: dict, user_approved: bool = False
474
- ) -> StructuredToolResult:
465
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
475
466
  topic_name = params["topic_name"]
476
467
  try:
477
468
  kafka_cluster_name = get_param_or_raise(params, "kafka_cluster_name")
478
469
  client = self.get_kafka_client(kafka_cluster_name)
479
470
  if client is None:
480
471
  return StructuredToolResult(
481
- status=ToolResultStatus.ERROR,
472
+ status=StructuredToolResultStatus.ERROR,
482
473
  error="No admin_client on toolset. This toolset is misconfigured.",
483
474
  params=params,
484
475
  )
@@ -530,7 +521,7 @@ class FindConsumerGroupsByTopic(BaseKafkaTool):
530
521
  result_text = result_text + "\n\n" + errors_text
531
522
 
532
523
  return StructuredToolResult(
533
- status=ToolResultStatus.SUCCESS,
524
+ status=StructuredToolResultStatus.SUCCESS,
534
525
  data=result_text,
535
526
  params=params,
536
527
  )
@@ -540,7 +531,7 @@ class FindConsumerGroupsByTopic(BaseKafkaTool):
540
531
  )
541
532
  logging.error(error_msg)
542
533
  return StructuredToolResult(
543
- status=ToolResultStatus.ERROR,
534
+ status=StructuredToolResultStatus.ERROR,
544
535
  error=error_msg,
545
536
  params=params,
546
537
  )
@@ -559,12 +550,10 @@ class ListKafkaClusters(BaseKafkaTool):
559
550
  toolset=toolset,
560
551
  )
561
552
 
562
- def _invoke(
563
- self, params: dict, user_approved: bool = False
564
- ) -> StructuredToolResult:
553
+ def _invoke(self, params: dict, context: ToolInvokeContext) -> StructuredToolResult:
565
554
  cluster_names = list(self.toolset.clients.keys())
566
555
  return StructuredToolResult(
567
- status=ToolResultStatus.SUCCESS,
556
+ status=StructuredToolResultStatus.SUCCESS,
568
557
  data="Available Kafka Clusters:\n" + "\n".join(cluster_names),
569
558
  params=params,
570
559
  )
@@ -610,6 +599,8 @@ class KafkaToolset(Toolset):
610
599
  admin_config = {
611
600
  "bootstrap.servers": cluster.kafka_broker,
612
601
  "client.id": cluster.kafka_client_id,
602
+ "socket.timeout.ms": 15000, # 15 second timeout
603
+ "api.version.request.timeout.ms": 15000, # 15 second API version timeout
613
604
  }
614
605
 
615
606
  if cluster.kafka_security_protocol:
@@ -623,6 +614,9 @@ class KafkaToolset(Toolset):
623
614
  admin_config["sasl.password"] = cluster.kafka_password
624
615
 
625
616
  client = AdminClient(admin_config)
617
+ # Test the connection by trying to list topics with a timeout
618
+ # This will fail fast if the broker is not reachable
619
+ _ = client.list_topics(timeout=10) # 10 second timeout
626
620
  self.clients[cluster.name] = client # Store in dictionary
627
621
  except Exception as e:
628
622
  message = (