/**
 * Native plugin marketplaces for Claude / OpenClaw — one per DotAgents repo.
 *
 * Every DotAgents repo that holds plugins synthesizes its OWN synthetic local
 * marketplace under each version's plugin directory, named after the repo:
 *
 *   <versionHome>/.{claude,openclaw}/plugins/
 *     known_marketplaces.json                    # registers each repo's marketplace
 *     marketplaces/agents-cli/                    # ~/.agents/plugins/*        (user repo)
 *     marketplaces/agents-<alias>/                # ~/.agents-<alias>/plugins/* (extra repo)
 *     marketplaces/agents-project/                # <cwd>/.agents/plugins/*    (project repo)
 *       .claude-plugin/marketplace.json           # synthesized catalog
 *       plugins/<plugin>/                         # copied plugin source
 *
 * Plus the version's settings.json gets
 *   `enabledPlugins["<plugin>@<marketplace>"] = true`.
 *
 * This produces native `/plugin:skill` slash namespacing, visibility in
 * `/plugins`, `/plugin enable|disable` support, AND honest attribution (the
 * user can see which repo each plugin came from) — matching the Claude Code
 * spec at https://code.claude.com/docs/en/plugins and /plugin-marketplaces.
 *
 * The naming policy lives in one place — marketplaceNameFor(). Source-side
 * discovery (discoverMarketplaces) and per-version synthesis (syncMarketplaceManifest
 * / registerMarketplace / syncAllMarketplaces) all key off a MarketplaceSpec so
 * the catalog name and on-disk layout are derived, never hard-coded per call.
 */
import type { AgentId, DiscoveredPlugin, MarketplaceSpec, DiscoveredMarketplace } from '../types.js';
/**
 * Canonical name for the user-repo marketplace (~/.agents/plugins/). Kept as an
 * exported constant for callers that operate on the user repo directly and for
 * the `marketplaces/agents-cli/` on-disk path that existing installs already have.
 */
export declare const MARKETPLACE_NAME = "agents-cli";
export declare const SYSTEM_MARKETPLACE_NAME = "agents-system";
/** Marketplace name for <cwd>/.agents/plugins/*. */
export declare const PROJECT_MARKETPLACE_NAME = "agents-project";
interface MarketplacePluginEntry {
    name: string;
    source: string;
    description?: string;
    version?: string;
    author?: {
        name: string;
        email?: string;
    };
}
export interface MarketplaceManifest {
    $schema?: string;
    name: string;
    description?: string;
    owner: {
        name: string;
        email?: string;
    };
    plugins: MarketplacePluginEntry[];
}
/** Result of synthesizing + registering one marketplace via syncAllMarketplaces. */
export interface SyncAllResult {
    spec: MarketplaceSpec;
    name: string;
    plugins: number;
}
/**
 * Map a MarketplaceSpec to its catalog name. This is the ONLY place that
 * encodes the repo → name policy; every other function derives the name here.
 */
export declare function marketplaceNameFor(spec: MarketplaceSpec): string;
/**
 * Discover every DotAgents repo that contributes plugins, in precedence order
 * (user, then each enabled extra repo, then the project repo when cwd has one).
 * No agent / version is involved — this walks source-side plugin roots only.
 *
 * A repo is included when its plugins/ directory exists on disk. The user repo
 * is always probed; extras come from getEnabledExtraRepos() (already filtered to
 * enabled + on-disk repos); the project repo is included only when
 * <cwd>/.agents/plugins/ exists.
 */
export declare function discoverMarketplaces(opts?: {
    cwd?: string;
}): DiscoveredMarketplace[];
export declare function marketplaceRoot(specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): string;
export declare function marketplaceManifestPath(specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): string;
export declare function pluginInstallDir(plugin: DiscoveredPlugin, specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): string;
export declare function knownMarketplacesPath(agent: AgentId, versionHome: string): string;
/**
 * Copy plugin source into the marketplace install dir for the given spec.
 * Source of truth remains the plugin's source dir — this is a per-version snapshot.
 *
 * Symlinks pointing OUTSIDE the plugin source root are dropped. They show up
 * when plugin authors (legitimately) link prompt-side references to sibling
 * codebases — e.g. the rush plugin's `app -> ../../../rush/app` for @app/...
 * autocomplete in user prompts. Faithfully copying those symlinks pollutes
 * the marketplace with gigabytes of node_modules / .next / brand-asset video
 * that the consumer (Claude Code, OpenClaw) then walks during plugin
 * discovery — which is the documented cause of multi-minute startup hangs.
 *
 * Internal symlinks (target stays inside the plugin root) are preserved.
 */
export declare function copyPluginToMarketplace(plugin: DiscoveredPlugin, spec: MarketplaceSpec | string, agent: AgentId, versionHome: string): string;
/**
 * Claude Code's plugin-manifest schema requires the resource path fields to be
 * relative paths starting with "./" — `skills`/`commands`/`agents` are
 * `union([startsWith("./"), array(startsWith("./"))])` (verified against the
 * Claude Code binary). Bare names like "loop" fail validation and Claude rejects
 * the ENTIRE plugin at load time, surfacing only in its `/plugin` > Errors tab.
 *
 * agents-cli copies plugin.json verbatim into the marketplace, so a malformed
 * manifest ships looking fully installed while loading nothing. This catches the
 * unambiguous type violation (non-"./" string entries) and returns one warning
 * per offending field so the caller can surface it loudly. `hooks`/`mcpServers`
 * are intentionally skipped — they legitimately accept inline objects, so a path
 * check would false-positive.
 */
export declare function validateClaudePluginManifest(manifest: unknown): string[];
/**
 * The repairable fields present-and-invalid in a parsed manifest. Drives both
 * the dry-run preview (heal/doctor --fix) and the actual write below.
 */
