Skip to main content

Storage & Content Module

Overview​

The Storage & Content module in @ever-works/agent provides unified facades for external content acquisition -- search, screenshots, content extraction, and data sources. These facades abstract over plugin-based providers to deliver consistent interfaces for gathering, capturing, and transforming content from the web.

Each facade follows the same BaseFacadeService pattern: dynamic provider resolution from the plugin registry, 4-level settings hierarchy, and capability-based plugin matching. Together they form the content acquisition layer that feeds into the generation pipeline.

Module Structure​

packages/agent/src/
facades/
search.facade.ts # Web search facade
screenshot.facade.ts # Screenshot/image capture facade
content-extractor.facade.ts # Web page content extraction facade
data-source.facade.ts # External data source aggregation facade
base.facade.ts # Abstract base class
facades.module.ts # Module registration
facades/__tests__/
search.facade.spec.ts
screenshot.facade.spec.ts
content-extractor.facade.spec.ts
data-source.facade.spec.ts

Plugin implementations (in packages/plugins/):

packages/plugins/
exa/ # Exa search provider
tavily/ # Tavily search provider
serpapi/ # SerpAPI search provider
brave/ # Brave Search provider
screenshotone/ # ScreenshotOne capture provider
urlbox/ # Urlbox capture provider
local-content-extractor/ # Local content extraction
notion-extractor/ # Notion page extraction

Key Classes and Services​

SearchFacadeService​

Extends BaseFacadeService and implements ISearchFacade. Provides web search capabilities through search provider plugins.

Capability: PLUGIN_CAPABILITIES.SEARCH

Operations:

  • search(query, options, facadeOptions) -- execute a web search query and return structured results
  • isConfigured() -- check if any search provider is available
  • getAvailableProviders() -- list registered search providers

Search results include title, URL, snippet, and optionally full page content depending on the provider.

ScreenshotFacadeService​

Extends BaseFacadeService and implements IScreenshotFacade. Captures website screenshots through screenshot provider plugins.

Capability: PLUGIN_CAPABILITIES.SCREENSHOT

Operations:

  • capture(url, options, facadeOptions) -- capture a screenshot of a URL. Returns image data (buffer or URL) with metadata.
  • isConfigured() -- check if any screenshot provider is available
  • getAvailableProviders() -- list registered screenshot providers

Screenshot options include viewport dimensions, format (PNG/JPEG), full-page capture, delay before capture, and device emulation.

ContentExtractorFacadeService​

Extends BaseFacadeService and implements IContentExtractorFacade. Extracts structured content from web pages and documents.

Capability: PLUGIN_CAPABILITIES.CONTENT_EXTRACTION

Operations:

  • extract(url, options, facadeOptions) -- extract text content, metadata, and structured data from a URL
  • isConfigured() -- check if any content extraction provider is available
  • getAvailableProviders() -- list registered extraction providers

Extraction results typically include: title, description, main text content, author, publish date, images, and structured data (OpenGraph, JSON-LD).

DataSourceFacadeService​

Implements IDataSourceFacade. Aggregates items from external data source plugins. Unlike other facades that delegate to a single provider, the data source facade queries all enabled data source plugins and merges their results.

Capability: PLUGIN_CAPABILITIES.DATA_SOURCE

Core operations:

  • queryAll(options) -- query all enabled data source plugins and aggregate results. Returns a unified DataSourceFacadeResult with items, categories, tags, brands, source mapping, and any errors from individual sources.
  • getEnabledSources(workId, userId) -- list data sources enabled for a specific work
  • isConfigured() -- check if any data source plugin is available
  • getAvailableProviders() -- list all registered data source providers

Per-plugin enablement:

Data source plugins can be enabled at the work level. The facade checks both:

  1. Request-level plugin config overrides (pluginConfig[pluginId].enabled === true)
  2. Registry scope resolution (isPluginEnabledForScope)
interface DataSourceFacadeResult {
items: MutableItemData[];
sourceMap: Map<string, string>; // item slug -> plugin ID
errors: Array<{ sourceId: string; error: string }>;
categories?: Category[];
tags?: Tag[];
brands?: Brand[];
}

BaseFacadeService (Shared Base)​

