Commit Graph

11 Commits

Author SHA1 Message Date
Carlos Garcia
93f2a101fa refactor: remove scripted file intercept — LLM owns all responses
Previously ab_ai_mail.py intercepted file uploads before reaching the
LLM and responded with a hardcoded clarification template. The LLM had
no involvement in the file upload response.

Changes:
- ab_ai_mail.py: remove _post_file_clarification, _find_pending_attachments,
  _describe_zip, and the two-step pending-attachment lookup. All messages
  (text, files, or both) are dispatched to the agent service immediately.
  Files with no text pass an empty message — the LLM decides what to do.
- upload.py: default message changed from hardcoded receipt instruction
  to '' so the LLM determines intent from file content.
- master_agent._synthesize: always runs through the LLM for both single
  and multi-agent cases — no raw templates reach the user.
- master_system.txt: add FILE UPLOADS routing rule so the LLM knows to
  route receipts to expenses_agent without asking for clarification.

New flow: upload → parse → LLM classifies → agent acts → LLM synthesizes
natural response → user sees it. Zero scripted intercepts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 21:05:38 -04:00
Carlos Garcia
af1d27be89 feat: pre-creation confirmation step with inline duplicate warnings
Before writing any expense records the bot now posts a numbered table
of parsed vendor/amount/date for every receipt, with duplicate entries
flagged inline. User replies 'confirm' (skips dups) or 'confirm, keep
all'. This catches OCR amount misreads before they land in Odoo.

Also removes the separate awaiting_dup_approval step; duplicate review
is now part of the single confirmation table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 16:54:25 -04:00
Carlos Garcia
bb1e93fabb fix: widen actions_taken to list[Any] and improve bot error replies
DispatchResponse declared actions_taken as list[dict] but agents return
list[str], causing a 422 on every successful upload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 16:31:45 -04:00
Carlos Garcia
d87f3c3e99 Non-blocking agent dispatch: run LLM call in background thread
message_post now returns immediately after collecting attachment data.
The agent HTTP call and reply posting happen in a daemon thread, so
Odoo commits the user's message and the browser confirms receipt right
away -- instead of waiting 10+ seconds for Ollama to respond.

File clarification (no LLM) still posts inline since it's instant.
The background thread opens its own DB cursor to post the bot reply.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:27:03 -04:00
Carlos Garcia
7d260ca526 Fix HTML display: use plain text + _text_to_html for all bot messages
All bot messages now built as plain text and converted via _text_to_html()
which escapes content and converts newlines to <br>. This avoids raw HTML
tags appearing literally in Odoo 18 Discuss.

- _describe_zip: returns plain str (no Markup/HTML)
- _post_file_clarification: builds plain text, posts via _text_to_html()
- _find_pending_attachments: strip HTML before phrase matching
- _text_to_html: new helper shared by clarification and agent replies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 12:21:58 -04:00
Carlos Garcia
9e3fe974dc 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>
2026-05-16 11:55:46 -04:00
Carlos Garcia
462f63d11d Add duplicate approval flow with time-based dedup
- expenses_agent: extract transaction time (HH:MM) from OCR receipt text
- expenses_agent: _find_semantic_duplicate uses time to rule out false positives (>30 min apart = different receipts)
- expenses_agent: pause when duplicates found, set mode=awaiting_dup_approval, ask user before creating sheet
- expenses_agent: _report formats approval message listing each dup pair with vendor/amount/date/times/filenames
- ab_ai_mail: _find_pending_attachments recognises dup-approval bot message so ZIP re-attaches on user reply

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 02:07:37 -04:00
Carlos Garcia
62d5d3f550 fix: force JSON output for Ollama intent classification; fix attachment detection
- ollama_backend: add format='json' for 'master' and receipt_parser
  callers so llama3.1:8b returns valid JSON instead of plain English
- ab_ai_mail: add debug logging to trace attachment_ids from Discuss;
  handle file-only messages and clarification look-back flow

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:17:58 -04:00
Carlos Garcia
4b7223a139 feat: file upload + expense report creation from Discuss attachments
- Discuss bot now reads ir.attachment from incoming messages; file-only
  messages no longer silently dropped
- ZIP files are described (contents listed) and bot asks clarifying
  question before acting; user's follow-up reply looks back for pending
  attachments so files don't need to be re-uploaded
- receipt_parser: extracts text from ZIP (recursive), JPG/PNG/etc (OCR),
  PDF (pdfplumber), HTML, TXT
- expenses_agent: full rewrite fixing broken method signatures; adds
  create_expense_sheet / create_expense / attach_receipt flow driven by
  LLM receipt parsing (Ollama, HIPAA-locked)
- master_agent: extra_context threads receipts + user_id into directives
- FastAPI /upload multipart endpoint; registered in main.py
- Odoo /ai/upload controller proxies files to agent service
- ab_ai_bot: dispatch_message_with_files() for multipart uploads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 01:02:24 -04:00
Carlos Garcia
65957339ef fix(addon): inherit discuss.channel not mail.channel (renamed in Odoo 17+)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 22:15:46 -04:00
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