API reference¶
Generated from the apogee-ai-connectors source with mkdocstrings. Every symbol below is exported from apogee_ai_connectors, so it is part of the supported public surface.
Application · DTOs¶
BenchDTO
dataclass
¶
BroadcastDTO
dataclass
¶
SendDTO
dataclass
¶
WebhookDTO
dataclass
¶
Application · Use cases¶
BenchSendUseCase
¶
execute
async
¶
Source code in apogee_ai_connectors/application/use_cases/bench_send_use_case.py
Python
async def execute(self, messages: int) -> dict[str, float]:
if messages <= 0:
raise ValueError("messages must be positive")
connector = ConsoleConnector(stream=io.StringIO())
start = time.perf_counter()
for i in range(messages):
await connector.send(ConnectorMessage(
channel="#bench", body=f"msg-{i}",
))
elapsed = (time.perf_counter() - start) * 1000.0
return {
"messages": float(messages),
"elapsed_ms": elapsed,
"messages_per_second": (messages / elapsed * 1000.0) if elapsed > 0 else 0.0,
}
BroadcastUseCase
¶
Sends a message through every connector in parallel.
Source code in apogee_ai_connectors/application/use_cases/broadcast_use_case.py
execute
async
¶
Python
execute(message: ConnectorMessage, names: tuple[str, ...] = ()) -> list[ConnectorEvent]
Source code in apogee_ai_connectors/application/use_cases/broadcast_use_case.py
Python
async def execute(
self, message: ConnectorMessage, names: tuple[str, ...] = (),
) -> list[ConnectorEvent]:
targets = (
[self._registry.get(n) for n in names]
if names else list(self._registry.all())
)
if not targets:
return []
return list(await asyncio.gather(
*[c.send(message) for c in targets],
return_exceptions=False,
))
ListConnectorsUseCase
¶
Source code in apogee_ai_connectors/application/use_cases/list_connectors_use_case.py
execute
async
¶
SendUseCase
¶
Source code in apogee_ai_connectors/application/use_cases/send_use_case.py
execute
async
¶
Python
execute(message: ConnectorMessage) -> ConnectorEvent
Domain¶
ConnectorEvent
dataclass
¶
Python
ConnectorEvent(connector: str, message_id: str, status: DeliveryStatus, latency_ms: float = 0.0, error: str = '', timestamp_s: float = time(), metadata: dict[str, str] = dict())
ConnectorMessage
dataclass
¶
Python
ConnectorMessage(body: str, channel: str = '', subject: str = '', recipients: tuple[str, ...] = (), headers: dict[str, str] = dict(), metadata: dict[str, str] = dict(), id: str = (lambda: f'm-{hex[:8]}')())
DeliveryStatus
¶
Domain · Enums¶
ConnectorKind
¶
Bases: str, Enum
Domain · Exceptions¶
ConnectorError
¶
Bases: Exception
Base for apogee-ai-connectors errors.
ConnectorNotFoundException
¶
DeliveryError
¶
Domain · Protocols (ports)¶
IConnector
¶
Bases: Protocol
send
async
¶
Python
send(message: ConnectorMessage) -> ConnectorEvent
IEventSink
¶
Bases: Protocol
emit
async
¶
Python
emit(event: ConnectorEvent) -> None
Infrastructure¶
ConnectorRegistry
¶
ConsoleConnector
¶
Prints messages to a stream. CI-safe — keeps a sent log.
Source code in apogee_ai_connectors/infrastructure/connectors/console_connector.py
send
async
¶
Python
send(message: ConnectorMessage) -> ConnectorEvent
Source code in apogee_ai_connectors/infrastructure/connectors/console_connector.py
Python
async def send(self, message: ConnectorMessage) -> ConnectorEvent:
start = time.perf_counter()
target = message.channel or "<no-channel>"
prefix = f"[{self.name}] {target}"
if message.subject:
prefix = f"{prefix} | {message.subject}"
# Fall back to current sys.stdout if the cached stream got closed
# (e.g. pytest's capsys replaces sys.stdout between tests).
stream = self._stream
if getattr(stream, "closed", False):
stream = sys.stdout
print(f"{prefix}: {message.body}", file=stream)
self.sent.append(message)
return ConnectorEvent(
connector=self.name,
message_id=message.id,
status=DeliveryStatus.DELIVERED,
latency_ms=(time.perf_counter() - start) * 1000.0,
)
DiscordWebhookConnector
¶
Posts to a Discord incoming webhook (no SDK required).
Source code in apogee_ai_connectors/infrastructure/connectors/discord_connector.py
send
async
¶
Python
send(message: ConnectorMessage) -> ConnectorEvent
Source code in apogee_ai_connectors/infrastructure/connectors/discord_connector.py
Python
async def send(self, message: ConnectorMessage) -> ConnectorEvent:
start = time.perf_counter()
payload = {"content": message.body}
if message.metadata.get("username"):
payload["username"] = message.metadata["username"]
try:
status = await asyncio.to_thread(self._post_sync, payload)
except DeliveryError as exc:
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.FAILED, error=str(exc),
latency_ms=(time.perf_counter() - start) * 1000.0,
)
delivered = status in (200, 204)
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.DELIVERED if delivered else DeliveryStatus.FAILED,
latency_ms=(time.perf_counter() - start) * 1000.0,
metadata={"http_status": str(status)},
error="" if delivered else f"http {status}",
)
SlackConnector
¶
Lazy slack-sdk async adapter — install via extras=slack.
Source code in apogee_ai_connectors/infrastructure/connectors/slack_connector.py
send
async
¶
Python
send(message: ConnectorMessage) -> ConnectorEvent
Source code in apogee_ai_connectors/infrastructure/connectors/slack_connector.py
Python
async def send(self, message: ConnectorMessage) -> ConnectorEvent:
self._ensure_client()
start = time.perf_counter()
channel = message.channel or self._default_channel
if not channel:
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.FAILED,
error="no channel and no default_channel",
latency_ms=(time.perf_counter() - start) * 1000.0,
)
try:
await self._client.chat_postMessage( # type: ignore[union-attr]
channel=channel, text=message.body,
)
except Exception as exc: # pragma: no cover
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.FAILED, error=str(exc),
latency_ms=(time.perf_counter() - start) * 1000.0,
)
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.DELIVERED,
latency_ms=(time.perf_counter() - start) * 1000.0,
)
SmtpEmailConnector
¶
Python
SmtpEmailConnector(host: str, port: int = 587, username: str = '', password: str = '', sender: str = '', timeout_s: float = 10.0)
Sends an email via stdlib smtplib. Uses SMTP_SSL when port=465.
Source code in apogee_ai_connectors/infrastructure/connectors/smtp_email_connector.py
Python
def __init__(
self,
host: str,
port: int = 587,
username: str = "",
password: str = "",
sender: str = "",
timeout_s: float = 10.0,
) -> None:
if not host:
raise ValueError("host cannot be empty")
self._host = host
self._port = port
self._username = username
self._password = password
self._sender = sender or username
self._timeout = timeout_s
send
async
¶
Python
send(message: ConnectorMessage) -> ConnectorEvent
Source code in apogee_ai_connectors/infrastructure/connectors/smtp_email_connector.py
Python
async def send(self, message: ConnectorMessage) -> ConnectorEvent:
start = time.perf_counter()
try:
await asyncio.to_thread(self._send_sync, message)
except DeliveryError as exc:
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.FAILED, error=str(exc),
latency_ms=(time.perf_counter() - start) * 1000.0,
)
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.DELIVERED,
latency_ms=(time.perf_counter() - start) * 1000.0,
)
WebhookConnector
¶
POSTs message body as JSON to a fixed URL via urllib (no httpx required).
Source code in apogee_ai_connectors/infrastructure/connectors/webhook_connector.py
send
async
¶
Python
send(message: ConnectorMessage) -> ConnectorEvent
Source code in apogee_ai_connectors/infrastructure/connectors/webhook_connector.py
Python
async def send(self, message: ConnectorMessage) -> ConnectorEvent:
start = time.perf_counter()
try:
data = json.loads(message.body)
if not isinstance(data, dict):
payload = {"body": message.body}
else:
payload = data
except json.JSONDecodeError:
payload = {"body": message.body}
if message.channel:
payload.setdefault("channel", message.channel)
if message.subject:
payload.setdefault("subject", message.subject)
try:
status = await asyncio.to_thread(self._post_sync, payload)
except DeliveryError as exc:
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.FAILED, error=str(exc),
latency_ms=(time.perf_counter() - start) * 1000.0,
)
delivered = 200 <= status < 300
return ConnectorEvent(
connector=self.name, message_id=message.id,
status=DeliveryStatus.DELIVERED if delivered else DeliveryStatus.FAILED,
latency_ms=(time.perf_counter() - start) * 1000.0,
metadata={"http_status": str(status)},
error="" if delivered else f"http {status}",
)