import OpenAI from 'openai';
import { Agent, hostedMcpTool, MCPServerStdio, OpenAIProvider, setDefaultModelProvider, setDefaultOpenAIClient, setDefaultOpenAIKey, setOpenAIAPI, tool, addTraceProcessor, getGlobalTraceProvider, setTracingExportApiKey, createMCPToolStaticFilter } from '@openai/agents';
import { ATTACHMENT_TOOLS_PREAMBLE } from '../../';
const TRACE_LOG_PREFIX = '[OpenAI Trace]';
const toSerializable = (value) => {
    if (typeof value.toJSON === 'function') {
        const json = value.toJSON();
        if (json) {
            return json;
        }
    }
    const fallback = {};
    for (const key of Object.keys(value)) {
        const item = value[key];
        if (typeof item === 'function') {
            continue;
        }
        fallback[key] = item;
    }
    return fallback;
};
const logTrace = (stage, trace) => {
    const payload = {
        traceId: trace.traceId,
        name: trace.name,
        groupId: trace.groupId,
        metadata: trace.metadata,
        raw: toSerializable(trace)
    };
    console.log(`${TRACE_LOG_PREFIX} ${stage}`, payload);
};
const logSpan = (stage, span) => {
    const payload = {
        traceId: span.traceId,
        spanId: span.spanId,
        parentId: span.parentId,
        startedAt: span.startedAt,
        endedAt: span.endedAt,
        data: span.spanData,
        error: span.error,
        raw: toSerializable(span)
    };
    console.log(`${TRACE_LOG_PREFIX} ${stage}`, payload);
};
const consoleLogTrace = {
    start() {
        console.log(`${TRACE_LOG_PREFIX} processor attached`);
    },
    async onTraceStart(trace) {
        logTrace('trace:start', trace);
    },
    async onTraceEnd(trace) {
        logTrace('trace:end', trace);
    },
    async onSpanStart(span) {
        logSpan('span:start', span);
    },
    async onSpanEnd(span) {
        logSpan('span:end', span);
    },
    async shutdown() {
        console.log(`${TRACE_LOG_PREFIX} processor shutdown`);
    },
    async forceFlush() {
        console.log(`${TRACE_LOG_PREFIX} force flush noop`);
    }
};
let tracingProcessorRegistered = false;
let tracingForcedFlushWarningLogged = false;
const isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
const coercePositiveInteger = (value) => {
    if (value === undefined || value === null) {
        return undefined;
    }
    const numeric = typeof value === 'string' ? Number(value.trim()) : Number(value);
    if (!Number.isFinite(numeric) || numeric <= 0) {
        return undefined;
    }
    return Math.round(numeric);
};
const normalizeModelSettings = (modelName, rawSettings) => {
    if (!rawSettings) {
        return undefined;
    }
    const normalized = { ...rawSettings };
    const modelId = typeof modelName === 'string' ? modelName.trim().toLowerCase() : '';
    const isGpt5 = modelId.startsWith('gpt-5');
    const applyReasoningEffort = () => {
        const effort = typeof normalized.reasoningEffort === 'string' ? normalized.reasoningEffort.trim() : undefined;
        if (!effort) {
            if (isPlainObject(normalized.reasoning)) {
                normalized.reasoning = { ...normalized.reasoning };
            }
            return;
        }
        const base = isPlainObject(normalized.reasoning) ? { ...normalized.reasoning } : {};
        base.effort = effort;
        normalized.reasoning = base;
    };
    const applyTextVerbosity = () => {
        const verbosity = typeof normalized.textVerbosity === 'string' ? normalized.textVerbosity.trim() : undefined;
        if (!verbosity) {
            if (isPlainObject(normalized.text)) {
                normalized.text = { ...normalized.text };
            }
            return;
        }
        const base = isPlainObject(normalized.text) ? { ...normalized.text } : {};
        base.verbosity = verbosity;
        normalized.text = base;
    };
    applyReasoningEffort();
    applyTextVerbosity();
    delete normalized.reasoningEffort;
    delete normalized.textVerbosity;
    const maxTokens = coercePositiveInteger(normalized.maxTokens);
    if (maxTokens !== undefined) {
        normalized.maxTokens = maxTokens;
    }
    else {
        delete normalized.maxTokens;
    }
    if (isGpt5) {
        delete normalized.temperature;
        delete normalized.topP;
    }
    return normalized;
};
const normalizeToolPermissions = (preferences) => {
    if (!preferences) {
        return [];
    }
    return Object.entries(preferences);
};
const isLikelyPrivateNetwork = (url) => {
    if (typeof url !== 'string') {
        return true;
    }
    const trimmed = url.trim();
    if (trimmed.length === 0) {
        return true;
    }
    try {
        const parsed = new URL(trimmed);
        const hostname = parsed.hostname.toLowerCase();
        if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1') {
            return true;
        }
        if (hostname.endsWith('.local')) {
            return true;
        }
        if (/^10\./.test(hostname) || /^192\.168\./.test(hostname) || /^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(hostname)) {
            return true;
        }
        return false;
    }
    catch {
        return true;
    }
};
const warnIfInaccessibleMcpServer = (serverId, serverUrl) => {
    const accessible = !isLikelyPrivateNetwork(serverUrl);
    if (!accessible) {
        console.warn(`MCP server "${serverId}" uses a URL that is likely inaccessible to OpenAI hosted models (${serverUrl ?? 'missing URL'}).` +
            ' GPT-5 will fail when it cannot reach the server dependency. Expose the server over a public HTTPS endpoint or disable it for this model.');
    }
    return accessible;
};
const normalizeServerLabel = (id) => {
    const raw = typeof id === 'string' ? id.trim() : '';
    if (raw.length === 0) {
        return 'mcp_default';
    }
    const withoutPrefix = raw.replace(/^(mcp[_-])/, '');
    return `mcp_${withoutPrefix}`;
};
let attachmentToolDefinitionsResolver = null;
let currentOpenAIClient = null;
let currentOpenAIProvider = null;
let currentOpenAIProviderOptions = null;
export const getCurrentOpenAIClient = () => currentOpenAIClient;
export const getCurrentOpenAIProvider = () => currentOpenAIProvider;
export const getCurrentOpenAIProviderOptions = () => {
    if (!currentOpenAIProviderOptions) {
        return null;
    }
    return { ...currentOpenAIProviderOptions };
};
export const setAttachmentToolDefinitionsResolver = (resolver) => {
    attachmentToolDefinitionsResolver = resolver;
};
export class OpenAIChatAgent {
    constructor(props, resolveAttachmentTools) {
        Object.defineProperty(this, "options", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "stdioServerConfigs", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "stdioMcpServers", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "stdioConnectPromise", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        Object.defineProperty(this, "agentFactory", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: void 0
        });
        Object.defineProperty(this, "agentInstance", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        Object.defineProperty(this, "nodeMcpServerCtor", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        Object.defineProperty(this, "nodeMcpServerCtorPromise", {
            enumerable: true,
            configurable: true,
            writable: true,
            value: null
        });
        const normalizedModelSettings = normalizeModelSettings(props.modelName, props.modelSettings);
        const resolvedOptions = {
            ...props,
            ...(normalizedModelSettings !== undefined ? { modelSettings: normalizedModelSettings } : {})
        };
        console.log('Creating ChatAgent with options:', resolvedOptions);
        console.log('Resolved MCP servers for agent:', resolvedOptions.mcpServers);
        const resolver = resolveAttachmentTools ?? attachmentToolDefinitionsResolver;
        if (!resolver) {
            throw new Error('Attachment tool definitions resolver is not configured. Ensure the OpenAI provider plugin was registered with the playground.');
        }
        const allServers = resolvedOptions.mcpServers ?? [];
        const modelId = typeof resolvedOptions.modelName === 'string' ? resolvedOptions.modelName.trim().toLowerCase() : '';
        const requiresPublicMcpServers = modelId.startsWith('gpt-5');
        const unreachableServers = [];
        // Separate stdio servers from hosted servers
        const stdioServers = allServers.filter((server) => {
            const isStdio = server.options.transportMode === 'stdio';
            return isStdio && (server.options.serverEnabled ?? true);
        });
        const hostedServers = allServers.filter((server) => {
            const isHosted = server.options.transportMode !== 'stdio';
            return isHosted;
        });
        const enabledServers = hostedServers.filter((server) => {
            const isEnabled = server.options.serverEnabled ?? true;
            if (!isEnabled) {
                return false;
            }
            const serverUrl = typeof server.options.url === 'string' ? server.options.url.trim() : '';
            const connectorId = typeof server.options.connectorId === 'string'
                ? server.options.connectorId?.trim() ?? ''
                : '';
            if (serverUrl.length === 0 && connectorId.length === 0) {
                console.warn(`Skipping MCP server "${server.options.serverName ?? server.id}" because it is missing both a server URL and connector id.`);
                return false;
            }
            const accessible = serverUrl.length > 0 ? warnIfInaccessibleMcpServer(server.id, serverUrl) : true;
            if (!accessible && requiresPublicMcpServers) {
                unreachableServers.push({
                    id: server.id,
                    name: server.options.serverName,
                    url: serverUrl
                });
                return false;
            }
            return true;
        });
        if (requiresPublicMcpServers && unreachableServers.length > 0) {
            const serverSummary = unreachableServers
                .map((entry) => {
                const label = entry.name && entry.name.trim().length > 0 ? entry.name : entry.id;
                const url = entry.url ?? 'missing URL';
                return `• ${label} (${url})`;
            })
                .join('\n');
            throw new Error('GPT-5 runs on OpenAI-hosted infrastructure and cannot reach MCP servers on private networks. ' +
                'Update these servers to use a publicly accessible HTTPS endpoint or disable them before invoking GPT-5:\n' +
                serverSummary);
        }
        const askFirstSummaries = [];
        const mcpTools = enabledServers.map((server) => {
            const permissions = normalizeToolPermissions(server.options.toolPreferences);
            const allowedTools = permissions
                .filter(([, permission]) => permission !== 'disabled')
                .map(([name]) => name);
            const askFirstTools = permissions
                .filter(([, permission]) => permission === 'ask_first')
                .map(([name]) => name);
            if (askFirstTools.length > 0) {
                askFirstSummaries.push({
                    serverLabel: server.options.serverName ?? server.id,
                    tools: askFirstTools
                });
            }
            console.log(`MCP Server "${server.options.serverName}" allowed tools:`, allowedTools);
            if (askFirstTools.length > 0) {
                console.log(`MCP Server "${server.options.serverName}" tools requiring approval:`, askFirstTools);
            }
            const serverLabel = normalizeServerLabel(server.id);
            if (serverLabel !== server.id) {
                console.log(`Using normalized MCP server label "${serverLabel}" for server id "${server.id}"`);
            }
            const serverUrl = typeof server.options.url === 'string' ? server.options.url.trim() : '';
            const connectorId = typeof server.options.connectorId === 'string'
                ? server.options.connectorId?.trim() ?? ''
                : '';
            const baseOptions = {
                serverLabel,
                ...(serverUrl.length > 0 ? { serverUrl } : {}),
                ...(connectorId.length > 0 ? { connectorId } : {}),
                headers: typeof server.options.headers === 'function' ? undefined : server.options.headers,
                ...(allowedTools.length > 0 ? { allowedTools } : {})
            };
            const authorization = server.options.authorization;
            if (authorization !== undefined) {
                ;
                baseOptions.authorization = authorization;
            }
            if (askFirstTools.length > 0) {
                return hostedMcpTool({
                    ...baseOptions,
                    requireApproval: {
                        always: {
                            toolNames: askFirstTools
                        }
                    }
                });
            }
            return hostedMcpTool(baseOptions);
        });
        const attachmentToolDefinitions = resolver();
        const attachmentTools = attachmentToolDefinitions.map((definition) => {
            const baseOptions = {
                name: definition.name,
                description: definition.description,
                parameters: definition.parameters,
                strict: true,
                async execute(rawInput, runContext) {
                    let parsedInput;
                    if (typeof rawInput === 'string') {
                        try {
                            parsedInput = JSON.parse(rawInput);
                        }
                        catch (error) {
                            console.warn(`Failed to parse input for attachment tool "${definition.name}"`, error);
                            parsedInput = undefined;
                        }
                    }
                    else if (rawInput && typeof rawInput === 'object') {
                        parsedInput = rawInput;
                    }
                    const context = (runContext?.context ?? {});
                    const runtime = {
                        attachments: context.attachments,
                        additionalPrompts: context.additionalPrompts,
                        getAttachmentCache: resolvedOptions.getAttachmentCache
                    };
                    const result = await definition.handler(parsedInput, runtime);
                    return JSON.stringify(result);
                }
            };
            if (definition.needsApproval) {
                return tool({
                    ...baseOptions,
                    needsApproval: definition.needsApproval
                });
            }
            return tool(baseOptions);
        });
        const customTools = (resolvedOptions.additionalTools ?? []).map((definition) => tool(definition));
        const tools = [...attachmentTools, ...mcpTools, ...customTools];
        const stdioServerConfigs = stdioServers
            .map((server) => {
            const stdioConfig = server.options.stdioConfig;
            const rawCommand = typeof stdioConfig?.command === 'string' ? stdioConfig.command.trim() : '';
            if (!rawCommand) {
                console.warn(`Skipping MCP server "${server.options.serverName ?? server.id}" because no stdio command is configured.`);
                return null;
            }
            const rawArgs = Array.isArray(stdioConfig?.args) ? stdioConfig?.args : [];
            const args = rawArgs
                .map((value) => typeof value === 'string' ? value.trim() : '')
                .filter((value) => value.length > 0);
            const envEntries = isPlainObject(stdioConfig?.env)
                ? Object.entries(stdioConfig?.env)
                    .filter((entry) => typeof entry[0] === 'string' && typeof entry[1] === 'string')
                : [];
            const env = envEntries.length > 0 ? Object.fromEntries(envEntries) : undefined;
            const normalizedCommand = rawCommand.trim();
            const commandParts = args.length > 0
                ? [normalizedCommand, ...args]
                : normalizedCommand.split(/\s+/).filter((segment) => segment.length > 0);
            if (commandParts.length === 0) {
                console.warn(`Skipping MCP server "${server.options.serverName ?? server.id}" because the stdio command could not be normalized.`);
                return null;
            }
            const [command, ...normalizedArgs] = commandParts;
            const fullCommand = [command, ...normalizedArgs].join(' ');
            return {
                id: server.id,
                name: server.options.serverName ?? server.id,
                command,
                args: normalizedArgs,
                fullCommand,
                ...(env ? { env } : {}),
                toolPreferences: server.options.toolPreferences
            };
        })
            .filter((candidate) => candidate !== null);
        if (resolvedOptions.apiMode) {
            setOpenAIAPI(resolvedOptions.apiMode);
        }
        const combinedInstructions = [ATTACHMENT_TOOLS_PREAMBLE, resolvedOptions.instructions ?? '']
            .filter((segment) => typeof segment === 'string' && segment.trim().length > 0)
            .join('\n\n');
        const trimmedApiKey = typeof resolvedOptions.apiKey === 'string' ? resolvedOptions.apiKey.trim() : '';
        if (!trimmedApiKey) {
            throw new Error('OpenAI API key is required to initialize the OpenAI chat agent.');
        }
        setTracingExportApiKey(trimmedApiKey);
        const client = createOpenAIClient({
            ...resolvedOptions,
            apiKey: trimmedApiKey
        });
        console.log('Created OpenAI client:', client);
        setDefaultOpenAIKey(trimmedApiKey);
        setDefaultOpenAIClient(client);
        const providerOptions = {
            openAIClient: client
        };
        if (resolvedOptions.apiMode) {
            providerOptions.useResponses = resolvedOptions.apiMode !== 'chat_completions';
        }
        currentOpenAIClient = client;
        currentOpenAIProviderOptions = { ...providerOptions };
        currentOpenAIProvider = new OpenAIProvider(providerOptions);
        setDefaultModelProvider(currentOpenAIProvider);
        const traceProvider = getGlobalTraceProvider();
        traceProvider.setDisabled(false);
        if (!tracingProcessorRegistered) {
            addTraceProcessor(consoleLogTrace);
            tracingProcessorRegistered = true;
        }
        void traceProvider.forceFlush?.().catch((error) => {
            if (!tracingForcedFlushWarningLogged) {
                console.warn('[OpenAI Trace] forceFlush unavailable or failed:', error);
                tracingForcedFlushWarningLogged = true;
            }
        });
        this.options = { ...resolvedOptions };
        this.stdioServerConfigs = stdioServerConfigs;
        this.stdioMcpServers = [];
        this.agentFactory = () => new Agent({
            name: 'Chat Agent',
            instructions: combinedInstructions,
            model: resolvedOptions.modelName,
            modelSettings: resolvedOptions.modelSettings,
            outputType: 'text',
            tools,
            mcpServers: this.stdioMcpServers
        });
        if (this.stdioServerConfigs.length === 0) {
            this.agentInstance = this.agentFactory();
        }
    }
    getAgent() {
        const agent = this.agentInstance;
        if (!agent) {
            throw new Error('OpenAIChatAgent is not initialized. Call ensureMcpServersReady() first.');
        }
        return agent;
    }
    async ensureMcpServersReady() {
        if (this.stdioServerConfigs.length === 0) {
            if (!this.agentInstance) {
                this.agentInstance = this.agentFactory();
            }
            return;
        }
        await this.initializeStdioServers();
        if (this.stdioMcpServers.length === 0) {
            throw new Error('No MCP stdio servers are available after initialization.');
        }
        if (!this.stdioConnectPromise) {
            const connectPromise = Promise.all(this.stdioMcpServers.map(async (server) => {
                try {
                    await server.connect();
                }
                catch (error) {
                    const reason = error instanceof Error ? error.message : String(error);
                    if (typeof reason === 'string' && reason.toLowerCase().includes('not implemented')) {
                        throw new Error(`Failed to connect to MCP server "${server.name}" via stdio: environment does not support stdio transports.
Run the playground in a Node-capable context (such as Electron main/preload or Node.js) and ensure @modelcontextprotocol/sdk is installed.`);
                    }
                    throw new Error(`Failed to connect to MCP server "${server.name}" via stdio: ${reason}`);
                }
            })).then(() => {
                return undefined;
            }).catch((error) => {
                this.stdioConnectPromise = null;
                throw error;
            });
            this.stdioConnectPromise = connectPromise;
        }
        await this.stdioConnectPromise;
        if (!this.agentInstance) {
            this.agentInstance = this.agentFactory();
        }
    }
    async closeMcpServers() {
        if (this.stdioMcpServers.length === 0) {
            this.stdioConnectPromise = null;
            return;
        }
        await Promise.allSettled(this.stdioMcpServers.map(async (server) => {
            try {
                await server.close();
            }
            catch (error) {
                const reason = error instanceof Error ? error.message : String(error);
                console.warn(`Failed to close MCP server "${server.name}": ${reason}`);
            }
        }));
        this.stdioConnectPromise = null;
    }
    async initializeStdioServers() {
        if (this.stdioServerConfigs.length === 0) {
            this.stdioMcpServers = [];
            return;
        }
        if (this.stdioMcpServers.length === this.stdioServerConfigs.length) {
            return;
        }
        const nodeCtor = await this.resolveNodeMcpServerCtor();
        const servers = await Promise.all(this.stdioServerConfigs.map(async (config) => {
            return this.createStdioServerInstance(config, nodeCtor);
        }));
        this.stdioMcpServers = servers;
        this.stdioConnectPromise = null;
    }
    async resolveNodeMcpServerCtor() {
        if (!OpenAIChatAgent.isNodeLikeEnvironment()) {
            return null;
        }
        if (this.nodeMcpServerCtor) {
            return this.nodeMcpServerCtor;
        }
        if (this.nodeMcpServerCtorPromise) {
            return this.nodeMcpServerCtorPromise;
        }
        const loadNodeCtor = async () => {
            const esmCtor = await this.importNodeShim();
            if (esmCtor) {
                return esmCtor;
            }
            const cjsCtor = await this.requireNodeShim();
            if (cjsCtor) {
                return cjsCtor;
            }
            const esmFallback = await this.importNodeMcpServerShim();
            if (esmFallback) {
                return esmFallback;
            }
            const cjsFallback = await this.requireNodeMcpServerShim();
            if (cjsFallback) {
                return cjsFallback;
            }
            console.warn('OpenAIChatAgent could not resolve a Node-compatible MCP stdio implementation. stdio servers will be unavailable.');
            return null;
        };
        this.nodeMcpServerCtorPromise = loadNodeCtor()
            .finally(() => {
            this.nodeMcpServerCtorPromise = null;
        });
        return this.nodeMcpServerCtorPromise;
    }
    async importNodeShim() {
        try {
            const loader = Function('specifier', 'return import(specifier)');
            const module = await loader('@openai/agents-core/_shims');
            if (module && typeof module === 'object') {
                const ctor = module.MCPServerStdio;
                if (typeof ctor === 'function') {
                    this.nodeMcpServerCtor = ctor;
                    console.info('OpenAIChatAgent loaded Node MCP stdio shim via dynamic import');
                    return this.nodeMcpServerCtor;
                }
            }
        }
        catch (error) {
            console.warn('OpenAIChatAgent failed to import Node MCP stdio shim via ESM', error);
        }
        return null;
    }
    async requireNodeShim() {
        try {
            const req = await this.resolveRequireFunction();
            if (!req) {
                return null;
            }
            const module = req('@openai/agents-core/_shims');
            const ctor = module?.MCPServerStdio;
            if (typeof ctor === 'function') {
                this.nodeMcpServerCtor = ctor;
                console.info('OpenAIChatAgent loaded Node MCP stdio shim via require/globalThis.require');
                return this.nodeMcpServerCtor;
            }
        }
        catch (error) {
            console.warn('OpenAIChatAgent failed to load Node MCP stdio shim via require', error);
        }
        return null;
    }
    async resolveRequireFunction() {
        const globalCandidate = typeof globalThis === 'object'
            ? globalThis.require
            : undefined;
        if (typeof globalCandidate === 'function') {
            return globalCandidate;
        }
        const windowCandidate = typeof window !== 'undefined'
            ? window.require
            : undefined;
        if (typeof windowCandidate === 'function') {
            return windowCandidate;
        }
        try {
            const fallback = Function('return typeof require === "function" ? require : undefined')();
            if (typeof fallback === 'function') {
                return fallback;
            }
        }
        catch {
            // ignore and continue
        }
        const processCandidate = typeof process === 'object'
            ? process
            : undefined;
        const mainModuleRequire = processCandidate?.mainModule?.require;
        if (typeof mainModuleRequire === 'function') {
            return mainModuleRequire.bind(processCandidate?.mainModule);
        }
        try {
            const loader = Function('specifier', 'return import(specifier)');
            const module = await loader('node:module');
            if (module && typeof module.createRequire === 'function') {
                const basePath = (() => {
                    if (typeof __filename === 'string') {
                        return __filename;
                    }
                    if (typeof __dirname === 'string') {
                        return `${__dirname}/noop.js`;
                    }
                    if (processCandidate?.cwd) {
                        return `${processCandidate.cwd()}/noop.js`;
                    }
                    return '/noop.js';
                })();
                return module.createRequire(basePath);
            }
        }
        catch (error) {
            console.warn('OpenAIChatAgent failed to obtain createRequire via node:module', error);
        }
        return null;
    }
    async importNodeMcpServerShim() {
        try {
            const loader = Function('specifier', 'return import(specifier)');
            const module = await loader('@openai/agents-core/_shims');
            if (module && typeof module === 'object') {
                const ctor = module.NodeMCPServerStdio
                    ?? module.MCPServerStdio;
                if (typeof ctor === 'function') {
                    this.nodeMcpServerCtor = ctor;
                    console.info('OpenAIChatAgent loaded Node MCP server shim via direct dynamic import');
                    return this.nodeMcpServerCtor;
                }
            }
        }
        catch (error) {
            console.warn('OpenAIChatAgent failed to import Node MCP server shim via ESM fallback', error);
        }
        return null;
    }
    async requireNodeMcpServerShim() {
        try {
            const req = await this.resolveRequireFunction();
            if (!req) {
                return null;
            }
            const module = req('@openai/agents-core/_shims');
            const ctor = module?.NodeMCPServerStdio ?? module?.MCPServerStdio;
            if (typeof ctor === 'function') {
                this.nodeMcpServerCtor = ctor;
                console.info('OpenAIChatAgent loaded Node MCP server shim via require fallback');
                return this.nodeMcpServerCtor;
            }
        }
        catch (error) {
            console.warn('OpenAIChatAgent failed to load Node MCP server shim via require fallback', error);
        }
        return null;
    }
    async createStdioServerInstance(config, nodeCtor) {
        const { name, command, args, fullCommand, env, toolPreferences } = config;
        // Build tool filter from preferences
        let toolFilter;
        if (toolPreferences) {
            const permissions = normalizeToolPermissions(toolPreferences);
            const allowed = [];
            const blocked = [];
            for (const [toolName, permission] of permissions) {
                if (permission === 'disabled') {
                    blocked.push(toolName);
                }
                else {
                    // 'enabled' and 'ask_first' are both allowed for stdio
                    // (stdio doesn't support approval flow, so ask_first becomes enabled)
                    allowed.push(toolName);
                }
            }
            // Only create filter if we have explicit permissions
            if (allowed.length > 0 || blocked.length > 0) {
                toolFilter = createMCPToolStaticFilter({
                    ...(allowed.length > 0 ? { allowed } : {}),
                    ...(blocked.length > 0 ? { blocked } : {})
                });
                // Log the filtering
                if (allowed.length > 0) {
                    console.log(`MCP STDIO Server "${name}" allowed tools:`, allowed);
                }
                if (blocked.length > 0) {
                    console.log(`MCP STDIO Server "${name}" blocked tools:`, blocked);
                }
            }
        }
        if (nodeCtor) {
            let normalizedCommand = command;
            let normalizedArgs = args;
            if (normalizedArgs.length === 0) {
                const segments = command.split(/\s+/).filter((segment) => segment.length > 0);
                if (segments.length > 1) {
                    normalizedCommand = segments.shift() ?? command;
                    normalizedArgs = segments;
                }
            }
            const nodeOptions = {
                name,
                command: normalizedCommand,
                ...(normalizedArgs.length > 0 ? { args: normalizedArgs } : {}),
                ...(toolFilter ? { toolFilter } : {})
            };
            if (env && Object.keys(env).length > 0) {
                nodeOptions.env = env;
            }
            return new nodeCtor(nodeOptions);
        }
        const fallbackOptions = {
            name,
            fullCommand,
            ...(args.length > 0 ? { args } : {}),
            ...(toolFilter ? { toolFilter } : {})
        };
        if (env && Object.keys(env).length > 0) {
            fallbackOptions.env = env;
        }
        return new MCPServerStdio(fallbackOptions);
    }
    static isNodeLikeEnvironment() {
        if (typeof process !== 'undefined' && !!process.versions?.node) {
            return true;
        }
        const windowRequire = typeof window !== 'undefined'
            ? window.require
            : undefined;
        if (typeof windowRequire === 'function') {
            return true;
        }
        if (typeof process !== 'undefined' && typeof process.type === 'string') {
            return true;
        }
        return false;
    }
}
export const normalizeBaseUrl = (explicitBaseUrl, connection) => {
    const candidates = [explicitBaseUrl];
    if (connection) {
        candidates.push(connection['baseUrl'], connection['baseURL']);
    }
    for (const candidate of candidates) {
        if (typeof candidate === 'string' && candidate.trim().length > 0) {
            return candidate.trim();
        }
    }
    return undefined;
};
export const normalizeClientHeaders = (headers) => {
    if (!headers) {
        return undefined;
    }
    const entries = Object.entries(headers)
        .map(([key, value]) => [key.trim(), value])
        .filter(([key, value]) => key.length > 0 && typeof value === 'string');
    if (entries.length === 0) {
        return undefined;
    }
    return Object.fromEntries(entries);
};
export const createOpenAIClient = (options) => {
    const baseUrl = normalizeBaseUrl(options.baseUrl, options.connection);
    const clientHeaders = normalizeClientHeaders(options.clientHeaders);
    const opts = {
        apiKey: options.apiKey,
        dangerouslyAllowBrowser: true,
        ...(baseUrl ? { baseURL: baseUrl } : {}),
        ...(clientHeaders ? { defaultHeaders: clientHeaders } : {}),
        ...(options.logLevel ? { logLevel: options.logLevel } : {})
    };
    return new OpenAI(opts);
};
