import { type PluginManifest } from '../types/plugin/index.js'; import { type Logger } from '../utils/logger.js'; /** * Scans a directory for subdirectories containing a plugin manifest. * Returns an array of absolute paths to plugin directories. */ export declare function discoverPlugins(parentDir: string, log?: Logger): Promise; /** * Reads and validates a plugin manifest from a plugin directory. * Throws on invalid manifest (fail fast). */ export declare function loadPluginManifest(pluginDir: string, capabilities?: PluginEnablementCapabilities): Promise; /** * Refuse a manifest whose contributions can never be enabled. * * Checked at LOAD, not at enable. A plugin that cannot enable was being * persisted as `installed` — a status that says the opposite — and the * author found out only when something tried to use it, at which point * every tool it also shipped went down with it. Failing where the manifest * is read means the author learns at the moment they are looking at the * manifest. * * The registries these types would need all exist and are wired to agents * through host configuration; what does not exist is the manifest path * into them. Naming the types is what makes that actionable. */ export interface PluginEnablementCapabilities { /** * Whether the host wired a `SkillRegistry`. * * Defaults to `false`, which keeps the previous behaviour for every * caller that has not been updated: a manifest declaring skills is * refused. The check cannot default the other way — a host that never * supplied a registry would then install a plugin whose skills go * nowhere. */ readonly skillsSupported?: boolean; } export declare function assertEnableable(manifest: PluginManifest, capabilities?: PluginEnablementCapabilities): void; /** Where a plugin came from. Project plugins ship with the repo; user plugins live in the home directory. */ export type PluginScope = 'project' | 'user'; /** * The discovery half of {@link PluginRuntimeConfig}. * * Structural rather than an import so this module keeps depending on nothing * — a parsed `PluginRuntimeConfig` satisfies it as-is. */ export interface PluginDiscoveryOptions { /** Whether the plugin runtime is on at all. `false` discovers nothing. */ readonly enabled?: boolean; /** Whether to scan for plugins. `false` discovers nothing. */ readonly autoDiscovery?: boolean; /** Which locations may be scanned. Absent means both. */ readonly allowedScopes?: readonly PluginScope[]; /** * Exact user application root. When supplied, user plugins live under its * `plugins/` child. Absent preserves the historical `~/.namzu/plugins` * lookup for SDK callers that do not own an application-home resolver. */ readonly userRoot?: string; /** Threaded into both `discoverPlugins` calls below. */ readonly log?: Logger; } /** * Find plugin directories, in the locations the caller permits. * * `allowedScopes` is a trust boundary, not a filter applied afterwards. A * plugin is arbitrary code with hooks into tool execution, and the two scopes * are not equally trusted: project plugins are reviewable in the repo the * agent is working on, while user plugins come from a home directory the * repo's reviewers never see. `['project']` is how a host says the second * kind is not allowed to run here. * * It was previously declared and unread — `PluginRuntimeConfig` carried * `enabled`, `autoDiscovery` and `allowedScopes`, nothing anywhere consulted * any of them, and this function scanned both locations unconditionally. A * host who set `allowedScopes: ['project']` got user plugins anyway, from a * setting that reads exactly like a boundary. * * A disallowed scope is NOT SCANNED rather than scanned and dropped. * Filtering after the fact still reads the directory, which is both pointless * work and a small disclosure — the returned count would tell a caller how * many plugins live somewhere they said they would not look. * * Passing nothing keeps the old behaviour: both scopes, no gate. Existing * callers are unaffected, and a caller who opts in gets what the config says. */ export declare function discoverAllPluginDirs(workingDirectory?: string, options?: PluginDiscoveryOptions): Promise<{ project: string[]; user: string[]; }>; //# sourceMappingURL=loader.d.ts.map