import { buildSandboxNpmInstallCommand, getAdapterSessionManagement, } from "@paperclipai/adapter-utils";
import { execute as acpxExecute, testEnvironment as acpxTestEnvironment, sessionCodec as acpxSessionCodec, getConfigSchema as getAcpxConfigSchema, listAcpxSkills, syncAcpxSkills, } from "@paperclipai/adapter-acpx-local/server";
import { agentConfigurationDoc as acpxAgentConfigurationDoc, models as acpxModels, } from "@paperclipai/adapter-acpx-local";
import { execute as claudeExecute, listClaudeSkills, syncClaudeSkills, listClaudeModels, refreshClaudeModels, testEnvironment as claudeTestEnvironment, sessionCodec as claudeSessionCodec, getQuotaWindows as claudeGetQuotaWindows, } from "@paperclipai/adapter-claude-local/server";
import { agentConfigurationDoc as claudeAgentConfigurationDoc, models as claudeModels, modelProfiles as claudeModelProfiles, } from "@paperclipai/adapter-claude-local";
import { execute as codexExecute, listCodexSkills, syncCodexSkills, testEnvironment as codexTestEnvironment, sessionCodec as codexSessionCodec, getQuotaWindows as codexGetQuotaWindows, } from "@paperclipai/adapter-codex-local/server";
import { agentConfigurationDoc as codexAgentConfigurationDoc, models as codexModels, modelProfiles as codexModelProfiles, } from "@paperclipai/adapter-codex-local";
import { execute as cursorExecute, listCursorSkills, syncCursorSkills, testEnvironment as cursorTestEnvironment, sessionCodec as cursorSessionCodec, } from "@paperclipai/adapter-cursor-local/server";
import { agentConfigurationDoc as cursorAgentConfigurationDoc, models as cursorModels, modelProfiles as cursorModelProfiles, } from "@paperclipai/adapter-cursor-local";
import { execute as cursorCloudExecute, getConfigSchema as getCursorCloudConfigSchema, sessionCodec as cursorCloudSessionCodec, testEnvironment as cursorCloudTestEnvironment, } from "@paperclipai/adapter-cursor-cloud/server";
import { agentConfigurationDoc as cursorCloudAgentConfigurationDoc } from "@paperclipai/adapter-cursor-cloud";
import { execute as geminiExecute, listGeminiSkills, syncGeminiSkills, testEnvironment as geminiTestEnvironment, sessionCodec as geminiSessionCodec, } from "@paperclipai/adapter-gemini-local/server";
import { agentConfigurationDoc as geminiAgentConfigurationDoc, models as geminiModels, modelProfiles as geminiModelProfiles, } from "@paperclipai/adapter-gemini-local";
import { execute as grokExecute, listGrokSkills, syncGrokSkills, testEnvironment as grokTestEnvironment, sessionCodec as grokSessionCodec, } from "@paperclipai/adapter-grok-local/server";
import { agentConfigurationDoc as grokAgentConfigurationDoc, models as grokModels, } from "@paperclipai/adapter-grok-local";
import { execute as openCodeExecute, listOpenCodeSkills, syncOpenCodeSkills, testEnvironment as openCodeTestEnvironment, sessionCodec as openCodeSessionCodec, listOpenCodeModels, } from "@paperclipai/adapter-opencode-local/server";
import { agentConfigurationDoc as openCodeAgentConfigurationDoc, models as openCodeModels, modelProfiles as openCodeModelProfiles, } from "@paperclipai/adapter-opencode-local";
import { execute as openclawGatewayExecute, testEnvironment as openclawGatewayTestEnvironment, } from "@paperclipai/adapter-openclaw-gateway/server";
import { agentConfigurationDoc as openclawGatewayAgentConfigurationDoc, models as openclawGatewayModels, } from "@paperclipai/adapter-openclaw-gateway";
import { listCodexModels, refreshCodexModels } from "./codex-models.js";
import { listCursorModels } from "./cursor-models.js";
import { execute as piExecute, listPiSkills, syncPiSkills, testEnvironment as piTestEnvironment, sessionCodec as piSessionCodec, listPiModels, } from "@paperclipai/adapter-pi-local/server";
import { agentConfigurationDoc as piAgentConfigurationDoc, modelProfiles as piModelProfiles, } from "@paperclipai/adapter-pi-local";
import { execute as hermesExecute, testEnvironment as hermesTestEnvironment, sessionCodec as hermesSessionCodec, listSkills as hermesListSkills, syncSkills as hermesSyncSkills, detectModel as detectModelFromHermes, } from "hermes-paperclip-adapter/server";
import { agentConfigurationDoc as hermesAgentConfigurationDoc, models as hermesModels, } from "hermes-paperclip-adapter";
import { BUILTIN_ADAPTER_TYPES } from "./builtin-adapter-types.js";
import { buildExternalAdapters } from "./plugin-loader.js";
import { getDisabledAdapterTypes } from "../services/adapter-plugin-store.js";
import { processAdapter } from "./process/index.js";
import { httpAdapter } from "./http/index.js";
function readConfiguredCommand(config, fallback) {
    const value = typeof config.command === "string" ? config.command.trim() : "";
    return value.length > 0 ? value : fallback;
}
function hasPathSeparator(command) {
    return command.includes("/") || command.includes("\\");
}
function shellQuote(value) {
    return `'${value.replace(/'/g, `'"'"'`)}'`;
}
function buildNpmRuntimeCommandSpec(config, fallbackCommand, packageName) {
    const command = readConfiguredCommand(config, fallbackCommand);
    const canSelfInstall = !hasPathSeparator(command) && command === fallbackCommand;
    const installLine = buildSandboxNpmInstallCommand(packageName);
    return {
        command,
        detectCommand: command,
        installCommand: canSelfInstall
            ? `if ! command -v ${shellQuote(command)} >/dev/null 2>&1; then ${installLine}; fi`
            : null,
    };
}
function buildCursorRuntimeCommandSpec(config) {
    const command = readConfiguredCommand(config, "agent");
    return {
        command,
        detectCommand: command,
        installCommand: null,
    };
}
function normalizeHermesConfig(ctx) {
    const config = ctx && typeof ctx === "object" && "config" in ctx && ctx.config && typeof ctx.config === "object"
        ? ctx.config
        : null;
    const agent = ctx && typeof ctx === "object" && "agent" in ctx && ctx.agent && typeof ctx.agent === "object"
        ? ctx.agent
        : null;
    const agentAdapterConfig = agent?.adapterConfig && typeof agent.adapterConfig === "object"
        ? agent.adapterConfig
        : null;
    const configCommand = typeof config?.command === "string" && config.command.length > 0 ? config.command : undefined;
    const agentCommand = typeof agentAdapterConfig?.command === "string" && agentAdapterConfig.command.length > 0
        ? agentAdapterConfig.command
        : undefined;
    if (config && !config.hermesCommand && configCommand) {
        config.hermesCommand = configCommand;
    }
    if (agentAdapterConfig && !agentAdapterConfig.hermesCommand && agentCommand) {
        agentAdapterConfig.hermesCommand = agentCommand;
    }
    return ctx;
}
function dedupeAdapterModels(models) {
    const seen = new Set();
    const result = [];
    for (const model of models) {
        const id = model.id.trim();
        if (!id || seen.has(id))
            continue;
        seen.add(id);
        result.push({ ...model, id });
    }
    return result;
}
function prefixAdapterModelLabels(models, provider) {
    const prefix = `${provider}: `;
    return models.map((model) => ({
        ...model,
        label: model.label.startsWith(prefix) ? model.label : `${prefix}${model.label}`,
    }));
}
async function listAcpxModels() {
    const [claude, codex] = await Promise.all([
        listClaudeModels().catch(() => claudeModels),
        listCodexModels().catch(() => codexModels),
    ]);
    return dedupeAdapterModels([
        ...acpxModels,
        ...prefixAdapterModelLabels(claude, "Claude"),
        ...prefixAdapterModelLabels(codex, "Codex"),
    ]);
}
const claudeLocalAdapter = {
    type: "claude_local",
    execute: claudeExecute,
    testEnvironment: claudeTestEnvironment,
    listSkills: listClaudeSkills,
    syncSkills: syncClaudeSkills,
    sessionCodec: claudeSessionCodec,
    sessionManagement: getAdapterSessionManagement("claude_local") ?? undefined,
    models: claudeModels,
    modelProfiles: claudeModelProfiles,
    listModels: listClaudeModels,
    refreshModels: refreshClaudeModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: false,
    getRuntimeCommandSpec: (config) => buildNpmRuntimeCommandSpec(config, "claude", "@anthropic-ai/claude-code"),
    agentConfigurationDoc: claudeAgentConfigurationDoc,
    getQuotaWindows: claudeGetQuotaWindows,
};
const acpxLocalAdapter = {
    type: "acpx_local",
    execute: acpxExecute,
    testEnvironment: acpxTestEnvironment,
    listSkills: listAcpxSkills,
    syncSkills: syncAcpxSkills,
    sessionCodec: acpxSessionCodec,
    sessionManagement: getAdapterSessionManagement("acpx_local") ?? undefined,
    models: dedupeAdapterModels([
        ...prefixAdapterModelLabels(claudeModels, "Claude"),
        ...prefixAdapterModelLabels(codexModels, "Codex"),
    ]),
    listModels: listAcpxModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: false,
    agentConfigurationDoc: acpxAgentConfigurationDoc,
    getConfigSchema: getAcpxConfigSchema,
};
const codexLocalAdapter = {
    type: "codex_local",
    execute: codexExecute,
    testEnvironment: codexTestEnvironment,
    listSkills: listCodexSkills,
    syncSkills: syncCodexSkills,
    sessionCodec: codexSessionCodec,
    sessionManagement: getAdapterSessionManagement("codex_local") ?? undefined,
    models: codexModels,
    modelProfiles: codexModelProfiles,
    listModels: listCodexModels,
    refreshModels: refreshCodexModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: false,
    getRuntimeCommandSpec: (config) => buildNpmRuntimeCommandSpec(config, "codex", "@openai/codex"),
    agentConfigurationDoc: codexAgentConfigurationDoc,
    getQuotaWindows: codexGetQuotaWindows,
};
const cursorLocalAdapter = {
    type: "cursor",
    execute: cursorExecute,
    testEnvironment: cursorTestEnvironment,
    listSkills: listCursorSkills,
    syncSkills: syncCursorSkills,
    sessionCodec: cursorSessionCodec,
    sessionManagement: getAdapterSessionManagement("cursor") ?? undefined,
    models: cursorModels,
    modelProfiles: cursorModelProfiles,
    listModels: listCursorModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: true,
    getRuntimeCommandSpec: buildCursorRuntimeCommandSpec,
    agentConfigurationDoc: cursorAgentConfigurationDoc,
};
const cursorCloudAdapter = {
    type: "cursor_cloud",
    execute: cursorCloudExecute,
    testEnvironment: cursorCloudTestEnvironment,
    sessionCodec: cursorCloudSessionCodec,
    sessionManagement: getAdapterSessionManagement("cursor_cloud") ?? undefined,
    models: [],
    supportsLocalAgentJwt: false,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: false,
    agentConfigurationDoc: cursorCloudAgentConfigurationDoc,
    getConfigSchema: getCursorCloudConfigSchema,
};
const geminiLocalAdapter = {
    type: "gemini_local",
    execute: geminiExecute,
    testEnvironment: geminiTestEnvironment,
    listSkills: listGeminiSkills,
    syncSkills: syncGeminiSkills,
    sessionCodec: geminiSessionCodec,
    sessionManagement: getAdapterSessionManagement("gemini_local") ?? undefined,
    models: geminiModels,
    modelProfiles: geminiModelProfiles,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: true,
    getRuntimeCommandSpec: (config) => buildNpmRuntimeCommandSpec(config, "gemini", "@google/gemini-cli"),
    agentConfigurationDoc: geminiAgentConfigurationDoc,
};
const grokLocalAdapter = {
    type: "grok_local",
    execute: grokExecute,
    testEnvironment: grokTestEnvironment,
    listSkills: listGrokSkills,
    syncSkills: syncGrokSkills,
    sessionCodec: grokSessionCodec,
    sessionManagement: getAdapterSessionManagement("grok_local") ?? undefined,
    models: grokModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: true,
    getRuntimeCommandSpec: (config) => ({
        command: readConfiguredCommand(config, "grok"),
        detectCommand: readConfiguredCommand(config, "grok"),
        installCommand: null,
    }),
    agentConfigurationDoc: grokAgentConfigurationDoc,
};
const openclawGatewayAdapter = {
    type: "openclaw_gateway",
    execute: openclawGatewayExecute,
    testEnvironment: openclawGatewayTestEnvironment,
    models: openclawGatewayModels,
    supportsLocalAgentJwt: false,
    supportsInstructionsBundle: false,
    requiresMaterializedRuntimeSkills: false,
    agentConfigurationDoc: openclawGatewayAgentConfigurationDoc,
};
const openCodeLocalAdapter = {
    type: "opencode_local",
    execute: openCodeExecute,
    testEnvironment: openCodeTestEnvironment,
    listSkills: listOpenCodeSkills,
    syncSkills: syncOpenCodeSkills,
    sessionCodec: openCodeSessionCodec,
    models: openCodeModels,
    modelProfiles: openCodeModelProfiles,
    sessionManagement: getAdapterSessionManagement("opencode_local") ?? undefined,
    listModels: listOpenCodeModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: true,
    getRuntimeCommandSpec: (config) => buildNpmRuntimeCommandSpec(config, "opencode", "opencode-ai"),
    agentConfigurationDoc: openCodeAgentConfigurationDoc,
};
const piLocalAdapter = {
    type: "pi_local",
    execute: piExecute,
    testEnvironment: piTestEnvironment,
    listSkills: listPiSkills,
    syncSkills: syncPiSkills,
    sessionCodec: piSessionCodec,
    sessionManagement: getAdapterSessionManagement("pi_local") ?? undefined,
    models: [],
    modelProfiles: piModelProfiles,
    listModels: listPiModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: true,
    instructionsPathKey: "instructionsFilePath",
    requiresMaterializedRuntimeSkills: true,
    getRuntimeCommandSpec: (config) => buildNpmRuntimeCommandSpec(config, "pi", "@mariozechner/pi-coding-agent"),
    agentConfigurationDoc: piAgentConfigurationDoc,
};
// hermes-paperclip-adapter v0.2.0 predates the authToken field; cast is
// intentional until hermes ships a matching AdapterExecutionContext type.
const executeHermesLocal = hermesExecute;
const hermesLocalAdapter = {
    type: "hermes_local",
    execute: async (ctx) => {
        const normalizedCtx = normalizeHermesConfig(ctx);
        if (!normalizedCtx.authToken)
            return executeHermesLocal(normalizedCtx);
        const existingConfig = (normalizedCtx.agent.adapterConfig ?? {});
        const existingEnv = typeof existingConfig.env === "object" && existingConfig.env !== null && !Array.isArray(existingConfig.env)
            ? existingConfig.env
            : {};
        const explicitApiKey = typeof existingEnv.PAPERCLIP_API_KEY === "string" && existingEnv.PAPERCLIP_API_KEY.trim().length > 0;
        const promptTemplate = typeof existingConfig.promptTemplate === "string" && existingConfig.promptTemplate.trim().length > 0
            ? existingConfig.promptTemplate
            : "";
        const authGuardPrompt = [
            "Paperclip API safety rule:",
            "Use Authorization: Bearer $PAPERCLIP_API_KEY on every Paperclip API request.",
            "Use X-Paperclip-Run-Id: $PAPERCLIP_RUN_ID on every Paperclip API request that writes or mutates data, including comments and issue updates.",
            "Never use a board, browser, or local-board session for Paperclip API writes.",
        ].join("\n");
        const patchedConfig = {
            ...existingConfig,
            env: {
                ...existingEnv,
                ...(!explicitApiKey ? { PAPERCLIP_API_KEY: normalizedCtx.authToken } : {}),
                PAPERCLIP_RUN_ID: normalizedCtx.runId,
            },
        };
        // Only inject the auth guard into promptTemplate when a custom template already exists.
        // When no custom template is set, Hermes uses its built-in default heartbeat/task prompt —
        // overwriting it with only the auth guard text would strip the assigned issue/workflow instructions.
        if (promptTemplate) {
            patchedConfig.promptTemplate = `${authGuardPrompt}\n\n${promptTemplate}`;
        }
        const patchedCtx = {
            ...normalizedCtx,
            agent: {
                ...normalizedCtx.agent,
                adapterConfig: patchedConfig,
            },
        };
        return executeHermesLocal(patchedCtx);
    },
    testEnvironment: (ctx) => hermesTestEnvironment(normalizeHermesConfig(ctx)),
    sessionCodec: hermesSessionCodec,
    listSkills: hermesListSkills,
    syncSkills: hermesSyncSkills,
    models: hermesModels,
    supportsLocalAgentJwt: true,
    supportsInstructionsBundle: false,
    requiresMaterializedRuntimeSkills: false,
    agentConfigurationDoc: hermesAgentConfigurationDoc,
    detectModel: () => detectModelFromHermes(),
};
const adaptersByType = new Map();
// For builtin types that are overridden by an external adapter, we keep the
// original builtin so it can be restored when the override is deactivated.
const builtinFallbacks = new Map();
// Tracks which override types are currently deactivated (paused).  When
// paused, `getServerAdapter()` returns the builtin fallback instead of the
// external.  Persisted across reloads via the same disabled-adapters store.
const pausedOverrides = new Set();
function registerBuiltInAdapters() {
    for (const adapter of [
        acpxLocalAdapter,
        claudeLocalAdapter,
        codexLocalAdapter,
        openCodeLocalAdapter,
        piLocalAdapter,
        cursorCloudAdapter,
        cursorLocalAdapter,
        geminiLocalAdapter,
        grokLocalAdapter,
        openclawGatewayAdapter,
        hermesLocalAdapter,
        processAdapter,
        httpAdapter,
    ]) {
        adaptersByType.set(adapter.type, adapter);
    }
}
registerBuiltInAdapters();
// ---------------------------------------------------------------------------
// Load external adapter plugins (e.g. droid_local)
//
// External adapter packages export createServerAdapter() which returns a
// ServerAdapterModule. When the module provides its own sessionManagement
// it is preserved; otherwise the host falls back to the built-in registry
// lookup (so externals that override a built-in type inherit the builtin's
// policy). This brings init-time registration to at-least-as-good behavior
// as the hot-install path (routes/adapters.ts:179 -> registerServerAdapter):
// both preserve module-provided sessionManagement, and init-time additionally
// applies the registry fallback for externals overriding a built-in type.
// ---------------------------------------------------------------------------
/** Cached sync wrapper — the store is a simple JSON file read, safe to call frequently. */
function getDisabledAdapterTypesFromStore() {
    return getDisabledAdapterTypes();
}
/**
 * Merge an external adapter module with host-provided session management.
 *
 * Module-provided `sessionManagement` takes precedence. When absent, fall
 * back to the hardcoded registry keyed by adapter type (so externals that
 * override a built-in — same `type` — inherit the builtin's policy). If
 * neither is available, `sessionManagement` remains `undefined`.
 *
 * Used by both the init-time IIFE below (external-adapter load pass on
 * server start) and the hot-install path in `routes/adapters.ts`
 * (`registerWithSessionManagement`), so the two load paths resolve
 * `sessionManagement` identically.
 */
