import type { Mailbox } from '../coordination/mailbox-types.js'; import { ExtensionRegistry } from '../extension/registry.js'; import type { HookRegistry } from '../hooks/registry.js'; import type { Container } from '../kernel/container.js'; import type { EventBus, EventName, Listener } from '../kernel/events.js'; import type { ProviderRegistry } from '../registry/provider-registry.js'; import type { SlashCommandRegistry } from '../registry/slash-command-registry.js'; import type { ToolRegistry } from '../registry/tool-registry.js'; import type { Config } from '../types/config.js'; import type { HookEvent, HookMatcher, InProcessHook } from '../types/hooks.js'; import type { Logger } from '../types/logger.js'; import type { ModelsRegistry } from '../types/models-registry.js'; import type { MCPRegistryView, MetricsSinkView, Notifier, PluginAPI, PluginCapabilities, PluginDependency, PluginLLM, PluginPipelines, ProviderRegistryView, SessionWriterView, SlashCommandRegistryView, ToolRegistryView } from '../types/plugin.js'; import type { Provider } from '../types/provider.js'; import type { SystemPromptContributor } from '../types/system-prompt-contributor.js'; import type { JSONSchema } from '../types/tool.js'; export interface PluginAPIInit { ownerName: string; container: Container; events: EventBus; /** * The agent's concrete pipelines. `DefaultPluginAPI` converts each to a * `ReadonlyPipeline` before exposing them to the plugin — plugins can * inspect and invoke pipelines but cannot mutate them. */ pipelines: PluginPipelines; toolRegistry: ToolRegistry; providerRegistry: ProviderRegistry; slashCommandRegistry?: SlashCommandRegistry | undefined; mcpRegistry?: MCPRegistryView | undefined; /** * The agent's extension registry. Plugins register AgentExtension * instances here to hook into agent lifecycle events. */ extensions?: ExtensionRegistry | undefined; /** * The host's lifecycle hook registry. When provided, `api.registerHook` * adds in-process hooks here. When absent, `registerHook` is a noop. */ hookRegistry?: HookRegistry | undefined; /** * The active session writer. Plugins append custom events here. * When not provided, a noop writer is used. */ sessionWriter?: SessionWriterView | undefined; /** * The host's metrics sink. When set, the plugin gets a scoped view * that auto-prefixes metric names with `plugin..`. * When not provided, a noop sink is used. */ metricsSink?: MetricsSinkView | undefined; /** * The host's models registry (models.dev-backed catalog of providers, * models, and per-token pricing). When provided, plugins that need * model metadata (cost-tracker, billing reports) can query it instead * of relying on bundled tables. Optional — minimal hosts/tests may * omit it. */ modelsRegistry?: ModelsRegistry | undefined; /** * The host's project-level mailbox. When provided, plugins that publish * to other agents (todo-listener, session-recap) can call `api.mailbox.send`. * When not provided, those plugins should gracefully no-op. */ mailbox?: Mailbox | undefined; /** * Notification router for one-way channel delivery. Plugins that * implement `NotificationChannel` register their channel here during * `setup()`. Optional — minimal hosts/tests may omit it. */ notifier?: Notifier | undefined; /** * LLM wiring for `api.llm`. When provided, `DefaultPluginAPI` exposes a * `PluginLLM` that routes completions through the host's provider layer: * * - `provider` — the host session's live default Provider instance * - `model` — the host session's default model id * - `createProvider` — optional factory used when a plugin requests a * DIFFERENT provider by name (per-call `opts.provider` or the plugin's * `config.extensions[].llm.provider`). The CLI host passes an * implementation backed by the provider registry + saved provider * configs; when absent, `DefaultPluginAPI` falls back to * `providerRegistry.create({ ...config.providers[name], type: name })`. * * Omit entirely on minimal hosts — `api.llm` stays undefined and plugins * must guard. */ llm?: { provider: Provider; model: string; getProvider?: (() => Provider) | undefined; getModel?: (() => string) | undefined; createProvider?: ((name: string, model?: string) => Provider) | undefined; } | undefined; config: Config; /** * The host's ConfigStore. Used to wire `api.onConfigChange()`. * When not provided, `onConfigChange` is a noop. */ configStore?: { watch(cb: (next: unknown, prev: unknown) => void): () => void; }; log: Logger; /** * Whether this plugin is first-party ("official"). Set by the host based on * the plugin's load source (e.g. shipped in the built-in factory list), NOT * self-declared by the plugin. Official plugins may register bare slash * command names and override built-ins; external plugins are namespaced. * Defaults to false. */ official?: boolean | undefined; /** * Declared capabilities of the plugin. Used for capability-based * authorization checks (e.g. tool mutation permissions). */ capabilities?: PluginCapabilities | undefined; } export declare class DefaultPluginAPI implements PluginAPI { readonly container: Container; readonly events: EventBus; readonly pipelines: PluginPipelines; readonly tools: ToolRegistryView; readonly providers: ProviderRegistryView; readonly mcp: MCPRegistryView; readonly slashCommands: SlashCommandRegistryView; readonly extensions: ExtensionRegistry; readonly session: SessionWriterView; readonly metrics: MetricsSinkView; readonly config: Config; readonly log: Logger; readonly modelsRegistry: ModelsRegistry | undefined; readonly mailbox: Mailbox | undefined; readonly notifier: Notifier | undefined; readonly llm: PluginLLM | undefined; private readonly configStore; private readonly hookRegistry; private readonly ownerName; private readonly pluginCleanupFns; constructor(init: PluginAPIInit); onEvent(event: K, handler: Listener): () => void; onPattern(pattern: string, handler: (event: string, payload: unknown) => void): () => void; emitCustom(event: string, payload: unknown): void; onConfigChange(handler: (next: Readonly, prev: Readonly) => void): () => void; /** Called by the plugin loader when uninstalling the plugin. */ drainCleanup(): void; registerSystemPromptContributor(c: SystemPromptContributor): () => void; registerHook(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook, options?: import('../types/hooks.js').HookRegistrationOptions | undefined): () => void; } /** * Define a plugin with automatic `apiVersion` injection and optional * TypeScript type inference for the plugin options schema. * * The `options` generic is inferred from the `factory` function's second * parameter, so annotating it gives you fully-typed options throughout: * * @example * ```ts * import { definePlugin } from '@wrongstack/core'; * * interface MyOptions { * threshold: number; * enabled: boolean; * } * * const myPlugin = definePlugin( * { * name: 'my-plugin', * version: '0.1.0', * description: 'My example plugin', * capabilities: { tools: true }, * configSchema: { * type: 'object', * properties: { * threshold: { type: 'number', default: 100 }, * enabled: { type: 'boolean', default: true }, * }, * }, * defaultConfig: { threshold: 100, enabled: true }, * }, * (api, options) => { * // options.threshold is `number` here, not `unknown` * api.tools.register({ * name: 'my-tool', * description: `Threshold is ${options.threshold}`, * // ... * }); * }, * ); * * export default myPlugin; * ``` * * Plugins that don't need typed options can omit the interface and let * TypeScript infer from `defaultConfig`, or omit `defaultConfig` entirely * (options will be `undefined` at runtime, accessible via `api.config`): * * @example * ```ts * const simplePlugin = definePlugin( * { name: 'simple' }, * (api) => { * api.tools.register({ name: 'ping', description: 'Ping the service' }); * }, * ); * ``` * * The `apiVersion` is automatically set to the current `KERNEL_API_VERSION` * so plugins are always compatible with the kernel that loaded them. * Plugins that need to pin to a specific kernel version can override it * in the returned object before exporting. */ export declare function definePlugin | undefined>(metadata: { name: string; version?: string | undefined; description?: string | undefined; capabilities?: PluginCapabilities | undefined; configSchema?: JSONSchema | undefined; defaultConfig?: TOptions | undefined; dependsOn?: (string | PluginDependency)[] | undefined; optionalDeps?: (string | PluginDependency)[] | undefined; conflictsWith?: string[] | undefined; }, factory: (api: PluginAPI, options: TOptions) => void | Promise): { name: string; version?: string | undefined; description?: string | undefined; apiVersion: string; capabilities?: PluginCapabilities | undefined; configSchema?: JSONSchema | undefined; defaultConfig?: TOptions | undefined; dependsOn?: (string | PluginDependency)[] | undefined; optionalDeps?: (string | PluginDependency)[] | undefined; conflictsWith?: string[] | undefined; setup: (api: PluginAPI) => void | Promise; }; //# sourceMappingURL=api.d.ts.map