agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
118 lines • 5.57 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.pdfLoader = exports.MissingPdfSupportError = void 0;
/**
* pdfLoader — PDF text extraction, page by page.
*
* Pattern: Adapter behind `DocumentLoader`, over a lazily-loaded optional peer.
* Role: rag/ layer. The ONE loader that needs a dependency, and the reason
* it is optional rather than bundled.
* Emits: N/A.
*
* ── Why `unpdf`, measured rather than assumed ───────────────────────────────
* PDF text extraction cannot be done without a real library. The candidates
* were installed and measured:
*
* | package | installed size | packages | deps | verdict |
* |---|---|---|---|---|
* | **`unpdf`** | **2.5 MB** | **1** | **none** | chosen |
* | `pdf-parse@2` | 86 MB | 3 | `@napi-rs/canvas` (**native**) | a native binary, to read text |
* | `pdf-parse@1` | 34 MB | 4 | debug, node-ensure | unmaintained since 2018 |
* | `pdfjs-dist@6` | 62 MB | 2 | none | 25× the size for the same engine |
*
* `unpdf` is a serverless build of the same pdf.js engine the heavyweight
* options wrap, with dual CJS/ESM exports and zero transitive dependencies.
* A real 2-page PDF extracts in ~95 ms.
*
* ── Pages are the point ─────────────────────────────────────────────────────
* It returns text PER PAGE, and that is why the page number in a citation is a
* fact rather than a guess. `<source id="handbook.pdf#7" page="2">` can be
* checked by opening page 2. A loader that flattened the document first could
* only ever say "somewhere in this PDF".
*
* ── A known warning on Node 22 ──────────────────────────────────────────────
* pdf.js v5 calls `Math.sumPrecise`, which arrives in V8 later than Node 22.
* The extraction is correct; the console shows `Warning: TypeError:
* Math.sumPrecise is not a function` per page. It is upstream and harmless,
* and it is documented here so it does not read as data loss.
*/
const lazyRequire_js_1 = require("../../lib/lazyRequire.js");
/** Raised when a PDF is met and `unpdf` is not installed. */
class MissingPdfSupportError extends Error {
code = 'ERR_MISSING_PDF_SUPPORT';
/** The file that could not be read. */
uri;
constructor(uri) {
super(`Reading '${uri}' requires the \`unpdf\` peer dependency.\n` +
' Install: npm install unpdf\n' +
' Or pass `backend` to pdfLoader() if your bundler resolves it statically.');
this.name = 'MissingPdfSupportError';
this.uri = uri;
}
}
exports.MissingPdfSupportError = MissingPdfSupportError;
function pdfLoader(options = {}) {
let backend;
const getBackend = (uri) => {
if (options.backend)
return Promise.resolve(options.backend);
return (backend ??= (async () => {
// `unpdf` is ESM-only in its import condition, so a dynamic import is
// tried first and the CJS require is the fallback — one of the two works
// on every runtime this package supports.
try {
const spec = 'unpdf';
return (await Promise.resolve(`${spec}`).then(s => __importStar(require(s))));
}
catch {
try {
return (0, lazyRequire_js_1.lazyRequire)('unpdf');
}
catch {
throw new MissingPdfSupportError(uri);
}
}
})());
};
return {
name: 'pdf',
extensions: ['.pdf'],
async load(input) {
const unpdf = await getBackend(input.uri);
const doc = await unpdf.getDocumentProxy(input.bytes);
const extracted = await unpdf.extractText(doc, { mergePages: false });
const pages = Array.isArray(extracted.text)
? extracted.text.map((p) => String(p))
: [String(extracted.text)];
// Pages are joined with a blank line so `byParagraph` sees a boundary at
// every page break — and so the offsets a splitter computes index THIS
// string, which is the one that gets stored.
return { text: pages.join('\n\n'), pages };
},
};
}
exports.pdfLoader = pdfLoader;
//# sourceMappingURL=pdf.js.map