export function resolveExternalAdapterRegistration(externalAdapter) {
    return {
        ...externalAdapter,
        sessionManagement: externalAdapter.sessionManagement
            ?? getAdapterSessionManagement(externalAdapter.type)
            ?? undefined,
    };
}
/**
 * Load external adapters from the plugin store and hardcoded sources.
 * Called once at module initialization. The promise is exported so that
 * callers (e.g. assertKnownAdapterType, app startup) can await completion
 * and avoid racing against the loading window.
 */
const externalAdaptersReady = (async () => {
    try {
        const externalAdapters = await buildExternalAdapters();
        for (const externalAdapter of externalAdapters) {
            const overriding = BUILTIN_ADAPTER_TYPES.has(externalAdapter.type);
            if (overriding) {
                console.log(`[paperclip] External adapter "${externalAdapter.type}" overrides built-in adapter`);
                // Save the original builtin for later restoration.
                const existing = adaptersByType.get(externalAdapter.type);
                if (existing && !builtinFallbacks.has(externalAdapter.type)) {
                    builtinFallbacks.set(externalAdapter.type, existing);
                }
            }
            adaptersByType.set(externalAdapter.type, resolveExternalAdapterRegistration(externalAdapter));
        }
    }
    catch (err) {
        console.error("[paperclip] Failed to load external adapters:", err);
    }
})();
/**
 * Await this before validating adapter types to avoid race conditions
 * during server startup. External adapters are loaded asynchronously;
 * calling assertKnownAdapterType before this resolves will reject
 * valid external adapter types.
 */
