Skip to content

Source plugins

Persistence & config validation share plugin-kit (namespace=source, legacy source_plugin_* keys).

Writing a plugin? See Source plugin development.

Goal

Peel “content acquisition” out of the pipeline so the core only consumes a unified SourceArtifact.

High-risk fetch (Firecrawl / yt-dlp, etc.) stays optional external plugins, off by default.

Architecture

text
apps/server/src/sources/
  types.ts        # SourceArtifact / SourcePlugin / Manifest
  registry.ts     # register, enable, match
  state.ts        # enable state (app_settings)
  loader.ts       # scan storage/plugins/source
  host.ts         # importSource / refreshExternal
  plugins/
    directHttp.ts # built-in low-risk plugin

storage/plugins/source/<dir>/
  plugin.json
  index.js

Built-in vs external

TypeLocationDefault
builtin direct-httpin codeenabled
externalstorage/plugins/source/*follows manifest; high risk forced off

plugin.json (essentials)

Typical fields: id, name, version, entry, apiVersion, description, riskLevel, capabilities, defaultEnabled, permissions, configSchema.

See the development guide for the full contract.

API

MethodPathNotes
GET/api/source-pluginsList
POST/api/source-plugins/rescanHot scan
PATCH/api/source-plugins/:id{ "enabled": true/false }
POST/api/source-plugins/:id/resetClear enable override
PUT/api/source-plugins/:id/configSave { "config": { ... } }
POST/api/source-plugins/:id/config/resetClear config

Matching

At create time you can pin a Source plugin id or let the host auto-match by URL / capabilities.