@xberg-io/llamaindex-xberg 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -26,12 +26,13 @@ __export(index_exports, {
26
26
  module.exports = __toCommonJS(index_exports);
27
27
 
28
28
  // src/reader.ts
29
- var import_xberg = require("@xberg-io/xberg");
29
+ var import_xberg2 = require("@xberg-io/xberg");
30
30
 
31
31
  // src/readerMapping.ts
32
32
  var import_node_crypto = require("crypto");
33
33
  var import_node_path = require("path");
34
34
  var import_schema = require("@llamaindex/core/schema");
35
+ var import_xberg = require("@xberg-io/xberg");
35
36
  var DEFAULT_RESULT_FORMAT = "element_based";
36
37
  var PAGE_RESULT_FORMAT = "unified";
37
38
  var METADATA_FIELDS = [
@@ -67,7 +68,7 @@ function prepareInputs(input) {
67
68
  if (typeof input === "string" || Array.isArray(input)) {
68
69
  const paths = Array.isArray(input) ? input : [input];
69
70
  return {
70
- inputs: paths.map((path) => ({ kind: "uri", uri: path })),
71
+ inputs: paths.map((path) => ({ kind: import_xberg.ExtractInputKind.Uri, uri: path })),
71
72
  sources: paths.map((path) => ({ path }))
72
73
  };
73
74
  }
@@ -78,7 +79,7 @@ function prepareInputs(input) {
78
79
  throw new Error("data and mimeType must be parallel lists of equal length");
79
80
  }
80
81
  return {
81
- inputs: data.map((bytes, index) => ({ kind: "bytes", bytes, mimeType: mimeType[index] })),
82
+ inputs: data.map((bytes, index) => ({ kind: import_xberg.ExtractInputKind.Bytes, bytes, mimeType: mimeType[index] })),
82
83
  sources: data.map((bytes) => ({ data: bytes }))
83
84
  };
84
85
  }
@@ -86,7 +87,7 @@ function prepareInputs(input) {
86
87
  throw new Error("mimeType must be a string for single bytes input");
87
88
  }
88
89
  return {
89
- inputs: [{ kind: "bytes", bytes: data, mimeType }],
90
+ inputs: [{ kind: import_xberg.ExtractInputKind.Bytes, bytes: data, mimeType }],
90
91
  sources: [{ data }]
91
92
  };
92
93
  }
@@ -345,7 +346,7 @@ var XbergReader = class {
345
346
  const config = buildExtractionConfig(this.extractionConfig);
346
347
  let result;
347
348
  try {
348
- result = inputs.length === 1 ? await (0, import_xberg.extract)(inputs[0], config) : await (0, import_xberg.extractBatch)(inputs, config);
349
+ result = inputs.length === 1 ? await (0, import_xberg2.extract)(inputs[0], config) : await (0, import_xberg2.extractBatch)(inputs, config);
349
350
  } catch (error) {
350
351
  if (this.raiseOnError) {
351
352
  throw error;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/reader.ts","../src/readerMapping.ts","../src/nodeParser.ts"],"sourcesContent":["export { XbergReader } from \"./reader.js\";\nexport { XbergNodeParser } from \"./nodeParser.js\";\nexport type { NodeIdFunction, XbergNodeParserConfig } from \"./nodeParser.js\";\nexport type {\n DocumentMetadata,\n SerializedChunk,\n SerializedChunkMetadata,\n SerializedElement,\n SerializedElementMetadata,\n XbergBytesInput,\n XbergInput,\n XbergReaderConfig,\n} from \"./types.js\";\n","import { extract, extractBatch } from \"@xberg-io/xberg\";\nimport type { ExtractionConfig, ExtractionResult } from \"@xberg-io/xberg\";\n\nimport type { BaseReader, Document } from \"@llamaindex/core/schema\";\n\nimport { buildExtractionConfig, mapResults, prepareInputs, resultsToDocuments, type XResult } from \"./readerMapping.js\";\nimport type { XbergInput, XbergReaderConfig } from \"./types.js\";\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Reader for 101 document formats powered by xberg's Rust extraction engine.\n *\n * Supports file paths, raw bytes, batch input, per-page splitting, and true\n * async via xberg's native `extract` / `extractBatch` functions. A single input\n * is dispatched to `extract`; multiple inputs go through `extractBatch`.\n */\nexport class XbergReader implements BaseReader<Document> {\n private readonly raiseOnError: boolean;\n private readonly extractionConfig?: ExtractionConfig;\n\n constructor(config: XbergReaderConfig = {}) {\n this.raiseOnError = config.raiseOnError ?? false;\n this.extractionConfig = config.extractionConfig;\n }\n\n async loadData(input: XbergInput, extraInfo?: Record<string, unknown>): Promise<Document[]> {\n const { inputs, sources } = prepareInputs(input);\n const config = buildExtractionConfig(this.extractionConfig);\n\n let result: ExtractionResult;\n try {\n result = inputs.length === 1 ? await extract(inputs[0], config) : await extractBatch(inputs, config);\n } catch (error) {\n if (this.raiseOnError) {\n throw error;\n }\n console.warn(`xberg extraction failed: ${errorMessage(error)}`);\n return [];\n }\n\n const docSources = mapResults(result as unknown as XResult, sources, this.raiseOnError);\n return resultsToDocuments(docSources, extraInfo);\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { basename, resolve } from \"node:path\";\n\nimport { Document } from \"@llamaindex/core/schema\";\n\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement, XbergBytesInput, XbergInput } from \"./types.js\";\n\n// Default result format so `ExtractedDocument.elements` is populated and the\n// companion XbergNodeParser can split documents element-by-element. ~keep\nconst DEFAULT_RESULT_FORMAT = \"element_based\";\nconst PAGE_RESULT_FORMAT = \"unified\";\n\n/**\n * The camelCase shapes the mappers read from the `@xberg-io/xberg` binding.\n * The binding exposes these via unexported `Js*` aliases, so structural\n * interfaces are declared locally and the native result is cast through them.\n */\ninterface XMetadata {\n title?: string | null;\n subject?: string | null;\n authors?: string[] | null;\n keywords?: string[] | null;\n language?: string | null;\n createdAt?: string | null;\n modifiedAt?: string | null;\n createdBy?: string | null;\n modifiedBy?: string | null;\n category?: string | null;\n tags?: string[] | null;\n documentVersion?: string | null;\n abstractText?: string | null;\n outputFormat?: string | null;\n}\n\ninterface XTable {\n markdown?: string | null;\n}\n\ninterface XPage {\n pageNumber: number;\n content: string;\n tables?: XTable[] | null;\n}\n\ninterface XElement {\n elementType: unknown;\n text: string;\n metadata?: { pageNumber?: number | null; elementIndex?: number | null } | null;\n}\n\ninterface XChunk {\n content: string;\n chunkType: unknown;\n metadata?: {\n chunkIndex?: number | null;\n totalChunks?: number | null;\n firstPage?: number | null;\n lastPage?: number | null;\n headingPath?: string[] | null;\n tokenCount?: number | null;\n } | null;\n}\n\ninterface XKeyword {\n text: string;\n score: number;\n algorithm: unknown;\n}\n\ninterface XWarning {\n source: string;\n message: string;\n}\n\ninterface XAnnotation {\n annotationType: unknown;\n content?: string | null;\n pageNumber: number;\n}\n\ninterface XBoundingBox {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\ninterface XImage {\n data?: Uint8Array | Buffer | number[] | null;\n format?: string | null;\n imageIndex?: number | null;\n pageNumber?: number | null;\n width?: number | null;\n height?: number | null;\n colorspace?: string | null;\n bitsPerComponent?: number | null;\n isMask?: boolean | null;\n description?: string | null;\n boundingBox?: XBoundingBox | null;\n ocrResult?: { content?: string | null } | null;\n}\n\ninterface XCounts {\n pages?: number | null;\n}\n\nexport interface XDocument {\n content?: string | null;\n mimeType?: string | null;\n metadata?: XMetadata | null;\n counts?: XCounts | null;\n tables?: XTable[] | null;\n pages?: XPage[] | null;\n elements?: XElement[] | null;\n chunks?: XChunk[] | null;\n images?: XImage[] | null;\n qualityScore?: number | null;\n detectedLanguages?: string[] | null;\n processingWarnings?: XWarning[] | null;\n extractedKeywords?: XKeyword[] | null;\n annotations?: XAnnotation[] | null;\n}\n\nexport interface XError {\n index: number;\n errorType: string;\n message: string;\n}\n\nexport interface XResult {\n results?: XDocument[] | null;\n errors?: XError[] | null;\n}\n\n/** Tracks the origin of one extraction input for metadata/id purposes. */\nexport interface Source {\n path?: string;\n data?: Uint8Array;\n}\n\n/** A successfully extracted document paired with its source descriptor. */\nexport type DocSource = [XDocument, Source];\n\n// Scalar / list `Metadata` fields copied verbatim into document metadata,\n// mapping the binding's camelCase field to its snake_case output key. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [keyof XMetadata, string]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"createdAt\", \"created_at\"],\n [\"modifiedAt\", \"modified_at\"],\n [\"createdBy\", \"created_by\"],\n [\"modifiedBy\", \"modified_by\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"documentVersion\", \"document_version\"],\n [\"abstractText\", \"abstract_text\"],\n];\n\n/** Return true when the config opts into page extraction. */\nexport function pagesRequested(config: ExtractionConfig | undefined): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\n/**\n * Return the `ExtractionConfig` to use, defaulting `resultFormat`.\n *\n * With no explicit `resultFormat` the reader defaults to `element_based` so the\n * element stream is populated and forwarded to the node parser. When the caller\n * opts into page extraction the reader defaults to `unified` instead, so pages\n * split cleanly without replicating the document-wide element stream. An\n * explicit `resultFormat` always wins.\n */\nexport function buildExtractionConfig(config: ExtractionConfig | undefined): ExtractionConfig {\n const base = { ...config };\n if (base.resultFormat !== undefined) {\n return base;\n }\n const resultFormat = pagesRequested(base) ? PAGE_RESULT_FORMAT : DEFAULT_RESULT_FORMAT;\n return { ...base, resultFormat } as unknown as ExtractionConfig;\n}\n\nfunction isBytesInput(input: XbergInput): input is XbergBytesInput {\n return typeof input === \"object\" && !Array.isArray(input) && \"data\" in input;\n}\n\n/** Validate the reader input and build parallel xberg inputs and sources. */\nexport function prepareInputs(input: XbergInput): { inputs: ExtractInput[]; sources: Source[] } {\n if (typeof input === \"string\" || Array.isArray(input)) {\n const paths = Array.isArray(input) ? input : [input];\n return {\n inputs: paths.map((path) => ({ kind: \"uri\", uri: path })),\n sources: paths.map((path) => ({ path })),\n };\n }\n\n if (isBytesInput(input)) {\n const { data, mimeType } = input;\n if (Array.isArray(data)) {\n if (!Array.isArray(mimeType) || data.length !== mimeType.length) {\n throw new Error(\"data and mimeType must be parallel lists of equal length\");\n }\n return {\n inputs: data.map((bytes, index) => ({ kind: \"bytes\", bytes, mimeType: mimeType[index] })),\n sources: data.map((bytes) => ({ data: bytes })),\n };\n }\n if (typeof mimeType !== \"string\") {\n throw new Error(\"mimeType must be a string for single bytes input\");\n }\n return {\n inputs: [{ kind: \"bytes\", bytes: data, mimeType }],\n sources: [{ data }],\n };\n }\n\n throw new Error(\"Either file_path or data must be provided\");\n}\n\n/**\n * Pair extracted documents with their sources, handling per-input errors.\n *\n * Successful documents preserve input order, so the surviving sources are the\n * inputs whose index is not in the error set. When `raiseOnError` is set the\n * first error is rethrown.\n */\nexport function mapResults(result: XResult, sources: Source[], raiseOnError: boolean): DocSource[] {\n const errors = result.errors ?? [];\n const failedIndices = new Set(errors.map((error) => error.index));\n for (const error of errors) {\n console.warn(`xberg failed to extract input ${error.index} (${error.errorType}): ${error.message}`);\n }\n if (errors.length > 0 && raiseOnError) {\n const first = errors[0];\n throw new Error(`xberg extraction failed for input ${first.index}: ${first.message}`);\n }\n\n const surviving = sources.filter((_, index) => !failedIndices.has(index));\n const results = result.results ?? [];\n const count = Math.min(results.length, surviving.length);\n const paired: DocSource[] = [];\n for (let index = 0; index < count; index += 1) {\n paired.push([results[index], surviving[index]]);\n }\n return paired;\n}\n\nfunction serializeMetadata(metadata: XMetadata | null | undefined): DocumentMetadata {\n if (metadata == null) {\n return {};\n }\n const result: DocumentMetadata = {};\n for (const [field, key] of METADATA_FIELDS) {\n const value = metadata[field];\n if (value != null) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/** Serialize xberg `Element` objects into the reader/node-parser contract. */\nexport function serializeElements(elements: XElement[]): SerializedElement[] {\n return elements.map((element) => ({\n text: element.text,\n element_type: String(element.elementType),\n metadata: {\n page_number: element.metadata?.pageNumber ?? null,\n element_index: element.metadata?.elementIndex ?? null,\n },\n }));\n}\n\n/** Serialize xberg native `Chunk` objects into the node-parser contract. */\nexport function serializeChunks(chunks: XChunk[]): SerializedChunk[] {\n return chunks.map((chunk) => ({\n content: chunk.content,\n chunk_type: String(chunk.chunkType),\n metadata: {\n chunk_index: chunk.metadata?.chunkIndex ?? null,\n total_chunks: chunk.metadata?.totalChunks ?? null,\n first_page: chunk.metadata?.firstPage ?? null,\n last_page: chunk.metadata?.lastPage ?? null,\n heading_path: [...(chunk.metadata?.headingPath ?? [])],\n token_count: chunk.metadata?.tokenCount ?? null,\n },\n }));\n}\n\nfunction serializeImages(images: XImage[], pageNumber: number | undefined): DocumentMetadata[] {\n const serialized: DocumentMetadata[] = [];\n for (const image of images) {\n if (pageNumber !== undefined && image.pageNumber !== pageNumber) {\n continue;\n }\n const raw = image.data;\n const bytes = raw == null ? null : Buffer.from(raw as Uint8Array | number[]);\n const entry: DocumentMetadata = {\n format: image.format,\n image_index: image.imageIndex,\n page_number: image.pageNumber,\n width: image.width,\n height: image.height,\n colorspace: image.colorspace,\n bits_per_component: image.bitsPerComponent,\n is_mask: image.isMask,\n description: image.description,\n data: bytes ? bytes.toString(\"base64\") : null,\n };\n if (image.boundingBox != null) {\n entry.bounding_box = {\n x0: image.boundingBox.x0,\n y0: image.boundingBox.y0,\n x1: image.boundingBox.x1,\n y1: image.boundingBox.y1,\n };\n }\n if (image.ocrResult != null) {\n entry.ocr_result = image.ocrResult.content;\n }\n serialized.push(entry);\n }\n return serialized;\n}\n\n/** Options for {@link buildMetadata}. */\nexport interface BuildMetadataOptions {\n document: XDocument;\n filePath?: string;\n source?: string;\n extraInfo?: Record<string, unknown>;\n pageNumber?: number;\n}\n\n/** Flatten an `ExtractedDocument` into a JSON-serialisable metadata dict. */\nexport function buildMetadata(options: BuildMetadataOptions): DocumentMetadata {\n const { document, filePath, source, extraInfo, pageNumber } = options;\n const meta: DocumentMetadata = {};\n\n if (filePath !== undefined) {\n meta.file_name = basename(filePath);\n meta.file_path = filePath;\n } else if (source !== undefined) {\n meta.file_name = source;\n meta.file_path = source;\n }\n\n meta.file_type = document.mimeType;\n meta.total_pages = document.counts?.pages;\n\n if (pageNumber !== undefined) {\n meta.page_number = pageNumber;\n }\n\n Object.assign(meta, serializeMetadata(document.metadata));\n meta.output_format = document.metadata?.outputFormat;\n\n if (document.qualityScore != null) {\n meta.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages != null) {\n meta.detected_languages = document.detectedLanguages;\n }\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n meta.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n meta.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n if (document.annotations && document.annotations.length > 0) {\n meta.annotations = document.annotations.map((annotation) => ({\n annotation_type: String(annotation.annotationType),\n content: annotation.content,\n page_number: annotation.pageNumber,\n }));\n }\n if (document.elements != null) {\n meta._xberg_elements = serializeElements(document.elements);\n }\n if (document.chunks && document.chunks.length > 0) {\n meta._xberg_chunks = serializeChunks(document.chunks);\n }\n if (document.images && document.images.length > 0) {\n meta.images = serializeImages(document.images, pageNumber);\n }\n\n if (extraInfo) {\n Object.assign(meta, extraInfo);\n }\n\n return meta;\n}\n\n/** Options for {@link generateDocId}. */\nexport interface GenerateDocIdOptions {\n filePath?: string;\n data?: Uint8Array;\n pageNumber?: number;\n}\n\n/** Generate a deterministic document ID via SHA-256 of the resolved source. */\nexport function generateDocId(options: GenerateDocIdOptions): string {\n const { filePath, data, pageNumber } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either file_path or data must be provided\");\n }\n const hasher = createHash(\"sha256\");\n if (filePath !== undefined) {\n hasher.update(resolve(filePath));\n } else if (data !== undefined) {\n hasher.update(data);\n }\n if (pageNumber !== undefined) {\n hasher.update(String(pageNumber));\n }\n return hasher.digest(\"hex\");\n}\n\n/** Return metadata keys excluded from LLM and embedding input. */\nexport function excludedKeys(meta: DocumentMetadata): string[] {\n const keys: string[] = [];\n if (\"_xberg_elements\" in meta) {\n keys.push(\"_xberg_elements\");\n }\n if (\"_xberg_chunks\" in meta) {\n keys.push(\"_xberg_chunks\");\n }\n if (\"images\" in meta) {\n keys.push(\"images\");\n }\n return keys;\n}\n\n/** Append table markdown to content when a table is not already inlined. */\nexport function appendTables(content: string, tables: XTable[] | null | undefined): string {\n if (!tables || tables.length === 0) {\n return content;\n }\n let result = content;\n for (const table of tables) {\n const markdown = table.markdown;\n if (markdown && !result.includes(markdown.trim())) {\n result = `${result.replace(/\\s+$/, \"\")}\\n\\n${markdown}`;\n }\n }\n return result;\n}\n\n/**\n * Build Documents from extracted documents.\n *\n * When an element stream or native chunk list is present the source becomes a\n * single Document carrying `_xberg_elements` / `_xberg_chunks`. Otherwise, when\n * pages are present, one Document is emitted per page. Elements and chunks are\n * document-global, so per-page splitting is suppressed for them to avoid\n * replicating every element or chunk onto every page.\n */\nexport function resultsToDocuments(docSources: DocSource[], extraInfo?: Record<string, unknown>): Document[] {\n const documents: Document[] = [];\n for (const [document, source] of docSources) {\n const sourceLabel = source.data !== undefined ? \"bytes\" : undefined;\n const hasPages = Boolean(document.pages && document.pages.length > 0);\n const hasChunks = Boolean(document.chunks && document.chunks.length > 0);\n\n if (hasPages && document.elements == null && !hasChunks) {\n for (const page of document.pages ?? []) {\n const content = appendTables(page.content, page.tables);\n const meta = buildMetadata({\n document,\n filePath: source.path,\n source: sourceLabel,\n extraInfo,\n pageNumber: page.pageNumber,\n });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data, pageNumber: page.pageNumber }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n } else {\n const content = appendTables(document.content ?? \"\", document.tables);\n const meta = buildMetadata({ document, filePath: source.path, source: sourceLabel, extraInfo });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n }\n return documents;\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport { NodeParser } from \"@llamaindex/core/node-parser\";\nimport { NodeRelationship, TextNode } from \"@llamaindex/core/schema\";\nimport type { BaseNode } from \"@llamaindex/core/schema\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement } from \"./types.js\";\n\nconst ELEMENT_METADATA_KEYS = [\"element_type\", \"page_number\", \"element_index\"] as const;\nconst CHUNK_METADATA_KEYS = [\n \"chunk_type\",\n \"heading_path\",\n \"page_number\",\n \"first_page\",\n \"last_page\",\n \"chunk_index\",\n \"total_chunks\",\n \"token_count\",\n] as const;\nconst FORWARDED_KEYS = [\"_xberg_chunks\", \"_xberg_elements\"] as const;\n\nconst MISSING_ELEMENTS_WARNING =\n \"has no '_xberg_chunks' or '_xberg_elements' metadata. Passing through unchanged. \" +\n \"Use XbergReader with ExtractionConfig(chunking) for native chunk nodes, or \" +\n \"ExtractionConfig(resultFormat='element_based') for element nodes.\";\n\n/** Generates the id for a child node from its running index and source node. */\nexport type NodeIdFunction = (index: number, source: BaseNode) => string;\n\n/** Constructor options for {@link XbergNodeParser}. */\nexport interface XbergNodeParserConfig {\n idFunc?: NodeIdFunction;\n}\n\n/**\n * Structure-aware node parser for xberg-extracted documents.\n *\n * Turns xberg's output into individual `TextNode` objects, preferring xberg's\n * native chunks (`_xberg_chunks`) and falling back to structural elements\n * (`_xberg_elements`). Documents carrying neither pass through unchanged with a\n * warning. It never calls xberg — it consumes Documents produced by\n * {@link XbergReader}.\n */\nexport class XbergNodeParser extends NodeParser<TextNode[]> {\n private readonly idFunc: NodeIdFunction;\n\n constructor(config: XbergNodeParserConfig = {}) {\n super();\n this.idFunc = config.idFunc ?? (() => randomUUID());\n }\n\n protected parseNodes(documents: TextNode[]): TextNode[] {\n const output: TextNode[] = [];\n\n for (const node of documents) {\n const chunks = node.metadata[FORWARDED_KEYS[0]];\n if (Array.isArray(chunks) && chunks.length > 0) {\n output.push(...this.nodesFromChunks(node, chunks as SerializedChunk[]));\n continue;\n }\n\n const elements = node.metadata[FORWARDED_KEYS[1]];\n if (Array.isArray(elements) && elements.length > 0) {\n output.push(...this.nodesFromElements(node, elements as SerializedElement[]));\n continue;\n }\n\n console.warn(`Document ${node.id_} ${MISSING_ELEMENTS_WARNING}`);\n output.push(node);\n }\n\n return output;\n }\n\n private newTextNode(text: string, index: number, source: TextNode, metadata: DocumentMetadata): TextNode {\n return new TextNode({\n text,\n id_: this.idFunc(index, source),\n metadata,\n excludedLlmMetadataKeys: [...source.excludedLlmMetadataKeys],\n metadataSeparator: source.metadataSeparator,\n textTemplate: source.textTemplate,\n relationships: { [NodeRelationship.SOURCE]: source.asRelatedNodeInfo() },\n });\n }\n\n private nodesFromChunks(source: TextNode, chunks: SerializedChunk[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...CHUNK_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const chunk of chunks) {\n const text = chunk.content ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = chunk.metadata;\n const textNode = this.newTextNode(text, index, source, {\n chunk_type: chunk.chunk_type ?? \"unknown\",\n heading_path: meta?.heading_path ?? [],\n page_number: meta?.first_page,\n first_page: meta?.first_page,\n last_page: meta?.last_page,\n chunk_index: meta?.chunk_index,\n total_chunks: meta?.total_chunks,\n token_count: meta?.token_count,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n private nodesFromElements(source: TextNode, elements: SerializedElement[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...ELEMENT_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const element of elements) {\n const text = element.text ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = element.metadata;\n const textNode = this.newTextNode(text, index, source, {\n element_type: element.element_type ?? \"unknown\",\n page_number: meta?.page_number,\n element_index: meta?.element_index,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n protected override postProcessParsedNodes(nodes: TextNode[], parentDocMap: Map<string, TextNode>): TextNode[] {\n const processed = super.postProcessParsedNodes(nodes, parentDocMap);\n return stripForwardedMetadata(processed);\n }\n}\n\n/**\n * Remove reader forwarding keys from child nodes only. The base parser copies\n * parent metadata (including the forwarding keys) onto children, so they are\n * stripped here; passthrough documents keep their metadata untouched.\n */\nfunction stripForwardedMetadata(nodes: TextNode[]): TextNode[] {\n for (const node of nodes) {\n if (node.sourceNode !== undefined) {\n for (const key of FORWARDED_KEYS) {\n delete node.metadata[key];\n }\n }\n }\n return nodes;\n}\n"],"mappings":"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","names":["import_node_crypto","import_schema"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/reader.ts","../src/readerMapping.ts","../src/nodeParser.ts"],"sourcesContent":["export { XbergReader } from \"./reader.js\";\nexport { XbergNodeParser } from \"./nodeParser.js\";\nexport type { NodeIdFunction, XbergNodeParserConfig } from \"./nodeParser.js\";\nexport type {\n DocumentMetadata,\n SerializedChunk,\n SerializedChunkMetadata,\n SerializedElement,\n SerializedElementMetadata,\n XbergBytesInput,\n XbergInput,\n XbergReaderConfig,\n} from \"./types.js\";\n","import { extract, extractBatch } from \"@xberg-io/xberg\";\nimport type { ExtractionConfig, ExtractionResult } from \"@xberg-io/xberg\";\n\nimport type { BaseReader, Document } from \"@llamaindex/core/schema\";\n\nimport { buildExtractionConfig, mapResults, prepareInputs, resultsToDocuments, type XResult } from \"./readerMapping.js\";\nimport type { XbergInput, XbergReaderConfig } from \"./types.js\";\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Reader for 101 document formats powered by xberg's Rust extraction engine.\n *\n * Supports file paths, raw bytes, batch input, per-page splitting, and true\n * async via xberg's native `extract` / `extractBatch` functions. A single input\n * is dispatched to `extract`; multiple inputs go through `extractBatch`.\n */\nexport class XbergReader implements BaseReader<Document> {\n private readonly raiseOnError: boolean;\n private readonly extractionConfig?: ExtractionConfig;\n\n constructor(config: XbergReaderConfig = {}) {\n this.raiseOnError = config.raiseOnError ?? false;\n this.extractionConfig = config.extractionConfig;\n }\n\n async loadData(input: XbergInput, extraInfo?: Record<string, unknown>): Promise<Document[]> {\n const { inputs, sources } = prepareInputs(input);\n const config = buildExtractionConfig(this.extractionConfig);\n\n let result: ExtractionResult;\n try {\n result = inputs.length === 1 ? await extract(inputs[0], config) : await extractBatch(inputs, config);\n } catch (error) {\n if (this.raiseOnError) {\n throw error;\n }\n console.warn(`xberg extraction failed: ${errorMessage(error)}`);\n return [];\n }\n\n const docSources = mapResults(result as unknown as XResult, sources, this.raiseOnError);\n return resultsToDocuments(docSources, extraInfo);\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { basename, resolve } from \"node:path\";\n\nimport { Document } from \"@llamaindex/core/schema\";\n\nimport { ExtractInputKind } from \"@xberg-io/xberg\";\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement, XbergBytesInput, XbergInput } from \"./types.js\";\n\n// Default result format so `ExtractedDocument.elements` is populated and the\n// companion XbergNodeParser can split documents element-by-element. ~keep\nconst DEFAULT_RESULT_FORMAT = \"element_based\";\nconst PAGE_RESULT_FORMAT = \"unified\";\n\n/**\n * The camelCase shapes the mappers read from the `@xberg-io/xberg` binding.\n * The binding exposes these via unexported `Js*` aliases, so structural\n * interfaces are declared locally and the native result is cast through them.\n */\ninterface XMetadata {\n title?: string | null;\n subject?: string | null;\n authors?: string[] | null;\n keywords?: string[] | null;\n language?: string | null;\n createdAt?: string | null;\n modifiedAt?: string | null;\n createdBy?: string | null;\n modifiedBy?: string | null;\n category?: string | null;\n tags?: string[] | null;\n documentVersion?: string | null;\n abstractText?: string | null;\n outputFormat?: string | null;\n}\n\ninterface XTable {\n markdown?: string | null;\n}\n\ninterface XPage {\n pageNumber: number;\n content: string;\n tables?: XTable[] | null;\n}\n\ninterface XElement {\n elementType: unknown;\n text: string;\n metadata?: { pageNumber?: number | null; elementIndex?: number | null } | null;\n}\n\ninterface XChunk {\n content: string;\n chunkType: unknown;\n metadata?: {\n chunkIndex?: number | null;\n totalChunks?: number | null;\n firstPage?: number | null;\n lastPage?: number | null;\n headingPath?: string[] | null;\n tokenCount?: number | null;\n } | null;\n}\n\ninterface XKeyword {\n text: string;\n score: number;\n algorithm: unknown;\n}\n\ninterface XWarning {\n source: string;\n message: string;\n}\n\ninterface XAnnotation {\n annotationType: unknown;\n content?: string | null;\n pageNumber: number;\n}\n\ninterface XBoundingBox {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\ninterface XImage {\n data?: Uint8Array | Buffer | number[] | null;\n format?: string | null;\n imageIndex?: number | null;\n pageNumber?: number | null;\n width?: number | null;\n height?: number | null;\n colorspace?: string | null;\n bitsPerComponent?: number | null;\n isMask?: boolean | null;\n description?: string | null;\n boundingBox?: XBoundingBox | null;\n ocrResult?: { content?: string | null } | null;\n}\n\ninterface XCounts {\n pages?: number | null;\n}\n\nexport interface XDocument {\n content?: string | null;\n mimeType?: string | null;\n metadata?: XMetadata | null;\n counts?: XCounts | null;\n tables?: XTable[] | null;\n pages?: XPage[] | null;\n elements?: XElement[] | null;\n chunks?: XChunk[] | null;\n images?: XImage[] | null;\n qualityScore?: number | null;\n detectedLanguages?: string[] | null;\n processingWarnings?: XWarning[] | null;\n extractedKeywords?: XKeyword[] | null;\n annotations?: XAnnotation[] | null;\n}\n\nexport interface XError {\n index: number;\n errorType: string;\n message: string;\n}\n\nexport interface XResult {\n results?: XDocument[] | null;\n errors?: XError[] | null;\n}\n\n/** Tracks the origin of one extraction input for metadata/id purposes. */\nexport interface Source {\n path?: string;\n data?: Uint8Array;\n}\n\n/** A successfully extracted document paired with its source descriptor. */\nexport type DocSource = [XDocument, Source];\n\n// Scalar / list `Metadata` fields copied verbatim into document metadata,\n// mapping the binding's camelCase field to its snake_case output key. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [keyof XMetadata, string]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"createdAt\", \"created_at\"],\n [\"modifiedAt\", \"modified_at\"],\n [\"createdBy\", \"created_by\"],\n [\"modifiedBy\", \"modified_by\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"documentVersion\", \"document_version\"],\n [\"abstractText\", \"abstract_text\"],\n];\n\n/** Return true when the config opts into page extraction. */\nexport function pagesRequested(config: ExtractionConfig | undefined): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\n/**\n * Return the `ExtractionConfig` to use, defaulting `resultFormat`.\n *\n * With no explicit `resultFormat` the reader defaults to `element_based` so the\n * element stream is populated and forwarded to the node parser. When the caller\n * opts into page extraction the reader defaults to `unified` instead, so pages\n * split cleanly without replicating the document-wide element stream. An\n * explicit `resultFormat` always wins.\n */\nexport function buildExtractionConfig(config: ExtractionConfig | undefined): ExtractionConfig {\n const base = { ...config };\n if (base.resultFormat !== undefined) {\n return base;\n }\n const resultFormat = pagesRequested(base) ? PAGE_RESULT_FORMAT : DEFAULT_RESULT_FORMAT;\n return { ...base, resultFormat } as unknown as ExtractionConfig;\n}\n\nfunction isBytesInput(input: XbergInput): input is XbergBytesInput {\n return typeof input === \"object\" && !Array.isArray(input) && \"data\" in input;\n}\n\n/** Validate the reader input and build parallel xberg inputs and sources. */\nexport function prepareInputs(input: XbergInput): { inputs: ExtractInput[]; sources: Source[] } {\n if (typeof input === \"string\" || Array.isArray(input)) {\n const paths = Array.isArray(input) ? input : [input];\n return {\n inputs: paths.map((path) => ({ kind: ExtractInputKind.Uri, uri: path })),\n sources: paths.map((path) => ({ path })),\n };\n }\n\n if (isBytesInput(input)) {\n const { data, mimeType } = input;\n if (Array.isArray(data)) {\n if (!Array.isArray(mimeType) || data.length !== mimeType.length) {\n throw new Error(\"data and mimeType must be parallel lists of equal length\");\n }\n return {\n inputs: data.map((bytes, index) => ({ kind: ExtractInputKind.Bytes, bytes, mimeType: mimeType[index] })),\n sources: data.map((bytes) => ({ data: bytes })),\n };\n }\n if (typeof mimeType !== \"string\") {\n throw new Error(\"mimeType must be a string for single bytes input\");\n }\n return {\n inputs: [{ kind: ExtractInputKind.Bytes, bytes: data, mimeType }],\n sources: [{ data }],\n };\n }\n\n throw new Error(\"Either file_path or data must be provided\");\n}\n\n/**\n * Pair extracted documents with their sources, handling per-input errors.\n *\n * Successful documents preserve input order, so the surviving sources are the\n * inputs whose index is not in the error set. When `raiseOnError` is set the\n * first error is rethrown.\n */\nexport function mapResults(result: XResult, sources: Source[], raiseOnError: boolean): DocSource[] {\n const errors = result.errors ?? [];\n const failedIndices = new Set(errors.map((error) => error.index));\n for (const error of errors) {\n console.warn(`xberg failed to extract input ${error.index} (${error.errorType}): ${error.message}`);\n }\n if (errors.length > 0 && raiseOnError) {\n const first = errors[0];\n throw new Error(`xberg extraction failed for input ${first.index}: ${first.message}`);\n }\n\n const surviving = sources.filter((_, index) => !failedIndices.has(index));\n const results = result.results ?? [];\n const count = Math.min(results.length, surviving.length);\n const paired: DocSource[] = [];\n for (let index = 0; index < count; index += 1) {\n paired.push([results[index], surviving[index]]);\n }\n return paired;\n}\n\nfunction serializeMetadata(metadata: XMetadata | null | undefined): DocumentMetadata {\n if (metadata == null) {\n return {};\n }\n const result: DocumentMetadata = {};\n for (const [field, key] of METADATA_FIELDS) {\n const value = metadata[field];\n if (value != null) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/** Serialize xberg `Element` objects into the reader/node-parser contract. */\nexport function serializeElements(elements: XElement[]): SerializedElement[] {\n return elements.map((element) => ({\n text: element.text,\n element_type: String(element.elementType),\n metadata: {\n page_number: element.metadata?.pageNumber ?? null,\n element_index: element.metadata?.elementIndex ?? null,\n },\n }));\n}\n\n/** Serialize xberg native `Chunk` objects into the node-parser contract. */\nexport function serializeChunks(chunks: XChunk[]): SerializedChunk[] {\n return chunks.map((chunk) => ({\n content: chunk.content,\n chunk_type: String(chunk.chunkType),\n metadata: {\n chunk_index: chunk.metadata?.chunkIndex ?? null,\n total_chunks: chunk.metadata?.totalChunks ?? null,\n first_page: chunk.metadata?.firstPage ?? null,\n last_page: chunk.metadata?.lastPage ?? null,\n heading_path: [...(chunk.metadata?.headingPath ?? [])],\n token_count: chunk.metadata?.tokenCount ?? null,\n },\n }));\n}\n\nfunction serializeImages(images: XImage[], pageNumber: number | undefined): DocumentMetadata[] {\n const serialized: DocumentMetadata[] = [];\n for (const image of images) {\n if (pageNumber !== undefined && image.pageNumber !== pageNumber) {\n continue;\n }\n const raw = image.data;\n const bytes = raw == null ? null : Buffer.from(raw as Uint8Array | number[]);\n const entry: DocumentMetadata = {\n format: image.format,\n image_index: image.imageIndex,\n page_number: image.pageNumber,\n width: image.width,\n height: image.height,\n colorspace: image.colorspace,\n bits_per_component: image.bitsPerComponent,\n is_mask: image.isMask,\n description: image.description,\n data: bytes ? bytes.toString(\"base64\") : null,\n };\n if (image.boundingBox != null) {\n entry.bounding_box = {\n x0: image.boundingBox.x0,\n y0: image.boundingBox.y0,\n x1: image.boundingBox.x1,\n y1: image.boundingBox.y1,\n };\n }\n if (image.ocrResult != null) {\n entry.ocr_result = image.ocrResult.content;\n }\n serialized.push(entry);\n }\n return serialized;\n}\n\n/** Options for {@link buildMetadata}. */\nexport interface BuildMetadataOptions {\n document: XDocument;\n filePath?: string;\n source?: string;\n extraInfo?: Record<string, unknown>;\n pageNumber?: number;\n}\n\n/** Flatten an `ExtractedDocument` into a JSON-serialisable metadata dict. */\nexport function buildMetadata(options: BuildMetadataOptions): DocumentMetadata {\n const { document, filePath, source, extraInfo, pageNumber } = options;\n const meta: DocumentMetadata = {};\n\n if (filePath !== undefined) {\n meta.file_name = basename(filePath);\n meta.file_path = filePath;\n } else if (source !== undefined) {\n meta.file_name = source;\n meta.file_path = source;\n }\n\n meta.file_type = document.mimeType;\n meta.total_pages = document.counts?.pages;\n\n if (pageNumber !== undefined) {\n meta.page_number = pageNumber;\n }\n\n Object.assign(meta, serializeMetadata(document.metadata));\n meta.output_format = document.metadata?.outputFormat;\n\n if (document.qualityScore != null) {\n meta.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages != null) {\n meta.detected_languages = document.detectedLanguages;\n }\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n meta.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n meta.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n if (document.annotations && document.annotations.length > 0) {\n meta.annotations = document.annotations.map((annotation) => ({\n annotation_type: String(annotation.annotationType),\n content: annotation.content,\n page_number: annotation.pageNumber,\n }));\n }\n if (document.elements != null) {\n meta._xberg_elements = serializeElements(document.elements);\n }\n if (document.chunks && document.chunks.length > 0) {\n meta._xberg_chunks = serializeChunks(document.chunks);\n }\n if (document.images && document.images.length > 0) {\n meta.images = serializeImages(document.images, pageNumber);\n }\n\n if (extraInfo) {\n Object.assign(meta, extraInfo);\n }\n\n return meta;\n}\n\n/** Options for {@link generateDocId}. */\nexport interface GenerateDocIdOptions {\n filePath?: string;\n data?: Uint8Array;\n pageNumber?: number;\n}\n\n/** Generate a deterministic document ID via SHA-256 of the resolved source. */\nexport function generateDocId(options: GenerateDocIdOptions): string {\n const { filePath, data, pageNumber } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either file_path or data must be provided\");\n }\n const hasher = createHash(\"sha256\");\n if (filePath !== undefined) {\n hasher.update(resolve(filePath));\n } else if (data !== undefined) {\n hasher.update(data);\n }\n if (pageNumber !== undefined) {\n hasher.update(String(pageNumber));\n }\n return hasher.digest(\"hex\");\n}\n\n/** Return metadata keys excluded from LLM and embedding input. */\nexport function excludedKeys(meta: DocumentMetadata): string[] {\n const keys: string[] = [];\n if (\"_xberg_elements\" in meta) {\n keys.push(\"_xberg_elements\");\n }\n if (\"_xberg_chunks\" in meta) {\n keys.push(\"_xberg_chunks\");\n }\n if (\"images\" in meta) {\n keys.push(\"images\");\n }\n return keys;\n}\n\n/** Append table markdown to content when a table is not already inlined. */\nexport function appendTables(content: string, tables: XTable[] | null | undefined): string {\n if (!tables || tables.length === 0) {\n return content;\n }\n let result = content;\n for (const table of tables) {\n const markdown = table.markdown;\n if (markdown && !result.includes(markdown.trim())) {\n result = `${result.replace(/\\s+$/, \"\")}\\n\\n${markdown}`;\n }\n }\n return result;\n}\n\n/**\n * Build Documents from extracted documents.\n *\n * When an element stream or native chunk list is present the source becomes a\n * single Document carrying `_xberg_elements` / `_xberg_chunks`. Otherwise, when\n * pages are present, one Document is emitted per page. Elements and chunks are\n * document-global, so per-page splitting is suppressed for them to avoid\n * replicating every element or chunk onto every page.\n */\nexport function resultsToDocuments(docSources: DocSource[], extraInfo?: Record<string, unknown>): Document[] {\n const documents: Document[] = [];\n for (const [document, source] of docSources) {\n const sourceLabel = source.data !== undefined ? \"bytes\" : undefined;\n const hasPages = Boolean(document.pages && document.pages.length > 0);\n const hasChunks = Boolean(document.chunks && document.chunks.length > 0);\n\n if (hasPages && document.elements == null && !hasChunks) {\n for (const page of document.pages ?? []) {\n const content = appendTables(page.content, page.tables);\n const meta = buildMetadata({\n document,\n filePath: source.path,\n source: sourceLabel,\n extraInfo,\n pageNumber: page.pageNumber,\n });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data, pageNumber: page.pageNumber }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n } else {\n const content = appendTables(document.content ?? \"\", document.tables);\n const meta = buildMetadata({ document, filePath: source.path, source: sourceLabel, extraInfo });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n }\n return documents;\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport { NodeParser } from \"@llamaindex/core/node-parser\";\nimport { NodeRelationship, TextNode } from \"@llamaindex/core/schema\";\nimport type { BaseNode } from \"@llamaindex/core/schema\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement } from \"./types.js\";\n\nconst ELEMENT_METADATA_KEYS = [\"element_type\", \"page_number\", \"element_index\"] as const;\nconst CHUNK_METADATA_KEYS = [\n \"chunk_type\",\n \"heading_path\",\n \"page_number\",\n \"first_page\",\n \"last_page\",\n \"chunk_index\",\n \"total_chunks\",\n \"token_count\",\n] as const;\nconst FORWARDED_KEYS = [\"_xberg_chunks\", \"_xberg_elements\"] as const;\n\nconst MISSING_ELEMENTS_WARNING =\n \"has no '_xberg_chunks' or '_xberg_elements' metadata. Passing through unchanged. \" +\n \"Use XbergReader with ExtractionConfig(chunking) for native chunk nodes, or \" +\n \"ExtractionConfig(resultFormat='element_based') for element nodes.\";\n\n/** Generates the id for a child node from its running index and source node. */\nexport type NodeIdFunction = (index: number, source: BaseNode) => string;\n\n/** Constructor options for {@link XbergNodeParser}. */\nexport interface XbergNodeParserConfig {\n idFunc?: NodeIdFunction;\n}\n\n/**\n * Structure-aware node parser for xberg-extracted documents.\n *\n * Turns xberg's output into individual `TextNode` objects, preferring xberg's\n * native chunks (`_xberg_chunks`) and falling back to structural elements\n * (`_xberg_elements`). Documents carrying neither pass through unchanged with a\n * warning. It never calls xberg — it consumes Documents produced by\n * {@link XbergReader}.\n */\nexport class XbergNodeParser extends NodeParser<TextNode[]> {\n private readonly idFunc: NodeIdFunction;\n\n constructor(config: XbergNodeParserConfig = {}) {\n super();\n this.idFunc = config.idFunc ?? (() => randomUUID());\n }\n\n protected parseNodes(documents: TextNode[]): TextNode[] {\n const output: TextNode[] = [];\n\n for (const node of documents) {\n const chunks = node.metadata[FORWARDED_KEYS[0]];\n if (Array.isArray(chunks) && chunks.length > 0) {\n output.push(...this.nodesFromChunks(node, chunks as SerializedChunk[]));\n continue;\n }\n\n const elements = node.metadata[FORWARDED_KEYS[1]];\n if (Array.isArray(elements) && elements.length > 0) {\n output.push(...this.nodesFromElements(node, elements as SerializedElement[]));\n continue;\n }\n\n console.warn(`Document ${node.id_} ${MISSING_ELEMENTS_WARNING}`);\n output.push(node);\n }\n\n return output;\n }\n\n private newTextNode(text: string, index: number, source: TextNode, metadata: DocumentMetadata): TextNode {\n return new TextNode({\n text,\n id_: this.idFunc(index, source),\n metadata,\n excludedLlmMetadataKeys: [...source.excludedLlmMetadataKeys],\n metadataSeparator: source.metadataSeparator,\n textTemplate: source.textTemplate,\n relationships: { [NodeRelationship.SOURCE]: source.asRelatedNodeInfo() },\n });\n }\n\n private nodesFromChunks(source: TextNode, chunks: SerializedChunk[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...CHUNK_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const chunk of chunks) {\n const text = chunk.content ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = chunk.metadata;\n const textNode = this.newTextNode(text, index, source, {\n chunk_type: chunk.chunk_type ?? \"unknown\",\n heading_path: meta?.heading_path ?? [],\n page_number: meta?.first_page,\n first_page: meta?.first_page,\n last_page: meta?.last_page,\n chunk_index: meta?.chunk_index,\n total_chunks: meta?.total_chunks,\n token_count: meta?.token_count,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n private nodesFromElements(source: TextNode, elements: SerializedElement[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...ELEMENT_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const element of elements) {\n const text = element.text ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = element.metadata;\n const textNode = this.newTextNode(text, index, source, {\n element_type: element.element_type ?? \"unknown\",\n page_number: meta?.page_number,\n element_index: meta?.element_index,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n protected override postProcessParsedNodes(nodes: TextNode[], parentDocMap: Map<string, TextNode>): TextNode[] {\n const processed = super.postProcessParsedNodes(nodes, parentDocMap);\n return stripForwardedMetadata(processed);\n }\n}\n\n/**\n * Remove reader forwarding keys from child nodes only. The base parser copies\n * parent metadata (including the forwarding keys) onto children, so they are\n * stripped here; passthrough documents keep their metadata untouched.\n */\nfunction stripForwardedMetadata(nodes: TextNode[]): TextNode[] {\n for (const node of nodes) {\n if (node.sourceNode !== undefined) {\n for (const key of FORWARDED_KEYS) {\n delete node.metadata[key];\n }\n }\n }\n return nodes;\n}\n"],"mappings":"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","names":["import_xberg","import_node_crypto","import_schema"]}
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { extract, extractBatch } from "@xberg-io/xberg";
5
5
  import { createHash } from "crypto";
6
6
  import { basename, resolve } from "path";
7
7
  import { Document } from "@llamaindex/core/schema";
8
+ import { ExtractInputKind } from "@xberg-io/xberg";
8
9
  var DEFAULT_RESULT_FORMAT = "element_based";
9
10
  var PAGE_RESULT_FORMAT = "unified";
10
11
  var METADATA_FIELDS = [
@@ -40,7 +41,7 @@ function prepareInputs(input) {
40
41
  if (typeof input === "string" || Array.isArray(input)) {
41
42
  const paths = Array.isArray(input) ? input : [input];
42
43
  return {
43
- inputs: paths.map((path) => ({ kind: "uri", uri: path })),
44
+ inputs: paths.map((path) => ({ kind: ExtractInputKind.Uri, uri: path })),
44
45
  sources: paths.map((path) => ({ path }))
45
46
  };
46
47
  }
@@ -51,7 +52,7 @@ function prepareInputs(input) {
51
52
  throw new Error("data and mimeType must be parallel lists of equal length");
52
53
  }
53
54
  return {
54
- inputs: data.map((bytes, index) => ({ kind: "bytes", bytes, mimeType: mimeType[index] })),
55
+ inputs: data.map((bytes, index) => ({ kind: ExtractInputKind.Bytes, bytes, mimeType: mimeType[index] })),
55
56
  sources: data.map((bytes) => ({ data: bytes }))
56
57
  };
57
58
  }
@@ -59,7 +60,7 @@ function prepareInputs(input) {
59
60
  throw new Error("mimeType must be a string for single bytes input");
60
61
  }
61
62
  return {
62
- inputs: [{ kind: "bytes", bytes: data, mimeType }],
63
+ inputs: [{ kind: ExtractInputKind.Bytes, bytes: data, mimeType }],
63
64
  sources: [{ data }]
64
65
  };
65
66
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/reader.ts","../src/readerMapping.ts","../src/nodeParser.ts"],"sourcesContent":["import { extract, extractBatch } from \"@xberg-io/xberg\";\nimport type { ExtractionConfig, ExtractionResult } from \"@xberg-io/xberg\";\n\nimport type { BaseReader, Document } from \"@llamaindex/core/schema\";\n\nimport { buildExtractionConfig, mapResults, prepareInputs, resultsToDocuments, type XResult } from \"./readerMapping.js\";\nimport type { XbergInput, XbergReaderConfig } from \"./types.js\";\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Reader for 101 document formats powered by xberg's Rust extraction engine.\n *\n * Supports file paths, raw bytes, batch input, per-page splitting, and true\n * async via xberg's native `extract` / `extractBatch` functions. A single input\n * is dispatched to `extract`; multiple inputs go through `extractBatch`.\n */\nexport class XbergReader implements BaseReader<Document> {\n private readonly raiseOnError: boolean;\n private readonly extractionConfig?: ExtractionConfig;\n\n constructor(config: XbergReaderConfig = {}) {\n this.raiseOnError = config.raiseOnError ?? false;\n this.extractionConfig = config.extractionConfig;\n }\n\n async loadData(input: XbergInput, extraInfo?: Record<string, unknown>): Promise<Document[]> {\n const { inputs, sources } = prepareInputs(input);\n const config = buildExtractionConfig(this.extractionConfig);\n\n let result: ExtractionResult;\n try {\n result = inputs.length === 1 ? await extract(inputs[0], config) : await extractBatch(inputs, config);\n } catch (error) {\n if (this.raiseOnError) {\n throw error;\n }\n console.warn(`xberg extraction failed: ${errorMessage(error)}`);\n return [];\n }\n\n const docSources = mapResults(result as unknown as XResult, sources, this.raiseOnError);\n return resultsToDocuments(docSources, extraInfo);\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { basename, resolve } from \"node:path\";\n\nimport { Document } from \"@llamaindex/core/schema\";\n\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement, XbergBytesInput, XbergInput } from \"./types.js\";\n\n// Default result format so `ExtractedDocument.elements` is populated and the\n// companion XbergNodeParser can split documents element-by-element. ~keep\nconst DEFAULT_RESULT_FORMAT = \"element_based\";\nconst PAGE_RESULT_FORMAT = \"unified\";\n\n/**\n * The camelCase shapes the mappers read from the `@xberg-io/xberg` binding.\n * The binding exposes these via unexported `Js*` aliases, so structural\n * interfaces are declared locally and the native result is cast through them.\n */\ninterface XMetadata {\n title?: string | null;\n subject?: string | null;\n authors?: string[] | null;\n keywords?: string[] | null;\n language?: string | null;\n createdAt?: string | null;\n modifiedAt?: string | null;\n createdBy?: string | null;\n modifiedBy?: string | null;\n category?: string | null;\n tags?: string[] | null;\n documentVersion?: string | null;\n abstractText?: string | null;\n outputFormat?: string | null;\n}\n\ninterface XTable {\n markdown?: string | null;\n}\n\ninterface XPage {\n pageNumber: number;\n content: string;\n tables?: XTable[] | null;\n}\n\ninterface XElement {\n elementType: unknown;\n text: string;\n metadata?: { pageNumber?: number | null; elementIndex?: number | null } | null;\n}\n\ninterface XChunk {\n content: string;\n chunkType: unknown;\n metadata?: {\n chunkIndex?: number | null;\n totalChunks?: number | null;\n firstPage?: number | null;\n lastPage?: number | null;\n headingPath?: string[] | null;\n tokenCount?: number | null;\n } | null;\n}\n\ninterface XKeyword {\n text: string;\n score: number;\n algorithm: unknown;\n}\n\ninterface XWarning {\n source: string;\n message: string;\n}\n\ninterface XAnnotation {\n annotationType: unknown;\n content?: string | null;\n pageNumber: number;\n}\n\ninterface XBoundingBox {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\ninterface XImage {\n data?: Uint8Array | Buffer | number[] | null;\n format?: string | null;\n imageIndex?: number | null;\n pageNumber?: number | null;\n width?: number | null;\n height?: number | null;\n colorspace?: string | null;\n bitsPerComponent?: number | null;\n isMask?: boolean | null;\n description?: string | null;\n boundingBox?: XBoundingBox | null;\n ocrResult?: { content?: string | null } | null;\n}\n\ninterface XCounts {\n pages?: number | null;\n}\n\nexport interface XDocument {\n content?: string | null;\n mimeType?: string | null;\n metadata?: XMetadata | null;\n counts?: XCounts | null;\n tables?: XTable[] | null;\n pages?: XPage[] | null;\n elements?: XElement[] | null;\n chunks?: XChunk[] | null;\n images?: XImage[] | null;\n qualityScore?: number | null;\n detectedLanguages?: string[] | null;\n processingWarnings?: XWarning[] | null;\n extractedKeywords?: XKeyword[] | null;\n annotations?: XAnnotation[] | null;\n}\n\nexport interface XError {\n index: number;\n errorType: string;\n message: string;\n}\n\nexport interface XResult {\n results?: XDocument[] | null;\n errors?: XError[] | null;\n}\n\n/** Tracks the origin of one extraction input for metadata/id purposes. */\nexport interface Source {\n path?: string;\n data?: Uint8Array;\n}\n\n/** A successfully extracted document paired with its source descriptor. */\nexport type DocSource = [XDocument, Source];\n\n// Scalar / list `Metadata` fields copied verbatim into document metadata,\n// mapping the binding's camelCase field to its snake_case output key. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [keyof XMetadata, string]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"createdAt\", \"created_at\"],\n [\"modifiedAt\", \"modified_at\"],\n [\"createdBy\", \"created_by\"],\n [\"modifiedBy\", \"modified_by\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"documentVersion\", \"document_version\"],\n [\"abstractText\", \"abstract_text\"],\n];\n\n/** Return true when the config opts into page extraction. */\nexport function pagesRequested(config: ExtractionConfig | undefined): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\n/**\n * Return the `ExtractionConfig` to use, defaulting `resultFormat`.\n *\n * With no explicit `resultFormat` the reader defaults to `element_based` so the\n * element stream is populated and forwarded to the node parser. When the caller\n * opts into page extraction the reader defaults to `unified` instead, so pages\n * split cleanly without replicating the document-wide element stream. An\n * explicit `resultFormat` always wins.\n */\nexport function buildExtractionConfig(config: ExtractionConfig | undefined): ExtractionConfig {\n const base = { ...config };\n if (base.resultFormat !== undefined) {\n return base;\n }\n const resultFormat = pagesRequested(base) ? PAGE_RESULT_FORMAT : DEFAULT_RESULT_FORMAT;\n return { ...base, resultFormat } as unknown as ExtractionConfig;\n}\n\nfunction isBytesInput(input: XbergInput): input is XbergBytesInput {\n return typeof input === \"object\" && !Array.isArray(input) && \"data\" in input;\n}\n\n/** Validate the reader input and build parallel xberg inputs and sources. */\nexport function prepareInputs(input: XbergInput): { inputs: ExtractInput[]; sources: Source[] } {\n if (typeof input === \"string\" || Array.isArray(input)) {\n const paths = Array.isArray(input) ? input : [input];\n return {\n inputs: paths.map((path) => ({ kind: \"uri\", uri: path })),\n sources: paths.map((path) => ({ path })),\n };\n }\n\n if (isBytesInput(input)) {\n const { data, mimeType } = input;\n if (Array.isArray(data)) {\n if (!Array.isArray(mimeType) || data.length !== mimeType.length) {\n throw new Error(\"data and mimeType must be parallel lists of equal length\");\n }\n return {\n inputs: data.map((bytes, index) => ({ kind: \"bytes\", bytes, mimeType: mimeType[index] })),\n sources: data.map((bytes) => ({ data: bytes })),\n };\n }\n if (typeof mimeType !== \"string\") {\n throw new Error(\"mimeType must be a string for single bytes input\");\n }\n return {\n inputs: [{ kind: \"bytes\", bytes: data, mimeType }],\n sources: [{ data }],\n };\n }\n\n throw new Error(\"Either file_path or data must be provided\");\n}\n\n/**\n * Pair extracted documents with their sources, handling per-input errors.\n *\n * Successful documents preserve input order, so the surviving sources are the\n * inputs whose index is not in the error set. When `raiseOnError` is set the\n * first error is rethrown.\n */\nexport function mapResults(result: XResult, sources: Source[], raiseOnError: boolean): DocSource[] {\n const errors = result.errors ?? [];\n const failedIndices = new Set(errors.map((error) => error.index));\n for (const error of errors) {\n console.warn(`xberg failed to extract input ${error.index} (${error.errorType}): ${error.message}`);\n }\n if (errors.length > 0 && raiseOnError) {\n const first = errors[0];\n throw new Error(`xberg extraction failed for input ${first.index}: ${first.message}`);\n }\n\n const surviving = sources.filter((_, index) => !failedIndices.has(index));\n const results = result.results ?? [];\n const count = Math.min(results.length, surviving.length);\n const paired: DocSource[] = [];\n for (let index = 0; index < count; index += 1) {\n paired.push([results[index], surviving[index]]);\n }\n return paired;\n}\n\nfunction serializeMetadata(metadata: XMetadata | null | undefined): DocumentMetadata {\n if (metadata == null) {\n return {};\n }\n const result: DocumentMetadata = {};\n for (const [field, key] of METADATA_FIELDS) {\n const value = metadata[field];\n if (value != null) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/** Serialize xberg `Element` objects into the reader/node-parser contract. */\nexport function serializeElements(elements: XElement[]): SerializedElement[] {\n return elements.map((element) => ({\n text: element.text,\n element_type: String(element.elementType),\n metadata: {\n page_number: element.metadata?.pageNumber ?? null,\n element_index: element.metadata?.elementIndex ?? null,\n },\n }));\n}\n\n/** Serialize xberg native `Chunk` objects into the node-parser contract. */\nexport function serializeChunks(chunks: XChunk[]): SerializedChunk[] {\n return chunks.map((chunk) => ({\n content: chunk.content,\n chunk_type: String(chunk.chunkType),\n metadata: {\n chunk_index: chunk.metadata?.chunkIndex ?? null,\n total_chunks: chunk.metadata?.totalChunks ?? null,\n first_page: chunk.metadata?.firstPage ?? null,\n last_page: chunk.metadata?.lastPage ?? null,\n heading_path: [...(chunk.metadata?.headingPath ?? [])],\n token_count: chunk.metadata?.tokenCount ?? null,\n },\n }));\n}\n\nfunction serializeImages(images: XImage[], pageNumber: number | undefined): DocumentMetadata[] {\n const serialized: DocumentMetadata[] = [];\n for (const image of images) {\n if (pageNumber !== undefined && image.pageNumber !== pageNumber) {\n continue;\n }\n const raw = image.data;\n const bytes = raw == null ? null : Buffer.from(raw as Uint8Array | number[]);\n const entry: DocumentMetadata = {\n format: image.format,\n image_index: image.imageIndex,\n page_number: image.pageNumber,\n width: image.width,\n height: image.height,\n colorspace: image.colorspace,\n bits_per_component: image.bitsPerComponent,\n is_mask: image.isMask,\n description: image.description,\n data: bytes ? bytes.toString(\"base64\") : null,\n };\n if (image.boundingBox != null) {\n entry.bounding_box = {\n x0: image.boundingBox.x0,\n y0: image.boundingBox.y0,\n x1: image.boundingBox.x1,\n y1: image.boundingBox.y1,\n };\n }\n if (image.ocrResult != null) {\n entry.ocr_result = image.ocrResult.content;\n }\n serialized.push(entry);\n }\n return serialized;\n}\n\n/** Options for {@link buildMetadata}. */\nexport interface BuildMetadataOptions {\n document: XDocument;\n filePath?: string;\n source?: string;\n extraInfo?: Record<string, unknown>;\n pageNumber?: number;\n}\n\n/** Flatten an `ExtractedDocument` into a JSON-serialisable metadata dict. */\nexport function buildMetadata(options: BuildMetadataOptions): DocumentMetadata {\n const { document, filePath, source, extraInfo, pageNumber } = options;\n const meta: DocumentMetadata = {};\n\n if (filePath !== undefined) {\n meta.file_name = basename(filePath);\n meta.file_path = filePath;\n } else if (source !== undefined) {\n meta.file_name = source;\n meta.file_path = source;\n }\n\n meta.file_type = document.mimeType;\n meta.total_pages = document.counts?.pages;\n\n if (pageNumber !== undefined) {\n meta.page_number = pageNumber;\n }\n\n Object.assign(meta, serializeMetadata(document.metadata));\n meta.output_format = document.metadata?.outputFormat;\n\n if (document.qualityScore != null) {\n meta.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages != null) {\n meta.detected_languages = document.detectedLanguages;\n }\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n meta.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n meta.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n if (document.annotations && document.annotations.length > 0) {\n meta.annotations = document.annotations.map((annotation) => ({\n annotation_type: String(annotation.annotationType),\n content: annotation.content,\n page_number: annotation.pageNumber,\n }));\n }\n if (document.elements != null) {\n meta._xberg_elements = serializeElements(document.elements);\n }\n if (document.chunks && document.chunks.length > 0) {\n meta._xberg_chunks = serializeChunks(document.chunks);\n }\n if (document.images && document.images.length > 0) {\n meta.images = serializeImages(document.images, pageNumber);\n }\n\n if (extraInfo) {\n Object.assign(meta, extraInfo);\n }\n\n return meta;\n}\n\n/** Options for {@link generateDocId}. */\nexport interface GenerateDocIdOptions {\n filePath?: string;\n data?: Uint8Array;\n pageNumber?: number;\n}\n\n/** Generate a deterministic document ID via SHA-256 of the resolved source. */\nexport function generateDocId(options: GenerateDocIdOptions): string {\n const { filePath, data, pageNumber } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either file_path or data must be provided\");\n }\n const hasher = createHash(\"sha256\");\n if (filePath !== undefined) {\n hasher.update(resolve(filePath));\n } else if (data !== undefined) {\n hasher.update(data);\n }\n if (pageNumber !== undefined) {\n hasher.update(String(pageNumber));\n }\n return hasher.digest(\"hex\");\n}\n\n/** Return metadata keys excluded from LLM and embedding input. */\nexport function excludedKeys(meta: DocumentMetadata): string[] {\n const keys: string[] = [];\n if (\"_xberg_elements\" in meta) {\n keys.push(\"_xberg_elements\");\n }\n if (\"_xberg_chunks\" in meta) {\n keys.push(\"_xberg_chunks\");\n }\n if (\"images\" in meta) {\n keys.push(\"images\");\n }\n return keys;\n}\n\n/** Append table markdown to content when a table is not already inlined. */\nexport function appendTables(content: string, tables: XTable[] | null | undefined): string {\n if (!tables || tables.length === 0) {\n return content;\n }\n let result = content;\n for (const table of tables) {\n const markdown = table.markdown;\n if (markdown && !result.includes(markdown.trim())) {\n result = `${result.replace(/\\s+$/, \"\")}\\n\\n${markdown}`;\n }\n }\n return result;\n}\n\n/**\n * Build Documents from extracted documents.\n *\n * When an element stream or native chunk list is present the source becomes a\n * single Document carrying `_xberg_elements` / `_xberg_chunks`. Otherwise, when\n * pages are present, one Document is emitted per page. Elements and chunks are\n * document-global, so per-page splitting is suppressed for them to avoid\n * replicating every element or chunk onto every page.\n */\nexport function resultsToDocuments(docSources: DocSource[], extraInfo?: Record<string, unknown>): Document[] {\n const documents: Document[] = [];\n for (const [document, source] of docSources) {\n const sourceLabel = source.data !== undefined ? \"bytes\" : undefined;\n const hasPages = Boolean(document.pages && document.pages.length > 0);\n const hasChunks = Boolean(document.chunks && document.chunks.length > 0);\n\n if (hasPages && document.elements == null && !hasChunks) {\n for (const page of document.pages ?? []) {\n const content = appendTables(page.content, page.tables);\n const meta = buildMetadata({\n document,\n filePath: source.path,\n source: sourceLabel,\n extraInfo,\n pageNumber: page.pageNumber,\n });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data, pageNumber: page.pageNumber }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n } else {\n const content = appendTables(document.content ?? \"\", document.tables);\n const meta = buildMetadata({ document, filePath: source.path, source: sourceLabel, extraInfo });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n }\n return documents;\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport { NodeParser } from \"@llamaindex/core/node-parser\";\nimport { NodeRelationship, TextNode } from \"@llamaindex/core/schema\";\nimport type { BaseNode } from \"@llamaindex/core/schema\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement } from \"./types.js\";\n\nconst ELEMENT_METADATA_KEYS = [\"element_type\", \"page_number\", \"element_index\"] as const;\nconst CHUNK_METADATA_KEYS = [\n \"chunk_type\",\n \"heading_path\",\n \"page_number\",\n \"first_page\",\n \"last_page\",\n \"chunk_index\",\n \"total_chunks\",\n \"token_count\",\n] as const;\nconst FORWARDED_KEYS = [\"_xberg_chunks\", \"_xberg_elements\"] as const;\n\nconst MISSING_ELEMENTS_WARNING =\n \"has no '_xberg_chunks' or '_xberg_elements' metadata. Passing through unchanged. \" +\n \"Use XbergReader with ExtractionConfig(chunking) for native chunk nodes, or \" +\n \"ExtractionConfig(resultFormat='element_based') for element nodes.\";\n\n/** Generates the id for a child node from its running index and source node. */\nexport type NodeIdFunction = (index: number, source: BaseNode) => string;\n\n/** Constructor options for {@link XbergNodeParser}. */\nexport interface XbergNodeParserConfig {\n idFunc?: NodeIdFunction;\n}\n\n/**\n * Structure-aware node parser for xberg-extracted documents.\n *\n * Turns xberg's output into individual `TextNode` objects, preferring xberg's\n * native chunks (`_xberg_chunks`) and falling back to structural elements\n * (`_xberg_elements`). Documents carrying neither pass through unchanged with a\n * warning. It never calls xberg — it consumes Documents produced by\n * {@link XbergReader}.\n */\nexport class XbergNodeParser extends NodeParser<TextNode[]> {\n private readonly idFunc: NodeIdFunction;\n\n constructor(config: XbergNodeParserConfig = {}) {\n super();\n this.idFunc = config.idFunc ?? (() => randomUUID());\n }\n\n protected parseNodes(documents: TextNode[]): TextNode[] {\n const output: TextNode[] = [];\n\n for (const node of documents) {\n const chunks = node.metadata[FORWARDED_KEYS[0]];\n if (Array.isArray(chunks) && chunks.length > 0) {\n output.push(...this.nodesFromChunks(node, chunks as SerializedChunk[]));\n continue;\n }\n\n const elements = node.metadata[FORWARDED_KEYS[1]];\n if (Array.isArray(elements) && elements.length > 0) {\n output.push(...this.nodesFromElements(node, elements as SerializedElement[]));\n continue;\n }\n\n console.warn(`Document ${node.id_} ${MISSING_ELEMENTS_WARNING}`);\n output.push(node);\n }\n\n return output;\n }\n\n private newTextNode(text: string, index: number, source: TextNode, metadata: DocumentMetadata): TextNode {\n return new TextNode({\n text,\n id_: this.idFunc(index, source),\n metadata,\n excludedLlmMetadataKeys: [...source.excludedLlmMetadataKeys],\n metadataSeparator: source.metadataSeparator,\n textTemplate: source.textTemplate,\n relationships: { [NodeRelationship.SOURCE]: source.asRelatedNodeInfo() },\n });\n }\n\n private nodesFromChunks(source: TextNode, chunks: SerializedChunk[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...CHUNK_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const chunk of chunks) {\n const text = chunk.content ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = chunk.metadata;\n const textNode = this.newTextNode(text, index, source, {\n chunk_type: chunk.chunk_type ?? \"unknown\",\n heading_path: meta?.heading_path ?? [],\n page_number: meta?.first_page,\n first_page: meta?.first_page,\n last_page: meta?.last_page,\n chunk_index: meta?.chunk_index,\n total_chunks: meta?.total_chunks,\n token_count: meta?.token_count,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n private nodesFromElements(source: TextNode, elements: SerializedElement[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...ELEMENT_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const element of elements) {\n const text = element.text ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = element.metadata;\n const textNode = this.newTextNode(text, index, source, {\n element_type: element.element_type ?? \"unknown\",\n page_number: meta?.page_number,\n element_index: meta?.element_index,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n protected override postProcessParsedNodes(nodes: TextNode[], parentDocMap: Map<string, TextNode>): TextNode[] {\n const processed = super.postProcessParsedNodes(nodes, parentDocMap);\n return stripForwardedMetadata(processed);\n }\n}\n\n/**\n * Remove reader forwarding keys from child nodes only. The base parser copies\n * parent metadata (including the forwarding keys) onto children, so they are\n * stripped here; passthrough documents keep their metadata untouched.\n */\nfunction stripForwardedMetadata(nodes: TextNode[]): TextNode[] {\n for (const node of nodes) {\n if (node.sourceNode !== undefined) {\n for (const key of FORWARDED_KEYS) {\n delete node.metadata[key];\n }\n }\n }\n return nodes;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/reader.ts","../src/readerMapping.ts","../src/nodeParser.ts"],"sourcesContent":["import { extract, extractBatch } from \"@xberg-io/xberg\";\nimport type { ExtractionConfig, ExtractionResult } from \"@xberg-io/xberg\";\n\nimport type { BaseReader, Document } from \"@llamaindex/core/schema\";\n\nimport { buildExtractionConfig, mapResults, prepareInputs, resultsToDocuments, type XResult } from \"./readerMapping.js\";\nimport type { XbergInput, XbergReaderConfig } from \"./types.js\";\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Reader for 101 document formats powered by xberg's Rust extraction engine.\n *\n * Supports file paths, raw bytes, batch input, per-page splitting, and true\n * async via xberg's native `extract` / `extractBatch` functions. A single input\n * is dispatched to `extract`; multiple inputs go through `extractBatch`.\n */\nexport class XbergReader implements BaseReader<Document> {\n private readonly raiseOnError: boolean;\n private readonly extractionConfig?: ExtractionConfig;\n\n constructor(config: XbergReaderConfig = {}) {\n this.raiseOnError = config.raiseOnError ?? false;\n this.extractionConfig = config.extractionConfig;\n }\n\n async loadData(input: XbergInput, extraInfo?: Record<string, unknown>): Promise<Document[]> {\n const { inputs, sources } = prepareInputs(input);\n const config = buildExtractionConfig(this.extractionConfig);\n\n let result: ExtractionResult;\n try {\n result = inputs.length === 1 ? await extract(inputs[0], config) : await extractBatch(inputs, config);\n } catch (error) {\n if (this.raiseOnError) {\n throw error;\n }\n console.warn(`xberg extraction failed: ${errorMessage(error)}`);\n return [];\n }\n\n const docSources = mapResults(result as unknown as XResult, sources, this.raiseOnError);\n return resultsToDocuments(docSources, extraInfo);\n }\n}\n","import { createHash } from \"node:crypto\";\nimport { basename, resolve } from \"node:path\";\n\nimport { Document } from \"@llamaindex/core/schema\";\n\nimport { ExtractInputKind } from \"@xberg-io/xberg\";\nimport type { ExtractInput, ExtractionConfig } from \"@xberg-io/xberg\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement, XbergBytesInput, XbergInput } from \"./types.js\";\n\n// Default result format so `ExtractedDocument.elements` is populated and the\n// companion XbergNodeParser can split documents element-by-element. ~keep\nconst DEFAULT_RESULT_FORMAT = \"element_based\";\nconst PAGE_RESULT_FORMAT = \"unified\";\n\n/**\n * The camelCase shapes the mappers read from the `@xberg-io/xberg` binding.\n * The binding exposes these via unexported `Js*` aliases, so structural\n * interfaces are declared locally and the native result is cast through them.\n */\ninterface XMetadata {\n title?: string | null;\n subject?: string | null;\n authors?: string[] | null;\n keywords?: string[] | null;\n language?: string | null;\n createdAt?: string | null;\n modifiedAt?: string | null;\n createdBy?: string | null;\n modifiedBy?: string | null;\n category?: string | null;\n tags?: string[] | null;\n documentVersion?: string | null;\n abstractText?: string | null;\n outputFormat?: string | null;\n}\n\ninterface XTable {\n markdown?: string | null;\n}\n\ninterface XPage {\n pageNumber: number;\n content: string;\n tables?: XTable[] | null;\n}\n\ninterface XElement {\n elementType: unknown;\n text: string;\n metadata?: { pageNumber?: number | null; elementIndex?: number | null } | null;\n}\n\ninterface XChunk {\n content: string;\n chunkType: unknown;\n metadata?: {\n chunkIndex?: number | null;\n totalChunks?: number | null;\n firstPage?: number | null;\n lastPage?: number | null;\n headingPath?: string[] | null;\n tokenCount?: number | null;\n } | null;\n}\n\ninterface XKeyword {\n text: string;\n score: number;\n algorithm: unknown;\n}\n\ninterface XWarning {\n source: string;\n message: string;\n}\n\ninterface XAnnotation {\n annotationType: unknown;\n content?: string | null;\n pageNumber: number;\n}\n\ninterface XBoundingBox {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n}\n\ninterface XImage {\n data?: Uint8Array | Buffer | number[] | null;\n format?: string | null;\n imageIndex?: number | null;\n pageNumber?: number | null;\n width?: number | null;\n height?: number | null;\n colorspace?: string | null;\n bitsPerComponent?: number | null;\n isMask?: boolean | null;\n description?: string | null;\n boundingBox?: XBoundingBox | null;\n ocrResult?: { content?: string | null } | null;\n}\n\ninterface XCounts {\n pages?: number | null;\n}\n\nexport interface XDocument {\n content?: string | null;\n mimeType?: string | null;\n metadata?: XMetadata | null;\n counts?: XCounts | null;\n tables?: XTable[] | null;\n pages?: XPage[] | null;\n elements?: XElement[] | null;\n chunks?: XChunk[] | null;\n images?: XImage[] | null;\n qualityScore?: number | null;\n detectedLanguages?: string[] | null;\n processingWarnings?: XWarning[] | null;\n extractedKeywords?: XKeyword[] | null;\n annotations?: XAnnotation[] | null;\n}\n\nexport interface XError {\n index: number;\n errorType: string;\n message: string;\n}\n\nexport interface XResult {\n results?: XDocument[] | null;\n errors?: XError[] | null;\n}\n\n/** Tracks the origin of one extraction input for metadata/id purposes. */\nexport interface Source {\n path?: string;\n data?: Uint8Array;\n}\n\n/** A successfully extracted document paired with its source descriptor. */\nexport type DocSource = [XDocument, Source];\n\n// Scalar / list `Metadata` fields copied verbatim into document metadata,\n// mapping the binding's camelCase field to its snake_case output key. ~keep\nconst METADATA_FIELDS: ReadonlyArray<readonly [keyof XMetadata, string]> = [\n [\"title\", \"title\"],\n [\"subject\", \"subject\"],\n [\"authors\", \"authors\"],\n [\"keywords\", \"keywords\"],\n [\"language\", \"language\"],\n [\"createdAt\", \"created_at\"],\n [\"modifiedAt\", \"modified_at\"],\n [\"createdBy\", \"created_by\"],\n [\"modifiedBy\", \"modified_by\"],\n [\"category\", \"category\"],\n [\"tags\", \"tags\"],\n [\"documentVersion\", \"document_version\"],\n [\"abstractText\", \"abstract_text\"],\n];\n\n/** Return true when the config opts into page extraction. */\nexport function pagesRequested(config: ExtractionConfig | undefined): boolean {\n return Boolean(config?.pages?.extractPages);\n}\n\n/**\n * Return the `ExtractionConfig` to use, defaulting `resultFormat`.\n *\n * With no explicit `resultFormat` the reader defaults to `element_based` so the\n * element stream is populated and forwarded to the node parser. When the caller\n * opts into page extraction the reader defaults to `unified` instead, so pages\n * split cleanly without replicating the document-wide element stream. An\n * explicit `resultFormat` always wins.\n */\nexport function buildExtractionConfig(config: ExtractionConfig | undefined): ExtractionConfig {\n const base = { ...config };\n if (base.resultFormat !== undefined) {\n return base;\n }\n const resultFormat = pagesRequested(base) ? PAGE_RESULT_FORMAT : DEFAULT_RESULT_FORMAT;\n return { ...base, resultFormat } as unknown as ExtractionConfig;\n}\n\nfunction isBytesInput(input: XbergInput): input is XbergBytesInput {\n return typeof input === \"object\" && !Array.isArray(input) && \"data\" in input;\n}\n\n/** Validate the reader input and build parallel xberg inputs and sources. */\nexport function prepareInputs(input: XbergInput): { inputs: ExtractInput[]; sources: Source[] } {\n if (typeof input === \"string\" || Array.isArray(input)) {\n const paths = Array.isArray(input) ? input : [input];\n return {\n inputs: paths.map((path) => ({ kind: ExtractInputKind.Uri, uri: path })),\n sources: paths.map((path) => ({ path })),\n };\n }\n\n if (isBytesInput(input)) {\n const { data, mimeType } = input;\n if (Array.isArray(data)) {\n if (!Array.isArray(mimeType) || data.length !== mimeType.length) {\n throw new Error(\"data and mimeType must be parallel lists of equal length\");\n }\n return {\n inputs: data.map((bytes, index) => ({ kind: ExtractInputKind.Bytes, bytes, mimeType: mimeType[index] })),\n sources: data.map((bytes) => ({ data: bytes })),\n };\n }\n if (typeof mimeType !== \"string\") {\n throw new Error(\"mimeType must be a string for single bytes input\");\n }\n return {\n inputs: [{ kind: ExtractInputKind.Bytes, bytes: data, mimeType }],\n sources: [{ data }],\n };\n }\n\n throw new Error(\"Either file_path or data must be provided\");\n}\n\n/**\n * Pair extracted documents with their sources, handling per-input errors.\n *\n * Successful documents preserve input order, so the surviving sources are the\n * inputs whose index is not in the error set. When `raiseOnError` is set the\n * first error is rethrown.\n */\nexport function mapResults(result: XResult, sources: Source[], raiseOnError: boolean): DocSource[] {\n const errors = result.errors ?? [];\n const failedIndices = new Set(errors.map((error) => error.index));\n for (const error of errors) {\n console.warn(`xberg failed to extract input ${error.index} (${error.errorType}): ${error.message}`);\n }\n if (errors.length > 0 && raiseOnError) {\n const first = errors[0];\n throw new Error(`xberg extraction failed for input ${first.index}: ${first.message}`);\n }\n\n const surviving = sources.filter((_, index) => !failedIndices.has(index));\n const results = result.results ?? [];\n const count = Math.min(results.length, surviving.length);\n const paired: DocSource[] = [];\n for (let index = 0; index < count; index += 1) {\n paired.push([results[index], surviving[index]]);\n }\n return paired;\n}\n\nfunction serializeMetadata(metadata: XMetadata | null | undefined): DocumentMetadata {\n if (metadata == null) {\n return {};\n }\n const result: DocumentMetadata = {};\n for (const [field, key] of METADATA_FIELDS) {\n const value = metadata[field];\n if (value != null) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/** Serialize xberg `Element` objects into the reader/node-parser contract. */\nexport function serializeElements(elements: XElement[]): SerializedElement[] {\n return elements.map((element) => ({\n text: element.text,\n element_type: String(element.elementType),\n metadata: {\n page_number: element.metadata?.pageNumber ?? null,\n element_index: element.metadata?.elementIndex ?? null,\n },\n }));\n}\n\n/** Serialize xberg native `Chunk` objects into the node-parser contract. */\nexport function serializeChunks(chunks: XChunk[]): SerializedChunk[] {\n return chunks.map((chunk) => ({\n content: chunk.content,\n chunk_type: String(chunk.chunkType),\n metadata: {\n chunk_index: chunk.metadata?.chunkIndex ?? null,\n total_chunks: chunk.metadata?.totalChunks ?? null,\n first_page: chunk.metadata?.firstPage ?? null,\n last_page: chunk.metadata?.lastPage ?? null,\n heading_path: [...(chunk.metadata?.headingPath ?? [])],\n token_count: chunk.metadata?.tokenCount ?? null,\n },\n }));\n}\n\nfunction serializeImages(images: XImage[], pageNumber: number | undefined): DocumentMetadata[] {\n const serialized: DocumentMetadata[] = [];\n for (const image of images) {\n if (pageNumber !== undefined && image.pageNumber !== pageNumber) {\n continue;\n }\n const raw = image.data;\n const bytes = raw == null ? null : Buffer.from(raw as Uint8Array | number[]);\n const entry: DocumentMetadata = {\n format: image.format,\n image_index: image.imageIndex,\n page_number: image.pageNumber,\n width: image.width,\n height: image.height,\n colorspace: image.colorspace,\n bits_per_component: image.bitsPerComponent,\n is_mask: image.isMask,\n description: image.description,\n data: bytes ? bytes.toString(\"base64\") : null,\n };\n if (image.boundingBox != null) {\n entry.bounding_box = {\n x0: image.boundingBox.x0,\n y0: image.boundingBox.y0,\n x1: image.boundingBox.x1,\n y1: image.boundingBox.y1,\n };\n }\n if (image.ocrResult != null) {\n entry.ocr_result = image.ocrResult.content;\n }\n serialized.push(entry);\n }\n return serialized;\n}\n\n/** Options for {@link buildMetadata}. */\nexport interface BuildMetadataOptions {\n document: XDocument;\n filePath?: string;\n source?: string;\n extraInfo?: Record<string, unknown>;\n pageNumber?: number;\n}\n\n/** Flatten an `ExtractedDocument` into a JSON-serialisable metadata dict. */\nexport function buildMetadata(options: BuildMetadataOptions): DocumentMetadata {\n const { document, filePath, source, extraInfo, pageNumber } = options;\n const meta: DocumentMetadata = {};\n\n if (filePath !== undefined) {\n meta.file_name = basename(filePath);\n meta.file_path = filePath;\n } else if (source !== undefined) {\n meta.file_name = source;\n meta.file_path = source;\n }\n\n meta.file_type = document.mimeType;\n meta.total_pages = document.counts?.pages;\n\n if (pageNumber !== undefined) {\n meta.page_number = pageNumber;\n }\n\n Object.assign(meta, serializeMetadata(document.metadata));\n meta.output_format = document.metadata?.outputFormat;\n\n if (document.qualityScore != null) {\n meta.quality_score = document.qualityScore;\n }\n if (document.detectedLanguages != null) {\n meta.detected_languages = document.detectedLanguages;\n }\n if (document.processingWarnings && document.processingWarnings.length > 0) {\n meta.processing_warnings = document.processingWarnings.map((warning) => ({\n source: warning.source,\n message: warning.message,\n }));\n }\n if (document.extractedKeywords && document.extractedKeywords.length > 0) {\n meta.extracted_keywords = document.extractedKeywords.map((keyword) => ({\n text: keyword.text,\n score: keyword.score,\n algorithm: String(keyword.algorithm),\n }));\n }\n if (document.annotations && document.annotations.length > 0) {\n meta.annotations = document.annotations.map((annotation) => ({\n annotation_type: String(annotation.annotationType),\n content: annotation.content,\n page_number: annotation.pageNumber,\n }));\n }\n if (document.elements != null) {\n meta._xberg_elements = serializeElements(document.elements);\n }\n if (document.chunks && document.chunks.length > 0) {\n meta._xberg_chunks = serializeChunks(document.chunks);\n }\n if (document.images && document.images.length > 0) {\n meta.images = serializeImages(document.images, pageNumber);\n }\n\n if (extraInfo) {\n Object.assign(meta, extraInfo);\n }\n\n return meta;\n}\n\n/** Options for {@link generateDocId}. */\nexport interface GenerateDocIdOptions {\n filePath?: string;\n data?: Uint8Array;\n pageNumber?: number;\n}\n\n/** Generate a deterministic document ID via SHA-256 of the resolved source. */\nexport function generateDocId(options: GenerateDocIdOptions): string {\n const { filePath, data, pageNumber } = options;\n if (filePath === undefined && data === undefined) {\n throw new Error(\"Either file_path or data must be provided\");\n }\n const hasher = createHash(\"sha256\");\n if (filePath !== undefined) {\n hasher.update(resolve(filePath));\n } else if (data !== undefined) {\n hasher.update(data);\n }\n if (pageNumber !== undefined) {\n hasher.update(String(pageNumber));\n }\n return hasher.digest(\"hex\");\n}\n\n/** Return metadata keys excluded from LLM and embedding input. */\nexport function excludedKeys(meta: DocumentMetadata): string[] {\n const keys: string[] = [];\n if (\"_xberg_elements\" in meta) {\n keys.push(\"_xberg_elements\");\n }\n if (\"_xberg_chunks\" in meta) {\n keys.push(\"_xberg_chunks\");\n }\n if (\"images\" in meta) {\n keys.push(\"images\");\n }\n return keys;\n}\n\n/** Append table markdown to content when a table is not already inlined. */\nexport function appendTables(content: string, tables: XTable[] | null | undefined): string {\n if (!tables || tables.length === 0) {\n return content;\n }\n let result = content;\n for (const table of tables) {\n const markdown = table.markdown;\n if (markdown && !result.includes(markdown.trim())) {\n result = `${result.replace(/\\s+$/, \"\")}\\n\\n${markdown}`;\n }\n }\n return result;\n}\n\n/**\n * Build Documents from extracted documents.\n *\n * When an element stream or native chunk list is present the source becomes a\n * single Document carrying `_xberg_elements` / `_xberg_chunks`. Otherwise, when\n * pages are present, one Document is emitted per page. Elements and chunks are\n * document-global, so per-page splitting is suppressed for them to avoid\n * replicating every element or chunk onto every page.\n */\nexport function resultsToDocuments(docSources: DocSource[], extraInfo?: Record<string, unknown>): Document[] {\n const documents: Document[] = [];\n for (const [document, source] of docSources) {\n const sourceLabel = source.data !== undefined ? \"bytes\" : undefined;\n const hasPages = Boolean(document.pages && document.pages.length > 0);\n const hasChunks = Boolean(document.chunks && document.chunks.length > 0);\n\n if (hasPages && document.elements == null && !hasChunks) {\n for (const page of document.pages ?? []) {\n const content = appendTables(page.content, page.tables);\n const meta = buildMetadata({\n document,\n filePath: source.path,\n source: sourceLabel,\n extraInfo,\n pageNumber: page.pageNumber,\n });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data, pageNumber: page.pageNumber }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n } else {\n const content = appendTables(document.content ?? \"\", document.tables);\n const meta = buildMetadata({ document, filePath: source.path, source: sourceLabel, extraInfo });\n const excluded = excludedKeys(meta);\n documents.push(\n new Document({\n text: content,\n id_: generateDocId({ filePath: source.path, data: source.data }),\n metadata: meta,\n excludedLlmMetadataKeys: excluded,\n excludedEmbedMetadataKeys: [...excluded],\n }),\n );\n }\n }\n return documents;\n}\n","import { randomUUID } from \"node:crypto\";\n\nimport { NodeParser } from \"@llamaindex/core/node-parser\";\nimport { NodeRelationship, TextNode } from \"@llamaindex/core/schema\";\nimport type { BaseNode } from \"@llamaindex/core/schema\";\n\nimport type { DocumentMetadata, SerializedChunk, SerializedElement } from \"./types.js\";\n\nconst ELEMENT_METADATA_KEYS = [\"element_type\", \"page_number\", \"element_index\"] as const;\nconst CHUNK_METADATA_KEYS = [\n \"chunk_type\",\n \"heading_path\",\n \"page_number\",\n \"first_page\",\n \"last_page\",\n \"chunk_index\",\n \"total_chunks\",\n \"token_count\",\n] as const;\nconst FORWARDED_KEYS = [\"_xberg_chunks\", \"_xberg_elements\"] as const;\n\nconst MISSING_ELEMENTS_WARNING =\n \"has no '_xberg_chunks' or '_xberg_elements' metadata. Passing through unchanged. \" +\n \"Use XbergReader with ExtractionConfig(chunking) for native chunk nodes, or \" +\n \"ExtractionConfig(resultFormat='element_based') for element nodes.\";\n\n/** Generates the id for a child node from its running index and source node. */\nexport type NodeIdFunction = (index: number, source: BaseNode) => string;\n\n/** Constructor options for {@link XbergNodeParser}. */\nexport interface XbergNodeParserConfig {\n idFunc?: NodeIdFunction;\n}\n\n/**\n * Structure-aware node parser for xberg-extracted documents.\n *\n * Turns xberg's output into individual `TextNode` objects, preferring xberg's\n * native chunks (`_xberg_chunks`) and falling back to structural elements\n * (`_xberg_elements`). Documents carrying neither pass through unchanged with a\n * warning. It never calls xberg — it consumes Documents produced by\n * {@link XbergReader}.\n */\nexport class XbergNodeParser extends NodeParser<TextNode[]> {\n private readonly idFunc: NodeIdFunction;\n\n constructor(config: XbergNodeParserConfig = {}) {\n super();\n this.idFunc = config.idFunc ?? (() => randomUUID());\n }\n\n protected parseNodes(documents: TextNode[]): TextNode[] {\n const output: TextNode[] = [];\n\n for (const node of documents) {\n const chunks = node.metadata[FORWARDED_KEYS[0]];\n if (Array.isArray(chunks) && chunks.length > 0) {\n output.push(...this.nodesFromChunks(node, chunks as SerializedChunk[]));\n continue;\n }\n\n const elements = node.metadata[FORWARDED_KEYS[1]];\n if (Array.isArray(elements) && elements.length > 0) {\n output.push(...this.nodesFromElements(node, elements as SerializedElement[]));\n continue;\n }\n\n console.warn(`Document ${node.id_} ${MISSING_ELEMENTS_WARNING}`);\n output.push(node);\n }\n\n return output;\n }\n\n private newTextNode(text: string, index: number, source: TextNode, metadata: DocumentMetadata): TextNode {\n return new TextNode({\n text,\n id_: this.idFunc(index, source),\n metadata,\n excludedLlmMetadataKeys: [...source.excludedLlmMetadataKeys],\n metadataSeparator: source.metadataSeparator,\n textTemplate: source.textTemplate,\n relationships: { [NodeRelationship.SOURCE]: source.asRelatedNodeInfo() },\n });\n }\n\n private nodesFromChunks(source: TextNode, chunks: SerializedChunk[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...CHUNK_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const chunk of chunks) {\n const text = chunk.content ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = chunk.metadata;\n const textNode = this.newTextNode(text, index, source, {\n chunk_type: chunk.chunk_type ?? \"unknown\",\n heading_path: meta?.heading_path ?? [],\n page_number: meta?.first_page,\n first_page: meta?.first_page,\n last_page: meta?.last_page,\n chunk_index: meta?.chunk_index,\n total_chunks: meta?.total_chunks,\n token_count: meta?.token_count,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n private nodesFromElements(source: TextNode, elements: SerializedElement[]): TextNode[] {\n const excludedEmbed = [...source.excludedEmbedMetadataKeys, ...ELEMENT_METADATA_KEYS];\n const result: TextNode[] = [];\n let index = 0;\n for (const element of elements) {\n const text = element.text ?? \"\";\n if (text.trim().length === 0) {\n continue;\n }\n const meta = element.metadata;\n const textNode = this.newTextNode(text, index, source, {\n element_type: element.element_type ?? \"unknown\",\n page_number: meta?.page_number,\n element_index: meta?.element_index,\n });\n textNode.excludedEmbedMetadataKeys = excludedEmbed;\n result.push(textNode);\n index += 1;\n }\n return result;\n }\n\n protected override postProcessParsedNodes(nodes: TextNode[], parentDocMap: Map<string, TextNode>): TextNode[] {\n const processed = super.postProcessParsedNodes(nodes, parentDocMap);\n return stripForwardedMetadata(processed);\n }\n}\n\n/**\n * Remove reader forwarding keys from child nodes only. The base parser copies\n * parent metadata (including the forwarding keys) onto children, so they are\n * stripped here; passthrough documents keep their metadata untouched.\n */\nfunction stripForwardedMetadata(nodes: TextNode[]): TextNode[] {\n for (const node of nodes) {\n if (node.sourceNode !== undefined) {\n for (const key of FORWARDED_KEYS) {\n delete node.metadata[key];\n }\n }\n }\n return nodes;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xberg-io/llamaindex-xberg",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "LlamaIndex.TS reader and node parser for Xberg — extract text, tables, metadata, and structure-aware nodes from 101 document formats with optional OCR.",
5
5
  "keywords": [
6
6
  "llamaindex",
@@ -53,7 +53,7 @@
53
53
  "test": "vitest run"
54
54
  },
55
55
  "dependencies": {
56
- "@xberg-io/xberg": "1.0.7"
56
+ "@xberg-io/xberg": "1.0.9"
57
57
  },
58
58
  "peerDependencies": {
59
59
  "@llamaindex/core": "^0.6.0"