export declare function repairableManifestFields(manifest: unknown): string[];
/**
 * Auto-repair a plugin's SOURCE plugin.json in place: delete any `skills`/
 * `commands` field that holds bare names (Claude Code silently rejects the
 * ENTIRE plugin otherwise). Claude auto-discovers both from their directories,
 * so deletion is the canonical, lossless fix — exactly what the validator's
 * warning already recommends. Returns the fields it dropped (empty = no change).
 *
 * Writes to the source manifest (not the regenerated marketplace copy) so the
 * fix survives the next sync. Pass `{ dryRun }` to preview without writing.
 */
export declare function repairPluginManifestFile(manifestPath: string, opts?: {
    dryRun?: boolean;
}): string[];
/**
 * Re-synthesize <marketplace>/.claude-plugin/marketplace.json from the plugins
 * already installed under <marketplace>/plugins/. Always run after add or remove
 * so the manifest stays in lockstep with on-disk contents. Returns the manifest
 * it wrote, or null when the marketplace has no plugins dir yet.
 */
export declare function syncMarketplaceManifest(spec: MarketplaceSpec, agent: AgentId, versionHome: string): MarketplaceManifest | null;
/**
 * Register a marketplace in known_marketplaces.json so Claude Code discovers
 * it on startup. Idempotent: re-running just refreshes lastUpdated. Other
 * marketplaces' entries are preserved untouched.
 */
export declare function registerMarketplace(spec: MarketplaceSpec, agent: AgentId, versionHome: string): void;
/**
 * Record a plugin in Droid's installed_plugins.json (user scope), pointing
 * installPath at the marketplace install dir so no second copy is needed. This
 * is what makes `droid plugin list` show the plugin (Active once enabledPlugins
 * is set). Idempotent: re-running refreshes lastUpdated and preserves the
 * original installedAt plus any non-user scope entries.
 */
export declare function registerDroidInstalledPlugin(pluginName: string, marketplaceName: string, installDir: string, version: string, agent: AgentId, versionHome: string): void;
/** True when Droid's installed_plugins.json carries a user-scope entry for the plugin. */
export declare function isDroidPluginInstalled(pluginName: string, marketplaceName: string, agent: AgentId, versionHome: string): boolean;
/**
 * Remove a plugin's user-scope entry from Droid's installed_plugins.json.
 * Inverse of registerDroidInstalledPlugin. Drops the key when no scopes remain
 * and deletes the file when the registry is empty.
 */
export declare function unregisterDroidInstalledPlugin(pluginName: string, marketplaceName: string, agent: AgentId, versionHome: string): void;
/**
 * Record a plugin in Copilot's config.json#installedPlugins (the registry that
 * makes `copilot plugin list` see it). `cache_path` points at the marketplace
 * install dir — no separate copy. Idempotent: re-running refreshes the entry and
 * preserves the original installed_at plus every other config key.
 */
export declare function registerCopilotInstalledPlugin(pluginName: string, marketplaceName: string, installDir: string, version: string, enabled: boolean, agent: AgentId, versionHome: string): void;
/**
 * Remove a plugin's entry from Copilot's config.json#installedPlugins. Inverse
 * of registerCopilotInstalledPlugin. Leaves the file (with an empty
 * installedPlugins) rather than deleting it, since config.json may hold other
 * Copilot-managed keys.
 */
export declare function unregisterCopilotInstalledPlugin(pluginName: string, marketplaceName: string, agent: AgentId, versionHome: string): void;
/**
 * Drop a marketplace entry from known_marketplaces.json. Called when the last
 * plugin under it is removed. Removes only its own entry; deletes the file only
 * when no entries remain.
 */
export declare function unregisterMarketplace(specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): void;
/**
 * Discover every source-side marketplace, then for each one re-synthesize its
 * catalog from the plugins already copied under the version home and register
 * it in known_marketplaces.json. Returns one result per marketplace that has at
 * least one plugin installed.
 *
 * Copying plugin source into a marketplace is the caller's responsibility
 * (copyPluginToMarketplace / syncPluginToVersion) — this reconciles catalogs +
 * registrations across all repos once the copies are in place. Marketplaces
 * whose version-home plugins dir is empty or absent are skipped, so we never
 * register a known_marketplace pointing at a directory with no catalog.
 */
export declare function syncAllMarketplaces(agent: AgentId, versionHome: string, opts?: {
    cwd?: string;
}): SyncAllResult[];
/**
 * Mark a plugin as enabled in <versionHome>/.{agent}/settings.json under
 * enabledPlugins["<plugin>@<marketplace>"]: true. Reads, mutates, writes —
 * preserving every other key. Trust/exec-surface gating is the caller's
 * responsibility (plugins.ts owns plugin capability inspection).
 */
export declare function addPluginToSettings(pluginName: string, marketplaceName: string, agent: AgentId, versionHome: string): void;
/**
 * Remove the enabledPlugins key for this plugin. Inverse of addPluginToSettings.
 */
export declare function removePluginFromSettings(pluginName: string, marketplaceName: string, agent: AgentId, versionHome: string): void;
/**
 * Remove a plugin's installed marketplace directory. Returns true if the dir
 * existed and was removed.
 */
export declare function removePluginFromMarketplace(pluginName: string, specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): boolean;
/**
 * Return true if the marketplace has no plugins left under it.
 */
export declare function marketplaceIsEmpty(specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): boolean;
/**
 * Drop the entire marketplace directory. Called after the last plugin removal.
 */
export declare function removeEmptyMarketplaceDir(specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): void;
/**
 * Detect whether a plugin is installed via the native marketplace path.
 */
export declare function isInstalledInMarketplace(pluginName: string, specOrName: MarketplaceSpec | string, agent: AgentId, versionHome: string): boolean;
export {};