export function waitForExternalAdapters() {
    return externalAdaptersReady;
}
export function registerServerAdapter(adapter) {
    if (BUILTIN_ADAPTER_TYPES.has(adapter.type) && !builtinFallbacks.has(adapter.type)) {
        const existing = adaptersByType.get(adapter.type);
        if (existing) {
            builtinFallbacks.set(adapter.type, existing);
        }
    }
    adaptersByType.set(adapter.type, adapter);
}
export function unregisterServerAdapter(type) {
    if (type === processAdapter.type || type === httpAdapter.type)
        return;
    if (builtinFallbacks.has(type)) {
        pausedOverrides.delete(type);
        const fallback = builtinFallbacks.get(type);
        if (fallback) {
            adaptersByType.set(type, fallback);
        }
        return;
    }
    if (BUILTIN_ADAPTER_TYPES.has(type)) {
        return;
    }
    adaptersByType.delete(type);
}
export function requireServerAdapter(type) {
    const adapter = findActiveServerAdapter(type);
    if (!adapter) {
        throw new Error(`Unknown adapter type: ${type}`);
    }
    return adapter;
}
export function getServerAdapter(type) {
    return findActiveServerAdapter(type) ?? processAdapter;
}
export async function listAdapterModels(type) {
    const adapter = findActiveServerAdapter(type);
    if (!adapter)
        return [];
    if (adapter.listModels) {
        const discovered = await adapter.listModels();
        if (discovered.length > 0)
            return discovered;
    }
    return adapter.models ?? [];
}
export async function refreshAdapterModels(type) {
    const adapter = findActiveServerAdapter(type);
    if (!adapter)
        return [];
    if (adapter.refreshModels) {
        const refreshed = await adapter.refreshModels();
        if (refreshed.length > 0)
            return refreshed;
    }
    if (adapter.listModels) {
        const discovered = await adapter.listModels();
        if (discovered.length > 0)
            return discovered;
    }
    return adapter.models ?? [];
}
export async function listAdapterModelProfiles(type) {
    const adapter = findActiveServerAdapter(type);
    if (!adapter)
        return [];
    if (adapter.listModelProfiles) {
        const discovered = await adapter.listModelProfiles();
        if (discovered.length > 0)
            return discovered;
    }
    return adapter.modelProfiles ?? [];
}
export function listServerAdapters() {
    return Array.from(adaptersByType.values());
}
/**
 * List adapters excluding those that are disabled in settings.
 * Used for menus and agent creation flows — disabled adapters remain
 * functional for existing agents but hidden from selection.
 */