All content facades inherit from BaseFacadeService which provides:

  • Provider resolution: resolvePlugin(providerOverride?, userId?, workId?) -- resolves the appropriate plugin via: explicit override > work active plugin > defaultForCapabilities > first enabled plugin
  • Settings resolution: getResolvedSettings(pluginId, options) -- merges from Work > User > Admin > Plugin defaults
  • Enable checking: isPluginEnabled(pluginId, workId, userId) -- scope-aware enablement
  • Typed settings helpers: getSettingTyped(), getSettingRequired(), getSettingWithDefault()

API Reference​

SearchFacadeService​

search(
query: string,
options?: {
maxResults?: number;
includeContent?: boolean;
},
facadeOptions?: FacadeOptions
): Promise<SearchResult[]>

isConfigured(): boolean
getAvailableProviders(): Array<{ id: string; name: string; enabled: boolean }>

ScreenshotFacadeService​

capture(
url: string,
options?: {
width?: number;
height?: number;
format?: 'png' | 'jpeg';
fullPage?: boolean;
delay?: number;
},
facadeOptions?: FacadeOptions
): Promise<ScreenshotResult>

isConfigured(): boolean
getAvailableProviders(): Array<{ id: string; name: string; enabled: boolean }>

ContentExtractorFacadeService​

extract(
url: string,
options?: ExtractOptions,
facadeOptions?: FacadeOptions
): Promise<ExtractedContent>

isConfigured(): boolean
getAvailableProviders(): Array<{ id: string; name: string; enabled: boolean }>

DataSourceFacadeService​

queryAll(options: DataSourceFacadeOptions): Promise<DataSourceFacadeResult>
getEnabledSources(workId: string, userId: string): Promise<EnabledDataSource[]>
isConfigured(): boolean
getAvailableProviders(): Array<{ id: string; name: string; sourceName: string; enabled: boolean }>
getDefaultProvider(capability: string, workId?: string, userId?: string): Promise<{ id: string; name: string } | null>

Configuration​

Plugin Settings Pattern​

All content provider plugins define their settings via JSON Schema with custom extensions:

{
"everworks.plugin": {
"settings": {
"apiKey": {
"type": "string",
"x-secret": true,
"x-envVar": "EXA_API_KEY",
"description": "API key for the service"
},
"maxResults": {
"type": "number",
"default": 10,
"x-widget": "slider"
}
}
}
}

Custom JSON Schema extensions:

ExtensionPurpose
x-secretMarks the field as sensitive (encrypted storage, masked in UI)
x-envVarEnvironment variable name for fallback value
x-widgetUI widget hint (slider, toggle, textarea, select)

Available Providers by Capability​

CapabilityPlugins
searchexa, tavily, serpapi, brave
screenshotscreenshotone, urlbox
content-extractionlocal-content-extractor, notion-extractor
data-sourceAny plugin implementing IDataSourcePlugin

Dependencies​

DependencyPurpose
@ever-works/pluginFacade interfaces, capability constants, plugin types
@ever-works/agent/pluginsPluginRegistryService, PluginSettingsService, WorkPluginRepository
@ever-works/agent/databaseWorkPluginRepository for work-level plugin config

Usage Examples​

import { SearchFacadeService } from '@ever-works/agent/facades';

const results = await searchFacade.search(
'best open source code editors 2025',
{ maxResults: 10, includeContent: true },
{ userId: user.id, workId: work.id }
);

results.forEach((r) => {
console.log(`${r.title}: ${r.url}`);
});

Screenshot Capture​

import { ScreenshotFacadeService } from '@ever-works/agent/facades';

const screenshot = await screenshotFacade.capture(
'https://example.com',
{ width: 1280, height: 720, format: 'png' },
{ userId: user.id }
);

Content Extraction​

import { ContentExtractorFacadeService } from '@ever-works/agent/facades';

const content = await contentExtractorFacade.extract('https://example.com/product', {}, { userId: user.id });

console.log(content.title);
console.log(content.mainText);

Data Source Aggregation​

import { DataSourceFacadeService } from '@ever-works/agent/facades';

const result = await dataSourceFacade.queryAll({
workId: work.id,
userId: user.id,
limit: 100,
pluginConfig: {
'my-data-source': { enabled: true }
}
});

console.log(`Collected ${result.items.length} items from data sources`);
result.errors.forEach((e) => {
console.warn(`Source ${e.sourceId} failed: ${e.error}`);
});