Fix dup approval flow: preserve raw message, force expenses routing, fix HTML rendering
- master_agent: thread raw user message into extra_context and peer_data so expenses_agent can check it directly without relying on LLM intent_summary - master_agent: when receipts are in extra_context always route to expenses_agent, so replies like 'skip duplicates' still trigger expense processing - expenses_agent: _plan() checks peer_data raw_message alongside task so skip/keep keywords are detected even when master rewrites the intent - ab_ai_mail: wrap clarification message HTML in Markup() so Odoo does not re-escape the tags; use <br> instead of <br/> - ab_ai_mail: convert agent plain-text replies newlines to <br> for proper line-break rendering in Discuss Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -58,12 +58,20 @@ class ExpensesAgent(BaseAgent):
|
||||
task = (self._directive.task if self._directive else '').lower()
|
||||
receipts = getattr(self._directive.context, 'receipts', []) if self._directive else []
|
||||
|
||||
# The master LLM rewrites the user message into intent_summary (task).
|
||||
# Also check the original raw_message threaded through peer_data so
|
||||
# short replies like "skip duplicates" are detected even when rewritten.
|
||||
raw_msg = ''
|
||||
if self._directive and self._directive.context:
|
||||
raw_msg = (self._directive.context.peer_data.get('raw_message') or '').lower()
|
||||
combined = task + ' ' + raw_msg
|
||||
|
||||
# Detect whether the user is responding to a duplicate-approval request
|
||||
skip_keywords = ('skip', 'yes', 'remove duplicate', 'exclude duplicate', 'drop duplicate')
|
||||
keep_keywords = ('keep all', 'keep both', 'include all', 'no skip', "don't skip")
|
||||
if any(k in task for k in skip_keywords):
|
||||
if any(k in combined for k in skip_keywords):
|
||||
user_dup_decision = 'skip'
|
||||
elif any(k in task for k in keep_keywords):
|
||||
elif any(k in combined for k in keep_keywords):
|
||||
user_dup_decision = 'keep_all'
|
||||
else:
|
||||
user_dup_decision = 'none' # first time through — will ask if dups found
|
||||
|
||||
@@ -101,6 +101,11 @@ class MasterAgent:
|
||||
await self._log_directive_complete(directive_id, 'complete', response_text)
|
||||
return MasterResponse(directive_id=directive_id, response=response_text,
|
||||
status='complete')
|
||||
# When receipts are present (upload flow), always dispatch expenses_agent
|
||||
# even if the user's message is a one-word reply like "skip duplicates".
|
||||
if (extra_context or {}).get('receipts') and 'expenses_agent' not in intent.agents:
|
||||
intent.agents.append('expenses_agent')
|
||||
intent.needs_clarification = False
|
||||
access = await self._check_access(user_id, intent.agents)
|
||||
if not access.allowed:
|
||||
denied = ', '.join(access.denied_agents)
|
||||
@@ -108,6 +113,10 @@ class MasterAgent:
|
||||
await self._memory.append_message(user_id, 'assistant', msg, directive_id)
|
||||
await self._log_directive_complete(directive_id, 'failed', msg)
|
||||
return MasterResponse(directive_id=directive_id, response=msg, status='failed')
|
||||
# Thread the raw user message into extra_context so agents can
|
||||
# check it directly without relying on the LLM's intent_summary.
|
||||
extra_context = dict(extra_context or {})
|
||||
extra_context.setdefault('raw_message', message or '')
|
||||
directives = await self._build_directives(intent, context, directive_id,
|
||||
user_id=user_id, extra_context=extra_context)
|
||||
reports = await self._dispatch_agents(directives)
|
||||
@@ -221,7 +230,10 @@ class MasterAgent:
|
||||
recent_findings=context.operational_findings,
|
||||
conversation_summary=chr(10).join(
|
||||
m['content'] for m in context.conversation[-5:] if m['role'] == 'assistant'),
|
||||
peer_data={'requesting_user_id': user_id},
|
||||
peer_data={
|
||||
'requesting_user_id': user_id,
|
||||
'raw_message': (extra_context or {}).get('raw_message', ''),
|
||||
},
|
||||
receipts=receipts)
|
||||
d = AgentDirective(
|
||||
directive_id=directive_id, agent=agent_key, task=intent.intent_summary,
|
||||
|
||||
Reference in New Issue
Block a user