Files
odoo-ai/addons/activeblue_ai/models/ab_ai_mail.py
Carlos Garcia 992d2c2775 feat(addon): add ActiveBlue AI bot to Odoo Discuss
- Create res.partner for the AI bot (appears in DM contacts)
- Override mail.channel.message_post to intercept direct messages
  to the bot partner and forward them to the agent service
- Post the agent reply back into the Discuss channel as the bot
- Add discuss to depends; load res_partner_bot.xml data

Users can now open Discuss -> New Message -> search 'ActiveBlue AI'
to start a conversation with the agent.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 22:14:00 -04:00

72 lines
2.2 KiB
Python

from __future__ import annotations
import logging
import re
from odoo import models, api
_logger = logging.getLogger(__name__)
_HTML_TAG = re.compile(r'<[^>]+>')
def _strip_html(html: str) -> str:
return _HTML_TAG.sub(' ', html or '').strip()
class MailChannel(models.Model):
_inherit = 'mail.channel'
@api.model
def _ai_bot_partner(self):
return self.env.ref('activeblue_ai.partner_activeblue_ai', raise_if_not_found=False)
def message_post(self, *, body='', author_id=None, **kwargs):
result = super().message_post(body=body, author_id=author_id, **kwargs)
# Only intercept direct-message channels
if self.channel_type != 'chat':
return result
bot_partner = self._ai_bot_partner()
if not bot_partner:
return result
member_partners = self.channel_member_ids.partner_id
if bot_partner not in member_partners:
return result
# Don't react to the bot's own messages
if author_id == bot_partner.id:
return result
text = _strip_html(body)
if not text:
return result
# Identify the human sender
human_partner = member_partners.filtered(lambda p: p != bot_partner)[:1]
user = self.env['res.users'].search([('partner_id', '=', human_partner.id)], limit=1)
uid = user.id if user else self.env.uid
try:
bot = self.env['ab.ai.bot'].sudo().search([('active', '=', True)], limit=1)
if not bot:
return result
response = bot.dispatch_message(
user_id=uid,
message=text,
context={'channel_id': self.id, 'source': 'discuss'},
)
reply = (response or {}).get('reply') or (response or {}).get('message') or \
'I could not process your request right now.'
self.sudo().message_post(
body=reply,
author_id=bot_partner.id,
message_type='comment',
subtype_xmlid='mail.mt_comment',
)
except Exception as exc:
_logger.error('AI bot Discuss reply failed: %s', exc)
return result