@finalai/final-agent-provider 0.6.2 → 0.7.0

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.
Files changed (94) hide show
  1. package/HOSTING.md +4 -4
  2. package/README.md +94 -2
  3. package/dist/modules/authoring-final-channel.mjs +2 -2
  4. package/dist/modules/authoring-final-channel.mjs.map +2 -2
  5. package/dist/modules/channel-factories.d.mts +5 -7
  6. package/dist/modules/channel-factories.mjs +4 -50
  7. package/dist/modules/channel-factories.mjs.map +2 -2
  8. package/dist/modules/channels/channel-utils.d.mts +132 -0
  9. package/dist/modules/channels/channel-utils.mjs +445 -0
  10. package/dist/modules/channels/channel-utils.mjs.map +7 -0
  11. package/dist/modules/channels/delivery.d.mts +5 -5
  12. package/dist/modules/channels/delivery.mjs.map +1 -1
  13. package/dist/modules/channels/direct-messaging.d.mts +2 -2
  14. package/dist/modules/channels/direct-messaging.mjs.map +2 -2
  15. package/dist/modules/channels/discord-dispatch.d.mts +17 -0
  16. package/dist/modules/channels/discord-dispatch.mjs +139 -0
  17. package/dist/modules/channels/discord-dispatch.mjs.map +7 -0
  18. package/dist/modules/channels/discord-gateway.d.mts +19 -0
  19. package/dist/modules/channels/discord-gateway.mjs +233 -0
  20. package/dist/modules/channels/discord-gateway.mjs.map +7 -0
  21. package/dist/modules/channels/discord.d.mts +9 -0
  22. package/dist/modules/channels/discord.mjs +904 -0
  23. package/dist/modules/channels/discord.mjs.map +7 -0
  24. package/dist/modules/channels/fake-platform.d.mts +2 -7
  25. package/dist/modules/channels/fake-platform.mjs +2 -38
  26. package/dist/modules/channels/fake-platform.mjs.map +2 -2
  27. package/dist/modules/channels/github.d.mts +5 -0
  28. package/dist/modules/channels/github.mjs +720 -0
  29. package/dist/modules/channels/github.mjs.map +7 -0
  30. package/dist/modules/channels/group-messaging.d.mts +2 -2
  31. package/dist/modules/channels/group-messaging.mjs.map +2 -2
  32. package/dist/modules/channels/index.d.mts +7 -3
  33. package/dist/modules/channels/index.mjs +7 -3
  34. package/dist/modules/channels/index.mjs.map +2 -2
  35. package/dist/modules/channels/linear.d.mts +4 -0
  36. package/dist/modules/channels/linear.mjs +621 -0
  37. package/dist/modules/channels/linear.mjs.map +7 -0
  38. package/dist/modules/channels/messaging-channel.d.mts +3 -3
  39. package/dist/modules/channels/messaging-channel.mjs +2 -2
  40. package/dist/modules/channels/messaging-channel.mjs.map +2 -2
  41. package/dist/modules/channels/phone.d.mts +8 -0
  42. package/dist/modules/channels/phone.mjs +382 -0
  43. package/dist/modules/channels/phone.mjs.map +7 -0
  44. package/dist/modules/channels/projection.mjs.map +1 -1
  45. package/dist/modules/channels/reply-receipts.d.mts +31 -0
  46. package/dist/modules/channels/reply-receipts.mjs +63 -0
  47. package/dist/modules/channels/reply-receipts.mjs.map +7 -0
  48. package/dist/modules/channels/routing.d.mts +1 -0
  49. package/dist/modules/channels/routing.mjs +5 -1
  50. package/dist/modules/channels/routing.mjs.map +2 -2
  51. package/dist/modules/channels/slack.d.mts +7 -0
  52. package/dist/modules/channels/slack.mjs +1134 -0
  53. package/dist/modules/channels/slack.mjs.map +7 -0
  54. package/dist/modules/channels/voice-recording.d.mts +7 -0
  55. package/dist/modules/channels/voice-recording.mjs +49 -0
  56. package/dist/modules/channels/voice-recording.mjs.map +7 -0
  57. package/dist/modules/channels/voice.d.mts +33 -0
  58. package/dist/modules/channels/voice.mjs +851 -0
  59. package/dist/modules/channels/voice.mjs.map +7 -0
  60. package/dist/modules/channels/webhook.d.mts +5 -0
  61. package/dist/modules/channels/webhook.mjs +76 -0
  62. package/dist/modules/channels/webhook.mjs.map +7 -0
  63. package/dist/modules/harnesses/acp-describe.mjs +1 -1
  64. package/dist/modules/harnesses/acp-describe.mjs.map +2 -2
  65. package/dist/modules/harnesses/config-fields.d.mts +6 -1
  66. package/dist/modules/harnesses/config-fields.mjs +7 -0
  67. package/dist/modules/harnesses/config-fields.mjs.map +3 -3
  68. package/dist/modules/harnesses/fidelity.mjs +17 -17
  69. package/dist/modules/harnesses/fidelity.mjs.map +2 -2
  70. package/dist/modules/harnesses/remote-claude-code.d.mts +14 -2
  71. package/dist/modules/harnesses/remote-claude-code.mjs +5 -3
  72. package/dist/modules/harnesses/remote-claude-code.mjs.map +2 -2
  73. package/dist/modules/harnesses/remote-url.mjs.map +1 -1
  74. package/dist/modules/harnesses/serverless-nanocode-codex.d.mts +3 -1
  75. package/dist/modules/harnesses/serverless-nanocode-codex.mjs +6 -0
  76. package/dist/modules/harnesses/serverless-nanocode-codex.mjs.map +2 -2
  77. package/dist/modules/runtime/remote-host.mjs.map +1 -1
  78. package/dist/modules/sandboxes/build-scripts.mjs.map +1 -1
  79. package/dist/modules/sandboxes/paths.mjs.map +1 -1
  80. package/dist/modules/testing/harness.mjs +2 -2
  81. package/dist/modules/testing/harness.mjs.map +1 -1
  82. package/package.json +45 -19
  83. package/dist/modules/channels/address-context.d.mts +0 -7
  84. package/dist/modules/channels/address-context.mjs +0 -80
  85. package/dist/modules/channels/address-context.mjs.map +0 -7
  86. package/dist/modules/channels/agent-events.d.mts +0 -103
  87. package/dist/modules/channels/agent-events.mjs +0 -341
  88. package/dist/modules/channels/agent-events.mjs.map +0 -7
  89. package/dist/modules/channels/agent-schedules.d.mts +0 -25
  90. package/dist/modules/channels/agent-schedules.mjs +0 -96
  91. package/dist/modules/channels/agent-schedules.mjs.map +0 -7
  92. package/dist/modules/channels/service-input.d.mts +0 -22
  93. package/dist/modules/channels/service-input.mjs +0 -32
  94. package/dist/modules/channels/service-input.mjs.map +0 -7
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/channels/slack.ts"],
4
+ "sourcesContent": ["import {\n defineChannel,\n packageRef,\n jsonValueSchema,\n type ChannelEventContextIface,\n type ChannelReceiveContextIface,\n type JsonObject,\n type JsonValue,\n type PlaceRef,\n type PrincipalRef,\n type Refusal,\n type ChannelReceiveResult,\n principalRefSchema,\n} from '@finalai/agent-provider';\nimport * as z from 'zod';\nimport {\n mirrorReceiptKey,\n settleMirrorReaction,\n shareReplyReceipt,\n type MirrorReactionResult,\n} from \"./reply-receipts.mjs\";\nimport { emojiToName, nameToEmoji } from 'gemoji';\nimport {\n channelBaseUrl,\n addSharedReaction,\n removeSharedReaction,\n providerPlaceKey,\n confirmOAuth,\n deliveryRetention,\n decisionChoices,\n decisionSummary,\n externalKey,\n freshTimestamp,\n inTenant,\n providerOriginSchema,\n parseJson,\n personFor,\n receivePersonMessage,\n receipt,\n refString,\n responseJson,\n startOAuth,\n stateKey,\n takeOAuth,\n textOf,\n completionText,\n verifyHmac,\n} from \"./channel-utils.mjs\";\n\nconst configSchema = z.object({\n baseUrl: z.string().url().optional(),\n history: z.union([z.literal('none'), z.literal('linked-members')]).default('none'),\n});\ntype Config = z.infer<typeof configSchema>;\nconst envelopeSchema = z.object({\n type: z.string().optional(),\n team_id: z.string().optional(),\n enterprise_id: z.string().nullish(),\n event_id: z.string().optional(),\n event: z.record(z.string(), jsonValueSchema).optional(),\n challenge: z.string().optional(),\n});\nconst messageSchema = z.object({\n type: z.string(),\n subtype: z.string().optional(),\n user: z.string().optional(),\n channel: z.string().optional(),\n channel_type: z.string().optional(),\n text: z.string().optional(),\n ts: z.string().optional(),\n thread_ts: z.string().optional(),\n bot_id: z.string().optional(),\n});\nconst slackEmoji = (emoji: string): string | null => {\n const name = emoji.replace(/^:|:$/g, '');\n if (/^[a-z0-9_+-]+(?:::skin-tone-[2-6])?$/i.test(name)) return name;\n const modifiers = [...emoji].filter((character) => /\\p{Emoji_Modifier}/u.test(character));\n if (modifiers.length > 1) return null;\n const base = emoji.replace(/\\p{Emoji_Modifier}/gu, '');\n const alias =\n (Object.hasOwn(emojiToName, base) ? emojiToName[base] : undefined) ??\n emojiToName[base + '\\ufe0f'] ??\n emojiToName[base.replace(/\\ufe0f/g, '')];\n if (typeof alias !== 'string') return null;\n const modifier = modifiers[0]?.codePointAt(0);\n return alias + (modifier == null ? '' : `::skin-tone-${modifier - 0x1f3f9}`);\n};\nconst finalEmoji = (name: string): string => {\n const match = /^(.+?)(?:::skin-tone-([2-6]))?$/.exec(name);\n if (match == null || match[1] == null) return `:${name}:`;\n const emoji = Object.hasOwn(nameToEmoji, match[1]) ? nameToEmoji[match[1]] : undefined;\n if (emoji == null) return `:${name}:`;\n if (match[2] == null) return emoji;\n const characters = [...emoji];\n characters.splice(1, 0, String.fromCodePoint(0x1f3f9 + Number(match[2])));\n return characters.join('');\n};\nconst safeSlackText = (text: string): string =>\n text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\nconst slackResponseSchema = z.looseObject({ ok: z.boolean(), error: z.string().optional() });\nconst api = async (\n ctx: Pick<ChannelReceiveContextIface<Config>, 'credentials'> &\n Partial<Pick<ChannelEventContextIface<Config>, 'origin'>>,\n method: string,\n body: JsonObject,\n): Promise<unknown> => {\n const app = await ctx.credentials.app({ tenant: ctx.origin?.place.tenant });\n const read = ['users.info', 'conversations.history', 'conversations.replies'].includes(method);\n const url = new URL(`https://slack.com/api/${method}`);\n if (read)\n for (const [key, value] of Object.entries(body))\n if (value != null)\n url.searchParams.set(key, typeof value === 'string' ? value : JSON.stringify(value));\n const data = await responseJson(\n await ctx.credentials.fetch(url, {\n method: read ? 'GET' : 'POST',\n headers: {\n authorization: `Bearer ${app.accessToken}`,\n ...(!read ? { 'content-type': 'application/json' } : {}),\n },\n ...(read\n ? {}\n : {\n body: JSON.stringify({\n ...body,\n ...(typeof body.text === 'string' ? { text: safeSlackText(body.text) } : {}),\n }),\n }),\n }),\n );\n const status = slackResponseSchema.parse(data);\n const repeated =\n (method === 'reactions.add' && status.error === 'already_reacted') ||\n (method === 'reactions.remove' && status.error === 'no_reaction') ||\n (method === 'chat.delete' && status.error === 'message_not_found') ||\n (method === 'chat.update' &&\n (status.error === 'message_not_modified' || status.error === 'message_not_found'));\n if (!status.ok && !repeated)\n throw new Error(`Slack ${method}: ${status.error ?? 'unknown error'}`, {\n cause: { code: status.error ?? 'unknown_error' },\n });\n return data;\n};\nconst classifyMirrorReaction = async (cause: unknown): Promise<MirrorReactionResult> => {\n const error = z\n .object({ code: z.string() })\n .safeParse(cause instanceof Error ? cause.cause : null);\n if (!error.success) return 'retry';\n if (error.data.code === 'message_not_found') return 'missing';\n return [\n 'missing_scope',\n 'not_in_channel',\n 'channel_not_found',\n 'no_permission',\n 'restricted_action',\n 'not_allowed_token_type',\n 'invalid_name',\n 'thread_locked',\n 'not_reactable',\n 'is_archived',\n 'team_access_not_granted',\n 'no_access',\n 'too_many_reactions',\n 'too_many_emoji',\n 'bad_timestamp',\n ].includes(error.data.code)\n ? 'unavailable'\n : 'retry';\n};\nconst responseUrl = (value: string | undefined): string | null => {\n if (value == null) return null;\n try {\n const url = new URL(value);\n return url.protocol === 'https:' &&\n url.hostname === 'hooks.slack.com' &&\n url.port === '' &&\n url.username === '' &&\n url.password === '' &&\n /^\\/(?:actions|commands|services)\\//.test(url.pathname)\n ? url.href\n : null;\n } catch {\n return null;\n }\n};\ninterface DecisionNoticeIface {\n ctx: Pick<ChannelReceiveContextIface<Config>, 'credentials' | 'store' | 'log'> &\n Partial<Pick<ChannelEventContextIface<Config>, 'origin'>>;\n decisionId: string;\n message?: string;\n channel?: string;\n user?: string;\n threadTs?: string;\n}\nconst confirmDecision = async (args: DecisionNoticeIface): Promise<void> => {\n const { ctx, decisionId } = args;\n const key = stateKey('slack-decision-confirmed', decisionId);\n const prior = await ctx.store.get(key);\n const metadata = z\n .object({ url: z.string() })\n .safeParse(await ctx.store.get(stateKey('slack-decision-message', decisionId)));\n const url = metadata.success ? responseUrl(metadata.data.url) : null;\n if (url != null && prior !== 'replaced') {\n try {\n const response = await ctx.credentials.fetch(url, {\n method: 'POST',\n redirect: 'error',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n replace_original: true,\n text: args.message ?? 'This decision has been answered in Final.',\n blocks: [],\n }),\n });\n await response.text();\n if (!response.ok) throw new Error('Slack approval confirmation unavailable.');\n await ctx.store.set(key, 'replaced', { ttlSeconds: 3600 });\n return;\n } catch {\n ctx.log('Slack approval replacement unavailable.');\n }\n }\n if (prior != null || args.channel == null || args.user == null) return;\n try {\n await api(ctx, 'chat.postEphemeral', {\n channel: args.channel,\n user: args.user,\n ...(args.threadTs == null ? {} : { thread_ts: args.threadTs }),\n text: args.message ?? 'This decision has been answered in Final.',\n });\n await ctx.store.set(key, 'notified', { ttlSeconds: 3600 });\n } catch {\n ctx.log('Slack approval confirmation unavailable.');\n }\n};\nconst slackUserSchema = z.object({\n user: z.object({\n id: z.string(),\n name: z.string().optional(),\n deleted: z.boolean().optional(),\n enterprise_user: z.object({ id: z.string(), enterprise_id: z.string() }).optional(),\n profile: z\n .object({ display_name: z.string().optional(), real_name: z.string().optional() })\n .optional(),\n }),\n});\nconst enterpriseTeamsSchema = z.object({\n teams: z.array(z.string()).max(256),\n overflow: z.boolean(),\n});\nconst proveTeam = async (\n ctx: ChannelReceiveContextIface<Config>,\n team: string,\n enterprise: string,\n): Promise<void> => {\n await ctx.store.set(stateKey('slack-enterprise', team), enterprise);\n const key = stateKey('slack-enterprise-teams', enterprise);\n const saved = enterpriseTeamsSchema.safeParse(await ctx.store.get(key));\n if (saved.success && (saved.data.overflow || saved.data.teams.includes(team))) return;\n const teams = [...(saved.success ? saved.data.teams : []), team];\n // Overflow retains no incomplete set: the next workspace revocation revokes the enterprise proof.\n await ctx.store.set(\n key,\n teams.length > 256 ? { teams: [], overflow: true } : { teams, overflow: false },\n );\n};\nconst revokeTeam = async (args: {\n ctx: ChannelReceiveContextIface<Config>;\n team: string;\n enterprise?: string;\n reason: 'uninstalled' | 'provider-revoked';\n}): Promise<void> => {\n const { ctx, team, reason } = args;\n const alias = z.string().safeParse(await ctx.store.get(stateKey('slack-enterprise', team)));\n const enterprise = args.enterprise ?? (alias.success ? alias.data : undefined);\n await ctx.people.revoke({ tenant: team, reason });\n if (enterprise != null && enterprise !== team) {\n const key = stateKey('slack-enterprise-teams', enterprise);\n const saved = enterpriseTeamsSchema.safeParse(await ctx.store.get(key));\n const teams = saved.success ? saved.data.teams.filter((known) => known !== team) : [];\n if (!saved.success || saved.data.overflow || teams.length === 0) {\n await ctx.people.revoke({ tenant: enterprise, reason });\n await ctx.store.set(key, { teams: [], overflow: false });\n } else await ctx.store.set(key, { teams, overflow: false });\n }\n await ctx.store.set(stateKey('slack-enterprise', team), null);\n await ctx.store.set(stateKey('slack-bot-user', team), null);\n};\nconst principalFor = async (\n ctx: ChannelReceiveContextIface<Config>,\n team: string,\n user: string,\n): Promise<PrincipalRef> => {\n const profile = slackUserSchema.parse(\n await api(inTenant(ctx, team), 'users.info', { user }),\n ).user;\n if (profile.enterprise_user != null)\n await proveTeam(ctx, team, profile.enterprise_user.enterprise_id);\n if (profile.deleted === true)\n await ctx.people.revoke({\n principal: {\n id: profile.enterprise_user?.id ?? profile.id,\n tenant: profile.enterprise_user?.enterprise_id ?? team,\n },\n reason: 'deactivated',\n });\n return {\n id: profile.enterprise_user?.id ?? profile.id,\n tenant: profile.enterprise_user?.enterprise_id ?? team,\n displayName:\n [profile.profile?.display_name, profile.profile?.real_name, profile.name, profile.id].find(\n (name) => name != null && name.trim().length > 0,\n ) ?? profile.id,\n };\n};\nconst placeFor = (message: z.infer<typeof messageSchema>, tenant: string): PlaceRef | null => {\n if (message.channel == null) return null;\n const channel: PlaceRef = {\n kind: message.channel_type === 'im' || message.channel.startsWith('D') ? 'dm' : 'channel',\n id: message.channel,\n tenant,\n title: message.channel,\n };\n return message.thread_ts == null\n ? channel\n : {\n kind: 'thread',\n id: `${message.channel}:${message.thread_ts}`,\n tenant,\n parent: channel,\n title: message.channel,\n };\n};\nconst location = (ctx: ChannelEventContextIface<Config>) => ({\n channel:\n refString(ctx.origin.ref, 'channel') ??\n (ctx.origin.place.kind === 'thread'\n ? (ctx.origin.place.parent?.id ?? ctx.origin.place.id.split(':')[0])\n : ctx.origin.place.id),\n thread_ts:\n refString(ctx.origin.ref, 'threadTs') ??\n refString(ctx.origin.ref, 'ts') ??\n (ctx.origin.place.kind === 'thread' ? ctx.origin.place.id.split(':').at(-1) : null),\n});\nconst botFor = async (\n ctx: ChannelReceiveContextIface<Config>,\n tenant: string,\n): Promise<string | undefined> => {\n const key = stateKey('slack-bot-user', tenant);\n const cached = z.string().safeParse(await ctx.store.get(key));\n if (cached.success) return cached.data;\n const bot = z\n .object({ user_id: z.string().optional() })\n .parse(await api(ctx, 'auth.test', {})).user_id;\n if (bot != null) await ctx.store.set(key, bot, deliveryRetention);\n return bot;\n};\nconst normalizedText = async (\n ctx: ChannelReceiveContextIface<Config>,\n text: string,\n tenant: string,\n): Promise<string> => {\n const bot = await botFor(ctx, tenant);\n return text\n .replace(/<@([A-Z0-9]+)>/g, (_match: string, id: string) => (id === bot ? '' : `@${id}`))\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&amp;/g, '&')\n .trim();\n};\nconst replySchema = z.object({ ts: z.string() });\nconst replyKey = (\n ctx: ChannelEventContextIface<Config>,\n replyOf?: { externalKey: string; turnId: string },\n) =>\n stateKey(\n 'slack-reply',\n replyOf?.externalKey ?? refString(ctx.origin.ref, 'externalKey') ?? ctx.origin.place.id,\n replyOf?.turnId ?? ctx.turn.id,\n );\nconst postReply = async (\n ctx: ChannelEventContextIface<Config>,\n text: string,\n final: boolean,\n key = replyKey(ctx),\n): Promise<void> => {\n const { channel, thread_ts } = location(ctx);\n if (channel == null) return;\n const saved = z\n .object({\n ts: z.string(),\n updatedAt: z.number(),\n final: z.boolean(),\n text: z.string().optional(),\n })\n .safeParse(await ctx.store.get(key));\n if (saved.success && saved.data.final) return;\n if (saved.success && !final && Date.now() - saved.data.updatedAt < 1_000) {\n await ctx.store.set(key, { ...saved.data, text: text.slice(0, 11500) }, deliveryRetention);\n return;\n }\n const body = text.slice(0, 11_500) + (text.length > 11_500 ? '\\nContinue in Final \u2192' : '');\n if (body.length === 0) return;\n const posted = await api(ctx, saved.success ? 'chat.update' : 'chat.postMessage', {\n channel,\n ...(saved.success ? { ts: saved.data.ts } : thread_ts == null ? {} : { thread_ts }),\n text: body,\n });\n if (saved.success && slackResponseSchema.parse(posted).error === 'message_not_found') {\n await ctx.store.set(key, null);\n await postReply(ctx, text, final, key);\n return;\n }\n const ts = saved.success ? saved.data.ts : replySchema.parse(posted).ts;\n await ctx.store.set(\n key,\n { ts, updatedAt: Date.now(), final, text: text.slice(0, 11500) },\n deliveryRetention,\n );\n await ctx.store.set(\n stateKey('slack-origin', ctx.origin.place.tenant ?? null, channel, ts),\n jsonValueSchema.parse({\n place: ctx.origin.place,\n externalKey: refString(ctx.origin.ref, 'externalKey') ?? ctx.origin.place.id,\n turnId: ctx.turn.id,\n }),\n deliveryRetention,\n );\n};\nconst savedPartial = async (ctx: ChannelEventContextIface<Config>): Promise<string> => {\n const receipt = z.object({ text: z.string() }).safeParse(await ctx.store.get(replyKey(ctx)));\n return receipt.success ? receipt.data.text : '';\n};\nconst sharedReply = async (\n ctx: ChannelEventContextIface<Config>,\n args: { text: string; final: boolean; messageIds: string[] },\n): Promise<void> => {\n const { channel, thread_ts } = location(ctx);\n await shareReplyReceipt({\n bindingId: ctx.binding.id,\n store: ctx.store,\n destination: stateKey(\n 'slack',\n ctx.origin.place.tenant ?? null,\n channel ?? null,\n thread_ts ?? null,\n ),\n messageIds: args.messageIds,\n originKey: replyKey(ctx),\n send: (key) => postReply(ctx, args.text, args.final, key),\n removeDuplicate: async (receipt, canonical) => {\n const saved = replySchema.safeParse(receipt);\n const target = replySchema.safeParse(canonical);\n if (saved.success && target.success && saved.data.ts !== target.data.ts && channel != null)\n await api(ctx, 'chat.delete', { channel, ts: saved.data.ts });\n },\n });\n};\nexport const slackChannel = (options: JsonObject = {}) => {\n const config = configSchema.parse(options);\n return defineChannel<Config, JsonValue, { text: string }>({\n name: 'slack',\n config,\n installed: packageRef('@finalai/final-agent-provider/channels/slack'),\n credentials: { app: 'slack' },\n identity: {\n kind: 'redirect',\n start: async (args, ctx) => {\n const app = await ctx.credentials.appInfo();\n return startOAuth(\n {\n ...args,\n authorizeUrl: 'https://slack.com/openid/connect/authorize',\n clientId: app.clientId,\n redirectUri: `${channelBaseUrl(config)}/b/${ctx.binding.id}/oauth/callback`,\n scope: 'openid profile',\n },\n ctx,\n );\n },\n },\n places: {\n kinds: ['dm', 'channel', 'thread'],\n defaults: (place) =>\n place.kind === 'dm'\n ? { create: 'direct-with-agent', replies: 'origin', audience: 'members' }\n : null,\n },\n routes: [\n {\n method: 'GET',\n path: '/oauth/callback',\n handler: async (ctx) => {\n const saved = await takeOAuth(ctx.request, ctx);\n if (saved == null)\n return new Response('Invalid or expired link request', { status: 400 });\n const app = await ctx.credentials.appInfo();\n const token = z.object({ ok: z.literal(true), access_token: z.string() }).parse(\n await responseJson(\n await ctx.credentials.fetch('https://slack.com/api/openid.connect.token', {\n method: 'POST',\n body: new URLSearchParams({\n client_id: app.clientId,\n client_secret: app.clientSecret,\n code: saved.code,\n redirect_uri: saved.redirectUri,\n grant_type: 'authorization_code',\n }),\n }),\n ),\n );\n const identity = z\n .object({\n ok: z.literal(true),\n sub: z.string(),\n 'https://slack.com/team_id': z.string(),\n 'https://slack.com/user_id': z.string().optional(),\n })\n .parse(\n await responseJson(\n await ctx.credentials.fetch('https://slack.com/api/openid.connect.userInfo', {\n headers: { authorization: `Bearer ${token.access_token}` },\n }),\n ),\n );\n const actual = await principalFor(\n ctx,\n identity['https://slack.com/team_id'],\n identity['https://slack.com/user_id'] ?? identity.sub,\n );\n const response = await confirmOAuth(\n { ticket: saved.ticket, expected: saved.principal, actual },\n ctx,\n );\n if (response.ok)\n await ctx.store.set(\n stateKey(\n 'slack-principal',\n identity['https://slack.com/team_id'],\n identity['https://slack.com/user_id'] ?? identity.sub,\n ),\n jsonValueSchema.parse(actual),\n deliveryRetention,\n );\n return response;\n },\n },\n {\n method: 'POST',\n path: '/webhook',\n handler: async (ctx) => {\n const body = await ctx.request.text();\n let raw: unknown = null;\n let completeJson = false;\n try {\n raw = JSON.parse(body);\n completeJson = true;\n } catch {\n // The signature does not authenticate Content-Type; complete JSON takes precedence.\n }\n if (\n !completeJson &&\n ctx.request.headers.get('content-type')?.includes('application/x-www-form-urlencoded')\n ) {\n const form = new URLSearchParams(body);\n raw = form.has('payload')\n ? parseJson(form.get('payload') ?? '')\n : Object.fromEntries(\n [...new Set(form.keys())].flatMap((key) => {\n const value = form.get(key);\n return value == null ? [] : [[key, value]];\n }),\n );\n }\n const app = await ctx.credentials.appInfo();\n const timestamp = ctx.request.headers.get('x-slack-request-timestamp');\n const signature = ctx.request.headers.get('x-slack-signature');\n if (\n app.signingSecret == null ||\n !freshTimestamp(timestamp) ||\n signature == null ||\n !signature.startsWith('v0=') ||\n !(await verifyHmac({\n secret: app.signingSecret,\n body: `v0:${timestamp}:${body}`,\n signature: signature.slice(3),\n }))\n )\n return new Response(null, { status: 401 });\n const envelope = envelopeSchema.safeParse(raw);\n if (\n envelope.success &&\n envelope.data.type === 'url_verification' &&\n envelope.data.challenge != null\n )\n return Response.json({ challenge: envelope.data.challenge });\n const slash = z\n .object({ command: z.literal('/final'), trigger_id: z.string() })\n .safeParse(raw);\n if (slash.success) {\n try {\n await ctx.receive(jsonValueSchema.parse(raw));\n const key = stateKey('slack-command-response', slash.data.trigger_id);\n const text = await ctx.store.get(key);\n await ctx.store.set(key, null);\n return Response.json({\n response_type: 'ephemeral',\n text: typeof text === 'string' ? text : 'Open Final to check this command.',\n });\n } catch {\n return Response.json({\n response_type: 'ephemeral',\n text: 'This command could not be completed. Open Final to check its state.',\n });\n }\n }\n await ctx.receive(jsonValueSchema.parse(raw));\n return new Response(null, { status: 200 });\n },\n },\n ],\n receive: async (input, baseContext) => {\n const tenant = z\n .object({ team_id: z.string().optional(), team: z.object({ id: z.string() }).optional() })\n .safeParse(input);\n const teamId = tenant.success ? (tenant.data.team_id ?? tenant.data.team?.id) : undefined;\n const ctx = teamId == null ? baseContext : inTenant(baseContext, teamId);\n const command = z\n .object({\n command: z.literal('/final'),\n trigger_id: z.string().optional(),\n text: z.string().default(''),\n user_id: z.string(),\n team_id: z.string(),\n channel_id: z.string(),\n })\n .safeParse(input);\n if (command.success) {\n const principal = await principalFor(ctx, command.data.team_id, command.data.user_id);\n const by = await personFor(ctx, principal);\n const place: PlaceRef = {\n kind: command.data.channel_id.startsWith('D') ? 'dm' : 'channel',\n id: command.data.channel_id,\n tenant: command.data.team_id,\n };\n const verb = command.data.text.trim().split(/\\s+/)[0];\n let text: string;\n if (typeof by !== 'string') text = `${by.message} ${by.linkUrl ?? ''}`;\n else if (verb === 'disconnect') {\n try {\n await ctx.places.disconnect(place, by);\n text = 'Disconnected this place from Final.';\n } catch {\n text =\n 'Could not disconnect this place. Open Final to manage its connection or disconnect its connected parent place.';\n }\n } else if (verb === 'unlink') {\n await ctx.people.revoke({ principal, reason: 'provider-revoked' });\n text = 'Unlinked your Slack account.';\n } else {\n const route = await ctx.places.resolve(place);\n text =\n route.kind === 'connected'\n ? 'This place is connected to Final. Use /final disconnect to disconnect it.'\n : `Connect this place in Final: ${route.connectUrl}`;\n }\n if (command.data.trigger_id != null)\n await ctx.store.set(stateKey('slack-command-response', command.data.trigger_id), text, {\n ttlSeconds: 60,\n });\n else\n await api(ctx, place.kind === 'dm' ? 'chat.postMessage' : 'chat.postEphemeral', {\n channel: command.data.channel_id,\n user: command.data.user_id,\n text,\n }).catch(() => ctx.log('Slack command response unavailable.'));\n return { accepted: true };\n }\n const interaction = z\n .object({\n type: z.literal('block_actions'),\n user: z.object({ id: z.string() }),\n team: z.object({ id: z.string() }),\n actions: z.array(z.object({ value: z.string() })),\n channel: z.object({ id: z.string() }).optional(),\n message: z\n .object({ thread_ts: z.string().optional(), ts: z.string().optional() })\n .optional(),\n response_url: z.string().optional(),\n })\n .safeParse(input);\n if (interaction.success) {\n const refuse = async (reason: Refusal): Promise<ChannelReceiveResult> => {\n if (interaction.data.channel != null)\n await api(ctx, 'chat.postEphemeral', {\n channel: interaction.data.channel.id,\n user: interaction.data.user.id,\n ...(interaction.data.message?.thread_ts == null\n ? {}\n : { thread_ts: interaction.data.message.thread_ts }),\n text: `${reason.message} ${reason.linkUrl ?? reason.connectUrl ?? ''}`,\n }).catch(() => ctx.log('Slack approval response unavailable.'));\n return { accepted: false, refusal: reason };\n };\n const principal = await principalFor(\n ctx,\n interaction.data.team.id,\n interaction.data.user.id,\n );\n const by = await personFor(ctx, principal);\n if (typeof by !== 'string') return refuse(by);\n const value = interaction.data.actions[0]?.value;\n if (value == null) return { ignored: true, reason: 'no-action' };\n const saved = z\n .object({\n decisionId: z.string(),\n principal: z.object({ id: z.string(), tenant: z.string().optional() }),\n outcome: jsonValueSchema,\n })\n .safeParse(await ctx.store.get(stateKey('slack-decision', value)));\n if (\n !saved.success ||\n saved.data.principal.id !== principal.id ||\n saved.data.principal.tenant !== principal.tenant\n )\n return refuse({\n refused: 'no-access',\n message: saved.success\n ? 'Only the requester can answer this decision.'\n : 'This approval expired. Answer in Final.',\n });\n const url = responseUrl(interaction.data.response_url);\n if (url != null)\n await ctx.store.set(\n stateKey('slack-decision-message', saved.data.decisionId),\n { url },\n { ttlSeconds: 1800 },\n );\n const confirm = (message = 'This decision is no longer waiting in Final.') =>\n confirmDecision({\n ctx,\n decisionId: saved.data.decisionId,\n message,\n channel: interaction.data.channel?.id,\n user: interaction.data.user.id,\n });\n const completed = await ctx.store.get(\n stateKey('slack-decision-resolved', saved.data.decisionId),\n );\n if (completed != null) {\n await confirm(\n completed === 'answered' ? 'This decision has been answered in Final.' : undefined,\n );\n return { accepted: true };\n }\n const result = await ctx.decisions.resolve({\n decisionId: saved.data.decisionId,\n outcome: saved.data.outcome,\n by,\n });\n if ('refused' in result) return refuse(result);\n await ctx.store.set(\n stateKey('slack-decision-resolved', saved.data.decisionId),\n result.resolved ? 'answered' : 'closed',\n {\n ttlSeconds: 3600,\n },\n );\n await confirm(result.resolved ? 'This decision has been answered in Final.' : undefined);\n return result.resolved\n ? { accepted: true }\n : {\n accepted: false,\n refusal: {\n refused: 'no-access',\n message: 'This decision is no longer waiting in Final.',\n },\n };\n }\n const envelope = envelopeSchema.safeParse(input);\n if (!envelope.success || envelope.data.event == null || envelope.data.team_id == null)\n return { ignored: true, reason: 'not-an-event' };\n const event = envelope.data.event;\n if (event.type === 'app_uninstalled' || event.type === 'tokens_revoked') {\n if (event.type === 'app_uninstalled') {\n await revokeTeam({\n ctx,\n team: envelope.data.team_id,\n enterprise: envelope.data.enterprise_id ?? undefined,\n reason: 'uninstalled',\n });\n } else {\n const tokens = z\n .object({\n oauth: z.array(z.string()).default([]),\n bot: z.array(z.string()).default([]),\n })\n .safeParse(event.tokens);\n if (!tokens.success) return { ignored: true, reason: 'invalid-revocation' };\n if (tokens.data.bot.length > 0)\n await revokeTeam({\n ctx,\n team: envelope.data.team_id,\n enterprise: envelope.data.enterprise_id ?? undefined,\n reason: 'provider-revoked',\n });\n else\n for (const user of tokens.data.oauth) {\n const cached = principalRefSchema.safeParse(\n await ctx.store.get(stateKey('slack-principal', envelope.data.team_id, user)),\n );\n const principal = cached.success\n ? cached.data\n : await principalFor(ctx, envelope.data.team_id, user);\n await ctx.people.revoke({ principal, reason: 'provider-revoked' });\n await ctx.store.set(stateKey('slack-principal', envelope.data.team_id, user), null);\n }\n }\n return { accepted: true };\n }\n if (event.type === 'user_change') {\n const changed = slackUserSchema.shape.user.safeParse(event.user);\n if (changed.success && changed.data.deleted === true)\n await ctx.people.revoke({\n principal: {\n id: changed.data.enterprise_user?.id ?? changed.data.id,\n tenant: changed.data.enterprise_user?.enterprise_id ?? envelope.data.team_id,\n },\n reason: 'deactivated',\n });\n return { ignored: true, reason: 'lifecycle' };\n }\n if (\n event.type === 'message' &&\n (event.subtype === 'message_changed' || event.subtype === 'message_deleted')\n ) {\n const deleted =\n event.subtype === 'message_deleted' ||\n z.object({ subtype: z.literal('tombstone') }).safeParse(event.message).success;\n const original = messageSchema.safeParse(deleted ? event.previous_message : event.message);\n if (!original.success || original.data.user == null || typeof event.channel !== 'string')\n return { ignored: true, reason: 'missing-original' };\n if (original.data.bot_id != null || original.data.subtype === 'bot_message')\n return { ignored: true, reason: 'own-message' };\n const timestamp =\n original.data.ts ?? (typeof event.deleted_ts === 'string' ? event.deleted_ts : null);\n if (timestamp == null) return { ignored: true, reason: 'missing-original' };\n const mapped = providerOriginSchema.safeParse(\n await ctx.store.get(\n stateKey('slack-origin', envelope.data.team_id, event.channel, timestamp),\n ),\n );\n if (!mapped.success) return { ignored: true, reason: 'unknown-origin' };\n const place = mapped.data.place;\n const by = await personFor(\n ctx,\n await principalFor(ctx, envelope.data.team_id, original.data.user),\n );\n if (typeof by !== 'string') return { accepted: false, refusal: by };\n const route = await ctx.places.resolve(place);\n if (route.kind !== 'connected') return { ignored: true, reason: 'unconnected' };\n const key = mapped.data.externalKey;\n const editedText = !deleted\n ? await normalizedText(ctx, original.data.text ?? '', envelope.data.team_id)\n : null;\n if (editedText != null && editedText.length === 0)\n return { ignored: true, reason: 'empty-message' };\n return receipt(\n !deleted\n ? await ctx.conversation(route.conversation).edit({\n externalKey: key,\n by,\n content: [\n {\n type: 'text',\n text: editedText ?? '',\n },\n ],\n })\n : await ctx\n .conversation(route.conversation)\n .remove({ externalKey: key, by })\n .then((result) => ('refused' in result ? result : { messageId: key })),\n );\n }\n if (event.type === 'reaction_added' || event.type === 'reaction_removed') {\n const parsed = z\n .object({\n user: z.string(),\n reaction: z.string(),\n item: z.object({ channel: z.string(), ts: z.string() }),\n })\n .safeParse(event);\n if (!parsed.success) return { ignored: true, reason: 'unsupported-reaction' };\n const mapped = providerOriginSchema.safeParse(\n await ctx.store.get(\n stateKey(\n 'slack-origin',\n envelope.data.team_id,\n parsed.data.item.channel,\n parsed.data.item.ts,\n ),\n ),\n );\n if (!mapped.success) return { ignored: true, reason: 'unknown-origin' };\n if (parsed.data.user === (await botFor(ctx, envelope.data.team_id)))\n return { ignored: true, reason: 'own-reaction' };\n const by = await personFor(\n ctx,\n await principalFor(ctx, envelope.data.team_id, parsed.data.user),\n );\n if (typeof by !== 'string') return { accepted: false, refusal: by };\n const route = await ctx.places.resolve(mapped.data.place);\n if (route.kind !== 'connected') return { ignored: true, reason: 'unconnected' };\n const target =\n mapped.data.turnId != null\n ? { replyOf: { externalKey: mapped.data.externalKey, turnId: mapped.data.turnId } }\n : {\n externalKey: mapped.data.externalKey,\n };\n const result = await ctx.conversation(route.conversation).react({\n target,\n emoji: finalEmoji(parsed.data.reaction),\n by,\n op: event.type === 'reaction_added' ? 'add' : 'remove',\n });\n return 'refused' in result ? { accepted: false, refusal: result } : { accepted: true };\n }\n const parsed = messageSchema.safeParse(event);\n if (\n !parsed.success ||\n parsed.data.user == null ||\n parsed.data.ts == null ||\n parsed.data.text == null ||\n parsed.data.bot_id != null ||\n (parsed.data.type !== 'app_mention' &&\n !(parsed.data.type === 'message' && parsed.data.channel_type === 'im'))\n )\n return { ignored: true, reason: 'not-a-human-mention' };\n const message = messageSchema\n .extend({ user: z.string(), ts: z.string(), text: z.string(), channel: z.string() })\n .parse(parsed.data);\n const place = placeFor(message, envelope.data.team_id);\n if (place == null) return { ignored: true, reason: 'no-place' };\n const text = await normalizedText(ctx, message.text, envelope.data.team_id);\n if (text.length === 0) return { ignored: true, reason: 'empty-message' };\n const principal = await principalFor(ctx, envelope.data.team_id, message.user);\n await api(ctx, 'reactions.add', {\n channel: message.channel,\n timestamp: message.ts,\n name: 'eyes',\n }).catch(() => ctx.log('Slack acknowledgement unavailable.'));\n const key = externalKey(place.parent ?? place, message.ts);\n const historyTeam = envelope.data.team_id;\n const loadContext = async () =>\n config.history === 'linked-members'\n ? historyFor({ ctx, message, team: historyTeam }).catch(() => {\n ctx.log('Slack history is unavailable for this app grant.');\n return [];\n })\n : [];\n await ctx.store.set(\n stateKey('slack-origin', envelope.data.team_id, message.channel, message.ts),\n jsonValueSchema.parse({ place, externalKey: key }),\n deliveryRetention,\n );\n const result = await receivePersonMessage({\n ctx,\n principal,\n place,\n resumeAfterLink: place.kind === 'dm',\n text,\n externalKey: key,\n loadContext,\n ref: {\n externalKey: key,\n channel: message.channel,\n ts: message.ts,\n threadTs: message.thread_ts ?? message.ts,\n requester: principal.id,\n user: message.user,\n tenant: principal.tenant ?? envelope.data.team_id,\n },\n });\n if ('accepted' in result && !result.accepted)\n await api(ctx, place.kind === 'dm' ? 'chat.postMessage' : 'chat.postEphemeral', {\n channel: message.channel,\n user: message.user,\n ...(message.thread_ts == null ? {} : { thread_ts: message.thread_ts }),\n text: `${result.refusal.message} ${result.refusal.linkUrl ?? result.refusal.connectUrl ?? ''}`,\n }).catch(() => ctx.log('Slack requester notice unavailable.'));\n return result;\n },\n events: {\n 'message.posted': async (data, ctx) => {\n const key = stateKey('slack-mirror', providerPlaceKey(ctx.origin.place), data.message.id);\n if ((await ctx.store.get(key)) != null) return;\n const { channel, thread_ts } = location(ctx);\n if (channel == null) return;\n const result = replySchema.parse(\n await api(ctx, 'chat.postMessage', {\n channel,\n ...(thread_ts == null ? {} : { thread_ts }),\n text: `From ${data.author.displayName} in Final\\n${textOf(data.message.content)}`.slice(\n 0,\n 11500,\n ),\n }),\n );\n await ctx.store.set(key, result.ts, deliveryRetention);\n },\n 'message.delta': async (data, ctx) => {\n const prior = ctx.state.get()?.text ?? (await savedPartial(ctx));\n const delta =\n data.delta.type === 'text' && typeof data.delta.text === 'string' ? data.delta.text : '';\n const text = prior + delta;\n ctx.state.set({ text });\n await sharedReply(ctx, { text, final: false, messageIds: [data.messageId] });\n },\n 'turn.completed': async (data, ctx) => {\n await sharedReply(ctx, {\n text: completionText(data, ctx.state.get()?.text ?? (await savedPartial(ctx))),\n final: true,\n messageIds: data.messages?.map((message) => message.id) ?? [],\n });\n },\n 'decision.created': async (data, ctx) => {\n const deliveredKey = stateKey('slack-decision-delivered', data.decisionId);\n if ((await ctx.store.get(deliveredKey)) != null) return;\n const { channel, thread_ts } = location(ctx);\n const user = refString(ctx.origin.ref, 'user') ?? refString(ctx.origin.ref, 'requester');\n const principalId = refString(ctx.origin.ref, 'requester') ?? user;\n const tenant = refString(ctx.origin.ref, 'tenant');\n if (channel == null || user == null) return;\n const choices = decisionChoices(data.request);\n const elements: JsonObject[] = [];\n for (const choice of choices) {\n const value = crypto.randomUUID();\n await ctx.store.set(\n stateKey('slack-decision', value),\n {\n decisionId: data.decisionId,\n principal: { id: principalId ?? user, ...(tenant == null ? {} : { tenant }) },\n outcome: choice.outcome,\n },\n { ttlSeconds: 3600 },\n );\n elements.push({\n type: 'button',\n text: { type: 'plain_text', text: choice.label },\n action_id: `final_decision_${elements.length}`,\n value,\n });\n }\n try {\n await api(ctx, 'chat.postEphemeral', {\n channel,\n user,\n ...(thread_ts == null ? {} : { thread_ts }),\n text: `${decisionSummary(data.request)}\\n${elements.length === 0 ? 'Answer in Final \u2192' : 'Choose an option below.'}`,\n ...(elements.length === 0\n ? {}\n : {\n blocks: [\n {\n type: 'section',\n text: { type: 'plain_text', text: decisionSummary(data.request) },\n },\n { type: 'actions', elements },\n ],\n }),\n });\n } catch {\n await api(ctx, 'chat.postMessage', {\n channel,\n ...(thread_ts == null ? {} : { thread_ts }),\n text: 'This request needs approval. Answer in Final.',\n });\n }\n await ctx.store.set(deliveredKey, true, { ttlSeconds: 3600 });\n },\n 'decision.resolved': async (data, ctx) => {\n await ctx.store.set(stateKey('slack-decision-resolved', data.decisionId), 'answered', {\n ttlSeconds: 3600,\n });\n const { channel, thread_ts } = location(ctx);\n await confirmDecision({\n ctx,\n decisionId: data.decisionId,\n channel: channel ?? undefined,\n user:\n refString(ctx.origin.ref, 'user') ??\n refString(ctx.origin.ref, 'requester') ??\n undefined,\n threadTs: thread_ts ?? undefined,\n });\n },\n 'message.edited': async (data, ctx) => {\n if (data.replyOf == null && data.externalKey.startsWith('final:')) {\n const key = mirrorReceiptKey({\n provider: 'slack',\n place: ctx.origin.place,\n externalKey: data.externalKey,\n messageId: data.message.id,\n });\n if (key == null) return;\n const saved = z.string().safeParse(await ctx.store.get(key));\n const { channel } = location(ctx);\n if (!saved.success || channel == null) return;\n const result = slackResponseSchema.parse(\n await api(ctx, 'chat.update', {\n channel,\n ts: saved.data,\n text: `From ${data.author.displayName} in Final\\n${textOf(data.message.content)}`.slice(\n 0,\n 11500,\n ),\n }),\n );\n if (result.error === 'message_not_found')\n await ctx.store.set(key, { deleted: true }, deliveryRetention);\n return;\n }\n if (data.replyOf == null) {\n const { channel, thread_ts } = location(ctx);\n if (channel == null) return;\n const key = stateKey(\n 'slack-prompt-update',\n providerPlaceKey(ctx.origin.place),\n data.externalKey,\n );\n const saved = z\n .object({ ts: z.string(), text: z.string() })\n .safeParse(await ctx.store.get(key));\n const text = `Updated in Final:\\n${textOf(data.message.content)}`.slice(0, 11500);\n if (saved.success && saved.data.text === text) return;\n const result = await api(ctx, saved.success ? 'chat.update' : 'chat.postMessage', {\n channel,\n ...(saved.success ? { ts: saved.data.ts } : thread_ts == null ? {} : { thread_ts }),\n text,\n });\n const missing =\n saved.success && slackResponseSchema.parse(result).error === 'message_not_found';\n const current = missing\n ? await api(ctx, 'chat.postMessage', {\n channel,\n ...(thread_ts == null ? {} : { thread_ts }),\n text,\n })\n : result;\n await ctx.store.set(\n key,\n { ts: saved.success && !missing ? saved.data.ts : replySchema.parse(current).ts, text },\n deliveryRetention,\n );\n return;\n }\n const { channel } = location(ctx);\n const saved = z\n .object({ ts: z.string() })\n .safeParse(await ctx.store.get(replyKey(ctx, data.replyOf)));\n const ts = saved.success ? saved.data.ts : null;\n if (channel != null && ts != null)\n await api(ctx, 'chat.update', {\n channel,\n ts,\n text: textOf(data.message.content).slice(0, 11500),\n });\n },\n 'message.removed': async (data, ctx) => {\n if (data.replyOf == null && data.externalKey.startsWith('final:')) {\n const key = mirrorReceiptKey({\n provider: 'slack',\n place: ctx.origin.place,\n externalKey: data.externalKey,\n messageId: data.message.id,\n });\n if (key == null) return;\n const saved = z.string().safeParse(await ctx.store.get(key));\n const { channel } = location(ctx);\n if (!saved.success || channel == null) return;\n await api(ctx, 'chat.delete', { channel, ts: saved.data });\n await ctx.store.set(key, { deleted: true }, deliveryRetention);\n return;\n }\n if (data.replyOf == null) {\n const key = stateKey(\n 'slack-prompt-update',\n providerPlaceKey(ctx.origin.place),\n data.externalKey,\n );\n const saved = z.object({ ts: z.string() }).safeParse(await ctx.store.get(key));\n const { channel } = location(ctx);\n if (saved.success && channel != null) {\n await api(ctx, 'chat.delete', { channel, ts: saved.data.ts });\n await ctx.store.set(key, null);\n }\n return;\n }\n const { channel } = location(ctx);\n const saved = z\n .object({ ts: z.string() })\n .safeParse(await ctx.store.get(replyKey(ctx, data.replyOf)));\n const ts = saved.success ? saved.data.ts : null;\n if (channel != null && ts != null) await api(ctx, 'chat.delete', { channel, ts });\n },\n 'reaction.added': async (data, ctx) => {\n const { channel } = location(ctx);\n const mirror = data.replyOf == null && data.externalKey.startsWith('final:');\n const mirrorKey = mirrorReceiptKey({\n provider: 'slack',\n place: ctx.origin.place,\n externalKey: data.externalKey,\n });\n const mirrored = z\n .string()\n .safeParse(mirrorKey == null ? null : await ctx.store.get(mirrorKey));\n if (mirror && !mirrored.success) return;\n const saved = z\n .object({ ts: z.string() })\n .safeParse(await ctx.store.get(replyKey(ctx, data.replyOf)));\n const name = slackEmoji(data.emoji);\n const timestamp =\n mirror && mirrored.success\n ? mirrored.data\n : data.replyOf == null\n ? refString(ctx.origin.ref, 'ts')\n : saved.success\n ? saved.data.ts\n : null;\n if (channel != null && timestamp != null && name != null)\n await settleMirrorReaction({\n ctx,\n key: mirror ? mirrorKey : null,\n classify: classifyMirrorReaction,\n work: () =>\n addSharedReaction({\n store: ctx.store,\n key: stateKey(\n 'slack-shared-reaction',\n ctx.origin.place.tenant ?? null,\n channel,\n timestamp,\n name,\n ),\n principal: data.principal,\n add: async () => {\n const response = slackResponseSchema.parse(\n await api(ctx, 'reactions.add', { channel, timestamp, name }),\n );\n return response.error !== 'already_reacted';\n },\n }),\n });\n },\n 'reaction.removed': async (data, ctx) => {\n const { channel } = location(ctx);\n const mirror = data.replyOf == null && data.externalKey.startsWith('final:');\n const mirrorKey = mirrorReceiptKey({\n provider: 'slack',\n place: ctx.origin.place,\n externalKey: data.externalKey,\n });\n const mirrored = z\n .string()\n .safeParse(mirrorKey == null ? null : await ctx.store.get(mirrorKey));\n if (mirror && !mirrored.success) return;\n const saved = z\n .object({ ts: z.string() })\n .safeParse(await ctx.store.get(replyKey(ctx, data.replyOf)));\n const name = slackEmoji(data.emoji);\n const timestamp =\n mirror && mirrored.success\n ? mirrored.data\n : data.replyOf == null\n ? refString(ctx.origin.ref, 'ts')\n : saved.success\n ? saved.data.ts\n : null;\n if (channel != null && timestamp != null && name != null)\n await settleMirrorReaction({\n ctx,\n key: mirror ? mirrorKey : null,\n classify: classifyMirrorReaction,\n work: () =>\n removeSharedReaction({\n store: ctx.store,\n key: stateKey(\n 'slack-shared-reaction',\n ctx.origin.place.tenant ?? null,\n channel,\n timestamp,\n name,\n ),\n principal: data.principal,\n remove: async () => {\n await api(ctx, 'reactions.remove', { channel, timestamp, name });\n },\n }),\n });\n },\n },\n });\n};\n\nconst historyFor = async (args: {\n ctx: ChannelReceiveContextIface<Config>;\n message: z.infer<typeof messageSchema>;\n team: string;\n}): Promise<string[]> => {\n const { ctx, message } = args;\n if (message.channel == null) return [];\n const messages: z.infer<typeof messageSchema>[] = [];\n let cursor: string | undefined;\n for (let page = 0; page < 5; page += 1) {\n const result = z\n .object({\n messages: z.array(messageSchema),\n response_metadata: z.object({ next_cursor: z.string().optional() }).optional(),\n })\n .parse(\n await api(\n ctx,\n message.thread_ts == null ? 'conversations.history' : 'conversations.replies',\n {\n channel: message.channel,\n limit: 100,\n ...(message.ts == null ? {} : { latest: message.ts, inclusive: false }),\n ...(message.thread_ts == null ? {} : { ts: message.thread_ts }),\n ...(cursor == null ? {} : { cursor }),\n },\n ),\n );\n messages.push(...result.messages);\n cursor = result.response_metadata?.next_cursor;\n if (cursor == null || cursor.length === 0 || message.thread_ts == null) break;\n }\n // Omit oversized threads rather than presenting an incomplete oldest-first slice as recent context.\n if (message.thread_ts != null && cursor != null && cursor.length > 0) return [];\n const recent = messages.sort((a, b) => Number(a.ts ?? 0) - Number(b.ts ?? 0)).slice(-20);\n const lines: string[] = [];\n const authors = new Map<string, string | null>();\n for (const earlier of recent) {\n if (\n earlier.user == null ||\n earlier.text == null ||\n earlier.bot_id != null ||\n earlier.ts === message.ts\n )\n continue;\n if (!authors.has(earlier.user)) {\n const principal = await principalFor(ctx, args.team, earlier.user);\n const linked = await ctx.people.resolve(principal);\n authors.set(earlier.user, linked.kind === 'member' ? linked.displayName : null);\n }\n const name = authors.get(earlier.user);\n if (name != null) {\n const text = await normalizedText(ctx, earlier.text, args.team);\n if (text.length > 0) lines.push(`${name}: ${text}`);\n }\n }\n return lines;\n};\n"],
5
+ "mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EASA;AAAA,OACK;AACP,YAAY,OAAO;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,aAAa,mBAAmB;AACzC;AAAA,EACE;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;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACnC,SAAS,EAAE,MAAM,CAAC,EAAE,QAAQ,MAAM,GAAG,EAAE,QAAQ,gBAAgB,CAAC,CAAC,EAAE,QAAQ,MAAM;AACnF,CAAC;AAED,MAAM,iBAAiB,EAAE,OAAO;AAAA,EAC9B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,eAAe,EAAE,OAAO,EAAE,QAAQ;AAAA,EAClC,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,EAC9B,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,eAAe,EAAE,SAAS;AAAA,EACtD,WAAW,EAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AACD,MAAM,gBAAgB,EAAE,OAAO;AAAA,EAC7B,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,EAClC,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC1B,IAAI,EAAE,OAAO,EAAE,SAAS;AAAA,EACxB,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,QAAQ,EAAE,OAAO,EAAE,SAAS;AAC9B,CAAC;AACD,MAAM,aAAa,CAAC,UAAiC;AACnD,QAAM,OAAO,MAAM,QAAQ,UAAU,EAAE;AACvC,MAAI,wCAAwC,KAAK,IAAI,EAAG,QAAO;AAC/D,QAAM,YAAY,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,cAAc,sBAAsB,KAAK,SAAS,CAAC;AACxF,MAAI,UAAU,SAAS,EAAG,QAAO;AACjC,QAAM,OAAO,MAAM,QAAQ,wBAAwB,EAAE;AACrD,QAAM,SACH,OAAO,OAAO,aAAa,IAAI,IAAI,YAAY,IAAI,IAAI,WACxD,YAAY,OAAO,QAAQ,KAC3B,YAAY,KAAK,QAAQ,WAAW,EAAE,CAAC;AACzC,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,WAAW,UAAU,CAAC,GAAG,YAAY,CAAC;AAC5C,SAAO,SAAS,YAAY,OAAO,KAAK,eAAe,WAAW,MAAO;AAC3E;AACA,MAAM,aAAa,CAAC,SAAyB;AAC3C,QAAM,QAAQ,kCAAkC,KAAK,IAAI;AACzD,MAAI,SAAS,QAAQ,MAAM,CAAC,KAAK,KAAM,QAAO,IAAI,IAAI;AACtD,QAAM,QAAQ,OAAO,OAAO,aAAa,MAAM,CAAC,CAAC,IAAI,YAAY,MAAM,CAAC,CAAC,IAAI;AAC7E,MAAI,SAAS,KAAM,QAAO,IAAI,IAAI;AAClC,MAAI,MAAM,CAAC,KAAK,KAAM,QAAO;AAC7B,QAAM,aAAa,CAAC,GAAG,KAAK;AAC5B,aAAW,OAAO,GAAG,GAAG,OAAO,cAAc,SAAU,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;AACxE,SAAO,WAAW,KAAK,EAAE;AAC3B;AACA,MAAM,gBAAgB,CAAC,SACrB,KAAK,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM;AACxE,MAAM,sBAAsB,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAC3F,MAAM,MAAM,OACV,KAEA,QACA,SACqB;AACrB,QAAM,MAAM,MAAM,IAAI,YAAY,IAAI,EAAE,QAAQ,IAAI,QAAQ,MAAM,OAAO,CAAC;AAC1E,QAAM,OAAO,CAAC,cAAc,yBAAyB,uBAAuB,EAAE,SAAS,MAAM;AAC7F,QAAM,MAAM,IAAI,IAAI,yBAAyB,MAAM,EAAE;AACrD,MAAI;AACF,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI;AAC5C,UAAI,SAAS;AACX,YAAI,aAAa,IAAI,KAAK,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK,CAAC;AAAA;AACzF,QAAM,OAAO,MAAM;AAAA,IACjB,MAAM,IAAI,YAAY,MAAM,KAAK;AAAA,MAC/B,QAAQ,OAAO,QAAQ;AAAA,MACvB,SAAS;AAAA,QACP,eAAe,UAAU,IAAI,WAAW;AAAA,QACxC,GAAI,CAAC,OAAO,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,MACxD;AAAA,MACA,GAAI,OACA,CAAC,IACD;AAAA,QACE,MAAM,KAAK,UAAU;AAAA,UACnB,GAAG;AAAA,UACH,GAAI,OAAO,KAAK,SAAS,WAAW,EAAE,MAAM,cAAc,KAAK,IAAI,EAAE,IAAI,CAAC;AAAA,QAC5E,CAAC;AAAA,MACH;AAAA,IACN,CAAC;AAAA,EACH;AACA,QAAM,SAAS,oBAAoB,MAAM,IAAI;AAC7C,QAAM,WACH,WAAW,mBAAmB,OAAO,UAAU,qBAC/C,WAAW,sBAAsB,OAAO,UAAU,iBAClD,WAAW,iBAAiB,OAAO,UAAU,uBAC7C,WAAW,kBACT,OAAO,UAAU,0BAA0B,OAAO,UAAU;AACjE,MAAI,CAAC,OAAO,MAAM,CAAC;AACjB,UAAM,IAAI,MAAM,SAAS,MAAM,KAAK,OAAO,SAAS,eAAe,IAAI;AAAA,MACrE,OAAO,EAAE,MAAM,OAAO,SAAS,gBAAgB;AAAA,IACjD,CAAC;AACH,SAAO;AACT;AACA,MAAM,yBAAyB,OAAO,UAAkD;AACtF,QAAM,QAAQ,EACX,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAC3B,UAAU,iBAAiB,QAAQ,MAAM,QAAQ,IAAI;AACxD,MAAI,CAAC,MAAM,QAAS,QAAO;AAC3B,MAAI,MAAM,KAAK,SAAS,oBAAqB,QAAO;AACpD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,MAAM,KAAK,IAAI,IACtB,gBACA;AACN;AACA,MAAM,cAAc,CAAC,UAA6C;AAChE,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,WAAO,IAAI,aAAa,YACtB,IAAI,aAAa,qBACjB,IAAI,SAAS,MACb,IAAI,aAAa,MACjB,IAAI,aAAa,MACjB,qCAAqC,KAAK,IAAI,QAAQ,IACpD,IAAI,OACJ;AAAA,EACN,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUA,MAAM,kBAAkB,OAAO,SAA6C;AAC1E,QAAM,EAAE,KAAK,WAAW,IAAI;AAC5B,QAAM,MAAM,SAAS,4BAA4B,UAAU;AAC3D,QAAM,QAAQ,MAAM,IAAI,MAAM,IAAI,GAAG;AACrC,QAAM,WAAW,EACd,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAC1B,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,0BAA0B,UAAU,CAAC,CAAC;AAChF,QAAM,MAAM,SAAS,UAAU,YAAY,SAAS,KAAK,GAAG,IAAI;AAChE,MAAI,OAAO,QAAQ,UAAU,YAAY;AACvC,QAAI;AACF,YAAM,WAAW,MAAM,IAAI,YAAY,MAAM,KAAK;AAAA,QAChD,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU;AAAA,UACnB,kBAAkB;AAAA,UAClB,MAAM,KAAK,WAAW;AAAA,UACtB,QAAQ,CAAC;AAAA,QACX,CAAC;AAAA,MACH,CAAC;AACD,YAAM,SAAS,KAAK;AACpB,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,0CAA0C;AAC5E,YAAM,IAAI,MAAM,IAAI,KAAK,YAAY,EAAE,YAAY,KAAK,CAAC;AACzD;AAAA,IACF,QAAQ;AACN,UAAI,IAAI,yCAAyC;AAAA,IACnD;AAAA,EACF;AACA,MAAI,SAAS,QAAQ,KAAK,WAAW,QAAQ,KAAK,QAAQ,KAAM;AAChE,MAAI;AACF,UAAM,IAAI,KAAK,sBAAsB;AAAA,MACnC,SAAS,KAAK;AAAA,MACd,MAAM,KAAK;AAAA,MACX,GAAI,KAAK,YAAY,OAAO,CAAC,IAAI,EAAE,WAAW,KAAK,SAAS;AAAA,MAC5D,MAAM,KAAK,WAAW;AAAA,IACxB,CAAC;AACD,UAAM,IAAI,MAAM,IAAI,KAAK,YAAY,EAAE,YAAY,KAAK,CAAC;AAAA,EAC3D,QAAQ;AACN,QAAI,IAAI,0CAA0C;AAAA,EACpD;AACF;AACA,MAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,MAAM,EAAE,OAAO;AAAA,IACb,IAAI,EAAE,OAAO;AAAA,IACb,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,SAAS,EAAE,QAAQ,EAAE,SAAS;AAAA,IAC9B,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,eAAe,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS;AAAA,IAClF,SAAS,EACN,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,SAAS,GAAG,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAChF,SAAS;AAAA,EACd,CAAC;AACH,CAAC;AACD,MAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG;AAAA,EAClC,UAAU,EAAE,QAAQ;AACtB,CAAC;AACD,MAAM,YAAY,OAChB,KACA,MACA,eACkB;AAClB,QAAM,IAAI,MAAM,IAAI,SAAS,oBAAoB,IAAI,GAAG,UAAU;AAClE,QAAM,MAAM,SAAS,0BAA0B,UAAU;AACzD,QAAM,QAAQ,sBAAsB,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AACtE,MAAI,MAAM,YAAY,MAAM,KAAK,YAAY,MAAM,KAAK,MAAM,SAAS,IAAI,GAAI;AAC/E,QAAM,QAAQ,CAAC,GAAI,MAAM,UAAU,MAAM,KAAK,QAAQ,CAAC,GAAI,IAAI;AAE/D,QAAM,IAAI,MAAM;AAAA,IACd;AAAA,IACA,MAAM,SAAS,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,KAAK,IAAI,EAAE,OAAO,UAAU,MAAM;AAAA,EAChF;AACF;AACA,MAAM,aAAa,OAAO,SAKL;AACnB,QAAM,EAAE,KAAK,MAAM,OAAO,IAAI;AAC9B,QAAM,QAAQ,EAAE,OAAO,EAAE,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,oBAAoB,IAAI,CAAC,CAAC;AAC1F,QAAM,aAAa,KAAK,eAAe,MAAM,UAAU,MAAM,OAAO;AACpE,QAAM,IAAI,OAAO,OAAO,EAAE,QAAQ,MAAM,OAAO,CAAC;AAChD,MAAI,cAAc,QAAQ,eAAe,MAAM;AAC7C,UAAM,MAAM,SAAS,0BAA0B,UAAU;AACzD,UAAM,QAAQ,sBAAsB,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AACtE,UAAM,QAAQ,MAAM,UAAU,MAAM,KAAK,MAAM,OAAO,CAAC,UAAU,UAAU,IAAI,IAAI,CAAC;AACpF,QAAI,CAAC,MAAM,WAAW,MAAM,KAAK,YAAY,MAAM,WAAW,GAAG;AAC/D,YAAM,IAAI,OAAO,OAAO,EAAE,QAAQ,YAAY,OAAO,CAAC;AACtD,YAAM,IAAI,MAAM,IAAI,KAAK,EAAE,OAAO,CAAC,GAAG,UAAU,MAAM,CAAC;AAAA,IACzD,MAAO,OAAM,IAAI,MAAM,IAAI,KAAK,EAAE,OAAO,UAAU,MAAM,CAAC;AAAA,EAC5D;AACA,QAAM,IAAI,MAAM,IAAI,SAAS,oBAAoB,IAAI,GAAG,IAAI;AAC5D,QAAM,IAAI,MAAM,IAAI,SAAS,kBAAkB,IAAI,GAAG,IAAI;AAC5D;AACA,MAAM,eAAe,OACnB,KACA,MACA,SAC0B;AAC1B,QAAM,UAAU,gBAAgB;AAAA,IAC9B,MAAM,IAAI,SAAS,KAAK,IAAI,GAAG,cAAc,EAAE,KAAK,CAAC;AAAA,EACvD,EAAE;AACF,MAAI,QAAQ,mBAAmB;AAC7B,UAAM,UAAU,KAAK,MAAM,QAAQ,gBAAgB,aAAa;AAClE,MAAI,QAAQ,YAAY;AACtB,UAAM,IAAI,OAAO,OAAO;AAAA,MACtB,WAAW;AAAA,QACT,IAAI,QAAQ,iBAAiB,MAAM,QAAQ;AAAA,QAC3C,QAAQ,QAAQ,iBAAiB,iBAAiB;AAAA,MACpD;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AACH,SAAO;AAAA,IACL,IAAI,QAAQ,iBAAiB,MAAM,QAAQ;AAAA,IAC3C,QAAQ,QAAQ,iBAAiB,iBAAiB;AAAA,IAClD,aACE,CAAC,QAAQ,SAAS,cAAc,QAAQ,SAAS,WAAW,QAAQ,MAAM,QAAQ,EAAE,EAAE;AAAA,MACpF,CAAC,SAAS,QAAQ,QAAQ,KAAK,KAAK,EAAE,SAAS;AAAA,IACjD,KAAK,QAAQ;AAAA,EACjB;AACF;AACA,MAAM,WAAW,CAAC,SAAwC,WAAoC;AAC5F,MAAI,QAAQ,WAAW,KAAM,QAAO;AACpC,QAAM,UAAoB;AAAA,IACxB,MAAM,QAAQ,iBAAiB,QAAQ,QAAQ,QAAQ,WAAW,GAAG,IAAI,OAAO;AAAA,IAChF,IAAI,QAAQ;AAAA,IACZ;AAAA,IACA,OAAO,QAAQ;AAAA,EACjB;AACA,SAAO,QAAQ,aAAa,OACxB,UACA;AAAA,IACE,MAAM;AAAA,IACN,IAAI,GAAG,QAAQ,OAAO,IAAI,QAAQ,SAAS;AAAA,IAC3C;AAAA,IACA,QAAQ;AAAA,IACR,OAAO,QAAQ;AAAA,EACjB;AACN;AACA,MAAM,WAAW,CAAC,SAA2C;AAAA,EAC3D,SACE,UAAU,IAAI,OAAO,KAAK,SAAS,MAClC,IAAI,OAAO,MAAM,SAAS,WACtB,IAAI,OAAO,MAAM,QAAQ,MAAM,IAAI,OAAO,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC,IAChE,IAAI,OAAO,MAAM;AAAA,EACvB,WACE,UAAU,IAAI,OAAO,KAAK,UAAU,KACpC,UAAU,IAAI,OAAO,KAAK,IAAI,MAC7B,IAAI,OAAO,MAAM,SAAS,WAAW,IAAI,OAAO,MAAM,GAAG,MAAM,GAAG,EAAE,GAAG,EAAE,IAAI;AAClF;AACA,MAAM,SAAS,OACb,KACA,WACgC;AAChC,QAAM,MAAM,SAAS,kBAAkB,MAAM;AAC7C,QAAM,SAAS,EAAE,OAAO,EAAE,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AAC5D,MAAI,OAAO,QAAS,QAAO,OAAO;AAClC,QAAM,MAAM,EACT,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EACzC,MAAM,MAAM,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,EAAE;AAC1C,MAAI,OAAO,KAAM,OAAM,IAAI,MAAM,IAAI,KAAK,KAAK,iBAAiB;AAChE,SAAO;AACT;AACA,MAAM,iBAAiB,OACrB,KACA,MACA,WACoB;AACpB,QAAM,MAAM,MAAM,OAAO,KAAK,MAAM;AACpC,SAAO,KACJ,QAAQ,mBAAmB,CAAC,QAAgB,OAAgB,OAAO,MAAM,KAAK,IAAI,EAAE,EAAG,EACvF,QAAQ,SAAS,GAAG,EACpB,QAAQ,SAAS,GAAG,EACpB,QAAQ,UAAU,GAAG,EACrB,KAAK;AACV;AACA,MAAM,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC/C,MAAM,WAAW,CACf,KACA,YAEA;AAAA,EACE;AAAA,EACA,SAAS,eAAe,UAAU,IAAI,OAAO,KAAK,aAAa,KAAK,IAAI,OAAO,MAAM;AAAA,EACrF,SAAS,UAAU,IAAI,KAAK;AAC9B;AACF,MAAM,YAAY,OAChB,KACA,MACA,OACA,MAAM,SAAS,GAAG,MACA;AAClB,QAAM,EAAE,SAAS,UAAU,IAAI,SAAS,GAAG;AAC3C,MAAI,WAAW,KAAM;AACrB,QAAM,QAAQ,EACX,OAAO;AAAA,IACN,IAAI,EAAE,OAAO;AAAA,IACb,WAAW,EAAE,OAAO;AAAA,IACpB,OAAO,EAAE,QAAQ;AAAA,IACjB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,CAAC,EACA,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AACrC,MAAI,MAAM,WAAW,MAAM,KAAK,MAAO;AACvC,MAAI,MAAM,WAAW,CAAC,SAAS,KAAK,IAAI,IAAI,MAAM,KAAK,YAAY,KAAO;AACxE,UAAM,IAAI,MAAM,IAAI,KAAK,EAAE,GAAG,MAAM,MAAM,MAAM,KAAK,MAAM,GAAG,KAAK,EAAE,GAAG,iBAAiB;AACzF;AAAA,EACF;AACA,QAAM,OAAO,KAAK,MAAM,GAAG,KAAM,KAAK,KAAK,SAAS,QAAS,+BAA0B;AACvF,MAAI,KAAK,WAAW,EAAG;AACvB,QAAM,SAAS,MAAM,IAAI,KAAK,MAAM,UAAU,gBAAgB,oBAAoB;AAAA,IAChF;AAAA,IACA,GAAI,MAAM,UAAU,EAAE,IAAI,MAAM,KAAK,GAAG,IAAI,aAAa,OAAO,CAAC,IAAI,EAAE,UAAU;AAAA,IACjF,MAAM;AAAA,EACR,CAAC;AACD,MAAI,MAAM,WAAW,oBAAoB,MAAM,MAAM,EAAE,UAAU,qBAAqB;AACpF,UAAM,IAAI,MAAM,IAAI,KAAK,IAAI;AAC7B,UAAM,UAAU,KAAK,MAAM,OAAO,GAAG;AACrC;AAAA,EACF;AACA,QAAM,KAAK,MAAM,UAAU,MAAM,KAAK,KAAK,YAAY,MAAM,MAAM,EAAE;AACrE,QAAM,IAAI,MAAM;AAAA,IACd;AAAA,IACA,EAAE,IAAI,WAAW,KAAK,IAAI,GAAG,OAAO,MAAM,KAAK,MAAM,GAAG,KAAK,EAAE;AAAA,IAC/D;AAAA,EACF;AACA,QAAM,IAAI,MAAM;AAAA,IACd,SAAS,gBAAgB,IAAI,OAAO,MAAM,UAAU,MAAM,SAAS,EAAE;AAAA,IACrE,gBAAgB,MAAM;AAAA,MACpB,OAAO,IAAI,OAAO;AAAA,MAClB,aAAa,UAAU,IAAI,OAAO,KAAK,aAAa,KAAK,IAAI,OAAO,MAAM;AAAA,MAC1E,QAAQ,IAAI,KAAK;AAAA,IACnB,CAAC;AAAA,IACD;AAAA,EACF;AACF;AACA,MAAM,eAAe,OAAO,QAA2D;AACrF,QAAMA,WAAU,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,GAAG,CAAC,CAAC;AAC3F,SAAOA,SAAQ,UAAUA,SAAQ,KAAK,OAAO;AAC/C;AACA,MAAM,cAAc,OAClB,KACA,SACkB;AAClB,QAAM,EAAE,SAAS,UAAU,IAAI,SAAS,GAAG;AAC3C,QAAM,kBAAkB;AAAA,IACtB,WAAW,IAAI,QAAQ;AAAA,IACvB,OAAO,IAAI;AAAA,IACX,aAAa;AAAA,MACX;AAAA,MACA,IAAI,OAAO,MAAM,UAAU;AAAA,MAC3B,WAAW;AAAA,MACX,aAAa;AAAA,IACf;AAAA,IACA,YAAY,KAAK;AAAA,IACjB,WAAW,SAAS,GAAG;AAAA,IACvB,MAAM,CAAC,QAAQ,UAAU,KAAK,KAAK,MAAM,KAAK,OAAO,GAAG;AAAA,IACxD,iBAAiB,OAAOA,UAAS,cAAc;AAC7C,YAAM,QAAQ,YAAY,UAAUA,QAAO;AAC3C,YAAM,SAAS,YAAY,UAAU,SAAS;AAC9C,UAAI,MAAM,WAAW,OAAO,WAAW,MAAM,KAAK,OAAO,OAAO,KAAK,MAAM,WAAW;AACpF,cAAM,IAAI,KAAK,eAAe,EAAE,SAAS,IAAI,MAAM,KAAK,GAAG,CAAC;AAAA,IAChE;AAAA,EACF,CAAC;AACH;AACO,MAAM,eAAe,CAAC,UAAsB,CAAC,MAAM;AACxD,QAAM,SAAS,aAAa,MAAM,OAAO;AACzC,SAAO,cAAmD;AAAA,IACxD,MAAM;AAAA,IACN;AAAA,IACA,WAAW,WAAW,8CAA8C;AAAA,IACpE,aAAa,EAAE,KAAK,QAAQ;AAAA,IAC5B,UAAU;AAAA,MACR,MAAM;AAAA,MACN,OAAO,OAAO,MAAM,QAAQ;AAC1B,cAAM,MAAM,MAAM,IAAI,YAAY,QAAQ;AAC1C,eAAO;AAAA,UACL;AAAA,YACE,GAAG;AAAA,YACH,cAAc;AAAA,YACd,UAAU,IAAI;AAAA,YACd,aAAa,GAAG,eAAe,MAAM,CAAC,MAAM,IAAI,QAAQ,EAAE;AAAA,YAC1D,OAAO;AAAA,UACT;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,OAAO,CAAC,MAAM,WAAW,QAAQ;AAAA,MACjC,UAAU,CAAC,UACT,MAAM,SAAS,OACX,EAAE,QAAQ,qBAAqB,SAAS,UAAU,UAAU,UAAU,IACtE;AAAA,IACR;AAAA,IACA,QAAQ;AAAA,MACN;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,SAAS,OAAO,QAAQ;AACtB,gBAAM,QAAQ,MAAM,UAAU,IAAI,SAAS,GAAG;AAC9C,cAAI,SAAS;AACX,mBAAO,IAAI,SAAS,mCAAmC,EAAE,QAAQ,IAAI,CAAC;AACxE,gBAAM,MAAM,MAAM,IAAI,YAAY,QAAQ;AAC1C,gBAAM,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,IAAI,GAAG,cAAc,EAAE,OAAO,EAAE,CAAC,EAAE;AAAA,YACxE,MAAM;AAAA,cACJ,MAAM,IAAI,YAAY,MAAM,8CAA8C;AAAA,gBACxE,QAAQ;AAAA,gBACR,MAAM,IAAI,gBAAgB;AAAA,kBACxB,WAAW,IAAI;AAAA,kBACf,eAAe,IAAI;AAAA,kBACnB,MAAM,MAAM;AAAA,kBACZ,cAAc,MAAM;AAAA,kBACpB,YAAY;AAAA,gBACd,CAAC;AAAA,cACH,CAAC;AAAA,YACH;AAAA,UACF;AACA,gBAAM,WAAW,EACd,OAAO;AAAA,YACN,IAAI,EAAE,QAAQ,IAAI;AAAA,YAClB,KAAK,EAAE,OAAO;AAAA,YACd,6BAA6B,EAAE,OAAO;AAAA,YACtC,6BAA6B,EAAE,OAAO,EAAE,SAAS;AAAA,UACnD,CAAC,EACA;AAAA,YACC,MAAM;AAAA,cACJ,MAAM,IAAI,YAAY,MAAM,iDAAiD;AAAA,gBAC3E,SAAS,EAAE,eAAe,UAAU,MAAM,YAAY,GAAG;AAAA,cAC3D,CAAC;AAAA,YACH;AAAA,UACF;AACF,gBAAM,SAAS,MAAM;AAAA,YACnB;AAAA,YACA,SAAS,2BAA2B;AAAA,YACpC,SAAS,2BAA2B,KAAK,SAAS;AAAA,UACpD;AACA,gBAAM,WAAW,MAAM;AAAA,YACrB,EAAE,QAAQ,MAAM,QAAQ,UAAU,MAAM,WAAW,OAAO;AAAA,YAC1D;AAAA,UACF;AACA,cAAI,SAAS;AACX,kBAAM,IAAI,MAAM;AAAA,cACd;AAAA,gBACE;AAAA,gBACA,SAAS,2BAA2B;AAAA,gBACpC,SAAS,2BAA2B,KAAK,SAAS;AAAA,cACpD;AAAA,cACA,gBAAgB,MAAM,MAAM;AAAA,cAC5B;AAAA,YACF;AACF,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,SAAS,OAAO,QAAQ;AACtB,gBAAM,OAAO,MAAM,IAAI,QAAQ,KAAK;AACpC,cAAI,MAAe;AACnB,cAAI,eAAe;AACnB,cAAI;AACF,kBAAM,KAAK,MAAM,IAAI;AACrB,2BAAe;AAAA,UACjB,QAAQ;AAAA,UAER;AACA,cACE,CAAC,gBACD,IAAI,QAAQ,QAAQ,IAAI,cAAc,GAAG,SAAS,mCAAmC,GACrF;AACA,kBAAM,OAAO,IAAI,gBAAgB,IAAI;AACrC,kBAAM,KAAK,IAAI,SAAS,IACpB,UAAU,KAAK,IAAI,SAAS,KAAK,EAAE,IACnC,OAAO;AAAA,cACL,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,QAAQ;AACzC,sBAAM,QAAQ,KAAK,IAAI,GAAG;AAC1B,uBAAO,SAAS,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC;AAAA,cAC3C,CAAC;AAAA,YACH;AAAA,UACN;AACA,gBAAM,MAAM,MAAM,IAAI,YAAY,QAAQ;AAC1C,gBAAM,YAAY,IAAI,QAAQ,QAAQ,IAAI,2BAA2B;AACrE,gBAAM,YAAY,IAAI,QAAQ,QAAQ,IAAI,mBAAmB;AAC7D,cACE,IAAI,iBAAiB,QACrB,CAAC,eAAe,SAAS,KACzB,aAAa,QACb,CAAC,UAAU,WAAW,KAAK,KAC3B,CAAE,MAAM,WAAW;AAAA,YACjB,QAAQ,IAAI;AAAA,YACZ,MAAM,MAAM,SAAS,IAAI,IAAI;AAAA,YAC7B,WAAW,UAAU,MAAM,CAAC;AAAA,UAC9B,CAAC;AAED,mBAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAC3C,gBAAM,WAAW,eAAe,UAAU,GAAG;AAC7C,cACE,SAAS,WACT,SAAS,KAAK,SAAS,sBACvB,SAAS,KAAK,aAAa;AAE3B,mBAAO,SAAS,KAAK,EAAE,WAAW,SAAS,KAAK,UAAU,CAAC;AAC7D,gBAAM,QAAQ,EACX,OAAO,EAAE,SAAS,EAAE,QAAQ,QAAQ,GAAG,YAAY,EAAE,OAAO,EAAE,CAAC,EAC/D,UAAU,GAAG;AAChB,cAAI,MAAM,SAAS;AACjB,gBAAI;AACF,oBAAM,IAAI,QAAQ,gBAAgB,MAAM,GAAG,CAAC;AAC5C,oBAAM,MAAM,SAAS,0BAA0B,MAAM,KAAK,UAAU;AACpE,oBAAM,OAAO,MAAM,IAAI,MAAM,IAAI,GAAG;AACpC,oBAAM,IAAI,MAAM,IAAI,KAAK,IAAI;AAC7B,qBAAO,SAAS,KAAK;AAAA,gBACnB,eAAe;AAAA,gBACf,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,cAC1C,CAAC;AAAA,YACH,QAAQ;AACN,qBAAO,SAAS,KAAK;AAAA,gBACnB,eAAe;AAAA,gBACf,MAAM;AAAA,cACR,CAAC;AAAA,YACH;AAAA,UACF;AACA,gBAAM,IAAI,QAAQ,gBAAgB,MAAM,GAAG,CAAC;AAC5C,iBAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,OAAO,OAAO,gBAAgB;AACrC,YAAM,SAAS,EACZ,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,GAAG,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EACxF,UAAU,KAAK;AAClB,YAAM,SAAS,OAAO,UAAW,OAAO,KAAK,WAAW,OAAO,KAAK,MAAM,KAAM;AAChF,YAAM,MAAM,UAAU,OAAO,cAAc,SAAS,aAAa,MAAM;AACvE,YAAM,UAAU,EACb,OAAO;AAAA,QACN,SAAS,EAAE,QAAQ,QAAQ;AAAA,QAC3B,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,QAChC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,QAC3B,SAAS,EAAE,OAAO;AAAA,QAClB,SAAS,EAAE,OAAO;AAAA,QAClB,YAAY,EAAE,OAAO;AAAA,MACvB,CAAC,EACA,UAAU,KAAK;AAClB,UAAI,QAAQ,SAAS;AACnB,cAAMC,aAAY,MAAM,aAAa,KAAK,QAAQ,KAAK,SAAS,QAAQ,KAAK,OAAO;AACpF,cAAM,KAAK,MAAM,UAAU,KAAKA,UAAS;AACzC,cAAMC,SAAkB;AAAA,UACtB,MAAM,QAAQ,KAAK,WAAW,WAAW,GAAG,IAAI,OAAO;AAAA,UACvD,IAAI,QAAQ,KAAK;AAAA,UACjB,QAAQ,QAAQ,KAAK;AAAA,QACvB;AACA,cAAM,OAAO,QAAQ,KAAK,KAAK,KAAK,EAAE,MAAM,KAAK,EAAE,CAAC;AACpD,YAAIC;AACJ,YAAI,OAAO,OAAO,SAAU,CAAAA,QAAO,GAAG,GAAG,OAAO,IAAI,GAAG,WAAW,EAAE;AAAA,iBAC3D,SAAS,cAAc;AAC9B,cAAI;AACF,kBAAM,IAAI,OAAO,WAAWD,QAAO,EAAE;AACrC,YAAAC,QAAO;AAAA,UACT,QAAQ;AACN,YAAAA,QACE;AAAA,UACJ;AAAA,QACF,WAAW,SAAS,UAAU;AAC5B,gBAAM,IAAI,OAAO,OAAO,EAAE,WAAAF,YAAW,QAAQ,mBAAmB,CAAC;AACjE,UAAAE,QAAO;AAAA,QACT,OAAO;AACL,gBAAM,QAAQ,MAAM,IAAI,OAAO,QAAQD,MAAK;AAC5C,UAAAC,QACE,MAAM,SAAS,cACX,8EACA,gCAAgC,MAAM,UAAU;AAAA,QACxD;AACA,YAAI,QAAQ,KAAK,cAAc;AAC7B,gBAAM,IAAI,MAAM,IAAI,SAAS,0BAA0B,QAAQ,KAAK,UAAU,GAAGA,OAAM;AAAA,YACrF,YAAY;AAAA,UACd,CAAC;AAAA;AAED,gBAAM,IAAI,KAAKD,OAAM,SAAS,OAAO,qBAAqB,sBAAsB;AAAA,YAC9E,SAAS,QAAQ,KAAK;AAAA,YACtB,MAAM,QAAQ,KAAK;AAAA,YACnB,MAAAC;AAAA,UACF,CAAC,EAAE,MAAM,MAAM,IAAI,IAAI,qCAAqC,CAAC;AAC/D,eAAO,EAAE,UAAU,KAAK;AAAA,MAC1B;AACA,YAAM,cAAc,EACjB,OAAO;AAAA,QACN,MAAM,EAAE,QAAQ,eAAe;AAAA,QAC/B,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,QACjC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,QACjC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAAA,QAChD,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS;AAAA,QAC/C,SAAS,EACN,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EACtE,SAAS;AAAA,QACZ,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,MACpC,CAAC,EACA,UAAU,KAAK;AAClB,UAAI,YAAY,SAAS;AACvB,cAAM,SAAS,OAAO,WAAmD;AACvE,cAAI,YAAY,KAAK,WAAW;AAC9B,kBAAM,IAAI,KAAK,sBAAsB;AAAA,cACnC,SAAS,YAAY,KAAK,QAAQ;AAAA,cAClC,MAAM,YAAY,KAAK,KAAK;AAAA,cAC5B,GAAI,YAAY,KAAK,SAAS,aAAa,OACvC,CAAC,IACD,EAAE,WAAW,YAAY,KAAK,QAAQ,UAAU;AAAA,cACpD,MAAM,GAAG,OAAO,OAAO,IAAI,OAAO,WAAW,OAAO,cAAc,EAAE;AAAA,YACtE,CAAC,EAAE,MAAM,MAAM,IAAI,IAAI,sCAAsC,CAAC;AAChE,iBAAO,EAAE,UAAU,OAAO,SAAS,OAAO;AAAA,QAC5C;AACA,cAAMF,aAAY,MAAM;AAAA,UACtB;AAAA,UACA,YAAY,KAAK,KAAK;AAAA,UACtB,YAAY,KAAK,KAAK;AAAA,QACxB;AACA,cAAM,KAAK,MAAM,UAAU,KAAKA,UAAS;AACzC,YAAI,OAAO,OAAO,SAAU,QAAO,OAAO,EAAE;AAC5C,cAAM,QAAQ,YAAY,KAAK,QAAQ,CAAC,GAAG;AAC3C,YAAI,SAAS,KAAM,QAAO,EAAE,SAAS,MAAM,QAAQ,YAAY;AAC/D,cAAM,QAAQ,EACX,OAAO;AAAA,UACN,YAAY,EAAE,OAAO;AAAA,UACrB,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAAA,UACrE,SAAS;AAAA,QACX,CAAC,EACA,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,kBAAkB,KAAK,CAAC,CAAC;AACnE,YACE,CAAC,MAAM,WACP,MAAM,KAAK,UAAU,OAAOA,WAAU,MACtC,MAAM,KAAK,UAAU,WAAWA,WAAU;AAE1C,iBAAO,OAAO;AAAA,YACZ,SAAS;AAAA,YACT,SAAS,MAAM,UACX,iDACA;AAAA,UACN,CAAC;AACH,cAAM,MAAM,YAAY,YAAY,KAAK,YAAY;AACrD,YAAI,OAAO;AACT,gBAAM,IAAI,MAAM;AAAA,YACd,SAAS,0BAA0B,MAAM,KAAK,UAAU;AAAA,YACxD,EAAE,IAAI;AAAA,YACN,EAAE,YAAY,KAAK;AAAA,UACrB;AACF,cAAM,UAAU,CAACG,WAAU,mDACzB,gBAAgB;AAAA,UACd;AAAA,UACA,YAAY,MAAM,KAAK;AAAA,UACvB,SAAAA;AAAA,UACA,SAAS,YAAY,KAAK,SAAS;AAAA,UACnC,MAAM,YAAY,KAAK,KAAK;AAAA,QAC9B,CAAC;AACH,cAAM,YAAY,MAAM,IAAI,MAAM;AAAA,UAChC,SAAS,2BAA2B,MAAM,KAAK,UAAU;AAAA,QAC3D;AACA,YAAI,aAAa,MAAM;AACrB,gBAAM;AAAA,YACJ,cAAc,aAAa,8CAA8C;AAAA,UAC3E;AACA,iBAAO,EAAE,UAAU,KAAK;AAAA,QAC1B;AACA,cAAMC,UAAS,MAAM,IAAI,UAAU,QAAQ;AAAA,UACzC,YAAY,MAAM,KAAK;AAAA,UACvB,SAAS,MAAM,KAAK;AAAA,UACpB;AAAA,QACF,CAAC;AACD,YAAI,aAAaA,QAAQ,QAAO,OAAOA,OAAM;AAC7C,cAAM,IAAI,MAAM;AAAA,UACd,SAAS,2BAA2B,MAAM,KAAK,UAAU;AAAA,UACzDA,QAAO,WAAW,aAAa;AAAA,UAC/B;AAAA,YACE,YAAY;AAAA,UACd;AAAA,QACF;AACA,cAAM,QAAQA,QAAO,WAAW,8CAA8C,MAAS;AACvF,eAAOA,QAAO,WACV,EAAE,UAAU,KAAK,IACjB;AAAA,UACE,UAAU;AAAA,UACV,SAAS;AAAA,YACP,SAAS;AAAA,YACT,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACN;AACA,YAAM,WAAW,eAAe,UAAU,KAAK;AAC/C,UAAI,CAAC,SAAS,WAAW,SAAS,KAAK,SAAS,QAAQ,SAAS,KAAK,WAAW;AAC/E,eAAO,EAAE,SAAS,MAAM,QAAQ,eAAe;AACjD,YAAM,QAAQ,SAAS,KAAK;AAC5B,UAAI,MAAM,SAAS,qBAAqB,MAAM,SAAS,kBAAkB;AACvE,YAAI,MAAM,SAAS,mBAAmB;AACpC,gBAAM,WAAW;AAAA,YACf;AAAA,YACA,MAAM,SAAS,KAAK;AAAA,YACpB,YAAY,SAAS,KAAK,iBAAiB;AAAA,YAC3C,QAAQ;AAAA,UACV,CAAC;AAAA,QACH,OAAO;AACL,gBAAM,SAAS,EACZ,OAAO;AAAA,YACN,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,YACrC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,UACrC,CAAC,EACA,UAAU,MAAM,MAAM;AACzB,cAAI,CAAC,OAAO,QAAS,QAAO,EAAE,SAAS,MAAM,QAAQ,qBAAqB;AAC1E,cAAI,OAAO,KAAK,IAAI,SAAS;AAC3B,kBAAM,WAAW;AAAA,cACf;AAAA,cACA,MAAM,SAAS,KAAK;AAAA,cACpB,YAAY,SAAS,KAAK,iBAAiB;AAAA,cAC3C,QAAQ;AAAA,YACV,CAAC;AAAA;AAED,uBAAW,QAAQ,OAAO,KAAK,OAAO;AACpC,oBAAM,SAAS,mBAAmB;AAAA,gBAChC,MAAM,IAAI,MAAM,IAAI,SAAS,mBAAmB,SAAS,KAAK,SAAS,IAAI,CAAC;AAAA,cAC9E;AACA,oBAAMJ,aAAY,OAAO,UACrB,OAAO,OACP,MAAM,aAAa,KAAK,SAAS,KAAK,SAAS,IAAI;AACvD,oBAAM,IAAI,OAAO,OAAO,EAAE,WAAAA,YAAW,QAAQ,mBAAmB,CAAC;AACjE,oBAAM,IAAI,MAAM,IAAI,SAAS,mBAAmB,SAAS,KAAK,SAAS,IAAI,GAAG,IAAI;AAAA,YACpF;AAAA,QACJ;AACA,eAAO,EAAE,UAAU,KAAK;AAAA,MAC1B;AACA,UAAI,MAAM,SAAS,eAAe;AAChC,cAAM,UAAU,gBAAgB,MAAM,KAAK,UAAU,MAAM,IAAI;AAC/D,YAAI,QAAQ,WAAW,QAAQ,KAAK,YAAY;AAC9C,gBAAM,IAAI,OAAO,OAAO;AAAA,YACtB,WAAW;AAAA,cACT,IAAI,QAAQ,KAAK,iBAAiB,MAAM,QAAQ,KAAK;AAAA,cACrD,QAAQ,QAAQ,KAAK,iBAAiB,iBAAiB,SAAS,KAAK;AAAA,YACvE;AAAA,YACA,QAAQ;AAAA,UACV,CAAC;AACH,eAAO,EAAE,SAAS,MAAM,QAAQ,YAAY;AAAA,MAC9C;AACA,UACE,MAAM,SAAS,cACd,MAAM,YAAY,qBAAqB,MAAM,YAAY,oBAC1D;AACA,cAAM,UACJ,MAAM,YAAY,qBAClB,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,WAAW,EAAE,CAAC,EAAE,UAAU,MAAM,OAAO,EAAE;AACzE,cAAM,WAAW,cAAc,UAAU,UAAU,MAAM,mBAAmB,MAAM,OAAO;AACzF,YAAI,CAAC,SAAS,WAAW,SAAS,KAAK,QAAQ,QAAQ,OAAO,MAAM,YAAY;AAC9E,iBAAO,EAAE,SAAS,MAAM,QAAQ,mBAAmB;AACrD,YAAI,SAAS,KAAK,UAAU,QAAQ,SAAS,KAAK,YAAY;AAC5D,iBAAO,EAAE,SAAS,MAAM,QAAQ,cAAc;AAChD,cAAM,YACJ,SAAS,KAAK,OAAO,OAAO,MAAM,eAAe,WAAW,MAAM,aAAa;AACjF,YAAI,aAAa,KAAM,QAAO,EAAE,SAAS,MAAM,QAAQ,mBAAmB;AAC1E,cAAM,SAAS,qBAAqB;AAAA,UAClC,MAAM,IAAI,MAAM;AAAA,YACd,SAAS,gBAAgB,SAAS,KAAK,SAAS,MAAM,SAAS,SAAS;AAAA,UAC1E;AAAA,QACF;AACA,YAAI,CAAC,OAAO,QAAS,QAAO,EAAE,SAAS,MAAM,QAAQ,iBAAiB;AACtE,cAAMC,SAAQ,OAAO,KAAK;AAC1B,cAAM,KAAK,MAAM;AAAA,UACf;AAAA,UACA,MAAM,aAAa,KAAK,SAAS,KAAK,SAAS,SAAS,KAAK,IAAI;AAAA,QACnE;AACA,YAAI,OAAO,OAAO,SAAU,QAAO,EAAE,UAAU,OAAO,SAAS,GAAG;AAClE,cAAM,QAAQ,MAAM,IAAI,OAAO,QAAQA,MAAK;AAC5C,YAAI,MAAM,SAAS,YAAa,QAAO,EAAE,SAAS,MAAM,QAAQ,cAAc;AAC9E,cAAMI,OAAM,OAAO,KAAK;AACxB,cAAM,aAAa,CAAC,UAChB,MAAM,eAAe,KAAK,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,OAAO,IACzE;AACJ,YAAI,cAAc,QAAQ,WAAW,WAAW;AAC9C,iBAAO,EAAE,SAAS,MAAM,QAAQ,gBAAgB;AAClD,eAAO;AAAA,UACL,CAAC,UACG,MAAM,IAAI,aAAa,MAAM,YAAY,EAAE,KAAK;AAAA,YAC9C,aAAaA;AAAA,YACb;AAAA,YACA,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,cAAc;AAAA,cACtB;AAAA,YACF;AAAA,UACF,CAAC,IACD,MAAM,IACH,aAAa,MAAM,YAAY,EAC/B,OAAO,EAAE,aAAaA,MAAK,GAAG,CAAC,EAC/B,KAAK,CAACD,YAAY,aAAaA,UAASA,UAAS,EAAE,WAAWC,KAAI,CAAE;AAAA,QAC7E;AAAA,MACF;AACA,UAAI,MAAM,SAAS,oBAAoB,MAAM,SAAS,oBAAoB;AACxE,cAAMC,UAAS,EACZ,OAAO;AAAA,UACN,MAAM,EAAE,OAAO;AAAA,UACf,UAAU,EAAE,OAAO;AAAA,UACnB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,EAAE,CAAC;AAAA,QACxD,CAAC,EACA,UAAU,KAAK;AAClB,YAAI,CAACA,QAAO,QAAS,QAAO,EAAE,SAAS,MAAM,QAAQ,uBAAuB;AAC5E,cAAM,SAAS,qBAAqB;AAAA,UAClC,MAAM,IAAI,MAAM;AAAA,YACd;AAAA,cACE;AAAA,cACA,SAAS,KAAK;AAAA,cACdA,QAAO,KAAK,KAAK;AAAA,cACjBA,QAAO,KAAK,KAAK;AAAA,YACnB;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAAC,OAAO,QAAS,QAAO,EAAE,SAAS,MAAM,QAAQ,iBAAiB;AACtE,YAAIA,QAAO,KAAK,SAAU,MAAM,OAAO,KAAK,SAAS,KAAK,OAAO;AAC/D,iBAAO,EAAE,SAAS,MAAM,QAAQ,eAAe;AACjD,cAAM,KAAK,MAAM;AAAA,UACf;AAAA,UACA,MAAM,aAAa,KAAK,SAAS,KAAK,SAASA,QAAO,KAAK,IAAI;AAAA,QACjE;AACA,YAAI,OAAO,OAAO,SAAU,QAAO,EAAE,UAAU,OAAO,SAAS,GAAG;AAClE,cAAM,QAAQ,MAAM,IAAI,OAAO,QAAQ,OAAO,KAAK,KAAK;AACxD,YAAI,MAAM,SAAS,YAAa,QAAO,EAAE,SAAS,MAAM,QAAQ,cAAc;AAC9E,cAAM,SACJ,OAAO,KAAK,UAAU,OAClB,EAAE,SAAS,EAAE,aAAa,OAAO,KAAK,aAAa,QAAQ,OAAO,KAAK,OAAO,EAAE,IAChF;AAAA,UACE,aAAa,OAAO,KAAK;AAAA,QAC3B;AACN,cAAMF,UAAS,MAAM,IAAI,aAAa,MAAM,YAAY,EAAE,MAAM;AAAA,UAC9D;AAAA,UACA,OAAO,WAAWE,QAAO,KAAK,QAAQ;AAAA,UACtC;AAAA,UACA,IAAI,MAAM,SAAS,mBAAmB,QAAQ;AAAA,QAChD,CAAC;AACD,eAAO,aAAaF,UAAS,EAAE,UAAU,OAAO,SAASA,QAAO,IAAI,EAAE,UAAU,KAAK;AAAA,MACvF;AACA,YAAM,SAAS,cAAc,UAAU,KAAK;AAC5C,UACE,CAAC,OAAO,WACR,OAAO,KAAK,QAAQ,QACpB,OAAO,KAAK,MAAM,QAClB,OAAO,KAAK,QAAQ,QACpB,OAAO,KAAK,UAAU,QACrB,OAAO,KAAK,SAAS,iBACpB,EAAE,OAAO,KAAK,SAAS,aAAa,OAAO,KAAK,iBAAiB;AAEnE,eAAO,EAAE,SAAS,MAAM,QAAQ,sBAAsB;AACxD,YAAM,UAAU,cACb,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,EAClF,MAAM,OAAO,IAAI;AACpB,YAAM,QAAQ,SAAS,SAAS,SAAS,KAAK,OAAO;AACrD,UAAI,SAAS,KAAM,QAAO,EAAE,SAAS,MAAM,QAAQ,WAAW;AAC9D,YAAM,OAAO,MAAM,eAAe,KAAK,QAAQ,MAAM,SAAS,KAAK,OAAO;AAC1E,UAAI,KAAK,WAAW,EAAG,QAAO,EAAE,SAAS,MAAM,QAAQ,gBAAgB;AACvE,YAAM,YAAY,MAAM,aAAa,KAAK,SAAS,KAAK,SAAS,QAAQ,IAAI;AAC7E,YAAM,IAAI,KAAK,iBAAiB;AAAA,QAC9B,SAAS,QAAQ;AAAA,QACjB,WAAW,QAAQ;AAAA,QACnB,MAAM;AAAA,MACR,CAAC,EAAE,MAAM,MAAM,IAAI,IAAI,oCAAoC,CAAC;AAC5D,YAAM,MAAM,YAAY,MAAM,UAAU,OAAO,QAAQ,EAAE;AACzD,YAAM,cAAc,SAAS,KAAK;AAClC,YAAM,cAAc,YAClB,OAAO,YAAY,mBACf,WAAW,EAAE,KAAK,SAAS,MAAM,YAAY,CAAC,EAAE,MAAM,MAAM;AAC1D,YAAI,IAAI,kDAAkD;AAC1D,eAAO,CAAC;AAAA,MACV,CAAC,IACD,CAAC;AACP,YAAM,IAAI,MAAM;AAAA,QACd,SAAS,gBAAgB,SAAS,KAAK,SAAS,QAAQ,SAAS,QAAQ,EAAE;AAAA,QAC3E,gBAAgB,MAAM,EAAE,OAAO,aAAa,IAAI,CAAC;AAAA,QACjD;AAAA,MACF;AACA,YAAM,SAAS,MAAM,qBAAqB;AAAA,QACxC;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB,MAAM,SAAS;AAAA,QAChC;AAAA,QACA,aAAa;AAAA,QACb;AAAA,QACA,KAAK;AAAA,UACH,aAAa;AAAA,UACb,SAAS,QAAQ;AAAA,UACjB,IAAI,QAAQ;AAAA,UACZ,UAAU,QAAQ,aAAa,QAAQ;AAAA,UACvC,WAAW,UAAU;AAAA,UACrB,MAAM,QAAQ;AAAA,UACd,QAAQ,UAAU,UAAU,SAAS,KAAK;AAAA,QAC5C;AAAA,MACF,CAAC;AACD,UAAI,cAAc,UAAU,CAAC,OAAO;AAClC,cAAM,IAAI,KAAK,MAAM,SAAS,OAAO,qBAAqB,sBAAsB;AAAA,UAC9E,SAAS,QAAQ;AAAA,UACjB,MAAM,QAAQ;AAAA,UACd,GAAI,QAAQ,aAAa,OAAO,CAAC,IAAI,EAAE,WAAW,QAAQ,UAAU;AAAA,UACpE,MAAM,GAAG,OAAO,QAAQ,OAAO,IAAI,OAAO,QAAQ,WAAW,OAAO,QAAQ,cAAc,EAAE;AAAA,QAC9F,CAAC,EAAE,MAAM,MAAM,IAAI,IAAI,qCAAqC,CAAC;AAC/D,aAAO;AAAA,IACT;AAAA,IACA,QAAQ;AAAA,MACN,kBAAkB,OAAO,MAAM,QAAQ;AACrC,cAAM,MAAM,SAAS,gBAAgB,iBAAiB,IAAI,OAAO,KAAK,GAAG,KAAK,QAAQ,EAAE;AACxF,YAAK,MAAM,IAAI,MAAM,IAAI,GAAG,KAAM,KAAM;AACxC,cAAM,EAAE,SAAS,UAAU,IAAI,SAAS,GAAG;AAC3C,YAAI,WAAW,KAAM;AACrB,cAAM,SAAS,YAAY;AAAA,UACzB,MAAM,IAAI,KAAK,oBAAoB;AAAA,YACjC;AAAA,YACA,GAAI,aAAa,OAAO,CAAC,IAAI,EAAE,UAAU;AAAA,YACzC,MAAM,QAAQ,KAAK,OAAO,WAAW;AAAA,EAAc,OAAO,KAAK,QAAQ,OAAO,CAAC,GAAG;AAAA,cAChF;AAAA,cACA;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AACA,cAAM,IAAI,MAAM,IAAI,KAAK,OAAO,IAAI,iBAAiB;AAAA,MACvD;AAAA,MACA,iBAAiB,OAAO,MAAM,QAAQ;AACpC,cAAM,QAAQ,IAAI,MAAM,IAAI,GAAG,QAAS,MAAM,aAAa,GAAG;AAC9D,cAAM,QACJ,KAAK,MAAM,SAAS,UAAU,OAAO,KAAK,MAAM,SAAS,WAAW,KAAK,MAAM,OAAO;AACxF,cAAM,OAAO,QAAQ;AACrB,YAAI,MAAM,IAAI,EAAE,KAAK,CAAC;AACtB,cAAM,YAAY,KAAK,EAAE,MAAM,OAAO,OAAO,YAAY,CAAC,KAAK,SAAS,EAAE,CAAC;AAAA,MAC7E;AAAA,MACA,kBAAkB,OAAO,MAAM,QAAQ;AACrC,cAAM,YAAY,KAAK;AAAA,UACrB,MAAM,eAAe,MAAM,IAAI,MAAM,IAAI,GAAG,QAAS,MAAM,aAAa,GAAG,CAAE;AAAA,UAC7E,OAAO;AAAA,UACP,YAAY,KAAK,UAAU,IAAI,CAAC,YAAY,QAAQ,EAAE,KAAK,CAAC;AAAA,QAC9D,CAAC;AAAA,MACH;AAAA,MACA,oBAAoB,OAAO,MAAM,QAAQ;AACvC,cAAM,eAAe,SAAS,4BAA4B,KAAK,UAAU;AACzE,YAAK,MAAM,IAAI,MAAM,IAAI,YAAY,KAAM,KAAM;AACjD,cAAM,EAAE,SAAS,UAAU,IAAI,SAAS,GAAG;AAC3C,cAAM,OAAO,UAAU,IAAI,OAAO,KAAK,MAAM,KAAK,UAAU,IAAI,OAAO,KAAK,WAAW;AACvF,cAAM,cAAc,UAAU,IAAI,OAAO,KAAK,WAAW,KAAK;AAC9D,cAAM,SAAS,UAAU,IAAI,OAAO,KAAK,QAAQ;AACjD,YAAI,WAAW,QAAQ,QAAQ,KAAM;AACrC,cAAM,UAAU,gBAAgB,KAAK,OAAO;AAC5C,cAAM,WAAyB,CAAC;AAChC,mBAAW,UAAU,SAAS;AAC5B,gBAAM,QAAQ,OAAO,WAAW;AAChC,gBAAM,IAAI,MAAM;AAAA,YACd,SAAS,kBAAkB,KAAK;AAAA,YAChC;AAAA,cACE,YAAY,KAAK;AAAA,cACjB,WAAW,EAAE,IAAI,eAAe,MAAM,GAAI,UAAU,OAAO,CAAC,IAAI,EAAE,OAAO,EAAG;AAAA,cAC5E,SAAS,OAAO;AAAA,YAClB;AAAA,YACA,EAAE,YAAY,KAAK;AAAA,UACrB;AACA,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,MAAM,EAAE,MAAM,cAAc,MAAM,OAAO,MAAM;AAAA,YAC/C,WAAW,kBAAkB,SAAS,MAAM;AAAA,YAC5C;AAAA,UACF,CAAC;AAAA,QACH;AACA,YAAI;AACF,gBAAM,IAAI,KAAK,sBAAsB;AAAA,YACnC;AAAA,YACA;AAAA,YACA,GAAI,aAAa,OAAO,CAAC,IAAI,EAAE,UAAU;AAAA,YACzC,MAAM,GAAG,gBAAgB,KAAK,OAAO,CAAC;AAAA,EAAK,SAAS,WAAW,IAAI,2BAAsB,yBAAyB;AAAA,YAClH,GAAI,SAAS,WAAW,IACpB,CAAC,IACD;AAAA,cACE,QAAQ;AAAA,gBACN;AAAA,kBACE,MAAM;AAAA,kBACN,MAAM,EAAE,MAAM,cAAc,MAAM,gBAAgB,KAAK,OAAO,EAAE;AAAA,gBAClE;AAAA,gBACA,EAAE,MAAM,WAAW,SAAS;AAAA,cAC9B;AAAA,YACF;AAAA,UACN,CAAC;AAAA,QACH,QAAQ;AACN,gBAAM,IAAI,KAAK,oBAAoB;AAAA,YACjC;AAAA,YACA,GAAI,aAAa,OAAO,CAAC,IAAI,EAAE,UAAU;AAAA,YACzC,MAAM;AAAA,UACR,CAAC;AAAA,QACH;AACA,cAAM,IAAI,MAAM,IAAI,cAAc,MAAM,EAAE,YAAY,KAAK,CAAC;AAAA,MAC9D;AAAA,MACA,qBAAqB,OAAO,MAAM,QAAQ;AACxC,cAAM,IAAI,MAAM,IAAI,SAAS,2BAA2B,KAAK,UAAU,GAAG,YAAY;AAAA,UACpF,YAAY;AAAA,QACd,CAAC;AACD,cAAM,EAAE,SAAS,UAAU,IAAI,SAAS,GAAG;AAC3C,cAAM,gBAAgB;AAAA,UACpB;AAAA,UACA,YAAY,KAAK;AAAA,UACjB,SAAS,WAAW;AAAA,UACpB,MACE,UAAU,IAAI,OAAO,KAAK,MAAM,KAChC,UAAU,IAAI,OAAO,KAAK,WAAW,KACrC;AAAA,UACF,UAAU,aAAa;AAAA,QACzB,CAAC;AAAA,MACH;AAAA,MACA,kBAAkB,OAAO,MAAM,QAAQ;AACrC,YAAI,KAAK,WAAW,QAAQ,KAAK,YAAY,WAAW,QAAQ,GAAG;AACjE,gBAAM,MAAM,iBAAiB;AAAA,YAC3B,UAAU;AAAA,YACV,OAAO,IAAI,OAAO;AAAA,YAClB,aAAa,KAAK;AAAA,YAClB,WAAW,KAAK,QAAQ;AAAA,UAC1B,CAAC;AACD,cAAI,OAAO,KAAM;AACjB,gBAAMG,SAAQ,EAAE,OAAO,EAAE,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AAC3D,gBAAM,EAAE,SAAAC,SAAQ,IAAI,SAAS,GAAG;AAChC,cAAI,CAACD,OAAM,WAAWC,YAAW,KAAM;AACvC,gBAAM,SAAS,oBAAoB;AAAA,YACjC,MAAM,IAAI,KAAK,eAAe;AAAA,cAC5B,SAAAA;AAAA,cACA,IAAID,OAAM;AAAA,cACV,MAAM,QAAQ,KAAK,OAAO,WAAW;AAAA,EAAc,OAAO,KAAK,QAAQ,OAAO,CAAC,GAAG;AAAA,gBAChF;AAAA,gBACA;AAAA,cACF;AAAA,YACF,CAAC;AAAA,UACH;AACA,cAAI,OAAO,UAAU;AACnB,kBAAM,IAAI,MAAM,IAAI,KAAK,EAAE,SAAS,KAAK,GAAG,iBAAiB;AAC/D;AAAA,QACF;AACA,YAAI,KAAK,WAAW,MAAM;AACxB,gBAAM,EAAE,SAAAC,UAAS,UAAU,IAAI,SAAS,GAAG;AAC3C,cAAIA,YAAW,KAAM;AACrB,gBAAM,MAAM;AAAA,YACV;AAAA,YACA,iBAAiB,IAAI,OAAO,KAAK;AAAA,YACjC,KAAK;AAAA,UACP;AACA,gBAAMD,SAAQ,EACX,OAAO,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,EAC3C,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AACrC,gBAAM,OAAO;AAAA,EAAsB,OAAO,KAAK,QAAQ,OAAO,CAAC,GAAG,MAAM,GAAG,KAAK;AAChF,cAAIA,OAAM,WAAWA,OAAM,KAAK,SAAS,KAAM;AAC/C,gBAAM,SAAS,MAAM,IAAI,KAAKA,OAAM,UAAU,gBAAgB,oBAAoB;AAAA,YAChF,SAAAC;AAAA,YACA,GAAID,OAAM,UAAU,EAAE,IAAIA,OAAM,KAAK,GAAG,IAAI,aAAa,OAAO,CAAC,IAAI,EAAE,UAAU;AAAA,YACjF;AAAA,UACF,CAAC;AACD,gBAAM,UACJA,OAAM,WAAW,oBAAoB,MAAM,MAAM,EAAE,UAAU;AAC/D,gBAAM,UAAU,UACZ,MAAM,IAAI,KAAK,oBAAoB;AAAA,YACjC,SAAAC;AAAA,YACA,GAAI,aAAa,OAAO,CAAC,IAAI,EAAE,UAAU;AAAA,YACzC;AAAA,UACF,CAAC,IACD;AACJ,gBAAM,IAAI,MAAM;AAAA,YACd;AAAA,YACA,EAAE,IAAID,OAAM,WAAW,CAAC,UAAUA,OAAM,KAAK,KAAK,YAAY,MAAM,OAAO,EAAE,IAAI,KAAK;AAAA,YACtF;AAAA,UACF;AACA;AAAA,QACF;AACA,cAAM,EAAE,QAAQ,IAAI,SAAS,GAAG;AAChC,cAAM,QAAQ,EACX,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EACzB,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,KAAK,KAAK,OAAO,CAAC,CAAC;AAC7D,cAAM,KAAK,MAAM,UAAU,MAAM,KAAK,KAAK;AAC3C,YAAI,WAAW,QAAQ,MAAM;AAC3B,gBAAM,IAAI,KAAK,eAAe;AAAA,YAC5B;AAAA,YACA;AAAA,YACA,MAAM,OAAO,KAAK,QAAQ,OAAO,EAAE,MAAM,GAAG,KAAK;AAAA,UACnD,CAAC;AAAA,MACL;AAAA,MACA,mBAAmB,OAAO,MAAM,QAAQ;AACtC,YAAI,KAAK,WAAW,QAAQ,KAAK,YAAY,WAAW,QAAQ,GAAG;AACjE,gBAAM,MAAM,iBAAiB;AAAA,YAC3B,UAAU;AAAA,YACV,OAAO,IAAI,OAAO;AAAA,YAClB,aAAa,KAAK;AAAA,YAClB,WAAW,KAAK,QAAQ;AAAA,UAC1B,CAAC;AACD,cAAI,OAAO,KAAM;AACjB,gBAAMA,SAAQ,EAAE,OAAO,EAAE,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AAC3D,gBAAM,EAAE,SAAAC,SAAQ,IAAI,SAAS,GAAG;AAChC,cAAI,CAACD,OAAM,WAAWC,YAAW,KAAM;AACvC,gBAAM,IAAI,KAAK,eAAe,EAAE,SAAAA,UAAS,IAAID,OAAM,KAAK,CAAC;AACzD,gBAAM,IAAI,MAAM,IAAI,KAAK,EAAE,SAAS,KAAK,GAAG,iBAAiB;AAC7D;AAAA,QACF;AACA,YAAI,KAAK,WAAW,MAAM;AACxB,gBAAM,MAAM;AAAA,YACV;AAAA,YACA,iBAAiB,IAAI,OAAO,KAAK;AAAA,YACjC,KAAK;AAAA,UACP;AACA,gBAAMA,SAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,MAAM,IAAI,MAAM,IAAI,GAAG,CAAC;AAC7E,gBAAM,EAAE,SAAAC,SAAQ,IAAI,SAAS,GAAG;AAChC,cAAID,OAAM,WAAWC,YAAW,MAAM;AACpC,kBAAM,IAAI,KAAK,eAAe,EAAE,SAAAA,UAAS,IAAID,OAAM,KAAK,GAAG,CAAC;AAC5D,kBAAM,IAAI,MAAM,IAAI,KAAK,IAAI;AAAA,UAC/B;AACA;AAAA,QACF;AACA,cAAM,EAAE,QAAQ,IAAI,SAAS,GAAG;AAChC,cAAM,QAAQ,EACX,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EACzB,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,KAAK,KAAK,OAAO,CAAC,CAAC;AAC7D,cAAM,KAAK,MAAM,UAAU,MAAM,KAAK,KAAK;AAC3C,YAAI,WAAW,QAAQ,MAAM,KAAM,OAAM,IAAI,KAAK,eAAe,EAAE,SAAS,GAAG,CAAC;AAAA,MAClF;AAAA,MACA,kBAAkB,OAAO,MAAM,QAAQ;AACrC,cAAM,EAAE,QAAQ,IAAI,SAAS,GAAG;AAChC,cAAM,SAAS,KAAK,WAAW,QAAQ,KAAK,YAAY,WAAW,QAAQ;AAC3E,cAAM,YAAY,iBAAiB;AAAA,UACjC,UAAU;AAAA,UACV,OAAO,IAAI,OAAO;AAAA,UAClB,aAAa,KAAK;AAAA,QACpB,CAAC;AACD,cAAM,WAAW,EACd,OAAO,EACP,UAAU,aAAa,OAAO,OAAO,MAAM,IAAI,MAAM,IAAI,SAAS,CAAC;AACtE,YAAI,UAAU,CAAC,SAAS,QAAS;AACjC,cAAM,QAAQ,EACX,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EACzB,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,KAAK,KAAK,OAAO,CAAC,CAAC;AAC7D,cAAM,OAAO,WAAW,KAAK,KAAK;AAClC,cAAM,YACJ,UAAU,SAAS,UACf,SAAS,OACT,KAAK,WAAW,OACd,UAAU,IAAI,OAAO,KAAK,IAAI,IAC9B,MAAM,UACJ,MAAM,KAAK,KACX;AACV,YAAI,WAAW,QAAQ,aAAa,QAAQ,QAAQ;AAClD,gBAAM,qBAAqB;AAAA,YACzB;AAAA,YACA,KAAK,SAAS,YAAY;AAAA,YAC1B,UAAU;AAAA,YACV,MAAM,MACJ,kBAAkB;AAAA,cAChB,OAAO,IAAI;AAAA,cACX,KAAK;AAAA,gBACH;AAAA,gBACA,IAAI,OAAO,MAAM,UAAU;AAAA,gBAC3B;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA,WAAW,KAAK;AAAA,cAChB,KAAK,YAAY;AACf,sBAAM,WAAW,oBAAoB;AAAA,kBACnC,MAAM,IAAI,KAAK,iBAAiB,EAAE,SAAS,WAAW,KAAK,CAAC;AAAA,gBAC9D;AACA,uBAAO,SAAS,UAAU;AAAA,cAC5B;AAAA,YACF,CAAC;AAAA,UACL,CAAC;AAAA,MACL;AAAA,MACA,oBAAoB,OAAO,MAAM,QAAQ;AACvC,cAAM,EAAE,QAAQ,IAAI,SAAS,GAAG;AAChC,cAAM,SAAS,KAAK,WAAW,QAAQ,KAAK,YAAY,WAAW,QAAQ;AAC3E,cAAM,YAAY,iBAAiB;AAAA,UACjC,UAAU;AAAA,UACV,OAAO,IAAI,OAAO;AAAA,UAClB,aAAa,KAAK;AAAA,QACpB,CAAC;AACD,cAAM,WAAW,EACd,OAAO,EACP,UAAU,aAAa,OAAO,OAAO,MAAM,IAAI,MAAM,IAAI,SAAS,CAAC;AACtE,YAAI,UAAU,CAAC,SAAS,QAAS;AACjC,cAAM,QAAQ,EACX,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EACzB,UAAU,MAAM,IAAI,MAAM,IAAI,SAAS,KAAK,KAAK,OAAO,CAAC,CAAC;AAC7D,cAAM,OAAO,WAAW,KAAK,KAAK;AAClC,cAAM,YACJ,UAAU,SAAS,UACf,SAAS,OACT,KAAK,WAAW,OACd,UAAU,IAAI,OAAO,KAAK,IAAI,IAC9B,MAAM,UACJ,MAAM,KAAK,KACX;AACV,YAAI,WAAW,QAAQ,aAAa,QAAQ,QAAQ;AAClD,gBAAM,qBAAqB;AAAA,YACzB;AAAA,YACA,KAAK,SAAS,YAAY;AAAA,YAC1B,UAAU;AAAA,YACV,MAAM,MACJ,qBAAqB;AAAA,cACnB,OAAO,IAAI;AAAA,cACX,KAAK;AAAA,gBACH;AAAA,gBACA,IAAI,OAAO,MAAM,UAAU;AAAA,gBAC3B;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,cACA,WAAW,KAAK;AAAA,cAChB,QAAQ,YAAY;AAClB,sBAAM,IAAI,KAAK,oBAAoB,EAAE,SAAS,WAAW,KAAK,CAAC;AAAA,cACjE;AAAA,YACF,CAAC;AAAA,UACL,CAAC;AAAA,MACL;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAEA,MAAM,aAAa,OAAO,SAID;AACvB,QAAM,EAAE,KAAK,QAAQ,IAAI;AACzB,MAAI,QAAQ,WAAW,KAAM,QAAO,CAAC;AACrC,QAAM,WAA4C,CAAC;AACnD,MAAI;AACJ,WAAS,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG;AACtC,UAAM,SAAS,EACZ,OAAO;AAAA,MACN,UAAU,EAAE,MAAM,aAAa;AAAA,MAC/B,mBAAmB,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS;AAAA,IAC/E,CAAC,EACA;AAAA,MACC,MAAM;AAAA,QACJ;AAAA,QACA,QAAQ,aAAa,OAAO,0BAA0B;AAAA,QACtD;AAAA,UACE,SAAS,QAAQ;AAAA,UACjB,OAAO;AAAA,UACP,GAAI,QAAQ,MAAM,OAAO,CAAC,IAAI,EAAE,QAAQ,QAAQ,IAAI,WAAW,MAAM;AAAA,UACrE,GAAI,QAAQ,aAAa,OAAO,CAAC,IAAI,EAAE,IAAI,QAAQ,UAAU;AAAA,UAC7D,GAAI,UAAU,OAAO,CAAC,IAAI,EAAE,OAAO;AAAA,QACrC;AAAA,MACF;AAAA,IACF;AACF,aAAS,KAAK,GAAG,OAAO,QAAQ;AAChC,aAAS,OAAO,mBAAmB;AACnC,QAAI,UAAU,QAAQ,OAAO,WAAW,KAAK,QAAQ,aAAa,KAAM;AAAA,EAC1E;AAEA,MAAI,QAAQ,aAAa,QAAQ,UAAU,QAAQ,OAAO,SAAS,EAAG,QAAO,CAAC;AAC9E,QAAM,SAAS,SAAS,KAAK,CAAC,GAAG,MAAM,OAAO,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG;AACvF,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAU,oBAAI,IAA2B;AAC/C,aAAW,WAAW,QAAQ;AAC5B,QACE,QAAQ,QAAQ,QAChB,QAAQ,QAAQ,QAChB,QAAQ,UAAU,QAClB,QAAQ,OAAO,QAAQ;AAEvB;AACF,QAAI,CAAC,QAAQ,IAAI,QAAQ,IAAI,GAAG;AAC9B,YAAM,YAAY,MAAM,aAAa,KAAK,KAAK,MAAM,QAAQ,IAAI;AACjE,YAAM,SAAS,MAAM,IAAI,OAAO,QAAQ,SAAS;AACjD,cAAQ,IAAI,QAAQ,MAAM,OAAO,SAAS,WAAW,OAAO,cAAc,IAAI;AAAA,IAChF;AACA,UAAM,OAAO,QAAQ,IAAI,QAAQ,IAAI;AACrC,QAAI,QAAQ,MAAM;AAChB,YAAM,OAAO,MAAM,eAAe,KAAK,QAAQ,MAAM,KAAK,IAAI;AAC9D,UAAI,KAAK,SAAS,EAAG,OAAM,KAAK,GAAG,IAAI,KAAK,IAAI,EAAE;AAAA,IACpD;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": ["receipt", "principal", "place", "text", "message", "result", "key", "parsed", "saved", "channel"]
7
+ }
@@ -0,0 +1,7 @@
1
+ export declare const recordingRawLimit: (encoding: string) => number;
2
+ export declare const recordingWav: (args: {
3
+ chunks: Uint8Array[];
4
+ bytes: number;
5
+ encoding: string;
6
+ sampleRate: number;
7
+ }) => Uint8Array;
@@ -0,0 +1,49 @@
1
+ const SERIALIZED_SEGMENT_LIMIT = 10 * 1024 * 1024;
2
+ const PCM_BYTES_LIMIT = Math.floor((Math.floor((SERIALIZED_SEGMENT_LIMIT - 512) * 3 / 4) - 44) / 2) * 2;
3
+ const recordingRawLimit = (encoding) => {
4
+ if (encoding === "linear16") return PCM_BYTES_LIMIT;
5
+ if (encoding === "mulaw") return PCM_BYTES_LIMIT / 2;
6
+ throw new Error("Recordings require linear16 or mulaw audio.");
7
+ };
8
+ const linearSample = (byte) => {
9
+ const value = ~byte & 255;
10
+ const magnitude = ((value & 15) << 3) + 132 << (value >> 4 & 7);
11
+ return (value & 128) === 0 ? magnitude - 132 : 132 - magnitude;
12
+ };
13
+ const recordingWav = (args) => {
14
+ recordingRawLimit(args.encoding);
15
+ if (!Number.isSafeInteger(args.sampleRate) || args.sampleRate <= 0 || args.sampleRate > 384e3)
16
+ throw new Error("Invalid recording sample rate.");
17
+ const dataBytes = args.encoding === "mulaw" ? args.bytes * 2 : args.bytes + args.bytes % 2;
18
+ const wav = new Uint8Array(44 + dataBytes);
19
+ const view = new DataView(wav.buffer);
20
+ wav.set(new TextEncoder().encode("RIFF"), 0);
21
+ view.setUint32(4, 36 + dataBytes, true);
22
+ wav.set(new TextEncoder().encode("WAVEfmt "), 8);
23
+ view.setUint32(16, 16, true);
24
+ view.setUint16(20, 1, true);
25
+ view.setUint16(22, 1, true);
26
+ view.setUint32(24, args.sampleRate, true);
27
+ view.setUint32(28, args.sampleRate * 2, true);
28
+ view.setUint16(32, 2, true);
29
+ view.setUint16(34, 16, true);
30
+ wav.set(new TextEncoder().encode("data"), 36);
31
+ view.setUint32(40, dataBytes, true);
32
+ let offset = 44;
33
+ for (const chunk of args.chunks) {
34
+ if (args.encoding === "linear16") {
35
+ wav.set(chunk, offset);
36
+ offset += chunk.byteLength;
37
+ } else
38
+ for (const byte of chunk) {
39
+ view.setInt16(offset, linearSample(byte), true);
40
+ offset += 2;
41
+ }
42
+ }
43
+ return wav;
44
+ };
45
+ export {
46
+ recordingRawLimit,
47
+ recordingWav
48
+ };
49
+ //# sourceMappingURL=voice-recording.mjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../src/channels/voice-recording.ts"],
4
+ "sourcesContent": ["const SERIALIZED_SEGMENT_LIMIT = 10 * 1024 * 1024;\n// Base64 and its content-block fields must fit the attachment budget too.\nconst PCM_BYTES_LIMIT =\n Math.floor((Math.floor(((SERIALIZED_SEGMENT_LIMIT - 512) * 3) / 4) - 44) / 2) * 2;\nexport const recordingRawLimit = (encoding: string): number => {\n if (encoding === 'linear16') return PCM_BYTES_LIMIT;\n if (encoding === 'mulaw') return PCM_BYTES_LIMIT / 2;\n throw new Error('Recordings require linear16 or mulaw audio.');\n};\nconst linearSample = (byte: number): number => {\n const value = ~byte & 0xff;\n const magnitude = (((value & 15) << 3) + 132) << ((value >> 4) & 7);\n return (value & 128) === 0 ? magnitude - 132 : 132 - magnitude;\n};\nexport const recordingWav = (args: {\n chunks: Uint8Array[];\n bytes: number;\n encoding: string;\n sampleRate: number;\n}): Uint8Array => {\n recordingRawLimit(args.encoding);\n if (!Number.isSafeInteger(args.sampleRate) || args.sampleRate <= 0 || args.sampleRate > 384_000)\n throw new Error('Invalid recording sample rate.');\n const dataBytes = args.encoding === 'mulaw' ? args.bytes * 2 : args.bytes + (args.bytes % 2);\n const wav = new Uint8Array(44 + dataBytes);\n const view = new DataView(wav.buffer);\n wav.set(new TextEncoder().encode('RIFF'), 0);\n view.setUint32(4, 36 + dataBytes, true);\n wav.set(new TextEncoder().encode('WAVEfmt '), 8);\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, 1, true);\n view.setUint32(24, args.sampleRate, true);\n view.setUint32(28, args.sampleRate * 2, true);\n view.setUint16(32, 2, true);\n view.setUint16(34, 16, true);\n wav.set(new TextEncoder().encode('data'), 36);\n view.setUint32(40, dataBytes, true);\n let offset = 44;\n for (const chunk of args.chunks) {\n if (args.encoding === 'linear16') {\n wav.set(chunk, offset);\n offset += chunk.byteLength;\n } else\n for (const byte of chunk) {\n view.setInt16(offset, linearSample(byte), true);\n offset += 2;\n }\n }\n return wav;\n};\n"],
5
+ "mappings": "AAAA,MAAM,2BAA2B,KAAK,OAAO;AAE7C,MAAM,kBACJ,KAAK,OAAO,KAAK,OAAQ,2BAA2B,OAAO,IAAK,CAAC,IAAI,MAAM,CAAC,IAAI;AAC3E,MAAM,oBAAoB,CAAC,aAA6B;AAC7D,MAAI,aAAa,WAAY,QAAO;AACpC,MAAI,aAAa,QAAS,QAAO,kBAAkB;AACnD,QAAM,IAAI,MAAM,6CAA6C;AAC/D;AACA,MAAM,eAAe,CAAC,SAAyB;AAC7C,QAAM,QAAQ,CAAC,OAAO;AACtB,QAAM,cAAe,QAAQ,OAAO,KAAK,QAAU,SAAS,IAAK;AACjE,UAAQ,QAAQ,SAAS,IAAI,YAAY,MAAM,MAAM;AACvD;AACO,MAAM,eAAe,CAAC,SAKX;AAChB,oBAAkB,KAAK,QAAQ;AAC/B,MAAI,CAAC,OAAO,cAAc,KAAK,UAAU,KAAK,KAAK,cAAc,KAAK,KAAK,aAAa;AACtF,UAAM,IAAI,MAAM,gCAAgC;AAClD,QAAM,YAAY,KAAK,aAAa,UAAU,KAAK,QAAQ,IAAI,KAAK,QAAS,KAAK,QAAQ;AAC1F,QAAM,MAAM,IAAI,WAAW,KAAK,SAAS;AACzC,QAAM,OAAO,IAAI,SAAS,IAAI,MAAM;AACpC,MAAI,IAAI,IAAI,YAAY,EAAE,OAAO,MAAM,GAAG,CAAC;AAC3C,OAAK,UAAU,GAAG,KAAK,WAAW,IAAI;AACtC,MAAI,IAAI,IAAI,YAAY,EAAE,OAAO,UAAU,GAAG,CAAC;AAC/C,OAAK,UAAU,IAAI,IAAI,IAAI;AAC3B,OAAK,UAAU,IAAI,GAAG,IAAI;AAC1B,OAAK,UAAU,IAAI,GAAG,IAAI;AAC1B,OAAK,UAAU,IAAI,KAAK,YAAY,IAAI;AACxC,OAAK,UAAU,IAAI,KAAK,aAAa,GAAG,IAAI;AAC5C,OAAK,UAAU,IAAI,GAAG,IAAI;AAC1B,OAAK,UAAU,IAAI,IAAI,IAAI;AAC3B,MAAI,IAAI,IAAI,YAAY,EAAE,OAAO,MAAM,GAAG,EAAE;AAC5C,OAAK,UAAU,IAAI,WAAW,IAAI;AAClC,MAAI,SAAS;AACb,aAAW,SAAS,KAAK,QAAQ;AAC/B,QAAI,KAAK,aAAa,YAAY;AAChC,UAAI,IAAI,OAAO,MAAM;AACrB,gBAAU,MAAM;AAAA,IAClB;AACE,iBAAW,QAAQ,OAAO;AACxB,aAAK,SAAS,QAAQ,aAAa,IAAI,GAAG,IAAI;AAC9C,kBAAU;AAAA,MACZ;AAAA,EACJ;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,33 @@
1
+ import { type ChannelReceiveContextIface, type ChannelSocketIface, type JsonObject, type JsonValue, type PlaceRef, type PrincipalRef } from '@finalai/agent-provider';
2
+ import * as z from 'zod';
3
+ declare const configSchema: z.ZodObject<{
4
+ baseUrl: z.ZodOptional<z.ZodString>;
5
+ oauthAuthorizeUrl: z.ZodOptional<z.ZodString>;
6
+ oauthTokenUrl: z.ZodOptional<z.ZodString>;
7
+ oauthUserInfoUrl: z.ZodOptional<z.ZodString>;
8
+ oauthClientId: z.ZodOptional<z.ZodString>;
9
+ oauthResource: z.ZodOptional<z.ZodString>;
10
+ voice: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ export type VoiceConfig = z.infer<typeof configSchema>;
13
+ export interface VoiceConnectionOptionsIface<Config> {
14
+ ctx: ChannelReceiveContextIface<Config>;
15
+ socket: ChannelSocketIface;
16
+ principal: PrincipalRef;
17
+ place: PlaceRef;
18
+ encoding: string;
19
+ sampleRate: number;
20
+ voice?: string;
21
+ recording?: boolean;
22
+ }
23
+ export declare const runVoiceConnection: <Config>(options: VoiceConnectionOptionsIface<Config>) => Promise<void>;
24
+ export declare const voiceChannel: (options?: JsonObject) => import("@finalai/agent-provider").ChannelDefinitionIface<{
25
+ baseUrl?: string | undefined;
26
+ oauthAuthorizeUrl?: string | undefined;
27
+ oauthTokenUrl?: string | undefined;
28
+ oauthUserInfoUrl?: string | undefined;
29
+ oauthClientId?: string | undefined;
30
+ oauthResource?: string | undefined;
31
+ voice?: string | undefined;
32
+ }, JsonValue, JsonValue>;
33
+ export {};