openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
192 lines (191 loc) • 9.41 kB
JavaScript
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { o as normalizeLowercaseStringOrEmpty } from "./string-coerce-CIXf7egm.js";
import { d as normalizeStringEntries, v as sortUniqueStrings } from "./string-normalization-DsCfAx8q.js";
import { n as createConfigScopedPromiseLoader } from "./plugin-cache-primitives-8mVpZ8Xc.js";
import { s as createPluginIdScopeSet } from "./current-plugin-metadata-snapshot-CmSX4G3W.js";
import { t as loadBundledPluginPublicArtifactModuleFromCandidatesSync } from "./public-surface-loader-i-BsDNoA.js";
import { i as resolvePluginCapabilityProviders } from "./capability-provider-runtime-DOgjx571.js";
import { n as normalizeMediaProviderId } from "./provider-id-DSbuCFIb.js";
import { t as resolveImageCapableConfigProviderIds } from "./config-provider-models-C4gvrjuU.js";
import { r as describeImagesWithModel, t as describeImageWithModel } from "./image-runtime-BOIoCq-0.js";
import { n as sortPluginEntriesForAutoDetect } from "./plugin-entry-order-DxrT0ucv.js";
import { t as resolveEnabledBundledManifestContractPlugins } from "./bundled-manifest-contract-plugins-T88xDbpM.js";
//#region src/media-understanding/provider-registry.ts
function mergeProviderIntoRegistry(registry, provider, registryKey = provider.id) {
const normalizedKey = normalizeMediaProviderId(registryKey);
const existing = registry.get(normalizedKey);
const merged = existing ? {
...existing,
...provider,
capabilities: provider.capabilities ?? existing.capabilities,
defaultModels: provider.defaultModels ?? existing.defaultModels,
autoPriority: provider.autoPriority ?? existing.autoPriority,
nativeDocumentInputs: provider.nativeDocumentInputs ?? existing.nativeDocumentInputs,
documentModels: provider.documentModels ?? existing.documentModels
} : provider;
registry.set(normalizedKey, hydrateModelBackedMediaProvider(merged));
}
function hydrateModelBackedMediaProvider(provider) {
if (!provider.capabilities?.includes("image")) return provider;
if (provider.describeImage && provider.describeImages) return provider;
return {
...provider,
describeImage: provider.describeImage ?? describeImageWithModel,
describeImages: provider.describeImages ?? describeImagesWithModel
};
}
/** Builds the media-understanding provider registry from plugin capabilities and config providers. */
function buildMediaUnderstandingRegistry(overrides, cfg, preparedProviders) {
const registry = /* @__PURE__ */ new Map();
const providers = preparedProviders ?? resolvePluginCapabilityProviders({
key: "mediaUnderstandingProviders",
cfg
});
for (const provider of providers) mergeProviderIntoRegistry(registry, provider);
for (const normalizedKey of resolveImageCapableConfigProviderIds(cfg)) if (!registry.has(normalizedKey)) mergeProviderIntoRegistry(registry, {
id: normalizedKey,
capabilities: ["image"]
});
if (overrides) for (const [key, provider] of Object.entries(overrides)) mergeProviderIntoRegistry(registry, provider, key);
return registry;
}
/** Looks up a media-understanding provider using the same id normalization as registry builds. */
function getMediaUnderstandingProvider(id, registry) {
return registry.get(normalizeMediaProviderId(id));
}
//#endregion
//#region src/plugins/document-extractor-public-artifacts.ts
const DOCUMENT_EXTRACTOR_ARTIFACT_CANDIDATES = ["document-extractor.js", "document-extractor-api.js"];
function isDocumentExtractorPlugin(value) {
return isRecord(value) && typeof value.id === "string" && typeof value.label === "string" && Array.isArray(value.mimeTypes) && value.mimeTypes.every((mimeType) => typeof mimeType === "string" && mimeType.trim()) && (value.autoDetectOrder === void 0 || typeof value.autoDetectOrder === "number") && typeof value.extract === "function";
}
function collectExtractorFactories(mod) {
const extractors = [];
const errors = [];
for (const [name, exported] of Object.entries(mod).toSorted(([left], [right]) => left.localeCompare(right))) {
if (typeof exported !== "function" || exported.length !== 0 || !name.startsWith("create") || !name.endsWith("DocumentExtractor")) continue;
let candidate;
try {
candidate = exported();
} catch (error) {
errors.push(error);
continue;
}
if (isDocumentExtractorPlugin(candidate)) extractors.push(candidate);
}
return {
extractors,
errors
};
}
/** Loads document extractor entries from a bundled plugin public artifact module. */
function loadBundledDocumentExtractorEntriesFromDir(params) {
const mod = loadBundledPluginPublicArtifactModuleFromCandidatesSync({
dirName: params.dirName,
artifactCandidates: DOCUMENT_EXTRACTOR_ARTIFACT_CANDIDATES
});
if (!mod) return null;
const { extractors, errors } = collectExtractorFactories(mod);
if (extractors.length === 0) {
if (errors.length > 0) throw new Error(`Unable to initialize document extractors for plugin ${params.pluginId}`, { cause: errors.length === 1 ? errors[0] : new AggregateError(errors) });
return null;
}
return extractors.map((extractor) => Object.assign({}, extractor, { pluginId: params.pluginId }));
}
//#endregion
//#region src/plugins/document-extractors.runtime.ts
/** Resolves bundled document extractor providers from enabled manifest contracts. */
function resolveExplicitAllowedDocumentExtractorPluginIds(params) {
const allow = params.config?.plugins?.allow;
if (!Array.isArray(allow) || allow.length === 0) return null;
const onlyPluginIdSet = createPluginIdScopeSet(params.onlyPluginIds);
const deniedPluginIds = new Set(params.config?.plugins?.deny ?? []);
const entries = params.config?.plugins?.entries ?? {};
return sortUniqueStrings(normalizeStringEntries(allow).filter((pluginId) => !onlyPluginIdSet || onlyPluginIdSet.has(pluginId)).filter((pluginId) => !deniedPluginIds.has(pluginId)).filter((pluginId) => entries[pluginId]?.enabled !== false));
}
/** Returns enabled document extractors in deterministic auto-detect order. */
function resolvePluginDocumentExtractors(params) {
const extractors = [];
const loadErrors = [];
const pluginIds = resolveExplicitAllowedDocumentExtractorPluginIds({
config: params?.config,
onlyPluginIds: params?.onlyPluginIds
}) ?? resolveEnabledBundledManifestContractPlugins({
config: params?.config,
workspaceDir: params?.workspaceDir,
env: params?.env,
onlyPluginIds: params?.onlyPluginIds,
contract: "documentExtractors"
}).map((plugin) => plugin.id);
for (const pluginId of pluginIds) {
let loaded;
try {
loaded = loadBundledDocumentExtractorEntriesFromDir({
dirName: pluginId,
pluginId
});
} catch (error) {
loadErrors.push(error);
continue;
}
if (loaded) extractors.push(...loaded);
}
if (extractors.length === 0 && loadErrors.length > 0) throw new Error("Unable to load document extractor plugins", { cause: loadErrors.length === 1 ? loadErrors[0] : new AggregateError(loadErrors) });
return sortPluginEntriesForAutoDetect(extractors);
}
//#endregion
//#region src/media/document-extractors.runtime.ts
const documentExtractorLoader = createConfigScopedPromiseLoader((config) => resolvePluginDocumentExtractors(config ? { config } : void 0));
/** Runs the first matching plugin document extractor and tags successful results with its extractor id. */
async function extractDocumentContent(params) {
const mimeType = normalizeLowercaseStringOrEmpty(params.mimeType);
const extractors = await documentExtractorLoader.load(params.config);
const request = {
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.onImageExtractionError ? { onImageExtractionError: params.onImageExtractionError } : {}
};
const errors = [];
for (const extractor of extractors) {
if (!extractor.mimeTypes.map((entry) => normalizeLowercaseStringOrEmpty(entry)).includes(mimeType)) continue;
try {
const result = await extractor.extract(request);
if (result) return {
...result,
extractor: extractor.id
};
} catch (error) {
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;
}
//#endregion
//#region src/media/pdf-extract.ts
/** Extracts PDF content through the configured document extractor and hides extractor metadata. */
async function extractPdfContent(params) {
const extracted = await extractDocumentContent({
buffer: params.buffer,
mimeType: "application/pdf",
maxPages: params.maxPages,
maxPixels: params.maxPixels,
minTextChars: params.minTextChars,
...params.password ? { password: params.password } : {},
...params.pageNumbers ? { pageNumbers: params.pageNumbers } : {},
...params.config ? { config: params.config } : {},
...params.onImageExtractionError ? { onImageExtractionError: params.onImageExtractionError } : {}
});
if (!extracted) throw new Error("PDF extraction disabled or unavailable: enable the document-extract plugin to process application/pdf files.");
return {
text: extracted.text,
images: extracted.images
};
}
//#endregion
export { buildMediaUnderstandingRegistry as n, getMediaUnderstandingProvider as r, extractPdfContent as t };