fix(documents): run pdfjs + canvas un-bundled so scanned PDFs actually rasterize

The bundled (Turbopack) copy of pdfjs-dist failed its render path in the
standalone image with a bare Error, so a scanned PDF on a non-Anthropic
provider fell back to 'PDF scanning needs a Claude vision provider' — while the
identical un-bundled module rasterizes the same document fine (verified in the
container end to end on the real document). Externalize pdfjs-dist and
@napi-rs/canvas so the server loads the real modules, and hoist pdfjs-dist to
the top level in the image so the runtime import resolves. Also log the render
error message (not just its name) and drop the redundant 'not saved' note from
the document summary panel.
This commit is contained in:
Marc-André Bombeck committed 2026-07-09 16:22:00 +02:00
1 parent 8246d9251c
commit a89e511359
16 files changed
+47 -22

No files matched your search

@@ -126,11 +126,9 @@ describe("<DocumentSummaryPanel>", () => {
);
expect(html).toContain('data-slot="document-summary-panel"');
expect(html).toContain('data-slot="document-summary-loading"');
expect(html).toContain("Not saved");
expect(html).toContain("not a diagnosis");
});
it("renders the summary body and the persistent note", () => {
it("renders the summary body", () => {
const html = render(
<DocumentSummaryPanel
output="summary"
@@ -141,7 +139,6 @@ describe("<DocumentSummaryPanel>", () => {
/>,
);
expect(html).toContain("A lipid panel dated 1 March 2026.");
expect(html).toContain("Not saved");
});
it("renders extracted text in a monospace block", () => {
@@ -159,7 +156,7 @@ describe("<DocumentSummaryPanel>", () => {
expect(html).toContain("font-mono");
});
it("surfaces an error via role=alert but keeps the note", () => {
it("surfaces an error via role=alert", () => {
const html = render(
<DocumentSummaryPanel
output="summary"
@@ -171,7 +168,6 @@ describe("<DocumentSummaryPanel>", () => {
);
expect(html).toContain('role="alert"');
expect(html).toContain("read the document");
expect(html).toContain("Not saved");
});
});
@@ -130,7 +130,7 @@ describe("<DocumentAiSection>", () => {
expect(html).toContain("review before saving");
});
it("renders the transient summary panel with the session-only note", () => {
it("renders the transient summary panel", () => {
const html = render(
base({
summaryOutput: "summary",
@@ -139,7 +139,6 @@ describe("<DocumentAiSection>", () => {
);
expect(html).toContain('data-slot="document-summary-panel"');
expect(html).toContain("An MRI report of the left knee.");
expect(html).toContain("Not saved");
});
it("renders no per-document egress notice — the settings confirm covers it", () => {
@@ -281,10 +281,6 @@ export function DocumentSummaryPanel({
{body}
</p>
) : null}
<p className="text-muted-foreground border-border/60 border-t pt-2 text-xs">
{t("documents.summary.notSaved")}
</p>
</div>
);
}
+7 -1
View File
@@ -176,7 +176,13 @@ export async function rasterizePdf(buffer: Buffer): Promise<RasterResult> {
} catch (err) {
annotate({
action: { name: "documents.rasterize.failed" },
meta: { reason: err instanceof Error ? err.name : "unknown" },
meta: {
reason: err instanceof Error ? err.name : "unknown",
// The message pins WHY a render failed (bundled-module mismatch, an
// encrypted/odd PDF, a font issue) — the name alone is opaque. Bounded
// so a pathological message can't bloat the wide event.
message: err instanceof Error ? err.message.slice(0, 300) : String(err),
},
});
return { ok: false };
} finally {