feat: add email_send orchestrator tool
Wraps the existing email_utils.send_email helper as an admin-only tool. Accepts to, subject, body (plain text); newlines converted to <br> for HTML part. Registered in _CALLABLES, _ALL_DECLARATIONS, and TOOL_ROLES (admin). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -48,7 +48,7 @@ from tools.scratch import (
|
||||
from tools.system import cortex_restart as _cortex_restart, cortex_logs as _cortex_logs
|
||||
from tools.web import http_fetch as _http_fetch
|
||||
from tools.files import file_list as _file_list, file_write as _file_write
|
||||
from tools.notify import nc_talk_send as _nc_talk_send
|
||||
from tools.notify import nc_talk_send as _nc_talk_send, email_send as _email_send
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -296,6 +296,7 @@ _CALLABLES: dict[str, callable] = {
|
||||
"cortex_restart": _cortex_restart,
|
||||
"cortex_logs": _cortex_logs,
|
||||
"http_fetch": _http_fetch,
|
||||
"email_send": _email_send,
|
||||
"nc_talk_send": _nc_talk_send,
|
||||
"task_list": _task_list,
|
||||
"task_create": _task_create,
|
||||
@@ -755,6 +756,24 @@ _file_write_declaration = types.FunctionDeclaration(
|
||||
),
|
||||
)
|
||||
|
||||
_email_send_declaration = types.FunctionDeclaration(
|
||||
name="email_send",
|
||||
description=(
|
||||
"Send an email from the server's configured SMTP account. Use for delivering "
|
||||
"summaries, reports, reminders, or any content the user wants emailed. "
|
||||
"body is plain text; newlines are preserved."
|
||||
),
|
||||
parameters=types.Schema(
|
||||
type=types.Type.OBJECT,
|
||||
properties={
|
||||
"to": types.Schema(type=types.Type.STRING, description="Recipient email address"),
|
||||
"subject": types.Schema(type=types.Type.STRING, description="Email subject line"),
|
||||
"body": types.Schema(type=types.Type.STRING, description="Plain-text email body"),
|
||||
},
|
||||
required=["to", "subject", "body"],
|
||||
),
|
||||
)
|
||||
|
||||
_nc_talk_send_declaration = types.FunctionDeclaration(
|
||||
name="nc_talk_send",
|
||||
description=(
|
||||
@@ -791,6 +810,8 @@ TOOL_ROLES: dict[str, str] = {
|
||||
"file_list": "admin",
|
||||
"file_write": "admin",
|
||||
"ae_task_list": "admin", # reads agents_sync kanban
|
||||
"email_send": "admin", # sends from server SMTP account
|
||||
"nc_talk_send": "admin",
|
||||
}
|
||||
|
||||
# Tools that require explicit user confirmation before executing.
|
||||
@@ -831,6 +852,7 @@ _ALL_DECLARATIONS: list[types.FunctionDeclaration] = [
|
||||
_cortex_restart_declaration,
|
||||
_cortex_logs_declaration,
|
||||
_http_fetch_declaration,
|
||||
_email_send_declaration,
|
||||
_nc_talk_send_declaration,
|
||||
_task_list_declaration,
|
||||
_task_create_declaration,
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
Notification tools — proactively send messages to user channels.
|
||||
|
||||
nc_talk_send routes through notification.py → channels.json.
|
||||
Requires notification_channel and notification_room set in the user's channels.json.
|
||||
email_send uses the server SMTP config from .env (smtp_server, smtp_from_*).
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from persona import get_user
|
||||
@@ -12,6 +13,21 @@ from persona import get_user
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def email_send(to: str, subject: str, body: str) -> str:
|
||||
"""Send an email via the server's configured SMTP account."""
|
||||
from email_utils import send_email
|
||||
ok = await asyncio.to_thread(
|
||||
send_email,
|
||||
to_email=to,
|
||||
subject=subject,
|
||||
body_text=body,
|
||||
body_html=body.replace("\n", "<br>"),
|
||||
)
|
||||
if ok:
|
||||
return f"Email sent to {to}."
|
||||
return "Failed to send email — check SMTP configuration in .env."
|
||||
|
||||
|
||||
async def nc_talk_send(message: str) -> str:
|
||||
"""Send a message to the user via their configured notification channel.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user