mirror of
https://github.com/renee-png/acmcc.git
synced 2026-06-21 09:50:01 +00:00
Inbound invoices: recipient-alias routing + parser hardening
parse-invoice: guard oversized PDFs (>18MB → clear "too large, saved for manual entry" message) and surface the AI gateway's actual error instead of a bare status code. inbound-bill-email: route to an association by the recipient alias (<alias>@bills.avriamail.com, via associations.inbound_alias) in addition to the sender's vendor mapping; fix extractEmail (bare addresses were mis-split, e.g. invoices@x → s@x); surface parse-invoice's real error in the inbox. Deployed via MCP; migration associations_inbound_alias adds + populates the aliases. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -82,6 +82,19 @@ Deno.serve(async (req) => {
|
||||
});
|
||||
}
|
||||
|
||||
// Guard against oversized/scanned PDFs that the AI gateway rejects with an
|
||||
// opaque error. The caller (inbound-bill-email) still keeps the attachment
|
||||
// in the inbox for manual entry when this returns an error.
|
||||
const approxBytes = Math.floor((pdf_base64.length * 3) / 4);
|
||||
const sizeMB = approxBytes / (1024 * 1024);
|
||||
const MAX_MB = 18;
|
||||
if (sizeMB > MAX_MB) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: `PDF too large to auto-parse (${sizeMB.toFixed(1)} MB; limit ${MAX_MB} MB). Saved to the inbox for manual entry.` }),
|
||||
{ status: 413, headers: { ...corsHeaders, "Content-Type": "application/json" } },
|
||||
);
|
||||
}
|
||||
|
||||
const prompt = `You are a meticulous invoice data extraction AI. Analyze the provided PDF invoice carefully — examine EVERY page and EVERY line item, including continuation pages, sub-totals, and tables. Do not skip or summarize line items; capture each one individually exactly as it appears.
|
||||
|
||||
CRITICAL RULES:
|
||||
@@ -162,11 +175,17 @@ Return ONLY valid JSON (no markdown, no code blocks, no commentary) with this ex
|
||||
|
||||
if (!response.ok) {
|
||||
const errText = await response.text();
|
||||
console.error("AI Gateway error:", errText);
|
||||
return new Response(JSON.stringify({ error: `AI processing failed: ${response.status}` }), {
|
||||
status: 502,
|
||||
headers: { ...corsHeaders, "Content-Type": "application/json" },
|
||||
});
|
||||
console.error("AI Gateway error:", response.status, errText);
|
||||
const snippet = errText.replace(/\s+/g, " ").slice(0, 300);
|
||||
const hint = response.status === 429 || response.status === 402
|
||||
? " (AI gateway rate/credit limit)"
|
||||
: response.status === 413 || /too large|payload|size/i.test(errText)
|
||||
? " (PDF too large for the AI gateway — saved to inbox for manual entry)"
|
||||
: "";
|
||||
return new Response(
|
||||
JSON.stringify({ error: `AI gateway error ${response.status}${hint}: ${snippet || "no detail"}` }),
|
||||
{ status: 502, headers: { ...corsHeaders, "Content-Type": "application/json" } },
|
||||
);
|
||||
}
|
||||
|
||||
const aiResult = await response.json();
|
||||
|
||||
Reference in New Issue
Block a user