This repository is a monorepo containing plugins for the ForgeSyte platform. Each plugin is a self-contained Python package designed to perform specific analysis tasks (e.g., OCR, motion detection, moderation) on data processed by ForgeSyte.
The ForgeSyte platform consists of several components working together:
- Gemini-CLI: MCP Client/Tool Caller that interacts with the core via MCP Protocol.
- ForgeSyte Core: FastAPI entry point, REST API, MCP adapter, and Plugin Loader.
- Document Store: Unified storage abstraction (MinIO, S3, Filesystem) used by both the Web UI and plugins.
- Plugins Ecosystem: This repository, containing independent pip packages discovered via entry points.
plugin_template/: Canonical reference implementation for new plugins.ocr/: Optical Character Recognition plugin.motion_detector/: Motion detection analysis.moderation/: Content moderation.block_mapper/: Visual block mapping.docs/: Shared documentation and standards.
All plugins must adhere to the structure defined in plugin_template.
plugin_name/
├── pyproject.toml # Build config & dependencies
├── README.md
├── forgesyte_plugin_name/ # Main package
│ ├── __init__.py
│ └── plugin.py # Plugin implementation
└── tests/
├── __init__.py
└── test_plugin.py # Unit tests
┌──────────────────────────────────────────┐
│ Web‑UI │
│ (React • Dynamic Plugin Host) │
└───────────────────────┬──────────────────┘
│
│ 1. Fetch plugin list
│ GET /v1/plugins
▼
┌────────────────────────────────────────────────────┐
│ UI Plugin Manager │
│────────────────────────────────────────────────────│
│ • Stores plugin metadata from server │
│ • Populates PluginSelector │
│ • Drives dynamic rendering in ResultsPanel │
└───────────────────────┬────────────────────────────┘
│
│ 2. User selects plugin
▼
┌────────────────────────────────────────────────────┐
│ PluginSelector.tsx │
│────────────────────────────────────────────────────│
│ • Renders list from metadata │
│ • No hard‑coded plugin names │
│ • Sends AnalyzeRequest to server │
└───────────────────────┬────────────────────────────┘
│
│ 3. POST /v1/analyze
│ AnalyzeRequest:
│ • plugin
│ • options
│ • image_url / bytes
▼
┌────────────────────────────────────────────────────┐
│ ForgeSyte API │
│────────────────────────────────────────────────────│
│ • Validates request │
│ • Fetches image bytes │
│ • Forwards to PluginManager │
└───────────────────────┬────────────────────────────┘
│
│ 4. plugin_manager.get(plugin)
▼
┌────────────────────────────────────────────────────┐
│ PluginManager │
│────────────────────────────────────────────────────│
│ • Discovers plugins (entry‑point + local) │
│ • Loads plugin metadata │
│ • Calls plugin.analyze() │
└───────────────────────┬────────────────────────────┘
│
│ 5. plugin.analyze(image, options)
▼
┌────────────────────────────────────────────────────┐
│ Plugin │
│────────────────────────────────────────────────────│
│ • Plugin‑specific logic │
│ • Internal models allowed │
│ • MUST return AnalysisResult │
│ text, blocks, confidence, language, error │
└───────────────────────┬────────────────────────────┘
│
│ 6. Return AnalysisResult
▼
┌────────────────────────────────────────────────────┐
│ ForgeSyte API │
│────────────────────────────────────────────────────│
│ • Serializes AnalysisResult → JSON │
│ • Sends to Web‑UI │
└───────────────────────┬────────────────────────────┘
│
│ 7. UI receives AnalysisResult
▼
┌────────────────────────────────────────────────────┐
│ ResultsPanel.tsx │
│────────────────────────────────────────────────────│
│ • Renders text, blocks, confidence │
│ • No plugin‑specific UI logic │
│ • Driven entirely by AnalysisResult │
└────────────────────────────────────────────────────┘pyproject.toml: Defines the project metadata and entry point.- Entry Point: Must define a
forgesyte.pluginsentry point.[project.entry-points."forgesyte.plugins"] plugin_name = "forgesyte_plugin_name.plugin:Plugin"
- Entry Point: Must define a
plugin.py: Contains thePluginclass.metadata(): ReturnsPluginMetadata(inputs, outputs, config schema).analyze(image_bytes, options): Core logic. Returns a dictionary based onAnalysisResult.- Lifecycle Hooks:
on_load()andon_unload().
Plugins interact with the main application via models (expected at runtime):
PluginMetadata: Capabilities description.AnalysisResult: Structured analysis results.
Adhere strictly to docs/development/PYTHON_STANDARDS.md.
- Formatting:
black . && isort . - Linting:
ruff check --fix . - Type Checking:
mypy . --no-site-packages - Testing:
pytest
- Type Hints: Mandatory for all functions.
- Path Handling: Use
pathlib.Path. - Logging: Use
logging.getLogger(__name__). - Error Handling: Return errors within the
AnalysisResultdictionary.
- Copy
plugin_template/tonew_plugin/. - Rename
forgesyte_plugin_template/package and updatepyproject.tomlentry points. - Implement
Plugin.name,metadata(), andanalyze()inplugin.py. - Update tests in
tests/test_plugin.py.
Each plugin is a standalone Python package managed by uv. To develop or test, navigate to its directory:
cd ocr # Example
uv sync --all-extras
uv run pytestUI tests use Vitest and are run from the repository root:
# In the root directory
npm install
npm test # Run all UI tests
npm test -- <path-to-test-file> # Run a specific test file
# Example: npm test -- ocr/ui/ResultRenderer.test.tsx