Files
agents-marketplace/tests/unit/buyer-pdf-extract.test.ts
david c552c4caa3 buyer: PDF book summarizer (/book) — chunk → map-reduce over suppliers
Adds an authenticated upload flow to the buyer web app: an operator
uploads a PDF, the server extracts + paragraph-aligned-chunks it
(~2.2k tokens), then runs a hierarchical map-reduce summarization by
paying marketplace suppliers per chunk — one on-chain escrow per map
call and per reduce node. One book upload fans out into dozens of real
mainnet escrows (the intended marketplace traffic) while producing a
genuine full-book summary.

Server module (buyer/src/pdf/): PDF extraction (text-only, rejects
scanned), token-aware chunker, supplier discovery/round-robin filtered
to capable models (kimi/deepseek/gpt; excludes qwen2.5:0.5b), pre-spend
cost estimate + wallet-floor guard, and a JobStore orchestrator that
reuses submitPrompt → findSubmittedEscrowRef → runAccept per call.
v1 serializes PostEscrow under a mutex (the shared tx builder can't pin
wallet inputs, so parallel escrows would double-spend); retries failed
calls on a different supplier then continues with gaps. 6 /v1/pdf-*
routes (multipart upload, estimate, confirm-gated start, SSE progress,
result, .md download) behind the existing session auth + page/chunk/
balance caps. SPA adds a 4-step BookSummarizer wizard.

Tests: chunk/estimate/supplier-pool/extract unit tests + orchestrator
(happy/gap/failover) + routes integration. Full buyer suite green
(181 tests); SPA build + typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 11:37:49 +02:00

28 lines
952 B
TypeScript

/**
* buyer-pdf-extract.test.ts — extraction error handling. A non-PDF buffer must
* surface as a structured PdfExtractionError (not an unhandled throw), so the
* upload route can map it to a clean 4xx.
*/
import { describe, it, expect } from "vitest";
import { extractPdfText } from "../../buyer/src/pdf/extract.js";
import { PdfExtractionError } from "../../buyer/src/pdf/types.js";
describe("extractPdfText", () => {
it("throws a structured PdfExtractionError on a non-PDF buffer", async () => {
await expect(extractPdfText(Buffer.from("definitely not a pdf"))).rejects.toBeInstanceOf(
PdfExtractionError,
);
});
it("error carries a machine-readable reason", async () => {
try {
await extractPdfText(Buffer.from("nope"));
throw new Error("expected throw");
} catch (e) {
expect(e).toBeInstanceOf(PdfExtractionError);
expect((e as PdfExtractionError).reason).toBeTruthy();
}
});
});