UNPKG

@microsoft/teams.apps

Version:

<p> <a href="https://www.npmjs.com/package/@microsoft/teams.apps" target="_blank"> <img src="https://img.shields.io/npm/v/@microsoft/teams.apps/latest" /> </a> <a href="https://www.npmjs.com/package/@microsoft/teams.apps?activeTab=code

713 lines • 55.1 kB
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.App = void 0;
const axios_1 = require("axios");
const teams_api_1 = require("@microsoft/teams.api");
const teams_common_1 = require("@microsoft/teams.common");
const package_json_1 = __importDefault(require("../package.json"));
const activity_sender_1 = require("./activity-sender");
const api_1 = require("./api");
const app_events_1 = require("./app.events");
const app_plugins_1 = require("./app.plugins");
const app_process_1 = require("./app.process");
const container_1 = require("./container");
const contexts_1 = require("./contexts");
const http_1 = require("./http");
const http_server_1 = require("./http/http-server");
const middleware = __importStar(require("./middleware"));
const remote_function_validator_1 = require("./middleware/auth/remote-function-validator");
const oauth_1 = require("./oauth");
const registry_1 = require("./oauth/registry");
const router_1 = require("./router");
const socket_mode_1 = require("./socket-mode");
const state_1 = require("./state");
const loader_1 = require("./state/loader");
const token_manager_1 = require("./token-manager");
const token_provider_1 = require("./token-provider");
const env_1 = require("./utils/env");
function isAppSendOptions(value) {
    if (typeof value === 'string')
        return false;
    return !('type' in value);
}
/**
 * The orchestrator for receiving/sending activities
 */
