@ever-works/plugin
v1.2.4
Published
Plugin system contracts, helpers, and utilities for Ever Works platform
Readme
@ever-works/plugin
Plugin system contracts, helpers, and utilities for the Ever Works platform.
Overview
This package provides everything needed to build plugins for the Ever Works ecosystem:
- Contracts: TypeScript interfaces defining plugin capabilities
- Abstract Classes: Base implementations for common plugin types
- Helpers: Utility functions for settings, validation, and context
- Testing Utilities: Mocks and test harnesses for plugin development
Installation
pnpm add @ever-works/pluginKey Features
- Standalone: No NestJS dependencies - plugins work in any TypeScript environment
- Type-Safe: Compile-time validation with TypeScript unions and mapped types
- Capability-Based: Plugins declare capabilities and implement corresponding interfaces
- Testable: Built-in mocks and test harnesses for comprehensive testing
Package Structure
@ever-works/plugin
├── /contracts # Plugin interfaces and capability definitions
├── /pipeline # Pipeline step types and execution context
├── /events # Event system types
├── /settings # Settings types and JSON Schema definitions
├── /common # Shared types (domain, item, form-field)
├── /helpers # Utility functions
├── /abstract # Abstract base classes
└── /testing # Test utilities and mocksUsage
Creating a Basic Plugin
import { BasePlugin, type PluginContext, type ValidationResult } from '@ever-works/plugin';
export class MyPlugin extends BasePlugin {
readonly id = 'my-plugin';
readonly name = 'My Plugin';
readonly version = '1.0.0';
readonly category = 'utility';
readonly capabilities = ['custom'] as const;
async onLoad(context: PluginContext): Promise<void> {
await super.onLoad(context);
this.log('Plugin loaded!');
}
}Creating a Git Provider Plugin
Git provider plugins implement IGitProviderPlugin which includes:
- Authentication methods:
getAuth(),getCloneUrl(),getWebUrl() - Repository API operations:
createRepository(),getRepository(),deleteRepository() - User/Org operations:
getUser(),getOrganizations() - Pull Request operations:
createPullRequest(),mergePullRequest() - Branch operations:
listBranches()
Local git operations (clone, push, commit) are provided by the platform's GitProvider base class in packages/agent.
import { BaseGitProvider, type IGitProviderPlugin, type GitAuth } from '@ever-works/plugin';
export class GitHubPlugin extends BaseGitProvider implements IGitProviderPlugin {
readonly id = 'github';
readonly name = 'GitHub';
readonly version = '1.0.0';
readonly providerName = 'github';
// Provider-specific authentication
getAuth(token: string): GitAuth {
return { username: 'x-access-token', password: token };
}
getCloneUrl(owner: string, repo: string): string {
return `https://github.com/${owner}/${repo}.git`;
}
getWebUrl(owner: string, repo: string): string {
return `https://github.com/${owner}/${repo}`;
}
// API Operations (provider-specific implementation)
async createRepository(options, token) {
// Use Octokit or fetch to call GitHub API
}
async getRepository(owner, repo, token) {
// Use Octokit or fetch to call GitHub API
}
async getUser(token) {
// Use Octokit or fetch to call GitHub API
}
async getOrganizations(token) {
// Use Octokit or fetch to call GitHub API
}
async listBranches(owner, repo, token) {
// Use Octokit or fetch to call GitHub API
}
async createPullRequest(options, token) {
// Use Octokit or fetch to call GitHub API
}
async mergePullRequest(owner, repo, prNumber, options, token) {
// Use Octokit or fetch to call GitHub API
}
async deleteRepository(owner, repo, token) {
// Use Octokit or fetch to call GitHub API
}
// Local git operations - inherited from platform's GitProvider
// clone, push, commit, pull, etc. are implemented once and shared
}Creating a Pipeline Modifier Plugin
Pipeline modifiers add, replace, or disable steps in an existing pipeline:
import { BasePipelineStep, type IPipelineModifierPlugin, type IPipelineContext } from '@ever-works/plugin';
export class MyModifierPlugin extends BasePipelineStep implements IPipelineModifierPlugin {
readonly id = 'my-modifier';
readonly name = 'My Modifier';
readonly version = '1.0.0';
readonly targetPipelines = ['standard-pipeline'];
getStepDefinition() {
return {
id: 'custom-step',
name: 'Custom Step',
position: { type: 'after', stepId: 'web-search' },
provides: ['customData']
};
}
async execute(context: IPipelineContext): Promise<IPipelineContext> {
// Your logic here
return context;
}
}Testing Plugins
import { createMockPluginContext, createTestHarness, testBasePluginContract } from '@ever-works/plugin/testing';
describe('MyPlugin', () => {
it('passes contract tests', async () => {
const plugin = new MyPlugin();
const results = await testBasePluginContract(plugin);
expect(results.every((r) => r.passed)).toBe(true);
});
it('loads correctly', async () => {
const plugin = new MyPlugin();
const harness = createTestHarness(plugin, {
settings: { apiKey: 'test-key' }
});
await harness.load();
expect(harness.isLoaded).toBe(true);
});
});Available Capabilities
| Capability | Interface | Description |
| ------------------- | ------------------------- | ------------------------------- |
| git-provider | IGitProviderPlugin | Git repository & API operations |
| oauth | IOAuthPlugin | OAuth-based authentication |
| deployment | IDeploymentPlugin | Deploy to hosting platforms |
| screenshot | IScreenshotPlugin | Capture web page screenshots |
| search | ISearchPlugin | Web search integration |
| content-extractor | IContentExtractorPlugin | Extract content from web pages |
| data-source | IDataSourcePlugin | External data sources |
| ai-provider | IAiProviderPlugin | AI/LLM providers |
| pipeline | IPipelinePlugin | Pipeline implementations |
| pipeline-modifier | IPipelineModifierPlugin | Pipeline step modifiers |
| form-field | IFormFieldPlugin | Custom form fields |
| sub-provider | ISubProviderPlugin | Sub-provider implementations |
| config-aware | IConfigAwarePlugin | React to config changes |
| custom-capability | ICustomCapabilityPlugin | Define custom capabilities |
Git Provider Architecture
The git provider system separates concerns:
IGitOperations- Local git operations (clone, push, commit, pull)- Implemented once in the platform using isomorphic-git
- Shared by all git providers (GitHub, GitLab, etc.)
IGitProviderPlugin- Provider-specific API operations- Each provider implements their own API calls
- Includes: createRepository, getPullRequest, getUser, etc.
IOAuthPlugin- OAuth authentication (separate capability)- For providers that support OAuth
- Can be combined with git-provider capability
┌─────────────────────────────────────────────────────────────────┐
│ GIT PROVIDER ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ IGitOperations (local git - shared implementation) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ cloneOrPull(), pull(), push(), commit(), add(), addAll()│ │
│ │ getCurrentBranch(), switchBranch(), getStatus() │ │
│ │ getLocalDir(), removeLocalDir() │ │
│ │ │ │
│ │ Implemented once in platform (packages/agent) │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ IGitProviderPlugin (provider API - each plugin implements) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ getAuth(), getCloneUrl(), getWebUrl() │ │
│ │ createRepository(), getRepository(), deleteRepository() │ │
│ │ getUser(), getOrganizations() │ │
│ │ createPullRequest(), mergePullRequest(), listBranches() │ │
│ │ │ │
│ │ GitHub uses Octokit, GitLab uses their API, etc. │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘Type Guards
import { isGitProviderPlugin, isAiProviderPlugin, hasCapability } from '@ever-works/plugin';
if (isGitProviderPlugin(plugin)) {
const repo = await plugin.getRepository('owner', 'repo', token);
}
if (hasCapability(plugin, 'ai-provider')) {
const models = await plugin.listModels();
}Exports
Main Export
import { IPlugin, BasePlugin, createMockPluginContext } from '@ever-works/plugin';Subpath Exports
// Contracts only
import { IPlugin, IGitProviderPlugin, IGitOperations } from '@ever-works/plugin/contracts';
// Pipeline types
import { IPipelineContext, PipelineStepDefinition } from '@ever-works/plugin/pipeline';
// Events
import { PluginEventName, PluginEventPayloads } from '@ever-works/plugin/events';
// Settings
import { JsonSchema, ValidationResult } from '@ever-works/plugin/settings';
// Common types
import { DomainType, ItemData, Category } from '@ever-works/plugin/common';
// Helpers
import { resolveSetting, validateString } from '@ever-works/plugin/helpers';
// Abstract classes
import { BasePlugin, BaseGitProvider } from '@ever-works/plugin/abstract';
// Testing
import { createMockPluginContext, createTestHarness } from '@ever-works/plugin/testing';License
AGPL-3.0
