genxai-framework 0.1.0__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.
- cli/__init__.py +3 -0
- cli/commands/__init__.py +6 -0
- cli/commands/approval.py +85 -0
- cli/commands/audit.py +127 -0
- cli/commands/metrics.py +25 -0
- cli/commands/tool.py +389 -0
- cli/main.py +32 -0
- genxai/__init__.py +81 -0
- genxai/api/__init__.py +5 -0
- genxai/api/app.py +21 -0
- genxai/config/__init__.py +5 -0
- genxai/config/settings.py +37 -0
- genxai/connectors/__init__.py +19 -0
- genxai/connectors/base.py +122 -0
- genxai/connectors/kafka.py +92 -0
- genxai/connectors/postgres_cdc.py +95 -0
- genxai/connectors/registry.py +44 -0
- genxai/connectors/sqs.py +94 -0
- genxai/connectors/webhook.py +73 -0
- genxai/core/__init__.py +37 -0
- genxai/core/agent/__init__.py +32 -0
- genxai/core/agent/base.py +206 -0
- genxai/core/agent/config_io.py +59 -0
- genxai/core/agent/registry.py +98 -0
- genxai/core/agent/runtime.py +970 -0
- genxai/core/communication/__init__.py +6 -0
- genxai/core/communication/collaboration.py +44 -0
- genxai/core/communication/message_bus.py +192 -0
- genxai/core/communication/protocols.py +35 -0
- genxai/core/execution/__init__.py +22 -0
- genxai/core/execution/metadata.py +181 -0
- genxai/core/execution/queue.py +201 -0
- genxai/core/graph/__init__.py +30 -0
- genxai/core/graph/checkpoints.py +77 -0
- genxai/core/graph/edges.py +131 -0
- genxai/core/graph/engine.py +813 -0
- genxai/core/graph/executor.py +516 -0
- genxai/core/graph/nodes.py +161 -0
- genxai/core/graph/trigger_runner.py +40 -0
- genxai/core/memory/__init__.py +19 -0
- genxai/core/memory/base.py +72 -0
- genxai/core/memory/embedding.py +327 -0
- genxai/core/memory/episodic.py +448 -0
- genxai/core/memory/long_term.py +467 -0
- genxai/core/memory/manager.py +543 -0
- genxai/core/memory/persistence.py +297 -0
- genxai/core/memory/procedural.py +461 -0
- genxai/core/memory/semantic.py +526 -0
- genxai/core/memory/shared.py +62 -0
- genxai/core/memory/short_term.py +303 -0
- genxai/core/memory/vector_store.py +508 -0
- genxai/core/memory/working.py +211 -0
- genxai/core/state/__init__.py +6 -0
- genxai/core/state/manager.py +293 -0
- genxai/core/state/schema.py +115 -0
- genxai/llm/__init__.py +14 -0
- genxai/llm/base.py +150 -0
- genxai/llm/factory.py +329 -0
- genxai/llm/providers/__init__.py +1 -0
- genxai/llm/providers/anthropic.py +249 -0
- genxai/llm/providers/cohere.py +274 -0
- genxai/llm/providers/google.py +334 -0
- genxai/llm/providers/ollama.py +147 -0
- genxai/llm/providers/openai.py +257 -0
- genxai/llm/routing.py +83 -0
- genxai/observability/__init__.py +6 -0
- genxai/observability/logging.py +327 -0
- genxai/observability/metrics.py +494 -0
- genxai/observability/tracing.py +372 -0
- genxai/performance/__init__.py +39 -0
- genxai/performance/cache.py +256 -0
- genxai/performance/pooling.py +289 -0
- genxai/security/audit.py +304 -0
- genxai/security/auth.py +315 -0
- genxai/security/cost_control.py +528 -0
- genxai/security/default_policies.py +44 -0
- genxai/security/jwt.py +142 -0
- genxai/security/oauth.py +226 -0
- genxai/security/pii.py +366 -0
- genxai/security/policy_engine.py +82 -0
- genxai/security/rate_limit.py +341 -0
- genxai/security/rbac.py +247 -0
- genxai/security/validation.py +218 -0
- genxai/tools/__init__.py +21 -0
- genxai/tools/base.py +383 -0
- genxai/tools/builtin/__init__.py +131 -0
- genxai/tools/builtin/communication/__init__.py +15 -0
- genxai/tools/builtin/communication/email_sender.py +159 -0
- genxai/tools/builtin/communication/notification_manager.py +167 -0
- genxai/tools/builtin/communication/slack_notifier.py +118 -0
- genxai/tools/builtin/communication/sms_sender.py +118 -0
- genxai/tools/builtin/communication/webhook_caller.py +136 -0
- genxai/tools/builtin/computation/__init__.py +15 -0
- genxai/tools/builtin/computation/calculator.py +101 -0
- genxai/tools/builtin/computation/code_executor.py +183 -0
- genxai/tools/builtin/computation/data_validator.py +259 -0
- genxai/tools/builtin/computation/hash_generator.py +129 -0
- genxai/tools/builtin/computation/regex_matcher.py +201 -0
- genxai/tools/builtin/data/__init__.py +15 -0
- genxai/tools/builtin/data/csv_processor.py +213 -0
- genxai/tools/builtin/data/data_transformer.py +299 -0
- genxai/tools/builtin/data/json_processor.py +233 -0
- genxai/tools/builtin/data/text_analyzer.py +288 -0
- genxai/tools/builtin/data/xml_processor.py +175 -0
- genxai/tools/builtin/database/__init__.py +15 -0
- genxai/tools/builtin/database/database_inspector.py +157 -0
- genxai/tools/builtin/database/mongodb_query.py +196 -0
- genxai/tools/builtin/database/redis_cache.py +167 -0
- genxai/tools/builtin/database/sql_query.py +145 -0
- genxai/tools/builtin/database/vector_search.py +163 -0
- genxai/tools/builtin/file/__init__.py +17 -0
- genxai/tools/builtin/file/directory_scanner.py +214 -0
- genxai/tools/builtin/file/file_compressor.py +237 -0
- genxai/tools/builtin/file/file_reader.py +102 -0
- genxai/tools/builtin/file/file_writer.py +122 -0
- genxai/tools/builtin/file/image_processor.py +186 -0
- genxai/tools/builtin/file/pdf_parser.py +144 -0
- genxai/tools/builtin/test/__init__.py +15 -0
- genxai/tools/builtin/test/async_simulator.py +62 -0
- genxai/tools/builtin/test/data_transformer.py +99 -0
- genxai/tools/builtin/test/error_generator.py +82 -0
- genxai/tools/builtin/test/simple_math.py +94 -0
- genxai/tools/builtin/test/string_processor.py +72 -0
- genxai/tools/builtin/web/__init__.py +15 -0
- genxai/tools/builtin/web/api_caller.py +161 -0
- genxai/tools/builtin/web/html_parser.py +330 -0
- genxai/tools/builtin/web/http_client.py +187 -0
- genxai/tools/builtin/web/url_validator.py +162 -0
- genxai/tools/builtin/web/web_scraper.py +170 -0
- genxai/tools/custom/my_test_tool_2.py +9 -0
- genxai/tools/dynamic.py +105 -0
- genxai/tools/mcp_server.py +167 -0
- genxai/tools/persistence/__init__.py +6 -0
- genxai/tools/persistence/models.py +55 -0
- genxai/tools/persistence/service.py +322 -0
- genxai/tools/registry.py +227 -0
- genxai/tools/security/__init__.py +11 -0
- genxai/tools/security/limits.py +214 -0
- genxai/tools/security/policy.py +20 -0
- genxai/tools/security/sandbox.py +248 -0
- genxai/tools/templates.py +435 -0
- genxai/triggers/__init__.py +19 -0
- genxai/triggers/base.py +104 -0
- genxai/triggers/file_watcher.py +75 -0
- genxai/triggers/queue.py +68 -0
- genxai/triggers/registry.py +82 -0
- genxai/triggers/schedule.py +66 -0
- genxai/triggers/webhook.py +68 -0
- genxai/utils/__init__.py +1 -0
- genxai/utils/tokens.py +295 -0
- genxai_framework-0.1.0.dist-info/METADATA +495 -0
- genxai_framework-0.1.0.dist-info/RECORD +156 -0
- genxai_framework-0.1.0.dist-info/WHEEL +5 -0
- genxai_framework-0.1.0.dist-info/entry_points.txt +2 -0
- genxai_framework-0.1.0.dist-info/licenses/LICENSE +21 -0
- genxai_framework-0.1.0.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Built-in tools for GenXAI."""
|
|
2
|
+
|
|
3
|
+
from genxai.tools.registry import ToolRegistry
|
|
4
|
+
|
|
5
|
+
# Import all tools to trigger registration
|
|
6
|
+
# Computation tools
|
|
7
|
+
from genxai.tools.builtin.computation.calculator import CalculatorTool
|
|
8
|
+
from genxai.tools.builtin.computation.code_executor import CodeExecutorTool
|
|
9
|
+
from genxai.tools.builtin.computation.data_validator import DataValidatorTool
|
|
10
|
+
from genxai.tools.builtin.computation.hash_generator import HashGeneratorTool
|
|
11
|
+
from genxai.tools.builtin.computation.regex_matcher import RegexMatcherTool
|
|
12
|
+
|
|
13
|
+
# File tools
|
|
14
|
+
from genxai.tools.builtin.file.file_reader import FileReaderTool
|
|
15
|
+
from genxai.tools.builtin.file.file_writer import FileWriterTool
|
|
16
|
+
from genxai.tools.builtin.file.directory_scanner import DirectoryScannerTool
|
|
17
|
+
from genxai.tools.builtin.file.file_compressor import FileCompressorTool
|
|
18
|
+
from genxai.tools.builtin.file.image_processor import ImageProcessorTool
|
|
19
|
+
from genxai.tools.builtin.file.pdf_parser import PDFParserTool
|
|
20
|
+
|
|
21
|
+
# Web tools
|
|
22
|
+
from genxai.tools.builtin.web.web_scraper import WebScraperTool
|
|
23
|
+
from genxai.tools.builtin.web.api_caller import APICallerTool
|
|
24
|
+
from genxai.tools.builtin.web.http_client import HTTPClientTool
|
|
25
|
+
from genxai.tools.builtin.web.html_parser import HTMLParserTool
|
|
26
|
+
from genxai.tools.builtin.web.url_validator import URLValidatorTool
|
|
27
|
+
|
|
28
|
+
# Database tools
|
|
29
|
+
from genxai.tools.builtin.database.sql_query import SQLQueryTool
|
|
30
|
+
from genxai.tools.builtin.database.mongodb_query import MongoDBQueryTool
|
|
31
|
+
from genxai.tools.builtin.database.redis_cache import RedisCacheTool
|
|
32
|
+
from genxai.tools.builtin.database.vector_search import VectorSearchTool
|
|
33
|
+
from genxai.tools.builtin.database.database_inspector import DatabaseInspectorTool
|
|
34
|
+
|
|
35
|
+
# Communication tools
|
|
36
|
+
from genxai.tools.builtin.communication.email_sender import EmailSenderTool
|
|
37
|
+
from genxai.tools.builtin.communication.slack_notifier import SlackNotifierTool
|
|
38
|
+
from genxai.tools.builtin.communication.sms_sender import SMSSenderTool
|
|
39
|
+
from genxai.tools.builtin.communication.webhook_caller import WebhookCallerTool
|
|
40
|
+
from genxai.tools.builtin.communication.notification_manager import NotificationManagerTool
|
|
41
|
+
|
|
42
|
+
# Data tools
|
|
43
|
+
from genxai.tools.builtin.data.json_processor import JSONProcessorTool
|
|
44
|
+
from genxai.tools.builtin.data.csv_processor import CSVProcessorTool
|
|
45
|
+
from genxai.tools.builtin.data.xml_processor import XMLProcessorTool
|
|
46
|
+
from genxai.tools.builtin.data.text_analyzer import TextAnalyzerTool
|
|
47
|
+
from genxai.tools.builtin.data.data_transformer import DataTransformerTool
|
|
48
|
+
|
|
49
|
+
# Auto-register all tools
|
|
50
|
+
_tools_to_register = [
|
|
51
|
+
# Computation
|
|
52
|
+
CalculatorTool(),
|
|
53
|
+
CodeExecutorTool(),
|
|
54
|
+
DataValidatorTool(),
|
|
55
|
+
HashGeneratorTool(),
|
|
56
|
+
RegexMatcherTool(),
|
|
57
|
+
# File
|
|
58
|
+
FileReaderTool(),
|
|
59
|
+
FileWriterTool(),
|
|
60
|
+
DirectoryScannerTool(),
|
|
61
|
+
FileCompressorTool(),
|
|
62
|
+
ImageProcessorTool(),
|
|
63
|
+
PDFParserTool(),
|
|
64
|
+
# Web
|
|
65
|
+
WebScraperTool(),
|
|
66
|
+
APICallerTool(),
|
|
67
|
+
HTTPClientTool(),
|
|
68
|
+
HTMLParserTool(),
|
|
69
|
+
URLValidatorTool(),
|
|
70
|
+
# Database
|
|
71
|
+
SQLQueryTool(),
|
|
72
|
+
MongoDBQueryTool(),
|
|
73
|
+
RedisCacheTool(),
|
|
74
|
+
VectorSearchTool(),
|
|
75
|
+
DatabaseInspectorTool(),
|
|
76
|
+
# Communication
|
|
77
|
+
EmailSenderTool(),
|
|
78
|
+
SlackNotifierTool(),
|
|
79
|
+
SMSSenderTool(),
|
|
80
|
+
WebhookCallerTool(),
|
|
81
|
+
NotificationManagerTool(),
|
|
82
|
+
# Data
|
|
83
|
+
JSONProcessorTool(),
|
|
84
|
+
CSVProcessorTool(),
|
|
85
|
+
XMLProcessorTool(),
|
|
86
|
+
TextAnalyzerTool(),
|
|
87
|
+
DataTransformerTool(),
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
# Register all tools
|
|
91
|
+
for tool in _tools_to_register:
|
|
92
|
+
try:
|
|
93
|
+
ToolRegistry.register(tool)
|
|
94
|
+
except Exception as e:
|
|
95
|
+
# Log but don't fail if a tool can't be registered
|
|
96
|
+
import logging
|
|
97
|
+
logging.warning(f"Failed to register tool {tool.metadata.name}: {e}")
|
|
98
|
+
|
|
99
|
+
__all__ = [
|
|
100
|
+
"CalculatorTool",
|
|
101
|
+
"CodeExecutorTool",
|
|
102
|
+
"DataValidatorTool",
|
|
103
|
+
"HashGeneratorTool",
|
|
104
|
+
"RegexMatcherTool",
|
|
105
|
+
"FileReaderTool",
|
|
106
|
+
"FileWriterTool",
|
|
107
|
+
"DirectoryScannerTool",
|
|
108
|
+
"FileCompressorTool",
|
|
109
|
+
"ImageProcessorTool",
|
|
110
|
+
"PDFParserTool",
|
|
111
|
+
"WebScraperTool",
|
|
112
|
+
"APICallerTool",
|
|
113
|
+
"HTTPClientTool",
|
|
114
|
+
"HTMLParserTool",
|
|
115
|
+
"URLValidatorTool",
|
|
116
|
+
"SQLQueryTool",
|
|
117
|
+
"MongoDBQueryTool",
|
|
118
|
+
"RedisCacheTool",
|
|
119
|
+
"VectorSearchTool",
|
|
120
|
+
"DatabaseInspectorTool",
|
|
121
|
+
"EmailSenderTool",
|
|
122
|
+
"SlackNotifierTool",
|
|
123
|
+
"SMSSenderTool",
|
|
124
|
+
"WebhookCallerTool",
|
|
125
|
+
"NotificationManagerTool",
|
|
126
|
+
"JSONProcessorTool",
|
|
127
|
+
"CSVProcessorTool",
|
|
128
|
+
"XMLProcessorTool",
|
|
129
|
+
"TextAnalyzerTool",
|
|
130
|
+
"DataTransformerTool",
|
|
131
|
+
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Communication tools for GenXAI."""
|
|
2
|
+
|
|
3
|
+
from genxai.tools.builtin.communication.email_sender import EmailSenderTool
|
|
4
|
+
from genxai.tools.builtin.communication.slack_notifier import SlackNotifierTool
|
|
5
|
+
from genxai.tools.builtin.communication.webhook_caller import WebhookCallerTool
|
|
6
|
+
from genxai.tools.builtin.communication.sms_sender import SMSSenderTool
|
|
7
|
+
from genxai.tools.builtin.communication.notification_manager import NotificationManagerTool
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"EmailSenderTool",
|
|
11
|
+
"SlackNotifierTool",
|
|
12
|
+
"WebhookCallerTool",
|
|
13
|
+
"SMSSenderTool",
|
|
14
|
+
"NotificationManagerTool",
|
|
15
|
+
]
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""Email sender tool for sending emails via SMTP."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from genxai.tools.base import Tool, ToolMetadata, ToolParameter, ToolCategory
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EmailSenderTool(Tool):
|
|
12
|
+
"""Send emails via SMTP with support for HTML and attachments."""
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
"""Initialize email sender tool."""
|
|
16
|
+
metadata = ToolMetadata(
|
|
17
|
+
name="email_sender",
|
|
18
|
+
description="Send emails via SMTP with HTML support and attachments",
|
|
19
|
+
category=ToolCategory.COMMUNICATION,
|
|
20
|
+
tags=["email", "smtp", "communication", "notification", "message"],
|
|
21
|
+
version="1.0.0",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
parameters = [
|
|
25
|
+
ToolParameter(
|
|
26
|
+
name="to",
|
|
27
|
+
type="string",
|
|
28
|
+
description="Recipient email address",
|
|
29
|
+
required=True,
|
|
30
|
+
),
|
|
31
|
+
ToolParameter(
|
|
32
|
+
name="subject",
|
|
33
|
+
type="string",
|
|
34
|
+
description="Email subject",
|
|
35
|
+
required=True,
|
|
36
|
+
),
|
|
37
|
+
ToolParameter(
|
|
38
|
+
name="body",
|
|
39
|
+
type="string",
|
|
40
|
+
description="Email body content",
|
|
41
|
+
required=True,
|
|
42
|
+
),
|
|
43
|
+
ToolParameter(
|
|
44
|
+
name="from_email",
|
|
45
|
+
type="string",
|
|
46
|
+
description="Sender email address",
|
|
47
|
+
required=True,
|
|
48
|
+
),
|
|
49
|
+
ToolParameter(
|
|
50
|
+
name="smtp_host",
|
|
51
|
+
type="string",
|
|
52
|
+
description="SMTP server host",
|
|
53
|
+
required=True,
|
|
54
|
+
),
|
|
55
|
+
ToolParameter(
|
|
56
|
+
name="smtp_port",
|
|
57
|
+
type="number",
|
|
58
|
+
description="SMTP server port",
|
|
59
|
+
required=False,
|
|
60
|
+
default=587,
|
|
61
|
+
),
|
|
62
|
+
ToolParameter(
|
|
63
|
+
name="username",
|
|
64
|
+
type="string",
|
|
65
|
+
description="SMTP username",
|
|
66
|
+
required=False,
|
|
67
|
+
),
|
|
68
|
+
ToolParameter(
|
|
69
|
+
name="password",
|
|
70
|
+
type="string",
|
|
71
|
+
description="SMTP password",
|
|
72
|
+
required=False,
|
|
73
|
+
),
|
|
74
|
+
ToolParameter(
|
|
75
|
+
name="html",
|
|
76
|
+
type="boolean",
|
|
77
|
+
description="Whether body is HTML",
|
|
78
|
+
required=False,
|
|
79
|
+
default=False,
|
|
80
|
+
),
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
super().__init__(metadata, parameters)
|
|
84
|
+
|
|
85
|
+
async def _execute(
|
|
86
|
+
self,
|
|
87
|
+
to: str,
|
|
88
|
+
subject: str,
|
|
89
|
+
body: str,
|
|
90
|
+
from_email: str,
|
|
91
|
+
smtp_host: str,
|
|
92
|
+
smtp_port: int = 587,
|
|
93
|
+
username: Optional[str] = None,
|
|
94
|
+
password: Optional[str] = None,
|
|
95
|
+
html: bool = False,
|
|
96
|
+
) -> Dict[str, Any]:
|
|
97
|
+
"""Execute email sending.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
to: Recipient email
|
|
101
|
+
subject: Email subject
|
|
102
|
+
body: Email body
|
|
103
|
+
from_email: Sender email
|
|
104
|
+
smtp_host: SMTP host
|
|
105
|
+
smtp_port: SMTP port
|
|
106
|
+
username: SMTP username
|
|
107
|
+
password: SMTP password
|
|
108
|
+
html: HTML flag
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Dictionary containing send results
|
|
112
|
+
"""
|
|
113
|
+
try:
|
|
114
|
+
import aiosmtplib
|
|
115
|
+
from email.mime.text import MIMEText
|
|
116
|
+
from email.mime.multipart import MIMEMultipart
|
|
117
|
+
except ImportError:
|
|
118
|
+
raise ImportError(
|
|
119
|
+
"aiosmtplib package not installed. Install with: pip install aiosmtplib"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
result: Dict[str, Any] = {
|
|
123
|
+
"to": to,
|
|
124
|
+
"subject": subject,
|
|
125
|
+
"success": False,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
# Create message
|
|
130
|
+
if html:
|
|
131
|
+
message = MIMEMultipart("alternative")
|
|
132
|
+
message.attach(MIMEText(body, "html"))
|
|
133
|
+
else:
|
|
134
|
+
message = MIMEText(body, "plain")
|
|
135
|
+
|
|
136
|
+
message["Subject"] = subject
|
|
137
|
+
message["From"] = from_email
|
|
138
|
+
message["To"] = to
|
|
139
|
+
|
|
140
|
+
# Send email
|
|
141
|
+
await aiosmtplib.send(
|
|
142
|
+
message,
|
|
143
|
+
hostname=smtp_host,
|
|
144
|
+
port=smtp_port,
|
|
145
|
+
username=username,
|
|
146
|
+
password=password,
|
|
147
|
+
start_tls=True if smtp_port == 587 else False,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
result.update({
|
|
151
|
+
"success": True,
|
|
152
|
+
"message": "Email sent successfully",
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
except Exception as e:
|
|
156
|
+
result["error"] = str(e)
|
|
157
|
+
|
|
158
|
+
logger.info(f"Email send completed: success={result['success']}")
|
|
159
|
+
return result
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Notification manager tool for multi-channel notifications."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from genxai.tools.base import Tool, ToolMetadata, ToolParameter, ToolCategory
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NotificationManagerTool(Tool):
|
|
12
|
+
"""Manage and send notifications across multiple channels."""
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
"""Initialize notification manager tool."""
|
|
16
|
+
metadata = ToolMetadata(
|
|
17
|
+
name="notification_manager",
|
|
18
|
+
description="Send notifications across multiple channels (email, Slack, webhook)",
|
|
19
|
+
category=ToolCategory.COMMUNICATION,
|
|
20
|
+
tags=["notification", "multi-channel", "alert", "messaging", "broadcast"],
|
|
21
|
+
version="1.0.0",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
parameters = [
|
|
25
|
+
ToolParameter(
|
|
26
|
+
name="message",
|
|
27
|
+
type="string",
|
|
28
|
+
description="Notification message",
|
|
29
|
+
required=True,
|
|
30
|
+
),
|
|
31
|
+
ToolParameter(
|
|
32
|
+
name="channels",
|
|
33
|
+
type="object",
|
|
34
|
+
description="Channel configurations (email, slack, webhook)",
|
|
35
|
+
required=True,
|
|
36
|
+
),
|
|
37
|
+
ToolParameter(
|
|
38
|
+
name="priority",
|
|
39
|
+
type="string",
|
|
40
|
+
description="Notification priority",
|
|
41
|
+
required=False,
|
|
42
|
+
default="normal",
|
|
43
|
+
enum=["low", "normal", "high", "urgent"],
|
|
44
|
+
),
|
|
45
|
+
ToolParameter(
|
|
46
|
+
name="title",
|
|
47
|
+
type="string",
|
|
48
|
+
description="Notification title/subject",
|
|
49
|
+
required=False,
|
|
50
|
+
),
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
super().__init__(metadata, parameters)
|
|
54
|
+
|
|
55
|
+
async def _execute(
|
|
56
|
+
self,
|
|
57
|
+
message: str,
|
|
58
|
+
channels: Dict[str, Any],
|
|
59
|
+
priority: str = "normal",
|
|
60
|
+
title: Optional[str] = None,
|
|
61
|
+
) -> Dict[str, Any]:
|
|
62
|
+
"""Execute multi-channel notification.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
message: Notification message
|
|
66
|
+
channels: Channel configurations
|
|
67
|
+
priority: Priority level
|
|
68
|
+
title: Notification title
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Dictionary containing send results for all channels
|
|
72
|
+
"""
|
|
73
|
+
result: Dict[str, Any] = {
|
|
74
|
+
"message": message,
|
|
75
|
+
"priority": priority,
|
|
76
|
+
"channels_attempted": [],
|
|
77
|
+
"channels_succeeded": [],
|
|
78
|
+
"channels_failed": [],
|
|
79
|
+
"success": False,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
# Process each channel
|
|
84
|
+
for channel_type, config in channels.items():
|
|
85
|
+
result["channels_attempted"].append(channel_type)
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
if channel_type == "email":
|
|
89
|
+
await self._send_email(message, title, config)
|
|
90
|
+
result["channels_succeeded"].append(channel_type)
|
|
91
|
+
|
|
92
|
+
elif channel_type == "slack":
|
|
93
|
+
await self._send_slack(message, title, config)
|
|
94
|
+
result["channels_succeeded"].append(channel_type)
|
|
95
|
+
|
|
96
|
+
elif channel_type == "webhook":
|
|
97
|
+
await self._send_webhook(message, title, priority, config)
|
|
98
|
+
result["channels_succeeded"].append(channel_type)
|
|
99
|
+
|
|
100
|
+
else:
|
|
101
|
+
result["channels_failed"].append({
|
|
102
|
+
"channel": channel_type,
|
|
103
|
+
"error": "Unsupported channel type"
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
except Exception as e:
|
|
107
|
+
result["channels_failed"].append({
|
|
108
|
+
"channel": channel_type,
|
|
109
|
+
"error": str(e)
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
result["success"] = len(result["channels_succeeded"]) > 0
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
result["error"] = str(e)
|
|
116
|
+
|
|
117
|
+
logger.info(
|
|
118
|
+
f"Notification sent: {len(result['channels_succeeded'])}/{len(result['channels_attempted'])} channels"
|
|
119
|
+
)
|
|
120
|
+
return result
|
|
121
|
+
|
|
122
|
+
async def _send_email(self, message: str, title: Optional[str], config: Dict[str, Any]) -> None:
|
|
123
|
+
"""Send email notification."""
|
|
124
|
+
# Placeholder - would integrate with EmailSenderTool
|
|
125
|
+
logger.info(f"Email notification sent: {title or 'Notification'}")
|
|
126
|
+
|
|
127
|
+
async def _send_slack(self, message: str, title: Optional[str], config: Dict[str, Any]) -> None:
|
|
128
|
+
"""Send Slack notification."""
|
|
129
|
+
try:
|
|
130
|
+
import httpx
|
|
131
|
+
except ImportError:
|
|
132
|
+
raise ImportError("httpx required for Slack notifications")
|
|
133
|
+
|
|
134
|
+
webhook_url = config.get("webhook_url")
|
|
135
|
+
if not webhook_url:
|
|
136
|
+
raise ValueError("webhook_url required for Slack channel")
|
|
137
|
+
|
|
138
|
+
payload = {
|
|
139
|
+
"text": f"*{title}*\n{message}" if title else message
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async with httpx.AsyncClient() as client:
|
|
143
|
+
response = await client.post(webhook_url, json=payload)
|
|
144
|
+
response.raise_for_status()
|
|
145
|
+
|
|
146
|
+
async def _send_webhook(
|
|
147
|
+
self, message: str, title: Optional[str], priority: str, config: Dict[str, Any]
|
|
148
|
+
) -> None:
|
|
149
|
+
"""Send webhook notification."""
|
|
150
|
+
try:
|
|
151
|
+
import httpx
|
|
152
|
+
except ImportError:
|
|
153
|
+
raise ImportError("httpx required for webhook notifications")
|
|
154
|
+
|
|
155
|
+
url = config.get("url")
|
|
156
|
+
if not url:
|
|
157
|
+
raise ValueError("url required for webhook channel")
|
|
158
|
+
|
|
159
|
+
payload = {
|
|
160
|
+
"message": message,
|
|
161
|
+
"title": title,
|
|
162
|
+
"priority": priority,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async with httpx.AsyncClient() as client:
|
|
166
|
+
response = await client.post(url, json=payload)
|
|
167
|
+
response.raise_for_status()
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""Slack notifier tool for sending messages to Slack."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
import logging
|
|
5
|
+
|
|
6
|
+
from genxai.tools.base import Tool, ToolMetadata, ToolParameter, ToolCategory
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SlackNotifierTool(Tool):
|
|
12
|
+
"""Send notifications to Slack channels via webhook."""
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
"""Initialize Slack notifier tool."""
|
|
16
|
+
metadata = ToolMetadata(
|
|
17
|
+
name="slack_notifier",
|
|
18
|
+
description="Send messages and notifications to Slack channels",
|
|
19
|
+
category=ToolCategory.COMMUNICATION,
|
|
20
|
+
tags=["slack", "notification", "webhook", "messaging", "communication"],
|
|
21
|
+
version="1.0.0",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
parameters = [
|
|
25
|
+
ToolParameter(
|
|
26
|
+
name="webhook_url",
|
|
27
|
+
type="string",
|
|
28
|
+
description="Slack webhook URL",
|
|
29
|
+
required=True,
|
|
30
|
+
),
|
|
31
|
+
ToolParameter(
|
|
32
|
+
name="message",
|
|
33
|
+
type="string",
|
|
34
|
+
description="Message text to send",
|
|
35
|
+
required=True,
|
|
36
|
+
),
|
|
37
|
+
ToolParameter(
|
|
38
|
+
name="username",
|
|
39
|
+
type="string",
|
|
40
|
+
description="Bot username to display",
|
|
41
|
+
required=False,
|
|
42
|
+
),
|
|
43
|
+
ToolParameter(
|
|
44
|
+
name="icon_emoji",
|
|
45
|
+
type="string",
|
|
46
|
+
description="Emoji icon (e.g., ':robot_face:')",
|
|
47
|
+
required=False,
|
|
48
|
+
),
|
|
49
|
+
ToolParameter(
|
|
50
|
+
name="channel",
|
|
51
|
+
type="string",
|
|
52
|
+
description="Channel to post to (overrides webhook default)",
|
|
53
|
+
required=False,
|
|
54
|
+
),
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
super().__init__(metadata, parameters)
|
|
58
|
+
|
|
59
|
+
async def _execute(
|
|
60
|
+
self,
|
|
61
|
+
webhook_url: str,
|
|
62
|
+
message: str,
|
|
63
|
+
username: Optional[str] = None,
|
|
64
|
+
icon_emoji: Optional[str] = None,
|
|
65
|
+
channel: Optional[str] = None,
|
|
66
|
+
) -> Dict[str, Any]:
|
|
67
|
+
"""Execute Slack notification.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
webhook_url: Slack webhook URL
|
|
71
|
+
message: Message text
|
|
72
|
+
username: Bot username
|
|
73
|
+
icon_emoji: Icon emoji
|
|
74
|
+
channel: Target channel
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Dictionary containing send results
|
|
78
|
+
"""
|
|
79
|
+
try:
|
|
80
|
+
import httpx
|
|
81
|
+
except ImportError:
|
|
82
|
+
raise ImportError(
|
|
83
|
+
"httpx package not installed. Install with: pip install httpx"
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
result: Dict[str, Any] = {
|
|
87
|
+
"message": message,
|
|
88
|
+
"success": False,
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
# Build payload
|
|
93
|
+
payload: Dict[str, Any] = {"text": message}
|
|
94
|
+
|
|
95
|
+
if username:
|
|
96
|
+
payload["username"] = username
|
|
97
|
+
if icon_emoji:
|
|
98
|
+
payload["icon_emoji"] = icon_emoji
|
|
99
|
+
if channel:
|
|
100
|
+
payload["channel"] = channel
|
|
101
|
+
|
|
102
|
+
# Send to Slack
|
|
103
|
+
async with httpx.AsyncClient() as client:
|
|
104
|
+
response = await client.post(webhook_url, json=payload)
|
|
105
|
+
response.raise_for_status()
|
|
106
|
+
|
|
107
|
+
result.update({
|
|
108
|
+
"success": True,
|
|
109
|
+
"status_code": response.status_code,
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
except httpx.HTTPStatusError as e:
|
|
113
|
+
result["error"] = f"HTTP error: {e.response.status_code}"
|
|
114
|
+
except Exception as e:
|
|
115
|
+
result["error"] = str(e)
|
|
116
|
+
|
|
117
|
+
logger.info(f"Slack notification completed: success={result['success']}")
|
|
118
|
+
return result
|