fix: harden master agent synthesize/memory, fix expense create fields
- _synthesize: short-circuit on any single-agent report (avoids extra Ollama call that can timeout); wrap multi-agent LLM call in try/except - _update_memory: catch exceptions so DB/memory failures don't kill reply - _log_directive_start: use 0 instead of NULL for channel_id (NOT NULL col) - create_expense: drop 'description' field (not valid on hr.expense in Odoo 18) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -273,29 +273,37 @@ class MasterAgent:
|
||||
async def _synthesize(self, reports, context: MasterContext) -> str:
|
||||
if not reports:
|
||||
return 'No agent responses received.'
|
||||
if len(reports) == 1 and reports[0].status == 'complete':
|
||||
return reports[0].summary
|
||||
if len(reports) == 1:
|
||||
return reports[0].summary or '(no summary)'
|
||||
summaries = chr(10).join(f'{r.agent}: {r.summary}' for r in reports)
|
||||
msg = ('Synthesize these agent reports into one coherent response. '
|
||||
'Business language only. No internal IDs. '
|
||||
'Separate: actions completed, items pending approval, recommendations.'
|
||||
+ chr(10) + summaries)
|
||||
resp = await self._llm.submit(
|
||||
[{'role': 'system', 'content': 'You are a business intelligence assistant.'},
|
||||
{'role': 'user', 'content': msg}],
|
||||
caller='master_synthesis')
|
||||
return resp.content
|
||||
try:
|
||||
resp = await self._llm.submit(
|
||||
[{'role': 'system', 'content': 'You are a business intelligence assistant.'},
|
||||
{'role': 'user', 'content': msg}],
|
||||
caller='master_synthesis')
|
||||
return resp.content or summaries
|
||||
except Exception as exc:
|
||||
logger.warning('_synthesize LLM call failed, falling back to raw summaries: %s', exc)
|
||||
return summaries
|
||||
|
||||
async def _update_memory(self, user_id, message, response, reports, directive_id):
|
||||
# User message is persisted at the top of handle_message — only save
|
||||
# the assistant reply here.
|
||||
await self._memory.append_message(user_id, 'assistant', response, directive_id)
|
||||
try:
|
||||
await self._memory.append_message(user_id, 'assistant', response or '', directive_id)
|
||||
except Exception as exc:
|
||||
logger.warning('_update_memory: append_message failed: %s', exc)
|
||||
for report in reports:
|
||||
if report.data:
|
||||
await self._memory.store_findings(
|
||||
scope=report.agent.replace('_agent', ''),
|
||||
summary=report.summary, raw_data=report.data,
|
||||
source_directive_id=directive_id)
|
||||
try:
|
||||
await self._memory.store_findings(
|
||||
scope=report.agent.replace('_agent', ''),
|
||||
summary=report.summary, raw_data=report.data,
|
||||
source_directive_id=directive_id)
|
||||
except Exception as exc:
|
||||
logger.warning('_update_memory: store_findings failed agent=%s: %s', report.agent, exc)
|
||||
|
||||
async def handle_approval(self, directive_id, item_id, approved, approver_uid) -> str:
|
||||
if approved:
|
||||
@@ -314,7 +322,7 @@ class MasterAgent:
|
||||
'(directive_id, user_id, channel_id, raw_message, status) '
|
||||
'VALUES ($1, $2, $3, $4, $5) ON CONFLICT (directive_id) DO NOTHING')
|
||||
async with pool.acquire(timeout=10) as conn:
|
||||
await conn.execute(sql, directive_id, user_id, channel_id, message, 'processing')
|
||||
await conn.execute(sql, directive_id, user_id, channel_id or 0, message, 'processing')
|
||||
except Exception as exc:
|
||||
logger.warning('_log_directive_start failed: %s', exc)
|
||||
|
||||
|
||||
@@ -127,8 +127,6 @@ class ExpensesTools:
|
||||
vals['date'] = date
|
||||
if product_id:
|
||||
vals['product_id'] = product_id
|
||||
if description:
|
||||
vals['description'] = description
|
||||
return await self._o.create('hr.expense', vals)
|
||||
|
||||
async def attach_receipt(self, model: str, record_id: int, filename: str,
|
||||
|
||||
Reference in New Issue
Block a user