Skip to content

feat: Python drop-in plugin system (#66) #188

@deucebucket

Description

@deucebucket

Parent: #66 Phase 5 - Custom Layers & Plugin System

What

Let users drop .py files into /data/plugins/ that subclass ProcessingLayer. Auto-discovered on restart.

Plugin Structure

/data/plugins/
  hardcover_lookup/
    manifest.json    # metadata, config schema, permissions
    layer.py         # class extending ProcessingLayer

manifest.json

{
  "id": "hardcover-lookup",
  "name": "Hardcover.app Lookup",
  "version": "1.0.0",
  "type": "layer",
  "entry_point": "layer.py",
  "permissions": {
    "network": ["api.hardcover.app"],
    "database": "read",
    "filesystem": "none"
  },
  "config_schema": {
    "properties": {
      "api_key": { "type": "string", "x-input-type": "password" },
      "timeout": { "type": "integer", "default": 30 }
    }
  }
}

Implementation

  • library_manager/plugin_loader.py - directory scanner + module importer
  • Plugin discovery using importlib.util.spec_from_file_location
  • Manifest validation
  • Auto-generate config forms from config_schema (JSON Schema → HTML)
  • Plugin configs in config.json under plugin_configs, secrets in secrets.json
  • Exception isolation (try/except around all plugin calls)
  • Timeout enforcement (ThreadPoolExecutor with configurable timeout)
  • Deep copy book data before passing to plugins
  • Register discovered plugins into LayerRegistry dynamically

Safety

  • Verified vs unverified distinction
  • Auto-disable after 5 consecutive failures
  • Timeout cap (30s default)
  • Data isolation via deep copy

Depends on

  • Template HTTP layers (for the CustomApiLayer pattern to follow)

Part of

#66 Phase 5, Tier 3

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions