@elizaos/plugin-slack 2.0.0-beta.1 → 2.0.11-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -29
- package/auto-enable.ts +1 -1
- package/package.json +29 -12
- package/dist/index.js +0 -3036
- package/dist/index.js.map +0 -17
package/dist/index.js.map
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/index.ts", "../src/connector-account-provider.ts", "../src/accounts.ts", "../src/connector-credential-refs.ts", "../src/types.ts", "../src/service.ts", "../src/formatting.ts", "../src/workflow-credential-provider.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import {\n getConnectorAccountManager,\n type IAgentRuntime,\n logger,\n type Plugin,\n} from \"@elizaos/core\";\nimport { createSlackConnectorAccountProvider } from \"./connector-account-provider\";\n\nimport { SlackService } from \"./service\";\nimport { SlackWorkflowCredentialProvider } from \"./workflow-credential-provider\";\n\nconst slackPlugin: Plugin = {\n name: \"slack\",\n description: \"Slack integration plugin for ElizaOS with Socket Mode support\",\n services: [SlackService, SlackWorkflowCredentialProvider],\n actions: [],\n providers: [],\n // Self-declared auto-enable: activate when the \"slack\" connector is\n // configured under config.connectors. The hardcoded CONNECTOR_PLUGINS map\n // in plugin-auto-enable-engine.ts still serves as a fallback.\n autoEnable: {\n connectorKeys: [\"slack\"],\n },\n init: async (_config: Record<string, string>, runtime: IAgentRuntime) => {\n // Register with the ConnectorAccountManager so the generic HTTP CRUD +\n // OAuth surface can list, create, patch, delete, and run OAuth v2 install\n // flows for Slack workspaces.\n try {\n const manager = getConnectorAccountManager(runtime);\n manager.registerProvider(createSlackConnectorAccountProvider(runtime));\n } catch (err) {\n logger.warn(\n {\n src: \"plugin:slack\",\n err: err instanceof Error ? err.message : String(err),\n },\n \"Failed to register Slack provider with ConnectorAccountManager\",\n );\n }\n\n const botToken = runtime.getSetting(\"SLACK_BOT_TOKEN\") as string;\n const appToken = runtime.getSetting(\"SLACK_APP_TOKEN\") as string;\n const signingSecret = runtime.getSetting(\"SLACK_SIGNING_SECRET\") as string;\n const userToken = runtime.getSetting(\"SLACK_USER_TOKEN\") as string;\n const channelIds = runtime.getSetting(\"SLACK_CHANNEL_IDS\") as string;\n const ignoreBotMessages = runtime.getSetting(\n \"SLACK_SHOULD_IGNORE_BOT_MESSAGES\",\n ) as string;\n const respondOnlyToMentions = runtime.getSetting(\n \"SLACK_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n ) as string;\n\n // Log configuration status\n const maskToken = (token: string | undefined): string => {\n if (!token || token.trim() === \"\") return \"[not set]\";\n if (token.length <= 8) return \"***\";\n return `${token.slice(0, 4)}...${token.slice(-4)}`;\n };\n\n logger.info(\n {\n src: \"plugin:slack\",\n agentId: runtime.agentId,\n settings: {\n botToken: maskToken(botToken),\n appToken: maskToken(appToken),\n signingSecret: signingSecret ? \"[set]\" : \"[not set]\",\n userToken: maskToken(userToken),\n channelIds: channelIds || \"[all channels]\",\n ignoreBotMessages: ignoreBotMessages || \"false\",\n respondOnlyToMentions: respondOnlyToMentions || \"false\",\n },\n },\n \"Slack plugin initializing\",\n );\n\n if (!botToken || botToken.trim() === \"\") {\n logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"SLACK_BOT_TOKEN not provided - Slack plugin is loaded but will not be functional\",\n );\n logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"To enable Slack functionality, please provide SLACK_BOT_TOKEN in your .env file\",\n );\n return;\n }\n\n if (!appToken || appToken.trim() === \"\") {\n logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"SLACK_APP_TOKEN not provided - Socket Mode will not work\",\n );\n logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"To enable Socket Mode, please provide SLACK_APP_TOKEN in your .env file\",\n );\n return;\n }\n\n // Validate token formats\n if (!botToken.startsWith(\"xoxb-\")) {\n logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"SLACK_BOT_TOKEN should start with 'xoxb-'. Please verify your token.\",\n );\n }\n\n if (!appToken.startsWith(\"xapp-\")) {\n logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"SLACK_APP_TOKEN should start with 'xapp-'. Please verify your token.\",\n );\n }\n\n if (userToken && !userToken.startsWith(\"xoxp-\")) {\n logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"SLACK_USER_TOKEN should start with 'xoxp-'. Please verify your token.\",\n );\n }\n\n logger.info(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"Slack plugin configuration validated successfully\",\n );\n },\n};\n\nexport default slackPlugin;\n\n// Account management exports\nexport {\n DEFAULT_ACCOUNT_ID,\n isMultiAccountEnabled,\n listEnabledSlackAccounts,\n listSlackAccountIds,\n normalizeAccountId,\n type ResolvedSlackAccount,\n resolveDefaultSlackAccountId,\n resolveSlackAccount,\n resolveSlackAppToken,\n resolveSlackBotToken,\n resolveSlackReplyToMode,\n resolveSlackUserToken,\n type SlackAccountConfig,\n type SlackActionConfig,\n type SlackChannelConfig,\n type SlackDmConfig,\n type SlackMultiAccountConfig,\n type SlackReactionNotificationMode,\n type SlackSlashCommandConfig,\n type SlackTokenSource,\n} from \"./accounts\";\n// Channel configuration types\nexport type {\n SlackConfig,\n SlackThreadConfig,\n} from \"./config\";\nexport { createSlackConnectorAccountProvider } from \"./connector-account-provider\";\n// Formatting exports\nexport {\n buildSlackMessagePermalink,\n type ChunkSlackTextOpts,\n chunkSlackText,\n escapeSlackMrkdwn,\n extractChannelIdFromMention,\n extractUrlFromSlackLink,\n extractUserIdFromMention,\n formatSlackChannel,\n formatSlackChannelMention,\n formatSlackDate,\n formatSlackLink,\n formatSlackSpecialMention,\n formatSlackUserDisplayName,\n formatSlackUserGroupMention,\n formatSlackUserMention,\n getChannelTypeString,\n isDirectMessage,\n isGroupDm,\n isPrivateChannel,\n markdownToSlackMrkdwn,\n markdownToSlackMrkdwnChunks,\n parseSlackMessagePermalink,\n resolveSlackSystemLocation,\n stripSlackFormatting,\n truncateText,\n} from \"./formatting\";\n// Export service for direct access\nexport { SlackService } from \"./service\";\n// Export types\nexport type {\n ISlackService,\n SlackChannel,\n SlackChannelType,\n SlackEventPayloadMap,\n SlackFile,\n SlackMessage,\n SlackMessageReceivedPayload,\n SlackMessageSendOptions,\n SlackMessageSentPayload,\n SlackReaction,\n SlackReactionPayload,\n SlackSettings,\n SlackTeam,\n SlackUser,\n SlackUserProfile,\n} from \"./types\";\nexport {\n formatMessageTsForLink,\n getSlackChannelType,\n getSlackUserDisplayName,\n isValidChannelId,\n isValidMessageTs,\n isValidTeamId,\n isValidUserId,\n MAX_SLACK_BLOCKS,\n MAX_SLACK_FILE_SIZE,\n MAX_SLACK_MESSAGE_LENGTH,\n parseSlackMessageLink,\n SLACK_SERVICE_NAME,\n SlackApiError,\n SlackClientNotAvailableError,\n SlackConfigurationError,\n SlackEventTypes,\n SlackPluginError,\n SlackServiceNotInitializedError,\n} from \"./types\";\n",
|
|
6
|
-
"/**\n * Slack ConnectorAccountManager provider.\n *\n * Bridges plugin-slack to the @elizaos/core ConnectorAccountManager so the\n * generic HTTP CRUD + OAuth surface can list, create, patch, delete, and run\n * the OAuth v2 install flow for Slack workspaces.\n *\n * Single-account env-only configurations (SLACK_BOT_TOKEN, SLACK_APP_TOKEN)\n * are surfaced as a synthesized 'default' account with role 'OWNER' so\n * downstream consumers see a uniform list. Multi-account configs declared on\n * character.settings.slack are surfaced verbatim.\n */\nimport {\n type ConnectorAccount,\n type ConnectorAccountManager,\n type ConnectorAccountPatch,\n type ConnectorAccountProvider,\n type ConnectorAccountPurpose,\n type ConnectorOAuthCallbackRequest,\n type ConnectorOAuthCallbackResult,\n type ConnectorOAuthStartRequest,\n type ConnectorOAuthStartResult,\n type IAgentRuntime,\n logger,\n} from \"@elizaos/core\";\nimport {\n DEFAULT_ACCOUNT_ID,\n listEnabledSlackAccounts,\n resolveDefaultSlackAccountId,\n resolveSlackAccount,\n} from \"./accounts\";\nimport { persistConnectorCredentialRefs } from \"./connector-credential-refs\";\nimport { SLACK_SERVICE_NAME } from \"./types\";\n\nconst SLACK_OAUTH_AUTHORIZE_URL = \"https://slack.com/oauth/v2/authorize\";\nconst SLACK_OAUTH_TOKEN_URL = \"https://slack.com/api/oauth.v2.access\";\n\nconst DEFAULT_BOT_SCOPES = [\n \"app_mentions:read\",\n \"channels:history\",\n \"channels:read\",\n \"chat:write\",\n \"groups:history\",\n \"groups:read\",\n \"im:history\",\n \"im:read\",\n \"im:write\",\n \"mpim:history\",\n \"mpim:read\",\n \"reactions:read\",\n \"reactions:write\",\n \"users:read\",\n];\n\nconst DEFAULT_PURPOSES: ConnectorAccountPurpose[] = [\n \"messaging\",\n \"posting\",\n \"reading\",\n];\n\ninterface SlackOAuthV2Response {\n ok: boolean;\n error?: string;\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n scope?: string;\n bot_user_id?: string;\n app_id?: string;\n team?: { id: string; name?: string };\n enterprise?: { id: string; name?: string } | null;\n authed_user?: {\n id: string;\n scope?: string;\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n token_type?: string;\n };\n incoming_webhook?: {\n channel?: string;\n channel_id?: string;\n configuration_url?: string;\n url?: string;\n };\n}\n\nfunction nowMs(): number {\n return Date.now();\n}\n\nfunction nonEmptyString(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction readSetting(runtime: IAgentRuntime, key: string): string | undefined {\n return nonEmptyString(runtime.getSetting?.(key));\n}\n\nfunction readClientConfig(runtime: IAgentRuntime): {\n clientId: string;\n clientSecret: string;\n redirectUri: string;\n} {\n const clientId = readSetting(runtime, \"SLACK_CLIENT_ID\");\n const clientSecret = readSetting(runtime, \"SLACK_CLIENT_SECRET\");\n const redirectUri = readSetting(runtime, \"SLACK_REDIRECT_URI\");\n if (!clientId || !clientSecret || !redirectUri) {\n throw new Error(\n \"Slack OAuth requires SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, and SLACK_REDIRECT_URI to be configured.\",\n );\n }\n return { clientId, clientSecret, redirectUri };\n}\n\nfunction synthesizeAccount(\n accountId: string,\n name: string | undefined,\n isDefault: boolean,\n source: string,\n): ConnectorAccount {\n return {\n id: accountId,\n provider: SLACK_SERVICE_NAME,\n label: name ?? `Slack (${accountId})`,\n role: \"OWNER\",\n purpose: DEFAULT_PURPOSES,\n accessGate: \"open\",\n status: \"connected\",\n createdAt: nowMs(),\n updatedAt: nowMs(),\n metadata: {\n synthesized: true,\n source,\n isDefault,\n },\n };\n}\n\nfunction normalizePurposes(\n purpose: ConnectorAccountPatch[\"purpose\"] | undefined,\n fallback: ConnectorAccountPurpose[],\n): ConnectorAccountPurpose[] {\n if (Array.isArray(purpose)) return purpose;\n if (typeof purpose === \"string\" && purpose.trim()) return [purpose];\n return fallback;\n}\n\nfunction mergeStoredAccountPatch(\n account: ConnectorAccount,\n patch: ConnectorAccountPatch,\n): ConnectorAccount {\n return {\n ...account,\n ...patch,\n provider: SLACK_SERVICE_NAME,\n id: account.id,\n purpose: normalizePurposes(patch.purpose, account.purpose),\n externalId:\n patch.externalId === undefined\n ? account.externalId\n : (patch.externalId ?? undefined),\n displayHandle:\n patch.displayHandle === undefined\n ? account.displayHandle\n : (patch.displayHandle ?? undefined),\n ownerBindingId:\n patch.ownerBindingId === undefined\n ? account.ownerBindingId\n : (patch.ownerBindingId ?? undefined),\n ownerIdentityId:\n patch.ownerIdentityId === undefined\n ? account.ownerIdentityId\n : (patch.ownerIdentityId ?? undefined),\n metadata: patch.metadata ?? account.metadata,\n createdAt: account.createdAt,\n };\n}\n\nexport function createSlackConnectorAccountProvider(\n runtime: IAgentRuntime,\n): ConnectorAccountProvider {\n return {\n provider: SLACK_SERVICE_NAME,\n label: \"Slack\",\n\n listAccounts: async (\n manager: ConnectorAccountManager,\n ): Promise<ConnectorAccount[]> => {\n const persisted = await manager\n .getStorage()\n .listAccounts(SLACK_SERVICE_NAME);\n const persistedById = new Map(persisted.map((a) => [a.id, a]));\n\n const enabled = listEnabledSlackAccounts(runtime);\n const defaultAccountId = resolveDefaultSlackAccountId(runtime);\n const synthesized: ConnectorAccount[] = enabled\n .filter((account) => !persistedById.has(account.accountId))\n .map((account) =>\n synthesizeAccount(\n account.accountId,\n account.name,\n account.accountId === defaultAccountId,\n account.botTokenSource,\n ),\n );\n\n if (synthesized.length === 0 && persisted.length === 0) {\n const fallback = resolveSlackAccount(runtime, DEFAULT_ACCOUNT_ID);\n if (fallback.botToken) {\n synthesized.push(\n synthesizeAccount(\n DEFAULT_ACCOUNT_ID,\n fallback.name,\n true,\n fallback.botTokenSource,\n ),\n );\n }\n }\n\n return [...persisted, ...synthesized];\n },\n\n createAccount: async (input: ConnectorAccountPatch) => {\n return {\n ...input,\n provider: SLACK_SERVICE_NAME,\n role: input.role ?? \"OWNER\",\n purpose: input.purpose ?? DEFAULT_PURPOSES,\n accessGate: input.accessGate ?? \"open\",\n status: input.status ?? \"pending\",\n };\n },\n\n patchAccount: async (\n accountId: string,\n patch: ConnectorAccountPatch,\n manager: ConnectorAccountManager,\n ) => {\n const existing = await manager\n .getStorage()\n .getAccount(SLACK_SERVICE_NAME, accountId);\n if (existing) {\n return mergeStoredAccountPatch(existing, patch);\n }\n return { ...patch, provider: SLACK_SERVICE_NAME };\n },\n\n deleteAccount: async (): Promise<void> => {\n // Token revocation is the runtime/secrets store's responsibility; the\n // manager removes the account row after this resolves.\n },\n\n startOAuth: async (\n request: ConnectorOAuthStartRequest,\n ): Promise<ConnectorOAuthStartResult> => {\n const config = readClientConfig(runtime);\n const redirectUri = request.redirectUri ?? config.redirectUri;\n const requestedScopes =\n request.scopes && request.scopes.length > 0\n ? request.scopes\n : DEFAULT_BOT_SCOPES;\n\n const params = new URLSearchParams({\n client_id: config.clientId,\n redirect_uri: redirectUri,\n scope: requestedScopes.join(\",\"),\n state: request.flow.state,\n });\n\n return {\n authUrl: `${SLACK_OAUTH_AUTHORIZE_URL}?${params.toString()}`,\n metadata: {\n ...request.metadata,\n requestedScopes,\n redirectUri,\n },\n };\n },\n\n completeOAuth: async (\n request: ConnectorOAuthCallbackRequest,\n manager: ConnectorAccountManager,\n ): Promise<ConnectorOAuthCallbackResult> => {\n const code = nonEmptyString(request.code);\n if (!code) {\n throw new Error(\n \"Slack OAuth callback is missing an authorization code.\",\n );\n }\n\n const config = readClientConfig(runtime);\n const redirectUri =\n nonEmptyString(request.flow.redirectUri) ??\n nonEmptyString(\n (request.flow.metadata as Record<string, unknown> | undefined)\n ?.redirectUri,\n ) ??\n config.redirectUri;\n\n const tokenParams = new URLSearchParams({\n client_id: config.clientId,\n client_secret: config.clientSecret,\n code,\n redirect_uri: redirectUri,\n });\n\n const response = await fetch(SLACK_OAUTH_TOKEN_URL, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: tokenParams.toString(),\n });\n if (!response.ok) {\n const body = await response.text();\n throw new Error(\n `Slack token exchange failed with ${response.status}: ${body}`,\n );\n }\n const parsed = (await response.json()) as SlackOAuthV2Response;\n if (!parsed.ok || !parsed.access_token) {\n throw new Error(\n `Slack token exchange returned an error: ${parsed.error ?? \"unknown\"}`,\n );\n }\n\n const teamId = parsed.team?.id;\n if (!teamId) {\n throw new Error(\"Slack token exchange did not include a team id.\");\n }\n const teamName = parsed.team?.name;\n const grantedScopes = parsed.scope ? parsed.scope.split(\",\") : [];\n const expiresAt =\n typeof parsed.expires_in === \"number\"\n ? Date.now() + parsed.expires_in * 1000\n : undefined;\n const authedUserExpiresAt =\n typeof parsed.authed_user?.expires_in === \"number\"\n ? Date.now() + parsed.authed_user.expires_in * 1000\n : undefined;\n const oauthCredentialVersion = String(Date.now());\n const accountMetadata = {\n teamId,\n teamName: teamName ?? null,\n appId: parsed.app_id ?? null,\n botUserId: parsed.bot_user_id ?? null,\n enterpriseId: parsed.enterprise?.id ?? null,\n authedUserId: parsed.authed_user?.id ?? null,\n tokenType: parsed.token_type ?? \"bot\",\n grantedScopes,\n hasRefreshToken: Boolean(\n parsed.refresh_token ?? parsed.authed_user?.refresh_token,\n ),\n expiresAt,\n oauthCredentialVersion,\n };\n const pendingAccount = await manager.upsertAccount(\n SLACK_SERVICE_NAME,\n {\n provider: SLACK_SERVICE_NAME,\n role: \"OWNER\",\n purpose: DEFAULT_PURPOSES,\n accessGate: \"open\",\n status: \"pending\",\n externalId: teamId,\n displayHandle: teamName,\n label: teamName ?? `Slack workspace ${teamId}`,\n metadata: accountMetadata,\n },\n request.flow.accountId,\n );\n const credentialPersist = await persistConnectorCredentialRefs({\n runtime,\n manager,\n provider: SLACK_SERVICE_NAME,\n accountIdForRef: pendingAccount.id,\n storageAccountId: pendingAccount.id,\n caller: \"plugin-slack\",\n credentials: [\n {\n credentialType: \"oauth.tokens\",\n value: JSON.stringify({\n access_token: parsed.access_token,\n ...(parsed.refresh_token\n ? { refresh_token: parsed.refresh_token }\n : {}),\n token_type: parsed.token_type ?? \"bot\",\n scope: parsed.scope ?? grantedScopes.join(\",\"),\n ...(expiresAt !== undefined ? { expires_at: expiresAt } : {}),\n ...(parsed.authed_user?.access_token\n ? {\n authed_user: {\n id: parsed.authed_user.id,\n access_token: parsed.authed_user.access_token,\n ...(parsed.authed_user.refresh_token\n ? { refresh_token: parsed.authed_user.refresh_token }\n : {}),\n ...(parsed.authed_user.token_type\n ? { token_type: parsed.authed_user.token_type }\n : {}),\n ...(parsed.authed_user.scope\n ? { scope: parsed.authed_user.scope }\n : {}),\n ...(authedUserExpiresAt !== undefined\n ? { expires_at: authedUserExpiresAt }\n : {}),\n },\n }\n : {}),\n }),\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n metadata: {\n provider: SLACK_SERVICE_NAME,\n hasRefreshToken: Boolean(\n parsed.refresh_token ?? parsed.authed_user?.refresh_token,\n ),\n hasAuthedUserToken: Boolean(parsed.authed_user?.access_token),\n },\n },\n ],\n });\n\n const accountPatch: ConnectorAccountPatch & {\n provider: string;\n id: string;\n } = {\n ...pendingAccount,\n id: pendingAccount.id,\n provider: SLACK_SERVICE_NAME,\n status: \"connected\",\n metadata: {\n ...accountMetadata,\n credentialRefs: credentialPersist.refs,\n credentialRefStorage: {\n vaultAvailable: credentialPersist.vaultAvailable,\n storageAvailable: credentialPersist.storageAvailable,\n },\n },\n };\n\n logger.info(\n {\n src: \"plugin:slack:connector\",\n teamId,\n teamName,\n },\n \"Slack OAuth completed\",\n );\n\n return {\n account: accountPatch,\n flow: { status: \"completed\" },\n };\n },\n };\n}\n",
|
|
7
|
-
"import type { IAgentRuntime } from \"@elizaos/core\";\n\n/**\n * Default account identifier used when no specific account is configured\n */\nexport const DEFAULT_ACCOUNT_ID = \"default\";\n\n/**\n * Source of the Slack token\n */\nexport type SlackTokenSource = \"env\" | \"config\" | \"character\" | \"none\";\n\n/**\n * DM-specific configuration\n */\nexport interface SlackDmConfig {\n /** If false, ignore all incoming Slack DMs */\n enabled?: boolean;\n /** Direct message access policy */\n policy?: \"open\" | \"disabled\" | \"allowlist\";\n /** Allowlist for DM senders (ids or names) */\n allowFrom?: Array<string | number>;\n /** Reply-to mode for DMs */\n replyToMode?: \"off\" | \"first\" | \"all\";\n}\n\n/**\n * Channel-specific configuration\n */\nexport interface SlackChannelConfig {\n /** If false, ignore this channel */\n enabled?: boolean;\n /** Require bot mention to respond */\n requireMention?: boolean;\n /** User allowlist for this channel */\n users?: Array<string | number>;\n /** Reply-to mode for this channel */\n replyToMode?: \"off\" | \"first\" | \"all\";\n}\n\n/**\n * Reaction notification mode\n */\nexport type SlackReactionNotificationMode = \"off\" | \"own\" | \"all\" | \"allowlist\";\n\n/**\n * Slash command configuration\n */\nexport interface SlackSlashCommandConfig {\n /** Enable slash commands */\n enabled?: boolean;\n /** Slash command name (without leading /) */\n command?: string;\n}\n\n/**\n * Action toggles for Slack features\n */\nexport interface SlackActionConfig {\n /** Enable reactions */\n reactions?: boolean;\n /** Enable pins */\n pins?: boolean;\n /** Enable file uploads */\n files?: boolean;\n /** Enable message editing */\n edit?: boolean;\n /** Enable message deletion */\n delete?: boolean;\n /** Enable emoji list */\n emojiList?: boolean;\n /** Enable member info */\n memberInfo?: boolean;\n}\n\n/**\n * Configuration for a single Slack account\n */\nexport interface SlackAccountConfig {\n /** Optional display name for this account */\n name?: string;\n /** If false, do not start this Slack account */\n enabled?: boolean;\n /** Slack bot token (xoxb-...) */\n botToken?: string;\n /** Slack app-level token (xapp-...) */\n appToken?: string;\n /** Slack signing secret */\n signingSecret?: string;\n /** Slack user token (xoxp-...) for user actions */\n userToken?: string;\n /** Controls how channel messages are handled */\n groupPolicy?: \"open\" | \"disabled\" | \"allowlist\";\n /** Outbound text chunk size (chars) */\n textChunkLimit?: number;\n /** Max media size in MB */\n mediaMaxMb?: number;\n /** Reaction notification mode */\n reactionNotifications?: SlackReactionNotificationMode;\n /** Reaction allowlist when mode is 'allowlist' */\n reactionAllowlist?: Array<string | number>;\n /** Reply-to mode */\n replyToMode?: \"off\" | \"first\" | \"all\";\n /** Reply-to mode by chat type */\n replyToModeByChatType?: Record<string, \"off\" | \"first\" | \"all\">;\n /** Per-action toggles */\n actions?: SlackActionConfig;\n /** Slash command configuration */\n slashCommand?: SlackSlashCommandConfig;\n /** DM configuration */\n dm?: SlackDmConfig;\n /** Per-channel configuration keyed by channel ID */\n channels?: Record<string, SlackChannelConfig>;\n /** Allowed channel IDs */\n allowedChannelIds?: string[];\n /** Whether to ignore bot messages */\n shouldIgnoreBotMessages?: boolean;\n /** Whether to respond only to mentions */\n shouldRespondOnlyToMentions?: boolean;\n}\n\n/**\n * Multi-account Slack configuration structure\n */\nexport interface SlackMultiAccountConfig {\n /** Default/base configuration applied to all accounts */\n enabled?: boolean;\n botToken?: string;\n appToken?: string;\n /** Per-account configuration overrides */\n accounts?: Record<string, SlackAccountConfig>;\n}\n\n/**\n * Resolved Slack account with all configuration merged\n */\nexport interface ResolvedSlackAccount {\n accountId: string;\n enabled: boolean;\n name?: string;\n botToken?: string;\n appToken?: string;\n signingSecret?: string;\n userToken?: string;\n botTokenSource: SlackTokenSource;\n appTokenSource: SlackTokenSource;\n config: SlackAccountConfig;\n}\n\n/**\n * Normalizes an account ID, returning the default if not provided\n */\nexport function normalizeAccountId(accountId?: string | null): string {\n if (!accountId || typeof accountId !== \"string\") {\n return DEFAULT_ACCOUNT_ID;\n }\n const trimmed = accountId.trim().toLowerCase();\n return trimmed || DEFAULT_ACCOUNT_ID;\n}\n\n/**\n * Validates and normalizes a Slack token with the expected prefix\n */\nfunction normalizeSlackToken(\n raw: string | null | undefined,\n prefix: string,\n): string | undefined {\n const trimmed = raw?.trim();\n return trimmed?.startsWith(prefix) ? trimmed : undefined;\n}\n\n/**\n * Validates and normalizes a Slack bot token (xoxb-)\n */\nexport function resolveSlackBotToken(raw?: string | null): string | undefined {\n return normalizeSlackToken(raw, \"xoxb-\");\n}\n\n/**\n * Validates and normalizes a Slack app token (xapp-)\n */\nexport function resolveSlackAppToken(raw?: string | null): string | undefined {\n return normalizeSlackToken(raw, \"xapp-\");\n}\n\n/**\n * Validates and normalizes a Slack user token (xoxp-)\n */\nexport function resolveSlackUserToken(raw?: string | null): string | undefined {\n return normalizeSlackToken(raw, \"xoxp-\");\n}\n\n/**\n * Gets the multi-account configuration from runtime settings\n */\nexport function getMultiAccountConfig(\n runtime: IAgentRuntime,\n): SlackMultiAccountConfig {\n const characterSlack = runtime.character?.settings?.slack as\n | SlackMultiAccountConfig\n | undefined;\n\n return {\n enabled: characterSlack?.enabled,\n botToken: characterSlack?.botToken,\n appToken: characterSlack?.appToken,\n accounts: characterSlack?.accounts,\n };\n}\n\n/**\n * Lists all configured account IDs\n */\nexport function listSlackAccountIds(runtime: IAgentRuntime): string[] {\n const config = getMultiAccountConfig(runtime);\n const accounts = config.accounts;\n\n if (!accounts || typeof accounts !== \"object\") {\n return [DEFAULT_ACCOUNT_ID];\n }\n\n const ids = Object.keys(accounts).filter(Boolean);\n if (ids.length === 0) {\n return [DEFAULT_ACCOUNT_ID];\n }\n\n return ids.slice().sort((a, b) => a.localeCompare(b));\n}\n\n/**\n * Resolves the default account ID to use\n */\nexport function resolveDefaultSlackAccountId(runtime: IAgentRuntime): string {\n const ids = listSlackAccountIds(runtime);\n if (ids.includes(DEFAULT_ACCOUNT_ID)) {\n return DEFAULT_ACCOUNT_ID;\n }\n return ids[0] ?? DEFAULT_ACCOUNT_ID;\n}\n\n/**\n * Gets the account-specific configuration\n */\nfunction getAccountConfig(\n runtime: IAgentRuntime,\n accountId: string,\n): SlackAccountConfig | undefined {\n const config = getMultiAccountConfig(runtime);\n const accounts = config.accounts;\n\n if (!accounts || typeof accounts !== \"object\") {\n return undefined;\n }\n\n return accounts[accountId];\n}\n\n/**\n * Merges base configuration with account-specific overrides\n */\n/**\n * Removes undefined values from an object to prevent them from overwriting during spread\n */\nfunction filterDefined<T extends object>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([, v]) => v !== undefined),\n ) as Partial<T>;\n}\n\nfunction mergeSlackAccountConfig(\n runtime: IAgentRuntime,\n accountId: string,\n): SlackAccountConfig {\n const multiConfig = getMultiAccountConfig(runtime);\n const { accounts: _ignored, ...baseConfig } = multiConfig;\n const accountConfig = getAccountConfig(runtime, accountId) ?? {};\n\n // Get environment/runtime settings for the base config\n const envChannelIds = runtime.getSetting(\"SLACK_CHANNEL_IDS\") as\n | string\n | undefined;\n\n const envConfig: SlackAccountConfig = {\n shouldIgnoreBotMessages:\n (\n runtime.getSetting(\"SLACK_SHOULD_IGNORE_BOT_MESSAGES\") as string\n )?.toLowerCase() === \"true\",\n shouldRespondOnlyToMentions:\n (\n runtime.getSetting(\"SLACK_SHOULD_RESPOND_ONLY_TO_MENTIONS\") as string\n )?.toLowerCase() === \"true\",\n allowedChannelIds: envChannelIds\n ? envChannelIds\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined,\n };\n\n // Merge order: env defaults < base config < account config\n // Filter undefined values to prevent them from overwriting defined values\n return {\n ...filterDefined(envConfig),\n ...filterDefined(baseConfig),\n ...filterDefined(accountConfig),\n };\n}\n\n/**\n * Resolves a complete Slack account configuration\n */\nexport function resolveSlackAccount(\n runtime: IAgentRuntime,\n accountId?: string | null,\n): ResolvedSlackAccount {\n const normalizedAccountId = normalizeAccountId(accountId);\n const multiConfig = getMultiAccountConfig(runtime);\n\n const baseEnabled = multiConfig.enabled !== false;\n const merged = mergeSlackAccountConfig(runtime, normalizedAccountId);\n const accountEnabled = merged.enabled !== false;\n const enabled = baseEnabled && accountEnabled;\n\n const allowEnv = normalizedAccountId === DEFAULT_ACCOUNT_ID;\n\n // Resolve bot token\n const envBotToken = allowEnv\n ? resolveSlackBotToken(runtime.getSetting(\"SLACK_BOT_TOKEN\") as string)\n : undefined;\n const configBotToken = resolveSlackBotToken(merged.botToken);\n const botToken = configBotToken ?? envBotToken;\n const botTokenSource: SlackTokenSource = configBotToken\n ? \"config\"\n : envBotToken\n ? \"env\"\n : \"none\";\n\n // Resolve app token\n const envAppToken = allowEnv\n ? resolveSlackAppToken(runtime.getSetting(\"SLACK_APP_TOKEN\") as string)\n : undefined;\n const configAppToken = resolveSlackAppToken(merged.appToken);\n const appToken = configAppToken ?? envAppToken;\n const appTokenSource: SlackTokenSource = configAppToken\n ? \"config\"\n : envAppToken\n ? \"env\"\n : \"none\";\n\n // Resolve signing secret\n const signingSecret =\n merged.signingSecret ??\n (runtime.getSetting(\"SLACK_SIGNING_SECRET\") as string);\n\n // Resolve user token\n const envUserToken = allowEnv\n ? resolveSlackUserToken(runtime.getSetting(\"SLACK_USER_TOKEN\") as string)\n : undefined;\n const configUserToken = resolveSlackUserToken(merged.userToken);\n const userToken = configUserToken ?? envUserToken;\n\n return {\n accountId: normalizedAccountId,\n enabled,\n name: merged.name?.trim() || undefined,\n botToken,\n appToken,\n signingSecret,\n userToken,\n botTokenSource,\n appTokenSource,\n config: merged,\n };\n}\n\n/**\n * Lists all enabled Slack accounts\n */\nexport function listEnabledSlackAccounts(\n runtime: IAgentRuntime,\n): ResolvedSlackAccount[] {\n return listSlackAccountIds(runtime)\n .map((accountId) => resolveSlackAccount(runtime, accountId))\n .filter((account) => account.enabled && account.botToken);\n}\n\n/**\n * Checks if multi-account mode is enabled\n */\nexport function isMultiAccountEnabled(runtime: IAgentRuntime): boolean {\n const accounts = listEnabledSlackAccounts(runtime);\n return accounts.length > 1;\n}\n\n/**\n * Resolves the reply-to mode for a specific chat type\n */\nexport function resolveSlackReplyToMode(\n account: ResolvedSlackAccount,\n chatType?: string | null,\n): \"off\" | \"first\" | \"all\" {\n const normalized = chatType?.toLowerCase().trim();\n\n // Check chat type specific override\n if (\n normalized &&\n account.config.replyToModeByChatType?.[normalized] !== undefined\n ) {\n return account.config.replyToModeByChatType[normalized] ?? \"off\";\n }\n\n // Check DM-specific setting\n if (normalized === \"direct\" || normalized === \"im\") {\n if (account.config.dm?.replyToMode !== undefined) {\n return account.config.dm.replyToMode;\n }\n }\n\n // Fall back to global setting\n return account.config.replyToMode ?? \"off\";\n}\n",
|
|
8
|
-
"import {\n CONNECTOR_ACCOUNT_STORAGE_SERVICE_TYPE,\n type ConnectorAccountManager,\n type IAgentRuntime,\n} from \"@elizaos/core\";\n\ntype JsonValue =\n | string\n | number\n | boolean\n | null\n | undefined\n | JsonValue[]\n | { readonly [key: string]: JsonValue };\ntype JsonRecord = Record<string, JsonValue>;\n\nexport interface ConnectorCredentialRefMetadata extends JsonRecord {\n credentialType: string;\n vaultRef: string;\n expiresAt?: number;\n metadata?: JsonRecord;\n}\n\ninterface ConnectorCredentialInput {\n credentialType: string;\n value: string;\n expiresAt?: number;\n metadata?: JsonRecord;\n}\n\ninterface PersistConnectorCredentialRefsParams {\n runtime: IAgentRuntime;\n manager?: ConnectorAccountManager;\n provider: string;\n accountIdForRef: string;\n storageAccountId?: string;\n credentials: ConnectorCredentialInput[];\n caller: string;\n}\n\ntype VaultWriter = {\n name: string;\n write: (\n vaultRef: string,\n credential: ConnectorCredentialInput,\n ) => Promise<string>;\n};\n\ntype CredentialRefWriter = {\n name: string;\n write: (ref: ConnectorCredentialRefMetadata) => Promise<void>;\n};\n\nexport async function persistConnectorCredentialRefs(\n params: PersistConnectorCredentialRefsParams,\n): Promise<{\n refs: ConnectorCredentialRefMetadata[];\n vaultAvailable: boolean;\n storageAvailable: boolean;\n}> {\n const refs: ConnectorCredentialRefMetadata[] = [];\n const vaultWriters = resolveVaultWriters(params.runtime, {\n provider: params.provider,\n accountId: params.accountIdForRef,\n caller: params.caller,\n });\n if (vaultWriters.length === 0) {\n throw new Error(\n `No durable connector credential store or vault writer is available for ${params.provider} account ${params.accountIdForRef}. Refusing to mark OAuth account connected without persisted credentials.`,\n );\n }\n if (!params.storageAccountId) {\n throw new Error(\n `No durable connector account id is available for ${params.provider} account ${params.accountIdForRef}. Refusing to mark OAuth account connected without persisted credential refs.`,\n );\n }\n const storageWriters = resolveCredentialRefWriters(\n params.runtime,\n params.manager,\n params.storageAccountId,\n );\n if (storageWriters.length === 0) {\n throw new Error(\n `No durable connector credential ref writer is available for ${params.provider} account ${params.storageAccountId}. Refusing to mark OAuth account connected without persisted credential refs.`,\n );\n }\n\n for (const credential of params.credentials) {\n const plannedRef = buildConnectorCredentialVaultRef({\n agentId: nonEmptyString(params.runtime.agentId) ?? \"agent\",\n provider: params.provider,\n accountId: params.accountIdForRef,\n credentialType: credential.credentialType,\n });\n const vaultRef = await writeWithFirstAvailableVault(\n vaultWriters,\n plannedRef,\n credential,\n );\n refs.push({\n credentialType: credential.credentialType,\n vaultRef,\n ...(credential.expiresAt !== undefined\n ? { expiresAt: credential.expiresAt }\n : {}),\n ...(credential.metadata ? { metadata: credential.metadata } : {}),\n });\n }\n\n if (refs.length > 0) {\n await writeRefsToStorage(storageWriters, refs);\n }\n\n return {\n refs,\n vaultAvailable: vaultWriters.length > 0,\n storageAvailable: storageWriters.length > 0,\n };\n}\n\nfunction resolveVaultWriters(\n runtime: IAgentRuntime,\n context: { provider: string; accountId: string; caller: string },\n): VaultWriter[] {\n const writers: VaultWriter[] = [];\n const credentialStore = getFirstService(runtime, [\n \"connector_credential_store\",\n \"CONNECTOR_CREDENTIAL_STORE\",\n \"connectorCredentialStore\",\n \"credential_store\",\n ]) as {\n putSecret?: (params: {\n vaultRef?: string;\n agentId: string;\n provider: string;\n accountId: string;\n credentialType: string;\n value: string;\n caller?: string;\n }) => Promise<string> | string;\n } | null;\n if (typeof credentialStore?.putSecret === \"function\") {\n writers.push({\n name: \"connector_credential_store\",\n write: async (vaultRef, credential) =>\n credentialStore.putSecret?.({\n vaultRef,\n agentId: nonEmptyString(runtime.agentId) ?? \"agent\",\n provider: context.provider,\n accountId: context.accountId,\n credentialType: credential.credentialType,\n value: credential.value,\n caller: context.caller,\n }) ?? vaultRef,\n });\n }\n\n const vault = getFirstService(runtime, [\"vault\", \"VAULT\"]) as {\n set?: (\n key: string,\n value: string,\n options?: { sensitive?: boolean; caller?: string },\n ) => Promise<void> | void;\n } | null;\n if (typeof vault?.set === \"function\") {\n writers.push({\n name: \"vault\",\n write: async (vaultRef, credential) => {\n await vault.set?.(vaultRef, credential.value, {\n sensitive: true,\n caller: context.caller,\n });\n return vaultRef;\n },\n });\n }\n\n const secrets = getService(runtime, \"SECRETS\") as {\n setGlobal?: (\n key: string,\n value: string,\n config?: { sensitive?: boolean },\n ) => Promise<boolean> | boolean;\n set?: (\n key: string,\n value: string,\n context: JsonRecord,\n config?: { sensitive?: boolean },\n ) => Promise<boolean> | boolean;\n } | null;\n if (\n typeof secrets?.setGlobal === \"function\" ||\n typeof secrets?.set === \"function\"\n ) {\n writers.push({\n name: \"SECRETS\",\n write: async (vaultRef, credential) => {\n if (typeof secrets.setGlobal === \"function\") {\n await secrets.setGlobal(vaultRef, credential.value, {\n sensitive: true,\n });\n return vaultRef;\n }\n await secrets.set?.(\n vaultRef,\n credential.value,\n { level: \"global\", agentId: runtime.agentId },\n { sensitive: true },\n );\n return vaultRef;\n },\n });\n }\n\n return writers;\n}\n\nfunction resolveCredentialRefWriters(\n runtime: IAgentRuntime,\n manager: ConnectorAccountManager | undefined,\n accountId: string,\n): CredentialRefWriter[] {\n const candidates = [\n manager?.getStorage?.(),\n getService(runtime, CONNECTOR_ACCOUNT_STORAGE_SERVICE_TYPE),\n (runtime as IAgentRuntime & { adapter?: unknown }).adapter,\n ].filter(Boolean);\n\n const writers: CredentialRefWriter[] = [];\n for (const candidate of candidates) {\n const writer = candidate as {\n setConnectorAccountCredentialRef?: (params: {\n accountId: string;\n credentialType: string;\n vaultRef: string;\n metadata?: JsonRecord;\n expiresAt?: number;\n }) => Promise<unknown> | unknown;\n setCredentialRef?: (params: {\n accountId: string;\n credentialType: string;\n vaultRef: string;\n metadata?: JsonRecord;\n expiresAt?: number;\n }) => Promise<unknown> | unknown;\n };\n if (typeof writer.setConnectorAccountCredentialRef === \"function\") {\n writers.push({\n name: \"setConnectorAccountCredentialRef\",\n write: async (ref) => {\n await writer.setConnectorAccountCredentialRef?.({\n accountId,\n credentialType: ref.credentialType,\n vaultRef: ref.vaultRef,\n ...(ref.metadata ? { metadata: ref.metadata } : {}),\n ...(ref.expiresAt !== undefined\n ? { expiresAt: ref.expiresAt }\n : {}),\n });\n },\n });\n } else if (typeof writer.setCredentialRef === \"function\") {\n writers.push({\n name: \"setCredentialRef\",\n write: async (ref) => {\n await writer.setCredentialRef?.({\n accountId,\n credentialType: ref.credentialType,\n vaultRef: ref.vaultRef,\n ...(ref.metadata ? { metadata: ref.metadata } : {}),\n ...(ref.expiresAt !== undefined\n ? { expiresAt: ref.expiresAt }\n : {}),\n });\n },\n });\n }\n }\n return writers;\n}\n\nasync function writeWithFirstAvailableVault(\n writers: VaultWriter[],\n plannedRef: string,\n credential: ConnectorCredentialInput,\n): Promise<string> {\n const errors: string[] = [];\n for (const writer of writers) {\n try {\n return await writer.write(plannedRef, credential);\n } catch (error) {\n errors.push(\n `${writer.name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n throw new Error(\n `Failed to persist connector credential ref ${plannedRef}: ${errors.join(\"; \")}`,\n );\n}\n\nasync function writeRefsToStorage(\n writers: CredentialRefWriter[],\n refs: ConnectorCredentialRefMetadata[],\n): Promise<void> {\n const errors: string[] = [];\n for (const writer of writers) {\n try {\n for (const ref of refs) {\n await writer.write(ref);\n }\n return;\n } catch (error) {\n errors.push(\n `${writer.name}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n throw new Error(\n `Failed to persist connector credential refs: ${errors.join(\"; \")}`,\n );\n}\n\nfunction buildConnectorCredentialVaultRef(params: {\n agentId: string;\n provider: string;\n accountId: string;\n credentialType: string;\n}): string {\n return [\n \"connector\",\n normalizeVaultSegment(params.agentId),\n normalizeVaultSegment(params.provider),\n normalizeVaultSegment(params.accountId),\n normalizeVaultSegment(params.credentialType),\n ].join(\".\");\n}\n\nfunction normalizeVaultSegment(value: string): string {\n const normalized = value\n .trim()\n .replace(/[^a-zA-Z0-9_-]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n return (normalized || \"unknown\").slice(0, 64);\n}\n\nfunction getFirstService(\n runtime: IAgentRuntime,\n serviceTypes: readonly string[],\n): unknown {\n for (const serviceType of serviceTypes) {\n const service = getService(runtime, serviceType);\n if (service) return service;\n }\n return null;\n}\n\nfunction getService(runtime: IAgentRuntime, serviceType: string): unknown {\n try {\n return runtime.getService?.(serviceType) ?? null;\n } catch {\n return null;\n }\n}\n\nfunction nonEmptyString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n",
|
|
9
|
-
"import type {\n Character,\n EntityPayload,\n EventPayload,\n MessagePayload,\n WorldPayload,\n} from \"@elizaos/core\";\nimport type { App as BoltApp } from \"@slack/bolt\";\n\ntype WebClient = BoltApp[\"client\"];\n\n/**\n * Slack-specific event types\n */\nexport enum SlackEventTypes {\n MESSAGE_RECEIVED = \"SLACK_MESSAGE_RECEIVED\",\n MESSAGE_SENT = \"SLACK_MESSAGE_SENT\",\n REACTION_ADDED = \"SLACK_REACTION_ADDED\",\n REACTION_REMOVED = \"SLACK_REACTION_REMOVED\",\n CHANNEL_JOINED = \"SLACK_CHANNEL_JOINED\",\n CHANNEL_LEFT = \"SLACK_CHANNEL_LEFT\",\n MEMBER_JOINED_CHANNEL = \"SLACK_MEMBER_JOINED_CHANNEL\",\n MEMBER_LEFT_CHANNEL = \"SLACK_MEMBER_LEFT_CHANNEL\",\n APP_MENTION = \"SLACK_APP_MENTION\",\n SLASH_COMMAND = \"SLACK_SLASH_COMMAND\",\n FILE_SHARED = \"SLACK_FILE_SHARED\",\n THREAD_REPLY = \"SLACK_THREAD_REPLY\",\n}\n\nexport interface SlackMessageReceivedPayload extends MessagePayload {\n channelId: string;\n threadTs: string | undefined;\n userId: string;\n teamId: string | undefined;\n isThreadReply: boolean;\n files: SlackFile[];\n}\n\nexport interface SlackMessageSentPayload extends MessagePayload {\n channelId: string;\n threadTs: string | undefined;\n messageTs: string;\n}\n\nexport interface SlackReactionPayload extends EventPayload {\n reaction: string;\n userId: string;\n channelId: string;\n messageTs: string;\n itemUser: string | undefined;\n}\n\nexport interface SlackChannelPayload extends WorldPayload {\n channelId: string;\n channelName: string;\n channelType: SlackChannelType;\n}\n\nexport interface SlackMemberPayload extends EntityPayload {\n userId: string;\n channelId: string;\n}\n\nexport interface SlackAppMentionPayload extends MessagePayload {\n channelId: string;\n userId: string;\n threadTs: string | undefined;\n}\n\nexport interface SlackSlashCommandPayload extends EventPayload {\n command: string;\n text: string;\n userId: string;\n channelId: string;\n teamId: string;\n responseUrl: string;\n triggerId: string;\n}\n\nexport interface SlackFile {\n id: string;\n name: string;\n title: string;\n mimetype: string;\n filetype: string;\n size: number;\n urlPrivate: string;\n urlPrivateDownload: string | undefined;\n permalink: string;\n thumb64: string | undefined;\n thumb80: string | undefined;\n thumb360: string | undefined;\n}\n\nexport type SlackChannelType = \"channel\" | \"group\" | \"im\" | \"mpim\";\n\nexport interface SlackEventPayloadMap {\n [SlackEventTypes.MESSAGE_RECEIVED]: SlackMessageReceivedPayload;\n [SlackEventTypes.MESSAGE_SENT]: SlackMessageSentPayload;\n [SlackEventTypes.REACTION_ADDED]: SlackReactionPayload;\n [SlackEventTypes.REACTION_REMOVED]: SlackReactionPayload;\n [SlackEventTypes.CHANNEL_JOINED]: SlackChannelPayload;\n [SlackEventTypes.CHANNEL_LEFT]: SlackChannelPayload;\n [SlackEventTypes.MEMBER_JOINED_CHANNEL]: SlackMemberPayload;\n [SlackEventTypes.MEMBER_LEFT_CHANNEL]: SlackMemberPayload;\n [SlackEventTypes.APP_MENTION]: SlackAppMentionPayload;\n [SlackEventTypes.SLASH_COMMAND]: SlackSlashCommandPayload;\n [SlackEventTypes.FILE_SHARED]: SlackMessageReceivedPayload;\n [SlackEventTypes.THREAD_REPLY]: SlackMessageReceivedPayload;\n}\n\nexport interface SlackUser {\n id: string;\n teamId: string | undefined;\n name: string;\n deleted: boolean;\n realName: string | undefined;\n tz: string | undefined;\n tzLabel: string | undefined;\n tzOffset: number | undefined;\n profile: SlackUserProfile;\n isAdmin: boolean;\n isOwner: boolean;\n isPrimaryOwner: boolean;\n isRestricted: boolean;\n isUltraRestricted: boolean;\n isBot: boolean;\n isAppUser: boolean;\n updated: number;\n}\n\nexport interface SlackUserProfile {\n title: string | undefined;\n phone: string | undefined;\n skype: string | undefined;\n realName: string | undefined;\n realNameNormalized: string | undefined;\n displayName: string | undefined;\n displayNameNormalized: string | undefined;\n statusText: string | undefined;\n statusEmoji: string | undefined;\n statusExpiration: number | undefined;\n avatarHash: string | undefined;\n email: string | undefined;\n image24: string | undefined;\n image32: string | undefined;\n image48: string | undefined;\n image72: string | undefined;\n image192: string | undefined;\n image512: string | undefined;\n image1024: string | undefined;\n imageOriginal: string | undefined;\n team: string | undefined;\n}\n\nexport interface SlackChannel {\n id: string;\n name: string;\n isChannel: boolean;\n isGroup: boolean;\n isIm: boolean;\n isMpim: boolean;\n isPrivate: boolean;\n isArchived: boolean;\n isGeneral: boolean;\n isShared: boolean;\n isOrgShared: boolean;\n isMember: boolean;\n topic: SlackChannelTopic | undefined;\n purpose: SlackChannelPurpose | undefined;\n numMembers: number | undefined;\n created: number;\n creator: string;\n}\n\nexport interface SlackChannelTopic {\n value: string;\n creator: string;\n lastSet: number;\n}\n\nexport interface SlackChannelPurpose {\n value: string;\n creator: string;\n lastSet: number;\n}\n\nexport interface SlackMessage {\n type: string;\n subtype: string | undefined;\n ts: string;\n user: string | undefined;\n text: string;\n threadTs: string | undefined;\n replyCount: number | undefined;\n replyUsersCount: number | undefined;\n latestReply: string | undefined;\n reactions: SlackReaction[] | undefined;\n files: SlackFile[] | undefined;\n attachments: SlackAttachment[] | undefined;\n blocks: SlackBlock[] | undefined;\n}\n\nexport interface SlackReaction {\n name: string;\n count: number;\n users: string[];\n}\n\nexport interface SlackAttachment {\n id: number;\n fallback: string | undefined;\n color: string | undefined;\n pretext: string | undefined;\n authorName: string | undefined;\n authorLink: string | undefined;\n authorIcon: string | undefined;\n title: string | undefined;\n titleLink: string | undefined;\n text: string | undefined;\n fields: SlackAttachmentField[] | undefined;\n imageUrl: string | undefined;\n thumbUrl: string | undefined;\n footer: string | undefined;\n footerIcon: string | undefined;\n ts: string | undefined;\n}\n\nexport interface SlackAttachmentField {\n title: string;\n value: string;\n short: boolean;\n}\n\nexport interface SlackBlock {\n type: string;\n blockId: string | undefined;\n elements: SlackBlockElement[] | undefined;\n text: SlackBlockText | undefined;\n}\n\nexport interface SlackBlockElement {\n type: string;\n text: SlackBlockText | undefined;\n actionId: string | undefined;\n url: string | undefined;\n value: string | undefined;\n style: string | undefined;\n}\n\nexport interface SlackBlockText {\n type: string;\n text: string;\n emoji: boolean | undefined;\n verbatim: boolean | undefined;\n}\n\nexport interface SlackTeam {\n id: string;\n name: string;\n domain: string;\n emailDomain: string | undefined;\n icon: SlackTeamIcon;\n}\n\nexport interface SlackTeamIcon {\n image34: string | undefined;\n image44: string | undefined;\n image68: string | undefined;\n image88: string | undefined;\n image102: string | undefined;\n image132: string | undefined;\n image230: string | undefined;\n imageDefault: boolean;\n}\n\nexport interface ISlackService {\n app: BoltApp | null;\n client: WebClient | null;\n character: Character;\n botUserId: string | null;\n teamId: string | null;\n}\n\nexport const SLACK_SERVICE_NAME = \"slack\";\n\nexport const ServiceType = {\n SLACK: \"slack\",\n} as const;\n\nexport interface SlackSettings {\n allowedChannelIds: string[] | undefined;\n shouldIgnoreBotMessages: boolean;\n shouldRespondOnlyToMentions: boolean;\n}\n\nexport interface SlackMessageSendOptions {\n threadTs: string | undefined;\n replyBroadcast: boolean | undefined;\n unfurlLinks: boolean | undefined;\n unfurlMedia: boolean | undefined;\n mrkdwn: boolean | undefined;\n attachments: SlackAttachment[] | undefined;\n blocks: SlackBlock[] | undefined;\n}\n\nexport class SlackPluginError extends Error {\n constructor(\n message: string,\n public readonly code: string,\n ) {\n super(message);\n this.name = \"SlackPluginError\";\n }\n}\n\nexport class SlackServiceNotInitializedError extends SlackPluginError {\n constructor() {\n super(\"Slack service is not initialized\", \"SERVICE_NOT_INITIALIZED\");\n this.name = \"SlackServiceNotInitializedError\";\n }\n}\n\nexport class SlackClientNotAvailableError extends SlackPluginError {\n constructor() {\n super(\"Slack client is not available\", \"CLIENT_NOT_AVAILABLE\");\n this.name = \"SlackClientNotAvailableError\";\n }\n}\n\nexport class SlackConfigurationError extends SlackPluginError {\n constructor(missingConfig: string) {\n super(`Missing required configuration: ${missingConfig}`, \"MISSING_CONFIG\");\n this.name = \"SlackConfigurationError\";\n }\n}\n\nexport class SlackApiError extends SlackPluginError {\n constructor(\n message: string,\n public readonly apiErrorCode: string | undefined,\n ) {\n super(message, \"API_ERROR\");\n this.name = \"SlackApiError\";\n }\n}\n\n/**\n * Validates a Slack channel ID format\n */\nexport function isValidChannelId(id: string): boolean {\n // Slack channel IDs start with C (public), G (private/group), or D (DM)\n return /^[CGD][A-Z0-9]{8,}$/i.test(id);\n}\n\n/**\n * Validates a Slack user ID format\n */\nexport function isValidUserId(id: string): boolean {\n // Slack user IDs start with U or W (enterprise grid)\n return /^[UW][A-Z0-9]{8,}$/i.test(id);\n}\n\n/**\n * Validates a Slack team ID format\n */\nexport function isValidTeamId(id: string): boolean {\n // Slack team IDs start with T\n return /^T[A-Z0-9]{8,}$/i.test(id);\n}\n\n/**\n * Validates a Slack message timestamp format\n */\nexport function isValidMessageTs(ts: string): boolean {\n // Slack timestamps are in the format: 1234567890.123456\n return /^\\d+\\.\\d{6}$/.test(ts);\n}\n\n/**\n * Parses a Slack message link to extract channel and message IDs\n */\nexport function parseSlackMessageLink(\n link: string,\n): { channelId: string; messageTs: string } | null {\n // Format: https://workspace.slack.com/archives/C12345678/p1234567890123456\n const match = link.match(/\\/archives\\/([CGD][A-Z0-9]+)\\/p(\\d+)/i);\n if (!match) return null;\n\n const channelId = match[1];\n const ts = match[2];\n // Convert the timestamp: p1234567890123456 -> 1234567890.123456\n const messageTs = `${ts.slice(0, 10)}.${ts.slice(10)}`;\n\n return { channelId, messageTs };\n}\n\n/**\n * Formats a message timestamp for use in Slack links\n */\nexport function formatMessageTsForLink(ts: string): string {\n // Convert: 1234567890.123456 -> p1234567890123456\n return `p${ts.replace(\".\", \"\")}`;\n}\n\n/**\n * Gets the display name for a Slack user\n */\nexport function getSlackUserDisplayName(user: SlackUser): string {\n return user.profile.displayName || user.profile.realName || user.name;\n}\n\n/**\n * Determines the channel type from a Slack channel object\n */\nexport function getSlackChannelType(channel: SlackChannel): SlackChannelType {\n if (channel.isIm) return \"im\";\n if (channel.isMpim) return \"mpim\";\n if (channel.isGroup || channel.isPrivate) return \"group\";\n return \"channel\";\n}\n\n/**\n * Maximum message length for Slack messages\n */\nexport const MAX_SLACK_MESSAGE_LENGTH = 4000;\n\n/**\n * Maximum number of blocks per message\n */\nexport const MAX_SLACK_BLOCKS = 50;\n\n/**\n * Maximum file size for uploads (in bytes) - 1GB for paid, varies for free\n */\nexport const MAX_SLACK_FILE_SIZE = 1024 * 1024 * 1024;\n",
|
|
10
|
-
"import {\n ChannelType,\n type Character,\n type Content,\n createUniqueUuid,\n type EventPayload,\n type HandlerCallback,\n type IAgentRuntime,\n type IMessageService,\n type Media,\n type Memory,\n type MessageConnectorChatContext,\n type MessageConnectorQueryContext,\n type MessageConnectorTarget,\n type MessageConnectorUserContext,\n type Room,\n Service,\n stringToUuid,\n type TargetInfo,\n type UUID,\n type World,\n} from \"@elizaos/core\";\nimport { App, LogLevel } from \"@slack/bolt\";\nimport type { WebAPICallResult } from \"@slack/web-api\";\n\ntype WebClient = App[\"client\"];\ntype AccountScopedTargetInfo = TargetInfo & { accountId?: string };\ntype AccountScopedConnectorContext = MessageConnectorQueryContext & {\n accountId?: string;\n account?: { accountId?: string };\n};\ntype MessageConnectorRegistration = Parameters<\n IAgentRuntime[\"registerMessageConnector\"]\n>[0];\n\ntype ConnectorFetchMessagesParams = {\n target?: TargetInfo;\n accountId?: string;\n limit?: number;\n before?: string;\n after?: string;\n cursor?: string;\n channelId?: string;\n roomId?: UUID;\n threadId?: string;\n};\n\ntype ConnectorSearchMessagesParams = ConnectorFetchMessagesParams & {\n query?: string;\n};\n\ntype ConnectorMessageMutationParams = {\n target?: TargetInfo;\n accountId?: string;\n channelId?: string;\n roomId?: UUID;\n threadId?: string;\n messageId?: string;\n messageTs?: string;\n emoji?: string;\n remove?: boolean;\n pin?: boolean;\n text?: string;\n content?: Content;\n};\n\ntype ConnectorUserLookupParams = {\n target?: TargetInfo;\n userId?: string;\n username?: string;\n handle?: string;\n query?: string;\n};\n\ntype ExtendedMessageConnectorRegistration = MessageConnectorRegistration & {\n listServers?: (context: MessageConnectorQueryContext) => Promise<World[]>;\n fetchMessages?: (\n context: MessageConnectorQueryContext,\n params: ConnectorFetchMessagesParams,\n ) => Promise<Memory[]>;\n searchMessages?: (\n context: MessageConnectorQueryContext,\n params: ConnectorSearchMessagesParams,\n ) => Promise<Memory[]>;\n reactHandler?: (\n runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ) => Promise<void>;\n editHandler?: (\n runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ) => Promise<Memory>;\n deleteHandler?: (\n runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ) => Promise<void>;\n pinHandler?: (\n runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ) => Promise<void>;\n getUser?: (\n runtime: IAgentRuntime,\n params: ConnectorUserLookupParams,\n ) => Promise<unknown>;\n};\n\ntype SlackApiUserProfile = {\n title?: string;\n phone?: string;\n skype?: string;\n real_name?: string;\n real_name_normalized?: string;\n display_name?: string;\n display_name_normalized?: string;\n status_text?: string;\n status_emoji?: string;\n status_expiration?: number;\n avatar_hash?: string;\n email?: string;\n image_24?: string;\n image_32?: string;\n image_48?: string;\n image_72?: string;\n image_192?: string;\n image_512?: string;\n image_1024?: string;\n image_original?: string;\n team?: string;\n};\n\ntype SlackApiUserMember = {\n id?: string;\n team_id?: string;\n name?: string;\n deleted?: boolean;\n real_name?: string;\n tz?: string;\n tz_label?: string;\n tz_offset?: number;\n profile?: SlackApiUserProfile;\n is_admin?: boolean;\n is_owner?: boolean;\n is_primary_owner?: boolean;\n is_restricted?: boolean;\n is_ultra_restricted?: boolean;\n is_bot?: boolean;\n is_app_user?: boolean;\n updated?: number;\n};\n\nconst SLACK_CONNECTOR_CONTEXTS = [\"social\", \"connectors\"];\nconst SLACK_CONNECTOR_CAPABILITIES = [\n \"send_message\",\n \"read_messages\",\n \"search_messages\",\n \"resolve_targets\",\n \"list_rooms\",\n \"list_servers\",\n \"chat_context\",\n \"user_context\",\n \"react_message\",\n \"edit_message\",\n \"delete_message\",\n \"pin_message\",\n \"get_user\",\n];\nconst SLACK_USER_ID_PATTERN = /^[UW][A-Z0-9]{2,}$/i;\n\nfunction normalizeSlackConnectorQuery(value: string): string {\n return value\n .trim()\n .replace(/^<#([A-Z0-9]+)(?:\\|[^>]+)?>$/i, \"$1\")\n .replace(/^<@([A-Z0-9]+)>$/i, \"$1\")\n .replace(/^#/, \"\")\n .replace(/^@/, \"\")\n .toLowerCase();\n}\n\nfunction scoreSlackConnectorMatch(\n query: string,\n id: string,\n labels: Array<string | null | undefined>,\n): number {\n if (!query) {\n return 0.45;\n }\n if (id.toLowerCase() === query) {\n return 1;\n }\n\n let bestScore = 0;\n for (const label of labels) {\n const normalized = label?.trim().toLowerCase();\n if (!normalized) {\n continue;\n }\n if (normalized === query) {\n bestScore = Math.max(bestScore, 0.95);\n } else if (normalized.startsWith(query)) {\n bestScore = Math.max(bestScore, 0.85);\n } else if (normalized.includes(query)) {\n bestScore = Math.max(bestScore, 0.7);\n }\n }\n return bestScore;\n}\n\nfunction extractSlackUserIdFromMetadata(\n metadata: unknown,\n accountId?: string | null,\n): string | null {\n if (!metadata || typeof metadata !== \"object\") {\n return null;\n }\n\n const record = metadata as Record<string, unknown>;\n const slack =\n record.slack && typeof record.slack === \"object\"\n ? (record.slack as Record<string, unknown>)\n : null;\n\n const metadataAccountId =\n typeof record.accountId === \"string\"\n ? record.accountId\n : typeof slack?.accountId === \"string\"\n ? slack.accountId\n : undefined;\n if (\n accountId &&\n metadataAccountId &&\n normalizeAccountId(metadataAccountId) !== normalizeAccountId(accountId)\n ) {\n return null;\n }\n\n const candidates = [\n slack?.userId,\n slack?.id,\n record.slackUserId,\n record.originalId,\n ];\n\n for (const candidate of candidates) {\n if (\n typeof candidate === \"string\" &&\n SLACK_USER_ID_PATTERN.test(candidate)\n ) {\n return candidate;\n }\n }\n return null;\n}\n\n// Define Slack event types inline to avoid import issues\ninterface SlackMessageEventType {\n type: \"message\";\n channel: string;\n channel_type?: string;\n user?: string;\n text?: string;\n ts: string;\n thread_ts?: string;\n team?: string;\n bot_id?: string;\n files?: SlackFile[];\n}\n\ninterface SlackAppMentionEventType {\n type: \"app_mention\";\n channel: string;\n user?: string;\n text: string;\n ts: string;\n thread_ts?: string;\n event_ts: string;\n}\n\n// Helper to get message service from runtime\nconst getMessageService = (runtime: IAgentRuntime): IMessageService | null => {\n if (\"messageService\" in runtime) {\n const withMessageService = runtime as IAgentRuntime & {\n messageService?: IMessageService | null;\n };\n return withMessageService.messageService ?? null;\n }\n return null;\n};\n\nimport {\n DEFAULT_ACCOUNT_ID,\n listEnabledSlackAccounts,\n normalizeAccountId,\n type ResolvedSlackAccount,\n resolveDefaultSlackAccountId,\n} from \"./accounts\";\nimport { markdownToSlackMrkdwn } from \"./formatting\";\nimport {\n getSlackChannelType,\n getSlackUserDisplayName,\n type ISlackService,\n isValidChannelId,\n MAX_SLACK_MESSAGE_LENGTH,\n SLACK_SERVICE_NAME,\n type SlackAttachment,\n type SlackBlock,\n type SlackChannel,\n SlackEventTypes,\n type SlackFile,\n type SlackMessage,\n type SlackMessageSendOptions,\n type SlackSettings,\n type SlackUser,\n} from \"./types\";\n\ntype SlackAccountRuntime = {\n accountId: string;\n account: ResolvedSlackAccount;\n app: App;\n client: WebClient;\n botUserId: string | null;\n teamId: string | null;\n settings: SlackSettings;\n allowedChannelIds: Set<string>;\n dynamicChannelIds: Set<string>;\n userCache: Map<string, SlackUser>;\n channelCache: Map<string, SlackChannel>;\n isConnected: boolean;\n};\n\n/**\n * SlackService class for interacting with Slack via Socket Mode\n */\nexport class SlackService extends Service implements ISlackService {\n static serviceType: string = SLACK_SERVICE_NAME;\n capabilityDescription =\n \"The agent is able to send and receive messages on Slack\";\n\n app: App | null = null;\n client: WebClient | null = null;\n character: Character;\n botUserId: string | null = null;\n teamId: string | null = null;\n\n private settings: SlackSettings;\n private botToken: string | null = null;\n private appToken: string | null = null;\n private signingSecret: string | null = null;\n private defaultAccountId = DEFAULT_ACCOUNT_ID;\n private accountStates: Map<string, SlackAccountRuntime> = new Map();\n private accountStarts: Map<string, Promise<SlackAccountRuntime>> = new Map();\n private allowedChannelIds: Set<string> = new Set();\n private dynamicChannelIds: Set<string> = new Set();\n private userCache: Map<string, SlackUser> = new Map();\n private channelCache: Map<string, SlackChannel> = new Map();\n private isConnected = false;\n\n constructor(runtime: IAgentRuntime) {\n super(runtime);\n this.character = runtime.character;\n this.settings = this.loadSettings();\n\n // Parse allowed channel IDs for the legacy/default account path.\n this.allowedChannelIds = this.buildAllowedChannelSet();\n if (this.allowedChannelIds.size > 0) {\n this.runtime.logger.debug(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n allowedChannelIds: Array.from(this.allowedChannelIds),\n },\n \"Channel restrictions enabled\",\n );\n }\n }\n\n private loadSettings(account?: ResolvedSlackAccount): SlackSettings {\n const ignoreBotMessages = this.runtime.getSetting(\n \"SLACK_SHOULD_IGNORE_BOT_MESSAGES\",\n );\n const respondOnlyToMentions = this.runtime.getSetting(\n \"SLACK_SHOULD_RESPOND_ONLY_TO_MENTIONS\",\n );\n\n return {\n allowedChannelIds: account?.config.allowedChannelIds,\n shouldIgnoreBotMessages:\n account?.config.shouldIgnoreBotMessages ??\n (ignoreBotMessages === \"true\" || ignoreBotMessages === true),\n shouldRespondOnlyToMentions:\n account?.config.shouldRespondOnlyToMentions ??\n (respondOnlyToMentions === \"true\" || respondOnlyToMentions === true),\n };\n }\n\n private buildAllowedChannelSet(account?: ResolvedSlackAccount): Set<string> {\n const allowed = new Set<string>();\n const configuredIds = account?.config.allowedChannelIds;\n const channelIdsRaw =\n configuredIds && configuredIds.length > 0\n ? configuredIds.join(\",\")\n : (this.runtime.getSetting(\"SLACK_CHANNEL_IDS\") as string | undefined);\n\n if (!channelIdsRaw?.trim()) {\n return allowed;\n }\n\n channelIdsRaw\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s.length > 0 && isValidChannelId(s))\n .forEach((id) => {\n allowed.add(id);\n });\n\n return allowed;\n }\n\n static async start(runtime: IAgentRuntime): Promise<SlackService> {\n const service = new SlackService(runtime);\n\n const accounts = listEnabledSlackAccounts(runtime);\n service.defaultAccountId = resolveDefaultSlackAccountId(runtime);\n\n if (accounts.length === 0) {\n runtime.logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"No enabled Slack accounts configured, Slack service will not start\",\n );\n return service;\n }\n\n let startedAccounts = 0;\n let lastError: unknown;\n for (const account of accounts) {\n if (!account.appToken?.trim()) {\n runtime.logger.warn(\n {\n src: \"plugin:slack\",\n agentId: runtime.agentId,\n accountId: account.accountId,\n },\n \"SLACK_APP_TOKEN not provided for Slack account, Socket Mode will not work\",\n );\n continue;\n }\n\n try {\n await service.initializeAccount(account);\n startedAccounts++;\n } catch (error) {\n lastError = error;\n runtime.logger.error(\n {\n src: \"plugin:slack\",\n agentId: runtime.agentId,\n accountId: account.accountId,\n error: error instanceof Error ? error.message : String(error),\n },\n \"Failed to initialize Slack account\",\n );\n }\n }\n\n if (startedAccounts === 0) {\n if (lastError) {\n throw lastError;\n }\n runtime.logger.warn(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"Slack service started without connected accounts\",\n );\n }\n\n return service;\n }\n\n static async stop(runtime: IAgentRuntime): Promise<void> {\n const service = runtime.getService(SLACK_SERVICE_NAME) as\n | SlackService\n | undefined;\n if (service) {\n await service.shutdown();\n }\n }\n\n static registerSendHandlers(\n runtime: IAgentRuntime,\n serviceInstance: SlackService,\n ): void {\n if (!serviceInstance) {\n return;\n }\n\n const registerConnector = (accountId?: string) => {\n const normalizedAccountId = accountId\n ? normalizeAccountId(accountId)\n : undefined;\n const state = normalizedAccountId\n ? serviceInstance.getAccountState(normalizedAccountId)\n : serviceInstance.getDefaultAccountState();\n const sendHandler = async (\n handlerRuntime: IAgentRuntime,\n target: TargetInfo,\n content: Content,\n ): Promise<void> => {\n await serviceInstance.handleSendMessage(\n handlerRuntime,\n normalizedAccountId && !(target as AccountScopedTargetInfo).accountId\n ? ({ ...target, accountId: normalizedAccountId } as TargetInfo)\n : target,\n content,\n );\n };\n\n const withContextAccount = (\n context: MessageConnectorQueryContext,\n ): MessageConnectorQueryContext =>\n normalizedAccountId &&\n !(context as AccountScopedConnectorContext).accountId\n ? ({\n ...context,\n accountId: normalizedAccountId,\n account: (context as AccountScopedConnectorContext).account ?? {\n source: \"slack\",\n accountId: normalizedAccountId,\n label: state?.account.name ?? normalizedAccountId,\n },\n } as MessageConnectorQueryContext)\n : context;\n\n const registration: ExtendedMessageConnectorRegistration = {\n source: \"slack\",\n ...(normalizedAccountId ? { accountId: normalizedAccountId } : {}),\n ...(normalizedAccountId\n ? {\n account: {\n source: \"slack\",\n accountId: normalizedAccountId,\n label: state?.account.name ?? normalizedAccountId,\n authMethod: \"BOT_TOKEN\",\n metadata: {\n teamId: state?.teamId,\n },\n },\n }\n : {}),\n label: state?.account.name ? `Slack (${state.account.name})` : \"Slack\",\n description:\n \"Slack connector for sending, reading, searching, reacting to, editing, deleting, and pinning messages in channels, threads, and users.\",\n capabilities: [...SLACK_CONNECTOR_CAPABILITIES],\n supportedTargetKinds: [\"channel\", \"thread\", \"user\"],\n contexts: [...SLACK_CONNECTOR_CONTEXTS],\n metadata: {\n service: SLACK_SERVICE_NAME,\n maxMessageLength: MAX_SLACK_MESSAGE_LENGTH,\n ...(normalizedAccountId ? { accountId: normalizedAccountId } : {}),\n },\n resolveTargets: (query, context) =>\n serviceInstance.resolveConnectorTargets(\n query,\n withContextAccount(context),\n ),\n listRecentTargets: (context) =>\n serviceInstance.listRecentConnectorTargets(\n withContextAccount(context),\n ),\n listRooms: (context) =>\n serviceInstance.listConnectorRooms(withContextAccount(context)),\n listServers: (context) =>\n serviceInstance.listConnectorServers(withContextAccount(context)),\n fetchMessages: (context, params) =>\n serviceInstance.fetchConnectorMessages(withContextAccount(context), {\n ...params,\n ...(normalizedAccountId && !params.accountId\n ? { accountId: normalizedAccountId }\n : {}),\n }),\n searchMessages: (context, params) =>\n serviceInstance.searchConnectorMessages(withContextAccount(context), {\n ...params,\n ...(normalizedAccountId && !params.accountId\n ? { accountId: normalizedAccountId }\n : {}),\n }),\n reactHandler: (handlerRuntime, params) =>\n serviceInstance.reactConnectorMessage(handlerRuntime, {\n ...params,\n ...(normalizedAccountId && !params.accountId\n ? { accountId: normalizedAccountId }\n : {}),\n }),\n editHandler: (handlerRuntime, params) =>\n serviceInstance.editConnectorMessage(handlerRuntime, {\n ...params,\n ...(normalizedAccountId && !params.accountId\n ? { accountId: normalizedAccountId }\n : {}),\n }),\n deleteHandler: (handlerRuntime, params) =>\n serviceInstance.deleteConnectorMessage(handlerRuntime, {\n ...params,\n ...(normalizedAccountId && !params.accountId\n ? { accountId: normalizedAccountId }\n : {}),\n }),\n pinHandler: (handlerRuntime, params) =>\n serviceInstance.pinConnectorMessage(handlerRuntime, {\n ...params,\n ...(normalizedAccountId && !params.accountId\n ? { accountId: normalizedAccountId }\n : {}),\n }),\n getUser: (handlerRuntime, params) =>\n serviceInstance.getConnectorUser(handlerRuntime, {\n ...params,\n ...(normalizedAccountId && !params.target\n ? {\n target: {\n source: \"slack\",\n accountId: normalizedAccountId,\n } as TargetInfo,\n }\n : {}),\n }),\n getChatContext: (target, context) =>\n serviceInstance.getConnectorChatContext(\n normalizedAccountId &&\n !(target as AccountScopedTargetInfo).accountId\n ? ({ ...target, accountId: normalizedAccountId } as TargetInfo)\n : target,\n withContextAccount(context),\n ),\n getUserContext: (entityId, context) =>\n serviceInstance.getConnectorUserContext(\n entityId,\n withContextAccount(context),\n ),\n sendHandler,\n };\n\n runtime.registerMessageConnector(registration);\n };\n\n if (typeof runtime.registerMessageConnector === \"function\") {\n registerConnector();\n for (const accountId of serviceInstance.getRegisteredAccountIds()) {\n registerConnector(accountId);\n }\n runtime.logger.info(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"Registered Slack message connector\",\n );\n return;\n }\n\n runtime.registerSendHandler(\n \"slack\",\n serviceInstance.handleSendMessage.bind(serviceInstance),\n );\n runtime.logger.info(\n { src: \"plugin:slack\", agentId: runtime.agentId },\n \"Registered Slack send handler\",\n );\n }\n\n async stop(): Promise<void> {\n await this.shutdown();\n }\n\n private syncDefaultAccountAliases(): void {\n const state = this.getDefaultAccountState();\n this.app = state?.app ?? null;\n this.client = state?.client ?? null;\n this.botUserId = state?.botUserId ?? null;\n this.teamId = state?.teamId ?? null;\n this.botToken = state?.account.botToken ?? null;\n this.appToken = state?.account.appToken ?? null;\n this.signingSecret = state?.account.signingSecret ?? null;\n this.isConnected = Array.from(this.accountStates?.values?.() ?? []).some(\n (accountState) => accountState.isConnected,\n );\n }\n\n private async initializeAccount(\n account: ResolvedSlackAccount,\n ): Promise<SlackAccountRuntime> {\n const accountId = normalizeAccountId(account.accountId);\n const cached = this.accountStates.get(accountId);\n if (cached) {\n return cached;\n }\n\n const starting = this.accountStarts.get(accountId);\n if (starting) {\n return starting;\n }\n\n const startPromise = (async () => {\n if (!account.botToken || !account.appToken) {\n throw new Error(\n `Slack account ${accountId} requires bot and app tokens`,\n );\n }\n\n this.runtime.logger.info(\n { src: \"plugin:slack\", agentId: this.runtime.agentId, accountId },\n \"Initializing Slack service with Socket Mode\",\n );\n\n const app = new App({\n token: account.botToken,\n appToken: account.appToken,\n socketMode: true,\n logLevel: LogLevel.INFO,\n ...(account.signingSecret\n ? { signingSecret: account.signingSecret }\n : {}),\n });\n\n const state: SlackAccountRuntime = {\n accountId,\n account,\n app,\n client: app.client,\n botUserId: null,\n teamId: null,\n settings: this.loadSettings(account),\n allowedChannelIds: this.buildAllowedChannelSet(account),\n dynamicChannelIds: new Set(),\n userCache: new Map(),\n channelCache: new Map(),\n isConnected: false,\n };\n\n const authResult = await state.client.auth.test();\n state.botUserId = authResult.user_id as string;\n state.teamId = authResult.team_id as string;\n\n this.accountStates.set(accountId, state);\n this.syncDefaultAccountAliases();\n\n this.runtime.logger.info(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n accountId,\n botUserId: state.botUserId,\n teamId: state.teamId,\n },\n \"Slack bot authenticated\",\n );\n\n this.registerEventHandlers(state);\n\n try {\n await app.start();\n } catch (error) {\n this.accountStates.delete(accountId);\n this.syncDefaultAccountAliases();\n throw error;\n }\n state.isConnected = true;\n this.syncDefaultAccountAliases();\n\n this.runtime.logger.info(\n { src: \"plugin:slack\", agentId: this.runtime.agentId, accountId },\n \"Slack account started successfully\",\n );\n\n await this.ensureWorkspaceExists(accountId);\n return state;\n })();\n\n this.accountStarts.set(accountId, startPromise);\n try {\n return await startPromise;\n } finally {\n this.accountStarts.delete(accountId);\n }\n }\n\n private async shutdown(): Promise<void> {\n const states =\n this.accountStates instanceof Map\n ? Array.from(this.accountStates.values())\n : [];\n if (states.length > 0) {\n for (const state of states) {\n await state.app.stop();\n state.isConnected = false;\n this.runtime.logger.info(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n accountId: state.accountId,\n },\n \"Slack account stopped\",\n );\n }\n this.accountStates.clear();\n this.syncDefaultAccountAliases();\n return;\n }\n\n if (this.app) {\n await this.app.stop();\n this.app = null;\n this.client = null;\n this.isConnected = false;\n\n this.runtime.logger.info(\n { src: \"plugin:slack\", agentId: this.runtime.agentId },\n \"Slack service stopped\",\n );\n }\n }\n\n private registerEventHandlers(state?: SlackAccountRuntime): void {\n const app = state?.app ?? this.app;\n const accountId = state?.accountId ?? this.defaultAccountId;\n if (!app) return;\n\n // Handle regular messages\n app.message(async ({ message, client }) => {\n await this.handleMessage(\n message as SlackMessageEventType,\n client,\n accountId,\n );\n });\n\n // Handle app mentions\n app.event(\"app_mention\", async ({ event, client }) => {\n await this.handleAppMention(\n event as SlackAppMentionEventType,\n client,\n accountId,\n );\n });\n\n // Handle reactions\n app.event(\"reaction_added\", async ({ event }) => {\n await this.handleReactionAdded(event, accountId);\n });\n\n app.event(\"reaction_removed\", async ({ event }) => {\n await this.handleReactionRemoved(event, accountId);\n });\n\n // Handle channel joins/leaves\n app.event(\"member_joined_channel\", async ({ event }) => {\n await this.handleMemberJoinedChannel(event, accountId);\n });\n\n app.event(\"member_left_channel\", async ({ event }) => {\n await this.handleMemberLeftChannel(event, accountId);\n });\n\n // Handle file shares\n app.event(\"file_shared\", async ({ event }) => {\n await this.handleFileShared(event, accountId);\n });\n }\n\n private getDefaultAccountState(): SlackAccountRuntime | null {\n const states = this.accountStates;\n if (!(states instanceof Map) || states.size === 0) {\n return null;\n }\n const defaultId = normalizeAccountId(\n this.defaultAccountId ?? DEFAULT_ACCOUNT_ID,\n );\n return states.get(defaultId) ?? states.values().next().value ?? null;\n }\n\n private getAccountState(\n accountId?: string | null,\n ): SlackAccountRuntime | null {\n const states = this.accountStates;\n if (!(states instanceof Map) || states.size === 0) {\n return null;\n }\n if (accountId) {\n return states.get(normalizeAccountId(accountId)) ?? null;\n }\n return this.getDefaultAccountState();\n }\n\n private getClientForAccount(accountId?: string | null): WebClient | null {\n const state = this.getAccountState(accountId);\n if (state?.client) {\n return state.client;\n }\n const requested = accountId ? normalizeAccountId(accountId) : null;\n const defaultId = normalizeAccountId(\n this.defaultAccountId ?? DEFAULT_ACCOUNT_ID,\n );\n if (!requested || requested === defaultId) {\n return this.client;\n }\n return null;\n }\n\n private getSettingsForAccount(accountId?: string | null): SlackSettings {\n return this.getAccountState(accountId)?.settings ?? this.settings;\n }\n\n private getAllowedChannelIdsForAccount(\n accountId?: string | null,\n ): Set<string> {\n return (\n this.getAccountState(accountId)?.allowedChannelIds ??\n this.allowedChannelIds\n );\n }\n\n private getDynamicChannelIdsForAccount(\n accountId?: string | null,\n ): Set<string> {\n return (\n this.getAccountState(accountId)?.dynamicChannelIds ??\n this.dynamicChannelIds\n );\n }\n\n private getUserCacheForAccount(\n accountId?: string | null,\n ): Map<string, SlackUser> {\n return this.getAccountState(accountId)?.userCache ?? this.userCache;\n }\n\n private getChannelCacheForAccount(\n accountId?: string | null,\n ): Map<string, SlackChannel> {\n return this.getAccountState(accountId)?.channelCache ?? this.channelCache;\n }\n\n private getBotUserIdForAccount(accountId?: string | null): string | null {\n return this.getAccountState(accountId)?.botUserId ?? this.botUserId;\n }\n\n private getTeamIdForAccount(accountId?: string | null): string | null {\n return this.getAccountState(accountId)?.teamId ?? this.teamId;\n }\n\n private getRegisteredAccountIds(): string[] {\n const states = this.accountStates;\n if (states instanceof Map && states.size > 0) {\n return Array.from(states.keys());\n }\n return [normalizeAccountId(this.defaultAccountId ?? DEFAULT_ACCOUNT_ID)];\n }\n\n private resolveAccountIdFromContext(\n context?: MessageConnectorQueryContext | null,\n target?: TargetInfo | null,\n ): string | undefined {\n const scopedTarget = target as AccountScopedTargetInfo | null | undefined;\n const scopedContext = context as\n | AccountScopedConnectorContext\n | null\n | undefined;\n return (\n scopedTarget?.accountId ??\n (scopedContext?.target as AccountScopedTargetInfo | undefined)\n ?.accountId ??\n scopedContext?.accountId ??\n scopedContext?.account?.accountId ??\n undefined\n );\n }\n\n private async resolveAccountIdForTarget(\n runtime: IAgentRuntime,\n target?: TargetInfo | null,\n fallback?: { accountId?: string; roomId?: UUID } | null,\n ): Promise<string> {\n const direct =\n (target as AccountScopedTargetInfo | null | undefined)?.accountId ??\n fallback?.accountId ??\n undefined;\n if (direct) {\n return normalizeAccountId(direct);\n }\n\n const roomId = target?.roomId ?? fallback?.roomId;\n if (roomId && typeof runtime.getRoom === \"function\") {\n const room = await runtime.getRoom(roomId);\n const metadata = room?.metadata as Record<string, unknown> | undefined;\n if (\n typeof metadata?.accountId === \"string\" &&\n metadata.accountId.trim()\n ) {\n return normalizeAccountId(metadata.accountId);\n }\n const slack =\n metadata?.slack && typeof metadata.slack === \"object\"\n ? (metadata.slack as Record<string, unknown>)\n : undefined;\n if (typeof slack?.accountId === \"string\" && slack.accountId.trim()) {\n return normalizeAccountId(slack.accountId);\n }\n }\n\n return normalizeAccountId(this.defaultAccountId ?? DEFAULT_ACCOUNT_ID);\n }\n\n private getCandidateAccountIds(\n context?: MessageConnectorQueryContext | null,\n target?: TargetInfo | null,\n ): string[] {\n const explicit = this.resolveAccountIdFromContext(context, target);\n if (explicit) {\n return [normalizeAccountId(explicit)];\n }\n return this.getRegisteredAccountIds();\n }\n\n private scopedSlackKey(\n prefix: string,\n key: string,\n accountId?: string | null,\n ): string {\n const normalized = normalizeAccountId(\n accountId ?? this.defaultAccountId ?? DEFAULT_ACCOUNT_ID,\n );\n return normalized === DEFAULT_ACCOUNT_ID\n ? `${prefix}-${key}`\n : `${prefix}-${normalized}-${key}`;\n }\n\n private buildEventPayload(accountId?: string | null): EventPayload {\n const normalized = normalizeAccountId(\n accountId ?? this.defaultAccountId ?? DEFAULT_ACCOUNT_ID,\n );\n return {\n runtime: this.runtime,\n source: \"slack\",\n accountId: normalized,\n metadata: { accountId: normalized },\n } as EventPayload;\n }\n\n private async handleMessage(\n message: SlackMessageEventType,\n _client: WebClient,\n accountId = this.defaultAccountId,\n ): Promise<void> {\n const settings = this.getSettingsForAccount(accountId);\n const botUserId = this.getBotUserIdForAccount(accountId);\n\n // Ignore bot messages if configured\n if (settings.shouldIgnoreBotMessages && message.bot_id) {\n return;\n }\n\n // Ignore messages from self\n if (message.user === botUserId) {\n return;\n }\n\n // Check channel restrictions\n if (!this.isChannelAllowed(message.channel, accountId)) {\n this.runtime.logger.debug(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n accountId,\n channelId: message.channel,\n },\n \"Message received in non-allowed channel, ignoring\",\n );\n return;\n }\n\n // Check if we should only respond to mentions\n const isMentioned = message.text?.includes(`<@${botUserId}>`);\n // Skip @mentions in channels — handleAppMention handles those\n if (isMentioned && message.channel_type !== \"im\") {\n return;\n }\n if (settings.shouldRespondOnlyToMentions && !isMentioned) {\n return;\n }\n\n const _isThreadReply = Boolean(\n message.thread_ts && message.thread_ts !== message.ts,\n );\n\n // Build memory from message\n const memory = await this.buildMemoryFromMessage(message, accountId);\n if (!memory) return;\n\n // Get or create room\n const room = await this.ensureRoomExists(\n message.channel,\n message.thread_ts,\n accountId,\n );\n\n const existingEntity = await this.runtime.getEntityById(memory.entityId);\n if (!existingEntity) {\n const user = await this.getUser(message.user, accountId);\n const displayName = user ? getSlackUserDisplayName(user) : message.user;\n await this.runtime.createEntity({\n id: memory.entityId,\n names: [displayName],\n metadata: {\n source: \"slack\",\n accountId,\n slack: {\n accountId,\n id: message.user,\n name: displayName,\n userName: user?.name || message.user,\n },\n },\n agentId: this.runtime.agentId,\n });\n }\n\n // Store the memory\n await this.runtime.createMemory(memory, \"messages\");\n\n // Emit event\n await this.runtime.emitEvent(\n SlackEventTypes.MESSAGE_RECEIVED as string,\n this.buildEventPayload(accountId),\n );\n\n // Process the message through the agent\n await this.processAgentMessage(\n memory,\n room,\n message.channel,\n message.thread_ts || message.ts,\n accountId,\n );\n }\n\n private async handleAppMention(\n event: SlackAppMentionEventType,\n _client: WebClient,\n accountId = this.defaultAccountId,\n ): Promise<void> {\n // Skip if no user (optional in AppMentionEvent)\n if (!event.user) return;\n\n // Build memory from mention\n const memory = await this.buildMemoryFromMention(\n {\n user: event.user,\n text: event.text,\n channel: event.channel,\n ts: event.ts,\n thread_ts: event.thread_ts,\n },\n accountId,\n );\n if (!memory) return;\n\n // Get or create room\n const room = await this.ensureRoomExists(\n event.channel,\n event.thread_ts,\n accountId,\n );\n\n const existingEntity = await this.runtime.getEntityById(memory.entityId);\n if (!existingEntity) {\n const user = await this.getUser(event.user, accountId);\n const displayName = user ? getSlackUserDisplayName(user) : event.user;\n await this.runtime.createEntity({\n id: memory.entityId,\n names: [displayName],\n metadata: {\n source: \"slack\",\n accountId,\n slack: {\n accountId,\n id: event.user,\n name: displayName,\n userName: user?.name || event.user,\n },\n },\n agentId: this.runtime.agentId,\n });\n }\n\n // Store the memory\n await this.runtime.createMemory(memory, \"messages\");\n\n // Emit event\n await this.runtime.emitEvent(\n SlackEventTypes.APP_MENTION as string,\n this.buildEventPayload(accountId),\n );\n\n // Process the message\n await this.processAgentMessage(\n memory,\n room,\n event.channel,\n event.thread_ts || event.ts,\n accountId,\n );\n }\n\n private async handleReactionAdded(\n _event: {\n user: string;\n reaction: string;\n item: { type: string; channel: string; ts: string };\n item_user?: string;\n },\n accountId = this.defaultAccountId,\n ): Promise<void> {\n await this.runtime.emitEvent(\n SlackEventTypes.REACTION_ADDED as string,\n this.buildEventPayload(accountId),\n );\n }\n\n private async handleReactionRemoved(\n _event: {\n user: string;\n reaction: string;\n item: { type: string; channel: string; ts: string };\n item_user?: string;\n },\n accountId = this.defaultAccountId,\n ): Promise<void> {\n await this.runtime.emitEvent(\n SlackEventTypes.REACTION_REMOVED as string,\n this.buildEventPayload(accountId),\n );\n }\n\n private async handleMemberJoinedChannel(\n event: {\n user: string;\n channel: string;\n team?: string;\n },\n accountId = this.defaultAccountId,\n ): Promise<void> {\n // If the bot joined, add to dynamic channels\n if (event.user === this.getBotUserIdForAccount(accountId)) {\n this.getDynamicChannelIdsForAccount(accountId).add(event.channel);\n await this.ensureRoomExists(event.channel, undefined, accountId);\n }\n\n await this.runtime.emitEvent(\n SlackEventTypes.MEMBER_JOINED_CHANNEL as string,\n this.buildEventPayload(accountId),\n );\n }\n\n private async handleMemberLeftChannel(\n event: {\n user: string;\n channel: string;\n team?: string;\n },\n accountId = this.defaultAccountId,\n ): Promise<void> {\n // If the bot left, remove from dynamic channels\n if (event.user === this.getBotUserIdForAccount(accountId)) {\n this.getDynamicChannelIdsForAccount(accountId).delete(event.channel);\n }\n\n await this.runtime.emitEvent(\n SlackEventTypes.MEMBER_LEFT_CHANNEL as string,\n this.buildEventPayload(accountId),\n );\n }\n\n private async handleFileShared(\n _event: {\n file_id: string;\n user_id: string;\n channel_id: string;\n },\n accountId = this.defaultAccountId,\n ): Promise<void> {\n await this.runtime.emitEvent(\n SlackEventTypes.FILE_SHARED as string,\n this.buildEventPayload(accountId),\n );\n }\n\n private isChannelAllowed(\n channelId: string,\n accountId?: string | null,\n ): boolean {\n const allowedChannelIds = this.getAllowedChannelIdsForAccount(accountId);\n const dynamicChannelIds = this.getDynamicChannelIdsForAccount(accountId);\n\n // If no restrictions, all channels allowed\n if (allowedChannelIds.size === 0 && dynamicChannelIds.size === 0) {\n return true;\n }\n\n // Check static and dynamic allowed lists\n return allowedChannelIds.has(channelId) || dynamicChannelIds.has(channelId);\n }\n\n private async processAgentMessage(\n memory: Memory,\n room: Room,\n channelId: string,\n threadTs: string,\n accountId = this.defaultAccountId,\n ): Promise<void> {\n const callback: HandlerCallback = async (\n response: Content,\n ): Promise<Memory[]> => {\n const responseText = response.text || \"\";\n if (!responseText.trim()) {\n this.runtime.logger.warn(\n { src: \"plugin:slack\", channelId, roomId: room.id },\n \"Empty response from model, skipping sendMessage\",\n );\n return [];\n }\n\n await this.sendMessage(\n channelId,\n responseText,\n {\n threadTs,\n replyBroadcast: undefined,\n unfurlLinks: undefined,\n unfurlMedia: undefined,\n mrkdwn: undefined,\n attachments: undefined,\n blocks: undefined,\n },\n accountId,\n );\n\n // Create memory for the response\n const responseMemory: Memory = {\n id: createUniqueUuid(this.runtime, `slack-response-${Date.now()}`),\n agentId: this.runtime.agentId,\n roomId: room.id,\n entityId: this.runtime.agentId,\n content: {\n text: response.text || \"\",\n source: \"slack\",\n inReplyTo: memory.id,\n metadata: { accountId },\n },\n metadata: {\n type: \"message\",\n source: \"slack\",\n provider: \"slack\",\n accountId,\n fromBot: true,\n fromId: this.runtime.agentId,\n sourceId: this.runtime.agentId,\n slack: {\n accountId,\n channelId,\n threadTs,\n },\n } satisfies Memory[\"metadata\"],\n createdAt: Date.now(),\n };\n\n await this.runtime.createMemory(responseMemory, \"messages\");\n\n await this.runtime.emitEvent(\n SlackEventTypes.MESSAGE_SENT as string,\n this.buildEventPayload(accountId),\n );\n\n return [responseMemory];\n };\n\n const messageService = getMessageService(this.runtime);\n if (messageService) {\n await messageService.handleMessage(this.runtime, memory, callback);\n }\n }\n\n private async buildMemoryFromMessage(\n message: SlackMessageEventType,\n accountId = this.defaultAccountId,\n ): Promise<Memory | null> {\n if (!message.user) return null;\n\n const roomId = await this.getRoomId(\n message.channel,\n message.thread_ts,\n accountId,\n );\n const entityId = this.getEntityId(message.user, accountId);\n\n // Get user info for display name\n const user = await this.getUser(message.user, accountId);\n const displayName = user ? getSlackUserDisplayName(user) : message.user;\n\n // Extract media from files\n const media: Media[] = [];\n if (\"files\" in message && message.files) {\n for (const file of message.files) {\n media.push({\n id: file.id,\n url: file.urlPrivate,\n title: file.title || file.name,\n source: \"slack\",\n description: file.name,\n });\n }\n }\n\n const memory: Memory = {\n id: createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\"slack\", message.ts, accountId),\n ),\n agentId: this.runtime.agentId,\n roomId,\n entityId,\n content: {\n text: message.text || \"\",\n source: \"slack\",\n name: displayName,\n metadata: { accountId },\n ...(media.length > 0 ? { attachments: media } : {}),\n },\n metadata: {\n type: \"message\",\n source: \"slack\",\n provider: \"slack\",\n accountId,\n timestamp: this.parseSlackTimestamp(message.ts),\n entityName: displayName,\n entityUserName: user?.name ?? message.user,\n fromBot: false,\n fromId: message.user,\n sourceId: entityId,\n chatType: message.channel_type,\n messageIdFull: message.ts,\n sender: {\n id: message.user,\n name: displayName,\n username: user?.name ?? message.user,\n },\n slack: {\n accountId,\n teamId: this.getTeamIdForAccount(accountId) ?? undefined,\n channelId: message.channel,\n userId: message.user,\n messageId: message.ts,\n threadTs: message.thread_ts,\n },\n slackChannelId: message.channel,\n slackMessageTs: message.ts,\n slackThreadTs: message.thread_ts,\n } satisfies Memory[\"metadata\"],\n createdAt: this.parseSlackTimestamp(message.ts),\n };\n\n return memory;\n }\n\n private async buildMemoryFromMention(\n event: {\n user: string;\n text: string;\n channel: string;\n ts: string;\n thread_ts?: string;\n },\n accountId = this.defaultAccountId,\n ): Promise<Memory | null> {\n const roomId = await this.getRoomId(\n event.channel,\n event.thread_ts,\n accountId,\n );\n const entityId = this.getEntityId(event.user, accountId);\n\n const user = await this.getUser(event.user, accountId);\n const displayName = user ? getSlackUserDisplayName(user) : event.user;\n\n // Remove the bot mention from the text\n const cleanText = event.text\n .replace(`<@${this.getBotUserIdForAccount(accountId)}>`, \"\")\n .trim();\n\n const memory: Memory = {\n id: createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\"slack-mention\", event.ts, accountId),\n ),\n agentId: this.runtime.agentId,\n roomId,\n entityId,\n content: {\n text: cleanText,\n source: \"slack\",\n name: displayName,\n metadata: { accountId },\n mentionContext: { isMention: true, isReply: false, isThread: false },\n },\n metadata: {\n type: \"message\",\n source: \"slack\",\n provider: \"slack\",\n accountId,\n timestamp: this.parseSlackTimestamp(event.ts),\n entityName: displayName,\n entityUserName: user?.name ?? event.user,\n fromBot: false,\n fromId: event.user,\n sourceId: entityId,\n messageIdFull: event.ts,\n slack: {\n accountId,\n teamId: this.getTeamIdForAccount(accountId) ?? undefined,\n channelId: event.channel,\n userId: event.user,\n messageId: event.ts,\n threadTs: event.thread_ts,\n },\n slackChannelId: event.channel,\n slackMessageTs: event.ts,\n slackThreadTs: event.thread_ts,\n } satisfies Memory[\"metadata\"],\n createdAt: this.parseSlackTimestamp(event.ts),\n };\n\n return memory;\n }\n\n private async getRoomId(\n channelId: string,\n threadTs?: string,\n accountId?: string | null,\n ): Promise<UUID> {\n // Use thread_ts to create unique rooms for threads\n const roomKey = threadTs ? `${channelId}-${threadTs}` : channelId;\n return createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\"slack-room\", roomKey, accountId),\n );\n }\n\n private getEntityId(userId: string, accountId?: string | null): UUID {\n return stringToUuid(this.scopedSlackKey(\"slack-user\", userId, accountId));\n }\n\n private parseSlackTimestamp(ts: string): number {\n // Slack timestamps are in the format: 1234567890.123456\n const [seconds] = ts.split(\".\");\n return parseInt(seconds, 10) * 1000;\n }\n\n private async ensureWorkspaceExists(\n accountId = this.defaultAccountId,\n ): Promise<void> {\n const teamId = this.getTeamIdForAccount(accountId);\n const client = this.getClientForAccount(accountId);\n if (!teamId || !client) return;\n\n const worldId = createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\"slack-workspace\", teamId, accountId),\n );\n\n const existingWorld = await this.runtime.getWorld(worldId);\n if (existingWorld) return;\n\n // Get team info\n const teamInfo = await client.team.info();\n const team = teamInfo.team;\n\n const world: World = {\n id: worldId,\n name: (team as { name?: string })?.name || `Slack Workspace ${teamId}`,\n agentId: this.runtime.agentId,\n metadata: {\n type: \"slack\",\n source: \"slack\",\n accountId,\n extra: {\n accountId,\n teamId,\n domain: (team as { domain?: string })?.domain,\n },\n },\n };\n\n await this.runtime.createWorld(world);\n\n this.runtime.logger.info(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n accountId,\n worldId,\n teamId,\n },\n \"Created Slack workspace world\",\n );\n }\n\n private async ensureRoomExists(\n channelId: string,\n threadTs?: string,\n accountId = this.defaultAccountId,\n ): Promise<Room> {\n const roomId = await this.getRoomId(channelId, threadTs, accountId);\n\n const existingRoom = await this.runtime.getRoom(roomId);\n if (existingRoom) return existingRoom;\n\n // Get channel info\n const channel = await this.getChannel(channelId, accountId);\n const channelType = channel ? getSlackChannelType(channel) : \"channel\";\n const teamId = this.getTeamIdForAccount(accountId);\n\n const worldId = teamId\n ? createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\"slack-workspace\", teamId, accountId),\n )\n : undefined;\n\n const elizaChannelType =\n channelType === \"im\"\n ? ChannelType.DM\n : channelType === \"mpim\"\n ? ChannelType.GROUP\n : ChannelType.GROUP;\n\n const room: Room = {\n id: roomId,\n name: channel?.name || channelId,\n agentId: this.runtime.agentId,\n source: \"slack\",\n type: elizaChannelType,\n channelId,\n worldId,\n metadata: {\n source: \"slack\",\n accountId,\n slackChannelType: channelType,\n threadTs,\n topic: channel?.topic?.value,\n purpose: channel?.purpose?.value,\n serverId: teamId,\n slack: {\n accountId,\n teamId,\n channelId,\n threadTs,\n },\n },\n };\n\n await this.runtime.createRoom(room);\n\n this.runtime.logger.debug(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n accountId,\n roomId,\n channelId,\n threadTs,\n },\n \"Created Slack room\",\n );\n\n return room;\n }\n\n private buildConnectorChannelTarget(\n channel: SlackChannel,\n score = 0.5,\n accountId = this.defaultAccountId,\n ): MessageConnectorTarget | null {\n if (!channel.id || channel.isArchived) {\n return null;\n }\n if (!this.isChannelAllowed(channel.id, accountId)) {\n return null;\n }\n\n const kind = channel.isIm ? \"user\" : channel.isMpim ? \"group\" : \"channel\";\n const label = channel.name ? `#${channel.name}` : channel.id;\n const teamId = this.getTeamIdForAccount(accountId);\n return {\n target: {\n source: \"slack\",\n accountId,\n channelId: channel.id,\n serverId: teamId ?? undefined,\n } as TargetInfo,\n label,\n kind,\n description: channel.purpose?.value || channel.topic?.value || label,\n score,\n contexts: [\"social\", \"connectors\"],\n metadata: {\n accountId,\n slackChannelId: channel.id,\n slackTeamId: teamId,\n slackChannelType: getSlackChannelType(channel),\n channelName: channel.name,\n isPrivate: channel.isPrivate,\n isMember: channel.isMember,\n topic: channel.topic?.value,\n purpose: channel.purpose?.value,\n },\n };\n }\n\n private buildConnectorUserTarget(\n user: SlackUser,\n score = 0.5,\n accountId = this.defaultAccountId,\n ): MessageConnectorTarget | null {\n if (!user.id || user.deleted || user.isBot || user.isAppUser) {\n return null;\n }\n const label = getSlackUserDisplayName(user);\n return {\n target: {\n source: \"slack\",\n accountId,\n entityId: user.id as UUID,\n serverId:\n user.teamId ?? this.getTeamIdForAccount(accountId) ?? undefined,\n } as TargetInfo,\n label: `@${label}`,\n kind: \"user\",\n description: user.profile.title || \"Slack user\",\n score,\n contexts: [\"social\", \"connectors\"],\n metadata: {\n accountId,\n slackUserId: user.id,\n slackTeamId: user.teamId ?? this.getTeamIdForAccount(accountId),\n slackName: user.name,\n slackRealName: user.realName,\n slackDisplayName: user.profile.displayName,\n email: user.profile.email,\n },\n };\n }\n\n private dedupeConnectorTargets(\n targets: MessageConnectorTarget[],\n ): MessageConnectorTarget[] {\n const byKey = new Map<string, MessageConnectorTarget>();\n for (const target of targets) {\n const key = [\n (target.target as AccountScopedTargetInfo).accountId ?? \"\",\n target.kind ?? \"target\",\n target.target.channelId ?? \"\",\n target.target.entityId ?? \"\",\n target.target.threadId ?? \"\",\n ].join(\":\");\n const existing = byKey.get(key);\n if (!existing || (target.score ?? 0) > (existing.score ?? 0)) {\n byKey.set(key, target);\n }\n }\n return Array.from(byKey.values()).sort(\n (a, b) => (b.score ?? 0) - (a.score ?? 0),\n );\n }\n\n private async resolveSlackTargetUserId(\n runtime: IAgentRuntime,\n entityId: string,\n accountId?: string | null,\n ): Promise<string | null> {\n if (SLACK_USER_ID_PATTERN.test(entityId)) {\n return entityId;\n }\n\n const entity =\n typeof runtime.getEntityById === \"function\"\n ? await runtime.getEntityById(entityId as UUID)\n : null;\n const metadataUserId = extractSlackUserIdFromMetadata(\n entity?.metadata,\n accountId,\n );\n if (metadataUserId) {\n return metadataUserId;\n }\n\n if (typeof runtime.getRelationships !== \"function\") {\n return null;\n }\n\n const relationships = await runtime.getRelationships({\n entityIds: [entityId as UUID],\n tags: [\"identity_link\"],\n });\n for (const relationship of relationships) {\n const linkedEntityId =\n relationship.sourceEntityId === entityId\n ? relationship.targetEntityId\n : relationship.targetEntityId === entityId\n ? relationship.sourceEntityId\n : null;\n if (!linkedEntityId || linkedEntityId === entityId) {\n continue;\n }\n const linkedEntity =\n typeof runtime.getEntityById === \"function\"\n ? await runtime.getEntityById(linkedEntityId as UUID)\n : null;\n const linkedUserId = extractSlackUserIdFromMetadata(\n linkedEntity?.metadata,\n accountId,\n );\n if (linkedUserId) {\n return linkedUserId;\n }\n }\n\n return null;\n }\n\n private async openDirectMessageChannel(\n userId: string,\n accountId?: string | null,\n ): Promise<string> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n const result = await client.conversations.open({ users: userId });\n const channel = result.channel as { id?: string } | undefined;\n if (!channel?.id) {\n throw new Error(`Could not open Slack DM channel for user ${userId}`);\n }\n return channel.id;\n }\n\n async handleSendMessage(\n runtime: IAgentRuntime,\n target: TargetInfo,\n content: Content,\n ): Promise<void> {\n const accountId = await this.resolveAccountIdForTarget(runtime, target);\n if (!this.getClientForAccount(accountId)) {\n throw new Error(\"Slack client not initialized\");\n }\n\n const text = typeof content.text === \"string\" ? content.text.trim() : \"\";\n if (!text) {\n throw new Error(\"Slack SendHandler requires non-empty text content.\");\n }\n\n let channelId = target.channelId;\n let threadTs = target.threadId;\n\n if (target.roomId && (!channelId || !threadTs)) {\n const room = await runtime.getRoom(target.roomId);\n channelId = channelId ?? room?.channelId;\n const metadata = room?.metadata as Record<string, unknown> | undefined;\n const metadataThreadTs =\n typeof metadata?.threadTs === \"string\" ? metadata.threadTs : undefined;\n threadTs = threadTs ?? metadataThreadTs;\n }\n\n if (channelId && SLACK_USER_ID_PATTERN.test(channelId)) {\n channelId = await this.openDirectMessageChannel(channelId, accountId);\n }\n\n if (!channelId && target.entityId) {\n const slackUserId = await this.resolveSlackTargetUserId(\n runtime,\n String(target.entityId),\n accountId,\n );\n if (!slackUserId) {\n throw new Error(\n `Could not resolve Slack user ID for entity ${target.entityId}`,\n );\n }\n channelId = await this.openDirectMessageChannel(slackUserId, accountId);\n }\n\n if (!channelId) {\n throw new Error(\n \"Slack SendHandler requires channelId, roomId, or entityId.\",\n );\n }\n\n await this.sendMessage(\n channelId,\n text,\n {\n threadTs,\n replyBroadcast: undefined,\n unfurlLinks: undefined,\n unfurlMedia: undefined,\n mrkdwn: undefined,\n attachments: undefined,\n blocks: undefined,\n },\n accountId,\n );\n }\n\n async resolveConnectorTargets(\n query: string,\n context: MessageConnectorQueryContext,\n ): Promise<MessageConnectorTarget[]> {\n const normalizedQuery = normalizeSlackConnectorQuery(query);\n const targets: MessageConnectorTarget[] = [];\n const accountIds = this.getCandidateAccountIds(context, context.target);\n\n for (const accountId of accountIds) {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n continue;\n }\n\n try {\n const channels = await this.listChannels(\n {\n types: \"public_channel,private_channel,mpim,im\",\n limit: 1000,\n },\n accountId,\n );\n for (const channel of channels) {\n const score = scoreSlackConnectorMatch(normalizedQuery, channel.id, [\n channel.name,\n channel.topic?.value,\n channel.purpose?.value,\n ]);\n if (score <= 0) {\n continue;\n }\n const target = this.buildConnectorChannelTarget(\n channel,\n score,\n accountId,\n );\n if (target) {\n targets.push(target);\n }\n }\n } catch (error) {\n this.runtime.logger.debug(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n accountId,\n error: error instanceof Error ? error.message : String(error),\n },\n \"Slack connector channel query failed\",\n );\n }\n\n try {\n const usersResult = await client.users.list({ limit: 200 });\n const members = (usersResult.members ?? []) as SlackApiUserMember[];\n for (const member of members) {\n const user: SlackUser = {\n id: member.id ?? \"\",\n teamId: member.team_id,\n name: member.name ?? \"\",\n deleted: Boolean(member.deleted),\n realName: member.real_name,\n tz: member.tz,\n tzLabel: member.tz_label,\n tzOffset: member.tz_offset,\n profile: {\n title: member.profile?.title,\n phone: member.profile?.phone,\n skype: member.profile?.skype,\n realName: member.profile?.real_name,\n realNameNormalized: member.profile?.real_name_normalized,\n displayName: member.profile?.display_name,\n displayNameNormalized: member.profile?.display_name_normalized,\n statusText: member.profile?.status_text,\n statusEmoji: member.profile?.status_emoji,\n statusExpiration: member.profile?.status_expiration,\n avatarHash: member.profile?.avatar_hash,\n email: member.profile?.email,\n image24: member.profile?.image_24,\n image32: member.profile?.image_32,\n image48: member.profile?.image_48,\n image72: member.profile?.image_72,\n image192: member.profile?.image_192,\n image512: member.profile?.image_512,\n image1024: member.profile?.image_1024,\n imageOriginal: member.profile?.image_original,\n team: member.profile?.team,\n },\n isAdmin: Boolean(member.is_admin),\n isOwner: Boolean(member.is_owner),\n isPrimaryOwner: Boolean(member.is_primary_owner),\n isRestricted: Boolean(member.is_restricted),\n isUltraRestricted: Boolean(member.is_ultra_restricted),\n isBot: Boolean(member.is_bot),\n isAppUser: Boolean(member.is_app_user),\n updated: member.updated ?? 0,\n };\n const score = scoreSlackConnectorMatch(normalizedQuery, user.id, [\n user.name,\n user.realName,\n user.profile.displayName,\n user.profile.realName,\n user.profile.email,\n ]);\n if (score <= 0) {\n continue;\n }\n const target = this.buildConnectorUserTarget(user, score, accountId);\n if (target) {\n targets.push(target);\n }\n }\n } catch (error) {\n this.runtime.logger.debug(\n {\n src: \"plugin:slack\",\n agentId: this.runtime.agentId,\n accountId,\n error: error instanceof Error ? error.message : String(error),\n },\n \"Slack connector user query failed\",\n );\n }\n\n if (context.target?.channelId) {\n const channel = await this.getChannel(\n context.target.channelId,\n accountId,\n );\n if (channel) {\n const target = this.buildConnectorChannelTarget(\n channel,\n 0.6,\n accountId,\n );\n if (target) {\n targets.push(target);\n }\n }\n }\n }\n\n return this.dedupeConnectorTargets(targets).slice(0, 25);\n }\n\n async listConnectorRooms(\n context: MessageConnectorQueryContext,\n ): Promise<MessageConnectorTarget[]> {\n const targets: MessageConnectorTarget[] = [];\n for (const accountId of this.getCandidateAccountIds(context)) {\n if (!this.getClientForAccount(accountId)) {\n continue;\n }\n const channels = await this.listChannels(\n {\n types: \"public_channel,private_channel,mpim,im\",\n limit: 1000,\n },\n accountId,\n );\n targets.push(\n ...channels\n .map((channel) =>\n this.buildConnectorChannelTarget(channel, 0.5, accountId),\n )\n .filter((target): target is MessageConnectorTarget =>\n Boolean(target),\n ),\n );\n }\n return this.dedupeConnectorTargets(targets).slice(0, 50);\n }\n\n async listRecentConnectorTargets(\n context: MessageConnectorQueryContext,\n ): Promise<MessageConnectorTarget[]> {\n const targets: MessageConnectorTarget[] = [];\n const room =\n context.roomId && typeof context.runtime.getRoom === \"function\"\n ? await context.runtime.getRoom(context.roomId)\n : null;\n const accountId = await this.resolveAccountIdForTarget(\n context.runtime,\n context.target,\n {\n accountId: (context as AccountScopedConnectorContext).accountId,\n roomId: context.roomId,\n },\n );\n const channelId =\n context.target?.channelId ??\n (room?.source === \"slack\" ? room.channelId : undefined);\n const roomMetadata = room?.metadata as Record<string, unknown> | undefined;\n const threadTs =\n context.target?.threadId ??\n (typeof roomMetadata?.threadTs === \"string\"\n ? roomMetadata.threadTs\n : undefined);\n\n if (channelId) {\n const channel = await this.getChannel(channelId, accountId);\n if (channel) {\n const target = this.buildConnectorChannelTarget(\n channel,\n 0.95,\n accountId,\n );\n if (target) {\n if (threadTs) {\n target.kind = \"thread\";\n target.target.threadId = threadTs;\n target.label = `${target.label ?? channelId} thread`;\n target.metadata = {\n ...(target.metadata ?? {}),\n slackThreadTs: threadTs,\n };\n }\n targets.push(target);\n }\n }\n }\n\n targets.push(\n ...(await this.listConnectorRooms({\n ...context,\n accountId,\n } as MessageConnectorQueryContext)),\n );\n return this.dedupeConnectorTargets(targets).slice(0, 25);\n }\n\n async getConnectorChatContext(\n target: TargetInfo,\n context: MessageConnectorQueryContext,\n ): Promise<MessageConnectorChatContext | null> {\n const accountId = await this.resolveAccountIdForTarget(\n context.runtime,\n target,\n {\n accountId: (context as AccountScopedConnectorContext).accountId,\n roomId: context.roomId,\n },\n );\n const client = this.getClientForAccount(accountId);\n if (!client) {\n return null;\n }\n\n const room =\n target.roomId && typeof context.runtime.getRoom === \"function\"\n ? await context.runtime.getRoom(target.roomId)\n : null;\n const channelId = target.channelId ?? room?.channelId;\n if (!channelId) {\n return null;\n }\n\n const metadata = room?.metadata as Record<string, unknown> | undefined;\n const threadTs =\n target.threadId ??\n (typeof metadata?.threadTs === \"string\" ? metadata.threadTs : undefined);\n const channel = await this.getChannel(channelId, accountId);\n\n const messages = threadTs\n ? await client.conversations.replies({\n channel: channelId,\n ts: threadTs,\n limit: 10,\n })\n : {\n messages: await this.readHistory(channelId, { limit: 10 }, accountId),\n };\n const rawMessages = (messages.messages ?? []) as Array<\n SlackMessage | Record<string, unknown>\n >;\n const recentMessages: MessageConnectorChatContext[\"recentMessages\"] = [];\n for (const rawMessage of rawMessages.slice().reverse()) {\n const text = String((rawMessage as SlackMessage).text ?? \"\");\n if (!text.trim()) {\n continue;\n }\n const userId =\n (rawMessage as SlackMessage).user ??\n (rawMessage as Record<string, string | undefined>).user;\n const user =\n typeof userId === \"string\"\n ? await this.getUser(userId, accountId)\n : null;\n recentMessages.push({\n entityId: userId ? (userId as UUID) : undefined,\n name: user ? getSlackUserDisplayName(user) : userId,\n text,\n timestamp: Number((rawMessage as SlackMessage).ts) * 1000 || undefined,\n metadata: {\n accountId,\n slackMessageTs: (rawMessage as SlackMessage).ts,\n slackUserId: userId,\n },\n });\n }\n\n return {\n target: {\n source: \"slack\",\n accountId,\n roomId: target.roomId ?? room?.id,\n channelId,\n serverId:\n target.serverId ?? this.getTeamIdForAccount(accountId) ?? undefined,\n threadId: threadTs,\n } as TargetInfo,\n label: channel?.name ? `#${channel.name}` : channelId,\n summary: channel?.purpose?.value || channel?.topic?.value,\n recentMessages,\n metadata: {\n accountId,\n slackChannelId: channelId,\n slackTeamId: this.getTeamIdForAccount(accountId),\n slackThreadTs: threadTs,\n channelName: channel?.name,\n },\n };\n }\n\n private async resolveConnectorMessageLocation(\n target?: TargetInfo | null,\n fallback?: ConnectorFetchMessagesParams,\n ): Promise<{ accountId: string; channelId: string; threadTs?: string }> {\n const accountId = await this.resolveAccountIdForTarget(\n this.runtime,\n target,\n fallback,\n );\n let channelId = target?.channelId ?? fallback?.channelId;\n let threadTs = target?.threadId ?? fallback?.threadId;\n const roomId = target?.roomId ?? fallback?.roomId;\n\n if (roomId && (!channelId || !threadTs)) {\n const room = await this.runtime.getRoom(roomId);\n channelId = channelId ?? room?.channelId;\n const metadata = room?.metadata as Record<string, unknown> | undefined;\n const roomThreadTs =\n typeof metadata?.threadTs === \"string\" ? metadata.threadTs : undefined;\n threadTs = threadTs ?? roomThreadTs;\n }\n\n if (channelId && SLACK_USER_ID_PATTERN.test(channelId)) {\n channelId = await this.openDirectMessageChannel(channelId, accountId);\n }\n\n if (!channelId && target?.entityId) {\n const slackUserId = await this.resolveSlackTargetUserId(\n this.runtime,\n String(target.entityId),\n accountId,\n );\n if (slackUserId) {\n channelId = await this.openDirectMessageChannel(slackUserId, accountId);\n }\n }\n\n if (!channelId) {\n throw new Error(\n \"Slack message operation requires channelId, roomId, or entityId.\",\n );\n }\n\n return { accountId, channelId, threadTs };\n }\n\n private async slackMessageToMemory(\n message: SlackMessage,\n channelId: string,\n threadTs?: string,\n accountId = this.defaultAccountId,\n ): Promise<Memory> {\n const effectiveThreadTs = threadTs ?? message.threadTs;\n const roomId = await this.getRoomId(\n channelId,\n effectiveThreadTs,\n accountId,\n );\n const botUserId = this.getBotUserIdForAccount(accountId);\n const slackUserId = message.user ?? botUserId ?? \"unknown\";\n const entityId =\n slackUserId === botUserId\n ? this.runtime.agentId\n : this.getEntityId(slackUserId, accountId);\n const user = message.user\n ? await this.getUser(message.user, accountId)\n : null;\n const displayName = user ? getSlackUserDisplayName(user) : slackUserId;\n const channel = await this.getChannel(channelId, accountId).catch(\n () => null,\n );\n const channelType = effectiveThreadTs\n ? ChannelType.THREAD\n : channel?.isIm\n ? ChannelType.DM\n : ChannelType.GROUP;\n\n const attachments: Media[] = (message.files ?? []).map((file) => ({\n id: file.id,\n url: file.urlPrivate,\n title: file.title || file.name,\n source: \"slack\",\n description: file.name,\n }));\n\n return {\n id: createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\"slack\", `${channelId}-${message.ts}`, accountId),\n ),\n agentId: this.runtime.agentId,\n roomId,\n entityId,\n content: {\n text: message.text || \"\",\n source: \"slack\",\n name: displayName,\n channelType,\n metadata: { accountId },\n ...(effectiveThreadTs && effectiveThreadTs !== message.ts\n ? {\n inReplyTo: createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\n \"slack\",\n `${channelId}-${effectiveThreadTs}`,\n accountId,\n ),\n ),\n }\n : {}),\n ...(attachments.length > 0 ? { attachments } : {}),\n },\n metadata: {\n type: \"message\",\n source: \"slack\",\n provider: \"slack\",\n accountId,\n timestamp: this.parseSlackTimestamp(message.ts),\n entityName: displayName,\n entityUserName: user?.name ?? slackUserId,\n fromBot: slackUserId === botUserId,\n fromId: slackUserId,\n sourceId: entityId,\n chatType: channelType,\n messageIdFull: message.ts,\n sender: {\n id: slackUserId,\n name: displayName,\n username: user?.name ?? slackUserId,\n },\n slack: {\n accountId,\n teamId: this.getTeamIdForAccount(accountId) ?? undefined,\n channelId,\n userId: slackUserId,\n messageId: message.ts,\n threadTs: effectiveThreadTs,\n },\n slackChannelId: channelId,\n slackMessageTs: message.ts,\n slackThreadTs: effectiveThreadTs,\n reactions: message.reactions,\n } satisfies Memory[\"metadata\"],\n createdAt: this.parseSlackTimestamp(message.ts),\n };\n }\n\n async listConnectorServers(\n context: MessageConnectorQueryContext,\n ): Promise<World[]> {\n const worlds: World[] = [];\n for (const accountId of this.getCandidateAccountIds(context)) {\n const teamId = this.getTeamIdForAccount(accountId);\n if (!teamId) {\n continue;\n }\n\n let name = `Slack Workspace ${teamId}`;\n try {\n const client = this.getClientForAccount(accountId);\n if (client) {\n const teamInfo = await client.team.info();\n const team = teamInfo.team as { name?: string } | undefined;\n name = team?.name || name;\n }\n } catch {\n // Best-effort metadata; the workspace id is still useful.\n }\n\n worlds.push({\n id: createUniqueUuid(\n this.runtime,\n this.scopedSlackKey(\"slack-workspace\", teamId, accountId),\n ),\n agentId: this.runtime.agentId,\n name,\n metadata: {\n source: \"slack\",\n accountId,\n teamId,\n },\n });\n }\n\n return worlds;\n }\n\n async fetchConnectorMessages(\n _context: MessageConnectorQueryContext,\n params: ConnectorFetchMessagesParams,\n ): Promise<Memory[]> {\n const accountId = await this.resolveAccountIdForTarget(\n _context.runtime,\n params.target,\n { accountId: params.accountId, roomId: params.roomId },\n );\n const client = this.getClientForAccount(accountId);\n if (!client) {\n return [];\n }\n\n const { channelId, threadTs } = await this.resolveConnectorMessageLocation(\n params.target,\n { ...params, accountId },\n );\n const limit = Number.isFinite(params.limit)\n ? Math.max(1, Math.min(Number(params.limit), 100))\n : 25;\n\n const rawMessages = threadTs\n ? (((\n await client.conversations.replies({\n channel: channelId,\n ts: threadTs,\n limit,\n latest: params.before,\n oldest: params.after,\n cursor: params.cursor,\n })\n ).messages as\n | Array<SlackMessage | Record<string, unknown>>\n | undefined) ?? [])\n : await this.readHistory(\n channelId,\n {\n limit,\n before: params.before,\n after: params.after,\n },\n accountId,\n );\n\n const memories: Memory[] = [];\n for (const rawMessage of rawMessages) {\n const message = rawMessage as SlackMessage;\n if (!message.ts) {\n continue;\n }\n memories.push(\n await this.slackMessageToMemory(\n message,\n channelId,\n threadTs,\n accountId,\n ),\n );\n }\n return memories.sort(\n (left, right) =>\n Number(right.createdAt ?? 0) - Number(left.createdAt ?? 0),\n );\n }\n\n async searchConnectorMessages(\n context: MessageConnectorQueryContext,\n params: ConnectorSearchMessagesParams,\n ): Promise<Memory[]> {\n const query = params.query?.trim().toLowerCase();\n if (!query) {\n return [];\n }\n\n const memories = await this.fetchConnectorMessages(context, {\n ...params,\n limit: Math.max(params.limit ?? 100, 100),\n });\n return memories\n .filter((memory) => {\n const text = String(memory.content?.text ?? \"\").toLowerCase();\n const name = String(memory.content?.name ?? \"\").toLowerCase();\n return text.includes(query) || name.includes(query);\n })\n .slice(0, params.limit ?? 25);\n }\n\n async reactConnectorMessage(\n _runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ): Promise<void> {\n const { accountId, channelId } = await this.resolveConnectorMessageLocation(\n params.target,\n params,\n );\n const messageTs = params.messageTs ?? params.messageId;\n const emoji = params.emoji?.trim();\n if (!messageTs || !emoji) {\n throw new Error(\"Slack reaction requires messageId/messageTs and emoji.\");\n }\n if (params.remove) {\n await this.removeReaction(channelId, messageTs, emoji, accountId);\n return;\n }\n await this.sendReaction(channelId, messageTs, emoji, accountId);\n }\n\n async editConnectorMessage(\n _runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ): Promise<Memory> {\n const { accountId, channelId, threadTs } =\n await this.resolveConnectorMessageLocation(params.target, params);\n const messageTs = params.messageTs ?? params.messageId;\n const text = params.content?.text ?? params.text;\n if (!messageTs || !text?.trim()) {\n throw new Error(\"Slack edit requires messageId/messageTs and text.\");\n }\n\n await this.editMessage(channelId, messageTs, text, accountId);\n return this.slackMessageToMemory(\n {\n type: \"message\",\n ts: messageTs,\n user: this.getBotUserIdForAccount(accountId) ?? undefined,\n text,\n threadTs,\n subtype: undefined,\n replyCount: undefined,\n replyUsersCount: undefined,\n latestReply: undefined,\n reactions: undefined,\n files: undefined,\n attachments: undefined,\n blocks: undefined,\n },\n channelId,\n threadTs,\n accountId,\n );\n }\n\n async deleteConnectorMessage(\n _runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ): Promise<void> {\n const { accountId, channelId } = await this.resolveConnectorMessageLocation(\n params.target,\n params,\n );\n const messageTs = params.messageTs ?? params.messageId;\n if (!messageTs) {\n throw new Error(\"Slack delete requires messageId/messageTs.\");\n }\n await this.deleteMessage(channelId, messageTs, accountId);\n }\n\n async pinConnectorMessage(\n _runtime: IAgentRuntime,\n params: ConnectorMessageMutationParams,\n ): Promise<void> {\n const { accountId, channelId } = await this.resolveConnectorMessageLocation(\n params.target,\n params,\n );\n const messageTs = params.messageTs ?? params.messageId;\n if (!messageTs) {\n throw new Error(\"Slack pin requires messageId/messageTs.\");\n }\n if (params.pin === false) {\n await this.unpinMessage(channelId, messageTs, accountId);\n return;\n }\n await this.pinMessage(channelId, messageTs, accountId);\n }\n\n async getConnectorUser(\n runtime: IAgentRuntime,\n params: ConnectorUserLookupParams,\n ): Promise<unknown> {\n const accountId = normalizeAccountId(\n (params.target as AccountScopedTargetInfo | undefined)?.accountId ??\n this.defaultAccountId ??\n DEFAULT_ACCOUNT_ID,\n );\n const lookup =\n params.userId ?? params.handle ?? params.username ?? params.query;\n if (!lookup) {\n return null;\n }\n\n let slackUserId = SLACK_USER_ID_PATTERN.test(lookup)\n ? lookup\n : await this.resolveSlackTargetUserId(runtime, lookup, accountId);\n\n const client = this.getClientForAccount(accountId);\n if (!slackUserId && client) {\n const usersResult = await client.users.list({ limit: 200 });\n const members = (usersResult.members ?? []) as SlackApiUserMember[];\n const normalized = normalizeSlackConnectorQuery(lookup);\n const match = members.find((member) =>\n [\n member.id,\n member.name,\n member.real_name,\n member.profile?.display_name,\n member.profile?.email,\n ]\n .filter((value): value is string => Boolean(value))\n .some((value) =>\n normalizeSlackConnectorQuery(value).includes(normalized),\n ),\n );\n slackUserId = match?.id ?? null;\n }\n\n if (!slackUserId) {\n return null;\n }\n\n const user = await this.getUser(slackUserId, accountId);\n if (!user) {\n return null;\n }\n\n return {\n id: this.getEntityId(user.id, accountId),\n agentId: this.runtime.agentId,\n names: [getSlackUserDisplayName(user), user.name, user.realName].filter(\n (value): value is string => Boolean(value),\n ),\n metadata: {\n source: \"slack\",\n accountId,\n slack: {\n accountId,\n id: user.id,\n teamId: user.teamId ?? this.getTeamIdForAccount(accountId),\n name: user.name,\n realName: user.realName,\n profile: { ...user.profile },\n },\n },\n };\n }\n\n async getConnectorUserContext(\n entityId: UUID | string,\n context: MessageConnectorQueryContext,\n ): Promise<MessageConnectorUserContext | null> {\n const accountId = normalizeAccountId(\n (context.target as AccountScopedTargetInfo | undefined)?.accountId ??\n (context as AccountScopedConnectorContext).accountId ??\n (context as AccountScopedConnectorContext).account?.accountId ??\n this.defaultAccountId ??\n DEFAULT_ACCOUNT_ID,\n );\n const slackUserId = await this.resolveSlackTargetUserId(\n context.runtime,\n String(entityId),\n accountId,\n );\n if (!slackUserId) {\n return null;\n }\n const user = await this.getUser(slackUserId, accountId);\n if (!user) {\n return null;\n }\n\n return {\n entityId,\n label: getSlackUserDisplayName(user),\n aliases: [\n user.name,\n user.realName,\n user.profile.displayName,\n user.profile.realName,\n user.profile.email,\n ].filter((value): value is string => Boolean(value)),\n handles: {\n slack: user.id,\n ...(user.profile.email ? { email: user.profile.email } : {}),\n },\n metadata: {\n accountId,\n slackUserId: user.id,\n slackTeamId: user.teamId ?? this.getTeamIdForAccount(accountId),\n profile: { ...user.profile },\n },\n };\n }\n\n async getUser(\n userId: string,\n accountId?: string | null,\n ): Promise<SlackUser | null> {\n const userCache = this.getUserCacheForAccount(accountId);\n // Check cache first\n const cachedUser = userCache.get(userId);\n if (cachedUser) {\n return cachedUser;\n }\n\n const client = this.getClientForAccount(accountId);\n if (!client) return null;\n\n const result = await client.users.info({ user: userId });\n if (!result.user) return null;\n\n const user: SlackUser = {\n id: result.user.id ?? userId,\n teamId: result.user.team_id,\n name: result.user.name ?? \"\",\n deleted: result.user.deleted || false,\n realName: result.user.real_name,\n tz: result.user.tz,\n tzLabel: result.user.tz_label,\n tzOffset: result.user.tz_offset,\n profile: {\n title: result.user.profile?.title,\n phone: result.user.profile?.phone,\n skype: result.user.profile?.skype,\n realName: result.user.profile?.real_name,\n realNameNormalized: result.user.profile?.real_name_normalized,\n displayName: result.user.profile?.display_name,\n displayNameNormalized: result.user.profile?.display_name_normalized,\n statusText: result.user.profile?.status_text,\n statusEmoji: result.user.profile?.status_emoji,\n statusExpiration: result.user.profile?.status_expiration,\n avatarHash: result.user.profile?.avatar_hash,\n email: result.user.profile?.email,\n image24: result.user.profile?.image_24,\n image32: result.user.profile?.image_32,\n image48: result.user.profile?.image_48,\n image72: result.user.profile?.image_72,\n image192: result.user.profile?.image_192,\n image512: result.user.profile?.image_512,\n image1024: result.user.profile?.image_1024,\n imageOriginal: result.user.profile?.image_original,\n team: result.user.profile?.team,\n },\n isAdmin: result.user.is_admin || false,\n isOwner: result.user.is_owner || false,\n isPrimaryOwner: result.user.is_primary_owner || false,\n isRestricted: result.user.is_restricted || false,\n isUltraRestricted: result.user.is_ultra_restricted || false,\n isBot: result.user.is_bot || false,\n isAppUser: result.user.is_app_user || false,\n updated: result.user.updated || 0,\n };\n\n userCache.set(userId, user);\n return user;\n }\n\n async getChannel(\n channelId: string,\n accountId?: string | null,\n ): Promise<SlackChannel | null> {\n const channelCache = this.getChannelCacheForAccount(accountId);\n // Check cache first\n const cachedChannel = channelCache.get(channelId);\n if (cachedChannel) {\n return cachedChannel;\n }\n\n const client = this.getClientForAccount(accountId);\n if (!client) return null;\n\n const result = await client.conversations.info({ channel: channelId });\n if (!result.channel) return null;\n\n const channel: SlackChannel = {\n id: (result.channel as { id: string }).id,\n name: (result.channel as { name: string }).name || \"\",\n isChannel:\n (result.channel as { is_channel?: boolean }).is_channel || false,\n isGroup: (result.channel as { is_group?: boolean }).is_group || false,\n isIm: (result.channel as { is_im?: boolean }).is_im || false,\n isMpim: (result.channel as { is_mpim?: boolean }).is_mpim || false,\n isPrivate:\n (result.channel as { is_private?: boolean }).is_private || false,\n isArchived:\n (result.channel as { is_archived?: boolean }).is_archived || false,\n isGeneral:\n (result.channel as { is_general?: boolean }).is_general || false,\n isShared: (result.channel as { is_shared?: boolean }).is_shared || false,\n isOrgShared:\n (result.channel as { is_org_shared?: boolean }).is_org_shared || false,\n isMember: (result.channel as { is_member?: boolean }).is_member || false,\n topic: (\n result.channel as {\n topic?: { value: string; creator: string; last_set: number };\n }\n ).topic\n ? {\n value: (result.channel as { topic: { value: string } }).topic.value,\n creator: (result.channel as { topic: { creator: string } }).topic\n .creator,\n lastSet: (result.channel as { topic: { last_set: number } }).topic\n .last_set,\n }\n : undefined,\n purpose: (\n result.channel as {\n purpose?: { value: string; creator: string; last_set: number };\n }\n ).purpose\n ? {\n value: (result.channel as { purpose: { value: string } }).purpose\n .value,\n creator: (result.channel as { purpose: { creator: string } })\n .purpose.creator,\n lastSet: (result.channel as { purpose: { last_set: number } })\n .purpose.last_set,\n }\n : undefined,\n numMembers: (result.channel as { num_members?: number }).num_members,\n created: (result.channel as { created: number }).created,\n creator: (result.channel as { creator: string }).creator,\n };\n\n channelCache.set(channelId, channel);\n return channel;\n }\n\n async sendMessage(\n channelId: string,\n text: string,\n options?: SlackMessageSendOptions,\n accountId?: string | null,\n ): Promise<{ ts: string; channelId: string }> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n // Split message if too long\n const convertedText = markdownToSlackMrkdwn(text);\n const messages = this.splitMessage(convertedText);\n let lastTs = \"\";\n\n for (const msg of messages) {\n const result = await client.chat.postMessage({\n channel: channelId,\n text: msg,\n thread_ts: options?.threadTs,\n reply_broadcast: options?.replyBroadcast,\n unfurl_links: options?.unfurlLinks,\n unfurl_media: options?.unfurlMedia,\n mrkdwn: options?.mrkdwn ?? true,\n attachments: options?.attachments as never,\n blocks: options?.blocks as never,\n });\n\n lastTs = result.ts as string;\n }\n\n return { ts: lastTs, channelId };\n }\n\n async sendReaction(\n channelId: string,\n messageTs: string,\n emoji: string,\n accountId?: string | null,\n ): Promise<void> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n // Remove colons if present\n const cleanEmoji = emoji.replace(/^:/, \"\").replace(/:$/, \"\");\n\n await client.reactions.add({\n channel: channelId,\n timestamp: messageTs,\n name: cleanEmoji,\n });\n }\n\n async removeReaction(\n channelId: string,\n messageTs: string,\n emoji: string,\n accountId?: string | null,\n ): Promise<void> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n const cleanEmoji = emoji.replace(/^:/, \"\").replace(/:$/, \"\");\n\n await client.reactions.remove({\n channel: channelId,\n timestamp: messageTs,\n name: cleanEmoji,\n });\n }\n\n async editMessage(\n channelId: string,\n messageTs: string,\n text: string,\n accountId?: string | null,\n ): Promise<void> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n await client.chat.update({\n channel: channelId,\n ts: messageTs,\n text,\n });\n }\n\n async deleteMessage(\n channelId: string,\n messageTs: string,\n accountId?: string | null,\n ): Promise<void> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n await client.chat.delete({\n channel: channelId,\n ts: messageTs,\n });\n }\n\n async pinMessage(\n channelId: string,\n messageTs: string,\n accountId?: string | null,\n ): Promise<void> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n await client.pins.add({\n channel: channelId,\n timestamp: messageTs,\n });\n }\n\n async unpinMessage(\n channelId: string,\n messageTs: string,\n accountId?: string | null,\n ): Promise<void> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n await client.pins.remove({\n channel: channelId,\n timestamp: messageTs,\n });\n }\n\n async listPins(\n channelId: string,\n accountId?: string | null,\n ): Promise<SlackMessage[]> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n const result = await client.pins.list({ channel: channelId });\n\n return (result.items || [])\n .filter(\n (item): item is { type: \"message\"; message: Record<string, unknown> } =>\n item.type === \"message\" && \"message\" in item && !!item.message,\n )\n .map((item) => ({\n type: item.message.type as string,\n subtype: item.message.subtype as string | undefined,\n ts: item.message.ts as string,\n user: item.message.user as string | undefined,\n text: item.message.text as string,\n threadTs: item.message.thread_ts as string | undefined,\n replyCount: item.message.reply_count as number | undefined,\n replyUsersCount: item.message.reply_users_count as number | undefined,\n latestReply: item.message.latest_reply as string | undefined,\n reactions: item.message.reactions as\n | { name: string; count: number; users: string[] }[]\n | undefined,\n files: item.message.files as SlackFile[] | undefined,\n attachments: item.message.attachments as SlackAttachment[] | undefined,\n blocks: item.message.blocks as SlackBlock[] | undefined,\n }));\n }\n\n async readHistory(\n channelId: string,\n options?: { limit?: number; before?: string; after?: string },\n accountId?: string | null,\n ): Promise<SlackMessage[]> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n const result = await client.conversations.history({\n channel: channelId,\n limit: options?.limit || 100,\n latest: options?.before,\n oldest: options?.after,\n });\n\n return (result.messages || []).map((msg) => ({\n type: msg.type as string,\n subtype: msg.subtype as string | undefined,\n ts: msg.ts as string,\n user: msg.user as string | undefined,\n text: msg.text as string,\n threadTs: msg.thread_ts as string | undefined,\n replyCount: msg.reply_count as number | undefined,\n replyUsersCount: msg.reply_users_count as number | undefined,\n latestReply: msg.latest_reply as string | undefined,\n reactions: msg.reactions as\n | { name: string; count: number; users: string[] }[]\n | undefined,\n files: msg.files as SlackFile[] | undefined,\n attachments: msg.attachments as SlackAttachment[] | undefined,\n blocks: msg.blocks as SlackBlock[] | undefined,\n }));\n }\n\n async listChannels(\n options?: {\n types?: string;\n limit?: number;\n },\n accountId?: string | null,\n ): Promise<SlackChannel[]> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n const result = await client.conversations.list({\n types: options?.types || \"public_channel,private_channel\",\n limit: options?.limit || 1000,\n });\n\n return (result.channels || []).map((ch) => ({\n id: ch.id ?? \"\",\n name: ch.name || \"\",\n isChannel: ch.is_channel || false,\n isGroup: ch.is_group || false,\n isIm: ch.is_im || false,\n isMpim: ch.is_mpim || false,\n isPrivate: ch.is_private || false,\n isArchived: ch.is_archived || false,\n isGeneral: ch.is_general || false,\n isShared: ch.is_shared || false,\n isOrgShared: ch.is_org_shared || false,\n isMember: ch.is_member || false,\n topic: ch.topic\n ? {\n value: ch.topic.value ?? \"\",\n creator: ch.topic.creator ?? \"\",\n lastSet: ch.topic.last_set ?? 0,\n }\n : undefined,\n purpose: ch.purpose\n ? {\n value: ch.purpose.value ?? \"\",\n creator: ch.purpose.creator ?? \"\",\n lastSet: ch.purpose.last_set ?? 0,\n }\n : undefined,\n numMembers: ch.num_members,\n created: ch.created || 0,\n creator: ch.creator || \"\",\n }));\n }\n\n async getEmojiList(\n accountId?: string | null,\n ): Promise<Record<string, string>> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n const result = await client.emoji.list();\n return (result.emoji || {}) as Record<string, string>;\n }\n\n async uploadFile(\n channelId: string,\n content: Buffer | string,\n filename: string,\n options?: { title?: string; initialComment?: string; threadTs?: string },\n accountId?: string | null,\n ): Promise<{ fileId: string; permalink: string }> {\n const client = this.getClientForAccount(accountId);\n if (!client) {\n throw new Error(\"Slack client not initialized\");\n }\n\n const result = await client.files.uploadV2({\n channel_id: channelId,\n content: typeof content === \"string\" ? content : undefined,\n file: typeof content !== \"string\" ? content : undefined,\n filename,\n title: options?.title,\n initial_comment: options?.initialComment,\n thread_ts: options?.threadTs,\n });\n\n const resultWithFile = result as WebAPICallResult & {\n file?: { id: string; permalink: string };\n };\n const file = resultWithFile.file;\n return {\n fileId: file?.id || \"\",\n permalink: file?.permalink || \"\",\n };\n }\n\n private splitMessage(text: string): string[] {\n if (text.length <= MAX_SLACK_MESSAGE_LENGTH) {\n return [text];\n }\n\n const messages: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n if (remaining.length <= MAX_SLACK_MESSAGE_LENGTH) {\n messages.push(remaining);\n break;\n }\n\n // Find a good split point (prefer newlines, then spaces)\n let splitIndex = MAX_SLACK_MESSAGE_LENGTH;\n\n const lastNewline = remaining.lastIndexOf(\"\\n\", MAX_SLACK_MESSAGE_LENGTH);\n if (lastNewline > MAX_SLACK_MESSAGE_LENGTH / 2) {\n splitIndex = lastNewline + 1;\n } else {\n const lastSpace = remaining.lastIndexOf(\" \", MAX_SLACK_MESSAGE_LENGTH);\n if (lastSpace > MAX_SLACK_MESSAGE_LENGTH / 2) {\n splitIndex = lastSpace + 1;\n }\n }\n\n messages.push(remaining.slice(0, splitIndex));\n remaining = remaining.slice(splitIndex);\n }\n\n return messages;\n }\n\n /**\n * Add a channel to the dynamic allowed list\n */\n addAllowedChannel(channelId: string, accountId?: string | null): void {\n if (isValidChannelId(channelId)) {\n this.getDynamicChannelIdsForAccount(accountId).add(channelId);\n }\n }\n\n /**\n * Remove a channel from the dynamic allowed list\n */\n removeAllowedChannel(channelId: string, accountId?: string | null): void {\n this.getDynamicChannelIdsForAccount(accountId).delete(channelId);\n }\n\n /**\n * Get all currently allowed channel IDs\n */\n getAllowedChannelIds(accountId?: string | null): string[] {\n return [\n ...this.getAllowedChannelIdsForAccount(accountId),\n ...this.getDynamicChannelIdsForAccount(accountId),\n ];\n }\n\n /**\n * Check if the service is connected\n */\n isServiceConnected(): boolean {\n return this.isConnected && this.app !== null;\n }\n\n /**\n * Get the bot's user ID\n */\n getBotUserId(): string | null {\n return this.botUserId;\n }\n\n /**\n * Get the team/workspace ID\n */\n getTeamId(): string | null {\n return this.teamId;\n }\n\n /**\n * Clear the user cache\n */\n clearUserCache(): void {\n this.userCache.clear();\n }\n\n /**\n * Clear the channel cache\n */\n clearChannelCache(): void {\n this.channelCache.clear();\n }\n}\n",
|
|
11
|
-
"import type { SlackChannel, SlackUser } from \"./types\";\n\n/**\n * Escape special characters for Slack mrkdwn format\n * Preserves Slack's angle-bracket tokens so mentions and links stay intact\n */\nfunction escapeSlackMrkdwnSegment(text: string): string {\n return text\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\");\n}\n\nconst SLACK_ANGLE_TOKEN_RE = /<[^>\\n]+>/g;\n\n/**\n * Checks if an angle-bracket token is an allowed Slack format\n */\nfunction isAllowedSlackAngleToken(token: string): boolean {\n if (!token.startsWith(\"<\") || !token.endsWith(\">\")) {\n return false;\n }\n const inner = token.slice(1, -1);\n return (\n inner.startsWith(\"@\") ||\n inner.startsWith(\"#\") ||\n inner.startsWith(\"!\") ||\n inner.startsWith(\"mailto:\") ||\n inner.startsWith(\"tel:\") ||\n inner.startsWith(\"http://\") ||\n inner.startsWith(\"https://\") ||\n inner.startsWith(\"slack://\")\n );\n}\n\n/**\n * Escapes Slack mrkdwn content while preserving valid Slack tokens\n */\nfunction escapeSlackMrkdwnContent(text: string): string {\n if (!text.includes(\"&\") && !text.includes(\"<\") && !text.includes(\">\")) {\n return text;\n }\n\n SLACK_ANGLE_TOKEN_RE.lastIndex = 0;\n const out: string[] = [];\n let lastIndex = 0;\n\n for (\n let match = SLACK_ANGLE_TOKEN_RE.exec(text);\n match;\n match = SLACK_ANGLE_TOKEN_RE.exec(text)\n ) {\n const matchIndex = match.index ?? 0;\n out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex, matchIndex)));\n const token = match[0] ?? \"\";\n out.push(\n isAllowedSlackAngleToken(token) ? token : escapeSlackMrkdwnSegment(token),\n );\n lastIndex = matchIndex + token.length;\n }\n\n out.push(escapeSlackMrkdwnSegment(text.slice(lastIndex)));\n return out.join(\"\");\n}\n\n/**\n * Escapes Slack mrkdwn text, handling blockquotes specially\n */\nexport function escapeSlackMrkdwn(text: string): string {\n if (!text.includes(\"&\") && !text.includes(\"<\") && !text.includes(\">\")) {\n return text;\n }\n\n return text\n .split(\"\\n\")\n .map((line) => {\n if (line.startsWith(\"> \")) {\n return `> ${escapeSlackMrkdwnContent(line.slice(2))}`;\n }\n return escapeSlackMrkdwnContent(line);\n })\n .join(\"\\n\");\n}\n\n// Placeholder used during conversion to prevent bold from being matched as italic\nconst BOLD_PLACEHOLDER = \"\\u0000BOLD\\u0000\";\n\n/**\n * Converts markdown bold to Slack mrkdwn\n * Uses placeholder to prevent bold from being matched by italic converter\n */\nfunction convertBold(text: string): string {\n return text.replace(\n /\\*\\*(.+?)\\*\\*/g,\n `${BOLD_PLACEHOLDER}$1${BOLD_PLACEHOLDER}`,\n );\n}\n\n/**\n * Converts markdown italic to Slack mrkdwn\n */\nfunction convertItalic(text: string): string {\n // Markdown uses single * for italic, Slack uses _\n // Then restore bold placeholders to actual asterisks\n const converted = text.replace(\n /(?<!\\*)\\*(?!\\*)(.+?)(?<!\\*)\\*(?!\\*)/g,\n \"_$1_\",\n );\n return converted.replace(new RegExp(BOLD_PLACEHOLDER, \"g\"), \"*\");\n}\n\n/**\n * Converts markdown strikethrough to Slack mrkdwn\n */\nfunction convertStrikethrough(text: string): string {\n return text.replace(/~~(.+?)~~/g, \"~$1~\");\n}\n\n/**\n * Converts markdown code blocks to Slack mrkdwn\n */\nfunction convertCodeBlocks(text: string): string {\n // Slack code blocks don't support language hints in the same way\n return text.replace(/```(\\w*)\\n?([\\s\\S]*?)```/g, \"```\\n$2```\");\n}\n\n/**\n * Converts markdown links to Slack mrkdwn links\n */\nfunction convertLinks(text: string): string {\n return text.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, (_, linkText, url) => {\n const trimmedUrl = url.trim();\n const trimmedText = linkText.trim();\n // If link text matches URL, just use URL\n if (\n trimmedText === trimmedUrl ||\n trimmedText === trimmedUrl.replace(/^mailto:/, \"\")\n ) {\n return `<${escapeSlackMrkdwnSegment(trimmedUrl)}>`;\n }\n return `<${escapeSlackMrkdwnSegment(trimmedUrl)}|${escapeSlackMrkdwnSegment(trimmedText)}>`;\n });\n}\n\n/**\n * Converts markdown headings to Slack mrkdwn (bold text)\n * Uses placeholder to prevent headings from being matched by italic converter\n */\nfunction convertHeadings(text: string): string {\n return text.replace(\n /^#{1,6}\\s+(.+)$/gm,\n `${BOLD_PLACEHOLDER}$1${BOLD_PLACEHOLDER}`,\n );\n}\n\n/**\n * Converts markdown to Slack mrkdwn format\n */\nexport function markdownToSlackMrkdwn(markdown: string): string {\n if (!markdown) {\n return \"\";\n }\n\n // Process in order: code blocks -> links -> headings -> text styles -> escape\n let result = convertCodeBlocks(markdown);\n result = convertLinks(result);\n result = convertHeadings(result);\n result = convertBold(result);\n result = convertItalic(result);\n result = convertStrikethrough(result);\n result = escapeSlackMrkdwn(result);\n\n return result;\n}\n\n/**\n * Options for chunking Slack text\n */\nexport interface ChunkSlackTextOpts {\n /** Max characters per message. Default: 4000 */\n maxChars?: number;\n}\n\nconst DEFAULT_MAX_CHARS = 4000;\n\n/**\n * Chunks Slack text while preserving code blocks\n */\nexport function chunkSlackText(\n text: string,\n maxChars: number = DEFAULT_MAX_CHARS,\n): string[] {\n if (!text) {\n return [];\n }\n\n if (text.length <= maxChars) {\n return [text];\n }\n\n const chunks: string[] = [];\n let remaining = text;\n let inCodeBlock = false;\n\n while (remaining.length > 0) {\n if (remaining.length <= maxChars) {\n chunks.push(remaining);\n break;\n }\n\n // Find a good break point\n let breakPoint = maxChars;\n\n // Check if we're in a code block\n const codeBlockCount = (remaining.slice(0, maxChars).match(/```/g) || [])\n .length;\n inCodeBlock = codeBlockCount % 2 !== 0;\n\n // Try to break at a newline\n const newlineIndex = remaining.lastIndexOf(\"\\n\", maxChars);\n if (newlineIndex > maxChars * 0.5) {\n breakPoint = newlineIndex + 1;\n } else {\n // Try to break at a space\n const spaceIndex = remaining.lastIndexOf(\" \", maxChars);\n if (spaceIndex > maxChars * 0.5) {\n breakPoint = spaceIndex + 1;\n }\n }\n\n let chunk = remaining.slice(0, breakPoint);\n\n // If we're breaking inside a code block, close it\n if (inCodeBlock) {\n chunk += \"\\n```\";\n }\n\n chunks.push(chunk);\n\n remaining = remaining.slice(breakPoint);\n\n // If we were in a code block, reopen it\n if (inCodeBlock) {\n remaining = `\\`\\`\\`\\n${remaining}`;\n }\n }\n\n return chunks;\n}\n\n/**\n * Converts markdown to Slack mrkdwn and splits into chunks\n */\nexport function markdownToSlackMrkdwnChunks(\n markdown: string,\n limit: number,\n): string[] {\n return chunkSlackText(markdownToSlackMrkdwn(markdown), limit);\n}\n\n/**\n * Formats a Slack user mention\n */\nexport function formatSlackUserMention(userId: string): string {\n return `<@${userId}>`;\n}\n\n/**\n * Formats a Slack channel mention\n */\nexport function formatSlackChannelMention(channelId: string): string {\n return `<#${channelId}>`;\n}\n\n/**\n * Formats a Slack user group mention\n */\nexport function formatSlackUserGroupMention(groupId: string): string {\n return `<!subteam^${groupId}>`;\n}\n\n/**\n * Formats a Slack special mention (@here, @channel, @everyone)\n */\nexport function formatSlackSpecialMention(\n type: \"here\" | \"channel\" | \"everyone\",\n): string {\n return `<!${type}>`;\n}\n\n/**\n * Formats a Slack link\n */\nexport function formatSlackLink(url: string, text?: string): string {\n const safeUrl = escapeSlackMrkdwnSegment(url);\n if (text && text !== url) {\n return `<${safeUrl}|${escapeSlackMrkdwnSegment(text)}>`;\n }\n return `<${safeUrl}>`;\n}\n\n/**\n * Formats a Slack date\n */\nexport function formatSlackDate(\n timestamp: number | Date,\n format: string = \"{date_short_pretty} at {time}\",\n fallbackText?: string,\n): string {\n const unix = Math.floor(\n (typeof timestamp === \"number\" ? timestamp : timestamp.getTime()) / 1000,\n );\n const fallback = fallbackText || new Date(unix * 1000).toISOString();\n return `<!date^${unix}^${format}|${fallback}>`;\n}\n\n/**\n * Extracts user ID from a Slack mention\n */\nexport function extractUserIdFromMention(mention: string): string | null {\n const match = mention.match(/^<@([UW][A-Z0-9]+)(?:\\|[^>]*)?>$/i);\n return match ? match[1] : null;\n}\n\n/**\n * Extracts channel ID from a Slack mention\n */\nexport function extractChannelIdFromMention(mention: string): string | null {\n const match = mention.match(/^<#([CGD][A-Z0-9]+)(?:\\|[^>]*)?>$/i);\n return match ? match[1] : null;\n}\n\n/**\n * Extracts URL from a Slack link\n */\nexport function extractUrlFromSlackLink(link: string): string | null {\n const match = link.match(/^<(https?:\\/\\/[^|>]+)(?:\\|[^>]*)?>$/);\n return match ? match[1] : null;\n}\n\n/**\n * Formats a user's display name\n */\nexport function formatSlackUserDisplayName(user: SlackUser): string {\n return user.profile.displayName || user.profile.realName || user.name;\n}\n\n/**\n * Formats a channel for display\n */\nexport function formatSlackChannel(channel: SlackChannel): string {\n if (channel.isIm) {\n return \"Direct Message\";\n }\n if (channel.isMpim) {\n return `Group DM: ${channel.name}`;\n }\n return `#${channel.name}`;\n}\n\n/**\n * Gets the channel type as a human-readable string\n */\nexport function getChannelTypeString(channel: SlackChannel): string {\n if (channel.isIm) {\n return \"DM\";\n }\n if (channel.isMpim) {\n return \"Group DM\";\n }\n if (channel.isPrivate || channel.isGroup) {\n return \"Private Channel\";\n }\n return \"Channel\";\n}\n\n/**\n * Resolves the system location string for logging/display\n */\nexport function resolveSlackSystemLocation(\n channel: SlackChannel,\n teamName?: string,\n): string {\n const channelType = getChannelTypeString(channel);\n const channelName = formatSlackChannel(channel);\n if (teamName) {\n return `${teamName} - ${channelType}: ${channelName}`;\n }\n return `${channelType}: ${channelName}`;\n}\n\n/**\n * Checks if a channel is a direct message\n */\nexport function isDirectMessage(channel: SlackChannel): boolean {\n return channel.isIm;\n}\n\n/**\n * Checks if a channel is a group DM (multi-party IM)\n */\nexport function isGroupDm(channel: SlackChannel): boolean {\n return channel.isMpim;\n}\n\n/**\n * Checks if a channel is a private channel\n */\nexport function isPrivateChannel(channel: SlackChannel): boolean {\n return channel.isPrivate || channel.isGroup;\n}\n\n/**\n * Truncates text to a maximum length with an ellipsis\n */\nexport function truncateText(\n text: string,\n maxLength: number,\n ellipsis = \"…\",\n): string {\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - ellipsis.length) + ellipsis;\n}\n\n/**\n * Strips Slack mrkdwn formatting from text\n */\nexport function stripSlackFormatting(text: string): string {\n return text\n .replace(/```[\\s\\S]*?```/g, \"\") // Code blocks (must be before inline code)\n .replace(/\\*([^*]+)\\*/g, \"$1\") // Bold\n .replace(/_([^_]+)_/g, \"$1\") // Italic\n .replace(/~([^~]+)~/g, \"$1\") // Strikethrough\n .replace(/`([^`]+)`/g, \"$1\") // Inline code\n .replace(/<@[UW][A-Z0-9]+(?:\\|[^>]*)?>/gi, \"\") // User mentions\n .replace(/<#[CGD][A-Z0-9]+(?:\\|[^>]*)?>/gi, \"\") // Channel mentions\n .replace(/<!subteam\\^[A-Z0-9]+(?:\\|[^>]*)?>/gi, \"\") // User group mentions\n .replace(/<!(?:here|channel|everyone)(?:\\|[^>]*)?>/gi, \"\") // Special mentions\n .replace(/<(https?:\\/\\/[^|>]+)(?:\\|([^>]*))?>/, \"$2\") // Links with text\n .replace(/<(https?:\\/\\/[^>]+)>/, \"$1\") // Plain links\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .trim();\n}\n\n/**\n * Builds a Slack message permalink\n */\nexport function buildSlackMessagePermalink(\n workspaceDomain: string,\n channelId: string,\n messageTs: string,\n): string {\n const formattedTs = `p${messageTs.replace(\".\", \"\")}`;\n return `https://${workspaceDomain}.slack.com/archives/${channelId}/${formattedTs}`;\n}\n\n/**\n * Parses a Slack message permalink\n */\nexport function parseSlackMessagePermalink(\n link: string,\n): { workspaceDomain: string; channelId: string; messageTs: string } | null {\n const match = link.match(\n /^https?:\\/\\/([^.]+)\\.slack\\.com\\/archives\\/([CGD][A-Z0-9]+)\\/p(\\d+)/i,\n );\n if (!match) {\n return null;\n }\n\n const ts = match[3];\n // Convert p1234567890123456 to 1234567890.123456\n const messageTs = `${ts.slice(0, 10)}.${ts.slice(10)}`;\n\n return {\n workspaceDomain: match[1],\n channelId: match[2],\n messageTs,\n };\n}\n",
|
|
12
|
-
"import { type IAgentRuntime, Service } from \"@elizaos/core\";\n\n// Inlined to avoid adding @elizaos/plugin-workflow as a compile-time dependency.\n// The runtime duck-types the service — only the serviceType string and resolve() shape matter.\nconst WORKFLOW_CREDENTIAL_PROVIDER_TYPE = \"workflow_credential_provider\";\ntype CredentialProviderResult =\n | { status: \"credential_data\"; data: Record<string, unknown> }\n | { status: \"needs_auth\"; authUrl: string }\n | null;\n\nconst SUPPORTED = [\"slackApi\", \"slackOAuth2Api\"];\n\nexport class SlackWorkflowCredentialProvider extends Service {\n static override readonly serviceType = WORKFLOW_CREDENTIAL_PROVIDER_TYPE;\n override capabilityDescription =\n \"Supplies Slack credentials to the workflow plugin.\";\n\n static async start(\n runtime: IAgentRuntime,\n ): Promise<SlackWorkflowCredentialProvider> {\n return new SlackWorkflowCredentialProvider(runtime);\n }\n\n async stop(): Promise<void> {}\n\n async resolve(\n _userId: string,\n credType: string,\n ): Promise<CredentialProviderResult> {\n // slackApi takes a bot token (xoxb-) for the legacy credential type.\n // slackOAuth2Api takes a user OAuth token (xoxp-) — NOT the Socket Mode app token (xapp-).\n // SLACK_APP_TOKEN is xapp- and only usable for Socket Mode WebSocket connections; it has no\n // API scopes, so wiring it as an OAuth2 access token would yield invalid_auth at execution.\n const botToken = this.runtime.getSetting(\"SLACK_BOT_TOKEN\") as\n | string\n | undefined;\n const userToken = this.runtime.getSetting(\"SLACK_USER_TOKEN\") as\n | string\n | undefined;\n if (credType === \"slackApi\" && botToken?.trim()) {\n return {\n status: \"credential_data\",\n data: { accessToken: botToken.trim() },\n };\n }\n if (credType === \"slackOAuth2Api\" && userToken?.trim()) {\n return {\n status: \"credential_data\",\n data: { accessToken: userToken.trim() },\n };\n }\n return null;\n }\n\n checkCredentialTypes(credTypes: string[]): {\n supported: string[];\n unsupported: string[];\n } {\n return {\n supported: credTypes.filter((t) => SUPPORTED.includes(t)),\n unsupported: credTypes.filter((t) => !SUPPORTED.includes(t)),\n };\n }\n}\n"
|
|
13
|
-
],
|
|
14
|
-
"mappings": ";AAAA;AAAA;AAAA,YAGE;AAAA;;;ACSF;AAAA;AAAA;;;ACPO,IAAM,qBAAqB;AAmJ3B,SAAS,kBAAkB,CAAC,WAAmC;AAAA,EACpE,IAAI,CAAC,aAAa,OAAO,cAAc,UAAU;AAAA,IAC/C,OAAO;AAAA,EACT;AAAA,EACA,MAAM,UAAU,UAAU,KAAK,EAAE,YAAY;AAAA,EAC7C,OAAO,WAAW;AAAA;AAMpB,SAAS,mBAAmB,CAC1B,KACA,QACoB;AAAA,EACpB,MAAM,UAAU,KAAK,KAAK;AAAA,EAC1B,OAAO,SAAS,WAAW,MAAM,IAAI,UAAU;AAAA;AAM1C,SAAS,oBAAoB,CAAC,KAAyC;AAAA,EAC5E,OAAO,oBAAoB,KAAK,OAAO;AAAA;AAMlC,SAAS,oBAAoB,CAAC,KAAyC;AAAA,EAC5E,OAAO,oBAAoB,KAAK,OAAO;AAAA;AAMlC,SAAS,qBAAqB,CAAC,KAAyC;AAAA,EAC7E,OAAO,oBAAoB,KAAK,OAAO;AAAA;AAMlC,SAAS,qBAAqB,CACnC,SACyB;AAAA,EACzB,MAAM,iBAAiB,QAAQ,WAAW,UAAU;AAAA,EAIpD,OAAO;AAAA,IACL,SAAS,gBAAgB;AAAA,IACzB,UAAU,gBAAgB;AAAA,IAC1B,UAAU,gBAAgB;AAAA,IAC1B,UAAU,gBAAgB;AAAA,EAC5B;AAAA;AAMK,SAAS,mBAAmB,CAAC,SAAkC;AAAA,EACpE,MAAM,SAAS,sBAAsB,OAAO;AAAA,EAC5C,MAAM,WAAW,OAAO;AAAA,EAExB,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAAA,IAC7C,OAAO,CAAC,kBAAkB;AAAA,EAC5B;AAAA,EAEA,MAAM,MAAM,OAAO,KAAK,QAAQ,EAAE,OAAO,OAAO;AAAA,EAChD,IAAI,IAAI,WAAW,GAAG;AAAA,IACpB,OAAO,CAAC,kBAAkB;AAAA,EAC5B;AAAA,EAEA,OAAO,IAAI,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAAA;AAM/C,SAAS,4BAA4B,CAAC,SAAgC;AAAA,EAC3E,MAAM,MAAM,oBAAoB,OAAO;AAAA,EACvC,IAAI,IAAI,SAAS,kBAAkB,GAAG;AAAA,IACpC,OAAO;AAAA,EACT;AAAA,EACA,OAAO,IAAI,MAAM;AAAA;AAMnB,SAAS,gBAAgB,CACvB,SACA,WACgC;AAAA,EAChC,MAAM,SAAS,sBAAsB,OAAO;AAAA,EAC5C,MAAM,WAAW,OAAO;AAAA,EAExB,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,OAAO,SAAS;AAAA;AASlB,SAAS,aAA+B,CAAC,KAAoB;AAAA,EAC3D,OAAO,OAAO,YACZ,OAAO,QAAQ,GAAG,EAAE,OAAO,IAAI,OAAO,MAAM,SAAS,CACvD;AAAA;AAGF,SAAS,uBAAuB,CAC9B,SACA,WACoB;AAAA,EACpB,MAAM,cAAc,sBAAsB,OAAO;AAAA,EACjD,QAAQ,UAAU,aAAa,eAAe;AAAA,EAC9C,MAAM,gBAAgB,iBAAiB,SAAS,SAAS,KAAK,CAAC;AAAA,EAG/D,MAAM,gBAAgB,QAAQ,WAAW,mBAAmB;AAAA,EAI5D,MAAM,YAAgC;AAAA,IACpC,yBAEI,QAAQ,WAAW,kCAAkC,GACpD,YAAY,MAAM;AAAA,IACvB,6BAEI,QAAQ,WAAW,uCAAuC,GACzD,YAAY,MAAM;AAAA,IACvB,mBAAmB,gBACf,cACG,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,IACjB;AAAA,EACN;AAAA,EAIA,OAAO;AAAA,OACF,cAAc,SAAS;AAAA,OACvB,cAAc,UAAU;AAAA,OACxB,cAAc,aAAa;AAAA,EAChC;AAAA;AAMK,SAAS,mBAAmB,CACjC,SACA,WACsB;AAAA,EACtB,MAAM,sBAAsB,mBAAmB,SAAS;AAAA,EACxD,MAAM,cAAc,sBAAsB,OAAO;AAAA,EAEjD,MAAM,cAAc,YAAY,YAAY;AAAA,EAC5C,MAAM,SAAS,wBAAwB,SAAS,mBAAmB;AAAA,EACnE,MAAM,iBAAiB,OAAO,YAAY;AAAA,EAC1C,MAAM,UAAU,eAAe;AAAA,EAE/B,MAAM,WAAW,wBAAwB;AAAA,EAGzC,MAAM,cAAc,WAChB,qBAAqB,QAAQ,WAAW,iBAAiB,CAAW,IACpE;AAAA,EACJ,MAAM,iBAAiB,qBAAqB,OAAO,QAAQ;AAAA,EAC3D,MAAM,WAAW,kBAAkB;AAAA,EACnC,MAAM,iBAAmC,iBACrC,WACA,cACE,QACA;AAAA,EAGN,MAAM,cAAc,WAChB,qBAAqB,QAAQ,WAAW,iBAAiB,CAAW,IACpE;AAAA,EACJ,MAAM,iBAAiB,qBAAqB,OAAO,QAAQ;AAAA,EAC3D,MAAM,WAAW,kBAAkB;AAAA,EACnC,MAAM,iBAAmC,iBACrC,WACA,cACE,QACA;AAAA,EAGN,MAAM,gBACJ,OAAO,iBACN,QAAQ,WAAW,sBAAsB;AAAA,EAG5C,MAAM,eAAe,WACjB,sBAAsB,QAAQ,WAAW,kBAAkB,CAAW,IACtE;AAAA,EACJ,MAAM,kBAAkB,sBAAsB,OAAO,SAAS;AAAA,EAC9D,MAAM,YAAY,mBAAmB;AAAA,EAErC,OAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA,MAAM,OAAO,MAAM,KAAK,KAAK;AAAA,IAC7B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV;AAAA;AAMK,SAAS,wBAAwB,CACtC,SACwB;AAAA,EACxB,OAAO,oBAAoB,OAAO,EAC/B,IAAI,CAAC,cAAc,oBAAoB,SAAS,SAAS,CAAC,EAC1D,OAAO,CAAC,YAAY,QAAQ,WAAW,QAAQ,QAAQ;AAAA;AAMrD,SAAS,qBAAqB,CAAC,SAAiC;AAAA,EACrE,MAAM,WAAW,yBAAyB,OAAO;AAAA,EACjD,OAAO,SAAS,SAAS;AAAA;AAMpB,SAAS,uBAAuB,CACrC,SACA,UACyB;AAAA,EACzB,MAAM,aAAa,UAAU,YAAY,EAAE,KAAK;AAAA,EAGhD,IACE,cACA,QAAQ,OAAO,wBAAwB,gBAAgB,WACvD;AAAA,IACA,OAAO,QAAQ,OAAO,sBAAsB,eAAe;AAAA,EAC7D;AAAA,EAGA,IAAI,eAAe,YAAY,eAAe,MAAM;AAAA,IAClD,IAAI,QAAQ,OAAO,IAAI,gBAAgB,WAAW;AAAA,MAChD,OAAO,QAAQ,OAAO,GAAG;AAAA,IAC3B;AAAA,EACF;AAAA,EAGA,OAAO,QAAQ,OAAO,eAAe;AAAA;;;ACnavC;AAAA;AAAA;AAqDA,eAAsB,8BAA8B,CAClD,QAKC;AAAA,EACD,MAAM,OAAyC,CAAC;AAAA,EAChD,MAAM,eAAe,oBAAoB,OAAO,SAAS;AAAA,IACvD,UAAU,OAAO;AAAA,IACjB,WAAW,OAAO;AAAA,IAClB,QAAQ,OAAO;AAAA,EACjB,CAAC;AAAA,EACD,IAAI,aAAa,WAAW,GAAG;AAAA,IAC7B,MAAM,IAAI,MACR,0EAA0E,OAAO,oBAAoB,OAAO,0FAC9G;AAAA,EACF;AAAA,EACA,IAAI,CAAC,OAAO,kBAAkB;AAAA,IAC5B,MAAM,IAAI,MACR,oDAAoD,OAAO,oBAAoB,OAAO,8FACxF;AAAA,EACF;AAAA,EACA,MAAM,iBAAiB,4BACrB,OAAO,SACP,OAAO,SACP,OAAO,gBACT;AAAA,EACA,IAAI,eAAe,WAAW,GAAG;AAAA,IAC/B,MAAM,IAAI,MACR,+DAA+D,OAAO,oBAAoB,OAAO,+FACnG;AAAA,EACF;AAAA,EAEA,WAAW,cAAc,OAAO,aAAa;AAAA,IAC3C,MAAM,aAAa,iCAAiC;AAAA,MAClD,SAAS,eAAe,OAAO,QAAQ,OAAO,KAAK;AAAA,MACnD,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO;AAAA,MAClB,gBAAgB,WAAW;AAAA,IAC7B,CAAC;AAAA,IACD,MAAM,WAAW,MAAM,6BACrB,cACA,YACA,UACF;AAAA,IACA,KAAK,KAAK;AAAA,MACR,gBAAgB,WAAW;AAAA,MAC3B;AAAA,SACI,WAAW,cAAc,YACzB,EAAE,WAAW,WAAW,UAAU,IAClC,CAAC;AAAA,SACD,WAAW,WAAW,EAAE,UAAU,WAAW,SAAS,IAAI,CAAC;AAAA,IACjE,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,KAAK,SAAS,GAAG;AAAA,IACnB,MAAM,mBAAmB,gBAAgB,IAAI;AAAA,EAC/C;AAAA,EAEA,OAAO;AAAA,IACL;AAAA,IACA,gBAAgB,aAAa,SAAS;AAAA,IACtC,kBAAkB,eAAe,SAAS;AAAA,EAC5C;AAAA;AAGF,SAAS,mBAAmB,CAC1B,SACA,SACe;AAAA,EACf,MAAM,UAAyB,CAAC;AAAA,EAChC,MAAM,kBAAkB,gBAAgB,SAAS;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAAA,EAWD,IAAI,OAAO,iBAAiB,cAAc,YAAY;AAAA,IACpD,QAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,OAAO,UAAU,eACtB,gBAAgB,YAAY;AAAA,QAC1B;AAAA,QACA,SAAS,eAAe,QAAQ,OAAO,KAAK;AAAA,QAC5C,UAAU,QAAQ;AAAA,QAClB,WAAW,QAAQ;AAAA,QACnB,gBAAgB,WAAW;AAAA,QAC3B,OAAO,WAAW;AAAA,QAClB,QAAQ,QAAQ;AAAA,MAClB,CAAC,KAAK;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,QAAQ,gBAAgB,SAAS,CAAC,SAAS,OAAO,CAAC;AAAA,EAOzD,IAAI,OAAO,OAAO,QAAQ,YAAY;AAAA,IACpC,QAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,OAAO,UAAU,eAAe;AAAA,QACrC,MAAM,MAAM,MAAM,UAAU,WAAW,OAAO;AAAA,UAC5C,WAAW;AAAA,UACX,QAAQ,QAAQ;AAAA,QAClB,CAAC;AAAA,QACD,OAAO;AAAA;AAAA,IAEX,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,UAAU,WAAW,SAAS,SAAS;AAAA,EAa7C,IACE,OAAO,SAAS,cAAc,cAC9B,OAAO,SAAS,QAAQ,YACxB;AAAA,IACA,QAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,OAAO,OAAO,UAAU,eAAe;AAAA,QACrC,IAAI,OAAO,QAAQ,cAAc,YAAY;AAAA,UAC3C,MAAM,QAAQ,UAAU,UAAU,WAAW,OAAO;AAAA,YAClD,WAAW;AAAA,UACb,CAAC;AAAA,UACD,OAAO;AAAA,QACT;AAAA,QACA,MAAM,QAAQ,MACZ,UACA,WAAW,OACX,EAAE,OAAO,UAAU,SAAS,QAAQ,QAAQ,GAC5C,EAAE,WAAW,KAAK,CACpB;AAAA,QACA,OAAO;AAAA;AAAA,IAEX,CAAC;AAAA,EACH;AAAA,EAEA,OAAO;AAAA;AAGT,SAAS,2BAA2B,CAClC,SACA,SACA,WACuB;AAAA,EACvB,MAAM,aAAa;AAAA,IACjB,SAAS,aAAa;AAAA,IACtB,WAAW,SAAS,sCAAsC;AAAA,IACzD,QAAkD;AAAA,EACrD,EAAE,OAAO,OAAO;AAAA,EAEhB,MAAM,UAAiC,CAAC;AAAA,EACxC,WAAW,aAAa,YAAY;AAAA,IAClC,MAAM,SAAS;AAAA,IAgBf,IAAI,OAAO,OAAO,qCAAqC,YAAY;AAAA,MACjE,QAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,OAAO,OAAO,QAAQ;AAAA,UACpB,MAAM,OAAO,mCAAmC;AAAA,YAC9C;AAAA,YACA,gBAAgB,IAAI;AAAA,YACpB,UAAU,IAAI;AAAA,eACV,IAAI,WAAW,EAAE,UAAU,IAAI,SAAS,IAAI,CAAC;AAAA,eAC7C,IAAI,cAAc,YAClB,EAAE,WAAW,IAAI,UAAU,IAC3B,CAAC;AAAA,UACP,CAAC;AAAA;AAAA,MAEL,CAAC;AAAA,IACH,EAAO,SAAI,OAAO,OAAO,qBAAqB,YAAY;AAAA,MACxD,QAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,OAAO,OAAO,QAAQ;AAAA,UACpB,MAAM,OAAO,mBAAmB;AAAA,YAC9B;AAAA,YACA,gBAAgB,IAAI;AAAA,YACpB,UAAU,IAAI;AAAA,eACV,IAAI,WAAW,EAAE,UAAU,IAAI,SAAS,IAAI,CAAC;AAAA,eAC7C,IAAI,cAAc,YAClB,EAAE,WAAW,IAAI,UAAU,IAC3B,CAAC;AAAA,UACP,CAAC;AAAA;AAAA,MAEL,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAGT,eAAe,4BAA4B,CACzC,SACA,YACA,YACiB;AAAA,EACjB,MAAM,SAAmB,CAAC;AAAA,EAC1B,WAAW,UAAU,SAAS;AAAA,IAC5B,IAAI;AAAA,MACF,OAAO,MAAM,OAAO,MAAM,YAAY,UAAU;AAAA,MAChD,OAAO,OAAO;AAAA,MACd,OAAO,KACL,GAAG,OAAO,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC1E;AAAA;AAAA,EAEJ;AAAA,EACA,MAAM,IAAI,MACR,8CAA8C,eAAe,OAAO,KAAK,IAAI,GAC/E;AAAA;AAGF,eAAe,kBAAkB,CAC/B,SACA,MACe;AAAA,EACf,MAAM,SAAmB,CAAC;AAAA,EAC1B,WAAW,UAAU,SAAS;AAAA,IAC5B,IAAI;AAAA,MACF,WAAW,OAAO,MAAM;AAAA,QACtB,MAAM,OAAO,MAAM,GAAG;AAAA,MACxB;AAAA,MACA;AAAA,MACA,OAAO,OAAO;AAAA,MACd,OAAO,KACL,GAAG,OAAO,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC1E;AAAA;AAAA,EAEJ;AAAA,EACA,MAAM,IAAI,MACR,gDAAgD,OAAO,KAAK,IAAI,GAClE;AAAA;AAGF,SAAS,gCAAgC,CAAC,QAK/B;AAAA,EACT,OAAO;AAAA,IACL;AAAA,IACA,sBAAsB,OAAO,OAAO;AAAA,IACpC,sBAAsB,OAAO,QAAQ;AAAA,IACrC,sBAAsB,OAAO,SAAS;AAAA,IACtC,sBAAsB,OAAO,cAAc;AAAA,EAC7C,EAAE,KAAK,GAAG;AAAA;AAGZ,SAAS,qBAAqB,CAAC,OAAuB;AAAA,EACpD,MAAM,aAAa,MAChB,KAAK,EACL,QAAQ,oBAAoB,GAAG,EAC/B,QAAQ,YAAY,EAAE;AAAA,EACzB,QAAQ,cAAc,WAAW,MAAM,GAAG,EAAE;AAAA;AAG9C,SAAS,eAAe,CACtB,SACA,cACS;AAAA,EACT,WAAW,eAAe,cAAc;AAAA,IACtC,MAAM,UAAU,WAAW,SAAS,WAAW;AAAA,IAC/C,IAAI;AAAA,MAAS,OAAO;AAAA,EACtB;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,UAAU,CAAC,SAAwB,aAA8B;AAAA,EACxE,IAAI;AAAA,IACF,OAAO,QAAQ,aAAa,WAAW,KAAK;AAAA,IAC5C,MAAM;AAAA,IACN,OAAO;AAAA;AAAA;AAIX,SAAS,cAAc,CAAC,OAAoC;AAAA,EAC1D,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,MAAM,KAAK,IAAI;AAAA;;;AChW7D,IAAK;AAAA,CAAL,CAAK,qBAAL;AAAA,EACL,uCAAmB;AAAA,EACnB,mCAAe;AAAA,EACf,qCAAiB;AAAA,EACjB,uCAAmB;AAAA,EACnB,qCAAiB;AAAA,EACjB,mCAAe;AAAA,EACf,4CAAwB;AAAA,EACxB,0CAAsB;AAAA,EACtB,kCAAc;AAAA,EACd,oCAAgB;AAAA,EAChB,kCAAc;AAAA,EACd,mCAAe;AAAA,GAZL;AA8QL,IAAM,qBAAqB;AAsB3B,MAAM,yBAAyB,MAAM;AAAA,EAGxB;AAAA,EAFlB,WAAW,CACT,SACgB,MAChB;AAAA,IACA,MAAM,OAAO;AAAA,IAFG;AAAA,IAGhB,KAAK,OAAO;AAAA;AAEhB;AAAA;AAEO,MAAM,wCAAwC,iBAAiB;AAAA,EACpE,WAAW,GAAG;AAAA,IACZ,MAAM,oCAAoC,yBAAyB;AAAA,IACnE,KAAK,OAAO;AAAA;AAEhB;AAAA;AAEO,MAAM,qCAAqC,iBAAiB;AAAA,EACjE,WAAW,GAAG;AAAA,IACZ,MAAM,iCAAiC,sBAAsB;AAAA,IAC7D,KAAK,OAAO;AAAA;AAEhB;AAAA;AAEO,MAAM,gCAAgC,iBAAiB;AAAA,EAC5D,WAAW,CAAC,eAAuB;AAAA,IACjC,MAAM,mCAAmC,iBAAiB,gBAAgB;AAAA,IAC1E,KAAK,OAAO;AAAA;AAEhB;AAAA;AAEO,MAAM,sBAAsB,iBAAiB;AAAA,EAGhC;AAAA,EAFlB,WAAW,CACT,SACgB,cAChB;AAAA,IACA,MAAM,SAAS,WAAW;AAAA,IAFV;AAAA,IAGhB,KAAK,OAAO;AAAA;AAEhB;AAKO,SAAS,gBAAgB,CAAC,IAAqB;AAAA,EAEpD,OAAO,uBAAuB,KAAK,EAAE;AAAA;AAMhC,SAAS,aAAa,CAAC,IAAqB;AAAA,EAEjD,OAAO,sBAAsB,KAAK,EAAE;AAAA;AAM/B,SAAS,aAAa,CAAC,IAAqB;AAAA,EAEjD,OAAO,mBAAmB,KAAK,EAAE;AAAA;AAM5B,SAAS,gBAAgB,CAAC,IAAqB;AAAA,EAEpD,OAAO,eAAe,KAAK,EAAE;AAAA;AAMxB,SAAS,qBAAqB,CACnC,MACiD;AAAA,EAEjD,MAAM,QAAQ,KAAK,MAAM,uCAAuC;AAAA,EAChE,IAAI,CAAC;AAAA,IAAO,OAAO;AAAA,EAEnB,MAAM,YAAY,MAAM;AAAA,EACxB,MAAM,KAAK,MAAM;AAAA,EAEjB,MAAM,YAAY,GAAG,GAAG,MAAM,GAAG,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,EAEnD,OAAO,EAAE,WAAW,UAAU;AAAA;AAMzB,SAAS,sBAAsB,CAAC,IAAoB;AAAA,EAEzD,OAAO,IAAI,GAAG,QAAQ,KAAK,EAAE;AAAA;AAMxB,SAAS,uBAAuB,CAAC,MAAyB;AAAA,EAC/D,OAAO,KAAK,QAAQ,eAAe,KAAK,QAAQ,YAAY,KAAK;AAAA;AAM5D,SAAS,mBAAmB,CAAC,SAAyC;AAAA,EAC3E,IAAI,QAAQ;AAAA,IAAM,OAAO;AAAA,EACzB,IAAI,QAAQ;AAAA,IAAQ,OAAO;AAAA,EAC3B,IAAI,QAAQ,WAAW,QAAQ;AAAA,IAAW,OAAO;AAAA,EACjD,OAAO;AAAA;AAMF,IAAM,2BAA2B;AAKjC,IAAM,mBAAmB;AAKzB,IAAM,sBAAsB,OAAO,OAAO;;;AHjZjD,IAAM,4BAA4B;AAClC,IAAM,wBAAwB;AAE9B,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,mBAA8C;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AACF;AA8BA,SAAS,KAAK,GAAW;AAAA,EACvB,OAAO,KAAK,IAAI;AAAA;AAGlB,SAAS,eAAc,CAAC,OAAoC;AAAA,EAC1D,IAAI,OAAO,UAAU;AAAA,IAAU;AAAA,EAC/B,MAAM,UAAU,MAAM,KAAK;AAAA,EAC3B,OAAO,QAAQ,SAAS,IAAI,UAAU;AAAA;AAGxC,SAAS,WAAW,CAAC,SAAwB,KAAiC;AAAA,EAC5E,OAAO,gBAAe,QAAQ,aAAa,GAAG,CAAC;AAAA;AAGjD,SAAS,gBAAgB,CAAC,SAIxB;AAAA,EACA,MAAM,WAAW,YAAY,SAAS,iBAAiB;AAAA,EACvD,MAAM,eAAe,YAAY,SAAS,qBAAqB;AAAA,EAC/D,MAAM,cAAc,YAAY,SAAS,oBAAoB;AAAA,EAC7D,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,aAAa;AAAA,IAC9C,MAAM,IAAI,MACR,qGACF;AAAA,EACF;AAAA,EACA,OAAO,EAAE,UAAU,cAAc,YAAY;AAAA;AAG/C,SAAS,iBAAiB,CACxB,WACA,MACA,WACA,QACkB;AAAA,EAClB,OAAO;AAAA,IACL,IAAI;AAAA,IACJ,UAAU;AAAA,IACV,OAAO,QAAQ,UAAU;AAAA,IACzB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,WAAW,MAAM;AAAA,IACjB,WAAW,MAAM;AAAA,IACjB,UAAU;AAAA,MACR,aAAa;AAAA,MACb;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAGF,SAAS,iBAAiB,CACxB,SACA,UAC2B;AAAA,EAC3B,IAAI,MAAM,QAAQ,OAAO;AAAA,IAAG,OAAO;AAAA,EACnC,IAAI,OAAO,YAAY,YAAY,QAAQ,KAAK;AAAA,IAAG,OAAO,CAAC,OAAO;AAAA,EAClE,OAAO;AAAA;AAGT,SAAS,uBAAuB,CAC9B,SACA,OACkB;AAAA,EAClB,OAAO;AAAA,OACF;AAAA,OACA;AAAA,IACH,UAAU;AAAA,IACV,IAAI,QAAQ;AAAA,IACZ,SAAS,kBAAkB,MAAM,SAAS,QAAQ,OAAO;AAAA,IACzD,YACE,MAAM,eAAe,YACjB,QAAQ,aACP,MAAM,cAAc;AAAA,IAC3B,eACE,MAAM,kBAAkB,YACpB,QAAQ,gBACP,MAAM,iBAAiB;AAAA,IAC9B,gBACE,MAAM,mBAAmB,YACrB,QAAQ,iBACP,MAAM,kBAAkB;AAAA,IAC/B,iBACE,MAAM,oBAAoB,YACtB,QAAQ,kBACP,MAAM,mBAAmB;AAAA,IAChC,UAAU,MAAM,YAAY,QAAQ;AAAA,IACpC,WAAW,QAAQ;AAAA,EACrB;AAAA;AAGK,SAAS,mCAAmC,CACjD,SAC0B;AAAA,EAC1B,OAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO;AAAA,IAEP,cAAc,OACZ,YACgC;AAAA,MAChC,MAAM,YAAY,MAAM,QACrB,WAAW,EACX,aAAa,kBAAkB;AAAA,MAClC,MAAM,gBAAgB,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAAA,MAE7D,MAAM,UAAU,yBAAyB,OAAO;AAAA,MAChD,MAAM,mBAAmB,6BAA6B,OAAO;AAAA,MAC7D,MAAM,cAAkC,QACrC,OAAO,CAAC,YAAY,CAAC,cAAc,IAAI,QAAQ,SAAS,CAAC,EACzD,IAAI,CAAC,YACJ,kBACE,QAAQ,WACR,QAAQ,MACR,QAAQ,cAAc,kBACtB,QAAQ,cACV,CACF;AAAA,MAEF,IAAI,YAAY,WAAW,KAAK,UAAU,WAAW,GAAG;AAAA,QACtD,MAAM,WAAW,oBAAoB,SAAS,kBAAkB;AAAA,QAChE,IAAI,SAAS,UAAU;AAAA,UACrB,YAAY,KACV,kBACE,oBACA,SAAS,MACT,MACA,SAAS,cACX,CACF;AAAA,QACF;AAAA,MACF;AAAA,MAEA,OAAO,CAAC,GAAG,WAAW,GAAG,WAAW;AAAA;AAAA,IAGtC,eAAe,OAAO,UAAiC;AAAA,MACrD,OAAO;AAAA,WACF;AAAA,QACH,UAAU;AAAA,QACV,MAAM,MAAM,QAAQ;AAAA,QACpB,SAAS,MAAM,WAAW;AAAA,QAC1B,YAAY,MAAM,cAAc;AAAA,QAChC,QAAQ,MAAM,UAAU;AAAA,MAC1B;AAAA;AAAA,IAGF,cAAc,OACZ,WACA,OACA,YACG;AAAA,MACH,MAAM,WAAW,MAAM,QACpB,WAAW,EACX,WAAW,oBAAoB,SAAS;AAAA,MAC3C,IAAI,UAAU;AAAA,QACZ,OAAO,wBAAwB,UAAU,KAAK;AAAA,MAChD;AAAA,MACA,OAAO,KAAK,OAAO,UAAU,mBAAmB;AAAA;AAAA,IAGlD,eAAe,YAA2B;AAAA,IAK1C,YAAY,OACV,YACuC;AAAA,MACvC,MAAM,SAAS,iBAAiB,OAAO;AAAA,MACvC,MAAM,cAAc,QAAQ,eAAe,OAAO;AAAA,MAClD,MAAM,kBACJ,QAAQ,UAAU,QAAQ,OAAO,SAAS,IACtC,QAAQ,SACR;AAAA,MAEN,MAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC,WAAW,OAAO;AAAA,QAClB,cAAc;AAAA,QACd,OAAO,gBAAgB,KAAK,GAAG;AAAA,QAC/B,OAAO,QAAQ,KAAK;AAAA,MACtB,CAAC;AAAA,MAED,OAAO;AAAA,QACL,SAAS,GAAG,6BAA6B,OAAO,SAAS;AAAA,QACzD,UAAU;AAAA,aACL,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA;AAAA,IAGF,eAAe,OACb,SACA,YAC0C;AAAA,MAC1C,MAAM,OAAO,gBAAe,QAAQ,IAAI;AAAA,MACxC,IAAI,CAAC,MAAM;AAAA,QACT,MAAM,IAAI,MACR,wDACF;AAAA,MACF;AAAA,MAEA,MAAM,SAAS,iBAAiB,OAAO;AAAA,MACvC,MAAM,cACJ,gBAAe,QAAQ,KAAK,WAAW,KACvC,gBACG,QAAQ,KAAK,UACV,WACN,KACA,OAAO;AAAA,MAET,MAAM,cAAc,IAAI,gBAAgB;AAAA,QACtC,WAAW,OAAO;AAAA,QAClB,eAAe,OAAO;AAAA,QACtB;AAAA,QACA,cAAc;AAAA,MAChB,CAAC;AAAA,MAED,MAAM,WAAW,MAAM,MAAM,uBAAuB;AAAA,QAClD,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,QAC/D,MAAM,YAAY,SAAS;AAAA,MAC7B,CAAC;AAAA,MACD,IAAI,CAAC,SAAS,IAAI;AAAA,QAChB,MAAM,OAAO,MAAM,SAAS,KAAK;AAAA,QACjC,MAAM,IAAI,MACR,oCAAoC,SAAS,WAAW,MAC1D;AAAA,MACF;AAAA,MACA,MAAM,SAAU,MAAM,SAAS,KAAK;AAAA,MACpC,IAAI,CAAC,OAAO,MAAM,CAAC,OAAO,cAAc;AAAA,QACtC,MAAM,IAAI,MACR,2CAA2C,OAAO,SAAS,WAC7D;AAAA,MACF;AAAA,MAEA,MAAM,SAAS,OAAO,MAAM;AAAA,MAC5B,IAAI,CAAC,QAAQ;AAAA,QACX,MAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AAAA,MACA,MAAM,WAAW,OAAO,MAAM;AAAA,MAC9B,MAAM,gBAAgB,OAAO,QAAQ,OAAO,MAAM,MAAM,GAAG,IAAI,CAAC;AAAA,MAChE,MAAM,YACJ,OAAO,OAAO,eAAe,WACzB,KAAK,IAAI,IAAI,OAAO,aAAa,OACjC;AAAA,MACN,MAAM,sBACJ,OAAO,OAAO,aAAa,eAAe,WACtC,KAAK,IAAI,IAAI,OAAO,YAAY,aAAa,OAC7C;AAAA,MACN,MAAM,yBAAyB,OAAO,KAAK,IAAI,CAAC;AAAA,MAChD,MAAM,kBAAkB;AAAA,QACtB;AAAA,QACA,UAAU,YAAY;AAAA,QACtB,OAAO,OAAO,UAAU;AAAA,QACxB,WAAW,OAAO,eAAe;AAAA,QACjC,cAAc,OAAO,YAAY,MAAM;AAAA,QACvC,cAAc,OAAO,aAAa,MAAM;AAAA,QACxC,WAAW,OAAO,cAAc;AAAA,QAChC;AAAA,QACA,iBAAiB,QACf,OAAO,iBAAiB,OAAO,aAAa,aAC9C;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,MAAM,iBAAiB,MAAM,QAAQ,cACnC,oBACA;AAAA,QACE,UAAU;AAAA,QACV,MAAM;AAAA,QACN,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,OAAO,YAAY,mBAAmB;AAAA,QACtC,UAAU;AAAA,MACZ,GACA,QAAQ,KAAK,SACf;AAAA,MACA,MAAM,oBAAoB,MAAM,+BAA+B;AAAA,QAC7D;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,iBAAiB,eAAe;AAAA,QAChC,kBAAkB,eAAe;AAAA,QACjC,QAAQ;AAAA,QACR,aAAa;AAAA,UACX;AAAA,YACE,gBAAgB;AAAA,YAChB,OAAO,KAAK,UAAU;AAAA,cACpB,cAAc,OAAO;AAAA,iBACjB,OAAO,gBACP,EAAE,eAAe,OAAO,cAAc,IACtC,CAAC;AAAA,cACL,YAAY,OAAO,cAAc;AAAA,cACjC,OAAO,OAAO,SAAS,cAAc,KAAK,GAAG;AAAA,iBACzC,cAAc,YAAY,EAAE,YAAY,UAAU,IAAI,CAAC;AAAA,iBACvD,OAAO,aAAa,eACpB;AAAA,gBACE,aAAa;AAAA,kBACX,IAAI,OAAO,YAAY;AAAA,kBACvB,cAAc,OAAO,YAAY;AAAA,qBAC7B,OAAO,YAAY,gBACnB,EAAE,eAAe,OAAO,YAAY,cAAc,IAClD,CAAC;AAAA,qBACD,OAAO,YAAY,aACnB,EAAE,YAAY,OAAO,YAAY,WAAW,IAC5C,CAAC;AAAA,qBACD,OAAO,YAAY,QACnB,EAAE,OAAO,OAAO,YAAY,MAAM,IAClC,CAAC;AAAA,qBACD,wBAAwB,YACxB,EAAE,YAAY,oBAAoB,IAClC,CAAC;AAAA,gBACP;AAAA,cACF,IACA,CAAC;AAAA,YACP,CAAC;AAAA,eACG,cAAc,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,YAC/C,UAAU;AAAA,cACR,UAAU;AAAA,cACV,iBAAiB,QACf,OAAO,iBAAiB,OAAO,aAAa,aAC9C;AAAA,cACA,oBAAoB,QAAQ,OAAO,aAAa,YAAY;AAAA,YAC9D;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,MAED,MAAM,eAGF;AAAA,WACC;AAAA,QACH,IAAI,eAAe;AAAA,QACnB,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,UAAU;AAAA,aACL;AAAA,UACH,gBAAgB,kBAAkB;AAAA,UAClC,sBAAsB;AAAA,YACpB,gBAAgB,kBAAkB;AAAA,YAClC,kBAAkB,kBAAkB;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAAA,MAEA,OAAO,KACL;AAAA,QACE,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF,GACA,uBACF;AAAA,MAEA,OAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM,EAAE,QAAQ,YAAY;AAAA,MAC9B;AAAA;AAAA,EAEJ;AAAA;;;AIzcF;AAAA;AAAA;AAAA;AAAA;AAAA;AAsBA;;;AChBA,SAAS,wBAAwB,CAAC,MAAsB;AAAA,EACtD,OAAO,KACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM;AAAA;AAGzB,IAAM,uBAAuB;AAK7B,SAAS,wBAAwB,CAAC,OAAwB;AAAA,EACxD,IAAI,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,SAAS,GAAG,GAAG;AAAA,IAClD,OAAO;AAAA,EACT;AAAA,EACA,MAAM,QAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,EAC/B,OACE,MAAM,WAAW,GAAG,KACpB,MAAM,WAAW,GAAG,KACpB,MAAM,WAAW,GAAG,KACpB,MAAM,WAAW,SAAS,KAC1B,MAAM,WAAW,MAAM,KACvB,MAAM,WAAW,SAAS,KAC1B,MAAM,WAAW,UAAU,KAC3B,MAAM,WAAW,UAAU;AAAA;AAO/B,SAAS,wBAAwB,CAAC,MAAsB;AAAA,EACtD,IAAI,CAAC,KAAK,SAAS,GAAG,KAAK,CAAC,KAAK,SAAS,GAAG,KAAK,CAAC,KAAK,SAAS,GAAG,GAAG;AAAA,IACrE,OAAO;AAAA,EACT;AAAA,EAEA,qBAAqB,YAAY;AAAA,EACjC,MAAM,MAAgB,CAAC;AAAA,EACvB,IAAI,YAAY;AAAA,EAEhB,SACM,QAAQ,qBAAqB,KAAK,IAAI,EAC1C,OACA,QAAQ,qBAAqB,KAAK,IAAI,GACtC;AAAA,IACA,MAAM,aAAa,MAAM,SAAS;AAAA,IAClC,IAAI,KAAK,yBAAyB,KAAK,MAAM,WAAW,UAAU,CAAC,CAAC;AAAA,IACpE,MAAM,QAAQ,MAAM,MAAM;AAAA,IAC1B,IAAI,KACF,yBAAyB,KAAK,IAAI,QAAQ,yBAAyB,KAAK,CAC1E;AAAA,IACA,YAAY,aAAa,MAAM;AAAA,EACjC;AAAA,EAEA,IAAI,KAAK,yBAAyB,KAAK,MAAM,SAAS,CAAC,CAAC;AAAA,EACxD,OAAO,IAAI,KAAK,EAAE;AAAA;AAMb,SAAS,iBAAiB,CAAC,MAAsB;AAAA,EACtD,IAAI,CAAC,KAAK,SAAS,GAAG,KAAK,CAAC,KAAK,SAAS,GAAG,KAAK,CAAC,KAAK,SAAS,GAAG,GAAG;AAAA,IACrE,OAAO;AAAA,EACT;AAAA,EAEA,OAAO,KACJ,MAAM;AAAA,CAAI,EACV,IAAI,CAAC,SAAS;AAAA,IACb,IAAI,KAAK,WAAW,IAAI,GAAG;AAAA,MACzB,OAAO,KAAK,yBAAyB,KAAK,MAAM,CAAC,CAAC;AAAA,IACpD;AAAA,IACA,OAAO,yBAAyB,IAAI;AAAA,GACrC,EACA,KAAK;AAAA,CAAI;AAAA;AAId,IAAM,mBAAmB;AAMzB,SAAS,WAAW,CAAC,MAAsB;AAAA,EACzC,OAAO,KAAK,QACV,kBACA,GAAG,qBAAqB,kBAC1B;AAAA;AAMF,SAAS,aAAa,CAAC,MAAsB;AAAA,EAG3C,MAAM,YAAY,KAAK,QACrB,wCACA,MACF;AAAA,EACA,OAAO,UAAU,QAAQ,IAAI,OAAO,kBAAkB,GAAG,GAAG,GAAG;AAAA;AAMjE,SAAS,oBAAoB,CAAC,MAAsB;AAAA,EAClD,OAAO,KAAK,QAAQ,cAAc,MAAM;AAAA;AAM1C,SAAS,iBAAiB,CAAC,MAAsB;AAAA,EAE/C,OAAO,KAAK,QAAQ,6BAA6B,YAAY;AAAA;AAM/D,SAAS,YAAY,CAAC,MAAsB;AAAA,EAC1C,OAAO,KAAK,QAAQ,4BAA4B,CAAC,GAAG,UAAU,QAAQ;AAAA,IACpE,MAAM,aAAa,IAAI,KAAK;AAAA,IAC5B,MAAM,cAAc,SAAS,KAAK;AAAA,IAElC,IACE,gBAAgB,cAChB,gBAAgB,WAAW,QAAQ,YAAY,EAAE,GACjD;AAAA,MACA,OAAO,IAAI,yBAAyB,UAAU;AAAA,IAChD;AAAA,IACA,OAAO,IAAI,yBAAyB,UAAU,KAAK,yBAAyB,WAAW;AAAA,GACxF;AAAA;AAOH,SAAS,eAAe,CAAC,MAAsB;AAAA,EAC7C,OAAO,KAAK,QACV,qBACA,GAAG,qBAAqB,kBAC1B;AAAA;AAMK,SAAS,qBAAqB,CAAC,UAA0B;AAAA,EAC9D,IAAI,CAAC,UAAU;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EAGA,IAAI,SAAS,kBAAkB,QAAQ;AAAA,EACvC,SAAS,aAAa,MAAM;AAAA,EAC5B,SAAS,gBAAgB,MAAM;AAAA,EAC/B,SAAS,YAAY,MAAM;AAAA,EAC3B,SAAS,cAAc,MAAM;AAAA,EAC7B,SAAS,qBAAqB,MAAM;AAAA,EACpC,SAAS,kBAAkB,MAAM;AAAA,EAEjC,OAAO;AAAA;AAWT,IAAM,oBAAoB;AAKnB,SAAS,cAAc,CAC5B,MACA,WAAmB,mBACT;AAAA,EACV,IAAI,CAAC,MAAM;AAAA,IACT,OAAO,CAAC;AAAA,EACV;AAAA,EAEA,IAAI,KAAK,UAAU,UAAU;AAAA,IAC3B,OAAO,CAAC,IAAI;AAAA,EACd;AAAA,EAEA,MAAM,SAAmB,CAAC;AAAA,EAC1B,IAAI,YAAY;AAAA,EAChB,IAAI,cAAc;AAAA,EAElB,OAAO,UAAU,SAAS,GAAG;AAAA,IAC3B,IAAI,UAAU,UAAU,UAAU;AAAA,MAChC,OAAO,KAAK,SAAS;AAAA,MACrB;AAAA,IACF;AAAA,IAGA,IAAI,aAAa;AAAA,IAGjB,MAAM,kBAAkB,UAAU,MAAM,GAAG,QAAQ,EAAE,MAAM,MAAM,KAAK,CAAC,GACpE;AAAA,IACH,cAAc,iBAAiB,MAAM;AAAA,IAGrC,MAAM,eAAe,UAAU,YAAY;AAAA,GAAM,QAAQ;AAAA,IACzD,IAAI,eAAe,WAAW,KAAK;AAAA,MACjC,aAAa,eAAe;AAAA,IAC9B,EAAO;AAAA,MAEL,MAAM,aAAa,UAAU,YAAY,KAAK,QAAQ;AAAA,MACtD,IAAI,aAAa,WAAW,KAAK;AAAA,QAC/B,aAAa,aAAa;AAAA,MAC5B;AAAA;AAAA,IAGF,IAAI,QAAQ,UAAU,MAAM,GAAG,UAAU;AAAA,IAGzC,IAAI,aAAa;AAAA,MACf,SAAS;AAAA,IACX;AAAA,IAEA,OAAO,KAAK,KAAK;AAAA,IAEjB,YAAY,UAAU,MAAM,UAAU;AAAA,IAGtC,IAAI,aAAa;AAAA,MACf,YAAY;AAAA,EAAW;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,OAAO;AAAA;AAMF,SAAS,2BAA2B,CACzC,UACA,OACU;AAAA,EACV,OAAO,eAAe,sBAAsB,QAAQ,GAAG,KAAK;AAAA;AAMvD,SAAS,sBAAsB,CAAC,QAAwB;AAAA,EAC7D,OAAO,KAAK;AAAA;AAMP,SAAS,yBAAyB,CAAC,WAA2B;AAAA,EACnE,OAAO,KAAK;AAAA;AAMP,SAAS,2BAA2B,CAAC,SAAyB;AAAA,EACnE,OAAO,aAAa;AAAA;AAMf,SAAS,yBAAyB,CACvC,MACQ;AAAA,EACR,OAAO,KAAK;AAAA;AAMP,SAAS,eAAe,CAAC,KAAa,MAAuB;AAAA,EAClE,MAAM,UAAU,yBAAyB,GAAG;AAAA,EAC5C,IAAI,QAAQ,SAAS,KAAK;AAAA,IACxB,OAAO,IAAI,WAAW,yBAAyB,IAAI;AAAA,EACrD;AAAA,EACA,OAAO,IAAI;AAAA;AAMN,SAAS,eAAe,CAC7B,WACA,SAAiB,iCACjB,cACQ;AAAA,EACR,MAAM,OAAO,KAAK,OACf,OAAO,cAAc,WAAW,YAAY,UAAU,QAAQ,KAAK,IACtE;AAAA,EACA,MAAM,WAAW,gBAAgB,IAAI,KAAK,OAAO,IAAI,EAAE,YAAY;AAAA,EACnE,OAAO,UAAU,QAAQ,UAAU;AAAA;AAM9B,SAAS,wBAAwB,CAAC,SAAgC;AAAA,EACvE,MAAM,QAAQ,QAAQ,MAAM,mCAAmC;AAAA,EAC/D,OAAO,QAAQ,MAAM,KAAK;AAAA;AAMrB,SAAS,2BAA2B,CAAC,SAAgC;AAAA,EAC1E,MAAM,QAAQ,QAAQ,MAAM,oCAAoC;AAAA,EAChE,OAAO,QAAQ,MAAM,KAAK;AAAA;AAMrB,SAAS,uBAAuB,CAAC,MAA6B;AAAA,EACnE,MAAM,QAAQ,KAAK,MAAM,qCAAqC;AAAA,EAC9D,OAAO,QAAQ,MAAM,KAAK;AAAA;AAMrB,SAAS,0BAA0B,CAAC,MAAyB;AAAA,EAClE,OAAO,KAAK,QAAQ,eAAe,KAAK,QAAQ,YAAY,KAAK;AAAA;AAM5D,SAAS,kBAAkB,CAAC,SAA+B;AAAA,EAChE,IAAI,QAAQ,MAAM;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EACA,IAAI,QAAQ,QAAQ;AAAA,IAClB,OAAO,aAAa,QAAQ;AAAA,EAC9B;AAAA,EACA,OAAO,IAAI,QAAQ;AAAA;AAMd,SAAS,oBAAoB,CAAC,SAA+B;AAAA,EAClE,IAAI,QAAQ,MAAM;AAAA,IAChB,OAAO;AAAA,EACT;AAAA,EACA,IAAI,QAAQ,QAAQ;AAAA,IAClB,OAAO;AAAA,EACT;AAAA,EACA,IAAI,QAAQ,aAAa,QAAQ,SAAS;AAAA,IACxC,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA;AAMF,SAAS,0BAA0B,CACxC,SACA,UACQ;AAAA,EACR,MAAM,cAAc,qBAAqB,OAAO;AAAA,EAChD,MAAM,cAAc,mBAAmB,OAAO;AAAA,EAC9C,IAAI,UAAU;AAAA,IACZ,OAAO,GAAG,cAAc,gBAAgB;AAAA,EAC1C;AAAA,EACA,OAAO,GAAG,gBAAgB;AAAA;AAMrB,SAAS,eAAe,CAAC,SAAgC;AAAA,EAC9D,OAAO,QAAQ;AAAA;AAMV,SAAS,SAAS,CAAC,SAAgC;AAAA,EACxD,OAAO,QAAQ;AAAA;AAMV,SAAS,gBAAgB,CAAC,SAAgC;AAAA,EAC/D,OAAO,QAAQ,aAAa,QAAQ;AAAA;AAM/B,SAAS,YAAY,CAC1B,MACA,WACA,WAAW,KACH;AAAA,EACR,IAAI,KAAK,UAAU,WAAW;AAAA,IAC5B,OAAO;AAAA,EACT;AAAA,EACA,OAAO,KAAK,MAAM,GAAG,YAAY,SAAS,MAAM,IAAI;AAAA;AAM/C,SAAS,oBAAoB,CAAC,MAAsB;AAAA,EACzD,OAAO,KACJ,QAAQ,mBAAmB,EAAE,EAC7B,QAAQ,gBAAgB,IAAI,EAC5B,QAAQ,cAAc,IAAI,EAC1B,QAAQ,cAAc,IAAI,EAC1B,QAAQ,cAAc,IAAI,EAC1B,QAAQ,kCAAkC,EAAE,EAC5C,QAAQ,mCAAmC,EAAE,EAC7C,QAAQ,uCAAuC,EAAE,EACjD,QAAQ,8CAA8C,EAAE,EACxD,QAAQ,uCAAuC,IAAI,EACnD,QAAQ,wBAAwB,IAAI,EACpC,QAAQ,UAAU,GAAG,EACrB,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,KAAK;AAAA;AAMH,SAAS,0BAA0B,CACxC,iBACA,WACA,WACQ;AAAA,EACR,MAAM,cAAc,IAAI,UAAU,QAAQ,KAAK,EAAE;AAAA,EACjD,OAAO,WAAW,sCAAsC,aAAa;AAAA;AAMhE,SAAS,0BAA0B,CACxC,MAC0E;AAAA,EAC1E,MAAM,QAAQ,KAAK,MACjB,sEACF;AAAA,EACA,IAAI,CAAC,OAAO;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,MAAM;AAAA,EAEjB,MAAM,YAAY,GAAG,GAAG,MAAM,GAAG,EAAE,KAAK,GAAG,MAAM,EAAE;AAAA,EAEnD,OAAO;AAAA,IACL,iBAAiB,MAAM;AAAA,IACvB,WAAW,MAAM;AAAA,IACjB;AAAA,EACF;AAAA;;;AD3UF,IAAM,2BAA2B,CAAC,UAAU,YAAY;AACxD,IAAM,+BAA+B;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,wBAAwB;AAE9B,SAAS,4BAA4B,CAAC,OAAuB;AAAA,EAC3D,OAAO,MACJ,KAAK,EACL,QAAQ,iCAAiC,IAAI,EAC7C,QAAQ,qBAAqB,IAAI,EACjC,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,EAAE,EAChB,YAAY;AAAA;AAGjB,SAAS,wBAAwB,CAC/B,OACA,IACA,QACQ;AAAA,EACR,IAAI,CAAC,OAAO;AAAA,IACV,OAAO;AAAA,EACT;AAAA,EACA,IAAI,GAAG,YAAY,MAAM,OAAO;AAAA,IAC9B,OAAO;AAAA,EACT;AAAA,EAEA,IAAI,YAAY;AAAA,EAChB,WAAW,SAAS,QAAQ;AAAA,IAC1B,MAAM,aAAa,OAAO,KAAK,EAAE,YAAY;AAAA,IAC7C,IAAI,CAAC,YAAY;AAAA,MACf;AAAA,IACF;AAAA,IACA,IAAI,eAAe,OAAO;AAAA,MACxB,YAAY,KAAK,IAAI,WAAW,IAAI;AAAA,IACtC,EAAO,SAAI,WAAW,WAAW,KAAK,GAAG;AAAA,MACvC,YAAY,KAAK,IAAI,WAAW,IAAI;AAAA,IACtC,EAAO,SAAI,WAAW,SAAS,KAAK,GAAG;AAAA,MACrC,YAAY,KAAK,IAAI,WAAW,GAAG;AAAA,IACrC;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,8BAA8B,CACrC,UACA,WACe;AAAA,EACf,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU;AAAA,IAC7C,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS;AAAA,EACf,MAAM,QACJ,OAAO,SAAS,OAAO,OAAO,UAAU,WACnC,OAAO,QACR;AAAA,EAEN,MAAM,oBACJ,OAAO,OAAO,cAAc,WACxB,OAAO,YACP,OAAO,OAAO,cAAc,WAC1B,MAAM,YACN;AAAA,EACR,IACE,aACA,qBACA,mBAAmB,iBAAiB,MAAM,mBAAmB,SAAS,GACtE;AAAA,IACA,OAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa;AAAA,IACjB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,EACT;AAAA,EAEA,WAAW,aAAa,YAAY;AAAA,IAClC,IACE,OAAO,cAAc,YACrB,sBAAsB,KAAK,SAAS,GACpC;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AA4BT,IAAM,oBAAoB,CAAC,YAAmD;AAAA,EAC5E,IAAI,oBAAoB,SAAS;AAAA,IAC/B,MAAM,qBAAqB;AAAA,IAG3B,OAAO,mBAAmB,kBAAkB;AAAA,EAC9C;AAAA,EACA,OAAO;AAAA;AAAA;AA+CF,MAAM,qBAAqB,QAAiC;AAAA,SAC1D,cAAsB;AAAA,EAC7B,wBACE;AAAA,EAEF,MAAkB;AAAA,EAClB,SAA2B;AAAA,EAC3B;AAAA,EACA,YAA2B;AAAA,EAC3B,SAAwB;AAAA,EAEhB;AAAA,EACA,WAA0B;AAAA,EAC1B,WAA0B;AAAA,EAC1B,gBAA+B;AAAA,EAC/B,mBAAmB;AAAA,EACnB,gBAAkD,IAAI;AAAA,EACtD,gBAA2D,IAAI;AAAA,EAC/D,oBAAiC,IAAI;AAAA,EACrC,oBAAiC,IAAI;AAAA,EACrC,YAAoC,IAAI;AAAA,EACxC,eAA0C,IAAI;AAAA,EAC9C,cAAc;AAAA,EAEtB,WAAW,CAAC,SAAwB;AAAA,IAClC,MAAM,OAAO;AAAA,IACb,KAAK,YAAY,QAAQ;AAAA,IACzB,KAAK,WAAW,KAAK,aAAa;AAAA,IAGlC,KAAK,oBAAoB,KAAK,uBAAuB;AAAA,IACrD,IAAI,KAAK,kBAAkB,OAAO,GAAG;AAAA,MACnC,KAAK,QAAQ,OAAO,MAClB;AAAA,QACE,KAAK;AAAA,QACL,SAAS,KAAK,QAAQ;AAAA,QACtB,mBAAmB,MAAM,KAAK,KAAK,iBAAiB;AAAA,MACtD,GACA,8BACF;AAAA,IACF;AAAA;AAAA,EAGM,YAAY,CAAC,SAA+C;AAAA,IAClE,MAAM,oBAAoB,KAAK,QAAQ,WACrC,kCACF;AAAA,IACA,MAAM,wBAAwB,KAAK,QAAQ,WACzC,uCACF;AAAA,IAEA,OAAO;AAAA,MACL,mBAAmB,SAAS,OAAO;AAAA,MACnC,yBACE,SAAS,OAAO,4BACf,sBAAsB,UAAU,sBAAsB;AAAA,MACzD,6BACE,SAAS,OAAO,gCACf,0BAA0B,UAAU,0BAA0B;AAAA,IACnE;AAAA;AAAA,EAGM,sBAAsB,CAAC,SAA6C;AAAA,IAC1E,MAAM,UAAU,IAAI;AAAA,IACpB,MAAM,gBAAgB,SAAS,OAAO;AAAA,IACtC,MAAM,gBACJ,iBAAiB,cAAc,SAAS,IACpC,cAAc,KAAK,GAAG,IACrB,KAAK,QAAQ,WAAW,mBAAmB;AAAA,IAElD,IAAI,CAAC,eAAe,KAAK,GAAG;AAAA,MAC1B,OAAO;AAAA,IACT;AAAA,IAEA,cACG,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,iBAAiB,CAAC,CAAC,EACjD,QAAQ,CAAC,OAAO;AAAA,MACf,QAAQ,IAAI,EAAE;AAAA,KACf;AAAA,IAEH,OAAO;AAAA;AAAA,cAGI,MAAK,CAAC,SAA+C;AAAA,IAChE,MAAM,UAAU,IAAI,aAAa,OAAO;AAAA,IAExC,MAAM,WAAW,yBAAyB,OAAO;AAAA,IACjD,QAAQ,mBAAmB,6BAA6B,OAAO;AAAA,IAE/D,IAAI,SAAS,WAAW,GAAG;AAAA,MACzB,QAAQ,OAAO,KACb,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,oEACF;AAAA,MACA,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,kBAAkB;AAAA,IACtB,IAAI;AAAA,IACJ,WAAW,WAAW,UAAU;AAAA,MAC9B,IAAI,CAAC,QAAQ,UAAU,KAAK,GAAG;AAAA,QAC7B,QAAQ,OAAO,KACb;AAAA,UACE,KAAK;AAAA,UACL,SAAS,QAAQ;AAAA,UACjB,WAAW,QAAQ;AAAA,QACrB,GACA,2EACF;AAAA,QACA;AAAA,MACF;AAAA,MAEA,IAAI;AAAA,QACF,MAAM,QAAQ,kBAAkB,OAAO;AAAA,QACvC;AAAA,QACA,OAAO,OAAO;AAAA,QACd,YAAY;AAAA,QACZ,QAAQ,OAAO,MACb;AAAA,UACE,KAAK;AAAA,UACL,SAAS,QAAQ;AAAA,UACjB,WAAW,QAAQ;AAAA,UACnB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,GACA,oCACF;AAAA;AAAA,IAEJ;AAAA,IAEA,IAAI,oBAAoB,GAAG;AAAA,MACzB,IAAI,WAAW;AAAA,QACb,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,OAAO,KACb,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,kDACF;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,cAGI,KAAI,CAAC,SAAuC;AAAA,IACvD,MAAM,UAAU,QAAQ,WAAW,kBAAkB;AAAA,IAGrD,IAAI,SAAS;AAAA,MACX,MAAM,QAAQ,SAAS;AAAA,IACzB;AAAA;AAAA,SAGK,oBAAoB,CACzB,SACA,iBACM;AAAA,IACN,IAAI,CAAC,iBAAiB;AAAA,MACpB;AAAA,IACF;AAAA,IAEA,MAAM,oBAAoB,CAAC,cAAuB;AAAA,MAChD,MAAM,sBAAsB,YACxB,mBAAmB,SAAS,IAC5B;AAAA,MACJ,MAAM,QAAQ,sBACV,gBAAgB,gBAAgB,mBAAmB,IACnD,gBAAgB,uBAAuB;AAAA,MAC3C,MAAM,cAAc,OAClB,gBACA,QACA,YACkB;AAAA,QAClB,MAAM,gBAAgB,kBACpB,gBACA,uBAAuB,CAAE,OAAmC,YACvD,KAAK,QAAQ,WAAW,oBAAoB,IAC7C,QACJ,OACF;AAAA;AAAA,MAGF,MAAM,qBAAqB,CACzB,YAEA,uBACA,CAAE,QAA0C,YACvC;AAAA,WACI;AAAA,QACH,WAAW;AAAA,QACX,SAAU,QAA0C,WAAW;AAAA,UAC7D,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,OAAO,OAAO,QAAQ,QAAQ;AAAA,QAChC;AAAA,MACF,IACA;AAAA,MAEN,MAAM,eAAqD;AAAA,QACzD,QAAQ;AAAA,WACJ,sBAAsB,EAAE,WAAW,oBAAoB,IAAI,CAAC;AAAA,WAC5D,sBACA;AAAA,UACE,SAAS;AAAA,YACP,QAAQ;AAAA,YACR,WAAW;AAAA,YACX,OAAO,OAAO,QAAQ,QAAQ;AAAA,YAC9B,YAAY;AAAA,YACZ,UAAU;AAAA,cACR,QAAQ,OAAO;AAAA,YACjB;AAAA,UACF;AAAA,QACF,IACA,CAAC;AAAA,QACL,OAAO,OAAO,QAAQ,OAAO,UAAU,MAAM,QAAQ,UAAU;AAAA,QAC/D,aACE;AAAA,QACF,cAAc,CAAC,GAAG,4BAA4B;AAAA,QAC9C,sBAAsB,CAAC,WAAW,UAAU,MAAM;AAAA,QAClD,UAAU,CAAC,GAAG,wBAAwB;AAAA,QACtC,UAAU;AAAA,UACR,SAAS;AAAA,UACT,kBAAkB;AAAA,aACd,sBAAsB,EAAE,WAAW,oBAAoB,IAAI,CAAC;AAAA,QAClE;AAAA,QACA,gBAAgB,CAAC,OAAO,YACtB,gBAAgB,wBACd,OACA,mBAAmB,OAAO,CAC5B;AAAA,QACF,mBAAmB,CAAC,YAClB,gBAAgB,2BACd,mBAAmB,OAAO,CAC5B;AAAA,QACF,WAAW,CAAC,YACV,gBAAgB,mBAAmB,mBAAmB,OAAO,CAAC;AAAA,QAChE,aAAa,CAAC,YACZ,gBAAgB,qBAAqB,mBAAmB,OAAO,CAAC;AAAA,QAClE,eAAe,CAAC,SAAS,WACvB,gBAAgB,uBAAuB,mBAAmB,OAAO,GAAG;AAAA,aAC/D;AAAA,aACC,uBAAuB,CAAC,OAAO,YAC/B,EAAE,WAAW,oBAAoB,IACjC,CAAC;AAAA,QACP,CAAC;AAAA,QACH,gBAAgB,CAAC,SAAS,WACxB,gBAAgB,wBAAwB,mBAAmB,OAAO,GAAG;AAAA,aAChE;AAAA,aACC,uBAAuB,CAAC,OAAO,YAC/B,EAAE,WAAW,oBAAoB,IACjC,CAAC;AAAA,QACP,CAAC;AAAA,QACH,cAAc,CAAC,gBAAgB,WAC7B,gBAAgB,sBAAsB,gBAAgB;AAAA,aACjD;AAAA,aACC,uBAAuB,CAAC,OAAO,YAC/B,EAAE,WAAW,oBAAoB,IACjC,CAAC;AAAA,QACP,CAAC;AAAA,QACH,aAAa,CAAC,gBAAgB,WAC5B,gBAAgB,qBAAqB,gBAAgB;AAAA,aAChD;AAAA,aACC,uBAAuB,CAAC,OAAO,YAC/B,EAAE,WAAW,oBAAoB,IACjC,CAAC;AAAA,QACP,CAAC;AAAA,QACH,eAAe,CAAC,gBAAgB,WAC9B,gBAAgB,uBAAuB,gBAAgB;AAAA,aAClD;AAAA,aACC,uBAAuB,CAAC,OAAO,YAC/B,EAAE,WAAW,oBAAoB,IACjC,CAAC;AAAA,QACP,CAAC;AAAA,QACH,YAAY,CAAC,gBAAgB,WAC3B,gBAAgB,oBAAoB,gBAAgB;AAAA,aAC/C;AAAA,aACC,uBAAuB,CAAC,OAAO,YAC/B,EAAE,WAAW,oBAAoB,IACjC,CAAC;AAAA,QACP,CAAC;AAAA,QACH,SAAS,CAAC,gBAAgB,WACxB,gBAAgB,iBAAiB,gBAAgB;AAAA,aAC5C;AAAA,aACC,uBAAuB,CAAC,OAAO,SAC/B;AAAA,YACE,QAAQ;AAAA,cACN,QAAQ;AAAA,cACR,WAAW;AAAA,YACb;AAAA,UACF,IACA,CAAC;AAAA,QACP,CAAC;AAAA,QACH,gBAAgB,CAAC,QAAQ,YACvB,gBAAgB,wBACd,uBACE,CAAE,OAAmC,YAClC,KAAK,QAAQ,WAAW,oBAAoB,IAC7C,QACJ,mBAAmB,OAAO,CAC5B;AAAA,QACF,gBAAgB,CAAC,UAAU,YACzB,gBAAgB,wBACd,UACA,mBAAmB,OAAO,CAC5B;AAAA,QACF;AAAA,MACF;AAAA,MAEA,QAAQ,yBAAyB,YAAY;AAAA;AAAA,IAG/C,IAAI,OAAO,QAAQ,6BAA6B,YAAY;AAAA,MAC1D,kBAAkB;AAAA,MAClB,WAAW,aAAa,gBAAgB,wBAAwB,GAAG;AAAA,QACjE,kBAAkB,SAAS;AAAA,MAC7B;AAAA,MACA,QAAQ,OAAO,KACb,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,oCACF;AAAA,MACA;AAAA,IACF;AAAA,IAEA,QAAQ,oBACN,SACA,gBAAgB,kBAAkB,KAAK,eAAe,CACxD;AAAA,IACA,QAAQ,OAAO,KACb,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,+BACF;AAAA;AAAA,OAGI,KAAI,GAAkB;AAAA,IAC1B,MAAM,KAAK,SAAS;AAAA;AAAA,EAGd,yBAAyB,GAAS;AAAA,IACxC,MAAM,QAAQ,KAAK,uBAAuB;AAAA,IAC1C,KAAK,MAAM,OAAO,OAAO;AAAA,IACzB,KAAK,SAAS,OAAO,UAAU;AAAA,IAC/B,KAAK,YAAY,OAAO,aAAa;AAAA,IACrC,KAAK,SAAS,OAAO,UAAU;AAAA,IAC/B,KAAK,WAAW,OAAO,QAAQ,YAAY;AAAA,IAC3C,KAAK,WAAW,OAAO,QAAQ,YAAY;AAAA,IAC3C,KAAK,gBAAgB,OAAO,QAAQ,iBAAiB;AAAA,IACrD,KAAK,cAAc,MAAM,KAAK,KAAK,eAAe,SAAS,KAAK,CAAC,CAAC,EAAE,KAClE,CAAC,iBAAiB,aAAa,WACjC;AAAA;AAAA,OAGY,kBAAiB,CAC7B,SAC8B;AAAA,IAC9B,MAAM,YAAY,mBAAmB,QAAQ,SAAS;AAAA,IACtD,MAAM,SAAS,KAAK,cAAc,IAAI,SAAS;AAAA,IAC/C,IAAI,QAAQ;AAAA,MACV,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,WAAW,KAAK,cAAc,IAAI,SAAS;AAAA,IACjD,IAAI,UAAU;AAAA,MACZ,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,gBAAgB,YAAY;AAAA,MAChC,IAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,UAAU;AAAA,QAC1C,MAAM,IAAI,MACR,iBAAiB,uCACnB;AAAA,MACF;AAAA,MAEA,KAAK,QAAQ,OAAO,KAClB,EAAE,KAAK,gBAAgB,SAAS,KAAK,QAAQ,SAAS,UAAU,GAChE,6CACF;AAAA,MAEA,MAAM,MAAM,IAAI,IAAI;AAAA,QAClB,OAAO,QAAQ;AAAA,QACf,UAAU,QAAQ;AAAA,QAClB,YAAY;AAAA,QACZ,UAAU,SAAS;AAAA,WACf,QAAQ,gBACR,EAAE,eAAe,QAAQ,cAAc,IACvC,CAAC;AAAA,MACP,CAAC;AAAA,MAED,MAAM,QAA6B;AAAA,QACjC;AAAA,QACA;AAAA,QACA;AAAA,QACA,QAAQ,IAAI;AAAA,QACZ,WAAW;AAAA,QACX,QAAQ;AAAA,QACR,UAAU,KAAK,aAAa,OAAO;AAAA,QACnC,mBAAmB,KAAK,uBAAuB,OAAO;AAAA,QACtD,mBAAmB,IAAI;AAAA,QACvB,WAAW,IAAI;AAAA,QACf,cAAc,IAAI;AAAA,QAClB,aAAa;AAAA,MACf;AAAA,MAEA,MAAM,aAAa,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA,MAChD,MAAM,YAAY,WAAW;AAAA,MAC7B,MAAM,SAAS,WAAW;AAAA,MAE1B,KAAK,cAAc,IAAI,WAAW,KAAK;AAAA,MACvC,KAAK,0BAA0B;AAAA,MAE/B,KAAK,QAAQ,OAAO,KAClB;AAAA,QACE,KAAK;AAAA,QACL,SAAS,KAAK,QAAQ;AAAA,QACtB;AAAA,QACA,WAAW,MAAM;AAAA,QACjB,QAAQ,MAAM;AAAA,MAChB,GACA,yBACF;AAAA,MAEA,KAAK,sBAAsB,KAAK;AAAA,MAEhC,IAAI;AAAA,QACF,MAAM,IAAI,MAAM;AAAA,QAChB,OAAO,OAAO;AAAA,QACd,KAAK,cAAc,OAAO,SAAS;AAAA,QACnC,KAAK,0BAA0B;AAAA,QAC/B,MAAM;AAAA;AAAA,MAER,MAAM,cAAc;AAAA,MACpB,KAAK,0BAA0B;AAAA,MAE/B,KAAK,QAAQ,OAAO,KAClB,EAAE,KAAK,gBAAgB,SAAS,KAAK,QAAQ,SAAS,UAAU,GAChE,oCACF;AAAA,MAEA,MAAM,KAAK,sBAAsB,SAAS;AAAA,MAC1C,OAAO;AAAA,OACN;AAAA,IAEH,KAAK,cAAc,IAAI,WAAW,YAAY;AAAA,IAC9C,IAAI;AAAA,MACF,OAAO,MAAM;AAAA,cACb;AAAA,MACA,KAAK,cAAc,OAAO,SAAS;AAAA;AAAA;AAAA,OAIzB,SAAQ,GAAkB;AAAA,IACtC,MAAM,SACJ,KAAK,yBAAyB,MAC1B,MAAM,KAAK,KAAK,cAAc,OAAO,CAAC,IACtC,CAAC;AAAA,IACP,IAAI,OAAO,SAAS,GAAG;AAAA,MACrB,WAAW,SAAS,QAAQ;AAAA,QAC1B,MAAM,MAAM,IAAI,KAAK;AAAA,QACrB,MAAM,cAAc;AAAA,QACpB,KAAK,QAAQ,OAAO,KAClB;AAAA,UACE,KAAK;AAAA,UACL,SAAS,KAAK,QAAQ;AAAA,UACtB,WAAW,MAAM;AAAA,QACnB,GACA,uBACF;AAAA,MACF;AAAA,MACA,KAAK,cAAc,MAAM;AAAA,MACzB,KAAK,0BAA0B;AAAA,MAC/B;AAAA,IACF;AAAA,IAEA,IAAI,KAAK,KAAK;AAAA,MACZ,MAAM,KAAK,IAAI,KAAK;AAAA,MACpB,KAAK,MAAM;AAAA,MACX,KAAK,SAAS;AAAA,MACd,KAAK,cAAc;AAAA,MAEnB,KAAK,QAAQ,OAAO,KAClB,EAAE,KAAK,gBAAgB,SAAS,KAAK,QAAQ,QAAQ,GACrD,uBACF;AAAA,IACF;AAAA;AAAA,EAGM,qBAAqB,CAAC,OAAmC;AAAA,IAC/D,MAAM,MAAM,OAAO,OAAO,KAAK;AAAA,IAC/B,MAAM,YAAY,OAAO,aAAa,KAAK;AAAA,IAC3C,IAAI,CAAC;AAAA,MAAK;AAAA,IAGV,IAAI,QAAQ,SAAS,SAAS,aAAa;AAAA,MACzC,MAAM,KAAK,cACT,SACA,QACA,SACF;AAAA,KACD;AAAA,IAGD,IAAI,MAAM,eAAe,SAAS,OAAO,aAAa;AAAA,MACpD,MAAM,KAAK,iBACT,OACA,QACA,SACF;AAAA,KACD;AAAA,IAGD,IAAI,MAAM,kBAAkB,SAAS,YAAY;AAAA,MAC/C,MAAM,KAAK,oBAAoB,OAAO,SAAS;AAAA,KAChD;AAAA,IAED,IAAI,MAAM,oBAAoB,SAAS,YAAY;AAAA,MACjD,MAAM,KAAK,sBAAsB,OAAO,SAAS;AAAA,KAClD;AAAA,IAGD,IAAI,MAAM,yBAAyB,SAAS,YAAY;AAAA,MACtD,MAAM,KAAK,0BAA0B,OAAO,SAAS;AAAA,KACtD;AAAA,IAED,IAAI,MAAM,uBAAuB,SAAS,YAAY;AAAA,MACpD,MAAM,KAAK,wBAAwB,OAAO,SAAS;AAAA,KACpD;AAAA,IAGD,IAAI,MAAM,eAAe,SAAS,YAAY;AAAA,MAC5C,MAAM,KAAK,iBAAiB,OAAO,SAAS;AAAA,KAC7C;AAAA;AAAA,EAGK,sBAAsB,GAA+B;AAAA,IAC3D,MAAM,SAAS,KAAK;AAAA,IACpB,IAAI,EAAE,kBAAkB,QAAQ,OAAO,SAAS,GAAG;AAAA,MACjD,OAAO;AAAA,IACT;AAAA,IACA,MAAM,YAAY,mBAChB,KAAK,oBAAoB,kBAC3B;AAAA,IACA,OAAO,OAAO,IAAI,SAAS,KAAK,OAAO,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA;AAAA,EAG1D,eAAe,CACrB,WAC4B;AAAA,IAC5B,MAAM,SAAS,KAAK;AAAA,IACpB,IAAI,EAAE,kBAAkB,QAAQ,OAAO,SAAS,GAAG;AAAA,MACjD,OAAO;AAAA,IACT;AAAA,IACA,IAAI,WAAW;AAAA,MACb,OAAO,OAAO,IAAI,mBAAmB,SAAS,CAAC,KAAK;AAAA,IACtD;AAAA,IACA,OAAO,KAAK,uBAAuB;AAAA;AAAA,EAG7B,mBAAmB,CAAC,WAA6C;AAAA,IACvE,MAAM,QAAQ,KAAK,gBAAgB,SAAS;AAAA,IAC5C,IAAI,OAAO,QAAQ;AAAA,MACjB,OAAO,MAAM;AAAA,IACf;AAAA,IACA,MAAM,YAAY,YAAY,mBAAmB,SAAS,IAAI;AAAA,IAC9D,MAAM,YAAY,mBAChB,KAAK,oBAAoB,kBAC3B;AAAA,IACA,IAAI,CAAC,aAAa,cAAc,WAAW;AAAA,MACzC,OAAO,KAAK;AAAA,IACd;AAAA,IACA,OAAO;AAAA;AAAA,EAGD,qBAAqB,CAAC,WAA0C;AAAA,IACtE,OAAO,KAAK,gBAAgB,SAAS,GAAG,YAAY,KAAK;AAAA;AAAA,EAGnD,8BAA8B,CACpC,WACa;AAAA,IACb,OACE,KAAK,gBAAgB,SAAS,GAAG,qBACjC,KAAK;AAAA;AAAA,EAID,8BAA8B,CACpC,WACa;AAAA,IACb,OACE,KAAK,gBAAgB,SAAS,GAAG,qBACjC,KAAK;AAAA;AAAA,EAID,sBAAsB,CAC5B,WACwB;AAAA,IACxB,OAAO,KAAK,gBAAgB,SAAS,GAAG,aAAa,KAAK;AAAA;AAAA,EAGpD,yBAAyB,CAC/B,WAC2B;AAAA,IAC3B,OAAO,KAAK,gBAAgB,SAAS,GAAG,gBAAgB,KAAK;AAAA;AAAA,EAGvD,sBAAsB,CAAC,WAA0C;AAAA,IACvE,OAAO,KAAK,gBAAgB,SAAS,GAAG,aAAa,KAAK;AAAA;AAAA,EAGpD,mBAAmB,CAAC,WAA0C;AAAA,IACpE,OAAO,KAAK,gBAAgB,SAAS,GAAG,UAAU,KAAK;AAAA;AAAA,EAGjD,uBAAuB,GAAa;AAAA,IAC1C,MAAM,SAAS,KAAK;AAAA,IACpB,IAAI,kBAAkB,OAAO,OAAO,OAAO,GAAG;AAAA,MAC5C,OAAO,MAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IACjC;AAAA,IACA,OAAO,CAAC,mBAAmB,KAAK,oBAAoB,kBAAkB,CAAC;AAAA;AAAA,EAGjE,2BAA2B,CACjC,SACA,QACoB;AAAA,IACpB,MAAM,eAAe;AAAA,IACrB,MAAM,gBAAgB;AAAA,IAItB,OACE,cAAc,aACb,eAAe,QACZ,aACJ,eAAe,aACf,eAAe,SAAS,aACxB;AAAA;AAAA,OAIU,0BAAyB,CACrC,SACA,QACA,UACiB;AAAA,IACjB,MAAM,SACH,QAAuD,aACxD,UAAU,aACV;AAAA,IACF,IAAI,QAAQ;AAAA,MACV,OAAO,mBAAmB,MAAM;AAAA,IAClC;AAAA,IAEA,MAAM,SAAS,QAAQ,UAAU,UAAU;AAAA,IAC3C,IAAI,UAAU,OAAO,QAAQ,YAAY,YAAY;AAAA,MACnD,MAAM,OAAO,MAAM,QAAQ,QAAQ,MAAM;AAAA,MACzC,MAAM,WAAW,MAAM;AAAA,MACvB,IACE,OAAO,UAAU,cAAc,YAC/B,SAAS,UAAU,KAAK,GACxB;AAAA,QACA,OAAO,mBAAmB,SAAS,SAAS;AAAA,MAC9C;AAAA,MACA,MAAM,QACJ,UAAU,SAAS,OAAO,SAAS,UAAU,WACxC,SAAS,QACV;AAAA,MACN,IAAI,OAAO,OAAO,cAAc,YAAY,MAAM,UAAU,KAAK,GAAG;AAAA,QAClE,OAAO,mBAAmB,MAAM,SAAS;AAAA,MAC3C;AAAA,IACF;AAAA,IAEA,OAAO,mBAAmB,KAAK,oBAAoB,kBAAkB;AAAA;AAAA,EAG/D,sBAAsB,CAC5B,SACA,QACU;AAAA,IACV,MAAM,WAAW,KAAK,4BAA4B,SAAS,MAAM;AAAA,IACjE,IAAI,UAAU;AAAA,MACZ,OAAO,CAAC,mBAAmB,QAAQ,CAAC;AAAA,IACtC;AAAA,IACA,OAAO,KAAK,wBAAwB;AAAA;AAAA,EAG9B,cAAc,CACpB,QACA,KACA,WACQ;AAAA,IACR,MAAM,aAAa,mBACjB,aAAa,KAAK,oBAAoB,kBACxC;AAAA,IACA,OAAO,eAAe,qBAClB,GAAG,UAAU,QACb,GAAG,UAAU,cAAc;AAAA;AAAA,EAGzB,iBAAiB,CAAC,WAAyC;AAAA,IACjE,MAAM,aAAa,mBACjB,aAAa,KAAK,oBAAoB,kBACxC;AAAA,IACA,OAAO;AAAA,MACL,SAAS,KAAK;AAAA,MACd,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,UAAU,EAAE,WAAW,WAAW;AAAA,IACpC;AAAA;AAAA,OAGY,cAAa,CACzB,SACA,SACA,YAAY,KAAK,kBACF;AAAA,IACf,MAAM,WAAW,KAAK,sBAAsB,SAAS;AAAA,IACrD,MAAM,YAAY,KAAK,uBAAuB,SAAS;AAAA,IAGvD,IAAI,SAAS,2BAA2B,QAAQ,QAAQ;AAAA,MACtD;AAAA,IACF;AAAA,IAGA,IAAI,QAAQ,SAAS,WAAW;AAAA,MAC9B;AAAA,IACF;AAAA,IAGA,IAAI,CAAC,KAAK,iBAAiB,QAAQ,SAAS,SAAS,GAAG;AAAA,MACtD,KAAK,QAAQ,OAAO,MAClB;AAAA,QACE,KAAK;AAAA,QACL,SAAS,KAAK,QAAQ;AAAA,QACtB;AAAA,QACA,WAAW,QAAQ;AAAA,MACrB,GACA,mDACF;AAAA,MACA;AAAA,IACF;AAAA,IAGA,MAAM,cAAc,QAAQ,MAAM,SAAS,KAAK,YAAY;AAAA,IAE5D,IAAI,eAAe,QAAQ,iBAAiB,MAAM;AAAA,MAChD;AAAA,IACF;AAAA,IACA,IAAI,SAAS,+BAA+B,CAAC,aAAa;AAAA,MACxD;AAAA,IACF;AAAA,IAEA,MAAM,iBAAiB,QACrB,QAAQ,aAAa,QAAQ,cAAc,QAAQ,EACrD;AAAA,IAGA,MAAM,SAAS,MAAM,KAAK,uBAAuB,SAAS,SAAS;AAAA,IACnE,IAAI,CAAC;AAAA,MAAQ;AAAA,IAGb,MAAM,OAAO,MAAM,KAAK,iBACtB,QAAQ,SACR,QAAQ,WACR,SACF;AAAA,IAEA,MAAM,iBAAiB,MAAM,KAAK,QAAQ,cAAc,OAAO,QAAQ;AAAA,IACvE,IAAI,CAAC,gBAAgB;AAAA,MACnB,MAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ,MAAM,SAAS;AAAA,MACvD,MAAM,cAAc,OAAO,wBAAwB,IAAI,IAAI,QAAQ;AAAA,MACnE,MAAM,KAAK,QAAQ,aAAa;AAAA,QAC9B,IAAI,OAAO;AAAA,QACX,OAAO,CAAC,WAAW;AAAA,QACnB,UAAU;AAAA,UACR,QAAQ;AAAA,UACR;AAAA,UACA,OAAO;AAAA,YACL;AAAA,YACA,IAAI,QAAQ;AAAA,YACZ,MAAM;AAAA,YACN,UAAU,MAAM,QAAQ,QAAQ;AAAA,UAClC;AAAA,QACF;AAAA,QACA,SAAS,KAAK,QAAQ;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,IAGA,MAAM,KAAK,QAAQ,aAAa,QAAQ,UAAU;AAAA,IAGlD,MAAM,KAAK,QAAQ,2DAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA,IAGA,MAAM,KAAK,oBACT,QACA,MACA,QAAQ,SACR,QAAQ,aAAa,QAAQ,IAC7B,SACF;AAAA;AAAA,OAGY,iBAAgB,CAC5B,OACA,SACA,YAAY,KAAK,kBACF;AAAA,IAEf,IAAI,CAAC,MAAM;AAAA,MAAM;AAAA,IAGjB,MAAM,SAAS,MAAM,KAAK,uBACxB;AAAA,MACE,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,IAAI,MAAM;AAAA,MACV,WAAW,MAAM;AAAA,IACnB,GACA,SACF;AAAA,IACA,IAAI,CAAC;AAAA,MAAQ;AAAA,IAGb,MAAM,OAAO,MAAM,KAAK,iBACtB,MAAM,SACN,MAAM,WACN,SACF;AAAA,IAEA,MAAM,iBAAiB,MAAM,KAAK,QAAQ,cAAc,OAAO,QAAQ;AAAA,IACvE,IAAI,CAAC,gBAAgB;AAAA,MACnB,MAAM,OAAO,MAAM,KAAK,QAAQ,MAAM,MAAM,SAAS;AAAA,MACrD,MAAM,cAAc,OAAO,wBAAwB,IAAI,IAAI,MAAM;AAAA,MACjE,MAAM,KAAK,QAAQ,aAAa;AAAA,QAC9B,IAAI,OAAO;AAAA,QACX,OAAO,CAAC,WAAW;AAAA,QACnB,UAAU;AAAA,UACR,QAAQ;AAAA,UACR;AAAA,UACA,OAAO;AAAA,YACL;AAAA,YACA,IAAI,MAAM;AAAA,YACV,MAAM;AAAA,YACN,UAAU,MAAM,QAAQ,MAAM;AAAA,UAChC;AAAA,QACF;AAAA,QACA,SAAS,KAAK,QAAQ;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,IAGA,MAAM,KAAK,QAAQ,aAAa,QAAQ,UAAU;AAAA,IAGlD,MAAM,KAAK,QAAQ,iDAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA,IAGA,MAAM,KAAK,oBACT,QACA,MACA,MAAM,SACN,MAAM,aAAa,MAAM,IACzB,SACF;AAAA;AAAA,OAGY,oBAAmB,CAC/B,QAMA,YAAY,KAAK,kBACF;AAAA,IACf,MAAM,KAAK,QAAQ,uDAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA;AAAA,OAGY,sBAAqB,CACjC,QAMA,YAAY,KAAK,kBACF;AAAA,IACf,MAAM,KAAK,QAAQ,2DAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA;AAAA,OAGY,0BAAyB,CACrC,OAKA,YAAY,KAAK,kBACF;AAAA,IAEf,IAAI,MAAM,SAAS,KAAK,uBAAuB,SAAS,GAAG;AAAA,MACzD,KAAK,+BAA+B,SAAS,EAAE,IAAI,MAAM,OAAO;AAAA,MAChE,MAAM,KAAK,iBAAiB,MAAM,SAAS,WAAW,SAAS;AAAA,IACjE;AAAA,IAEA,MAAM,KAAK,QAAQ,qEAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA;AAAA,OAGY,wBAAuB,CACnC,OAKA,YAAY,KAAK,kBACF;AAAA,IAEf,IAAI,MAAM,SAAS,KAAK,uBAAuB,SAAS,GAAG;AAAA,MACzD,KAAK,+BAA+B,SAAS,EAAE,OAAO,MAAM,OAAO;AAAA,IACrE;AAAA,IAEA,MAAM,KAAK,QAAQ,iEAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA;AAAA,OAGY,iBAAgB,CAC5B,QAKA,YAAY,KAAK,kBACF;AAAA,IACf,MAAM,KAAK,QAAQ,iDAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA;AAAA,EAGM,gBAAgB,CACtB,WACA,WACS;AAAA,IACT,MAAM,oBAAoB,KAAK,+BAA+B,SAAS;AAAA,IACvE,MAAM,oBAAoB,KAAK,+BAA+B,SAAS;AAAA,IAGvE,IAAI,kBAAkB,SAAS,KAAK,kBAAkB,SAAS,GAAG;AAAA,MAChE,OAAO;AAAA,IACT;AAAA,IAGA,OAAO,kBAAkB,IAAI,SAAS,KAAK,kBAAkB,IAAI,SAAS;AAAA;AAAA,OAG9D,oBAAmB,CAC/B,QACA,MACA,WACA,UACA,YAAY,KAAK,kBACF;AAAA,IACf,MAAM,WAA4B,OAChC,aACsB;AAAA,MACtB,MAAM,eAAe,SAAS,QAAQ;AAAA,MACtC,IAAI,CAAC,aAAa,KAAK,GAAG;AAAA,QACxB,KAAK,QAAQ,OAAO,KAClB,EAAE,KAAK,gBAAgB,WAAW,QAAQ,KAAK,GAAG,GAClD,iDACF;AAAA,QACA,OAAO,CAAC;AAAA,MACV;AAAA,MAEA,MAAM,KAAK,YACT,WACA,cACA;AAAA,QACE;AAAA,QACA,gBAAgB;AAAA,QAChB,aAAa;AAAA,QACb,aAAa;AAAA,QACb,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,QAAQ;AAAA,MACV,GACA,SACF;AAAA,MAGA,MAAM,iBAAyB;AAAA,QAC7B,IAAI,iBAAiB,KAAK,SAAS,kBAAkB,KAAK,IAAI,GAAG;AAAA,QACjE,SAAS,KAAK,QAAQ;AAAA,QACtB,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK,QAAQ;AAAA,QACvB,SAAS;AAAA,UACP,MAAM,SAAS,QAAQ;AAAA,UACvB,QAAQ;AAAA,UACR,WAAW,OAAO;AAAA,UAClB,UAAU,EAAE,UAAU;AAAA,QACxB;AAAA,QACA,UAAU;AAAA,UACR,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,UAAU;AAAA,UACV;AAAA,UACA,SAAS;AAAA,UACT,QAAQ,KAAK,QAAQ;AAAA,UACrB,UAAU,KAAK,QAAQ;AAAA,UACvB,OAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,QACA,WAAW,KAAK,IAAI;AAAA,MACtB;AAAA,MAEA,MAAM,KAAK,QAAQ,aAAa,gBAAgB,UAAU;AAAA,MAE1D,MAAM,KAAK,QAAQ,mDAEjB,KAAK,kBAAkB,SAAS,CAClC;AAAA,MAEA,OAAO,CAAC,cAAc;AAAA;AAAA,IAGxB,MAAM,iBAAiB,kBAAkB,KAAK,OAAO;AAAA,IACrD,IAAI,gBAAgB;AAAA,MAClB,MAAM,eAAe,cAAc,KAAK,SAAS,QAAQ,QAAQ;AAAA,IACnE;AAAA;AAAA,OAGY,uBAAsB,CAClC,SACA,YAAY,KAAK,kBACO;AAAA,IACxB,IAAI,CAAC,QAAQ;AAAA,MAAM,OAAO;AAAA,IAE1B,MAAM,SAAS,MAAM,KAAK,UACxB,QAAQ,SACR,QAAQ,WACR,SACF;AAAA,IACA,MAAM,WAAW,KAAK,YAAY,QAAQ,MAAM,SAAS;AAAA,IAGzD,MAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ,MAAM,SAAS;AAAA,IACvD,MAAM,cAAc,OAAO,wBAAwB,IAAI,IAAI,QAAQ;AAAA,IAGnE,MAAM,QAAiB,CAAC;AAAA,IACxB,IAAI,WAAW,WAAW,QAAQ,OAAO;AAAA,MACvC,WAAW,QAAQ,QAAQ,OAAO;AAAA,QAChC,MAAM,KAAK;AAAA,UACT,IAAI,KAAK;AAAA,UACT,KAAK,KAAK;AAAA,UACV,OAAO,KAAK,SAAS,KAAK;AAAA,UAC1B,QAAQ;AAAA,UACR,aAAa,KAAK;AAAA,QACpB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,IAEA,MAAM,SAAiB;AAAA,MACrB,IAAI,iBACF,KAAK,SACL,KAAK,eAAe,SAAS,QAAQ,IAAI,SAAS,CACpD;AAAA,MACA,SAAS,KAAK,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP,MAAM,QAAQ,QAAQ;AAAA,QACtB,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU,EAAE,UAAU;AAAA,WAClB,MAAM,SAAS,IAAI,EAAE,aAAa,MAAM,IAAI,CAAC;AAAA,MACnD;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,WAAW,KAAK,oBAAoB,QAAQ,EAAE;AAAA,QAC9C,YAAY;AAAA,QACZ,gBAAgB,MAAM,QAAQ,QAAQ;AAAA,QACtC,SAAS;AAAA,QACT,QAAQ,QAAQ;AAAA,QAChB,UAAU;AAAA,QACV,UAAU,QAAQ;AAAA,QAClB,eAAe,QAAQ;AAAA,QACvB,QAAQ;AAAA,UACN,IAAI,QAAQ;AAAA,UACZ,MAAM;AAAA,UACN,UAAU,MAAM,QAAQ,QAAQ;AAAA,QAClC;AAAA,QACA,OAAO;AAAA,UACL;AAAA,UACA,QAAQ,KAAK,oBAAoB,SAAS,KAAK;AAAA,UAC/C,WAAW,QAAQ;AAAA,UACnB,QAAQ,QAAQ;AAAA,UAChB,WAAW,QAAQ;AAAA,UACnB,UAAU,QAAQ;AAAA,QACpB;AAAA,QACA,gBAAgB,QAAQ;AAAA,QACxB,gBAAgB,QAAQ;AAAA,QACxB,eAAe,QAAQ;AAAA,MACzB;AAAA,MACA,WAAW,KAAK,oBAAoB,QAAQ,EAAE;AAAA,IAChD;AAAA,IAEA,OAAO;AAAA;AAAA,OAGK,uBAAsB,CAClC,OAOA,YAAY,KAAK,kBACO;AAAA,IACxB,MAAM,SAAS,MAAM,KAAK,UACxB,MAAM,SACN,MAAM,WACN,SACF;AAAA,IACA,MAAM,WAAW,KAAK,YAAY,MAAM,MAAM,SAAS;AAAA,IAEvD,MAAM,OAAO,MAAM,KAAK,QAAQ,MAAM,MAAM,SAAS;AAAA,IACrD,MAAM,cAAc,OAAO,wBAAwB,IAAI,IAAI,MAAM;AAAA,IAGjE,MAAM,YAAY,MAAM,KACrB,QAAQ,KAAK,KAAK,uBAAuB,SAAS,MAAM,EAAE,EAC1D,KAAK;AAAA,IAER,MAAM,SAAiB;AAAA,MACrB,IAAI,iBACF,KAAK,SACL,KAAK,eAAe,iBAAiB,MAAM,IAAI,SAAS,CAC1D;AAAA,MACA,SAAS,KAAK,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,UAAU,EAAE,UAAU;AAAA,QACtB,gBAAgB,EAAE,WAAW,MAAM,SAAS,OAAO,UAAU,MAAM;AAAA,MACrE;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,WAAW,KAAK,oBAAoB,MAAM,EAAE;AAAA,QAC5C,YAAY;AAAA,QACZ,gBAAgB,MAAM,QAAQ,MAAM;AAAA,QACpC,SAAS;AAAA,QACT,QAAQ,MAAM;AAAA,QACd,UAAU;AAAA,QACV,eAAe,MAAM;AAAA,QACrB,OAAO;AAAA,UACL;AAAA,UACA,QAAQ,KAAK,oBAAoB,SAAS,KAAK;AAAA,UAC/C,WAAW,MAAM;AAAA,UACjB,QAAQ,MAAM;AAAA,UACd,WAAW,MAAM;AAAA,UACjB,UAAU,MAAM;AAAA,QAClB;AAAA,QACA,gBAAgB,MAAM;AAAA,QACtB,gBAAgB,MAAM;AAAA,QACtB,eAAe,MAAM;AAAA,MACvB;AAAA,MACA,WAAW,KAAK,oBAAoB,MAAM,EAAE;AAAA,IAC9C;AAAA,IAEA,OAAO;AAAA;AAAA,OAGK,UAAS,CACrB,WACA,UACA,WACe;AAAA,IAEf,MAAM,UAAU,WAAW,GAAG,aAAa,aAAa;AAAA,IACxD,OAAO,iBACL,KAAK,SACL,KAAK,eAAe,cAAc,SAAS,SAAS,CACtD;AAAA;AAAA,EAGM,WAAW,CAAC,QAAgB,WAAiC;AAAA,IACnE,OAAO,aAAa,KAAK,eAAe,cAAc,QAAQ,SAAS,CAAC;AAAA;AAAA,EAGlE,mBAAmB,CAAC,IAAoB;AAAA,IAE9C,OAAO,WAAW,GAAG,MAAM,GAAG;AAAA,IAC9B,OAAO,SAAS,SAAS,EAAE,IAAI;AAAA;AAAA,OAGnB,sBAAqB,CACjC,YAAY,KAAK,kBACF;AAAA,IACf,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,UAAU,CAAC;AAAA,MAAQ;AAAA,IAExB,MAAM,UAAU,iBACd,KAAK,SACL,KAAK,eAAe,mBAAmB,QAAQ,SAAS,CAC1D;AAAA,IAEA,MAAM,gBAAgB,MAAM,KAAK,QAAQ,SAAS,OAAO;AAAA,IACzD,IAAI;AAAA,MAAe;AAAA,IAGnB,MAAM,WAAW,MAAM,OAAO,KAAK,KAAK;AAAA,IACxC,MAAM,OAAO,SAAS;AAAA,IAEtB,MAAM,QAAe;AAAA,MACnB,IAAI;AAAA,MACJ,MAAO,MAA4B,QAAQ,mBAAmB;AAAA,MAC9D,SAAS,KAAK,QAAQ;AAAA,MACtB,UAAU;AAAA,QACR,MAAM;AAAA,QACN,QAAQ;AAAA,QACR;AAAA,QACA,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,QAAS,MAA8B;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,QAAQ,YAAY,KAAK;AAAA,IAEpC,KAAK,QAAQ,OAAO,KAClB;AAAA,MACE,KAAK;AAAA,MACL,SAAS,KAAK,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,IACF,GACA,+BACF;AAAA;AAAA,OAGY,iBAAgB,CAC5B,WACA,UACA,YAAY,KAAK,kBACF;AAAA,IACf,MAAM,SAAS,MAAM,KAAK,UAAU,WAAW,UAAU,SAAS;AAAA,IAElE,MAAM,eAAe,MAAM,KAAK,QAAQ,QAAQ,MAAM;AAAA,IACtD,IAAI;AAAA,MAAc,OAAO;AAAA,IAGzB,MAAM,UAAU,MAAM,KAAK,WAAW,WAAW,SAAS;AAAA,IAC1D,MAAM,cAAc,UAAU,oBAAoB,OAAO,IAAI;AAAA,IAC7D,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IAEjD,MAAM,UAAU,SACZ,iBACE,KAAK,SACL,KAAK,eAAe,mBAAmB,QAAQ,SAAS,CAC1D,IACA;AAAA,IAEJ,MAAM,mBACJ,gBAAgB,OACZ,YAAY,KACZ,gBAAgB,SACd,YAAY,QACZ,YAAY;AAAA,IAEpB,MAAM,OAAa;AAAA,MACjB,IAAI;AAAA,MACJ,MAAM,SAAS,QAAQ;AAAA,MACvB,SAAS,KAAK,QAAQ;AAAA,MACtB,QAAQ;AAAA,MACR,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,kBAAkB;AAAA,QAClB;AAAA,QACA,OAAO,SAAS,OAAO;AAAA,QACvB,SAAS,SAAS,SAAS;AAAA,QAC3B,UAAU;AAAA,QACV,OAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,QAAQ,WAAW,IAAI;AAAA,IAElC,KAAK,QAAQ,OAAO,MAClB;AAAA,MACE,KAAK;AAAA,MACL,SAAS,KAAK,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,GACA,oBACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAGD,2BAA2B,CACjC,SACA,QAAQ,KACR,YAAY,KAAK,kBACc;AAAA,IAC/B,IAAI,CAAC,QAAQ,MAAM,QAAQ,YAAY;AAAA,MACrC,OAAO;AAAA,IACT;AAAA,IACA,IAAI,CAAC,KAAK,iBAAiB,QAAQ,IAAI,SAAS,GAAG;AAAA,MACjD,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,OAAO,QAAQ,OAAO,SAAS,QAAQ,SAAS,UAAU;AAAA,IAChE,MAAM,QAAQ,QAAQ,OAAO,IAAI,QAAQ,SAAS,QAAQ;AAAA,IAC1D,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,OAAO;AAAA,MACL,QAAQ;AAAA,QACN,QAAQ;AAAA,QACR;AAAA,QACA,WAAW,QAAQ;AAAA,QACnB,UAAU,UAAU;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,QAAQ,SAAS,SAAS,QAAQ,OAAO,SAAS;AAAA,MAC/D;AAAA,MACA,UAAU,CAAC,UAAU,YAAY;AAAA,MACjC,UAAU;AAAA,QACR;AAAA,QACA,gBAAgB,QAAQ;AAAA,QACxB,aAAa;AAAA,QACb,kBAAkB,oBAAoB,OAAO;AAAA,QAC7C,aAAa,QAAQ;AAAA,QACrB,WAAW,QAAQ;AAAA,QACnB,UAAU,QAAQ;AAAA,QAClB,OAAO,QAAQ,OAAO;AAAA,QACtB,SAAS,QAAQ,SAAS;AAAA,MAC5B;AAAA,IACF;AAAA;AAAA,EAGM,wBAAwB,CAC9B,MACA,QAAQ,KACR,YAAY,KAAK,kBACc;AAAA,IAC/B,IAAI,CAAC,KAAK,MAAM,KAAK,WAAW,KAAK,SAAS,KAAK,WAAW;AAAA,MAC5D,OAAO;AAAA,IACT;AAAA,IACA,MAAM,QAAQ,wBAAwB,IAAI;AAAA,IAC1C,OAAO;AAAA,MACL,QAAQ;AAAA,QACN,QAAQ;AAAA,QACR;AAAA,QACA,UAAU,KAAK;AAAA,QACf,UACE,KAAK,UAAU,KAAK,oBAAoB,SAAS,KAAK;AAAA,MAC1D;AAAA,MACA,OAAO,IAAI;AAAA,MACX,MAAM;AAAA,MACN,aAAa,KAAK,QAAQ,SAAS;AAAA,MACnC;AAAA,MACA,UAAU,CAAC,UAAU,YAAY;AAAA,MACjC,UAAU;AAAA,QACR;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK,UAAU,KAAK,oBAAoB,SAAS;AAAA,QAC9D,WAAW,KAAK;AAAA,QAChB,eAAe,KAAK;AAAA,QACpB,kBAAkB,KAAK,QAAQ;AAAA,QAC/B,OAAO,KAAK,QAAQ;AAAA,MACtB;AAAA,IACF;AAAA;AAAA,EAGM,sBAAsB,CAC5B,SAC0B;AAAA,IAC1B,MAAM,QAAQ,IAAI;AAAA,IAClB,WAAW,UAAU,SAAS;AAAA,MAC5B,MAAM,MAAM;AAAA,QACT,OAAO,OAAmC,aAAa;AAAA,QACxD,OAAO,QAAQ;AAAA,QACf,OAAO,OAAO,aAAa;AAAA,QAC3B,OAAO,OAAO,YAAY;AAAA,QAC1B,OAAO,OAAO,YAAY;AAAA,MAC5B,EAAE,KAAK,GAAG;AAAA,MACV,MAAM,WAAW,MAAM,IAAI,GAAG;AAAA,MAC9B,IAAI,CAAC,aAAa,OAAO,SAAS,MAAM,SAAS,SAAS,IAAI;AAAA,QAC5D,MAAM,IAAI,KAAK,MAAM;AAAA,MACvB;AAAA,IACF;AAAA,IACA,OAAO,MAAM,KAAK,MAAM,OAAO,CAAC,EAAE,KAChC,CAAC,GAAG,OAAO,EAAE,SAAS,MAAM,EAAE,SAAS,EACzC;AAAA;AAAA,OAGY,yBAAwB,CACpC,SACA,UACA,WACwB;AAAA,IACxB,IAAI,sBAAsB,KAAK,QAAQ,GAAG;AAAA,MACxC,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,SACJ,OAAO,QAAQ,kBAAkB,aAC7B,MAAM,QAAQ,cAAc,QAAgB,IAC5C;AAAA,IACN,MAAM,iBAAiB,+BACrB,QAAQ,UACR,SACF;AAAA,IACA,IAAI,gBAAgB;AAAA,MAClB,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,OAAO,QAAQ,qBAAqB,YAAY;AAAA,MAClD,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,gBAAgB,MAAM,QAAQ,iBAAiB;AAAA,MACnD,WAAW,CAAC,QAAgB;AAAA,MAC5B,MAAM,CAAC,eAAe;AAAA,IACxB,CAAC;AAAA,IACD,WAAW,gBAAgB,eAAe;AAAA,MACxC,MAAM,iBACJ,aAAa,mBAAmB,WAC5B,aAAa,iBACb,aAAa,mBAAmB,WAC9B,aAAa,iBACb;AAAA,MACR,IAAI,CAAC,kBAAkB,mBAAmB,UAAU;AAAA,QAClD;AAAA,MACF;AAAA,MACA,MAAM,eACJ,OAAO,QAAQ,kBAAkB,aAC7B,MAAM,QAAQ,cAAc,cAAsB,IAClD;AAAA,MACN,MAAM,eAAe,+BACnB,cAAc,UACd,SACF;AAAA,MACA,IAAI,cAAc;AAAA,QAChB,OAAO;AAAA,MACT;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,OAGK,yBAAwB,CACpC,QACA,WACiB;AAAA,IACjB,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IACA,MAAM,SAAS,MAAM,OAAO,cAAc,KAAK,EAAE,OAAO,OAAO,CAAC;AAAA,IAChE,MAAM,UAAU,OAAO;AAAA,IACvB,IAAI,CAAC,SAAS,IAAI;AAAA,MAChB,MAAM,IAAI,MAAM,4CAA4C,QAAQ;AAAA,IACtE;AAAA,IACA,OAAO,QAAQ;AAAA;AAAA,OAGX,kBAAiB,CACrB,SACA,QACA,SACe;AAAA,IACf,MAAM,YAAY,MAAM,KAAK,0BAA0B,SAAS,MAAM;AAAA,IACtE,IAAI,CAAC,KAAK,oBAAoB,SAAS,GAAG;AAAA,MACxC,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,OAAO,OAAO,QAAQ,SAAS,WAAW,QAAQ,KAAK,KAAK,IAAI;AAAA,IACtE,IAAI,CAAC,MAAM;AAAA,MACT,MAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAAA,IAEA,IAAI,YAAY,OAAO;AAAA,IACvB,IAAI,WAAW,OAAO;AAAA,IAEtB,IAAI,OAAO,WAAW,CAAC,aAAa,CAAC,WAAW;AAAA,MAC9C,MAAM,OAAO,MAAM,QAAQ,QAAQ,OAAO,MAAM;AAAA,MAChD,YAAY,aAAa,MAAM;AAAA,MAC/B,MAAM,WAAW,MAAM;AAAA,MACvB,MAAM,mBACJ,OAAO,UAAU,aAAa,WAAW,SAAS,WAAW;AAAA,MAC/D,WAAW,YAAY;AAAA,IACzB;AAAA,IAEA,IAAI,aAAa,sBAAsB,KAAK,SAAS,GAAG;AAAA,MACtD,YAAY,MAAM,KAAK,yBAAyB,WAAW,SAAS;AAAA,IACtE;AAAA,IAEA,IAAI,CAAC,aAAa,OAAO,UAAU;AAAA,MACjC,MAAM,cAAc,MAAM,KAAK,yBAC7B,SACA,OAAO,OAAO,QAAQ,GACtB,SACF;AAAA,MACA,IAAI,CAAC,aAAa;AAAA,QAChB,MAAM,IAAI,MACR,8CAA8C,OAAO,UACvD;AAAA,MACF;AAAA,MACA,YAAY,MAAM,KAAK,yBAAyB,aAAa,SAAS;AAAA,IACxE;AAAA,IAEA,IAAI,CAAC,WAAW;AAAA,MACd,MAAM,IAAI,MACR,4DACF;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,YACT,WACA,MACA;AAAA,MACE;AAAA,MACA,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,aAAa;AAAA,MACb,QAAQ;AAAA,IACV,GACA,SACF;AAAA;AAAA,OAGI,wBAAuB,CAC3B,OACA,SACmC;AAAA,IACnC,MAAM,kBAAkB,6BAA6B,KAAK;AAAA,IAC1D,MAAM,UAAoC,CAAC;AAAA,IAC3C,MAAM,aAAa,KAAK,uBAAuB,SAAS,QAAQ,MAAM;AAAA,IAEtE,WAAW,aAAa,YAAY;AAAA,MAClC,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,MACjD,IAAI,CAAC,QAAQ;AAAA,QACX;AAAA,MACF;AAAA,MAEA,IAAI;AAAA,QACF,MAAM,WAAW,MAAM,KAAK,aAC1B;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,QACT,GACA,SACF;AAAA,QACA,WAAW,WAAW,UAAU;AAAA,UAC9B,MAAM,QAAQ,yBAAyB,iBAAiB,QAAQ,IAAI;AAAA,YAClE,QAAQ;AAAA,YACR,QAAQ,OAAO;AAAA,YACf,QAAQ,SAAS;AAAA,UACnB,CAAC;AAAA,UACD,IAAI,SAAS,GAAG;AAAA,YACd;AAAA,UACF;AAAA,UACA,MAAM,SAAS,KAAK,4BAClB,SACA,OACA,SACF;AAAA,UACA,IAAI,QAAQ;AAAA,YACV,QAAQ,KAAK,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,QACA,OAAO,OAAO;AAAA,QACd,KAAK,QAAQ,OAAO,MAClB;AAAA,UACE,KAAK;AAAA,UACL,SAAS,KAAK,QAAQ;AAAA,UACtB;AAAA,UACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,GACA,sCACF;AAAA;AAAA,MAGF,IAAI;AAAA,QACF,MAAM,cAAc,MAAM,OAAO,MAAM,KAAK,EAAE,OAAO,IAAI,CAAC;AAAA,QAC1D,MAAM,UAAW,YAAY,WAAW,CAAC;AAAA,QACzC,WAAW,UAAU,SAAS;AAAA,UAC5B,MAAM,OAAkB;AAAA,YACtB,IAAI,OAAO,MAAM;AAAA,YACjB,QAAQ,OAAO;AAAA,YACf,MAAM,OAAO,QAAQ;AAAA,YACrB,SAAS,QAAQ,OAAO,OAAO;AAAA,YAC/B,UAAU,OAAO;AAAA,YACjB,IAAI,OAAO;AAAA,YACX,SAAS,OAAO;AAAA,YAChB,UAAU,OAAO;AAAA,YACjB,SAAS;AAAA,cACP,OAAO,OAAO,SAAS;AAAA,cACvB,OAAO,OAAO,SAAS;AAAA,cACvB,OAAO,OAAO,SAAS;AAAA,cACvB,UAAU,OAAO,SAAS;AAAA,cAC1B,oBAAoB,OAAO,SAAS;AAAA,cACpC,aAAa,OAAO,SAAS;AAAA,cAC7B,uBAAuB,OAAO,SAAS;AAAA,cACvC,YAAY,OAAO,SAAS;AAAA,cAC5B,aAAa,OAAO,SAAS;AAAA,cAC7B,kBAAkB,OAAO,SAAS;AAAA,cAClC,YAAY,OAAO,SAAS;AAAA,cAC5B,OAAO,OAAO,SAAS;AAAA,cACvB,SAAS,OAAO,SAAS;AAAA,cACzB,SAAS,OAAO,SAAS;AAAA,cACzB,SAAS,OAAO,SAAS;AAAA,cACzB,SAAS,OAAO,SAAS;AAAA,cACzB,UAAU,OAAO,SAAS;AAAA,cAC1B,UAAU,OAAO,SAAS;AAAA,cAC1B,WAAW,OAAO,SAAS;AAAA,cAC3B,eAAe,OAAO,SAAS;AAAA,cAC/B,MAAM,OAAO,SAAS;AAAA,YACxB;AAAA,YACA,SAAS,QAAQ,OAAO,QAAQ;AAAA,YAChC,SAAS,QAAQ,OAAO,QAAQ;AAAA,YAChC,gBAAgB,QAAQ,OAAO,gBAAgB;AAAA,YAC/C,cAAc,QAAQ,OAAO,aAAa;AAAA,YAC1C,mBAAmB,QAAQ,OAAO,mBAAmB;AAAA,YACrD,OAAO,QAAQ,OAAO,MAAM;AAAA,YAC5B,WAAW,QAAQ,OAAO,WAAW;AAAA,YACrC,SAAS,OAAO,WAAW;AAAA,UAC7B;AAAA,UACA,MAAM,QAAQ,yBAAyB,iBAAiB,KAAK,IAAI;AAAA,YAC/D,KAAK;AAAA,YACL,KAAK;AAAA,YACL,KAAK,QAAQ;AAAA,YACb,KAAK,QAAQ;AAAA,YACb,KAAK,QAAQ;AAAA,UACf,CAAC;AAAA,UACD,IAAI,SAAS,GAAG;AAAA,YACd;AAAA,UACF;AAAA,UACA,MAAM,SAAS,KAAK,yBAAyB,MAAM,OAAO,SAAS;AAAA,UACnE,IAAI,QAAQ;AAAA,YACV,QAAQ,KAAK,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,QACA,OAAO,OAAO;AAAA,QACd,KAAK,QAAQ,OAAO,MAClB;AAAA,UACE,KAAK;AAAA,UACL,SAAS,KAAK,QAAQ;AAAA,UACtB;AAAA,UACA,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QAC9D,GACA,mCACF;AAAA;AAAA,MAGF,IAAI,QAAQ,QAAQ,WAAW;AAAA,QAC7B,MAAM,UAAU,MAAM,KAAK,WACzB,QAAQ,OAAO,WACf,SACF;AAAA,QACA,IAAI,SAAS;AAAA,UACX,MAAM,SAAS,KAAK,4BAClB,SACA,KACA,SACF;AAAA,UACA,IAAI,QAAQ;AAAA,YACV,QAAQ,KAAK,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,OAAO,KAAK,uBAAuB,OAAO,EAAE,MAAM,GAAG,EAAE;AAAA;AAAA,OAGnD,mBAAkB,CACtB,SACmC;AAAA,IACnC,MAAM,UAAoC,CAAC;AAAA,IAC3C,WAAW,aAAa,KAAK,uBAAuB,OAAO,GAAG;AAAA,MAC5D,IAAI,CAAC,KAAK,oBAAoB,SAAS,GAAG;AAAA,QACxC;AAAA,MACF;AAAA,MACA,MAAM,WAAW,MAAM,KAAK,aAC1B;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,MACT,GACA,SACF;AAAA,MACA,QAAQ,KACN,GAAG,SACA,IAAI,CAAC,YACJ,KAAK,4BAA4B,SAAS,KAAK,SAAS,CAC1D,EACC,OAAO,CAAC,WACP,QAAQ,MAAM,CAChB,CACJ;AAAA,IACF;AAAA,IACA,OAAO,KAAK,uBAAuB,OAAO,EAAE,MAAM,GAAG,EAAE;AAAA;AAAA,OAGnD,2BAA0B,CAC9B,SACmC;AAAA,IACnC,MAAM,UAAoC,CAAC;AAAA,IAC3C,MAAM,OACJ,QAAQ,UAAU,OAAO,QAAQ,QAAQ,YAAY,aACjD,MAAM,QAAQ,QAAQ,QAAQ,QAAQ,MAAM,IAC5C;AAAA,IACN,MAAM,YAAY,MAAM,KAAK,0BAC3B,QAAQ,SACR,QAAQ,QACR;AAAA,MACE,WAAY,QAA0C;AAAA,MACtD,QAAQ,QAAQ;AAAA,IAClB,CACF;AAAA,IACA,MAAM,YACJ,QAAQ,QAAQ,cACf,MAAM,WAAW,UAAU,KAAK,YAAY;AAAA,IAC/C,MAAM,eAAe,MAAM;AAAA,IAC3B,MAAM,WACJ,QAAQ,QAAQ,aACf,OAAO,cAAc,aAAa,WAC/B,aAAa,WACb;AAAA,IAEN,IAAI,WAAW;AAAA,MACb,MAAM,UAAU,MAAM,KAAK,WAAW,WAAW,SAAS;AAAA,MAC1D,IAAI,SAAS;AAAA,QACX,MAAM,SAAS,KAAK,4BAClB,SACA,MACA,SACF;AAAA,QACA,IAAI,QAAQ;AAAA,UACV,IAAI,UAAU;AAAA,YACZ,OAAO,OAAO;AAAA,YACd,OAAO,OAAO,WAAW;AAAA,YACzB,OAAO,QAAQ,GAAG,OAAO,SAAS;AAAA,YAClC,OAAO,WAAW;AAAA,iBACZ,OAAO,YAAY,CAAC;AAAA,cACxB,eAAe;AAAA,YACjB;AAAA,UACF;AAAA,UACA,QAAQ,KAAK,MAAM;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA,IAEA,QAAQ,KACN,GAAI,MAAM,KAAK,mBAAmB;AAAA,SAC7B;AAAA,MACH;AAAA,IACF,CAAiC,CACnC;AAAA,IACA,OAAO,KAAK,uBAAuB,OAAO,EAAE,MAAM,GAAG,EAAE;AAAA;AAAA,OAGnD,wBAAuB,CAC3B,QACA,SAC6C;AAAA,IAC7C,MAAM,YAAY,MAAM,KAAK,0BAC3B,QAAQ,SACR,QACA;AAAA,MACE,WAAY,QAA0C;AAAA,MACtD,QAAQ,QAAQ;AAAA,IAClB,CACF;AAAA,IACA,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,OACJ,OAAO,UAAU,OAAO,QAAQ,QAAQ,YAAY,aAChD,MAAM,QAAQ,QAAQ,QAAQ,OAAO,MAAM,IAC3C;AAAA,IACN,MAAM,YAAY,OAAO,aAAa,MAAM;AAAA,IAC5C,IAAI,CAAC,WAAW;AAAA,MACd,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,WAAW,MAAM;AAAA,IACvB,MAAM,WACJ,OAAO,aACN,OAAO,UAAU,aAAa,WAAW,SAAS,WAAW;AAAA,IAChE,MAAM,UAAU,MAAM,KAAK,WAAW,WAAW,SAAS;AAAA,IAE1D,MAAM,WAAW,WACb,MAAM,OAAO,cAAc,QAAQ;AAAA,MACjC,SAAS;AAAA,MACT,IAAI;AAAA,MACJ,OAAO;AAAA,IACT,CAAC,IACD;AAAA,MACE,UAAU,MAAM,KAAK,YAAY,WAAW,EAAE,OAAO,GAAG,GAAG,SAAS;AAAA,IACtE;AAAA,IACJ,MAAM,cAAe,SAAS,YAAY,CAAC;AAAA,IAG3C,MAAM,iBAAgE,CAAC;AAAA,IACvE,WAAW,cAAc,YAAY,MAAM,EAAE,QAAQ,GAAG;AAAA,MACtD,MAAM,OAAO,OAAQ,WAA4B,QAAQ,EAAE;AAAA,MAC3D,IAAI,CAAC,KAAK,KAAK,GAAG;AAAA,QAChB;AAAA,MACF;AAAA,MACA,MAAM,SACH,WAA4B,QAC5B,WAAkD;AAAA,MACrD,MAAM,OACJ,OAAO,WAAW,WACd,MAAM,KAAK,QAAQ,QAAQ,SAAS,IACpC;AAAA,MACN,eAAe,KAAK;AAAA,QAClB,UAAU,SAAU,SAAkB;AAAA,QACtC,MAAM,OAAO,wBAAwB,IAAI,IAAI;AAAA,QAC7C;AAAA,QACA,WAAW,OAAQ,WAA4B,EAAE,IAAI,QAAQ;AAAA,QAC7D,UAAU;AAAA,UACR;AAAA,UACA,gBAAiB,WAA4B;AAAA,UAC7C,aAAa;AAAA,QACf;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,OAAO;AAAA,MACL,QAAQ;AAAA,QACN,QAAQ;AAAA,QACR;AAAA,QACA,QAAQ,OAAO,UAAU,MAAM;AAAA,QAC/B;AAAA,QACA,UACE,OAAO,YAAY,KAAK,oBAAoB,SAAS,KAAK;AAAA,QAC5D,UAAU;AAAA,MACZ;AAAA,MACA,OAAO,SAAS,OAAO,IAAI,QAAQ,SAAS;AAAA,MAC5C,SAAS,SAAS,SAAS,SAAS,SAAS,OAAO;AAAA,MACpD;AAAA,MACA,UAAU;AAAA,QACR;AAAA,QACA,gBAAgB;AAAA,QAChB,aAAa,KAAK,oBAAoB,SAAS;AAAA,QAC/C,eAAe;AAAA,QACf,aAAa,SAAS;AAAA,MACxB;AAAA,IACF;AAAA;AAAA,OAGY,gCAA+B,CAC3C,QACA,UACsE;AAAA,IACtE,MAAM,YAAY,MAAM,KAAK,0BAC3B,KAAK,SACL,QACA,QACF;AAAA,IACA,IAAI,YAAY,QAAQ,aAAa,UAAU;AAAA,IAC/C,IAAI,WAAW,QAAQ,YAAY,UAAU;AAAA,IAC7C,MAAM,SAAS,QAAQ,UAAU,UAAU;AAAA,IAE3C,IAAI,WAAW,CAAC,aAAa,CAAC,WAAW;AAAA,MACvC,MAAM,OAAO,MAAM,KAAK,QAAQ,QAAQ,MAAM;AAAA,MAC9C,YAAY,aAAa,MAAM;AAAA,MAC/B,MAAM,WAAW,MAAM;AAAA,MACvB,MAAM,eACJ,OAAO,UAAU,aAAa,WAAW,SAAS,WAAW;AAAA,MAC/D,WAAW,YAAY;AAAA,IACzB;AAAA,IAEA,IAAI,aAAa,sBAAsB,KAAK,SAAS,GAAG;AAAA,MACtD,YAAY,MAAM,KAAK,yBAAyB,WAAW,SAAS;AAAA,IACtE;AAAA,IAEA,IAAI,CAAC,aAAa,QAAQ,UAAU;AAAA,MAClC,MAAM,cAAc,MAAM,KAAK,yBAC7B,KAAK,SACL,OAAO,OAAO,QAAQ,GACtB,SACF;AAAA,MACA,IAAI,aAAa;AAAA,QACf,YAAY,MAAM,KAAK,yBAAyB,aAAa,SAAS;AAAA,MACxE;AAAA,IACF;AAAA,IAEA,IAAI,CAAC,WAAW;AAAA,MACd,MAAM,IAAI,MACR,kEACF;AAAA,IACF;AAAA,IAEA,OAAO,EAAE,WAAW,WAAW,SAAS;AAAA;AAAA,OAG5B,qBAAoB,CAChC,SACA,WACA,UACA,YAAY,KAAK,kBACA;AAAA,IACjB,MAAM,oBAAoB,YAAY,QAAQ;AAAA,IAC9C,MAAM,SAAS,MAAM,KAAK,UACxB,WACA,mBACA,SACF;AAAA,IACA,MAAM,YAAY,KAAK,uBAAuB,SAAS;AAAA,IACvD,MAAM,cAAc,QAAQ,QAAQ,aAAa;AAAA,IACjD,MAAM,WACJ,gBAAgB,YACZ,KAAK,QAAQ,UACb,KAAK,YAAY,aAAa,SAAS;AAAA,IAC7C,MAAM,OAAO,QAAQ,OACjB,MAAM,KAAK,QAAQ,QAAQ,MAAM,SAAS,IAC1C;AAAA,IACJ,MAAM,cAAc,OAAO,wBAAwB,IAAI,IAAI;AAAA,IAC3D,MAAM,UAAU,MAAM,KAAK,WAAW,WAAW,SAAS,EAAE,MAC1D,MAAM,IACR;AAAA,IACA,MAAM,cAAc,oBAChB,YAAY,SACZ,SAAS,OACP,YAAY,KACZ,YAAY;AAAA,IAElB,MAAM,eAAwB,QAAQ,SAAS,CAAC,GAAG,IAAI,CAAC,UAAU;AAAA,MAChE,IAAI,KAAK;AAAA,MACT,KAAK,KAAK;AAAA,MACV,OAAO,KAAK,SAAS,KAAK;AAAA,MAC1B,QAAQ;AAAA,MACR,aAAa,KAAK;AAAA,IACpB,EAAE;AAAA,IAEF,OAAO;AAAA,MACL,IAAI,iBACF,KAAK,SACL,KAAK,eAAe,SAAS,GAAG,aAAa,QAAQ,MAAM,SAAS,CACtE;AAAA,MACA,SAAS,KAAK,QAAQ;AAAA,MACtB;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP,MAAM,QAAQ,QAAQ;AAAA,QACtB,QAAQ;AAAA,QACR,MAAM;AAAA,QACN;AAAA,QACA,UAAU,EAAE,UAAU;AAAA,WAClB,qBAAqB,sBAAsB,QAAQ,KACnD;AAAA,UACE,WAAW,iBACT,KAAK,SACL,KAAK,eACH,SACA,GAAG,aAAa,qBAChB,SACF,CACF;AAAA,QACF,IACA,CAAC;AAAA,WACD,YAAY,SAAS,IAAI,EAAE,YAAY,IAAI,CAAC;AAAA,MAClD;AAAA,MACA,UAAU;AAAA,QACR,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,UAAU;AAAA,QACV;AAAA,QACA,WAAW,KAAK,oBAAoB,QAAQ,EAAE;AAAA,QAC9C,YAAY;AAAA,QACZ,gBAAgB,MAAM,QAAQ;AAAA,QAC9B,SAAS,gBAAgB;AAAA,QACzB,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,UAAU;AAAA,QACV,eAAe,QAAQ;AAAA,QACvB,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,MAAM;AAAA,UACN,UAAU,MAAM,QAAQ;AAAA,QAC1B;AAAA,QACA,OAAO;AAAA,UACL;AAAA,UACA,QAAQ,KAAK,oBAAoB,SAAS,KAAK;AAAA,UAC/C;AAAA,UACA,QAAQ;AAAA,UACR,WAAW,QAAQ;AAAA,UACnB,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB;AAAA,QAChB,gBAAgB,QAAQ;AAAA,QACxB,eAAe;AAAA,QACf,WAAW,QAAQ;AAAA,MACrB;AAAA,MACA,WAAW,KAAK,oBAAoB,QAAQ,EAAE;AAAA,IAChD;AAAA;AAAA,OAGI,qBAAoB,CACxB,SACkB;AAAA,IAClB,MAAM,SAAkB,CAAC;AAAA,IACzB,WAAW,aAAa,KAAK,uBAAuB,OAAO,GAAG;AAAA,MAC5D,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,MACjD,IAAI,CAAC,QAAQ;AAAA,QACX;AAAA,MACF;AAAA,MAEA,IAAI,OAAO,mBAAmB;AAAA,MAC9B,IAAI;AAAA,QACF,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,QACjD,IAAI,QAAQ;AAAA,UACV,MAAM,WAAW,MAAM,OAAO,KAAK,KAAK;AAAA,UACxC,MAAM,OAAO,SAAS;AAAA,UACtB,OAAO,MAAM,QAAQ;AAAA,QACvB;AAAA,QACA,MAAM;AAAA,MAIR,OAAO,KAAK;AAAA,QACV,IAAI,iBACF,KAAK,SACL,KAAK,eAAe,mBAAmB,QAAQ,SAAS,CAC1D;AAAA,QACA,SAAS,KAAK,QAAQ;AAAA,QACtB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,OAAO;AAAA;AAAA,OAGH,uBAAsB,CAC1B,UACA,QACmB;AAAA,IACnB,MAAM,YAAY,MAAM,KAAK,0BAC3B,SAAS,SACT,OAAO,QACP,EAAE,WAAW,OAAO,WAAW,QAAQ,OAAO,OAAO,CACvD;AAAA,IACA,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,OAAO,CAAC;AAAA,IACV;AAAA,IAEA,QAAQ,WAAW,aAAa,MAAM,KAAK,gCACzC,OAAO,QACP,KAAK,QAAQ,UAAU,CACzB;AAAA,IACA,MAAM,QAAQ,OAAO,SAAS,OAAO,KAAK,IACtC,KAAK,IAAI,GAAG,KAAK,IAAI,OAAO,OAAO,KAAK,GAAG,GAAG,CAAC,IAC/C;AAAA,IAEJ,MAAM,cAAc,YAEd,MAAM,OAAO,cAAc,QAAQ;AAAA,MACjC,SAAS;AAAA,MACT,IAAI;AAAA,MACJ;AAAA,MACA,QAAQ,OAAO;AAAA,MACf,QAAQ,OAAO;AAAA,MACf,QAAQ,OAAO;AAAA,IACjB,CAAC,GACD,YAEgB,CAAC,IACnB,MAAM,KAAK,YACT,WACA;AAAA,MACE;AAAA,MACA,QAAQ,OAAO;AAAA,MACf,OAAO,OAAO;AAAA,IAChB,GACA,SACF;AAAA,IAEJ,MAAM,WAAqB,CAAC;AAAA,IAC5B,WAAW,cAAc,aAAa;AAAA,MACpC,MAAM,UAAU;AAAA,MAChB,IAAI,CAAC,QAAQ,IAAI;AAAA,QACf;AAAA,MACF;AAAA,MACA,SAAS,KACP,MAAM,KAAK,qBACT,SACA,WACA,UACA,SACF,CACF;AAAA,IACF;AAAA,IACA,OAAO,SAAS,KACd,CAAC,MAAM,UACL,OAAO,MAAM,aAAa,CAAC,IAAI,OAAO,KAAK,aAAa,CAAC,CAC7D;AAAA;AAAA,OAGI,wBAAuB,CAC3B,SACA,QACmB;AAAA,IACnB,MAAM,QAAQ,OAAO,OAAO,KAAK,EAAE,YAAY;AAAA,IAC/C,IAAI,CAAC,OAAO;AAAA,MACV,OAAO,CAAC;AAAA,IACV;AAAA,IAEA,MAAM,WAAW,MAAM,KAAK,uBAAuB,SAAS;AAAA,SACvD;AAAA,MACH,OAAO,KAAK,IAAI,OAAO,SAAS,KAAK,GAAG;AAAA,IAC1C,CAAC;AAAA,IACD,OAAO,SACJ,OAAO,CAAC,WAAW;AAAA,MAClB,MAAM,OAAO,OAAO,OAAO,SAAS,QAAQ,EAAE,EAAE,YAAY;AAAA,MAC5D,MAAM,OAAO,OAAO,OAAO,SAAS,QAAQ,EAAE,EAAE,YAAY;AAAA,MAC5D,OAAO,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,KAAK;AAAA,KACnD,EACA,MAAM,GAAG,OAAO,SAAS,EAAE;AAAA;AAAA,OAG1B,sBAAqB,CACzB,UACA,QACe;AAAA,IACf,QAAQ,WAAW,cAAc,MAAM,KAAK,gCAC1C,OAAO,QACP,MACF;AAAA,IACA,MAAM,YAAY,OAAO,aAAa,OAAO;AAAA,IAC7C,MAAM,QAAQ,OAAO,OAAO,KAAK;AAAA,IACjC,IAAI,CAAC,aAAa,CAAC,OAAO;AAAA,MACxB,MAAM,IAAI,MAAM,wDAAwD;AAAA,IAC1E;AAAA,IACA,IAAI,OAAO,QAAQ;AAAA,MACjB,MAAM,KAAK,eAAe,WAAW,WAAW,OAAO,SAAS;AAAA,MAChE;AAAA,IACF;AAAA,IACA,MAAM,KAAK,aAAa,WAAW,WAAW,OAAO,SAAS;AAAA;AAAA,OAG1D,qBAAoB,CACxB,UACA,QACiB;AAAA,IACjB,QAAQ,WAAW,WAAW,aAC5B,MAAM,KAAK,gCAAgC,OAAO,QAAQ,MAAM;AAAA,IAClE,MAAM,YAAY,OAAO,aAAa,OAAO;AAAA,IAC7C,MAAM,OAAO,OAAO,SAAS,QAAQ,OAAO;AAAA,IAC5C,IAAI,CAAC,aAAa,CAAC,MAAM,KAAK,GAAG;AAAA,MAC/B,MAAM,IAAI,MAAM,mDAAmD;AAAA,IACrE;AAAA,IAEA,MAAM,KAAK,YAAY,WAAW,WAAW,MAAM,SAAS;AAAA,IAC5D,OAAO,KAAK,qBACV;AAAA,MACE,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,MAAM,KAAK,uBAAuB,SAAS,KAAK;AAAA,MAChD;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb,WAAW;AAAA,MACX,OAAO;AAAA,MACP,aAAa;AAAA,MACb,QAAQ;AAAA,IACV,GACA,WACA,UACA,SACF;AAAA;AAAA,OAGI,uBAAsB,CAC1B,UACA,QACe;AAAA,IACf,QAAQ,WAAW,cAAc,MAAM,KAAK,gCAC1C,OAAO,QACP,MACF;AAAA,IACA,MAAM,YAAY,OAAO,aAAa,OAAO;AAAA,IAC7C,IAAI,CAAC,WAAW;AAAA,MACd,MAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAAA,IACA,MAAM,KAAK,cAAc,WAAW,WAAW,SAAS;AAAA;AAAA,OAGpD,oBAAmB,CACvB,UACA,QACe;AAAA,IACf,QAAQ,WAAW,cAAc,MAAM,KAAK,gCAC1C,OAAO,QACP,MACF;AAAA,IACA,MAAM,YAAY,OAAO,aAAa,OAAO;AAAA,IAC7C,IAAI,CAAC,WAAW;AAAA,MACd,MAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAAA,IACA,IAAI,OAAO,QAAQ,OAAO;AAAA,MACxB,MAAM,KAAK,aAAa,WAAW,WAAW,SAAS;AAAA,MACvD;AAAA,IACF;AAAA,IACA,MAAM,KAAK,WAAW,WAAW,WAAW,SAAS;AAAA;AAAA,OAGjD,iBAAgB,CACpB,SACA,QACkB;AAAA,IAClB,MAAM,YAAY,mBACf,OAAO,QAAgD,aACtD,KAAK,oBACL,kBACJ;AAAA,IACA,MAAM,SACJ,OAAO,UAAU,OAAO,UAAU,OAAO,YAAY,OAAO;AAAA,IAC9D,IAAI,CAAC,QAAQ;AAAA,MACX,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,cAAc,sBAAsB,KAAK,MAAM,IAC/C,SACA,MAAM,KAAK,yBAAyB,SAAS,QAAQ,SAAS;AAAA,IAElE,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,eAAe,QAAQ;AAAA,MAC1B,MAAM,cAAc,MAAM,OAAO,MAAM,KAAK,EAAE,OAAO,IAAI,CAAC;AAAA,MAC1D,MAAM,UAAW,YAAY,WAAW,CAAC;AAAA,MACzC,MAAM,aAAa,6BAA6B,MAAM;AAAA,MACtD,MAAM,QAAQ,QAAQ,KAAK,CAAC,WAC1B;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO;AAAA,QACP,OAAO,SAAS;AAAA,QAChB,OAAO,SAAS;AAAA,MAClB,EACG,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC,EACjD,KAAK,CAAC,UACL,6BAA6B,KAAK,EAAE,SAAS,UAAU,CACzD,CACJ;AAAA,MACA,cAAc,OAAO,MAAM;AAAA,IAC7B;AAAA,IAEA,IAAI,CAAC,aAAa;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,OAAO,MAAM,KAAK,QAAQ,aAAa,SAAS;AAAA,IACtD,IAAI,CAAC,MAAM;AAAA,MACT,OAAO;AAAA,IACT;AAAA,IAEA,OAAO;AAAA,MACL,IAAI,KAAK,YAAY,KAAK,IAAI,SAAS;AAAA,MACvC,SAAS,KAAK,QAAQ;AAAA,MACtB,OAAO,CAAC,wBAAwB,IAAI,GAAG,KAAK,MAAM,KAAK,QAAQ,EAAE,OAC/D,CAAC,UAA2B,QAAQ,KAAK,CAC3C;AAAA,MACA,UAAU;AAAA,QACR,QAAQ;AAAA,QACR;AAAA,QACA,OAAO;AAAA,UACL;AAAA,UACA,IAAI,KAAK;AAAA,UACT,QAAQ,KAAK,UAAU,KAAK,oBAAoB,SAAS;AAAA,UACzD,MAAM,KAAK;AAAA,UACX,UAAU,KAAK;AAAA,UACf,SAAS,KAAK,KAAK,QAAQ;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA;AAAA,OAGI,wBAAuB,CAC3B,UACA,SAC6C;AAAA,IAC7C,MAAM,YAAY,mBACf,QAAQ,QAAgD,aACtD,QAA0C,aAC1C,QAA0C,SAAS,aACpD,KAAK,oBACL,kBACJ;AAAA,IACA,MAAM,cAAc,MAAM,KAAK,yBAC7B,QAAQ,SACR,OAAO,QAAQ,GACf,SACF;AAAA,IACA,IAAI,CAAC,aAAa;AAAA,MAChB,OAAO;AAAA,IACT;AAAA,IACA,MAAM,OAAO,MAAM,KAAK,QAAQ,aAAa,SAAS;AAAA,IACtD,IAAI,CAAC,MAAM;AAAA,MACT,OAAO;AAAA,IACT;AAAA,IAEA,OAAO;AAAA,MACL;AAAA,MACA,OAAO,wBAAwB,IAAI;AAAA,MACnC,SAAS;AAAA,QACP,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,KAAK,QAAQ;AAAA,MACf,EAAE,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AAAA,MACnD,SAAS;AAAA,QACP,OAAO,KAAK;AAAA,WACR,KAAK,QAAQ,QAAQ,EAAE,OAAO,KAAK,QAAQ,MAAM,IAAI,CAAC;AAAA,MAC5D;AAAA,MACA,UAAU;AAAA,QACR;AAAA,QACA,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK,UAAU,KAAK,oBAAoB,SAAS;AAAA,QAC9D,SAAS,KAAK,KAAK,QAAQ;AAAA,MAC7B;AAAA,IACF;AAAA;AAAA,OAGI,QAAO,CACX,QACA,WAC2B;AAAA,IAC3B,MAAM,YAAY,KAAK,uBAAuB,SAAS;AAAA,IAEvD,MAAM,aAAa,UAAU,IAAI,MAAM;AAAA,IACvC,IAAI,YAAY;AAAA,MACd,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC;AAAA,MAAQ,OAAO;AAAA,IAEpB,MAAM,SAAS,MAAM,OAAO,MAAM,KAAK,EAAE,MAAM,OAAO,CAAC;AAAA,IACvD,IAAI,CAAC,OAAO;AAAA,MAAM,OAAO;AAAA,IAEzB,MAAM,OAAkB;AAAA,MACtB,IAAI,OAAO,KAAK,MAAM;AAAA,MACtB,QAAQ,OAAO,KAAK;AAAA,MACpB,MAAM,OAAO,KAAK,QAAQ;AAAA,MAC1B,SAAS,OAAO,KAAK,WAAW;AAAA,MAChC,UAAU,OAAO,KAAK;AAAA,MACtB,IAAI,OAAO,KAAK;AAAA,MAChB,SAAS,OAAO,KAAK;AAAA,MACrB,UAAU,OAAO,KAAK;AAAA,MACtB,SAAS;AAAA,QACP,OAAO,OAAO,KAAK,SAAS;AAAA,QAC5B,OAAO,OAAO,KAAK,SAAS;AAAA,QAC5B,OAAO,OAAO,KAAK,SAAS;AAAA,QAC5B,UAAU,OAAO,KAAK,SAAS;AAAA,QAC/B,oBAAoB,OAAO,KAAK,SAAS;AAAA,QACzC,aAAa,OAAO,KAAK,SAAS;AAAA,QAClC,uBAAuB,OAAO,KAAK,SAAS;AAAA,QAC5C,YAAY,OAAO,KAAK,SAAS;AAAA,QACjC,aAAa,OAAO,KAAK,SAAS;AAAA,QAClC,kBAAkB,OAAO,KAAK,SAAS;AAAA,QACvC,YAAY,OAAO,KAAK,SAAS;AAAA,QACjC,OAAO,OAAO,KAAK,SAAS;AAAA,QAC5B,SAAS,OAAO,KAAK,SAAS;AAAA,QAC9B,SAAS,OAAO,KAAK,SAAS;AAAA,QAC9B,SAAS,OAAO,KAAK,SAAS;AAAA,QAC9B,SAAS,OAAO,KAAK,SAAS;AAAA,QAC9B,UAAU,OAAO,KAAK,SAAS;AAAA,QAC/B,UAAU,OAAO,KAAK,SAAS;AAAA,QAC/B,WAAW,OAAO,KAAK,SAAS;AAAA,QAChC,eAAe,OAAO,KAAK,SAAS;AAAA,QACpC,MAAM,OAAO,KAAK,SAAS;AAAA,MAC7B;AAAA,MACA,SAAS,OAAO,KAAK,YAAY;AAAA,MACjC,SAAS,OAAO,KAAK,YAAY;AAAA,MACjC,gBAAgB,OAAO,KAAK,oBAAoB;AAAA,MAChD,cAAc,OAAO,KAAK,iBAAiB;AAAA,MAC3C,mBAAmB,OAAO,KAAK,uBAAuB;AAAA,MACtD,OAAO,OAAO,KAAK,UAAU;AAAA,MAC7B,WAAW,OAAO,KAAK,eAAe;AAAA,MACtC,SAAS,OAAO,KAAK,WAAW;AAAA,IAClC;AAAA,IAEA,UAAU,IAAI,QAAQ,IAAI;AAAA,IAC1B,OAAO;AAAA;AAAA,OAGH,WAAU,CACd,WACA,WAC8B;AAAA,IAC9B,MAAM,eAAe,KAAK,0BAA0B,SAAS;AAAA,IAE7D,MAAM,gBAAgB,aAAa,IAAI,SAAS;AAAA,IAChD,IAAI,eAAe;AAAA,MACjB,OAAO;AAAA,IACT;AAAA,IAEA,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC;AAAA,MAAQ,OAAO;AAAA,IAEpB,MAAM,SAAS,MAAM,OAAO,cAAc,KAAK,EAAE,SAAS,UAAU,CAAC;AAAA,IACrE,IAAI,CAAC,OAAO;AAAA,MAAS,OAAO;AAAA,IAE5B,MAAM,UAAwB;AAAA,MAC5B,IAAK,OAAO,QAA2B;AAAA,MACvC,MAAO,OAAO,QAA6B,QAAQ;AAAA,MACnD,WACG,OAAO,QAAqC,cAAc;AAAA,MAC7D,SAAU,OAAO,QAAmC,YAAY;AAAA,MAChE,MAAO,OAAO,QAAgC,SAAS;AAAA,MACvD,QAAS,OAAO,QAAkC,WAAW;AAAA,MAC7D,WACG,OAAO,QAAqC,cAAc;AAAA,MAC7D,YACG,OAAO,QAAsC,eAAe;AAAA,MAC/D,WACG,OAAO,QAAqC,cAAc;AAAA,MAC7D,UAAW,OAAO,QAAoC,aAAa;AAAA,MACnE,aACG,OAAO,QAAwC,iBAAiB;AAAA,MACnE,UAAW,OAAO,QAAoC,aAAa;AAAA,MACnE,OACE,OAAO,QAGP,QACE;AAAA,QACE,OAAQ,OAAO,QAAyC,MAAM;AAAA,QAC9D,SAAU,OAAO,QAA2C,MACzD;AAAA,QACH,SAAU,OAAO,QAA4C,MAC1D;AAAA,MACL,IACA;AAAA,MACJ,SACE,OAAO,QAGP,UACE;AAAA,QACE,OAAQ,OAAO,QAA2C,QACvD;AAAA,QACH,SAAU,OAAO,QACd,QAAQ;AAAA,QACX,SAAU,OAAO,QACd,QAAQ;AAAA,MACb,IACA;AAAA,MACJ,YAAa,OAAO,QAAqC;AAAA,MACzD,SAAU,OAAO,QAAgC;AAAA,MACjD,SAAU,OAAO,QAAgC;AAAA,IACnD;AAAA,IAEA,aAAa,IAAI,WAAW,OAAO;AAAA,IACnC,OAAO;AAAA;AAAA,OAGH,YAAW,CACf,WACA,MACA,SACA,WAC4C;AAAA,IAC5C,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAGA,MAAM,gBAAgB,sBAAsB,IAAI;AAAA,IAChD,MAAM,WAAW,KAAK,aAAa,aAAa;AAAA,IAChD,IAAI,SAAS;AAAA,IAEb,WAAW,OAAO,UAAU;AAAA,MAC1B,MAAM,SAAS,MAAM,OAAO,KAAK,YAAY;AAAA,QAC3C,SAAS;AAAA,QACT,MAAM;AAAA,QACN,WAAW,SAAS;AAAA,QACpB,iBAAiB,SAAS;AAAA,QAC1B,cAAc,SAAS;AAAA,QACvB,cAAc,SAAS;AAAA,QACvB,QAAQ,SAAS,UAAU;AAAA,QAC3B,aAAa,SAAS;AAAA,QACtB,QAAQ,SAAS;AAAA,MACnB,CAAC;AAAA,MAED,SAAS,OAAO;AAAA,IAClB;AAAA,IAEA,OAAO,EAAE,IAAI,QAAQ,UAAU;AAAA;AAAA,OAG3B,aAAY,CAChB,WACA,WACA,OACA,WACe;AAAA,IACf,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAGA,MAAM,aAAa,MAAM,QAAQ,MAAM,EAAE,EAAE,QAAQ,MAAM,EAAE;AAAA,IAE3D,MAAM,OAAO,UAAU,IAAI;AAAA,MACzB,SAAS;AAAA,MACT,WAAW;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAAA;AAAA,OAGG,eAAc,CAClB,WACA,WACA,OACA,WACe;AAAA,IACf,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,aAAa,MAAM,QAAQ,MAAM,EAAE,EAAE,QAAQ,MAAM,EAAE;AAAA,IAE3D,MAAM,OAAO,UAAU,OAAO;AAAA,MAC5B,SAAS;AAAA,MACT,WAAW;AAAA,MACX,MAAM;AAAA,IACR,CAAC;AAAA;AAAA,OAGG,YAAW,CACf,WACA,WACA,MACA,WACe;AAAA,IACf,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,OAAO,KAAK,OAAO;AAAA,MACvB,SAAS;AAAA,MACT,IAAI;AAAA,MACJ;AAAA,IACF,CAAC;AAAA;AAAA,OAGG,cAAa,CACjB,WACA,WACA,WACe;AAAA,IACf,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,OAAO,KAAK,OAAO;AAAA,MACvB,SAAS;AAAA,MACT,IAAI;AAAA,IACN,CAAC;AAAA;AAAA,OAGG,WAAU,CACd,WACA,WACA,WACe;AAAA,IACf,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,OAAO,KAAK,IAAI;AAAA,MACpB,SAAS;AAAA,MACT,WAAW;AAAA,IACb,CAAC;AAAA;AAAA,OAGG,aAAY,CAChB,WACA,WACA,WACe;AAAA,IACf,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,OAAO,KAAK,OAAO;AAAA,MACvB,SAAS;AAAA,MACT,WAAW;AAAA,IACb,CAAC;AAAA;AAAA,OAGG,SAAQ,CACZ,WACA,WACyB;AAAA,IACzB,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,SAAS,MAAM,OAAO,KAAK,KAAK,EAAE,SAAS,UAAU,CAAC;AAAA,IAE5D,QAAQ,OAAO,SAAS,CAAC,GACtB,OACC,CAAC,SACC,KAAK,SAAS,cAAa,aAAa,SAAQ,CAAC,CAAC,KAAK,OAC3D,EACC,IAAI,CAAC,UAAU;AAAA,MACd,MAAM,KAAK,QAAQ;AAAA,MACnB,SAAS,KAAK,QAAQ;AAAA,MACtB,IAAI,KAAK,QAAQ;AAAA,MACjB,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK,QAAQ;AAAA,MACnB,UAAU,KAAK,QAAQ;AAAA,MACvB,YAAY,KAAK,QAAQ;AAAA,MACzB,iBAAiB,KAAK,QAAQ;AAAA,MAC9B,aAAa,KAAK,QAAQ;AAAA,MAC1B,WAAW,KAAK,QAAQ;AAAA,MAGxB,OAAO,KAAK,QAAQ;AAAA,MACpB,aAAa,KAAK,QAAQ;AAAA,MAC1B,QAAQ,KAAK,QAAQ;AAAA,IACvB,EAAE;AAAA;AAAA,OAGA,YAAW,CACf,WACA,SACA,WACyB;AAAA,IACzB,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,SAAS,MAAM,OAAO,cAAc,QAAQ;AAAA,MAChD,SAAS;AAAA,MACT,OAAO,SAAS,SAAS;AAAA,MACzB,QAAQ,SAAS;AAAA,MACjB,QAAQ,SAAS;AAAA,IACnB,CAAC;AAAA,IAED,QAAQ,OAAO,YAAY,CAAC,GAAG,IAAI,CAAC,SAAS;AAAA,MAC3C,MAAM,IAAI;AAAA,MACV,SAAS,IAAI;AAAA,MACb,IAAI,IAAI;AAAA,MACR,MAAM,IAAI;AAAA,MACV,MAAM,IAAI;AAAA,MACV,UAAU,IAAI;AAAA,MACd,YAAY,IAAI;AAAA,MAChB,iBAAiB,IAAI;AAAA,MACrB,aAAa,IAAI;AAAA,MACjB,WAAW,IAAI;AAAA,MAGf,OAAO,IAAI;AAAA,MACX,aAAa,IAAI;AAAA,MACjB,QAAQ,IAAI;AAAA,IACd,EAAE;AAAA;AAAA,OAGE,aAAY,CAChB,SAIA,WACyB;AAAA,IACzB,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,SAAS,MAAM,OAAO,cAAc,KAAK;AAAA,MAC7C,OAAO,SAAS,SAAS;AAAA,MACzB,OAAO,SAAS,SAAS;AAAA,IAC3B,CAAC;AAAA,IAED,QAAQ,OAAO,YAAY,CAAC,GAAG,IAAI,CAAC,QAAQ;AAAA,MAC1C,IAAI,GAAG,MAAM;AAAA,MACb,MAAM,GAAG,QAAQ;AAAA,MACjB,WAAW,GAAG,cAAc;AAAA,MAC5B,SAAS,GAAG,YAAY;AAAA,MACxB,MAAM,GAAG,SAAS;AAAA,MAClB,QAAQ,GAAG,WAAW;AAAA,MACtB,WAAW,GAAG,cAAc;AAAA,MAC5B,YAAY,GAAG,eAAe;AAAA,MAC9B,WAAW,GAAG,cAAc;AAAA,MAC5B,UAAU,GAAG,aAAa;AAAA,MAC1B,aAAa,GAAG,iBAAiB;AAAA,MACjC,UAAU,GAAG,aAAa;AAAA,MAC1B,OAAO,GAAG,QACN;AAAA,QACE,OAAO,GAAG,MAAM,SAAS;AAAA,QACzB,SAAS,GAAG,MAAM,WAAW;AAAA,QAC7B,SAAS,GAAG,MAAM,YAAY;AAAA,MAChC,IACA;AAAA,MACJ,SAAS,GAAG,UACR;AAAA,QACE,OAAO,GAAG,QAAQ,SAAS;AAAA,QAC3B,SAAS,GAAG,QAAQ,WAAW;AAAA,QAC/B,SAAS,GAAG,QAAQ,YAAY;AAAA,MAClC,IACA;AAAA,MACJ,YAAY,GAAG;AAAA,MACf,SAAS,GAAG,WAAW;AAAA,MACvB,SAAS,GAAG,WAAW;AAAA,IACzB,EAAE;AAAA;AAAA,OAGE,aAAY,CAChB,WACiC;AAAA,IACjC,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,SAAS,MAAM,OAAO,MAAM,KAAK;AAAA,IACvC,OAAQ,OAAO,SAAS,CAAC;AAAA;AAAA,OAGrB,WAAU,CACd,WACA,SACA,UACA,SACA,WACgD;AAAA,IAChD,MAAM,SAAS,KAAK,oBAAoB,SAAS;AAAA,IACjD,IAAI,CAAC,QAAQ;AAAA,MACX,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AAAA,IAEA,MAAM,SAAS,MAAM,OAAO,MAAM,SAAS;AAAA,MACzC,YAAY;AAAA,MACZ,SAAS,OAAO,YAAY,WAAW,UAAU;AAAA,MACjD,MAAM,OAAO,YAAY,WAAW,UAAU;AAAA,MAC9C;AAAA,MACA,OAAO,SAAS;AAAA,MAChB,iBAAiB,SAAS;AAAA,MAC1B,WAAW,SAAS;AAAA,IACtB,CAAC;AAAA,IAED,MAAM,iBAAiB;AAAA,IAGvB,MAAM,OAAO,eAAe;AAAA,IAC5B,OAAO;AAAA,MACL,QAAQ,MAAM,MAAM;AAAA,MACpB,WAAW,MAAM,aAAa;AAAA,IAChC;AAAA;AAAA,EAGM,YAAY,CAAC,MAAwB;AAAA,IAC3C,IAAI,KAAK,UAAU,0BAA0B;AAAA,MAC3C,OAAO,CAAC,IAAI;AAAA,IACd;AAAA,IAEA,MAAM,WAAqB,CAAC;AAAA,IAC5B,IAAI,YAAY;AAAA,IAEhB,OAAO,UAAU,SAAS,GAAG;AAAA,MAC3B,IAAI,UAAU,UAAU,0BAA0B;AAAA,QAChD,SAAS,KAAK,SAAS;AAAA,QACvB;AAAA,MACF;AAAA,MAGA,IAAI,aAAa;AAAA,MAEjB,MAAM,cAAc,UAAU,YAAY;AAAA,GAAM,wBAAwB;AAAA,MACxE,IAAI,cAAc,2BAA2B,GAAG;AAAA,QAC9C,aAAa,cAAc;AAAA,MAC7B,EAAO;AAAA,QACL,MAAM,YAAY,UAAU,YAAY,KAAK,wBAAwB;AAAA,QACrE,IAAI,YAAY,2BAA2B,GAAG;AAAA,UAC5C,aAAa,YAAY;AAAA,QAC3B;AAAA;AAAA,MAGF,SAAS,KAAK,UAAU,MAAM,GAAG,UAAU,CAAC;AAAA,MAC5C,YAAY,UAAU,MAAM,UAAU;AAAA,IACxC;AAAA,IAEA,OAAO;AAAA;AAAA,EAMT,iBAAiB,CAAC,WAAmB,WAAiC;AAAA,IACpE,IAAI,iBAAiB,SAAS,GAAG;AAAA,MAC/B,KAAK,+BAA+B,SAAS,EAAE,IAAI,SAAS;AAAA,IAC9D;AAAA;AAAA,EAMF,oBAAoB,CAAC,WAAmB,WAAiC;AAAA,IACvE,KAAK,+BAA+B,SAAS,EAAE,OAAO,SAAS;AAAA;AAAA,EAMjE,oBAAoB,CAAC,WAAqC;AAAA,IACxD,OAAO;AAAA,MACL,GAAG,KAAK,+BAA+B,SAAS;AAAA,MAChD,GAAG,KAAK,+BAA+B,SAAS;AAAA,IAClD;AAAA;AAAA,EAMF,kBAAkB,GAAY;AAAA,IAC5B,OAAO,KAAK,eAAe,KAAK,QAAQ;AAAA;AAAA,EAM1C,YAAY,GAAkB;AAAA,IAC5B,OAAO,KAAK;AAAA;AAAA,EAMd,SAAS,GAAkB;AAAA,IACzB,OAAO,KAAK;AAAA;AAAA,EAMd,cAAc,GAAS;AAAA,IACrB,KAAK,UAAU,MAAM;AAAA;AAAA,EAMvB,iBAAiB,GAAS;AAAA,IACxB,KAAK,aAAa,MAAM;AAAA;AAE5B;;;AEzrGA,oBAA6B;AAI7B,IAAM,oCAAoC;AAM1C,IAAM,YAAY,CAAC,YAAY,gBAAgB;AAAA;AAExC,MAAM,wCAAwC,SAAQ;AAAA,SAClC,cAAc;AAAA,EAC9B,wBACP;AAAA,cAEW,MAAK,CAChB,SAC0C;AAAA,IAC1C,OAAO,IAAI,gCAAgC,OAAO;AAAA;AAAA,OAG9C,KAAI,GAAkB;AAAA,OAEtB,QAAO,CACX,SACA,UACmC;AAAA,IAKnC,MAAM,WAAW,KAAK,QAAQ,WAAW,iBAAiB;AAAA,IAG1D,MAAM,YAAY,KAAK,QAAQ,WAAW,kBAAkB;AAAA,IAG5D,IAAI,aAAa,cAAc,UAAU,KAAK,GAAG;AAAA,MAC/C,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM,EAAE,aAAa,SAAS,KAAK,EAAE;AAAA,MACvC;AAAA,IACF;AAAA,IACA,IAAI,aAAa,oBAAoB,WAAW,KAAK,GAAG;AAAA,MACtD,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM,EAAE,aAAa,UAAU,KAAK,EAAE;AAAA,MACxC;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,EAGT,oBAAoB,CAAC,WAGnB;AAAA,IACA,OAAO;AAAA,MACL,WAAW,UAAU,OAAO,CAAC,MAAM,UAAU,SAAS,CAAC,CAAC;AAAA,MACxD,aAAa,UAAU,OAAO,CAAC,MAAM,CAAC,UAAU,SAAS,CAAC,CAAC;AAAA,IAC7D;AAAA;AAEJ;;;APpDA,IAAM,cAAsB;AAAA,EAC1B,MAAM;AAAA,EACN,aAAa;AAAA,EACb,UAAU,CAAC,cAAc,+BAA+B;AAAA,EACxD,SAAS,CAAC;AAAA,EACV,WAAW,CAAC;AAAA,EAIZ,YAAY;AAAA,IACV,eAAe,CAAC,OAAO;AAAA,EACzB;AAAA,EACA,MAAM,OAAO,SAAiC,YAA2B;AAAA,IAIvE,IAAI;AAAA,MACF,MAAM,UAAU,2BAA2B,OAAO;AAAA,MAClD,QAAQ,iBAAiB,oCAAoC,OAAO,CAAC;AAAA,MACrE,OAAO,KAAK;AAAA,MACZ,QAAO,KACL;AAAA,QACE,KAAK;AAAA,QACL,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACtD,GACA,gEACF;AAAA;AAAA,IAGF,MAAM,WAAW,QAAQ,WAAW,iBAAiB;AAAA,IACrD,MAAM,WAAW,QAAQ,WAAW,iBAAiB;AAAA,IACrD,MAAM,gBAAgB,QAAQ,WAAW,sBAAsB;AAAA,IAC/D,MAAM,YAAY,QAAQ,WAAW,kBAAkB;AAAA,IACvD,MAAM,aAAa,QAAQ,WAAW,mBAAmB;AAAA,IACzD,MAAM,oBAAoB,QAAQ,WAChC,kCACF;AAAA,IACA,MAAM,wBAAwB,QAAQ,WACpC,uCACF;AAAA,IAGA,MAAM,YAAY,CAAC,UAAsC;AAAA,MACvD,IAAI,CAAC,SAAS,MAAM,KAAK,MAAM;AAAA,QAAI,OAAO;AAAA,MAC1C,IAAI,MAAM,UAAU;AAAA,QAAG,OAAO;AAAA,MAC9B,OAAO,GAAG,MAAM,MAAM,GAAG,CAAC,OAAO,MAAM,MAAM,EAAE;AAAA;AAAA,IAGjD,QAAO,KACL;AAAA,MACE,KAAK;AAAA,MACL,SAAS,QAAQ;AAAA,MACjB,UAAU;AAAA,QACR,UAAU,UAAU,QAAQ;AAAA,QAC5B,UAAU,UAAU,QAAQ;AAAA,QAC5B,eAAe,gBAAgB,UAAU;AAAA,QACzC,WAAW,UAAU,SAAS;AAAA,QAC9B,YAAY,cAAc;AAAA,QAC1B,mBAAmB,qBAAqB;AAAA,QACxC,uBAAuB,yBAAyB;AAAA,MAClD;AAAA,IACF,GACA,2BACF;AAAA,IAEA,IAAI,CAAC,YAAY,SAAS,KAAK,MAAM,IAAI;AAAA,MACvC,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,kFACF;AAAA,MACA,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,iFACF;AAAA,MACA;AAAA,IACF;AAAA,IAEA,IAAI,CAAC,YAAY,SAAS,KAAK,MAAM,IAAI;AAAA,MACvC,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,0DACF;AAAA,MACA,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,yEACF;AAAA,MACA;AAAA,IACF;AAAA,IAGA,IAAI,CAAC,SAAS,WAAW,OAAO,GAAG;AAAA,MACjC,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,sEACF;AAAA,IACF;AAAA,IAEA,IAAI,CAAC,SAAS,WAAW,OAAO,GAAG;AAAA,MACjC,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,sEACF;AAAA,IACF;AAAA,IAEA,IAAI,aAAa,CAAC,UAAU,WAAW,OAAO,GAAG;AAAA,MAC/C,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,uEACF;AAAA,IACF;AAAA,IAEA,QAAO,KACL,EAAE,KAAK,gBAAgB,SAAS,QAAQ,QAAQ,GAChD,mDACF;AAAA;AAEJ;AAEA,IAAe;",
|
|
15
|
-
"debugId": "3501C22F83015CAC64756E2164756E21",
|
|
16
|
-
"names": []
|
|
17
|
-
}
|