Skip to main content

Plugin Helpers & Utilities

The Plugin Helpers module (@ever-works/plugin/helpers) provides essential utility functions used across all plugin implementations. It includes context assertion helpers for safely accessing plugin runtime services, a settings resolver that merges configuration from multiple priority layers, and date formatting utilities for LLM prompt construction.

Package Overview

PropertyValue
Import path@ever-works/plugin/helpers
Locationplatform/packages/plugin/src/helpers/
DependenciesNone (uses only Node.js built-ins and plugin contracts)
Used byAll plugin implementations

Module Exports

export { resolveSettings, type ResolvedSettings } from './settings-resolver.js';
export {
assertPluginContext,
getLogger,
getCache,
getHttpClient,
getEnvVars,
createScopedLogger,
createScopedCache,
isProduction,
isDevelopment
} from './context-helpers.js';
export { getCurrentDateString } from './date-helpers.js';

Context Helpers

The context-helpers.ts module provides safe accessor functions for plugin runtime services. Plugins receive a PluginContext object during initialization, and these helpers ensure that required services are available before use.

assertPluginContext

Validates that the plugin context is properly initialized. Throws descriptive errors if the context or any expected service is missing.

import { assertPluginContext } from '@ever-works/plugin/helpers';

function onActivate(context: PluginContext) {
assertPluginContext(context);
// Safe to use context.logger, context.cache, etc.
}

Safe Service Getters

Each getter retrieves a service from the context with a descriptive error if the service is unavailable.

FunctionReturnsDescription
getLogger(context)PluginLoggerLogger instance from context
getCache(context)PluginCacheCache service from context
getHttpClient(context)PluginHttpClientHTTP client from context
getEnvVars(context)Record<string, string>Environment variables map
import { getLogger, getCache } from '@ever-works/plugin/helpers';

const logger = getLogger(context);
logger.info('Plugin activated');

const cache = getCache(context);
await cache.get('my-key');

Scoped Logger and Cache

Create child instances scoped to a specific operation or module name. Scoped loggers prefix all messages, and scoped caches prefix all keys to avoid collisions between plugins.

import { createScopedLogger, createScopedCache } from '@ever-works/plugin/helpers';

const logger = createScopedLogger(context, 'git-sync');
logger.info('Starting sync'); // => "[git-sync] Starting sync"

const cache = createScopedCache(context, 'github');
await cache.set('repos', data); // key stored as "github:repos"
await cache.get('repos'); // retrieves "github:repos"

Environment Checks

Simple boolean checks for the current runtime environment.

import { isProduction, isDevelopment } from '@ever-works/plugin/helpers';

if (isProduction(context)) {
// Production-only logic
}

if (isDevelopment(context)) {
// Development-only debug logging
}

Settings Resolver

The settings-resolver.ts module implements a layered settings resolution strategy. Plugin settings can be defined at multiple levels, and the resolver merges them in a deterministic priority order.

Resolution Priority

Settings are resolved from highest to lowest priority. The first non-null, non-undefined value wins:

PrioritySourceDescription
1 (highest)User settingsPer-user configuration
2Work settingsPer-work overrides
3Admin settingsOrganization-wide defaults
4Environment variablesx-envVar mapped values
5 (lowest)Schema defaultsDefault values from JSON Schema

resolveSettings

import { resolveSettings } from '@ever-works/plugin/helpers';

const resolved = resolveSettings({
schema: pluginSettingsSchema,
userSettings: { model: 'gpt-4', temperature: 0.7 },
workSettings: { model: 'gpt-3.5-turbo' },
adminSettings: {},
envVars: { OPENAI_API_KEY: 'sk-...' }
});

// resolved.model => 'gpt-4' (user takes priority over work)
// resolved.apiKey => 'sk-...' (from env var via x-envVar mapping)
// resolved.temperature => 0.7 (from user settings)

Environment Variable Mapping

The resolver reads x-envVar annotations from the plugin's JSON Schema to map environment variables to settings fields.

// In plugin settings schema:
{
"properties": {
"apiKey": {
"type": "string",
"x-envVar": "OPENAI_API_KEY",
"x-secret": true
}
}
}

// If no user/work/admin setting provides apiKey,
// the resolver checks process.env.OPENAI_API_KEY

Environment Variable Parsing

The resolver automatically parses environment variable string values into their appropriate types based on the schema:

Schema TypeParsing Behavior
numberparseFloat(value), skipped if NaN
boolean'true' / '1' become true, 'false' / '0' become false
stringUsed as-is

Deep Equality Check

The resolver uses a deep equality comparison when determining whether a setting has changed, ensuring that object and array values are compared structurally rather than by reference. This prevents unnecessary updates when settings objects are reconstructed but contain identical values.

Date Helpers

The date-helpers.ts module provides date formatting utilities optimized for inclusion in LLM prompts.

getCurrentDateString

Returns the current date as a human-readable string using Intl.DateTimeFormat. This is used in AI prompts to give the model awareness of the current date without requiring system-level access.

import { getCurrentDateString } from '@ever-works/plugin/helpers';

const dateStr = getCurrentDateString();
// => "Tuesday, March 4, 2025"

// Used in AI prompts:
const systemPrompt = `You are a helpful assistant. Today's date is ${getCurrentDateString()}.`;

The format uses the en-US locale with { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' } options, producing a consistent, unambiguous date representation that LLMs can easily parse.

Usage Patterns

Typical Plugin Initialization

import {
assertPluginContext,
getLogger,
getCache,
resolveSettings,
createScopedLogger
} from '@ever-works/plugin/helpers';

class MyPlugin implements IPlugin {
private logger!: PluginLogger;
private cache!: PluginCache;

async onActivate(context: PluginContext): Promise<void> {
assertPluginContext(context);
this.logger = createScopedLogger(context, 'my-plugin');
this.cache = getCache(context);

const settings = resolveSettings({
schema: this.settingsSchema,
userSettings: context.settings,
workSettings: context.workSettings,
adminSettings: context.adminSettings,
envVars: context.envVars
});

this.logger.info('Plugin activated with resolved settings');
}
}

Settings Resolution in Capabilities

async generateContent(prompt: string, context: PluginContext): Promise<string> {
const settings = resolveSettings({
schema: this.settingsSchema,
userSettings: context.settings,
workSettings: context.workSettings,
adminSettings: {},
envVars: context.envVars,
});

return this.aiOps.createChatCompletion({
messages: [{ role: 'user', content: prompt }],
temperature: settings.temperature,
model: settings.model,
});
}

File Structure

plugin/src/helpers/
index.ts # Public exports
context-helpers.ts # Context assertion and service accessors
settings-resolver.ts # Layered settings resolution
date-helpers.ts # Date formatting for LLM prompts