import { ClaudeAgentClient } from "./providers/claude-agent.js";
import { CodexAppServerAgentClient } from "./providers/codex-app-server-agent.js";
import { CopilotACPAgentClient } from "./providers/copilot-acp-agent.js";
import { GenericACPAgentClient } from "./providers/generic-acp-agent.js";
import { OpenCodeAgentClient, OpenCodeServerManager } from "./providers/opencode-agent.js";
import { PiACPAgentClient } from "./providers/pi-acp-agent.js";
import { AGENT_PROVIDER_DEFINITIONS, BUILTIN_PROVIDER_IDS, getAgentProviderDefinition, } from "./provider-manifest.js";
export { AGENT_PROVIDER_DEFINITIONS, getAgentProviderDefinition };
const PROVIDER_CLIENT_FACTORIES = {
    claude: (logger, runtimeSettings) => new ClaudeAgentClient({
        logger,
        runtimeSettings,
    }),
    codex: (logger, runtimeSettings) => new CodexAppServerAgentClient(logger, runtimeSettings),
    copilot: (logger, runtimeSettings) => new CopilotACPAgentClient({
        logger,
        runtimeSettings,
    }),
    opencode: (logger, runtimeSettings) => new OpenCodeAgentClient(logger, runtimeSettings),
    pi: (logger, runtimeSettings) => new PiACPAgentClient({
        logger,
        runtimeSettings,
    }),
};
function getProviderClientFactory(provider) {
    const factory = PROVIDER_CLIENT_FACTORIES[provider];
    if (!factory) {
        throw new Error(`No provider client factory registered for '${provider}'`);
    }
    return factory;
}
function toRuntimeSettings(override) {
    if (!override?.command && !override?.env && !override?.disallowedTools) {
        return undefined;
    }
    return {
        command: override.command
            ? {
                mode: "replace",
                argv: override.command,
            }
            : undefined,
        env: override.env,
        disallowedTools: override.disallowedTools,
    };
}
function mergeRuntimeSettings(base, override) {
    if (!base && !override) {
        return undefined;
    }
    return {
        command: override?.command ?? base?.command,
        env: base?.env || override?.env
            ? {
                ...(base?.env ?? {}),
                ...(override?.env ?? {}),
            }
            : undefined,
        disallowedTools: base?.disallowedTools || override?.disallowedTools
            ? [...(base?.disallowedTools ?? []), ...(override?.disallowedTools ?? [])]
            : undefined,
    };
}
function applyOverrideToDefinition(definition, override) {
    if (!override) {
        return definition;
    }
    return {
        ...definition,
        label: override.label ?? definition.label,
        description: override.description ?? definition.description,
    };
}
function createDerivedDefinition(providerId, baseDefinition, override) {
    if (!override.label) {
        throw new Error(`Custom provider '${providerId}' requires a label`);
    }
    return {
        ...baseDefinition,
        id: providerId,
        label: override.label,
        description: override.description ?? baseDefinition.description,
    };
}
function mapPersistenceHandle(provider, handle) {
    if (!handle) {
        return null;
    }
    return {
        ...handle,
        provider,
    };
}
function mapRuntimeInfo(provider, runtimeInfo) {
    return {
        ...runtimeInfo,
        provider,
    };
}
function mapStreamEvent(provider, event) {
    return {
        ...event,
        provider,
    };
}
function mapPersistedAgentDescriptor(provider, descriptor) {
    return {
        ...descriptor,
        provider,
        persistence: {
            ...descriptor.persistence,
            provider,
        },
    };
}
function mapModel(provider, model) {
    return {
        ...model,
        provider,
    };
}
function mergeModels(provider, profileModels, runtimeModels) {
    if (profileModels.length === 0) {
        return runtimeModels.map((model) => mapModel(provider, model));
    }
    return profileModels.map((model) => ({
        ...model,
        provider,
    }));
}
function wrapSessionProvider(provider, inner) {
    return {
        provider,
        id: inner.id,
        capabilities: inner.capabilities,
        get features() {
            return inner.features;
        },
        run: (prompt, options) => inner.run(prompt, options),
        startTurn: (prompt, options) => inner.startTurn(prompt, options),
        subscribe: (callback) => inner.subscribe((event) => callback(mapStreamEvent(provider, event))),
        async *streamHistory() {
            for await (const event of inner.streamHistory()) {
                yield mapStreamEvent(provider, event);
            }
        },
        getRuntimeInfo: async () => mapRuntimeInfo(provider, await inner.getRuntimeInfo()),
        getAvailableModes: () => inner.getAvailableModes(),
        getCurrentMode: () => inner.getCurrentMode(),
        setMode: (modeId) => inner.setMode(modeId),
        getPendingPermissions: () => inner.getPendingPermissions(),
        respondToPermission: (requestId, response) => inner.respondToPermission(requestId, response),
        describePersistence: () => mapPersistenceHandle(provider, inner.describePersistence()),
        interrupt: () => inner.interrupt(),
        close: () => inner.close(),
        listCommands: inner.listCommands?.bind(inner),
        setModel: inner.setModel?.bind(inner),
        setThinkingOption: inner.setThinkingOption?.bind(inner),
        setFeature: inner.setFeature?.bind(inner),
    };
}
function wrapClientProvider(provider, inner) {
    const listPersistedAgents = inner.listPersistedAgents?.bind(inner);
    return {
        provider,
        capabilities: inner.capabilities,
        createSession: async (config, launchContext) => wrapSessionProvider(provider, await inner.createSession({
            ...config,
            provider: inner.provider,
        }, launchContext)),
        resumeSession: async (handle, overrides, launchContext) => wrapSessionProvider(provider, await inner.resumeSession({
            ...handle,
            provider: inner.provider,
        }, overrides
            ? {
                ...overrides,
                provider: inner.provider,
            }
            : undefined, launchContext)),
        listModels: async (options) => (await inner.listModels(options)).map((model) => mapModel(provider, model)),
        listModes: inner.listModes?.bind(inner),
        listPersistedAgents: listPersistedAgents
            ? async (options) => (await listPersistedAgents(options)).map((descriptor) => mapPersistedAgentDescriptor(provider, descriptor))
            : undefined,
        isAvailable: () => inner.isAvailable(),
        getDiagnostic: inner.getDiagnostic?.bind(inner),
    };
}
function createRegistryEntry(logger, provider, resolved) {
    const modelClient = resolved.createBaseClient(logger);
    return {
        ...resolved.definition,
        createClient: (providerLogger) => {
            const inner = resolved.createBaseClient(providerLogger);
            return inner.provider === provider ? inner : wrapClientProvider(provider, inner);
        },
        fetchModels: async (options) => mergeModels(provider, resolved.profileModels, await modelClient.listModels(options)),
        fetchModes: async (options) => {
            const modes = modelClient.listModes
                ? await modelClient.listModes(options)
                : resolved.definition.modes;
            return modes.map((mode) => {
                if (mode.icon && mode.colorTier)
                    return mode;
                const definitionMode = resolved.definition.modes.find((d) => d.id === mode.id);
                if (!definitionMode)
                    return mode;
                return {
                    ...mode,
                    icon: mode.icon ?? definitionMode.icon,
                    colorTier: mode.colorTier ?? definitionMode.colorTier,
                };
            });
        },
    };
}
function buildResolvedBuiltinProviders(providerOverrides, runtimeSettings) {
    const resolvedProviders = new Map();
    for (const definition of AGENT_PROVIDER_DEFINITIONS) {
        const override = providerOverrides[definition.id];
        const factory = getProviderClientFactory(definition.id);
        const mergedRuntimeSettings = mergeRuntimeSettings(runtimeSettings?.[definition.id], toRuntimeSettings(override));
        resolvedProviders.set(definition.id, {
            definition: applyOverrideToDefinition(definition, override),
            runtimeSettings: mergedRuntimeSettings,
            profileModels: override?.models ?? [],
            enabled: override?.enabled !== false,
            createBaseClient: (logger) => factory(logger, mergedRuntimeSettings),
        });
    }
    return resolvedProviders;
}
function addDerivedProviders(resolvedProviders, providerOverrides) {
    for (const [providerId, override] of Object.entries(providerOverrides)) {
        if (BUILTIN_PROVIDER_IDS.includes(providerId)) {
            continue;
        }
        if (!override.extends) {
            throw new Error(`Custom provider '${providerId}' requires an extends value`);
        }
        if (override.extends === "acp") {
            if (!override.command) {
                throw new Error(`ACP provider '${providerId}' requires a command`);
            }
            resolvedProviders.set(providerId, {
                definition: createDerivedDefinition(providerId, {
                    id: providerId,
                    label: override.label ?? providerId,
                    description: override.description ?? "Custom ACP provider",
                    defaultModeId: null,
                    modes: [],
                }, override),
                runtimeSettings: toRuntimeSettings(override),
                profileModels: override.models ?? [],
                enabled: override.enabled !== false,
                createBaseClient: (logger) => new GenericACPAgentClient({
                    logger,
                    command: override.command,
                    env: override.env,
                }),
            });
            continue;
        }
        const baseProvider = resolvedProviders.get(override.extends);
        if (!baseProvider) {
            throw new Error(`Custom provider '${providerId}' extends unknown provider '${override.extends}'`);
        }
        const mergedRuntimeSettings = mergeRuntimeSettings(baseProvider.runtimeSettings, toRuntimeSettings(override));
        const baseDefinition = baseProvider.definition;
        const baseFactory = getProviderClientFactory(override.extends);
        resolvedProviders.set(providerId, {
            definition: createDerivedDefinition(providerId, baseDefinition, override),
            runtimeSettings: mergedRuntimeSettings,
            profileModels: override.models ?? [],
            enabled: override.enabled !== false,
            createBaseClient: (logger) => baseFactory(logger, mergedRuntimeSettings),
        });
    }
}
export function buildProviderRegistry(logger, options) {
    const runtimeSettings = options?.runtimeSettings;
    const providerOverrides = options?.providerOverrides ?? {};
    const resolvedProviders = buildResolvedBuiltinProviders(providerOverrides, runtimeSettings);
    addDerivedProviders(resolvedProviders, providerOverrides);
    return Object.fromEntries([...resolvedProviders.entries()]
        .filter(([, resolved]) => resolved.enabled)
        .map(([provider, resolved]) => [provider, createRegistryEntry(logger, provider, resolved)]));
}
export function getProviderIds(registry) {
    return Object.keys(registry);
}
// Deprecated: Use buildProviderRegistry instead
export const PROVIDER_REGISTRY = null;
export function createAllClients(logger, options) {
    const registry = buildProviderRegistry(logger, options);
    return Object.fromEntries(Object.entries(registry).map(([provider, definition]) => [
        provider,
        definition.createClient(logger),
    ]));
}
export async function shutdownProviders(logger, options) {
    await OpenCodeServerManager.getInstance(logger, options?.runtimeSettings?.opencode).shutdown();
}
//# sourceMappingURL=provider-registry.js.map