Add signature_vars to send_email/reply/forward/schedule_send for LLM identity

This commit is contained in:
Admin
2026-06-25 04:50:47 +00:00
parent 12e72ac891
commit ebbbe0e6ec
+102 -13
View File
@@ -122,6 +122,13 @@ class GlobalConfig:
EMAIL_HTML_SIGNATURE: str = "" EMAIL_HTML_SIGNATURE: str = ""
# LLM identity defaults (can be overridden per-call via signature_vars)
LLM_NAME: str = os.getenv("LLM_NAME", "")
LLM_TITLE: str = os.getenv("LLM_TITLE", "")
LLM_PHONE: str = os.getenv("LLM_PHONE", "")
LLM_ADDRESS: str = os.getenv("LLM_ADDRESS", "")
LLM_EMAIL: str = os.getenv("LLM_EMAIL", "")
@classmethod @classmethod
def resolve_html_signature(cls, raw: str) -> str: def resolve_html_signature(cls, raw: str) -> str:
if not raw: if not raw:
@@ -136,6 +143,32 @@ class GlobalConfig:
# Otherwise, treat as inline HTML # Otherwise, treat as inline HTML
return raw.strip() return raw.strip()
@staticmethod
def render_signature_with_vars(signature_template: str, override_vars: Optional[Dict[str, str]] = None) -> str:
"""
Replace {{NAME}}, {{TITLE}}, {{PHONE}}, {{ADDRESS}}, {{EMAIL}} in signature_template
using env-based defaults or per-call overrides.
"""
if not signature_template:
return signature_template
if override_vars is None:
override_vars = {}
name = override_vars.get("NAME") or os.getenv("LLM_NAME", "")
title = override_vars.get("TITLE") or os.getenv("LLM_TITLE", "")
phone = override_vars.get("PHONE") or os.getenv("LLM_PHONE", "")
address = override_vars.get("ADDRESS") or os.getenv("LLM_ADDRESS", "")
email = override_vars.get("EMAIL") or os.getenv("LLM_EMAIL", "")
out = signature_template
out = out.replace("{{NAME}}", name)
out = out.replace("{{TITLE}}", title)
out = out.replace("{{PHONE}}", phone)
out = out.replace("{{ADDRESS}}", address)
out = out.replace("{{EMAIL}}", email)
return out
@property @property
def personnel(self) -> List[Dict[str, Any]]: def personnel(self) -> List[Dict[str, Any]]:
try: try:
@@ -1097,9 +1130,20 @@ TOOLS = [
"body": {"type": "string"}, "body": {"type": "string"},
"cc": {"type": "array", "items": {"type": "string"}}, "cc": {"type": "array", "items": {"type": "string"}},
"bcc": {"type": "array", "items": {"type": "string"}}, "bcc": {"type": "array", "items": {"type": "string"}},
"html": {"type": "boolean", "description": "Treat body as HTML"}, "html": {"type": "boolean", "description": "Treat body as HTML (default: true)"},
"in_reply_to": {"type": "string"}, "in_reply_to": {"type": "string"},
"references": {"type": "string"} "references": {"type": "string"},
"signature_vars": {
"type": "object",
"description": "Optional identity variables for signature template (NAME, TITLE, PHONE, ADDRESS, EMAIL)",
"properties": {
"NAME": {"type": "string"},
"TITLE": {"type": "string"},
"PHONE": {"type": "string"},
"ADDRESS": {"type": "string"},
"EMAIL": {"type": "string"}
}
}
}, },
"required": ["to", "subject", "body"] "required": ["to", "subject", "body"]
} }
@@ -1114,10 +1158,21 @@ TOOLS = [
"folder": {"type": "string"}, "folder": {"type": "string"},
"uid": {"type": "integer"}, "uid": {"type": "integer"},
"body": {"type": "string"}, "body": {"type": "string"},
"html": {"type": "boolean"}, "html": {"type": "boolean", "description": "Treat body as HTML (default: true)"},
"to": {"type": "array", "items": {"type": "string"}, "description": "Override reply recipients"}, "to": {"type": "array", "items": {"type": "string"}, "description": "Override reply recipients"},
"cc": {"type": "array", "items": {"type": "string"}}, "cc": {"type": "array", "items": {"type": "string"}},
"bcc": {"type": "array", "items": {"type": "string"}} "bcc": {"type": "array", "items": {"type": "string"}},
"signature_vars": {
"type": "object",
"description": "Optional identity variables for signature template (NAME, TITLE, PHONE, ADDRESS, EMAIL)",
"properties": {
"NAME": {"type": "string"},
"TITLE": {"type": "string"},
"PHONE": {"type": "string"},
"ADDRESS": {"type": "string"},
"EMAIL": {"type": "string"}
}
}
}, },
"required": ["folder", "uid", "body"] "required": ["folder", "uid", "body"]
} }
@@ -1135,7 +1190,18 @@ TOOLS = [
"cc": {"type": "array", "items": {"type": "string"}}, "cc": {"type": "array", "items": {"type": "string"}},
"bcc": {"type": "array", "items": {"type": "string"}}, "bcc": {"type": "array", "items": {"type": "string"}},
"note": {"type": "string", "description": "Optional note to prepend"}, "note": {"type": "string", "description": "Optional note to prepend"},
"html": {"type": "boolean"} "html": {"type": "boolean", "description": "Treat body as HTML (default: true)"},
"signature_vars": {
"type": "object",
"description": "Optional identity variables for signature template (NAME, TITLE, PHONE, ADDRESS, EMAIL)",
"properties": {
"NAME": {"type": "string"},
"TITLE": {"type": "string"},
"PHONE": {"type": "string"},
"ADDRESS": {"type": "string"},
"EMAIL": {"type": "string"}
}
}
}, },
"required": ["folder", "uid", "to"] "required": ["folder", "uid", "to"]
} }
@@ -1209,10 +1275,21 @@ TOOLS = [
"body": {"type": "string"}, "body": {"type": "string"},
"cc": {"type": "array", "items": {"type": "string"}}, "cc": {"type": "array", "items": {"type": "string"}},
"bcc": {"type": "array", "items": {"type": "string"}}, "bcc": {"type": "array", "items": {"type": "string"}},
"html": {"type": "boolean"}, "html": {"type": "boolean", "description": "Treat body as HTML (default: true)"},
"send_at": {"type": "number", "description": "Unix timestamp when to send"}, "send_at": {"type": "number", "description": "Unix timestamp when to send"},
"in_reply_to": {"type": "string"}, "in_reply_to": {"type": "string"},
"references": {"type": "string"} "references": {"type": "string"},
"signature_vars": {
"type": "object",
"description": "Optional identity variables for signature template (NAME, TITLE, PHONE, ADDRESS, EMAIL)",
"properties": {
"NAME": {"type": "string"},
"TITLE": {"type": "string"},
"PHONE": {"type": "string"},
"ADDRESS": {"type": "string"},
"EMAIL": {"type": "string"}
}
}
}, },
"required": ["to", "subject", "body", "send_at"] "required": ["to", "subject", "body", "send_at"]
} }
@@ -1631,8 +1708,13 @@ def send_email_impl(args):
html = True html = True
body = args["body"] body = args["body"]
# Use LLM-provided identity if present
signature_vars = args.get("signature_vars") or {}
if html and config.EMAIL_HTML_SIGNATURE: if html and config.EMAIL_HTML_SIGNATURE:
body = body.rstrip("\n") + "\n" + config.EMAIL_HTML_SIGNATURE sig = GlobalConfig.render_signature_with_vars(config.EMAIL_HTML_SIGNATURE, signature_vars)
body = body.rstrip("\n") + "\n" + sig
try: try:
send_email( send_email(
@@ -1660,8 +1742,13 @@ def schedule_send_impl(args):
html = True html = True
body = args["body"] body = args["body"]
# Use LLM-provided identity if present
signature_vars = args.get("signature_vars") or {}
if html and config.EMAIL_HTML_SIGNATURE: if html and config.EMAIL_HTML_SIGNATURE:
body = body.rstrip("\n") + "\n" + config.EMAIL_HTML_SIGNATURE sig = GlobalConfig.render_signature_with_vars(config.EMAIL_HTML_SIGNATURE, signature_vars)
body = body.rstrip("\n") + "\n" + sig
task_id = add_scheduled_send( task_id = add_scheduled_send(
account_id=account_id, account_id=account_id,
@@ -1678,7 +1765,7 @@ def schedule_send_impl(args):
return {"status": "scheduled", "task_id": task_id, "account": account_id} return {"status": "scheduled", "task_id": task_id, "account": account_id}
def reply_to_message_impl(account=None, folder=None, uid=None, body=None, html=None, to=None, cc=None, bcc=None): def reply_to_message_impl(account=None, folder=None, uid=None, body=None, html=None, to=None, cc=None, bcc=None, signature_vars=None):
acc = get_account(account) acc = get_account(account)
imap = create_imap(acc) imap = create_imap(acc)
try: try:
@@ -1712,7 +1799,8 @@ def reply_to_message_impl(account=None, folder=None, uid=None, body=None, html=N
# Append HTML signature if sending as HTML # Append HTML signature if sending as HTML
if html and config.EMAIL_HTML_SIGNATURE: if html and config.EMAIL_HTML_SIGNATURE:
body = (body or "").rstrip("\n") + "\n" + config.EMAIL_HTML_SIGNATURE sig = GlobalConfig.render_signature_with_vars(config.EMAIL_HTML_SIGNATURE, signature_vars or {})
body = (body or "").rstrip("\n") + "\n" + sig
send_email( send_email(
acc=acc, acc=acc,
@@ -1730,7 +1818,7 @@ def reply_to_message_impl(account=None, folder=None, uid=None, body=None, html=N
imap.logout() imap.logout()
def forward_message_impl(account=None, folder=None, uid=None, to=None, cc=None, bcc=None, note="", html=None, body=None): def forward_message_impl(account=None, folder=None, uid=None, to=None, cc=None, bcc=None, note="", html=None, body=None, signature_vars=None):
acc = get_account(account) acc = get_account(account)
imap = create_imap(acc) imap = create_imap(acc)
try: try:
@@ -1756,7 +1844,8 @@ def forward_message_impl(account=None, folder=None, uid=None, to=None, cc=None,
# Append HTML signature if sending as HTML # Append HTML signature if sending as HTML
if html and config.EMAIL_HTML_SIGNATURE: if html and config.EMAIL_HTML_SIGNATURE:
body = body.rstrip("\n") + "\n" + config.EMAIL_HTML_SIGNATURE sig = GlobalConfig.render_signature_with_vars(config.EMAIL_HTML_SIGNATURE, signature_vars or {})
body = body.rstrip("\n") + "\n" + sig
send_email( send_email(
acc=acc, acc=acc,