export function listEnabledServerAdapters() {
    const disabled = getDisabledAdapterTypesFromStore();
    const disabledSet = disabled.length > 0 ? new Set(disabled) : null;
    return disabledSet
        ? Array.from(adaptersByType.values()).filter((a) => !disabledSet.has(a.type))
        : Array.from(adaptersByType.values());
}
export async function detectAdapterModel(type) {
    const adapter = findActiveServerAdapter(type);
    if (!adapter?.detectModel)
        return null;
    const detected = await adapter.detectModel();
    if (!detected)
        return null;
    return {
        model: detected.model,
        provider: detected.provider,
        source: detected.source,
        ...(detected.candidates?.length ? { candidates: detected.candidates } : {}),
    };
}
// ---------------------------------------------------------------------------
// Override pause / resume
// ---------------------------------------------------------------------------
/**
 * Pause or resume an external override for a builtin adapter type.
 *
 * - `paused = true`  → subsequent calls to `getServerAdapter(type)` return
 *   the builtin fallback instead of the external adapter.  Already-running
 *   agent sessions are unaffected (they hold a reference to the module they
 *   started with).
 *
 * - `paused = false` → the external adapter is active again.
 *
 * Returns `true` if the state actually changed, `false` if the type is not
 * an override or was already in the requested state.
 */
export function setOverridePaused(type, paused) {
    if (!builtinFallbacks.has(type))
        return false;
    const wasPaused = pausedOverrides.has(type);
    if (paused && !wasPaused) {
        pausedOverrides.add(type);
        console.log(`[paperclip] Override paused for "${type}" — builtin adapter restored`);
        return true;
    }
    if (!paused && wasPaused) {
        pausedOverrides.delete(type);
        console.log(`[paperclip] Override resumed for "${type}" — external adapter active`);
        return true;
    }
    return false;
}
/** Check whether the external override for a builtin type is currently paused. */
export function isOverridePaused(type) {
    return pausedOverrides.has(type);
}
/** Get the set of types whose overrides are currently paused. */
export function getPausedOverrides() {
    return pausedOverrides;
}
export function findServerAdapter(type) {
    return adaptersByType.get(type) ?? null;
}
export function findActiveServerAdapter(type) {
    if (pausedOverrides.has(type)) {
        const fallback = builtinFallbacks.get(type);
        if (fallback)
            return fallback;
    }
    return adaptersByType.get(type) ?? null;
}
//# sourceMappingURL=registry.js.map