class App {
    options;
    api;
    cloud;
    graph;
    log;
    server;
    /**
     * **Experimental.** The Socket Mode inbound transport, present only when the
     * app was constructed with `socketMode` enabled. It is the same
     * {@link IHttpServerAdapter} instance {@link App.server} runs on. Use it to
     * observe the socket lifecycle
     * (`app.socketMode.status`, `app.socketMode.geoStatuses`, `app.socketMode.events`).
     * WebSocket is only recommended for use when developing agents.
     *
     * @experimental This API is in preview and may change in the future.
     */
    socketMode;
    http;
    client;
    /**
     * The app's legacy shared storage instance.
     *
     * @deprecated Use `ctx.state` for turn state. Applications that need general
     * persistence should own and use their storage provider directly.
     */
    storage;
    entraTokenValidator;
    /**
     * Graph API base URL derived from the configured cloud's `graphScope`.
     * Undefined when the scope isn't a URL — `GraphClient` then uses its public-cloud default.
     * Shared across every `GraphClient` the app constructs (`app.graph`, `ctx.appGraph`, `ctx.userGraph`)
     * so sovereign customers get consistent routing.
     */
    graphBaseUrl;
    /**
     * the apps credentials
     */
    get credentials() {
        return this.tokenManager.credentials;
    }
    /**
     * The app's token source, for acquiring a token for something the SDK does not
     * call for you, such as an OpenTelemetry exporter.
     */
    get tokenProvider() {
        return this._tokenProvider;
    }
    /**
     * the apps id
     */
    get id() {
        return this.credentials?.clientId;
    }
    get oauth() {
        return {
            ...oauth_1.DEFAULT_OAUTH_SETTINGS,
            ...this.options.oauth,
        };
    }
    container = new container_1.Container();
    pluginManager;
    router = new router_1.Router();
    tenantTokens = new teams_common_1.LocalStorage({}, { max: 20000 });
    events;
    isInitialized = false;
    port;
    activitySender;
    /**
     * The concrete token machinery: MSAL clients, credential resolution, and the
     * per-grant acquisition logic. Private because {@link App.tokenProvider} is
     * the supported way in.
     */
    tokenManager;
    _tokenProvider;
    stateLoader;
    eventManager;
    activityProcessor;
    oauthFlowRegistry;
    _userAgent = `teams.ts[apps]/${package_json_1.default.version}`;
    constructor(options = {}) {
        this.options = options;
        this.log = this.options.logger || new teams_common_1.ConsoleLogger('@teams/app');
        this.events = new teams_common_1.EventEmitter(this.log.child('events'));
        this.storage = this.options.storage || new teams_common_1.LocalStorage();
        const hasConfiguredOAuthFlows = (this.options.oauthFlows?.length ?? 0) > 0;
        if (hasConfiguredOAuthFlows &&
            this.options.oauth?.defaultConnectionName !== undefined) {
            throw new Error('oauth.defaultConnectionName cannot be combined with registered OAuth flows. ' +
                'Remove defaultConnectionName and name the connection when calling OAuth helpers.');
        }
        this.stateLoader = (0, state_1.createStateLoader)(this.options.state, this.log);
        // Resolve cloud environment from options or CLOUD env var
        const cloudEnvName = typeof process !== 'undefined' ? process.env.CLOUD : undefined;
        this.cloud = this.options.cloud ?? (cloudEnvName ? (0, teams_api_1.cloudFromName)(cloudEnvName) : teams_api_1.PUBLIC);
        if (!options.client) {
            this.client = new teams_common_1.Client({
                headers: {
                    'User-Agent': this._userAgent,
                },
            });
        }
        else if (typeof options.client === 'function') {
            this.client = options.client().clone({
                headers: {
                    'User-Agent': this._userAgent,
                },
            });
        }
        else if ('request' in options.client) {
            this.client = options.client.clone({
                headers: {
                    'User-Agent': this._userAgent,
                },
            });
        }
        else {
            this.client = new teams_common_1.Client(options.client).clone({
                headers: {
                    'User-Agent': this._userAgent,
                },
            });
        }
        // Derive Graph API base URL from the cloud's graphScope (e.g. "https://graph.microsoft.us/.default"
        // -> "https://graph.microsoft.us"). Falls back to the public Graph endpoint inside GraphClient if
        // the scope isn't a URL (custom delegated scope, empty, etc.).
        const graphUrlMatch = /^(https?:\/\/[^/]+)/i.exec((this.cloud.graphScope ?? '').trim());
        this.graphBaseUrl = graphUrlMatch?.[1];
        if (!this.graphBaseUrl && this.cloud.graphScope) {
            this.log.warn(`graphScope "${this.cloud.graphScope}" is not a URL; Graph calls will route to the public cloud. ` +
                'Set graphScope to an "https://<host>/.default" value to route to the correct Graph endpoint.');
        }
        this.graph = new api_1.GraphClient(this.client.clone({ token: async () => (await this.getAppGraphToken()) ?? undefined }), { baseUrlRoot: this.graphBaseUrl });
        this.tokenManager = new token_manager_1.TokenManager({
            clientId: this.options.clientId,
            clientSecret: this.options.clientSecret,
            tenantId: this.options.tenantId,
            token: this.options.token,
            managedIdentityClientId: this.options.managedIdentityClientId,
            cloud: this.cloud,
        }, this.log);
        this._tokenProvider = new token_provider_1.AppTokenProvider(this.tokenManager, this.cloud);
        const serviceUrl = (this.options.serviceUrl ?? process.env.SERVICE_URL ??
            'https://smba.trafficmanager.net/teams').replace(/\/+$/, '');
        const settings = {
            ...this.options.apiClientSettings,
            cloud: this.cloud,
            tokenProvider: this.tokenProvider,
        };
        this.api = new api_1.ApiClient(serviceUrl, this.client.clone(), settings);
        // initialize ActivitySender for sending activities
        this.activitySender = new activity_sender_1.ActivitySender(this.log, (senderServiceUrl, agenticIdentity) => this.api.clone({
            serviceUrl: senderServiceUrl,
            agenticIdentity,
        }));
        // initialize the activity pipeline collaborators. App owns these and passes
        // in what they need (rather than them reaching into App via `this`), which
        // keeps the primitives above private.
        this.pluginManager = new app_plugins_1.PluginManager({
            container: this.container,
            log: this.log,
            handlers: {
                onError: (event) => this.eventManager.onError(event),
                onActivity: (event) => this.onActivity(event),
                emit: (name, event) => this.events.emit(name, event),
            },
        });
        this.eventManager = new app_events_1.EventManager(this.events, this.pluginManager.plugins);
        this.activityProcessor = new app_process_1.ActivityProcessor({
            router: this.router,
            plugins: this.pluginManager.plugins,
            eventManager: this.eventManager,
            getAppGraphToken: (tenantId) => this.getAppGraphToken(tenantId),
            getAgenticGraphToken: (identity, tenantId) => this.getAgenticGraphToken(identity, tenantId),
            activitySender: this.activitySender,
            api: this.api,
            client: this.client,
            storage: this.storage,
            getStateLoader: () => this.stateLoader,
            log: this.log,
            getId: () => this.id,
            getConnectionName: () => this.oauth.defaultConnectionName,
            shouldFetchUserToken: () => this.shouldFetchUserToken(),
            validateOAuthConnection: (connectionName, connectionNameProvided) => this.oauthFlowRegistry.validate(connectionName, connectionNameProvided),
            onOAuthSignInInitiated: (context, connectionName, supportsSso) => this.oauthFlowRegistry.recordPending(context, connectionName, supportsSso),
            getOAuthConnectionStatus: context => this.oauthFlowRegistry.getConnectionStatus(context),
            apiClientSettings: this.options.apiClientSettings,
            graphBaseUrl: this.graphBaseUrl,
            agent365Baggage: this.options.telemetry?.agent365,
        });
        if (this.credentials?.clientId) {
            this.entraTokenValidator = middleware.createEntraTokenValidator(this.credentials.tenantId || 'common', this.credentials.clientId, { applicationIdUri: this.options.applicationIdUri, loginEndpoint: this.cloud.loginEndpoint, logger: this.log });
        }
        // Determine HTTP server
        const plugins = this.options.plugins || [];
        const httpPlugin = app_plugins_1.PluginManager.findHttpPlugin(plugins);
        // Error if both httpServerAdapter and http plugin are provided
        if (this.options.httpServerAdapter && httpPlugin) {
            throw new Error('Cannot provide both httpServerAdapter option and HttpPlugin in plugins array. ' +
                'Use either:\n' +
                '  - new App({ httpServerAdapter: new ExpressAdapter() }) (recommended)\n' +
                '  - new App({ plugins: [new HttpPlugin()] }) (deprecated)');
        }
        // The deprecated HttpPlugin is a full HTTP server and can't coexist with
        // Socket Mode, which is the app's exclusive inbound transport when enabled.
        if (this.options.socketMode && httpPlugin) {
            throw new Error('Cannot provide both socketMode and an HttpPlugin: Socket Mode manages its own ' +
                'inbound transport. Enable one or the other.');
        }
        let server;
        // HttpPlugin in plugins array (backwards compatibility)
        if (httpPlugin) {
            this.log.warn('[DEPRECATED] HttpPlugin in plugins array will be deprecated. Use httpServerAdapter option instead:\n' +
                '  new App({ httpServerAdapter: new ExpressAdapter() })');
            this.http = httpPlugin;
            // Extract internal server and always set this.server
            server = httpPlugin.asServer?.();
            if (!server) {
                throw new Error('HttpPlugin.asServer() returned undefined');
            }
        }
        else if (this.options.socketMode) {
            const built = this.buildSocketMode();
            server = built.server;
            this.socketMode = built.socketMode;
        }
        else {
            let dangerouslyAllowUnauthenticatedRequests = this.options.dangerouslyAllowUnauthenticatedRequests;
            if (dangerouslyAllowUnauthenticatedRequests === undefined && this.options.skipAuth !== undefined) {
                this.log.warn('[DEPRECATED] skipAuth is deprecated. Use dangerouslyAllowUnauthenticatedRequests instead.');
                dangerouslyAllowUnauthenticatedRequests = this.options.skipAuth;
            }
            if (dangerouslyAllowUnauthenticatedRequests === undefined) {
                const unauthenticatedRequestsEnvValue = (0, env_1.getBooleanEnvValue)('DANGEROUSLY_ALLOW_UNAUTHENTICATED_REQUESTS');
                if (unauthenticatedRequestsEnvValue !== undefined) {
                    this.log.warn('DANGEROUSLY_ALLOW_UNAUTHENTICATED_REQUESTS is set. ' +
                        'Unauthenticated request behavior is configured by the environment.');
                    dangerouslyAllowUnauthenticatedRequests = unauthenticatedRequestsEnvValue;
                }
            }
            dangerouslyAllowUnauthenticatedRequests ??= false;
            server = new http_server_1.HttpServer(this.options.httpServerAdapter ?? new http_1.ExpressAdapter(undefined, {
                logger: this.log,
                onError: (err) => this.eventManager.onError({ error: err })
            }), {
                dangerouslyAllowUnauthenticatedRequests,
                logger: this.log,
                messagingEndpoint: this.options.messagingEndpoint ?? '/api/messages',
            });
        }
        // Always set this.server
        this.server = server;
        // Set callback for handling activities
        server.onRequest = (event) => this.onActivity(event);
        // add injectable items to container
        this.container.register('ILogger', { useValue: this.log });
        this.container.register('IStorage', { useValue: this.storage });
        // Register HTTP server for plugins that need HTTP capabilities
        this.container.register('IHttpServer', { useValue: server });
        // Register all plugins (including HttpPlugin if using old way)
        for (const plugin of plugins) {
            this.plugin(plugin);
        }
        if (this.options.activity?.mentions?.stripText) {
            const options = this.options.activity?.mentions?.stripText;
            this.use(middleware.stripMentionsText(typeof options === 'boolean' ? {} : options));
        }
        this.oauthFlowRegistry = new registry_1.OAuthFlowRegistry({
            defaultConnectionName: hasConfiguredOAuthFlows
                ? undefined
                : this.oauth.defaultConnectionName,
            router: this.router,
            client: this.client,
            events: this.events,
            graphBaseUrl: this.graphBaseUrl,
        });
        for (const connectionName of this.options.oauthFlows ?? []) {
            this.addOAuthFlow(connectionName);
        }
        this.event('error', ({ error }) => {
            this.log.error(error.message);
            if (error instanceof axios_1.AxiosError) {
                this.log.error(error.request.path);
                this.log.error(error.response?.data);
            }
        });
    }
    /**
     * initialize the app.
     */
    async initialize() {
        if (this.isInitialized) {
            return;
        }
        // initialize plugins
        await this.pluginManager.init();
        // initialize server
        await this.server.initialize({
            credentials: this.credentials,
            cloud: this.cloud,
        });
        this.isInitialized = true;
    }
    /**
     * start the server after initialization
     * @param port port to listen on
     */
    async start(port) {
        this.port = port || process.env.PORT || 3978;
        try {
            await this.initialize();
            // Start plugins
            await this.pluginManager.start({ port: this.port });
            this.events.emit('start', this.log);
            // Start HTTP server
            await this.server.start(this.port);
        }
        catch (error) {
            await this.stop();
            const reportError = this.eventManager.onError({ error });
            if (this.socketMode) {
                await reportError;
                throw error;
            }
        }
    }
    /**
     * stop the app
     */
    async stop() {
        try {
            // Stop plugins
            await this.pluginManager.stop();
            // Stop HTTP server
            await this.server.stop();
        }
        catch (error) {
            this.eventManager.onError({ error });
        }
    }
    async send(conversationId, activity, options) {
        return this.sendActivity(conversationId, activity, options);
    }
    // Implementation shared by the three-argument form and the legacy two-argument form.
    async reply(conversationId, messageId, activity, options) {
        if (typeof messageId === 'string' && activity !== undefined && !isAppSendOptions(activity)) {
            if (!conversationId || conversationId.trim() === '') {
                throw new Error('conversationId must be a non-empty string');
            }
            if (messageId.trim() === '') {
                throw new Error('messageId must be a non-empty string');
            }
            return this.sendActivity(conversationId, activity, options, messageId);
        }
        const opts = activity && isAppSendOptions(activity) ? activity : options;
        return this.send(conversationId, messageId, opts);
    }
    /**
     * Create an AgenticIdentity for scoped proactive sends and API clients.
     *
     * AgenticIdentity is the SDK operation/request scope for Agent 365. This
     * helper fills the required blueprint and tenant identifiers from app
     * configuration while allowing app/user IDs to be omitted or set to `null`
     * when the operation is not scoped to a concrete agentic app or user.
     *
     * @param options identity fields and optional overrides
     */
    getAgenticIdentity(options = {}) {
        const tenantId = options.tenantId ?? this.credentials?.tenantId ?? this.options.tenantId;
        if (!tenantId) {
            throw new Error('tenantId is required to get an AgenticIdentity');
        }
        const agenticAppBlueprintId = options.agenticAppBlueprintId ?? this.id;
        if (!agenticAppBlueprintId) {
            throw new Error('agenticAppBlueprintId is required to get an AgenticIdentity');
        }
        return {
            agenticAppBlueprintId,
            agenticAppId: options.agenticAppId,
            agenticUserId: options.agenticUserId,
            tenantId,
        };
    }
    /**
     * Registers an OAuth flow for one Bot Framework OAuth connection.
     *
     * Connection names are matched case-insensitively. Registering the same
     * connection more than once throws. The first registration removes
     * the implicit legacy default. This method cannot be used when
     * `oauth.defaultConnectionName` was configured.
     *
     * @param connectionName OAuth connection name.
     * @param options Optional card defaults for the flow.
     * @returns The registered flow so callbacks can be chained.
     */
    addOAuthFlow(connectionName, options = {}) {
        if (this.options.oauth?.defaultConnectionName !== undefined) {
            throw new Error('oauth.defaultConnectionName cannot be combined with registered OAuth flows. ' +
                'Remove defaultConnectionName and name the connection when calling OAuth helpers.');
        }
        const flow = new oauth_1.OAuthFlow(connectionName, options);
        this.enableOAuthState();
        this.oauthFlowRegistry.add(flow);
        return flow;
    }
    /**
     * Gets the OAuth flow for a connection.
     *
     * The implicit legacy default is available only until the first flow
     * is registered.
     *
     * @param connectionName Connection to resolve.
     * @throws When the connection name is blank or no matching flow is registered.
     */
    getOAuthFlow(connectionName) {
        return this.oauthFlowRegistry.get(connectionName);
    }
    /**
     * subscribe to an event
     * @param name event to subscribe to
     * @param cb callback to invoke
     */
    on(name, cb) {
        this.router.on(name, cb);
        return this;
    }
    /**
     * subscribe to a message event for a specific pattern
     * @param pattern pattern to match against message text
     * @param cb callback to invoke
     */
    message(pattern, cb) {
        this.router.register({
            type: 'user',
            select: (activity) => {
                if (activity.type !== 'message') {
                    return false;
                }
                return new RegExp(pattern).test(activity.text);
            },
            callback: cb,
        });
        return this;
    }
    /**
     * register a middleware
     * @param cb callback to invoke
     */
    use(cb) {
        this.router.use(cb);
        return this;
    }
    /**
     * subscribe to an event
     * @param name the event to subscribe to
     * @param cb the callback to invoke
     */
    event(name, cb) {
        this.events.on(name, cb);
        return this;
    }
    /**
     * add a plugin
     * @param plugin plugin to add
     */
    plugin(plugin) {
        this.pluginManager.add(plugin);
        return this;
    }
    /**
     * get a plugin
     */
    getPlugin(name) {
        return this.pluginManager.get(name);
    }
    function(name, cb) {
        const log = this.log.child('functions').child(name);
        // Create the remote function validator once
        const validator = this.entraTokenValidator
            ? new remote_function_validator_1.RemoteFunctionValidator(this.entraTokenValidator, log)
            : null;
        this.server.registerRoute('POST', `/api/functions/${name}`, async ({ body, headers }) => {
            // Validate JWT token and extract context
            if (!validator) {
                log.debug('unauthorized - no token validator configured');
                return { status: 401, body: 'unauthorized' };
            }
            const context = await validator.check(headers);
            if (!context) {
                return { status: 401, body: 'unauthorized' };
            }
            const ctx = new contexts_1.FunctionContext({
                ...context,
                log,
                api: this.api,
                appGraph: this.graph,
                data: body,
                activitySender: this.activitySender,
                botId: this.id,
            });
            const data = await cb(ctx);
            return { status: 200, body: data };
        });
        return this;
    }
    /**
     * add/update a static tab.
     * the tab will be hosted at
     * `http://localhost:{{PORT}}/tabs/{{name}}` or `https://{{BOT_DOMAIN}}/tabs/{{name}}`
     * @remark scopes default to `personal`
     * @param name A unique identifier for the entity which the tab displays.
     * @param path The path to the web `dist` folder.
     */
    tab(name, path) {
        this.server.serveStatic(`/tabs/${name}`, path);
        return this;
    }
    /**
     * whether any registered route matches the inbound activity
     *
     * Useful for hosts that embed the app behind their own pipeline (e.g. the
     * Microsoft 365 Extension and need to decide whether to hand a turn
     * to this app or let it fall through, without running the activity.
     * @param activity the inbound activity to test against registered routes
     */
    hasMatchingRoute(activity) {
        return this.router.select(activity).length > 0;
    }
    /**
     * activity handler called when an inbound activity is received
     * @param event the received activity event
     */
    process(event) {
        return this.activityProcessor.process(event);
    }
    async onActivity(event) {
        this.eventManager.onActivity(event);
        return await this.process(event);
    }
    ///
    /// Token
    ///
    async getBotToken() {
        return await this.tokenProvider.getAppToken();
    }
    /**
     * Acquires a Graph token for an Agentic User, via the federated identity exchange the token manager already performs.
     *
     * Separate from {@link getAppGraphToken} because the identity differs, not merely the scope: this reads as the agent, so it sees what was shared with the agent rather than everything the app may read.
     */
    async getAgenticGraphToken(identity, tenantId) {
        if (!identity.agenticAppId || !identity.agenticUserId) {
            return null;
        }
        return await this.tokenProvider.getAgenticUserToken(this.cloud.graphScope, identity.agenticAppId, identity.agenticUserId, 
        // The identity's own tenant wins when the platform sends one, then the tenant the activity arrived from.
        // The fallback to the app's configured tenant is deliberately not repeated here: `TokenManager.resolveAgenticTenantId` already applies it, and throws when neither is available, which is a better failure than silently acquiring in the wrong directory.
        identity.tenantId || tenantId);
    }
    async getAppGraphToken(tenantId) {
        // Graph falls back to the `common` tenant rather than the cloud's login
        // tenant, so the tenant is resolved here instead of letting the provider
        // apply its own default.
        return await this.tokenProvider.getAppToken(this.cloud.graphScope, tenantId || this.credentials?.tenantId || token_manager_1.DEFAULT_TENANT_FOR_GRAPH_TOKEN);
    }
    /**
     * Whether deprecated context OAuth fields require an eager token lookup.
     *
     * Registered flows never enable this behavior. An explicit legacy
     * `oauth.fetchUserToken` wins; otherwise lookup is enabled only when the
     * legacy default connection was explicitly configured.
     *
     * @deprecated Registered flows fetch tokens only through `OAuthFlow` methods.
     */
    shouldFetchUserToken() {
        const explicit = this.options.oauth?.fetchUserToken;
        if (explicit !== undefined) {
            return explicit;
        }
        return this.options.oauth?.defaultConnectionName !== undefined;
    }
    async sendActivity(conversationId, activity, options, replyChainId) {
        if (!this.id) {
            throw new Error('App has no credentials set up');
        }
        const params = (0, teams_api_1.toActivityParams)(activity);
        const ref = {
            channelId: 'msteams',
            serviceUrl: this.api.serviceUrl,
            bot: {
                id: this.id,
                role: 'bot',
            },
            conversation: {
                id: conversationId,
            },
        };
        const senderOptions = options?.agenticIdentity || replyChainId
            ? { agenticIdentity: options?.agenticIdentity, replyChainId }
            : undefined;
        return this.activitySender.send(params, ref, senderOptions);
    }
    /**
     * Build the Socket Mode inbound transport and the {@link HttpServer} that runs
     * it. The {@link SocketModeAdapter} is constructed internally so it can reuse
     * the app's credentials, and token provider.
     *
     * Socket Mode is the server's only adapter. A supplied `httpServerAdapter` is
     * intentionally unused, and no HTTP listener or route is created.
     */
    buildSocketMode() {
        if (this.cloud.tokenIssuer !== teams_api_1.PUBLIC.tokenIssuer) {
            throw new Error(`Socket Mode is not supported in this cloud environment (tokenIssuer=${this.cloud.tokenIssuer}). ` +
                'Socket Mode currently supports only regular production clouds. ' +
                'Use the HTTP inbound transport instead.');
        }
        const options = this.options.socketMode === true ? {} : this.options.socketMode;
        const messagingEndpoint = this.options.messagingEndpoint ?? '/api/messages';
        const socketAdapter = new socket_mode_1.SocketModeAdapter(options, {
            credentials: this.credentials,
            client: this.client,
            tokenProvider: this.tokenProvider,
            processActivity: (event) => this.onActivity(event),
            messagingEndpoint,
            onError: (err) => this.eventManager.onError({ error: err }),
            logger: this.log,
        });
        const server = new http_server_1.HttpServer(socketAdapter, {
            logger: this.log,
            messagingEndpoint,
        });
        return { server, socketMode: socketAdapter };
    }
    enableOAuthState() {
        if (this.options.state === false || this.stateLoader) {
            return;
        }
        this.stateLoader = (0, loader_1.createOAuthStateLoader)(this.log);
    }
}
exports.App = App;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2FwcC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxpQ0FBbUM7QUFFbkMsb0RBYThCO0FBQzlCLDBEQVFpQztBQUVqQyxtRUFBa0M7QUFFbEMsdURBQW1EO0FBQ25ELCtCQUErQztBQUMvQyw2Q0FBNEM7QUFjNUMsK0NBQThDO0FBQzlDLCtDQUFrRDtBQUNsRCwyQ0FBd0M7QUFDeEMseUNBQWlGO0FBRWpGLGlDQUF3QztBQUN4QyxvREFBZ0Q7QUFDaEQseURBQTJDO0FBQzNDLDJGQUFzRjtBQUN0RixtQ0FBNEQ7QUFFNUQsK0NBQXFEO0FBRXJELHFDQUFrQztBQUVsQywrQ0FBcUU7QUFDckUsbUNBQTZEO0FBQzdELDJDQUF3RDtBQUN4RCxtREFBK0U7QUFDL0UscURBQXVFO0FBR3ZFLHFDQUFpRDtBQUVqRCxTQUFTLGdCQUFnQixDQUFDLEtBQThEO0lBQ3RGLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQzVDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsQ0FBQztBQUM1QixDQUFDO0FBRUQ7O0dBRUc7QUFDSCxNQUFhLEdBQUc7SUEyRk87SUExRlosR0FBRyxDQUFZO0lBQ2YsS0FBSyxDQUFtQjtJQUN4QixLQUFLLENBQWM7SUFDbkIsR0FBRyxDQUFVO0lBQ2IsTUFBTSxDQUFhO0lBRTVCOzs7Ozs7Ozs7T0FTRztJQUNNLFVBQVUsQ0FBcUI7SUFDL0IsSUFBSSxDQUFjO0lBQ2xCLE1BQU0sQ0FBYTtJQUM1Qjs7Ozs7T0FLRztJQUNNLE9BQU8sQ0FBVztJQUNsQixtQkFBbUIsQ0FBMkI7SUFFdkQ7Ozs7O09BS0c7SUFDTSxZQUFZLENBQVU7SUFFL0I7O09BRUc7SUFDSCxJQUFJLFdBQVc7UUFDYixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDO0lBQ3ZDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFJLGFBQWE7UUFDZixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxFQUFFO1FBQ0osT0FBTyxJQUFJLENBQUMsV0FBVyxFQUFFLFFBQVEsQ0FBQztJQUNwQyxDQUFDO0lBRUQsSUFBSSxLQUFLO1FBQ1AsT0FBTztZQUNMLEdBQUcsOEJBQXNCO1lBQ3pCLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLO1NBQ3RCLENBQUM7SUFDSixDQUFDO0lBRVMsU0FBUyxHQUFHLElBQUkscUJBQVMsRUFBRSxDQUFDO0lBQzVCLGFBQWEsQ0FBeUI7SUFDdEMsTUFBTSxHQUFHLElBQUksZUFBTSxFQUFvQyxDQUFDO0lBQ3hELFlBQVksR0FBRyxJQUFJLDJCQUFZLENBQVMsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDNUQsTUFBTSxDQUFtQztJQUN6QyxhQUFhLEdBQUcsS0FBSyxDQUFDO0lBQ3RCLElBQUksQ0FBbUI7SUFDdkIsY0FBYyxDQUFpQjtJQUV6Qzs7OztPQUlHO0lBQ2MsWUFBWSxDQUFlO0lBRTNCLGNBQWMsQ0FBbUI7SUFDMUMsV0FBVyxDQUFtQjtJQUU5QixZQUFZLENBQXlCO0lBQ3JDLGlCQUFpQixDQUE4QjtJQUN0QyxpQkFBaUIsQ0FBNkI7SUFFOUMsVUFBVSxHQUFHLGtCQUFrQixzQkFBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBRTlELFlBQXFCLFVBQStCLEVBQUU7UUFBakMsWUFBTyxHQUFQLE9BQU8sQ0FBMEI7UUFDcEQsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sSUFBSSxJQUFJLDRCQUFhLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLDJCQUFZLENBQXFCLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDN0UsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxJQUFJLDJCQUFZLEVBQUUsQ0FBQztRQUMxRCxNQUFNLHVCQUF1QixHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUMzRSxJQUNFLHVCQUF1QjtZQUN2QixJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxxQkFBcUIsS0FBSyxTQUFTLEVBQ3ZELENBQUM7WUFDRCxNQUFNLElBQUksS0FBSyxDQUNiLDhFQUE4RTtnQkFDOUUsa0ZBQWtGLENBQ25GLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFBLHlCQUFpQixFQUNsQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFDbEIsSUFBSSxDQUFDLEdBQUcsQ0FDVCxDQUFDO1FBRUYsMERBQTBEO1FBQzFELE1BQU0sWUFBWSxHQUFHLE9BQU8sT0FBTyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUNwRixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxJQUFBLHlCQUFhLEVBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLGtCQUFNLENBQUMsQ0FBQztRQUV6RixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxxQkFBVSxDQUFDO2dCQUMzQixPQUFPLEVBQUU7b0JBQ1AsWUFBWSxFQUFFLElBQUksQ0FBQyxVQUFVO2lCQUM5QjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxJQUFJLE9BQU8sT0FBTyxDQUFDLE1BQU0sS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUNoRCxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUM7Z0JBQ25DLE9BQU8sRUFBRTtvQkFDUCxZQUFZLEVBQUUsSUFBSSxDQUFDLFVBQVU7aUJBQzlCO2FBQ0YsQ0FBQyxDQUFDO1FBQ0wsQ0FBQzthQUFNLElBQUksU0FBUyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUN2QyxJQUFJLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO2dCQUNqQyxPQUFPLEVBQUU7b0JBQ1AsWUFBWSxFQUFFLElBQUksQ0FBQyxVQUFVO2lCQUM5QjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLHFCQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQztnQkFDakQsT0FBTyxFQUFFO29CQUNQLFlBQVksRUFBRSxJQUFJLENBQUMsVUFBVTtpQkFDOUI7YUFDRixDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsb0dBQW9HO1FBQ3BHLGtHQUFrRztRQUNsRywrREFBK0Q7UUFDL0QsTUFBTSxhQUFhLEdBQUcsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN4RixJQUFJLENBQUMsWUFBWSxHQUFHLGFBQWEsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQ1gsZUFBZSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsOERBQThEO2dCQUNsRyw4RkFBOEYsQ0FDL0YsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksaUJBQVcsQ0FDMUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUMsSUFBSSxTQUFTLEVBQUUsQ0FBQyxFQUN0RixFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQ25DLENBQUM7UUFFRixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksNEJBQVksQ0FBQztZQUNuQyxRQUFRLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRO1lBQy9CLFlBQVksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVk7WUFDdkMsUUFBUSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUTtZQUMvQixLQUFLLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLO1lBQ3pCLHVCQUF1QixFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsdUJBQXVCO1lBQzdELEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztTQUNsQixFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNiLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxpQ0FBZ0IsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUxRSxNQUFNLFVBQVUsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVztZQUNwRSx1Q0FBdUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDL0QsTUFBTSxRQUFRLEdBQStCO1lBQzNDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUI7WUFDakMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO1lBQ2pCLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtTQUNsQyxDQUFDO1FBQ0YsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLGVBQVMsQ0FDdEIsVUFBVSxFQUNWLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLEVBQ25CLFFBQVEsQ0FDVCxDQUFDO1FBRUYsbURBQW1EO1FBQ25ELElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxnQ0FBYyxDQUN0QyxJQUFJLENBQUMsR0FBRyxFQUNSLENBQUMsZ0JBQWdCLEVBQUUsZUFBZSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQztZQUNwRCxVQUFVLEVBQUUsZ0JBQWdCO1lBQzVCLGVBQWU7U0FDaEIsQ0FBQyxDQUNILENBQUM7UUFFRiw0RUFBNEU7UUFDNUUsMkVBQTJFO1FBQzNFLHNDQUFzQztRQUN0QyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksMkJBQWEsQ0FBVTtZQUM5QyxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO1lBQ2IsUUFBUSxFQUFFO2dCQUNSLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO2dCQUNwRCxVQUFVLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO2dCQUM3QyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFXLEVBQUUsS0FBSyxDQUFDO2FBQzVEO1NBQ0YsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLHlCQUFZLENBQVUsSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZGLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLCtCQUFpQixDQUFVO1lBQ3RELE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNuQixPQUFPLEVBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPO1lBQ25DLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTtZQUMvQixnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVEsQ0FBQztZQUMvRCxvQkFBb0IsRUFBRSxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDO1lBQzNGLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYztZQUNuQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7WUFDYixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1lBQ3JCLGNBQWMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVztZQUN0QyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUc7WUFDYixLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDcEIsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxxQkFBcUI7WUFDekQsb0JBQW9CLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLG9CQUFvQixFQUFFO1lBQ3ZELHVCQUF1QixFQUFFLENBQUMsY0FBYyxFQUFFLHNCQUFzQixFQUFFLEVBQUUsQ0FDbEUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxjQUFjLEVBQUUsc0JBQXNCLENBQUM7WUFDekUsc0JBQXNCLEVBQUUsQ0FBQyxPQUFPLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBRSxFQUFFLENBQy9ELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQ2xDLE9BQU8sRUFDUCxjQUFjLEVBQ2QsV0FBVyxDQUNaO1lBQ0gsd0JBQXdCLEVBQUUsT0FBTyxDQUFDLEVBQUUsQ0FDbEMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLG1CQUFtQixDQUFDLE9BQU8sQ0FBQztZQUNyRCxpQkFBaUIsRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQjtZQUNqRCxZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7WUFDL0IsZUFBZSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLFFBQVE7U0FDbEQsQ0FBQyxDQUFDO1FBRUgsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLFFBQVEsRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxVQUFVLENBQUMseUJBQXlCLENBQzdELElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxJQUFJLFFBQVEsRUFDckMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQ3pCLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FDL0csQ0FBQztRQUNKLENBQUM7UUFFRCx3QkFBd0I7UUFDeEIsTUFBTSxPQUFPLEdBQW1CLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUMzRCxNQUFNLFVBQVUsR0FBRywyQkFBYSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQTJCLENBQUM7UUFFbkYsK0RBQStEO1FBQy9ELElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNqRCxNQUFNLElBQUksS0FBSyxDQUNiLGdGQUFnRjtnQkFDaEYsZUFBZTtnQkFDZiwwRUFBMEU7Z0JBQzFFLDJEQUEyRCxDQUM1RCxDQUFDO1FBQ0osQ0FBQztRQUVELHlFQUF5RTtRQUN6RSw0RUFBNEU7UUFDNUUsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUMxQyxNQUFNLElBQUksS0FBSyxDQUNiLGdGQUFnRjtnQkFDaEYsNkNBQTZDLENBQzlDLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxNQUFrQixDQUFDO1FBRXZCLHdEQUF3RDtRQUN4RCxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsc0dBQXNHO2dCQUNsSCx3REFBd0QsQ0FBQyxDQUFDO1lBQzVELElBQUksQ0FBQyxJQUFJLEdBQUcsVUFBVSxDQUFDO1lBQ3ZCLHFEQUFxRDtZQUNyRCxNQUFNLEdBQUksVUFBa0IsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDO1lBQzFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDWixNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxDQUFDLENBQUM7WUFDOUQsQ0FBQztRQUNILENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbkMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQztRQUNyQyxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksdUNBQXVDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyx1Q0FBdUMsQ0FBQztZQUNuRyxJQUFJLHVDQUF1QyxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDakcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQ1gsMkZBQTJGLENBQzVGLENBQUM7Z0JBQ0YsdUNBQXVDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUM7WUFDbEUsQ0FBQztZQUNELElBQUksdUNBQXVDLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQzFELE1BQU0sK0JBQStCLEdBQUcsSUFBQSx3QkFBa0IsRUFBQyw0Q0FBNEMsQ0FBQyxDQUFDO2dCQUN6RyxJQUFJLCtCQUErQixLQUFLLFNBQVMsRUFBRSxDQUFDO29CQUNsRCxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FDWCxxREFBcUQ7d0JBQ3JELG9FQUFvRSxDQUNyRSxDQUFDO29CQUNGLHVDQUF1QyxHQUFHLCtCQUErQixDQUFDO2dCQUM1RSxDQUFDO1lBQ0gsQ0FBQztZQUNELHVDQUF1QyxLQUFLLEtBQUssQ0FBQztZQUNsRCxNQUFNLEdBQUcsSUFBSSx3QkFBVSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLElBQUksSUFBSSxxQkFBYyxDQUFDLFNBQVMsRUFBRTtnQkFDdEYsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHO2dCQUNoQixPQUFPLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDO2FBQzVELENBQUMsRUFBRTtnQkFDRix1Q0FBdUM7Z0JBQ3ZDLE1BQU0sRUFBRSxJQUFJLENBQUMsR0FBRztnQkFDaEIsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsSUFBSSxlQUFlO2FBQ3JFLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCx5QkFBeUI7UUFDekIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUM7UUFFckIsdUNBQXVDO1FBQ3ZDLE1BQU0sQ0FBQyxTQUFTLEdBQUcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFckQsb0NBQW9DO1FBQ3BDLElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7UUFFaEUsK0RBQStEO1FBQy9ELElBQUksQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBRTdELCtEQUErRDtRQUMvRCxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEIsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxDQUFDO1lBQy9DLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUM7WUFDM0QsSUFBSSxDQUFDLEdBQUcsQ0FDTixVQUFVLENBQUMsaUJBQWlCLENBQzFCLE9BQU8sT0FBTyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQzVDLENBQ0YsQ0FBQztRQUNKLENBQUM7UUFFRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsSUFBSSw0QkFBaUIsQ0FBQztZQUM3QyxxQkFBcUIsRUFBRSx1QkFBdUI7Z0JBQzVDLENBQUMsQ0FBQyxTQUFTO2dCQUNYLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLHFCQUFxQjtZQUNwQyxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNuQixZQUFZLEVBQUUsSUFBSSxDQUFDLFlBQVk7U0FDaEMsQ0FBQyxDQUFDO1FBQ0gsS0FBSyxNQUFNLGNBQWMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUMzRCxJQUFJLENBQUMsWUFBWSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7UUFFRCxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFPLEVBQUUsRUFBRTtZQUNyQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFOUIsSUFBSSxLQUFLLFlBQVksa0JBQVUsRUFBRSxDQUFDO2dCQUNoQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUNuQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3ZDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxVQUFVO1FBQ2QsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdkIsT0FBTztRQUNULENBQUM7UUFFRCxxQkFBcUI7UUFDckIsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksRUFBRSxDQUFDO1FBRWhDLG9CQUFvQjtRQUNwQixNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDO1lBQzNCLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztZQUM3QixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7U0FDbEIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFDNUIsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBc0I7UUFDaEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDO1FBRTdDLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBRXhCLGdCQUFnQjtZQUNoQixNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ3BELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7WUFFcEMsb0JBQW9CO1lBQ3BCLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFBQyxPQUFPLEtBQVUsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2xCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUN6RCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDcEIsTUFBTSxXQUFXLENBQUM7Z0JBQ2xCLE1BQU0sS0FBSyxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsSUFBSTtRQUNSLElBQUksQ0FBQztZQUNILGVBQWU7WUFDZixNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUM7WUFFaEMsbUJBQW1CO1lBQ25CLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUMzQixDQUFDO1FBQUMsT0FBTyxLQUFVLEVBQUUsQ0FBQztZQUNwQixJQUFJLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUM7SUE4QkQsS0FBSyxDQUFDLElBQUksQ0FDUixjQUFzQixFQUN0QixRQUFnRCxFQUNoRCxPQUF3QjtRQUV4QixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsY0FBYyxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBMERELHFGQUFxRjtJQUNyRixLQUFLLENBQUMsS0FBSyxDQUNULGNBQXNCLEVBQ3RCLFNBQTBELEVBQzFELFFBQWtFLEVBQ2xFLE9BQXdCO1FBRXhCLElBQUksT0FBTyxTQUFTLEtBQUssUUFBUSxJQUFJLFFBQVEsS0FBSyxTQUFTLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQzNGLElBQUksQ0FBQyxjQUFjLElBQUksY0FBYyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO2dCQUNwRCxNQUFNLElBQUksS0FBSyxDQUFDLDJDQUEyQyxDQUFDLENBQUM7WUFDL0QsQ0FBQztZQUNELElBQUksU0FBUyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO2dCQUM1QixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxDQUFDLENBQUM7WUFDMUQsQ0FBQztZQUVELE9BQU8sSUFBSSxDQUFDLFlBQVksQ0FBQyxjQUFjLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN6RSxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsUUFBUSxJQUFJLGdCQUFnQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUN6RSxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLFNBQW1ELEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDOUYsQ0FBQztJQUVEOzs7Ozs7Ozs7T0FTRztJQUNILGtCQUFrQixDQUFDLFVBQXdDLEVBQUU7UUFDM0QsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLFFBQVEsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztRQUN6RixJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDZCxNQUFNLElBQUksS0FBSyxDQUFDLGdEQUFnRCxDQUFDLENBQUM7UUFDcEUsQ0FBQztRQUVELE1BQU0scUJBQXFCLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixJQUFJLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDdkUsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDM0IsTUFBTSxJQUFJLEtBQUssQ0FBQyw2REFBNkQsQ0FBQyxDQUFDO1FBQ2pGLENBQUM7UUFFRCxPQUFPO1lBQ0wscUJBQXFCO1lBQ3JCLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtZQUNsQyxhQUFhLEVBQUUsT0FBTyxDQUFDLGFBQWE7WUFDcEMsUUFBUTtTQUNULENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7Ozs7O09BV0c7SUFDSCxZQUFZLENBQ1YsY0FBc0IsRUFDdEIsVUFBOEIsRUFBRTtRQUVoQyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLHFCQUFxQixLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzVELE1BQU0sSUFBSSxLQUFLLENBQ2IsOEVBQThFO2dCQUM5RSxrRkFBa0YsQ0FDbkYsQ0FBQztRQUNKLENBQUM7UUFFRCxNQUFNLElBQUksR0FBRyxJQUFJLGlCQUFTLENBQVUsY0FBYyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzdELElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDakMsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSCxZQUFZLENBQUMsY0FBc0I7UUFDakMsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsRUFBRSxDQUNBLElBQVUsRUFDVixFQUF1RTtRQUV2RSxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDekIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE9BQU8sQ0FDTCxPQUF3QixFQUN4QixFQUE0RTtRQUU1RSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBWTtZQUM5QixJQUFJLEVBQUUsTUFBTTtZQUNaLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFO2dCQUNuQixJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQ2hDLE9BQU8sS0FBSyxDQUFDO2dCQUNmLENBQUM7Z0JBRUQsT0FBTyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pELENBQUM7WUFDRCxRQUFRLEVBQUUsRUFBRTtTQUNiLENBQUMsQ0FBQztRQUVILE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7T0FHRztJQUNILEdBQUcsQ0FDRCxFQUFxRztRQUVyRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNwQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUF3QyxJQUFVLEVBQUUsRUFBMEM7UUFDakcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3pCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxNQUFlO1FBQ3BCLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQy9CLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxDQUFDLElBQWdCO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQWVELFFBQVEsQ0FDTixJQUFZLEVBQ1osRUFBNEQ7UUFFNUQsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRXBELDRDQUE0QztRQUM1QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsbUJBQW1CO1lBQ3hDLENBQUMsQ0FBQyxJQUFJLG1EQUF1QixDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxHQUFHLENBQUM7WUFDNUQsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUVULElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxrQkFBa0IsSUFBSSxFQUFFLEVBQUUsS0FBSyxFQUFFLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUU7WUFDdEYseUNBQXlDO1lBQ3pDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDZixHQUFHLENBQUMsS0FBSyxDQUFDLDhDQUE4QyxDQUFDLENBQUM7Z0JBQzFELE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsQ0FBQztZQUMvQyxDQUFDO1lBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQy9DLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDYixPQUFPLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsY0FBYyxFQUFFLENBQUM7WUFDL0MsQ0FBQztZQUVELE1BQU0sR0FBRyxHQUFHLElBQUksMEJBQWUsQ0FBUTtnQkFDckMsR0FBRyxPQUFPO2dCQUNWLEdBQUc7Z0JBQ0gsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHO2dCQUNiLFFBQVEsRUFBRSxJQUFJLENBQUMsS0FBSztnQkFDcEIsSUFBSSxFQUFFLElBQWE7Z0JBQ25CLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYztnQkFDbkMsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFO2FBQ2YsQ0FBQyxDQUFDO1lBRUgsTUFBTSxJQUFJLEdBQUcsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDM0IsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDO1FBQ3JDLENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEdBQUcsQ0FBQyxJQUFZLEVBQUUsSUFBWTtRQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxTQUFTLElBQUksRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRS9DLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxnQkFBZ0IsQ0FBQyxRQUFrQjtRQUNqQyxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVEOzs7T0FHRztJQUNILE9BQU8sQ0FBQyxLQUFxQjtRQUMzQixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVELEtBQUssQ0FBQyxVQUFVLENBQ2QsS0FBcUI7UUFFckIsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEMsT0FBTyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELEdBQUc7SUFDSCxTQUFTO0lBQ1QsR0FBRztJQUVPLEtBQUssQ0FBQyxXQUFXO1FBQ3pCLE9BQU8sTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2hELENBQUM7SUFFRDs7OztPQUlHO0lBQ08sS0FBSyxDQUFDLG9CQUFvQixDQUFDLFFBQXlCLEVBQUUsUUFBaUI7UUFDL0UsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDdEQsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsT0FBTyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsbUJBQW1CLENBQ2pELElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUNyQixRQUFRLENBQUMsWUFBWSxFQUNyQixRQUFRLENBQUMsYUFBYTtRQUN0Qix5R0FBeUc7UUFDekcsMlBBQTJQO1FBQzNQLFFBQVEsQ0FBQyxRQUFRLElBQUksUUFBUSxDQUM5QixDQUFDO0lBQ0osQ0FBQztJQUVTLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFpQjtRQUNoRCx3RUFBd0U7UUFDeEUseUVBQXlFO1FBQ3pFLHlCQUF5QjtRQUN6QixPQUFPLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQ3pDLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUNyQixRQUFRLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxRQUFRLElBQUksOENBQThCLENBQ3pFLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDTyxvQkFBb0I7UUFDNUIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsY0FBYyxDQUFDO1FBQ3BELElBQUksUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzNCLE9BQU8sUUFBUSxDQUFDO1FBQ2xCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLHFCQUFxQixLQUFLLFNBQVMsQ0FBQztJQUNqRSxDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVksQ0FDeEIsY0FBc0IsRUFDdEIsUUFBZ0QsRUFDaEQsT0FBd0IsRUFDeEIsWUFBcUI7UUFFckIsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNiLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUNuRCxDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsSUFBQSw0QkFBZ0IsRUFBQyxRQUFRLENBQUMsQ0FBQztRQUUxQyxNQUFNLEdBQUcsR0FBMEI7WUFDakMsU0FBUyxFQUFFLFNBQVM7WUFDcEIsVUFBVSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVTtZQUMvQixHQUFHLEVBQUU7Z0JBQ0gsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFO2dCQUNYLElBQUksRUFBRSxLQUFLO2FBQ1o7WUFDRCxZQUFZLEVBQUU7Z0JBQ1osRUFBRSxFQUFFLGNBQWM7YUFDc0I7U0FDM0MsQ0FBQztRQUVGLE1BQU0sYUFBYSxHQUNqQixPQUFPLEVBQUUsZUFBZSxJQUFJLFlBQVk7WUFDdEMsQ0FBQyxDQUFDLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFO1lBQzdELENBQUMsQ0FBQyxTQUFTLENBQUM7UUFFaEIsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO0lBQzlELENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0ssZUFBZTtRQUNyQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxLQUFLLGtCQUFNLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbEQsTUFBTSxJQUFJLEtBQUssQ0FDYix1RUFBdUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLEtBQUs7Z0JBQ2xHLGlFQUFpRTtnQkFDakUseUNBQXlDLENBQzFDLENBQUM7UUFDSixDQUFDO1FBQ0QsTUFBTSxPQUFPLEdBQ1gsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBZ0MsQ0FBQztRQUN6RixNQUFNLGlCQUFpQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLElBQUksZUFBZSxDQUFDO1FBRTVFLE1BQU0sYUFBYSxHQUFHLElBQUksK0JBQWlCLENBQUMsT0FBTyxFQUFFO1lBQ25ELFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztZQUM3QixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDbkIsYUFBYSxFQUFFLElBQUksQ0FBQyxhQUFhO1lBQ2pDLGVBQWUsRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUM7WUFDbEQsaUJBQWlCO1lBQ2pCLE9BQU8sRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7WUFDM0QsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHO1NBQ2pCLENBQUMsQ0FBQztRQUVILE1BQU0sTUFBTSxHQUFHLElBQUksd0JBQVUsQ0FBQyxhQUFhLEVBQUU7WUFDM0MsTUFBTSxFQUFFLElBQUksQ0FBQyxHQUFHO1lBQ2hCLGlCQUFpQjtTQUNsQixDQUFDLENBQUM7UUFDSCxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsQ0FBQztJQUMvQyxDQUFDO0lBQ08sZ0JBQWdCO1FBQ3RCLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEtBQUssS0FBSyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNyRCxPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBQSwrQkFBc0IsRUFBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEQsQ0FBQztDQUVGO0FBcDRCRCxrQkFvNEJDIn0=