// Document extractor runtime helpers choose lazy extraction adapters by media type. import { normalizeLowercaseStringOrEmpty } from "@openclaw/normalization-core/string-coerce"; import type { OpenClawConfig } from "../config/types.openclaw.js"; import type { DocumentExtractionRequest, DocumentExtractionResult, } from "../plugins/document-extractor-types.js"; import { resolvePluginDocumentExtractors } from "../plugins/document-extractors.runtime.js"; import { createConfigScopedPromiseLoader } from "../plugins/plugin-cache-primitives.js"; const documentExtractorLoader = createConfigScopedPromiseLoader((config?: OpenClawConfig) => resolvePluginDocumentExtractors(config ? { config } : undefined), ); /** Runs the first matching plugin document extractor and tags successful results with its extractor id. */ export async function extractDocumentContent( params: DocumentExtractionRequest & { config?: OpenClawConfig; }, ): Promise<(DocumentExtractionResult & { extractor: string }) | null> { const mimeType = normalizeLowercaseStringOrEmpty(params.mimeType); params.signal?.throwIfAborted(); const extractors = await documentExtractorLoader.load(params.config); params.signal?.throwIfAborted(); // Keep config and loader-only fields out of plugin calls; extractors receive the SDK request shape. const request: DocumentExtractionRequest = { buffer: params.buffer, mimeType: params.mimeType, maxPages: params.maxPages, maxPixels: params.maxPixels, minTextChars: params.minTextChars, ...(params.password ? { password: params.password } : {}), ...(params.pageNumbers ? { pageNumbers: params.pageNumbers } : {}), ...(params.signal ? { signal: params.signal } : {}), ...(params.onImageExtractionError ? { onImageExtractionError: params.onImageExtractionError } : {}), }; const errors: unknown[] = []; for (const extractor of extractors) { if ( !extractor.mimeTypes.map((entry) => normalizeLowercaseStringOrEmpty(entry)).includes(mimeType) ) { continue; } try { const result = await extractor.extract(request); params.signal?.throwIfAborted(); if (result) { return { ...result, extractor: extractor.id, }; } } catch (error) { params.signal?.throwIfAborted(); errors.push(error); } } if (errors.length > 0) { throw new Error(`Document extraction failed for ${mimeType || "unknown MIME type"}`, { cause: errors.length === 1 ? errors[0] : new AggregateError(errors), }); } return null; }