@datasynx/agentic-crm 1.5.0 → 1.6.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-BbInMUgp.js","names":["DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR","DATA_DIR"],"sources":["../src/core/oauth-store.ts","../src/sync/microsoft-webhook-handler.ts","../src/sync/slack-webhook-handler.ts","../src/mcp/tools/get-capabilities.ts","../src/mcp/tools/get-active-session.ts","../src/mcp/tools/get-customer-context.ts","../src/mcp/tools/search-customer-knowledge.ts","../src/mcp/tools/list-customers.ts","../src/mcp/tools/log-interaction.ts","../src/mcp/tools/export-customer.ts","../src/mcp/tools/update-customer-facts.ts","../src/core/deal-health.ts","../src/mcp/tools/get-deal-health.ts","../src/mcp/tools/get-pipeline-forecast.ts","../src/mcp/tools/summarize-meeting.ts","../src/mcp/tools/get-pipeline-stages.ts","../src/core/cross-customer.ts","../src/mcp/tools/get-market-intelligence.ts","../src/mcp/tools/get-relationship-graph.ts","../src/mcp/tools/get-relationship-health.ts","../src/core/playbooks.ts","../src/agents/deal-agent.ts","../src/mcp/tools/run-deal-agent.ts","../src/mcp/tools/approve-agent-action.ts","../src/mcp/tools/simulate-revenue.ts","../src/mcp/tools/get-playbook.ts","../src/mcp/tools/create-playbook.ts","../src/mcp/tools/list-playbooks.ts","../src/mcp/tools/distill-playbook.ts","../src/mcp/tools/pursue-goal.ts","../src/mcp/tools/get-goal-status.ts","../src/mcp/tools/register-push-subscription.ts","../src/mcp/tools/get-push-status.ts","../src/core/org-intelligence.ts","../src/mcp/tools/get-org-intelligence.ts","../src/agents/deal-room.ts","../src/mcp/tools/open-deal-room.ts","../src/mcp/tools/get-proactive-briefing.ts","../src/mcp/tools/list-email-templates.ts","../src/mcp/tools/get-email-template.ts","../src/mcp/tools/draft-email.ts","../src/mcp/tools/enroll-in-sequence.ts","../src/mcp/tools/list-sequence-enrollments.ts","../src/mcp/tools/unenroll-from-sequence.ts","../src/mcp/tools/list-sequences.ts","../src/mcp/tools/generate-quote.ts","../src/mcp/tools/get-quote-status.ts","../src/mcp/tools/get-booking-link.ts","../src/mcp/tools/create-ticket.ts","../src/mcp/tools/update-ticket.ts","../src/mcp/tools/list-tickets.ts","../src/mcp/tools/close-ticket.ts","../src/mcp/tools/send-nps-survey.ts","../src/mcp/tools/get-survey-results.ts","../src/mcp/tools/search-knowledge-base.ts","../src/mcp/tools/create-kb-article.ts","../src/mcp/tools/backup-now.ts","../src/mcp/tools/list-backups.ts","../src/mcp/tools/trigger-sync.ts","../src/mcp/tools/get-audit-log.ts","../src/mcp/tools/get-logs.ts","../src/mcp/tools/get-diagnostics.ts","../src/mcp/tools/get-pipeline-changes.ts","../src/mcp/prompts.ts","../src/mcp/resources.ts","../src/mcp/tools/custom-objects.ts","../src/mcp/server.ts"],"sourcesContent":["import fs from \"fs\";\nimport path from \"path\";\nimport type { OAuth2Client } from \"google-auth-library\";\n\nlet _auth: OAuth2Client | null = null;\n\nexport async function initOAuthFromDisk(dataDir: string): Promise<boolean> {\n const credPath = path.join(dataDir, \".agentic\", \"gmail-credentials.json\");\n const tokenPath = path.join(dataDir, \".agentic\", \"gmail-token.json\");\n\n if (!fs.existsSync(credPath) || !fs.existsSync(tokenPath)) {\n return false;\n }\n\n try {\n const { getGmailAuth: loadAuth } = await import(\"../sync/gmail-auth.js\");\n _auth = await loadAuth(credPath, tokenPath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function getGmailAuth(): OAuth2Client | null {\n return _auth;\n}\n\nexport function resetOAuthStore(): void {\n _auth = null;\n}\n","import { readSubscriptions, writeSubscriptions, type PushSubscription } from \"./push-manager.js\";\nimport { appendInteraction } from \"../fs/interactions-writer.js\";\n\nexport interface MicrosoftGraphNotification {\n subscriptionId: string;\n clientState?: string;\n resource: string;\n resourceData?: { id: string; \"@odata.type\": string };\n}\n\nexport function verifyMicrosoftGraphSignature(\n body: { value?: Array<Partial<MicrosoftGraphNotification>> },\n expectedClientState: string\n): boolean {\n const notifications = body.value ?? [];\n if (notifications.length === 0) return expectedClientState === \"\";\n return notifications.every((n) => n.clientState === expectedClientState);\n}\n\nexport interface ValidationResult {\n isValidation: boolean;\n token?: string;\n}\n\nexport function handleMicrosoftValidationRequest(\n queryParams: Record<string, string | undefined>\n): ValidationResult {\n const token = queryParams[\"validationToken\"];\n if (token) return { isValidation: true, token };\n return { isValidation: false };\n}\n\nexport interface GraphMessage {\n id: string;\n subject?: string;\n from?: { emailAddress?: { address?: string; name?: string } };\n receivedDateTime?: string;\n bodyPreview?: string;\n}\n\nexport type FetchGraphMessageFn = (\n accessToken: string,\n messageId: string\n) => Promise<GraphMessage | null>;\nexport type AppendInteractionFn = typeof appendInteraction;\n\nexport interface HandleMicrosoftPushOptions {\n fetchMessageFn?: FetchGraphMessageFn;\n appendInteractionFn?: AppendInteractionFn;\n}\n\nexport { readSubscriptions };\n\nfunction findSubscriptionByMsId(\n subs: PushSubscription[],\n subscriptionId: string\n): PushSubscription | null {\n return (\n subs.find(\n (s) =>\n s.provider === \"microsoft-graph\" &&\n s.status === \"active\" &&\n s.providerData.microsoftSubscriptionId === subscriptionId\n ) ?? null\n );\n}\n\nexport async function handleMicrosoftPushEvent(\n dataDir: string,\n notifications: MicrosoftGraphNotification[],\n accessToken: string,\n options: HandleMicrosoftPushOptions = {}\n): Promise<{ processed: number; skipped: number }> {\n const subs = await readSubscriptions(dataDir);\n const { fetchMessageFn, appendInteractionFn = appendInteraction } = options;\n\n let processed = 0;\n let skipped = 0;\n let anyProcessed = false;\n\n for (const notification of notifications) {\n const sub = findSubscriptionByMsId(subs, notification.subscriptionId);\n if (!sub) {\n skipped++;\n continue;\n }\n\n const messageId = notification.resourceData?.id;\n if (!messageId || !fetchMessageFn) {\n skipped++;\n continue;\n }\n\n try {\n const message = await fetchMessageFn(accessToken, messageId);\n if (!message) {\n skipped++;\n continue;\n }\n\n const from = message.from?.emailAddress?.address ?? \"unknown\";\n const sourceRef = `msgraph://message/${message.id}`;\n\n await appendInteractionFn(dataDir, sub.slug, {\n date: message.receivedDateTime\n ? new Date(message.receivedDateTime).toISOString().slice(0, 10)\n : new Date().toISOString().slice(0, 10),\n type: \"Email\",\n direction: \"inbound\",\n with: from,\n subject: message.subject ?? \"(no subject)\",\n summary: message.bodyPreview ?? \"(no preview)\",\n nextSteps: [],\n sourceRef,\n synced: new Date().toISOString(),\n });\n\n processed++;\n anyProcessed = true;\n\n // Update sub counters\n const idx = subs.findIndex((s) => s.id === sub.id);\n if (idx !== -1) {\n subs[idx] = {\n ...subs[idx]!,\n eventsProcessed: subs[idx]!.eventsProcessed + 1,\n lastEventAt: new Date().toISOString(),\n };\n }\n } catch {\n skipped++;\n }\n }\n\n if (anyProcessed) {\n await writeSubscriptions(dataDir, subs);\n }\n\n return { processed, skipped };\n}\n","import crypto from \"crypto\";\nimport { readSubscriptions, writeSubscriptions, type PushSubscription } from \"./push-manager.js\";\nimport { appendInteraction } from \"../fs/interactions-writer.js\";\n\nexport interface SlackEvent {\n type: string;\n user?: string;\n text?: string;\n channel?: string;\n ts?: string;\n bot_id?: string;\n}\n\nexport function verifySlackSignature(\n body: string,\n headers: { \"x-slack-signature\"?: string; \"x-slack-request-timestamp\"?: string },\n signingSecret: string\n): boolean {\n const sig = headers[\"x-slack-signature\"];\n const ts = headers[\"x-slack-request-timestamp\"];\n if (!sig || !ts) return false;\n\n // Replay protection: reject requests older than 5 minutes\n const tsNum = Number(ts);\n if (Math.abs(Date.now() / 1000 - tsNum) > 5 * 60) return false;\n\n const sigBase = `v0:${ts}:${body}`;\n const expected = \"v0=\" + crypto.createHmac(\"sha256\", signingSecret).update(sigBase).digest(\"hex\");\n\n try {\n const sigBuf = Buffer.from(sig);\n const expBuf = Buffer.from(expected);\n if (sigBuf.length !== expBuf.length) return false;\n return crypto.timingSafeEqual(sigBuf, expBuf);\n } catch {\n return false;\n }\n}\n\nexport type SlackUrlVerificationResult =\n | { isVerification: true; challenge: string }\n | { isVerification: false; challenge?: never };\n\nexport function handleSlackUrlVerification(body: {\n type?: string;\n challenge?: string;\n}): SlackUrlVerificationResult {\n if (body.type === \"url_verification\") {\n return { isVerification: true, challenge: body.challenge ?? \"\" };\n }\n return { isVerification: false };\n}\n\nexport type AppendInteractionFn = typeof appendInteraction;\nexport type FetchUserInfoFn = (\n botToken: string,\n userId: string\n) => Promise<{ email?: string; name?: string }>;\n\nexport interface HandleSlackPushOptions {\n appendInteractionFn?: AppendInteractionFn;\n fetchUserInfoFn?: FetchUserInfoFn;\n teamId?: string;\n}\n\nfunction findSubscriptionByTeam(\n subs: PushSubscription[],\n teamId: string | undefined\n): PushSubscription | null {\n return (\n subs.find(\n (s) =>\n s.provider === \"slack\" &&\n s.status === \"active\" &&\n (!teamId || s.providerData.slackTeamId === teamId)\n ) ?? null\n );\n}\n\nexport async function handleSlackPushEvent(\n dataDir: string,\n event: SlackEvent,\n botToken: string,\n options: HandleSlackPushOptions = {}\n): Promise<{ processed: number; skipped: number }> {\n // Only process message events\n if (event.type !== \"message\") return { processed: 0, skipped: 1 };\n\n // Skip bot messages\n if (event.bot_id) return { processed: 0, skipped: 1 };\n\n // Skip empty text\n if (!event.text?.trim()) return { processed: 0, skipped: 1 };\n\n const subs = await readSubscriptions(dataDir);\n const sub = findSubscriptionByTeam(subs, options.teamId);\n if (!sub) return { processed: 0, skipped: 1 };\n\n const { appendInteractionFn = appendInteraction, fetchUserInfoFn } = options;\n\n let senderName = event.user ?? \"unknown\";\n if (fetchUserInfoFn && event.user) {\n try {\n const info = await fetchUserInfoFn(botToken, event.user);\n senderName = info.name ?? info.email ?? event.user;\n } catch {\n // keep default\n }\n }\n\n const ts = event.ts\n ? new Date(Number(event.ts) * 1000).toISOString().slice(0, 10)\n : new Date().toISOString().slice(0, 10);\n const sourceRef = `slack://channel/${event.channel ?? \"dm\"}/ts/${event.ts ?? Date.now()}`;\n\n try {\n await appendInteractionFn(dataDir, sub.slug, {\n date: ts,\n type: \"Meeting\",\n direction: \"inbound\",\n with: senderName,\n subject: `Slack message in ${event.channel ?? \"DM\"}`,\n summary: event.text.slice(0, 300),\n nextSteps: [],\n sourceRef,\n synced: new Date().toISOString(),\n });\n\n // Update sub counters\n const idx = subs.findIndex((s) => s.id === sub.id);\n if (idx !== -1) {\n subs[idx] = {\n ...subs[idx]!,\n eventsProcessed: subs[idx]!.eventsProcessed + 1,\n lastEventAt: new Date().toISOString(),\n };\n await writeSubscriptions(dataDir, subs);\n }\n\n return { processed: 1, skipped: 0 };\n } catch {\n return { processed: 0, skipped: 1 };\n }\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { CAPABILITIES_TEXT } from \"../capabilities.js\";\n\nexport async function handleGetCapabilities(): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n}> {\n return {\n content: [{ type: \"text\", text: CAPABILITIES_TEXT }],\n };\n}\n\nexport function registerGetCapabilities(server: McpServer): void {\n server.registerTool(\n \"get_capabilities\",\n {\n title: \"Get Capabilities\",\n description:\n \"Returns all available MCP tools, their inputs, and the CRM workflow guide. \" +\n \"Call this first to understand what DatasynxOpenCRM can do.\",\n inputSchema: z.object({}),\n },\n async () => handleGetCapabilities()\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { getSession } from \"../../core/session-store.js\";\n\nexport interface ActiveSessionResult {\n hasSession: boolean;\n customerSlug?: string;\n customerName?: string;\n startedAt?: string;\n owner?: string;\n}\n\nexport async function handleGetActiveSession(): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n}> {\n const session = getSession();\n\n const result: ActiveSessionResult = session\n ? {\n hasSession: true,\n customerSlug: session.customerSlug,\n customerName: session.customerName,\n startedAt: session.startedAt,\n ...(session.owner !== undefined ? { owner: session.owner } : {}),\n }\n : { hasSession: false };\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n}\n\nexport function registerGetActiveSession(server: McpServer): void {\n server.registerTool(\n \"get_active_session\",\n {\n title: \"Get Active Session\",\n description:\n \"Check which customer is currently active in the session store. \" +\n \"Returns session info if a customer session is open, otherwise returns hasSession: false.\",\n inputSchema: z.object({}),\n },\n async () => handleGetActiveSession()\n );\n}\n","import path from \"path\";\nimport fs from \"fs\";\nimport { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { buildContext } from \"../../core/context-builder.js\";\nimport { getSession } from \"../../core/session-store.js\";\nimport { getLastGmailSync, updateSlugSyncState } from \"../../fs/sync-state.js\";\nimport { getGmailAuth } from \"../../core/oauth-store.js\";\nimport { canSeeCustomer } from \"../../core/rbac.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nfunction triggerOnQuerySync(dataDir: string, slug: string): void {\n const auth = getGmailAuth();\n if (!auth) return;\n\n const lastSync = getLastGmailSync(dataDir, slug);\n const thirtyMinAgo = new Date(Date.now() - 30 * 60 * 1000);\n if (lastSync && lastSync >= thirtyMinAgo) return;\n\n const sourcesPath = path.join(dataDir, \"customers\", slug, \"sources.json\");\n if (!fs.existsSync(sourcesPath)) return;\n\n try {\n const sources = JSON.parse(fs.readFileSync(sourcesPath, \"utf-8\") as string) as {\n gmail?: { query?: string; enabled?: boolean };\n };\n if (!sources.gmail?.enabled || !sources.gmail.query) return;\n\n const query = sources.gmail.query;\n void import(\"../../sync/gmail-sync.js\")\n .then(({ syncGmail }) =>\n syncGmail({ slug, dataDir, auth, query })\n .then(() =>\n updateSlugSyncState(dataDir, slug, { lastGmailSync: new Date().toISOString() })\n )\n .catch(() => {})\n )\n .catch(() => {});\n } catch {\n // non-critical\n }\n}\n\nexport async function handleGetCustomerContext(\n input: { slug?: string },\n dataDir: string = DATA_DIR\n): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}> {\n const targetSlug = input.slug ?? getSession()?.customerSlug;\n\n if (!targetSlug) {\n return {\n content: [\n {\n type: \"text\",\n text: \"No customer specified and no active session. Use: get_customer_context({ slug: 'acme-corp' })\",\n },\n ],\n isError: true,\n };\n }\n\n // RBAC data-visibility: rep role only sees owned customers\n const actor = process.env[\"DXCRM_ACTOR\"] ?? \"system\";\n if (!canSeeCustomer(dataDir, actor, targetSlug)) {\n return {\n content: [\n { type: \"text\", text: `Access denied: '${actor}' cannot view customer '${targetSlug}'.` },\n ],\n isError: true,\n };\n }\n\n // Fire-and-forget on-query sync — does not block context return\n triggerOnQuerySync(dataDir, targetSlug);\n\n try {\n const context = await buildContext(dataDir, targetSlug);\n return {\n content: [{ type: \"text\", text: context }],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: ${(err as Error).message}`,\n },\n ],\n isError: true,\n };\n }\n}\n\nexport function registerGetCustomerContext(server: McpServer): void {\n server.registerTool(\n \"get_customer_context\",\n {\n title: \"Get Customer Context\",\n description: `Returns a complete, LLM-ready context block for a customer.\nUse this before any customer-related conversation or action.\nAutomatically triggers a background Gmail sync if last sync was >30 minutes ago.\n\nArgs:\n slug: Customer ID (e.g. \"acme-corp\"). Leave empty to use active session customer.\n\nReturns: Structured markdown with Quick Reference, Contacts, Critical Context,\nRecent Activity (last 10 interactions), Pipeline, and Open Questions.\n\nPerformance: <3 seconds. Token budget: <3000.`,\n inputSchema: z.object({\n slug: z\n .string()\n .optional()\n .describe(\"Customer slug (e.g. 'acme-corp'). Leave empty for active session customer.\"),\n }),\n },\n async ({ slug }) => handleGetCustomerContext({ ...(slug !== undefined ? { slug } : {}) })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { searchKnowledge } from \"../../core/lancedb.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleSearchCustomerKnowledge(\n input: { slug: string; query: string; limit?: number },\n dataDir: string = DATA_DIR\n): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n}> {\n const limit = input.limit ?? 5;\n\n try {\n const results = await searchKnowledge(dataDir, input.slug, input.query, limit);\n\n const response =\n results.length === 0\n ? {\n results: [],\n message:\n `No results found for \"${input.query}\" in customer \"${input.slug}\". ` +\n \"The customer may not have been synced yet. Run dxcrm sync to index emails and transcripts.\",\n }\n : { results };\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(response, null, 2) }],\n };\n } catch {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n results: [],\n message: `Search unavailable for customer \"${input.slug}\". LanceDB may not be initialized.`,\n }),\n },\n ],\n };\n }\n}\n\nexport function registerSearchCustomerKnowledge(server: McpServer): void {\n server.registerTool(\n \"search_customer_knowledge\",\n {\n title: \"Search Customer Knowledge\",\n description: `Hybrid vector + full-text search across all emails and transcripts for a customer.\nUse when you need to find specific information from past communications.\n\nArgs:\n slug: Customer ID (e.g. \"acme-corp\")\n query: Natural language search query (e.g. \"pricing discussion\", \"GDPR concerns\")\n limit: Max results to return (default 5)\n\nReturns: { results: Array<{ content, score, source }> }\nIf no results: returns empty array with a helpful sync suggestion.`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n query: z.string().describe(\"Search query (natural language or keywords)\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .optional()\n .describe(\"Max results to return (default 5)\"),\n }),\n },\n async ({ slug, query, limit }) =>\n handleSearchCustomerKnowledge({\n slug,\n query,\n ...(limit !== undefined ? { limit } : {}),\n })\n );\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport matter from \"gray-matter\";\nimport { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { customerVisibility } from \"../../core/rbac.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport interface CustomerSummary {\n slug: string;\n name: string;\n stage: string;\n lastInteraction?: string | undefined;\n dealValue?: number | undefined;\n}\n\nfunction extractLastInteractionDate(interactionsPath: string): string | undefined {\n if (!fs.existsSync(interactionsPath)) return undefined;\n\n const content = fs.readFileSync(interactionsPath, \"utf-8\") as string;\n // Match first ## YYYY-MM-DD heading\n const match = /^## (\\d{4}-\\d{2}-\\d{2})/m.exec(content);\n return match ? match[1] : undefined;\n}\n\nexport async function handleListCustomers(\n input: { filter?: string },\n dataDir: string = DATA_DIR\n): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n}> {\n const customersDir = path.join(dataDir, \"customers\");\n const customers: CustomerSummary[] = [];\n\n if (!fs.existsSync(customersDir)) {\n return {\n content: [{ type: \"text\", text: JSON.stringify([], null, 2) }],\n };\n }\n\n const entries = fs.readdirSync(customersDir) as string[];\n\n // Resolve RBAC visibility once (reads rbac.json a single time, not per customer).\n const actor = process.env[\"DXCRM_ACTOR\"] ?? \"system\";\n const canSee = customerVisibility(dataDir, actor);\n\n for (const entry of entries) {\n const customerDir = path.join(customersDir, entry);\n\n // Skip if not a directory\n try {\n const stat = fs.statSync(customerDir);\n if (!stat.isDirectory()) continue;\n } catch {\n continue;\n }\n\n const mainFactsPath = path.join(customerDir, \"main_facts.md\");\n if (!fs.existsSync(mainFactsPath)) continue;\n\n try {\n const raw = matter(fs.readFileSync(mainFactsPath, \"utf-8\") as string);\n const data = raw.data as Record<string, unknown>;\n\n const name = typeof data[\"name\"] === \"string\" ? data[\"name\"] : entry;\n const stage =\n typeof data[\"relationship_stage\"] === \"string\" ? data[\"relationship_stage\"] : \"unknown\";\n const dealValue = typeof data[\"deal_value\"] === \"number\" ? data[\"deal_value\"] : undefined;\n\n const lastInteraction = extractLastInteractionDate(path.join(customerDir, \"interactions.md\"));\n\n const summary: CustomerSummary = {\n slug: entry,\n name,\n stage,\n ...(lastInteraction !== undefined ? { lastInteraction } : {}),\n ...(dealValue !== undefined ? { dealValue } : {}),\n };\n\n // Apply filter if provided (name, slug, or stage)\n if (input.filter) {\n const filterLower = input.filter.toLowerCase();\n const matches =\n name.toLowerCase().includes(filterLower) ||\n entry.toLowerCase().includes(filterLower) ||\n stage.toLowerCase().includes(filterLower);\n if (!matches) continue;\n }\n\n // RBAC data-visibility: rep role only sees owned customers\n if (!canSee(entry)) continue;\n\n customers.push(summary);\n } catch {\n // Skip customers with malformed data\n continue;\n }\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(customers, null, 2) }],\n };\n}\n\nexport function registerListCustomers(server: McpServer): void {\n server.registerTool(\n \"list_customers\",\n {\n title: \"List Customers\",\n description: `List all customers with their pipeline stage, last interaction date, and deal value.\nUseful for morning briefings and pipeline overviews.\n\nArgs:\n filter: Optional substring to filter by name or slug (case-insensitive)\n\nReturns: Array of { slug, name, stage, lastInteraction?, dealValue? }`,\n inputSchema: z.object({\n filter: z\n .string()\n .optional()\n .describe(\"Substring filter on customer name or slug (case-insensitive)\"),\n }),\n },\n async ({ filter }) => handleListCustomers({ ...(filter !== undefined ? { filter } : {}) })\n );\n}\n","import path from \"path\";\nimport fs from \"fs\";\nimport matter from \"gray-matter\";\nimport { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { appendInteraction, formatInteractionEntry } from \"../../fs/interactions-writer.js\";\nimport { writeFileAtomic } from \"../../fs/atomic-write.js\";\nimport type { InteractionEntry } from \"../../schemas/interaction.js\";\nimport { writeAuditEntry, getActor } from \"../../fs/audit-log.js\";\nimport { enforceRbac } from \"../../core/rbac.js\";\nimport { updateGraphFromInteraction } from \"../../core/graph-extractor.js\";\nimport { updateHealthFromInteraction } from \"../../core/relationship-health.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleLogInteraction(\n input: {\n slug: string;\n type: InteractionEntry[\"type\"];\n summary: string;\n with: string;\n nextSteps?: string[];\n direction?: \"inbound\" | \"outbound\";\n source?: string;\n date?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n}> {\n const today = new Date().toISOString().split(\"T\")[0] as string;\n const interactionDate = input.date ?? today;\n const sourceRef = input.source ?? `agent://log/${Date.now()}`;\n\n const entry: InteractionEntry = {\n date: interactionDate,\n type: input.type,\n with: input.with,\n summary: input.summary,\n nextSteps: input.nextSteps ?? [],\n sourceRef,\n synced: new Date().toISOString(),\n ...(input.direction !== undefined ? { direction: input.direction } : {}),\n };\n\n const interactionsPath = path.join(dataDir, \"customers\", input.slug, \"interactions.md\");\n const entryText = formatInteractionEntry(entry);\n\n try {\n enforceRbac(dataDir, \"log_interaction\");\n\n await appendInteraction(dataDir, input.slug, entry);\n\n // Graph auto-update: fire-and-forget\n updateGraphFromInteraction(dataDir, input.slug, {\n withStr: input.with,\n interactionDate: interactionDate,\n }).catch(() => {\n // non-critical — interaction already written\n });\n\n // Health auto-update: fire-and-forget (runs after graph update)\n updateHealthFromInteraction(dataDir, input.slug).catch(() => {\n // non-critical — interaction already written\n });\n\n // Update last_touchpoint in main_facts.md\n const mainFactsPath = path.join(dataDir, \"customers\", input.slug, \"main_facts.md\");\n if (fs.existsSync(mainFactsPath)) {\n try {\n const raw = matter(fs.readFileSync(mainFactsPath, \"utf-8\"));\n raw.data.last_touchpoint = interactionDate;\n // js-yaml quotes YYYY-MM-DD strings; strip quotes to keep plain date format\n let serialized = matter.stringify(raw.content, raw.data);\n serialized = serialized.replace(\n /^(last_touchpoint:\\s*)['\"](\\d{4}-\\d{2}-\\d{2})['\"]/m,\n \"$1$2\"\n );\n writeFileAtomic(mainFactsPath, serialized);\n } catch {\n // non-critical — interaction is already written\n }\n }\n\n writeAuditEntry(dataDir, {\n timestamp: new Date().toISOString(),\n actor: getActor(),\n tool: \"log_interaction\",\n slug: input.slug,\n summary: input.summary,\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n path: interactionsPath,\n entry: entryText,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: false,\n error: (err as Error).message,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n}\n\nexport function registerLogInteraction(server: McpServer): void {\n server.registerTool(\n \"log_interaction\",\n {\n title: \"Log Interaction\",\n description: `Write a new interaction entry to the CRM. Use after every call, meeting, or email.\nFormat matches auto-synced entries exactly — immediately searchable.\n\nArgs:\n slug: Customer ID\n type: Interaction type (\"Email\" | \"Call\" | \"Meeting\" | \"Note\" | \"Demo\" | \"Proposal\" | \"Contract\" | \"Other\")\n summary: 2-5 sentences describing what happened (min 1 char)\n with: Who was involved (name or email address)\n nextSteps: Array of action items (optional)\n direction: \"inbound\" or \"outbound\" (optional)\n source: Source reference string (optional, auto-generated if omitted)\n\nReturns: { success: boolean, path: string, entry: string }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n type: z\n .enum([\"Email\", \"Call\", \"Meeting\", \"Note\", \"Demo\", \"Proposal\", \"Contract\", \"Other\"])\n .describe(\"Type of interaction\"),\n summary: z.string().min(1).describe(\"2-5 sentence summary of what happened\"),\n with: z.string().describe(\"Who was involved (name or email)\"),\n nextSteps: z.array(z.string()).optional().describe(\"Action items for follow-up\"),\n direction: z\n .enum([\"inbound\", \"outbound\"])\n .optional()\n .describe(\"Direction of communication\"),\n source: z\n .string()\n .optional()\n .describe(\"Source reference (e.g. gmail://thread/123). Auto-generated if omitted.\"),\n date: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/)\n .optional()\n .describe(\"Date of interaction (YYYY-MM-DD). Defaults to today.\"),\n }),\n },\n async ({ slug, type, summary, with: withStr, nextSteps, direction, source, date }) =>\n handleLogInteraction({\n slug,\n type,\n summary,\n with: withStr,\n ...(nextSteps !== undefined ? { nextSteps } : {}),\n ...(direction !== undefined ? { direction } : {}),\n ...(source !== undefined ? { source } : {}),\n ...(date !== undefined ? { date } : {}),\n })\n );\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport matter from \"gray-matter\";\nimport { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readPipeline } from \"../../fs/pipeline-writer.js\";\nimport { enforceRbac } from \"../../core/rbac.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nfunction countInteractions(content: string): number {\n // Count ## YYYY-MM-DD headings\n const matches = content.match(/^## \\d{4}-\\d{2}-\\d{2}/gm);\n return matches ? matches.length : 0;\n}\n\nexport async function handleExportCustomer(\n input: { slug: string; format?: \"json\" | \"markdown\"; includeAttachmentContent?: boolean },\n dataDir: string = DATA_DIR\n): Promise<{\n content: Array<{ type: \"text\"; text: string }>;\n isError?: boolean;\n}> {\n enforceRbac(dataDir, \"export_customer\");\n\n const customerDir = path.join(dataDir, \"customers\", input.slug);\n\n if (!fs.existsSync(customerDir)) {\n return {\n content: [\n {\n type: \"text\",\n text: `Error: Customer '${input.slug}' not found. Check 'list_customers()' for available customers.`,\n },\n ],\n isError: true,\n };\n }\n\n const format = input.format ?? \"json\";\n\n // Read main_facts.md\n const mainFactsPath = path.join(customerDir, \"main_facts.md\");\n let mainFacts: Record<string, unknown> = {};\n let mainFactsContent = \"\";\n if (fs.existsSync(mainFactsPath)) {\n const raw = matter(fs.readFileSync(mainFactsPath, \"utf-8\") as string);\n mainFacts = raw.data as Record<string, unknown>;\n mainFactsContent = raw.content ?? \"\";\n }\n\n // Read interactions\n const interactionsPath = path.join(customerDir, \"interactions.md\");\n let interactionsContent = \"\";\n let interactionsCount = 0;\n if (fs.existsSync(interactionsPath)) {\n interactionsContent = fs.readFileSync(interactionsPath, \"utf-8\") as string;\n interactionsCount = countInteractions(interactionsContent);\n }\n\n // Read pipeline\n const pipeline = await readPipeline(dataDir, input.slug);\n\n // Read attachments list, separating converted Markdown from raw files.\n const includeAttachmentContent = input.includeAttachmentContent ?? false;\n const attachmentsDir = path.join(customerDir, \"attachments\");\n const attachments: string[] = [];\n const attachmentContents: Record<string, string> = {};\n if (fs.existsSync(attachmentsDir)) {\n try {\n const files = fs.readdirSync(attachmentsDir) as string[];\n for (const f of files) {\n try {\n if (!fs.statSync(path.join(attachmentsDir, f)).isFile()) continue;\n attachments.push(f);\n if (includeAttachmentContent && f.endsWith(\".md\")) {\n attachmentContents[f] = fs.readFileSync(path.join(attachmentsDir, f), \"utf-8\") as string;\n }\n } catch {\n /* skip */\n }\n }\n } catch {\n /* skip */\n }\n }\n const attachmentContentSection = (): string[] => {\n const entries = Object.entries(attachmentContents);\n if (!includeAttachmentContent || entries.length === 0) return [];\n return [\n \"\",\n `## Attachment Contents (${entries.length})`,\n ...entries.map(([name, content]) => `\\n### ${name}\\n\\n${content.trim()}`),\n ];\n };\n\n if (format === \"markdown\") {\n const markdown = [\n `# Export: ${input.slug}`,\n \"\",\n \"## Main Facts\",\n mainFactsContent.trim() || \"(no content)\",\n \"\",\n \"## Metadata\",\n Object.entries(mainFacts)\n .map(([k, v]) => `- **${k}**: ${JSON.stringify(v)}`)\n .join(\"\\n\") || \"(no metadata)\",\n \"\",\n `## Interactions (${interactionsCount} total)`,\n interactionsContent.trim() || \"(no interactions)\",\n \"\",\n \"## Pipeline\",\n pipeline.length > 0\n ? pipeline\n .map(\n (d) =>\n `- **${d.name}** · ${d.stage}${d.value !== undefined ? ` · €${d.value}` : \"\"}${d.close_date ? ` · close: ${d.close_date}` : \"\"}`\n )\n .join(\"\\n\")\n : \"(no deals)\",\n \"\",\n `## Attachments (${attachments.length})`,\n attachments.length > 0 ? attachments.map((f) => `- ${f}`).join(\"\\n\") : \"(none)\",\n ...attachmentContentSection(),\n ].join(\"\\n\");\n\n return {\n content: [{ type: \"text\", text: markdown }],\n };\n }\n\n // Default: JSON\n const exported = {\n slug: input.slug,\n exportedAt: new Date().toISOString(),\n mainFacts,\n interactionsCount,\n pipeline,\n attachments,\n ...(includeAttachmentContent ? { attachmentContents } : {}),\n };\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(exported, null, 2) }],\n };\n}\n\nexport function registerExportCustomer(server: McpServer): void {\n server.registerTool(\n \"export_customer\",\n {\n title: \"Export Customer\",\n description: `Export all customer data (main_facts + interactions + pipeline deals + attachments).\nUseful for reporting, audits, handoffs, or creating a complete sendable bundle\nof every conversation and document for a customer.\n\nArgs:\n slug: Customer ID (e.g. \"acme-corp\")\n format: Output format — \"json\" (default) or \"markdown\"\n includeAttachmentContent: Inline the converted Markdown of every attachment\n (default false). Use this to produce a single self-contained bundle.\n\nReturns:\n JSON: { slug, exportedAt, mainFacts, interactionsCount, pipeline, attachments[, attachmentContents] }\n Markdown: Formatted document with all sections (and attachment contents when requested)`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n format: z\n .enum([\"json\", \"markdown\"])\n .optional()\n .describe(\"Output format: 'json' (default) or 'markdown'\"),\n includeAttachmentContent: z\n .boolean()\n .optional()\n .describe(\"Inline converted attachment Markdown into the export (default false)\"),\n }),\n },\n async ({ slug, format, includeAttachmentContent }) =>\n handleExportCustomer({\n slug,\n ...(format !== undefined ? { format } : {}),\n ...(includeAttachmentContent !== undefined ? { includeAttachmentContent } : {}),\n })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport {\n readMainFacts,\n writeMainFacts,\n ensureCustomerDir,\n customerExists,\n} from \"../../fs/customer-dir.js\";\nimport { writeAuditEntry, getActor } from \"../../fs/audit-log.js\";\nimport { enforceRbac } from \"../../core/rbac.js\";\nimport type { MainFacts } from \"../../schemas/main-facts.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleUpdateCustomerFacts(\n input: {\n slug: string;\n name?: string | undefined;\n domain?: string | undefined;\n email?: string | undefined;\n phone?: string | undefined;\n industry?: string | undefined;\n relationshipStage?: \"prospect\" | \"active\" | \"churned\" | \"paused\" | undefined;\n dealValue?: number | undefined;\n primaryContact?: string | undefined;\n timezone?: string | undefined;\n tags?: string[] | undefined;\n notes?: string | undefined;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const today = new Date().toISOString().slice(0, 10);\n\n try {\n enforceRbac(dataDir, \"update_customer_facts\");\n\n let existing: MainFacts;\n let created = false;\n if (!customerExists(dataDir, input.slug)) {\n await ensureCustomerDir(dataDir, input.slug);\n existing = {\n name: input.name ?? input.slug,\n relationship_stage: \"prospect\",\n currency: \"EUR\",\n tags: [],\n created: today,\n updated: today,\n };\n created = true;\n } else {\n existing = await readMainFacts(dataDir, input.slug);\n }\n\n const updated = {\n ...existing,\n ...(input.name !== undefined ? { name: input.name } : {}),\n ...(input.domain !== undefined ? { domain: input.domain } : {}),\n ...(input.email !== undefined ? { email: input.email } : {}),\n ...(input.phone !== undefined ? { phone: input.phone } : {}),\n ...(input.industry !== undefined ? { industry: input.industry } : {}),\n ...(input.relationshipStage !== undefined\n ? { relationship_stage: input.relationshipStage }\n : {}),\n ...(input.dealValue !== undefined ? { deal_value: input.dealValue } : {}),\n ...(input.primaryContact !== undefined ? { primary_contact: input.primaryContact } : {}),\n ...(input.timezone !== undefined ? { timezone: input.timezone } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n updated: today,\n };\n\n await writeMainFacts(dataDir, input.slug, updated);\n\n writeAuditEntry(dataDir, {\n timestamp: new Date().toISOString(),\n actor: getActor(),\n tool: \"update_customer_facts\",\n slug: input.slug,\n summary: Object.keys(input)\n .filter((k) => k !== \"slug\")\n .join(\", \"),\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: true, created, facts: updated }, null, 2),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerUpdateCustomerFacts(server: McpServer): void {\n server.registerTool(\n \"update_customer_facts\",\n {\n title: \"Update Customer Facts\",\n description: `Create or update a customer's main_facts.md profile.\nIf the customer slug does not exist yet, creates the customer directory and initial profile.\nIf it exists, merges the provided fields into existing data.\n\nUse to add a new customer (\"create acme-corp\") or update existing info.\n\nArgs:\n slug: Customer ID / slug — e.g. \"acme-corp\" (kebab-case, no spaces)\n name: Company name (used as display name)\n domain: Primary domain (e.g. \"acme.com\")\n email: Primary contact email\n phone: Phone number\n industry: Industry vertical\n relationshipStage: \"prospect\" | \"active\" | \"churned\" | \"paused\"\n dealValue: Expected deal value in EUR\n primaryContact: Primary contact person name\n timezone: Timezone (e.g. \"Europe/Berlin\")\n tags: Array of tags (replaces existing tags)\n\nReturns: { success: boolean, created: boolean, facts: object }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n name: z.string().optional().describe(\"Company name\"),\n domain: z.string().optional().describe(\"Primary domain\"),\n email: z.string().optional().describe(\"Primary contact email\"),\n phone: z.string().optional().describe(\"Phone number\"),\n industry: z.string().optional().describe(\"Industry vertical\"),\n relationshipStage: z\n .enum([\"prospect\", \"active\", \"churned\", \"paused\"])\n .optional()\n .describe(\"Relationship stage\"),\n dealValue: z.number().optional().describe(\"Expected deal value in EUR\"),\n primaryContact: z.string().optional().describe(\"Primary contact person name\"),\n timezone: z.string().optional().describe(\"Timezone (e.g. Europe/Berlin)\"),\n tags: z.array(z.string()).optional().describe(\"Tags (replaces existing)\"),\n }),\n },\n async (input) => handleUpdateCustomerFacts(input)\n );\n}\n","import type { PipelineDeal } from \"../schemas/pipeline.js\";\n\nexport interface DealHealthSignals {\n daysSinceLastActivity: number;\n daysInCurrentStage: number;\n daysToClose?: number | undefined;\n probability?: number | undefined;\n}\n\nexport interface DealHealthScore {\n score: number; // 0–100\n grade: \"A\" | \"B\" | \"C\" | \"D\" | \"F\";\n signals: DealHealthSignals;\n warnings: string[];\n}\n\nfunction grade(score: number): \"A\" | \"B\" | \"C\" | \"D\" | \"F\" {\n if (score >= 80) return \"A\";\n if (score >= 65) return \"B\";\n if (score >= 50) return \"C\";\n if (score >= 35) return \"D\";\n return \"F\";\n}\n\nexport function scoreDeal(deal: PipelineDeal, signals: DealHealthSignals): DealHealthScore {\n let score = 100;\n const warnings: string[] = [];\n\n // Activity recency (max penalty -40)\n if (signals.daysSinceLastActivity > 60) {\n score -= 40;\n warnings.push(`No activity in ${signals.daysSinceLastActivity} days`);\n } else if (signals.daysSinceLastActivity > 30) {\n score -= 25;\n warnings.push(`Low activity — last touch ${signals.daysSinceLastActivity} days ago`);\n } else if (signals.daysSinceLastActivity > 14) {\n score -= 10;\n }\n\n // Stage stagnation (max penalty -25)\n if (signals.daysInCurrentStage > 90) {\n score -= 25;\n warnings.push(`Stuck in \"${deal.stage}\" for ${signals.daysInCurrentStage} days`);\n } else if (signals.daysInCurrentStage > 45) {\n score -= 12;\n warnings.push(`Slow progress in \"${deal.stage}\"`);\n }\n\n // Close date risk (max penalty -20)\n if (signals.daysToClose !== undefined) {\n if (signals.daysToClose < 0) {\n score -= 20;\n warnings.push(\"Close date passed\");\n } else if (signals.daysToClose < 7) {\n score -= 10;\n warnings.push(\"Close date in less than 7 days\");\n }\n }\n\n // Probability sanity (max penalty -15)\n if (signals.probability !== undefined) {\n if (signals.probability < 20 && deal.stage !== \"lead\") {\n score -= 15;\n warnings.push(`Low probability (${signals.probability}%) for stage \"${deal.stage}\"`);\n }\n }\n\n score = Math.max(0, score);\n return { score, grade: grade(score), signals, warnings };\n}\n\nexport interface DealTiming {\n daysSinceLastActivity: number;\n daysInCurrentStage: number;\n daysToClose?: number;\n}\n\nconst MS_PER_DAY = 86_400_000;\n\n/**\n * Derive activity/close timing for a deal relative to `todayDate`. Centralizes\n * the day-diff math that deal-room and deal-agent each computed identically.\n * A blank/whitespace close_date yields `undefined` (not a NaN day count).\n */\nexport function deriveDealTiming(deal: PipelineDeal, todayDate: Date): DealTiming {\n const updatedDate = deal.updated ? new Date(deal.updated) : todayDate;\n const daysSinceLastActivity = Math.floor(\n (todayDate.getTime() - updatedDate.getTime()) / MS_PER_DAY\n );\n const timing: DealTiming = {\n daysSinceLastActivity,\n daysInCurrentStage: daysSinceLastActivity,\n };\n if (deal.close_date && deal.close_date.trim() !== \"\") {\n timing.daysToClose = Math.floor(\n (new Date(deal.close_date).getTime() - todayDate.getTime()) / MS_PER_DAY\n );\n }\n return timing;\n}\n\n/** Score a deal using timing derived from `todayDate` plus the deal's probability. */\nexport function scoreDealForToday(deal: PipelineDeal, todayDate: Date): DealHealthScore {\n const timing = deriveDealTiming(deal, todayDate);\n return scoreDeal(deal, {\n daysSinceLastActivity: timing.daysSinceLastActivity,\n daysInCurrentStage: timing.daysInCurrentStage,\n ...(timing.daysToClose !== undefined ? { daysToClose: timing.daysToClose } : {}),\n ...(deal.probability !== undefined ? { probability: deal.probability } : {}),\n });\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readPipeline } from \"../../fs/pipeline-writer.js\";\nimport { scoreDeal } from \"../../core/deal-health.js\";\nimport type { DealHealthScore } from \"../../core/deal-health.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetDealHealth(\n input: { slug: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const deals = await readPipeline(dataDir, input.slug);\n const today = new Date();\n\n const results: Array<{ deal: string; stage: string } & DealHealthScore> = [];\n\n for (const deal of deals) {\n // Approximate signals from deal metadata\n const updatedDate = deal.updated ? new Date(deal.updated) : today;\n const daysSinceLastActivity = Math.floor(\n (today.getTime() - updatedDate.getTime()) / (1000 * 60 * 60 * 24)\n );\n\n const daysToClose = deal.close_date\n ? Math.floor(\n (new Date(deal.close_date).getTime() - today.getTime()) / (1000 * 60 * 60 * 24)\n )\n : undefined;\n\n const health = scoreDeal(deal, {\n daysSinceLastActivity,\n daysInCurrentStage: daysSinceLastActivity,\n ...(daysToClose !== undefined ? { daysToClose } : {}),\n ...(deal.probability !== undefined ? { probability: deal.probability } : {}),\n });\n\n results.push({ deal: deal.name, stage: deal.stage, ...health });\n }\n\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ slug: input.slug, deals: results }, null, 2) },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetDealHealth(server: McpServer): void {\n server.registerTool(\n \"get_deal_health\",\n {\n title: \"Get Deal Health\",\n description: `Score the health of all deals for a customer (0–100). Grade A–F based on activity recency, stage velocity, close date proximity, and probability.\n\nReturns: { slug, deals: [{ deal, stage, score, grade, signals, warnings }] }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n }),\n },\n async ({ slug }) => handleGetDealHealth({ slug })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readPipelineSync } from \"../../fs/pipeline-writer.js\";\nimport { listCustomerSlugs } from \"../../fs/customer-dir.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\ninterface ForecastDeal {\n slug: string;\n dealName: string;\n stage: string;\n value?: number | undefined;\n probability?: number | undefined;\n weightedValue: number;\n closeDate?: string | undefined;\n}\n\nexport async function handleGetPipelineForecast(\n input: { filter?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const slugs = listCustomerSlugs(dataDir).filter(\n (d) => !input.filter || d.includes(input.filter)\n );\n\n const allDeals: ForecastDeal[] = [];\n\n for (const slug of slugs) {\n // readPipelineSync already guards a missing file (returns []); no need for\n // a per-iteration existsSync + dynamic import.\n const deals = readPipelineSync(dataDir, slug);\n\n for (const deal of deals) {\n if (deal.stage === \"won\" || deal.stage === \"lost\") continue;\n const prob = deal.probability ?? 50;\n const value = deal.value ?? 0;\n const forecastDeal: ForecastDeal = {\n slug,\n dealName: deal.name,\n stage: deal.stage,\n value,\n probability: prob,\n weightedValue: Math.round((value * prob) / 100),\n };\n if (deal.close_date !== undefined) forecastDeal.closeDate = deal.close_date;\n allDeals.push(forecastDeal);\n }\n }\n\n const totalWeightedValue = allDeals.reduce((sum, d) => sum + d.weightedValue, 0);\n const byStage = allDeals.reduce<Record<string, { count: number; weightedValue: number }>>(\n (acc, d) => {\n if (!acc[d.stage]) acc[d.stage] = { count: 0, weightedValue: 0 };\n acc[d.stage]!.count++;\n acc[d.stage]!.weightedValue += d.weightedValue;\n return acc;\n },\n {}\n );\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ deals: allDeals, totalWeightedValue, byStage }, null, 2),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetPipelineForecast(server: McpServer): void {\n server.registerTool(\n \"get_pipeline_forecast\",\n {\n title: \"Get Pipeline Forecast\",\n description: `Aggregate weighted pipeline revenue across all customers. Groups open deals by stage, computes probability-weighted expected revenue.\n\nReturns: { deals: [...], totalWeightedValue: number, byStage: { stage: { count, weightedValue } } }`,\n inputSchema: z.object({\n filter: z.string().optional().describe(\"Filter by customer slug substring\"),\n }),\n },\n async ({ filter }) => handleGetPipelineForecast({ ...(filter !== undefined ? { filter } : {}) })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { appendInteraction } from \"../../fs/interactions-writer.js\";\nimport { writeAuditEntry, getActor } from \"../../fs/audit-log.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleSummarizeMeeting(\n input: {\n slug: string;\n transcript: string;\n with?: string;\n date?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n let summary = input.transcript.slice(0, 400);\n let nextSteps: string[] = [];\n\n try {\n const { callLlm } = await import(\"../../core/llm.js\");\n const prompt = `Summarize this meeting transcript in 3-5 sentences and extract action items.\\n\\nTranscript:\\n${input.transcript.slice(0, 3000)}\\n\\nRespond as JSON: { \"summary\": \"...\", \"nextSteps\": [\"...\"] }`;\n const response = await callLlm(prompt);\n const parsed = JSON.parse(response) as { summary?: string; nextSteps?: string[] };\n summary = parsed.summary ?? summary;\n nextSteps = parsed.nextSteps ?? [];\n } catch {\n // LLM unavailable — use raw transcript slice\n }\n\n const date = input.date ?? new Date().toISOString().slice(0, 10);\n const sourceRef = `agent://meeting/${Date.now()}`;\n\n await appendInteraction(dataDir, input.slug, {\n date,\n type: \"Meeting\",\n with: input.with ?? \"Meeting Participant\",\n summary,\n nextSteps,\n sourceRef,\n synced: new Date().toISOString(),\n });\n\n writeAuditEntry(dataDir, {\n timestamp: new Date().toISOString(),\n actor: getActor(),\n tool: \"summarize_meeting\",\n slug: input.slug,\n summary: summary.slice(0, 100),\n });\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: true, summary, nextSteps, sourceRef }, null, 2),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerSummarizeMeeting(server: McpServer): void {\n server.registerTool(\n \"summarize_meeting\",\n {\n title: \"Summarize Meeting\",\n description: `Summarize a meeting transcript and log it as an interaction. Uses LLM to extract key points and action items (falls back to raw text slice if LLM unavailable).\n\nArgs:\n slug: Customer ID\n transcript: Full meeting transcript text\n with: Participant name(s) (optional)\n date: Meeting date YYYY-MM-DD (optional, defaults to today)\n\nReturns: { success, summary, nextSteps, sourceRef }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n transcript: z.string().min(1).describe(\"Full meeting transcript\"),\n with: z.string().optional().describe(\"Participant names\"),\n date: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/)\n .optional()\n .describe(\"Meeting date\"),\n }),\n },\n async ({ slug, transcript, with: withStr, date }) =>\n handleSummarizeMeeting({\n slug,\n transcript,\n ...(withStr !== undefined ? { with: withStr } : {}),\n ...(date !== undefined ? { date } : {}),\n })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { getPipelineStages } from \"../../core/pipeline-stages.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetPipelineStages(\n _input: Record<string, never>,\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const stages = getPipelineStages(dataDir);\n return {\n content: [{ type: \"text\", text: JSON.stringify({ stages }, null, 2) }],\n };\n}\n\nexport function registerGetPipelineStages(server: McpServer): void {\n server.registerTool(\n \"get_pipeline_stages\",\n {\n title: \"Get Pipeline Stages\",\n description:\n \"Returns all configured pipeline stages. Falls back to default stages (lead, qualified, proposal, negotiation, won, lost) if no custom stages are configured.\",\n inputSchema: z.object({}),\n },\n async () => handleGetPipelineStages({})\n );\n}\n","import { searchKnowledge } from \"./lancedb.js\";\nimport { listCustomerSlugs } from \"../fs/customer-dir.js\";\n\nexport interface CrossCustomerResult {\n slug: string;\n relevantContent: string;\n score: number;\n}\n\nexport async function searchAcrossCustomers(\n dataDir: string,\n query: string,\n limit = 5,\n excludeSlug?: string\n): Promise<CrossCustomerResult[]> {\n const slugs = listCustomerSlugs(dataDir).filter((d) => d !== excludeSlug);\n\n // Each customer's vector search is independent — fan out in parallel rather\n // than awaiting one LanceDB query at a time (latency was linear in #customers).\n const perCustomer = await Promise.all(\n slugs.map(async (slug) => {\n const results = await searchKnowledge(dataDir, slug, query, 2);\n return results.map((r) => ({\n slug,\n relevantContent: r.content.slice(0, 200),\n score: r.score,\n }));\n })\n );\n\n return perCustomer\n .flat()\n .sort((a, b) => b.score - a.score)\n .slice(0, limit);\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { searchAcrossCustomers, type CrossCustomerResult } from \"../../core/cross-customer.js\";\nimport { listCustomerSlugs } from \"../../fs/customer-dir.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetMarketIntelligence(\n input: { query: string; excludeCurrentCustomer?: boolean; slug?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const excludeSlug = input.excludeCurrentCustomer ? input.slug : undefined;\n\n // Count total customers before excluding\n const all = listCustomerSlugs(dataDir);\n const totalCustomersSearched = excludeSlug\n ? all.filter((s) => s !== excludeSlug).length\n : all.length;\n\n const results: CrossCustomerResult[] = await searchAcrossCustomers(\n dataDir,\n input.query,\n 10,\n excludeSlug\n );\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ query: input.query, results, totalCustomersSearched }, null, 2),\n },\n ],\n };\n}\n\nexport function registerGetMarketIntelligence(server: McpServer): void {\n server.registerTool(\n \"get_market_intelligence\",\n {\n title: \"Get Market Intelligence\",\n description:\n \"Search across all customers to find patterns, common topics, or similar issues. Uses semantic search (LanceDB) across all customer knowledge bases. Results use slug (not real names) for privacy.\",\n inputSchema: z.object({\n query: z.string().describe(\"What to search for across all customers\"),\n excludeCurrentCustomer: z\n .boolean()\n .optional()\n .describe(\"Exclude the current customer from results\"),\n slug: z\n .string()\n .optional()\n .describe(\"Current customer slug (used with excludeCurrentCustomer)\"),\n }),\n },\n async ({ query, excludeCurrentCustomer, slug }) =>\n handleGetMarketIntelligence({\n query,\n ...(excludeCurrentCustomer !== undefined ? { excludeCurrentCustomer } : {}),\n ...(slug !== undefined ? { slug } : {}),\n })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readGraph, getStakeholders, findPath } from \"../../core/graph.js\";\nimport type { GraphNode } from \"../../core/graph.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nfunction summarizeNode(n: GraphNode) {\n return { id: n.id, name: n.label, email: n.properties[\"email\"] };\n}\n\nexport async function handleGetRelationshipGraph(\n input: { slug: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const graph = readGraph(dataDir, input.slug);\n const stakeholders = getStakeholders(graph);\n\n // Warm intro paths: BFS from owner contacts to each economic buyer\n const ownerContactIds = graph.nodes\n .filter((n) => n.type === \"person\" && n.properties[\"isOwnerContact\"] === true)\n .map((n) => n.id);\n const economicBuyerIds = stakeholders.economicBuyers.map((n) => n.id);\n\n const warmIntroPaths: Array<{ target: string; path: string[] }> = [];\n for (const ebId of economicBuyerIds) {\n for (const ownerId of ownerContactIds) {\n const p = findPath(graph, ownerId, ebId);\n if (p.length > 1) {\n warmIntroPaths.push({ target: ebId, path: p });\n break;\n }\n }\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n slug: input.slug,\n nodeCount: graph.nodes.length,\n edgeCount: graph.edges.length,\n updatedAt: graph.updatedAt,\n stakeholders: {\n champions: stakeholders.champions.map(summarizeNode),\n blockers: stakeholders.blockers.map(summarizeNode),\n economicBuyers: stakeholders.economicBuyers.map(summarizeNode),\n allContacts: stakeholders.allContacts.map(summarizeNode),\n missingRoles: stakeholders.missingRoles,\n },\n warmIntroPaths,\n nodes: graph.nodes,\n edges: graph.edges,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetRelationshipGraph(server: McpServer): void {\n server.registerTool(\n \"get_relationship_graph\",\n {\n title: \"Get Relationship Graph\",\n description: `Returns the knowledge graph for a customer: all known contacts, companies,\nand the relationships between them (KNOWS, WORKS_AT, IS_CHAMPION, IS_BLOCKER, IS_ECONOMIC_BUYER).\n\nThe graph auto-populates from every log_interaction call.\nUse this before a complex deal conversation to understand the stakeholder map.\n\nArgs:\n slug: Customer slug\n\nReturns: {\n stakeholders: { champions[], blockers[], economicBuyers[], allContacts[], missingRoles[] },\n nodes: GraphNode[],\n edges: GraphEdge[]\n}`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n }),\n },\n async ({ slug }) => handleGetRelationshipGraph({ slug })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readHealth, computeCustomerHealth, writeHealth } from \"../../core/relationship-health.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\nconst MAX_HEALTH_AGE_MS = 60 * 60 * 1000; // 1 hour\n\nexport async function handleGetRelationshipHealth(\n input: { slug: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n let health = readHealth(dataDir, input.slug);\n if (health === null || Date.now() - new Date(health.updatedAt).getTime() > MAX_HEALTH_AGE_MS) {\n health = computeCustomerHealth(dataDir, input.slug);\n writeHealth(dataDir, input.slug, health);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n slug: input.slug,\n overallHealth: health.overallHealth,\n updatedAt: health.updatedAt,\n atRiskContacts: health.contacts\n .filter((c) => c.riskFlags.length > 0)\n .map((c) => c.email ?? c.contactId),\n coldContacts: health.contacts\n .filter((c) => c.trend === \"cold\")\n .map((c) => c.email ?? c.contactId),\n contacts: health.contacts,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetRelationshipHealth(server: McpServer): void {\n server.registerTool(\n \"get_relationship_health\",\n {\n title: \"Get Relationship Health\",\n description: `Returns health scores for all contacts of a customer.\nScores decay automatically when communication cadence breaks — without any manual input.\n\nEach contact gets:\n- score (0–100), grade (A–F), trend (rising|stable|declining|cold)\n- riskFlags: NO_CONTACT_14D, NO_CONTACT_30D, CHAMPION_SILENT\n- recommendation: concrete next action\n\noverallHealth is the average across all contacts.\natRiskContacts + coldContacts are pre-filtered for quick triage.\nHealth auto-updates after every log_interaction call. Recomputes if stale (>1h).\n\nArgs:\n slug: Customer slug\n\nReturns: {\n overallHealth: number,\n atRiskContacts: string[],\n coldContacts: string[],\n contacts: ContactHealth[]\n}`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug (e.g. 'acme-corp')\"),\n }),\n },\n async ({ slug }) => handleGetRelationshipHealth({ slug })\n );\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { writeFileAtomic } from \"../fs/atomic-write.js\";\nimport matter from \"gray-matter\";\nimport { callLlm } from \"./llm.js\";\nimport { withFileQueue } from \"../fs/write-queue.js\";\nimport type { DealSnapshot } from \"./revenue-simulation.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface PlaybookFrontmatter {\n trigger: string;\n successRate: number;\n usedCount: number;\n lastUpdated: string;\n}\n\nexport interface Playbook {\n slug: string;\n name: string;\n frontmatter: PlaybookFrontmatter;\n content: string;\n path: string;\n}\n\nexport interface TriggerCondition {\n type:\n | \"stage\"\n | \"value_gt\"\n | \"value_lt\"\n | \"days_stalled_gt\"\n | \"days_stalled_lt\"\n | \"health_lt\"\n | \"health_gt\"\n | \"no_champion\"\n | \"has_champion\";\n value?: number;\n stage?: string;\n}\n\nexport interface PlaybookMatch {\n playbook: Playbook;\n score: number;\n matchedConditions: TriggerCondition[];\n totalConditions: number;\n}\n\nexport interface LlmDistillation {\n name: string;\n trigger: string;\n content: string;\n successRate: number;\n reasoning: string;\n}\n\n// ─── File paths ───────────────────────────────────────────────────────────────\n\nexport function playbooksDir(dataDir: string, slug: string): string {\n return path.join(dataDir, \"customers\", slug, \"playbooks\");\n}\n\n// ─── File operations ──────────────────────────────────────────────────────────\n\nexport function listPlaybooks(dataDir: string, slug: string): Playbook[] {\n const dir = playbooksDir(dataDir, slug);\n if (!fs.existsSync(dir)) return [];\n return fs\n .readdirSync(dir)\n .filter((f) => f.endsWith(\".md\"))\n .map((f): Playbook => {\n const filePath = path.join(dir, f);\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const parsed = matter(raw);\n return {\n slug,\n name: f.replace(/\\.md$/, \"\"),\n frontmatter: parsed.data as PlaybookFrontmatter,\n content: parsed.content.trim(),\n path: filePath,\n };\n });\n}\n\nexport function readPlaybook(dataDir: string, slug: string, name: string): Playbook | null {\n const filePath = path.join(playbooksDir(dataDir, slug), `${name}.md`);\n if (!fs.existsSync(filePath)) return null;\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const parsed = matter(raw);\n return {\n slug,\n name,\n frontmatter: parsed.data as PlaybookFrontmatter,\n content: parsed.content.trim(),\n path: filePath,\n };\n}\n\nexport async function writePlaybook(\n dataDir: string,\n slug: string,\n playbook: Playbook\n): Promise<void> {\n const dir = playbooksDir(dataDir, slug);\n const filePath = path.join(dir, `${playbook.name}.md`);\n await withFileQueue(filePath, async () => {\n fs.mkdirSync(dir, { recursive: true });\n const raw = matter.stringify(playbook.content, playbook.frontmatter);\n writeFileAtomic(filePath, raw);\n });\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nexport function toKebabCase(name: string): string {\n return name\n .replace(/[^a-z0-9-]/gi, \"-\")\n .toLowerCase()\n .replace(/-+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n// ─── Trigger DSL ──────────────────────────────────────────────────────────────\n\nexport interface ParsedTrigger {\n conditions: TriggerCondition[];\n operator: \"AND\" | \"OR\";\n}\n\nfunction parseTokens(tokens: string[]): TriggerCondition[] {\n return tokens.flatMap((token): TriggerCondition[] => {\n if (token.startsWith(\"deal_stage_\")) {\n return [{ type: \"stage\", stage: token.slice(\"deal_stage_\".length) }];\n }\n const valueGt = token.match(/^value\\s*>\\s*(\\d+)$/);\n if (valueGt) return [{ type: \"value_gt\", value: Number(valueGt[1]) }];\n\n const valueLt = token.match(/^value\\s*<\\s*(\\d+)$/);\n if (valueLt) return [{ type: \"value_lt\", value: Number(valueLt[1]) }];\n\n const stalledGt = token.match(/^days_stalled\\s*>\\s*(\\d+)$/);\n if (stalledGt) return [{ type: \"days_stalled_gt\", value: Number(stalledGt[1]) }];\n\n const stalledLt = token.match(/^days_stalled\\s*<\\s*(\\d+)$/);\n if (stalledLt) return [{ type: \"days_stalled_lt\", value: Number(stalledLt[1]) }];\n\n const healthLt = token.match(/^health\\s*<\\s*(\\d+)$/);\n if (healthLt) return [{ type: \"health_lt\", value: Number(healthLt[1]) }];\n\n const healthGt = token.match(/^health\\s*>\\s*(\\d+)$/);\n if (healthGt) return [{ type: \"health_gt\", value: Number(healthGt[1]) }];\n\n if (token === \"no_champion\") return [{ type: \"no_champion\" }];\n if (token === \"has_champion\") return [{ type: \"has_champion\" }];\n\n return []; // unknown token — silently dropped\n });\n}\n\nexport function parseTrigger(triggerStr: string | null | undefined): TriggerCondition[] {\n if (!triggerStr?.trim()) return [];\n const tokens = triggerStr\n .split(/\\s+AND\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n return parseTokens(tokens);\n}\n\nexport function parseTriggerFull(triggerStr: string | null | undefined): ParsedTrigger {\n if (!triggerStr?.trim()) return { conditions: [], operator: \"AND\" };\n const orTokens = triggerStr\n .split(/\\s+OR\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n if (orTokens.length > 1) {\n return { conditions: parseTokens(orTokens), operator: \"OR\" };\n }\n const andTokens = triggerStr\n .split(/\\s+AND\\s+/)\n .map((t) => t.trim())\n .filter(Boolean);\n return { conditions: parseTokens(andTokens), operator: \"AND\" };\n}\n\nexport function evaluateCondition(\n cond: TriggerCondition,\n deal: DealSnapshot,\n daysSinceContact: number\n): boolean {\n switch (cond.type) {\n case \"stage\":\n return deal.stage === cond.stage;\n case \"value_gt\":\n return deal.value > (cond.value ?? 0);\n case \"value_lt\":\n return deal.value < (cond.value ?? Infinity);\n // v1: days_stalled uses daysSinceContact as proxy (stage-change timestamps not tracked)\n case \"days_stalled_gt\":\n return daysSinceContact > (cond.value ?? 0);\n case \"days_stalled_lt\":\n return daysSinceContact < (cond.value ?? Infinity);\n case \"health_lt\":\n return deal.healthScore < (cond.value ?? 100);\n case \"health_gt\":\n return deal.healthScore > (cond.value ?? 0);\n case \"no_champion\":\n return !deal.championPresent;\n case \"has_champion\":\n return deal.championPresent;\n default:\n return false;\n }\n}\n\nexport function evaluateTrigger(\n conditions: TriggerCondition[],\n deal: DealSnapshot,\n daysSinceContact: number = 0,\n operator: \"AND\" | \"OR\" = \"AND\"\n): boolean {\n if (operator === \"OR\") {\n return conditions.some((c) => evaluateCondition(c, deal, daysSinceContact));\n }\n return conditions.every((c) => evaluateCondition(c, deal, daysSinceContact));\n}\n\n// ─── Matching ─────────────────────────────────────────────────────────────────\n\nexport function matchPlaybooks(\n playbooks: Playbook[],\n deal: DealSnapshot,\n daysSinceContact: number = 0\n): PlaybookMatch[] {\n const results: PlaybookMatch[] = [];\n for (const pb of playbooks) {\n const { conditions, operator } = parseTriggerFull(pb.frontmatter.trigger);\n if (conditions.length === 0) continue;\n const matched = conditions.filter((c) => evaluateCondition(c, deal, daysSinceContact));\n const isMatch = operator === \"OR\" ? matched.length > 0 : matched.length === conditions.length;\n if (isMatch) {\n results.push({\n playbook: pb,\n score: 1.0,\n matchedConditions: matched,\n totalConditions: conditions.length,\n });\n }\n }\n return results.sort((a, b) => {\n const rateDiff =\n (b.playbook.frontmatter.successRate ?? 0) - (a.playbook.frontmatter.successRate ?? 0);\n return rateDiff !== 0\n ? rateDiff\n : (b.playbook.frontmatter.usedCount ?? 0) - (a.playbook.frontmatter.usedCount ?? 0);\n });\n}\n\nexport function getBestPlaybook(\n dataDir: string,\n slug: string,\n deal: DealSnapshot,\n daysSinceContact: number = 0\n): PlaybookMatch | null {\n return matchPlaybooks(listPlaybooks(dataDir, slug), deal, daysSinceContact)[0] ?? null;\n}\n\n// ─── Distillation ─────────────────────────────────────────────────────────────\n\nexport function buildDistillPrompt(\n slug: string,\n dealName: string,\n outcome: \"won\" | \"lost\",\n interactions: string\n): string {\n return `You are analyzing a sales deal to extract a reusable playbook.\n\nCustomer: ${slug}\nDeal: ${dealName}\nOutcome: ${outcome}\nInteractions (chronological):\n${interactions.slice(0, 4000)}\n\nExtract a reusable playbook from this deal's journey.\n\nAllowed trigger tokens (combine with \" AND \"):\n- deal_stage_<stage> (e.g. deal_stage_negotiation)\n- value > <n> (e.g. value > 50000)\n- value < <n>\n- days_stalled > <n> (e.g. days_stalled > 7)\n- days_stalled < <n>\n- health < <n> (e.g. health < 60)\n- health > <n>\n- no_champion\n- has_champion\n\nReturn JSON only (no markdown wrapper):\n{\n \"name\": \"<kebab-case-playbook-name>\",\n \"trigger\": \"<DSL string using allowed tokens>\",\n \"content\": \"<markdown with ## Situation, ## Steps, ## Warnings sections>\",\n \"successRate\": <0.0-1.0>,\n \"reasoning\": \"<why these trigger conditions>\"\n}`;\n}\n\nexport function parseLlmDistillation(\n response: string,\n outcomeFallback: number = 0.5\n): LlmDistillation | null {\n try {\n const match = response.match(/\\{[\\s\\S]*\\}/);\n if (!match) return null;\n const parsed = JSON.parse(match[0]) as Partial<LlmDistillation>;\n if (!parsed.name || !parsed.trigger || !parsed.content) return null;\n return {\n name: parsed.name,\n trigger: parsed.trigger,\n content: parsed.content,\n successRate: typeof parsed.successRate === \"number\" ? parsed.successRate : outcomeFallback,\n reasoning: parsed.reasoning ?? \"\",\n };\n } catch {\n return null;\n }\n}\n\nexport type DistillPlaybookResult =\n | { ok: true; playbook: Playbook; reasoning: string }\n | { ok: false; errorKind: \"no_interactions\" | \"parse_failed\" };\n\nexport async function distillPlaybook(\n dataDir: string,\n slug: string,\n dealName: string,\n outcome: \"won\" | \"lost\",\n llmFn: (prompt: string) => Promise<string> = callLlm\n): Promise<DistillPlaybookResult> {\n const interactionsPath = path.join(dataDir, \"customers\", slug, \"interactions.md\");\n if (!fs.existsSync(interactionsPath)) return { ok: false, errorKind: \"no_interactions\" };\n\n const interactions = fs.readFileSync(interactionsPath, \"utf-8\");\n const prompt = buildDistillPrompt(slug, dealName, outcome, interactions);\n const response = await llmFn(prompt);\n\n const outcomeFallback = outcome === \"won\" ? 1.0 : 0.0;\n const distillation = parseLlmDistillation(response, outcomeFallback);\n if (!distillation) return { ok: false, errorKind: \"parse_failed\" };\n\n const today = new Date().toISOString().slice(0, 10);\n const name = toKebabCase(distillation.name);\n\n const playbook: Playbook = {\n slug,\n name,\n frontmatter: {\n trigger: distillation.trigger,\n successRate: distillation.successRate,\n usedCount: 1,\n lastUpdated: today,\n },\n content: distillation.content,\n path: path.join(playbooksDir(dataDir, slug), `${name}.md`),\n };\n\n await writePlaybook(dataDir, slug, playbook);\n return { ok: true, playbook, reasoning: distillation.reasoning };\n}\n","import fs from \"fs\";\nimport path from \"path\";\nimport { writeJsonFile } from \"../fs/json-store.js\";\nimport { readPipeline } from \"../fs/pipeline-writer.js\";\nimport { deriveDealTiming, scoreDealForToday } from \"../core/deal-health.js\";\nimport { computeCustomerHealth, readHealth } from \"../core/relationship-health.js\";\nimport type { InteractionEntry } from \"../schemas/interaction.js\";\nimport { readGraph, getStakeholders } from \"../core/graph.js\";\nimport { callLlm } from \"../core/llm.js\";\nimport { listPlaybooks, matchPlaybooks, type PlaybookMatch } from \"../core/playbooks.js\";\nimport type { PipelineDeal } from \"../schemas/pipeline.js\";\nimport type { DealHealthScore } from \"../core/deal-health.js\";\nimport type { HealthSnapshot } from \"../core/relationship-health.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type AutonomyLevel = \"observe\" | \"suggest\" | \"act\";\nexport type ActionType = \"log_interaction\" | \"update_deal\" | \"alert\" | \"schedule_meeting\";\nexport type ActionStatus = \"pending\" | \"approved\" | \"executed\" | \"rejected\" | \"skipped\";\nexport type RiskLevel = \"low\" | \"medium\" | \"high\" | \"critical\";\n\nexport interface DealAgentConfig {\n slug: string;\n dealName: string;\n autonomyLevel: AutonomyLevel;\n instruction?: string;\n valueThreshold: number;\n today: string;\n}\n\nexport interface DealAgentAction {\n actionId: string;\n type: ActionType;\n payload: Record<string, unknown>;\n confidence: number;\n reasoning: string;\n requiresHumanApproval: boolean;\n status: ActionStatus;\n createdAt: string;\n}\n\nexport interface DealPlanStep {\n step: number;\n action: string;\n priority: \"urgent\" | \"high\" | \"medium\" | \"low\";\n reason: string;\n}\n\nexport interface DealAgentTrace {\n timestamp: string;\n slug: string;\n dealName: string;\n autonomyLevel: AutonomyLevel;\n observation: string;\n plan: string[];\n actionsConsidered: DealAgentAction[];\n actionTaken: DealAgentAction | null;\n outcome: \"queued\" | \"executed\" | \"observed\" | \"error\";\n}\n\nexport interface DealAgentResult {\n slug: string;\n dealName: string;\n assessment: string;\n riskLevel: RiskLevel;\n plan: DealPlanStep[];\n actionsQueued: DealAgentAction[];\n actionsExecuted: DealAgentAction[];\n trace: DealAgentTrace;\n}\n\nexport interface LlmDealAnalysis {\n assessment: string;\n riskLevel: RiskLevel;\n plan: DealPlanStep[];\n actions: Array<{\n type: ActionType;\n payload: Record<string, unknown>;\n confidence: number;\n reasoning: string;\n }>;\n}\n\nexport interface DealObservation {\n deal: PipelineDeal;\n daysSinceLastActivity: number;\n daysInCurrentStage: number;\n daysToClose?: number;\n dealHealthScore: DealHealthScore;\n overallRelationshipHealth: number;\n atRiskContacts: string[];\n coldContacts: string[];\n missingRoles: Array<{ role: string; urgency: string }>;\n championCount: number;\n recentInteractionsSummary: string;\n contextSummary: string;\n matchingPlaybooks?: PlaybookMatch[]; // D15: procedural memory\n}\n\nexport interface AgentQueue {\n schemaVersion: \"1\";\n slug: string;\n pendingActions: DealAgentAction[];\n updatedAt: string;\n}\n\n// ─── File paths ───────────────────────────────────────────────────────────────\n\nexport function agentQueuePath(dataDir: string, slug: string): string {\n return path.join(dataDir, \"customers\", slug, \"agent-queue.json\");\n}\n\n// ─── Queue read / write ───────────────────────────────────────────────────────\n\nexport function readAgentQueue(dataDir: string, slug: string): AgentQueue {\n const p = agentQueuePath(dataDir, slug);\n if (!fs.existsSync(p)) {\n return { schemaVersion: \"1\", slug, pendingActions: [], updatedAt: new Date().toISOString() };\n }\n try {\n return JSON.parse(fs.readFileSync(p, \"utf-8\")) as AgentQueue;\n } catch {\n return { schemaVersion: \"1\", slug, pendingActions: [], updatedAt: new Date().toISOString() };\n }\n}\n\nexport function writeAgentQueue(dataDir: string, slug: string, queue: AgentQueue): void {\n const p = agentQueuePath(dataDir, slug);\n const dir = path.dirname(p);\n if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });\n const updated: AgentQueue = { ...queue, updatedAt: new Date().toISOString() };\n writeJsonFile(p, updated);\n}\n\n// ─── Action ID ────────────────────────────────────────────────────────────────\n\nexport function makeActionId(): string {\n return `da_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n}\n\n// ─── Observation helpers ──────────────────────────────────────────────────────\n\nfunction buildRecentInteractionsSummary(interactionsPath: string): string {\n if (!fs.existsSync(interactionsPath)) return \"(no interactions)\";\n const content = fs.readFileSync(interactionsPath, \"utf-8\") as string;\n const blocks = content\n .split(/(?=^## \\d{4}-\\d{2}-\\d{2})/m)\n .filter((b) => b.trim().length > 0)\n .slice(0, 3);\n return blocks\n .map((b) => {\n const dateMatch = b.match(/^## (\\d{4}-\\d{2}-\\d{2}) · (\\w+)/m);\n const summaryMatch = b.match(/^\\*\\*Summary:\\*\\*\\s*(.+)$/m);\n if (!dateMatch || !summaryMatch) return \"\";\n return `[${dateMatch[1]!}/${dateMatch[2]!}] ${summaryMatch[1]!.trim()}`;\n })\n .filter(Boolean)\n .join(\"\\n\");\n}\n\nfunction buildContextSummary(data: {\n deal: PipelineDeal;\n daysSinceLastActivity: number;\n daysInCurrentStage: number;\n daysToClose: number | undefined;\n dealHealthScore: DealHealthScore;\n health: HealthSnapshot;\n atRiskContacts: string[];\n coldContacts: string[];\n missingRoles: Array<{ role: string; urgency: string }>;\n championCount: number;\n recentInteractionsSummary: string;\n}): string {\n const lines: string[] = [\n `Deal: ${data.deal.name} | Stage: ${data.deal.stage} | Value: €${data.deal.value ?? \"?\"} | Close: ${data.deal.close_date ?? \"not set\"}`,\n `Days since activity: ${data.daysSinceLastActivity} | Days to close: ${data.daysToClose ?? \"?\"}`,\n `Deal health: grade ${data.dealHealthScore.grade} (score ${data.dealHealthScore.score})`,\n `Warnings: ${data.dealHealthScore.warnings.join(\"; \") || \"none\"}`,\n ``,\n `Relationship health: ${data.health.overallHealth}/100`,\n `At-risk contacts: ${data.atRiskContacts.join(\", \") || \"none\"}`,\n `Cold contacts: ${data.coldContacts.join(\", \") || \"none\"}`,\n `Missing stakeholder roles: ${data.missingRoles.map((r) => r.role).join(\", \") || \"none\"}`,\n `Champions identified: ${data.championCount}`,\n ``,\n `Recent interactions:`,\n data.recentInteractionsSummary || \"(none)\",\n ];\n return lines.join(\"\\n\");\n}\n\n// ─── Observation Layer ────────────────────────────────────────────────────────\n\nexport async function observeDeal(\n dataDir: string,\n slug: string,\n dealName: string,\n today: string\n): Promise<DealObservation | null> {\n const deals = await readPipeline(dataDir, slug).catch(() => [] as PipelineDeal[]);\n const deal = deals.find((d) => d.name.toLowerCase() === dealName.toLowerCase());\n if (!deal) return null;\n\n const todayDate = new Date(today);\n const { daysSinceLastActivity, daysInCurrentStage, daysToClose } = deriveDealTiming(\n deal,\n todayDate\n );\n const dealHealthScore = scoreDealForToday(deal, todayDate);\n\n // Prefer the cached health snapshot (written on each interaction); only\n // recompute — re-reading and parsing the full interactions file — when none\n // exists yet. Mirrors proactive-worker's read-then-compute pattern.\n const health = readHealth(dataDir, slug) ?? computeCustomerHealth(dataDir, slug, today);\n const atRiskContacts = health.contacts\n .filter((c) => c.riskFlags.length > 0)\n .map((c) => c.email ?? c.contactId);\n const coldContacts = health.contacts\n .filter((c) => c.trend === \"cold\")\n .map((c) => c.email ?? c.contactId);\n\n const graph = readGraph(dataDir, slug);\n const stakeholders = getStakeholders(graph);\n const missingRoles = stakeholders.missingRoles.map((r) => ({\n role: r.role,\n urgency: r.urgency,\n }));\n const championCount = stakeholders.champions.length;\n\n const interactionsPath = path.join(dataDir, \"customers\", slug, \"interactions.md\");\n const recentInteractionsSummary = buildRecentInteractionsSummary(interactionsPath);\n\n const contextSummary = buildContextSummary({\n deal,\n daysSinceLastActivity,\n daysInCurrentStage,\n daysToClose,\n dealHealthScore,\n health,\n atRiskContacts,\n coldContacts,\n missingRoles,\n championCount,\n recentInteractionsSummary,\n });\n\n const obs: DealObservation = {\n deal,\n daysSinceLastActivity,\n daysInCurrentStage,\n dealHealthScore,\n overallRelationshipHealth: health.overallHealth,\n atRiskContacts,\n coldContacts,\n missingRoles,\n championCount,\n recentInteractionsSummary,\n contextSummary,\n };\n if (daysToClose !== undefined) obs.daysToClose = daysToClose;\n\n // D15: load matching playbooks from procedural memory\n const dealSnap = {\n slug,\n name: deal.name,\n stage: deal.stage,\n value: deal.value ?? 0,\n probability: deal.probability ?? 50,\n healthScore: health.overallHealth,\n daysSinceContact: daysSinceLastActivity,\n championPresent: championCount > 0,\n };\n const allPlaybooks = listPlaybooks(dataDir, slug);\n const matchingPlaybooks = matchPlaybooks(allPlaybooks, dealSnap, daysSinceLastActivity);\n if (matchingPlaybooks.length > 0) obs.matchingPlaybooks = matchingPlaybooks;\n\n return obs;\n}\n\n// ─── LLM Prompt ──────────────────────────────────────────────────────────────\n\nexport function buildLlmPrompt(obs: DealObservation, config: DealAgentConfig): string {\n const instruction = config.instruction ?? \"Analyze this deal and recommend next actions.\";\n\n const playbookSection =\n obs.matchingPlaybooks && obs.matchingPlaybooks.length > 0\n ? `\\n## Matching Playbooks (${obs.matchingPlaybooks.length} found — apply these proven tactics)\\n` +\n obs.matchingPlaybooks\n .slice(0, 2)\n .map(\n (m) =>\n `### ${m.playbook.name} (${Math.round(m.playbook.frontmatter.successRate * 100)}% success rate, used ${m.playbook.frontmatter.usedCount}x)\\n${m.playbook.content.slice(0, 500)}`\n )\n .join(\"\\n\\n\")\n : \"\";\n\n return `You are a CRM deal agent. Analyze the deal situation and return an action plan.\nReturn ONLY valid JSON — no markdown, no explanation.\n\n${obs.contextSummary}${playbookSection}\n\nInstruction: ${instruction}\n\nRespond with JSON matching exactly:\n{\n \"assessment\": \"<2-3 sentence situation assessment>\",\n \"riskLevel\": \"low\" | \"medium\" | \"high\" | \"critical\",\n \"plan\": [\n { \"step\": 1, \"action\": \"<what to do>\", \"priority\": \"urgent\" | \"high\" | \"medium\" | \"low\", \"reason\": \"<why>\" }\n ],\n \"actions\": [\n {\n \"type\": \"log_interaction\" | \"update_deal\" | \"alert\" | \"schedule_meeting\",\n \"payload\": { /* tool-specific fields */ },\n \"confidence\": 0.0-1.0,\n \"reasoning\": \"<why this action>\"\n }\n ]\n}\n\nPayload schema per type:\n- log_interaction: { slug, type: \"Note\"|\"Call\"|\"Meeting\", summary, with }\n- update_deal: { slug, dealName, stage?, probability?, closeDate?, notes? }\n- alert: { slug, message, urgency: \"critical\"|\"high\"|\"medium\" }\n- schedule_meeting: { slug, with, notes }`;\n}\n\n// ─── LLM Response Parser ──────────────────────────────────────────────────────\n\nexport function parseLlmResponse(response: string): LlmDealAnalysis | null {\n try {\n const cleaned = response\n .replace(/^```(?:json)?\\n?/m, \"\")\n .replace(/\\n?```$/m, \"\")\n .trim();\n const parsed = JSON.parse(cleaned) as Partial<LlmDealAnalysis>;\n if (!parsed.assessment || !parsed.riskLevel || !Array.isArray(parsed.plan)) {\n return null;\n }\n return {\n assessment: String(parsed.assessment),\n riskLevel: parsed.riskLevel,\n plan: Array.isArray(parsed.plan) ? parsed.plan : [],\n actions: Array.isArray(parsed.actions) ? parsed.actions : [],\n };\n } catch {\n return null;\n }\n}\n\n// ─── Rule-Based Fallback ──────────────────────────────────────────────────────\n\nexport function buildRuleBasedAnalysis(\n obs: DealObservation,\n config: DealAgentConfig\n): LlmDealAnalysis {\n const plan: DealPlanStep[] = [];\n const actions: LlmDealAnalysis[\"actions\"] = [];\n let riskLevel: RiskLevel = \"low\";\n\n if (obs.dealHealthScore.grade === \"F\" || obs.coldContacts.length > 0) riskLevel = \"critical\";\n else if (obs.dealHealthScore.grade === \"D\" || obs.atRiskContacts.length > 0) riskLevel = \"high\";\n else if (obs.dealHealthScore.grade === \"C\") riskLevel = \"medium\";\n\n let step = 1;\n\n // D15: Playbook alerts as first plan items\n if (obs.matchingPlaybooks && obs.matchingPlaybooks.length > 0) {\n for (const match of obs.matchingPlaybooks.slice(0, 2)) {\n plan.push({\n step: step++,\n action: `Apply playbook: \"${match.playbook.name}\"`,\n priority: \"high\",\n reason: `Proven tactic (${Math.round(match.playbook.frontmatter.successRate * 100)}% success, used ${match.playbook.frontmatter.usedCount}x) — trigger: ${match.playbook.frontmatter.trigger}`,\n });\n actions.push({\n type: \"alert\",\n payload: {\n slug: config.slug,\n message: `Playbook available: \"${match.playbook.name}\" (${Math.round(match.playbook.frontmatter.successRate * 100)}% success rate)`,\n playbookContent: match.playbook.content.slice(0, 1000),\n urgency: \"high\",\n },\n confidence: match.playbook.frontmatter.successRate,\n reasoning: `Trigger matched: ${match.playbook.frontmatter.trigger}`,\n });\n }\n }\n\n if (obs.coldContacts.length > 0) {\n plan.push({\n step: step++,\n action: `Re-engage cold contacts: ${obs.coldContacts.join(\", \")}`,\n priority: \"urgent\",\n reason: \"No contact in 30+ days\",\n });\n actions.push({\n type: \"alert\",\n payload: {\n slug: config.slug,\n message: `Cold contacts: ${obs.coldContacts.join(\", \")}`,\n urgency: \"critical\",\n },\n confidence: 0.95,\n reasoning: \"No contact in 30+ days\",\n });\n }\n\n if (obs.atRiskContacts.length > 0) {\n plan.push({\n step: step++,\n action: `Schedule call with at-risk contacts`,\n priority: \"high\",\n reason: \"14+ days without contact\",\n });\n actions.push({\n type: \"schedule_meeting\",\n payload: {\n slug: config.slug,\n with: obs.atRiskContacts[0] ?? \"\",\n notes: \"Scheduled by deal agent — relationship at risk\",\n },\n confidence: 0.8,\n reasoning: \"At-risk contact identified\",\n });\n }\n\n if (obs.missingRoles.some((r) => r.role === \"economic_buyer\")) {\n plan.push({\n step: step++,\n action: \"Identify economic buyer\",\n priority: \"high\",\n reason: \"No budget owner identified\",\n });\n }\n\n if (obs.daysToClose !== undefined && obs.daysToClose < 14 && obs.dealHealthScore.grade !== \"A\") {\n plan.push({\n step: step++,\n action: \"Update deal close date or probability\",\n priority: \"urgent\",\n reason: `Close date in ${obs.daysToClose} days, deal at grade ${obs.dealHealthScore.grade}`,\n });\n actions.push({\n type: \"update_deal\",\n payload: {\n slug: config.slug,\n dealName: config.dealName,\n notes: `Reviewed by deal agent — ${obs.daysToClose}d to close`,\n },\n confidence: 0.75,\n reasoning: \"Close date imminent\",\n });\n }\n\n if (plan.length === 0) {\n plan.push({\n step: 1,\n action: \"Maintain current cadence\",\n priority: \"low\",\n reason: \"Deal healthy\",\n });\n }\n\n const assessment = `Deal \"${config.dealName}\" in stage \"${obs.deal.stage}\" — health grade ${obs.dealHealthScore.grade} (${obs.dealHealthScore.score}/100). Risk: ${riskLevel}.`;\n return { assessment, riskLevel, plan, actions };\n}\n\n// ─── Action Selection ─────────────────────────────────────────────────────────\n\nexport function selectActions(\n analysis: LlmDealAnalysis,\n obs: DealObservation,\n config: DealAgentConfig\n): DealAgentAction[] {\n return analysis.actions.map((a) => {\n const dealValue = obs.deal.value ?? 0;\n const autoExecutable =\n config.autonomyLevel === \"act\" && a.confidence >= 0.7 && dealValue < config.valueThreshold;\n\n return {\n actionId: makeActionId(),\n type: a.type,\n payload: a.payload,\n confidence: a.confidence,\n reasoning: a.reasoning,\n requiresHumanApproval: !autoExecutable,\n status: \"pending\" as ActionStatus,\n createdAt: new Date().toISOString(),\n };\n });\n}\n\n// ─── Action Execution ─────────────────────────────────────────────────────────\n\nconst VALID_STAGES = [\"lead\", \"qualified\", \"proposal\", \"negotiation\", \"won\", \"lost\"] as const;\n\nexport async function executeAction(\n action: DealAgentAction,\n dataDir: string\n): Promise<\"executed\" | \"skipped\"> {\n const slug = action.payload[\"slug\"] as string | undefined;\n if (!slug) return \"skipped\";\n\n switch (action.type) {\n case \"log_interaction\": {\n const { appendInteraction } = await import(\"../fs/interactions-writer.js\");\n const today = new Date().toISOString().slice(0, 10);\n await appendInteraction(dataDir, slug, {\n date: today,\n type: (action.payload[\"type\"] as InteractionEntry[\"type\"]) ?? \"Note\",\n with: String(action.payload[\"with\"] ?? \"agent\"),\n summary: String(action.payload[\"summary\"] ?? \"\"),\n nextSteps: [],\n sourceRef: `agent://deal-agent/${action.actionId}`,\n synced: new Date().toISOString(),\n });\n return \"executed\";\n }\n\n case \"schedule_meeting\": {\n const { appendInteraction } = await import(\"../fs/interactions-writer.js\");\n const today = new Date().toISOString().slice(0, 10);\n await appendInteraction(dataDir, slug, {\n date: today,\n type: \"Note\",\n with: String(action.payload[\"with\"] ?? \"\"),\n summary: `[Agent scheduled] ${String(action.payload[\"notes\"] ?? \"Meeting scheduled by deal agent\")}`,\n nextSteps: [`Schedule meeting with ${String(action.payload[\"with\"] ?? \"contact\")}`],\n sourceRef: `agent://deal-agent/${action.actionId}`,\n synced: new Date().toISOString(),\n });\n return \"executed\";\n }\n\n case \"update_deal\": {\n const { handleUpdateDeal } = await import(\"../mcp/tools/update-deal.js\");\n const payload = action.payload as {\n slug: string;\n dealName: string;\n stage?: string;\n value?: number;\n probability?: number;\n closeDate?: string;\n notes?: string;\n };\n const validStage = VALID_STAGES.find((s) => s === payload.stage);\n await handleUpdateDeal(\n {\n slug: payload.slug,\n dealName: payload.dealName,\n ...(validStage !== undefined ? { stage: validStage } : {}),\n ...(payload.value !== undefined ? { value: payload.value } : {}),\n ...(payload.probability !== undefined ? { probability: payload.probability } : {}),\n ...(payload.closeDate !== undefined ? { closeDate: payload.closeDate } : {}),\n ...(payload.notes !== undefined ? { notes: payload.notes } : {}),\n },\n dataDir\n );\n return \"executed\";\n }\n\n case \"alert\": {\n const queue = readAgentQueue(dataDir, slug);\n const alertAction: DealAgentAction = { ...action, status: \"pending\" };\n if (!queue.pendingActions.find((a) => a.actionId === action.actionId)) {\n queue.pendingActions.push(alertAction);\n writeAgentQueue(dataDir, slug, queue);\n }\n return \"executed\";\n }\n }\n}\n\n// ─── Main: runDealAgent ───────────────────────────────────────────────────────\n\nexport async function runDealAgent(\n config: DealAgentConfig,\n dataDir: string,\n llmFn: (prompt: string) => Promise<string> = callLlm\n): Promise<DealAgentResult> {\n const timestamp = new Date().toISOString();\n\n const obs = await observeDeal(dataDir, config.slug, config.dealName, config.today);\n if (!obs) {\n throw new Error(`Deal \"${config.dealName}\" not found for customer \"${config.slug}\"`);\n }\n\n let analysis: LlmDealAnalysis;\n try {\n const prompt = buildLlmPrompt(obs, config);\n const rawResponse = await llmFn(prompt);\n analysis = parseLlmResponse(rawResponse) ?? buildRuleBasedAnalysis(obs, config);\n } catch {\n analysis = buildRuleBasedAnalysis(obs, config);\n }\n\n const allActions = selectActions(analysis, obs, config);\n\n const actionsQueued: DealAgentAction[] = [];\n const actionsExecuted: DealAgentAction[] = [];\n\n if (config.autonomyLevel === \"observe\") {\n // No side effects\n } else if (config.autonomyLevel === \"suggest\") {\n if (allActions.length > 0) {\n const queue = readAgentQueue(dataDir, config.slug);\n for (const action of allActions) {\n queue.pendingActions.push({ ...action, requiresHumanApproval: true });\n actionsQueued.push(action);\n }\n writeAgentQueue(dataDir, config.slug, queue);\n }\n } else {\n // act mode\n const queue = readAgentQueue(dataDir, config.slug);\n let queueDirty = false;\n for (const action of allActions) {\n if (!action.requiresHumanApproval) {\n const outcome = await executeAction(action, dataDir).catch(() => \"skipped\" as const);\n actionsExecuted.push({\n ...action,\n status: outcome === \"executed\" ? \"executed\" : \"skipped\",\n });\n } else {\n queue.pendingActions.push(action);\n actionsQueued.push(action);\n queueDirty = true;\n }\n }\n if (queueDirty) writeAgentQueue(dataDir, config.slug, queue);\n }\n\n const trace: DealAgentTrace = {\n timestamp,\n slug: config.slug,\n dealName: config.dealName,\n autonomyLevel: config.autonomyLevel,\n observation: obs.contextSummary,\n plan: analysis.plan.map((s) => `${s.step}. ${s.action} [${s.priority}]`),\n actionsConsidered: allActions,\n actionTaken: actionsExecuted[0] ?? null,\n outcome:\n actionsExecuted.length > 0 ? \"executed\" : actionsQueued.length > 0 ? \"queued\" : \"observed\",\n };\n\n return {\n slug: config.slug,\n dealName: config.dealName,\n assessment: analysis.assessment,\n riskLevel: analysis.riskLevel,\n plan: analysis.plan,\n actionsQueued,\n actionsExecuted,\n trace,\n };\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { runDealAgent } from \"../../agents/deal-agent.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleRunDealAgent(\n input: {\n slug: string;\n dealName: string;\n autonomyLevel?: \"observe\" | \"suggest\" | \"act\";\n instruction?: string;\n valueThreshold?: number;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const today = new Date().toISOString().slice(0, 10);\n const result = await runDealAgent(\n {\n slug: input.slug,\n dealName: input.dealName,\n autonomyLevel: input.autonomyLevel ?? \"suggest\",\n valueThreshold: input.valueThreshold ?? 50_000,\n today,\n ...(input.instruction !== undefined ? { instruction: input.instruction } : {}),\n },\n dataDir\n );\n return {\n content: [{ type: \"text\", text: JSON.stringify(result, null, 2) }],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerRunDealAgent(server: McpServer): void {\n server.registerTool(\n \"run_deal_agent\",\n {\n title: \"Run Deal Agent\",\n description: `Analyzes a specific deal and generates a prioritized action plan.\n\nThree autonomy levels:\n- observe: analyze and return plan, no side effects\n- suggest (default): queue actions for human review in agent-queue.json\n- act: auto-execute actions with confidence ≥ 0.7 and value < valueThreshold\n\nEach action includes confidence score and reasoning (glass-box).\nReturns full trace for inspection.\n\nArgs:\n slug: Customer slug\n dealName: Exact deal name\n autonomyLevel: \"observe\" | \"suggest\" | \"act\" (default: \"suggest\")\n instruction: Optional context/question for the agent\n valueThreshold: EUR value above which no auto-execution (default: 50000)\n\nReturns: { assessment, riskLevel, plan[], actionsQueued[], actionsExecuted[], trace }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n dealName: z.string().describe(\"Exact deal name\"),\n autonomyLevel: z\n .enum([\"observe\", \"suggest\", \"act\"])\n .optional()\n .describe(\"Autonomy level (default: suggest)\"),\n instruction: z.string().optional().describe(\"Optional instruction for the agent\"),\n valueThreshold: z\n .number()\n .optional()\n .describe(\"EUR value above which no auto-execution (default: 50000)\"),\n }),\n },\n async ({ slug, dealName, autonomyLevel, instruction, valueThreshold }) =>\n handleRunDealAgent({\n slug,\n dealName,\n ...(autonomyLevel !== undefined ? { autonomyLevel } : {}),\n ...(instruction !== undefined ? { instruction } : {}),\n ...(valueThreshold !== undefined ? { valueThreshold } : {}),\n })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readAgentQueue, writeAgentQueue, executeAction } from \"../../agents/deal-agent.js\";\n\nexport { readAgentQueue } from \"../../agents/deal-agent.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleApproveAgentAction(\n input: { slug: string; actionId: string; approved: boolean },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const queue = readAgentQueue(dataDir, input.slug);\n const idx = queue.pendingActions.findIndex((a) => a.actionId === input.actionId);\n\n if (idx === -1) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { success: false, error: `Action ${input.actionId} not found in queue` },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n const action = queue.pendingActions[idx]!;\n\n if (!input.approved) {\n queue.pendingActions[idx] = { ...action, status: \"rejected\" };\n writeAgentQueue(dataDir, input.slug, queue);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { success: true, actionId: input.actionId, status: \"rejected\" },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n const outcome = await executeAction(action, dataDir);\n queue.pendingActions[idx] = {\n ...action,\n status: outcome === \"executed\" ? \"executed\" : \"skipped\",\n };\n writeAgentQueue(dataDir, input.slug, queue);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n actionId: input.actionId,\n status: queue.pendingActions[idx]!.status,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerApproveAgentAction(server: McpServer): void {\n server.registerTool(\n \"approve_agent_action\",\n {\n title: \"Approve Agent Action\",\n description: `Approve or reject a pending action from the deal agent queue.\n\nFind actionId in the actionsQueued array returned by run_deal_agent.\n\nArgs:\n slug: Customer slug\n actionId: Action ID from the agent queue\n approved: true to execute, false to reject\n\nReturns: { success, actionId, status }`,\n inputSchema: z.object({\n slug: z.string(),\n actionId: z.string(),\n approved: z.boolean(),\n }),\n },\n async ({ slug, actionId, approved }) => handleApproveAgentAction({ slug, actionId, approved })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport {\n buildSimulationInput,\n runSimulation,\n buildConfidenceMessage,\n} from \"../../core/revenue-simulation.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleSimulateRevenue(\n input: { horizon?: \"quarter\" | \"year\"; iterations?: number },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const today = new Date().toISOString().slice(0, 10);\n const horizon = input.horizon ?? \"quarter\";\n\n const simInput = await buildSimulationInput(dataDir, horizon, today);\n if (input.iterations !== undefined) simInput.iterations = input.iterations;\n\n const result = runSimulation(simInput);\n const confidence = buildConfidenceMessage(result, simInput.deals.length);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n forecast: result,\n confidence,\n dealCount: simInput.deals.length,\n horizon,\n simulatedAt: new Date().toISOString(),\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerSimulateRevenue(server: McpServer): void {\n server.registerTool(\n \"simulate_revenue\",\n {\n title: \"Simulate Revenue\",\n description: `Monte Carlo pipeline revenue simulation with P10/P50/P90 confidence intervals.\n\nAdjusts deal win probabilities using relationship health scores (D12) and\nchampion presence (D11). Returns the range of possible quarterly/annual outcomes.\n\nUse this instead of (or alongside) get_pipeline_forecast when you need:\n- Uncertainty quantification (not just expected value)\n- At-risk revenue identification\n- Deal sensitivity analysis (\"which deal matters most\")\n- Month-by-month close distribution\n\nArgs:\n horizon: \"quarter\" (default) | \"year\"\n iterations: simulation iterations (default: 10000)\n\nReturns: { forecast: { p10, p50, p90, expected, stdDev, atRiskRevenue, byCloseMonth, topRisks, sensitivityMap }, confidence, dealCount, horizon }`,\n inputSchema: z.object({\n horizon: z\n .enum([\"quarter\", \"year\"])\n .optional()\n .describe('Forecast horizon (default: \"quarter\")'),\n iterations: z.number().optional().describe(\"Monte Carlo iterations (default: 10000)\"),\n }),\n },\n async ({ horizon, iterations }) =>\n handleSimulateRevenue({\n ...(horizon !== undefined ? { horizon } : {}),\n ...(iterations !== undefined ? { iterations } : {}),\n })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { listPlaybooks, matchPlaybooks } from \"../../core/playbooks.js\";\nimport type { DealSnapshot } from \"../../core/revenue-simulation.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetPlaybook(\n input: {\n slug: string;\n stage?: string;\n value?: number;\n healthScore?: number;\n daysSinceContact?: number;\n championPresent?: boolean;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const playbooks = listPlaybooks(dataDir, input.slug);\n\n const hasDealContext =\n input.stage !== undefined || input.value !== undefined || input.healthScore !== undefined;\n\n if (!hasDealContext) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n matches: playbooks.map((pb) => ({\n name: pb.name,\n trigger: pb.frontmatter.trigger,\n successRate: pb.frontmatter.successRate,\n usedCount: pb.frontmatter.usedCount,\n lastUpdated: pb.frontmatter.lastUpdated,\n content: pb.content,\n })),\n totalPlaybooks: playbooks.length,\n slug: input.slug,\n },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n const mockDeal: DealSnapshot = {\n slug: input.slug,\n name: \"\",\n stage: input.stage ?? \"lead\",\n value: input.value ?? 0,\n probability: 50,\n healthScore: input.healthScore ?? 60,\n daysSinceContact: input.daysSinceContact ?? 0,\n championPresent: input.championPresent ?? false,\n };\n\n const matches = matchPlaybooks(playbooks, mockDeal, input.daysSinceContact ?? 0);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n matches: matches.map((m) => ({\n name: m.playbook.name,\n score: m.score,\n matchedConditions: m.matchedConditions,\n trigger: m.playbook.frontmatter.trigger,\n successRate: m.playbook.frontmatter.successRate,\n usedCount: m.playbook.frontmatter.usedCount,\n content: m.playbook.content,\n })),\n totalPlaybooks: playbooks.length,\n slug: input.slug,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetPlaybook(server: McpServer): void {\n server.registerTool(\n \"get_playbook\",\n {\n title: \"Get Playbook\",\n description: `Retrieve playbooks for a customer. With deal context, returns only matching playbooks sorted by success rate. Without deal context, returns all playbooks.\n\nUse after run_deal_agent or before a sales call to get proven guidance for the current situation.\n\nArgs:\n slug: Customer ID (required)\n stage: Deal stage (optional — enables trigger matching)\n value: Deal value in euros (optional)\n healthScore: Relationship health score 0–100 (optional)\n daysSinceContact: Days since last contact / days_stalled proxy (optional)\n championPresent: Whether a champion is identified (optional)\n\nReturns: { matches: [{ name, score, trigger, successRate, usedCount, content }], totalPlaybooks, slug }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer ID\"),\n stage: z.string().optional().describe(\"Deal stage\"),\n value: z.number().optional().describe(\"Deal value in euros\"),\n healthScore: z.number().optional().describe(\"Health score 0–100\"),\n daysSinceContact: z.number().optional().describe(\"Days since last contact\"),\n championPresent: z.boolean().optional().describe(\"Champion identified\"),\n }),\n },\n async ({ slug, stage, value, healthScore, daysSinceContact, championPresent }) =>\n handleGetPlaybook(\n {\n slug,\n ...(stage !== undefined ? { stage } : {}),\n ...(value !== undefined ? { value } : {}),\n ...(healthScore !== undefined ? { healthScore } : {}),\n ...(daysSinceContact !== undefined ? { daysSinceContact } : {}),\n ...(championPresent !== undefined ? { championPresent } : {}),\n },\n DATA_DIR\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { writePlaybook, playbooksDir, toKebabCase } from \"../../core/playbooks.js\";\nimport path from \"path\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleCreatePlaybook(\n input: {\n slug: string;\n name: string;\n trigger: string;\n content: string;\n successRate?: number;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const name = toKebabCase(input.name);\n const today = new Date().toISOString().slice(0, 10);\n const filePath = path.join(playbooksDir(dataDir, input.slug), `${name}.md`);\n\n const playbook = {\n slug: input.slug,\n name,\n frontmatter: {\n trigger: input.trigger,\n successRate: input.successRate ?? 0.5,\n usedCount: 0,\n lastUpdated: today,\n },\n content: input.content,\n path: filePath,\n };\n\n await writePlaybook(dataDir, input.slug, playbook);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n playbook: {\n name,\n trigger: input.trigger,\n successRate: playbook.frontmatter.successRate,\n usedCount: 0,\n lastUpdated: today,\n path: filePath,\n },\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerCreatePlaybook(server: McpServer): void {\n server.registerTool(\n \"create_playbook\",\n {\n title: \"Create Playbook\",\n description: `Create or update a playbook for a customer. Playbooks encode proven tactics for specific deal situations.\n\nTrigger DSL uses AND-only conditions:\n deal_stage_<stage> | value > N | value < N | days_stalled > N | health < N | health > N | no_champion | has_champion\n\nExample: \"deal_stage_negotiation AND value > 50000 AND days_stalled > 7\"\n\nArgs:\n slug: Customer ID\n name: Playbook name (auto-converted to kebab-case)\n trigger: Trigger DSL string (conditions separated by AND)\n content: Playbook markdown body (## Situation, ## Steps, ## Warnings, ## Templates)\n successRate: Historical win rate 0.0–1.0 (default: 0.5)\n\nReturns: { success: true, playbook: { name, trigger, successRate, path } }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer ID\"),\n name: z.string().describe(\"Playbook name\"),\n trigger: z.string().describe(\"Trigger DSL string\"),\n content: z.string().describe(\"Playbook markdown body\"),\n successRate: z.number().min(0).max(1).optional().describe(\"Historical win rate 0.0–1.0\"),\n }),\n },\n async ({ slug, name, trigger, content, successRate }) =>\n handleCreatePlaybook(\n {\n slug,\n name,\n trigger,\n content,\n ...(successRate !== undefined ? { successRate } : {}),\n },\n DATA_DIR\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { listPlaybooks } from \"../../core/playbooks.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleListPlaybooks(\n input: { slug: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const playbooks = listPlaybooks(dataDir, input.slug);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n playbooks: playbooks.map((pb) => ({\n name: pb.name,\n trigger: pb.frontmatter.trigger,\n successRate: pb.frontmatter.successRate,\n usedCount: pb.frontmatter.usedCount,\n lastUpdated: pb.frontmatter.lastUpdated,\n })),\n count: playbooks.length,\n slug: input.slug,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerListPlaybooks(server: McpServer): void {\n server.registerTool(\n \"list_playbooks\",\n {\n title: \"List Playbooks\",\n description: `List all playbooks for a customer (metadata only, no body content).\n\nUse to discover available playbooks before calling get_playbook with deal context.\n\nArgs:\n slug: Customer ID\n\nReturns: { playbooks: [{ name, trigger, successRate, usedCount, lastUpdated }], count, slug }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer ID\"),\n }),\n },\n async ({ slug }) => handleListPlaybooks({ slug }, DATA_DIR)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { distillPlaybook } from \"../../core/playbooks.js\";\nimport { callLlm } from \"../../core/llm.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleDistillPlaybook(\n input: { slug: string; dealName: string; outcome: \"won\" | \"lost\" },\n dataDir: string = DATA_DIR,\n llmFn: (prompt: string) => Promise<string> = callLlm\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const result = await distillPlaybook(dataDir, input.slug, input.dealName, input.outcome, llmFn);\n\n if (!result.ok) {\n const error =\n result.errorKind === \"no_interactions\"\n ? `No interactions.md found for ${input.slug}`\n : \"LLM response could not be parsed as playbook\";\n return {\n content: [{ type: \"text\", text: JSON.stringify({ success: false, error }, null, 2) }],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n playbook: {\n name: result.playbook.name,\n trigger: result.playbook.frontmatter.trigger,\n successRate: result.playbook.frontmatter.successRate,\n usedCount: result.playbook.frontmatter.usedCount,\n path: result.playbook.path,\n },\n reasoning: result.reasoning,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerDistillPlaybook(server: McpServer): void {\n server.registerTool(\n \"distill_playbook\",\n {\n title: \"Distill Playbook\",\n description: `Use LLM to extract a reusable playbook from a won or lost deal's interaction history. Analyzes the customer's interactions.md and identifies the winning/losing pattern as a structured playbook.\n\nRun after every won or lost deal to build your procedural memory library.\n\nArgs:\n slug: Customer ID\n dealName: Name of the deal to analyze\n outcome: \"won\" or \"lost\"\n\nReturns: { success: true, playbook: { name, trigger, successRate, path }, reasoning }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer ID\"),\n dealName: z.string().describe(\"Deal name to analyze\"),\n outcome: z.enum([\"won\", \"lost\"]).describe(\"Deal outcome\"),\n }),\n },\n async ({ slug, dealName, outcome }) =>\n handleDistillPlaybook({ slug, dealName, outcome }, DATA_DIR)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { pursueGoal, type BuildInputFn } from \"../../core/goal-engine.js\";\nimport { enforceRbac } from \"../../core/rbac.js\";\nimport { getActor } from \"../../fs/audit-log.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handlePursueGoal(\n input: { goal: string; deadline: string; context?: string },\n dataDir: string = DATA_DIR,\n options: { buildInputFn?: BuildInputFn; llmFn?: (p: string) => Promise<string> } = {}\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n enforceRbac(dataDir, \"pursue_goal\");\n\n const goal = await pursueGoal(\n dataDir,\n {\n description: input.goal,\n deadline: input.deadline,\n ...(input.context ? { context: input.context } : {}),\n },\n {\n actor: getActor(),\n ...(options.buildInputFn ? { buildInputFn: options.buildInputFn } : {}),\n ...(options.llmFn ? { llmFn: options.llmFn } : {}),\n }\n );\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n goalId: goal.id,\n description: goal.description,\n target: goal.target,\n deadline: goal.deadline,\n type: goal.type,\n decomposition: {\n analysis: goal.decomposition.analysis,\n currentPipeline: goal.decomposition.currentPipeline,\n gap: goal.decomposition.gap,\n subGoals: goal.decomposition.subGoals,\n probabilisticOutcome: goal.decomposition.probabilisticOutcome,\n },\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerPursueGoal(server: McpServer): void {\n server.registerTool(\n \"pursue_goal\",\n {\n title: \"Pursue Goal\",\n description: `Set a revenue or pipeline goal and get an AI-decomposed action plan.\n\nAnalyzes current pipeline (P50 forecast) and decomposes the gap into prioritized sub-goals per deal. Persists the goal in .agentic/goals.json for tracking.\n\nRBAC: manager+\n\nArgs:\n goal: Natural language goal description (e.g. \"Close €500k ARR this quarter\")\n deadline: Target deadline (YYYY-MM-DD)\n context: Optional constraints (e.g. \"Focus on existing pipeline only\")\n\nReturns: { goalId, description, target, deadline, decomposition: { analysis, currentPipeline, gap, subGoals, probabilisticOutcome } }`,\n inputSchema: z.object({\n goal: z.string().describe(\"Natural language goal (e.g. 'Close €500k ARR this quarter')\"),\n deadline: z.string().describe(\"Target deadline YYYY-MM-DD\"),\n context: z.string().optional().describe(\"Optional constraints or focus areas\"),\n }),\n },\n async ({ goal, deadline, context }) =>\n handlePursueGoal({ goal, deadline, ...(context !== undefined ? { context } : {}) }, DATA_DIR)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readGoals, getActiveGoals } from \"../../core/goal-engine.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetGoalStatus(\n input: { goalId?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const today = new Date().toISOString().slice(0, 10);\n const allGoals = input.goalId\n ? readGoals(dataDir).filter((g) => g.id === input.goalId)\n : getActiveGoals(dataDir);\n\n if (input.goalId && allGoals.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { success: false, error: `Goal '${input.goalId}' not found` },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n const goals = allGoals.map((g) => {\n const deadlineMs = new Date(g.deadline).getTime();\n const todayMs = new Date(today).getTime();\n const daysRemaining = Math.max(0, Math.ceil((deadlineMs - todayMs) / 86_400_000));\n return {\n id: g.id,\n description: g.description,\n target: g.target,\n progress: g.progress,\n status: g.status,\n deadline: g.deadline,\n daysRemaining,\n subGoals: g.decomposition.subGoals.slice(0, 3),\n createdAt: g.createdAt,\n };\n });\n\n const active = allGoals.filter((g) => g.status === \"active\");\n const completed = allGoals.filter((g) => g.status === \"completed\");\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { goals, activeCount: active.length, completedCount: completed.length },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetGoalStatus(server: McpServer): void {\n server.registerTool(\n \"get_goal_status\",\n {\n title: \"Get Goal Status\",\n description: `Get the status of active goals. Without goalId, returns all active goals. With goalId, returns that specific goal.\n\nReturns progress, days remaining, and top sub-goals for each goal.\n\nArgs:\n goalId: (optional) Specific goal ID — if omitted, returns all active goals\n\nReturns: { goals: [{ id, description, target, progress, status, deadline, daysRemaining, subGoals }], activeCount, completedCount }`,\n inputSchema: z.object({\n goalId: z.string().optional().describe(\"Specific goal ID (omit for all active goals)\"),\n }),\n },\n async ({ goalId }) =>\n handleGetGoalStatus({ ...(goalId !== undefined ? { goalId } : {}) }, DATA_DIR)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { register, type PushProvider } from \"../../sync/push-manager.js\";\nimport { enforceRbac } from \"../../core/rbac.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nconst VALID_PROVIDERS: PushProvider[] = [\"gmail\", \"microsoft-graph\", \"slack\"];\n\nexport async function handleRegisterPushSubscription(\n input: {\n provider: PushProvider;\n slug: string;\n webhookUrl: string;\n gmailTopicName?: string;\n microsoftClientState?: string;\n microsoftResource?: string;\n slackTeamId?: string;\n slackChannelId?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n if (!VALID_PROVIDERS.includes(input.provider)) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n { success: false, error: `Unknown provider: ${input.provider}` },\n null,\n 2\n ),\n },\n ],\n };\n }\n\n enforceRbac(dataDir, \"register_push_subscription\");\n\n const providerData: Record<string, string> = {};\n if (input.gmailTopicName) providerData[\"gmailTopicName\"] = input.gmailTopicName;\n if (input.microsoftClientState)\n providerData[\"microsoftClientState\"] = input.microsoftClientState;\n if (input.microsoftResource) providerData[\"microsoftResource\"] = input.microsoftResource;\n if (input.slackTeamId) providerData[\"slackTeamId\"] = input.slackTeamId;\n if (input.slackChannelId) providerData[\"slackChannelId\"] = input.slackChannelId;\n\n const sub = await register(dataDir, input.provider, input.slug, {\n webhookUrl: input.webhookUrl,\n providerData,\n });\n\n const warning = input.webhookUrl.includes(\"localhost\")\n ? \"Warning: webhookUrl contains 'localhost' — providers cannot reach local endpoints. Use a tunnel (e.g. ngrok http 3847) for development.\"\n : undefined;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n subscriptionId: sub.id,\n provider: sub.provider,\n slug: sub.slug,\n status: sub.status,\n expiresAt: sub.expiresAt,\n createdAt: sub.createdAt,\n ...(warning ? { warning } : {}),\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerRegisterPushSubscription(server: McpServer): void {\n server.registerTool(\n \"register_push_subscription\",\n {\n title: \"Register Push Subscription\",\n description: `Register a real-time push subscription for a customer (Gmail Pub/Sub, MS Graph webhook, or Slack Events).\n\nInstead of polling every 30 minutes, the provider will push new events to dxcrm within seconds.\n\nRBAC: admin only\n\nArgs:\n provider: \"gmail\" | \"microsoft-graph\" | \"slack\"\n slug: Customer slug to receive events for\n webhookUrl: Public HTTPS URL where the provider will POST events (e.g. https://yourserver.com/webhooks/gmail)\n gmailTopicName: (Gmail only) Cloud Pub/Sub topic name (e.g. projects/my-project/topics/gmail-push)\n microsoftClientState: (MS Graph only) Secret for HMAC verification\n microsoftResource: (MS Graph only) Resource path (e.g. /me/mailFolders/Inbox/messages)\n slackTeamId: (Slack only) Workspace/team ID (e.g. T12345)\n slackChannelId: (Slack only) Optional specific channel to monitor\n\nReturns: { subscriptionId, provider, slug, status, expiresAt, createdAt, warning? }`,\n inputSchema: z.object({\n provider: z.enum([\"gmail\", \"microsoft-graph\", \"slack\"]).describe(\"Push provider\"),\n slug: z.string().describe(\"Customer slug\"),\n webhookUrl: z.string().describe(\"Public HTTPS URL for provider callbacks\"),\n gmailTopicName: z.string().optional().describe(\"Gmail: Cloud Pub/Sub topic name\"),\n microsoftClientState: z.string().optional().describe(\"MS Graph: secret for verification\"),\n microsoftResource: z.string().optional().describe(\"MS Graph: resource path\"),\n slackTeamId: z.string().optional().describe(\"Slack: workspace team ID\"),\n slackChannelId: z.string().optional().describe(\"Slack: optional channel ID\"),\n }),\n },\n async ({\n provider,\n slug,\n webhookUrl,\n gmailTopicName,\n microsoftClientState,\n microsoftResource,\n slackTeamId,\n slackChannelId,\n }) =>\n handleRegisterPushSubscription(\n {\n provider,\n slug,\n webhookUrl,\n ...(gmailTopicName !== undefined ? { gmailTopicName } : {}),\n ...(microsoftClientState !== undefined ? { microsoftClientState } : {}),\n ...(microsoftResource !== undefined ? { microsoftResource } : {}),\n ...(slackTeamId !== undefined ? { slackTeamId } : {}),\n ...(slackChannelId !== undefined ? { slackChannelId } : {}),\n },\n DATA_DIR\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readSubscriptions, type PushProvider, type PushStatus } from \"../../sync/push-manager.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetPushStatus(\n input: { slug?: string; provider?: PushProvider },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n let subs = await readSubscriptions(dataDir);\n\n if (input.slug) subs = subs.filter((s) => s.slug === input.slug);\n if (input.provider) subs = subs.filter((s) => s.provider === input.provider);\n\n const now = Date.now();\n const RENEWAL_THRESHOLD_MS = 24 * 60 * 60 * 1000;\n\n const subscriptions = subs.map((s) => {\n const expiresInHours = s.expiresAt\n ? Math.round((new Date(s.expiresAt).getTime() - now) / (60 * 60 * 1000))\n : null;\n const needsRenewal =\n s.expiresAt !== null && new Date(s.expiresAt).getTime() - now < RENEWAL_THRESHOLD_MS;\n\n return {\n id: s.id,\n provider: s.provider,\n slug: s.slug,\n status: s.status,\n expiresAt: s.expiresAt,\n expiresInHours,\n needsRenewal,\n lastEventAt: s.lastEventAt,\n eventsProcessed: s.eventsProcessed,\n webhookUrl: s.webhookUrl,\n };\n });\n\n const countByStatus = (status: PushStatus) => subs.filter((s) => s.status === status).length;\n\n const summary = {\n total: subs.length,\n active: countByStatus(\"active\"),\n expiringSoon: subscriptions.filter((s) => s.needsRenewal && s.status === \"active\").length,\n expired: countByStatus(\"expired\"),\n };\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ subscriptions, summary }, null, 2),\n },\n ],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetPushStatus(server: McpServer): void {\n server.registerTool(\n \"get_push_status\",\n {\n title: \"Get Push Status\",\n description: `Get the status of all active push subscriptions (Gmail Pub/Sub, MS Graph, Slack Events).\n\nShows which customers have real-time push enabled, when subscriptions expire, and how many events have been processed.\n\nRBAC: any\n\nArgs:\n slug: (optional) Filter by customer slug\n provider: (optional) Filter by provider — \"gmail\" | \"microsoft-graph\" | \"slack\"\n\nReturns: { subscriptions: [{ id, provider, slug, status, expiresAt, expiresInHours, needsRenewal, lastEventAt, eventsProcessed }], summary: { total, active, expiringSoon, expired } }`,\n inputSchema: z.object({\n slug: z.string().optional().describe(\"Filter by customer slug\"),\n provider: z\n .enum([\"gmail\", \"microsoft-graph\", \"slack\"])\n .optional()\n .describe(\"Filter by provider\"),\n }),\n },\n async ({ slug, provider }) =>\n handleGetPushStatus(\n {\n ...(slug !== undefined ? { slug } : {}),\n ...(provider !== undefined ? { provider } : {}),\n },\n DATA_DIR\n )\n );\n}\n","import { readGraph, getStakeholders, type MissingRole } from \"./graph.js\";\nimport { readHealth } from \"./relationship-health.js\";\nimport type { ExternalSignal } from \"../sync/external-signals.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport type StakeholderRole =\n | \"champion\"\n | \"economic_buyer\"\n | \"blocker\"\n | \"influencer\"\n | \"user\"\n | \"unknown\";\n\nexport interface StakeholderProfile {\n name: string;\n email?: string;\n role: StakeholderRole;\n healthScore: number;\n daysSinceContact: number;\n contactStrength: number;\n riskFlags: string[];\n}\n\nexport interface StakeholderMap {\n slug: string;\n dealName?: string;\n updatedAt: string;\n people: StakeholderProfile[];\n missingRoles: MissingRole[];\n riskAssessment: string;\n recommendation: string;\n}\n\n// ─── Core functions ───────────────────────────────────────────────────────────\n\nexport function buildStakeholderMap(\n dataDir: string,\n slug: string,\n today: string,\n dealName?: string\n): StakeholderMap {\n const graph = readGraph(dataDir, slug);\n const stakeholders = getStakeholders(graph);\n const health = readHealth(dataDir, slug);\n\n const champIds = new Set(stakeholders.champions.map((n) => n.id));\n const buyerIds = new Set(stakeholders.economicBuyers.map((n) => n.id));\n const blockerIds = new Set(stakeholders.blockers.map((n) => n.id));\n\n const healthByContactId = new Map((health?.contacts ?? []).map((c) => [c.contactId, c]));\n\n const personNodes = graph.nodes.filter((n) => n.type === \"person\");\n\n const people: StakeholderProfile[] = personNodes.map((node) => {\n const contactHealth = healthByContactId.get(node.id);\n\n let role: StakeholderRole = \"unknown\";\n if (champIds.has(node.id)) role = \"champion\";\n else if (buyerIds.has(node.id)) role = \"economic_buyer\";\n else if (blockerIds.has(node.id)) role = \"blocker\";\n\n const edges = graph.edges.filter((e) => e.from === node.id);\n const contactStrength =\n edges.length > 0 ? Math.round(Math.max(...edges.map((e) => e.weight)) * 100) / 100 : 0.5;\n\n const profile: StakeholderProfile = {\n name: node.label,\n role,\n healthScore: contactHealth?.score ?? 50,\n daysSinceContact: contactHealth?.daysSinceContact ?? 999,\n contactStrength,\n riskFlags: contactHealth?.riskFlags ?? [],\n };\n if (node.properties.email) {\n profile.email = node.properties.email as string;\n }\n return profile;\n });\n\n const riskAssessment = buildRiskAssessment(people, stakeholders.missingRoles, []);\n\n const recommendation = deriveRecommendation(people, stakeholders.missingRoles);\n\n return {\n slug,\n ...(dealName ? { dealName } : {}),\n updatedAt: new Date(`${today}T00:00:00Z`).toISOString(),\n people,\n missingRoles: stakeholders.missingRoles,\n riskAssessment,\n recommendation,\n };\n}\n\nexport function buildRiskAssessment(\n people: StakeholderProfile[],\n missingRoles: MissingRole[],\n signals: ExternalSignal[] = []\n): string {\n const risks: string[] = [];\n\n if (missingRoles.some((r) => r.role === \"champion\")) {\n risks.push(\"No champion identified — deal lacks an internal advocate.\");\n }\n if (missingRoles.some((r) => r.role === \"economic_buyer\")) {\n risks.push(\"Economic buyer unknown — decision authority not confirmed.\");\n }\n\n const coldPeople = people.filter((p) => p.riskFlags.includes(\"NO_CONTACT_30D\"));\n if (coldPeople.length > 0) {\n risks.push(`Cold contacts (30d+ silence): ${coldPeople.map((p) => p.name).join(\", \")}.`);\n }\n\n const lowHealth = people.filter((p) => p.healthScore < 40);\n if (lowHealth.length > 0) {\n risks.push(`Low health score (<40): ${lowHealth.map((p) => p.name).join(\", \")}.`);\n }\n\n const negativeSignals = signals.filter((s) => s.impact === \"negative\");\n for (const sig of negativeSignals.slice(0, 2)) {\n risks.push(`External signal: ${sig.summary}`);\n }\n\n return risks.length > 0 ? risks.join(\" \") : \"No critical risks detected.\";\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────────────\n\nfunction deriveRecommendation(people: StakeholderProfile[], missingRoles: MissingRole[]): string {\n const critical = missingRoles.find((r) => r.urgency === \"critical\");\n if (critical) return critical.suggestion;\n\n const coldPeople = people.filter((p) => p.riskFlags.includes(\"NO_CONTACT_30D\"));\n if (coldPeople.length > 0) {\n return `Re-engage ${coldPeople.map((p) => p.name).join(\", \")} — no contact in 30+ days.`;\n }\n\n const important = missingRoles.find((r) => r.urgency === \"important\");\n if (important) return important.suggestion;\n\n const avgHealth =\n people.length > 0\n ? Math.round(people.reduce((s, p) => s + p.healthScore, 0) / people.length)\n : 0;\n return `Relationship health avg ${avgHealth}/100. Maintain regular contact cadence.`;\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { buildStakeholderMap } from \"../../core/org-intelligence.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetOrgIntelligence(\n input: { slug: string; dealName?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const today = new Date().toISOString().slice(0, 10);\n const map = buildStakeholderMap(dataDir, input.slug, today, input.dealName);\n return {\n content: [{ type: \"text\", text: JSON.stringify(map, null, 2) }],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetOrgIntelligence(server: McpServer): void {\n server.registerTool(\n \"get_org_intelligence\",\n {\n title: \"Get Org Intelligence\",\n description: `Build a stakeholder map for a customer: champions, economic buyers, blockers, health scores, risk flags, and a prioritised recommendation.\n\nReturns: { slug, updatedAt, people: [{ name, email, role, healthScore, daysSinceContact, contactStrength, riskFlags }], missingRoles, riskAssessment, recommendation }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n dealName: z.string().optional().describe(\"Optional deal name to scope the analysis\"),\n }),\n },\n async ({ slug, dealName }) => handleGetOrgIntelligence(dealName ? { slug, dealName } : { slug })\n );\n}\n","import { buildStakeholderMap, type StakeholderMap } from \"../core/org-intelligence.js\";\nimport { readHealth } from \"../core/relationship-health.js\";\nimport { readPipeline } from \"../fs/pipeline-writer.js\";\nimport { scoreDealForToday } from \"../core/deal-health.js\";\nimport {\n buildSimulationInput,\n runSimulation,\n type SimulationResult,\n} from \"../core/revenue-simulation.js\";\nimport { listPlaybooks, matchPlaybooks, type PlaybookMatch } from \"../core/playbooks.js\";\nimport type { DealHealthScore } from \"../core/deal-health.js\";\nimport type { ContactHealth } from \"../core/relationship-health.js\";\nimport type { MissingRole } from \"../core/graph.js\";\n\n// ─── Types ────────────────────────────────────────────────────────────────────\n\nexport interface DealHealthEntry {\n deal: string;\n stage: string;\n score: number;\n grade: string;\n warnings: string[];\n}\n\nexport interface DealRoomBrief {\n slug: string;\n dealName: string;\n generatedAt: string;\n stakeholders: StakeholderMap;\n relationshipHealth: ContactHealth[];\n dealHealth: DealHealthEntry[];\n revenueSimulation: Pick<SimulationResult, \"p50\" | \"p10\" | \"p90\" | \"expected\" | \"atRiskRevenue\">;\n recommendedPlaybook: PlaybookMatch | null;\n executiveSummary: string;\n topPriorities: string[];\n riskScore: number;\n}\n\n// ─── Orchestrator ─────────────────────────────────────────────────────────────\n\nexport async function buildDealRoom(\n dataDir: string,\n slug: string,\n dealName: string,\n today: string\n): Promise<DealRoomBrief> {\n // Parallel data collection\n const [pipelineDeals, simInput] = await Promise.all([\n readPipeline(dataDir, slug).catch(() => []),\n buildSimulationInput(dataDir, \"quarter\", today).catch(() => ({\n deals: [],\n externalSignals: [],\n iterations: 1000,\n horizon: \"quarter\" as const,\n today,\n })),\n ]);\n\n // Sync reads (fast FS reads)\n const stakeholders = buildStakeholderMap(dataDir, slug, today, dealName);\n const health = readHealth(dataDir, slug);\n const simResult = runSimulation({ ...simInput, iterations: 1000 });\n\n // Deal health scores\n const todayDate = new Date(today);\n const dealHealth: DealHealthEntry[] = pipelineDeals\n .filter((d) => d.stage !== \"won\" && d.stage !== \"lost\")\n .map((deal) => {\n const scored: DealHealthScore = scoreDealForToday(deal, todayDate);\n return {\n deal: deal.name,\n stage: deal.stage,\n score: scored.score,\n grade: scored.grade,\n warnings: scored.warnings,\n };\n });\n\n // Playbook matching — use the first active deal as context\n const firstActiveDeal = pipelineDeals.find((d) => d.stage !== \"won\" && d.stage !== \"lost\");\n let recommendedPlaybook: PlaybookMatch | null = null;\n if (firstActiveDeal) {\n // Prefer champion's contact health for accurate daysSinceContact signal\n const championEmail = stakeholders.people.find((p) => p.role === \"champion\")?.email;\n const champContact = championEmail\n ? health?.contacts.find(\n (c) => c.email === championEmail || c.contactId === `person:${championEmail}`\n )\n : undefined;\n const contactHealth = champContact ?? health?.contacts?.[0];\n const daysSinceContact = contactHealth?.daysSinceContact ?? 999;\n const dealSnapshot = {\n slug,\n name: firstActiveDeal.name,\n stage: firstActiveDeal.stage,\n value: firstActiveDeal.value ?? 0,\n probability: firstActiveDeal.probability ?? 50,\n healthScore: health?.overallHealth ?? 50,\n daysSinceContact,\n championPresent: stakeholders.people.some((p) => p.role === \"champion\"),\n };\n const matches = matchPlaybooks(listPlaybooks(dataDir, slug), dealSnapshot, daysSinceContact);\n recommendedPlaybook = matches[0] ?? null;\n }\n\n const riskScore = computeRiskScore(\n stakeholders.missingRoles,\n dealHealth,\n health?.overallHealth ?? 100\n );\n const topPriorities = buildTopPriorities(stakeholders, dealHealth);\n const executiveSummary = buildExecutiveSummary(\n slug,\n dealName,\n stakeholders,\n health?.overallHealth ?? 100,\n simResult,\n riskScore\n );\n\n return {\n slug,\n dealName,\n generatedAt: new Date().toISOString(),\n stakeholders,\n relationshipHealth: health?.contacts ?? [],\n dealHealth,\n revenueSimulation: {\n p50: simResult.p50,\n p10: simResult.p10,\n p90: simResult.p90,\n expected: simResult.expected,\n atRiskRevenue: simResult.atRiskRevenue,\n },\n recommendedPlaybook,\n executiveSummary,\n topPriorities,\n riskScore,\n };\n}\n\n// ─── Synthesis helpers ────────────────────────────────────────────────────────\n\nfunction computeRiskScore(\n missingRoles: MissingRole[],\n dealHealth: DealHealthEntry[],\n overallHealth: number\n): number {\n let risk = 0;\n\n for (const mr of missingRoles) {\n risk += mr.urgency === \"critical\" ? 25 : 10;\n }\n\n const avgDealScore =\n dealHealth.length > 0 ? dealHealth.reduce((s, d) => s + d.score, 0) / dealHealth.length : 100;\n risk += Math.round((100 - avgDealScore) * 0.3);\n\n risk += Math.round((100 - overallHealth) * 0.2);\n\n return Math.min(100, Math.max(0, risk));\n}\n\nfunction buildTopPriorities(stakeholders: StakeholderMap, dealHealth: DealHealthEntry[]): string[] {\n const priorities: string[] = [];\n\n for (const mr of stakeholders.missingRoles) {\n if (mr.urgency === \"critical\") priorities.push(mr.suggestion);\n }\n\n const coldPeople = stakeholders.people.filter((p) => p.riskFlags.includes(\"NO_CONTACT_30D\"));\n if (coldPeople.length > 0) {\n priorities.push(`Re-engage ${coldPeople.map((p) => p.name).join(\", \")} — silent 30+ days.`);\n }\n\n const atRiskDeals = dealHealth.filter((d) => d.score < 50);\n const showCount = Math.min(3, atRiskDeals.length);\n for (const d of atRiskDeals.slice(0, showCount)) {\n priorities.push(\n `Rescue deal \"${d.deal}\" (health ${d.score}/100): ${d.warnings[0] ?? \"at risk\"}`\n );\n }\n if (atRiskDeals.length > showCount) {\n priorities.push(`+${atRiskDeals.length - showCount} more at-risk deal(s) need attention.`);\n }\n\n for (const mr of stakeholders.missingRoles) {\n if (mr.urgency === \"important\") priorities.push(mr.suggestion);\n }\n\n if (priorities.length === 0) {\n priorities.push(\"Maintain current momentum — schedule next check-in.\");\n }\n\n return priorities;\n}\n\nfunction buildExecutiveSummary(\n slug: string,\n dealName: string,\n stakeholders: StakeholderMap,\n overallHealth: number,\n sim: Pick<SimulationResult, \"p50\" | \"atRiskRevenue\">,\n riskScore: number\n): string {\n const champCount = stakeholders.people.filter((p) => p.role === \"champion\").length;\n const missingCritical = stakeholders.missingRoles.filter((r) => r.urgency === \"critical\").length;\n\n const parts: string[] = [];\n parts.push(\n `${slug}/${dealName}: relationship health ${overallHealth}/100, ${champCount} champion(s) identified.`\n );\n if (sim.p50 > 0) {\n parts.push(`Pipeline P50 forecast: €${(sim.p50 / 1000).toFixed(1)}k.`);\n }\n if (missingCritical > 0) {\n parts.push(\n `Critical gaps: ${missingCritical} key role(s) unidentified — risk score ${riskScore}/100.`\n );\n } else {\n parts.push(`Overall risk score: ${riskScore}/100.`);\n }\n return parts.join(\" \");\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { buildDealRoom } from \"../../agents/deal-room.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleOpenDealRoom(\n input: { slug: string; dealName: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const today = new Date().toISOString().slice(0, 10);\n const brief = await buildDealRoom(dataDir, input.slug, input.dealName, today);\n return {\n content: [{ type: \"text\", text: JSON.stringify(brief, null, 2) }],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerOpenDealRoom(server: McpServer): void {\n server.registerTool(\n \"open_deal_room\",\n {\n title: \"Open Deal Room\",\n description: `Multi-agent deal brief: orchestrates relationship graph, health scores, deal health, revenue simulation, and playbook matching into a unified deal-room brief with executive summary, top priorities, and risk score (0–100).\n\nReturns: { slug, dealName, generatedAt, stakeholders, relationshipHealth, dealHealth, revenueSimulation, recommendedPlaybook, executiveSummary, topPriorities, riskScore }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n dealName: z.string().describe(\"Name of the deal to analyse\"),\n }),\n },\n async ({ slug, dealName }) => handleOpenDealRoom({ slug, dealName })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { buildDailyBriefing } from \"../../core/proactive-agent.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetProactiveBriefing(\n input: { date?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const date = input.date ?? new Date().toISOString().slice(0, 10);\n const briefing = await buildDailyBriefing(dataDir, date);\n return {\n content: [{ type: \"text\", text: JSON.stringify(briefing, null, 2) }],\n };\n } catch (err) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: false, error: (err as Error).message }, null, 2),\n },\n ],\n };\n }\n}\n\nexport function registerGetProactiveBriefing(server: McpServer): void {\n server.registerTool(\n \"get_proactive_briefing\",\n {\n title: \"Get Proactive Briefing\",\n description: `Generate a proactive daily briefing: urgent alerts (relationship decay, deal risk, overdue close dates), pipeline forecast (P50/P90), and a single top-action recommendation.\n\nReturns: { date, generatedAt, urgent: string[], opportunities: string[], forecast: string, topAction: string }`,\n inputSchema: z.object({\n date: z.string().optional().describe(\"ISO date (YYYY-MM-DD). Defaults to today.\"),\n }),\n },\n async ({ date }) => handleGetProactiveBriefing(date ? { date } : {})\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { listTemplates } from \"../../fs/template-store.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleListEmailTemplates(\n input: { category?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const templates = listTemplates(dataDir, input.category ? { category: input.category } : {});\n const summary = templates.map(({ body: _body, ...meta }) => meta);\n return { content: [{ type: \"text\", text: JSON.stringify(summary, null, 2) }] };\n}\n\nexport function registerListEmailTemplates(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"list_email_templates\",\n {\n description:\n \"List available email templates. Optionally filter by category (e.g. 'outreach', 'followup', 'support').\",\n inputSchema: z.object({\n category: z.string().optional().describe(\"Filter by category\"),\n }),\n },\n ({ category }) => handleListEmailTemplates(category ? { category } : {}, dataDir)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { getTemplate } from \"../../fs/template-store.js\";\nimport { extractVariables } from \"../../core/template-engine.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetEmailTemplate(\n input: { id: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const tmpl = getTemplate(dataDir, input.id);\n if (!tmpl) {\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ error: `Template '${input.id}' not found` }) },\n ],\n };\n }\n const allVars = extractVariables(`${tmpl.subject}\\n${tmpl.body}`);\n const unique = [...new Set(allVars)];\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ ...tmpl, detectedVariables: unique }, null, 2),\n },\n ],\n };\n}\n\nexport function registerGetEmailTemplate(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"get_email_template\",\n {\n description:\n \"Get a specific email template by ID, including its body and detected variables.\",\n inputSchema: z.object({\n id: z.string().describe(\"Template ID (e.g. 'enterprise-intro')\"),\n }),\n },\n ({ id }) => handleGetEmailTemplate({ id }, dataDir)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { getTemplate } from \"../../fs/template-store.js\";\nimport { interpolate, buildVariablesFromCustomer } from \"../../core/template-engine.js\";\nimport { readMainFacts } from \"../../fs/customer-dir.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleDraftEmail(\n input: {\n slug: string;\n templateId: string;\n overrides?: Record<string, string>;\n tone?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const tmpl = getTemplate(dataDir, input.templateId);\n if (!tmpl) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ error: `Template '${input.templateId}' not found` }),\n },\n ],\n };\n }\n\n const autoVars = await buildVariablesFromCustomer(dataDir, input.slug);\n const vars = { ...autoVars, ...(input.overrides ?? {}) };\n\n const subject = interpolate(tmpl.subject, vars);\n const interpolatedBody = interpolate(tmpl.body, vars);\n\n // Tone: explicit override wins; otherwise fall back to the customer's tone\n // profile (D8), then the global default.\n let effectiveTone = input.tone;\n if (!effectiveTone) {\n const { resolveTone, toneInstruction } = await import(\"../../core/tone.js\");\n const instr = toneInstruction(resolveTone(dataDir, input.slug));\n if (instr) effectiveTone = instr;\n }\n\n // Optional LLM polish: rewrite the interpolated body in the requested tone.\n // Falls back to the plain interpolation when no ANTHROPIC_API_KEY is set or\n // the call fails — the template-fill behaviour is always preserved.\n let body = interpolatedBody;\n let polished = false;\n if (effectiveTone) {\n try {\n const { callLlm } = await import(\"../../core/llm.js\");\n const refined = await callLlm(\n `Rewrite the following email in a ${effectiveTone} tone. Keep the same language, ` +\n `preserve all names and facts, and do not invent details. ` +\n `Return ONLY the rewritten email body, no preamble.\\n\\n---\\n${interpolatedBody}`\n );\n if (refined && refined.trim()) {\n // EU-AI-Act Art. 50 (D17): label AI-generated content (opt-out).\n const { labelAiContent } = await import(\"../../core/compliance.js\");\n body = labelAiContent(refined.trim());\n polished = true;\n }\n } catch {\n // graceful fallback to the interpolated body\n }\n }\n\n // Try to get email from main_facts for 'to' field\n const facts = await readMainFacts(dataDir, input.slug).catch(() => null);\n const to = facts?.email ?? \"\";\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n subject,\n body,\n to,\n slug: input.slug,\n templateId: input.templateId,\n tone: effectiveTone ?? null,\n polished,\n resolvedVariables: vars,\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerDraftEmail(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"draft_email\",\n {\n description: `Draft a personalized email for a customer using a stored template.\nVariables are auto-filled from the customer's main_facts.md. Override any variable manually.\nOptionally pass a tone (e.g. \"formal\", \"friendly\", \"concise\") to LLM-polish the body —\nfalls back to plain template-fill when no ANTHROPIC_API_KEY is configured.\nReturns: { subject, body, to, tone, polished, resolvedVariables } — does NOT send automatically.`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n templateId: z.string().describe(\"Template ID to use\"),\n overrides: z\n .record(z.string())\n .optional()\n .describe(\"Override any template variable (e.g. {firstName: 'Alice'})\"),\n tone: z\n .string()\n .optional()\n .describe(\"Optional tone to LLM-polish the body (e.g. 'formal', 'friendly', 'concise')\"),\n }),\n },\n ({ slug, templateId, overrides, tone }) =>\n handleDraftEmail(\n {\n slug,\n templateId,\n ...(overrides !== undefined ? { overrides } : {}),\n ...(tone !== undefined ? { tone } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { getSequence, writeEnrollment } from \"../../fs/sequence-store.js\";\nimport { getTemplate } from \"../../fs/template-store.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleEnrollInSequence(\n input: { slug: string; contactEmail: string; sequenceId: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const sequence = getSequence(dataDir, input.sequenceId);\n if (!sequence) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ error: `Sequence '${input.sequenceId}' not found` }),\n },\n ],\n };\n }\n\n // Validate that the first step's template exists\n const firstStep = sequence.steps[0]!;\n const template = getTemplate(dataDir, firstStep.templateId);\n if (!template) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error: `Template '${firstStep.templateId}' for step 0 not found`,\n }),\n },\n ],\n };\n }\n\n const enrollmentId = `enroll_${Date.now()}_${Math.random().toString(16).slice(2, 8)}`;\n const now = new Date().toISOString();\n\n const enrollment = {\n id: enrollmentId,\n sequenceId: input.sequenceId,\n slug: input.slug,\n contactEmail: input.contactEmail,\n enrolledAt: now,\n status: \"active\" as const,\n currentStep: 0,\n stepsCompleted: [] as number[],\n };\n\n await writeEnrollment(dataDir, enrollment);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n enrollmentId,\n sequenceName: sequence.name,\n totalSteps: sequence.steps.length,\n }),\n },\n ],\n };\n}\n\nexport function registerEnrollInSequence(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"enroll_in_sequence\",\n {\n description: `Enroll a contact in an email sequence. Validates that the sequence and its first template exist.\nReturns: { enrollmentId, sequenceName, totalSteps }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n contactEmail: z.string().email().describe(\"Email address of the contact to enroll\"),\n sequenceId: z.string().describe(\"ID of the sequence to enroll in\"),\n }),\n },\n ({ slug, contactEmail, sequenceId }) =>\n handleEnrollInSequence({ slug, contactEmail, sequenceId }, dataDir)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readEnrollments } from \"../../fs/sequence-store.js\";\nimport type { SequenceEnrollment } from \"../../schemas/sequence.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleListSequenceEnrollments(\n input: { slug?: string; status?: \"active\" | \"paused\" | \"completed\" },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n let enrollments = readEnrollments(dataDir);\n\n if (input.slug !== undefined) {\n enrollments = enrollments.filter((e: SequenceEnrollment) => e.slug === input.slug);\n }\n\n if (input.status !== undefined) {\n enrollments = enrollments.filter((e: SequenceEnrollment) => e.status === input.status);\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ enrollments }, null, 2),\n },\n ],\n };\n}\n\nexport function registerListSequenceEnrollments(\n server: McpServer,\n dataDir: string = DATA_DIR\n): void {\n server.registerTool(\n \"list_sequence_enrollments\",\n {\n description: `List email sequence enrollments. Filter by customer slug or status.\nReturns: { enrollments: SequenceEnrollment[] }`,\n inputSchema: z.object({\n slug: z.string().optional().describe(\"Filter by customer slug\"),\n status: z\n .enum([\"active\", \"paused\", \"completed\"])\n .optional()\n .describe(\"Filter by enrollment status\"),\n }),\n },\n ({ slug, status }) =>\n handleListSequenceEnrollments(\n {\n ...(slug !== undefined ? { slug } : {}),\n ...(status !== undefined ? { status } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { updateEnrollment } from \"../../fs/sequence-store.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleUnenrollFromSequence(\n input: { enrollmentId: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const updated = await updateEnrollment(dataDir, input.enrollmentId, { status: \"paused\" });\n\n if (!updated) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n success: false,\n error: `Enrollment '${input.enrollmentId}' not found`,\n }),\n },\n ],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: true }),\n },\n ],\n };\n}\n\nexport function registerUnenrollFromSequence(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"unenroll_from_sequence\",\n {\n description: `Unenroll (pause) a contact from an email sequence. Sets status to \"paused\" (soft delete).\nReturns: { success: boolean }`,\n inputSchema: z.object({\n enrollmentId: z.string().describe(\"ID of the enrollment to pause\"),\n }),\n },\n ({ enrollmentId }) => handleUnenrollFromSequence({ enrollmentId }, dataDir)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { listSequences, readEnrollments } from \"../../fs/sequence-store.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleListSequences(\n _input: Record<string, never>,\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const sequences = listSequences(dataDir);\n const enrollments = readEnrollments(dataDir);\n\n const result = sequences.map((seq) => ({\n id: seq.id,\n name: seq.name,\n stepCount: seq.steps.length,\n enrollmentCount: enrollments.filter((e) => e.sequenceId === seq.id).length,\n }));\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ sequences: result }, null, 2),\n },\n ],\n };\n}\n\nexport function registerListSequences(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"list_sequences\",\n {\n description: `List all email sequences with step count and enrollment count.\nReturns: { sequences: Array<{ id, name, stepCount, enrollmentCount }> }`,\n inputSchema: z.object({}),\n },\n () => handleListSequences({}, dataDir)\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { generateQuote } from \"../../core/quote-generator.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGenerateQuote(\n input: {\n slug: string;\n dealName: string;\n lineItems: Array<{ description: string; quantity: number; unitPrice: number }>;\n vatPercent?: number;\n validUntilDays?: number;\n currency?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n try {\n const quote = await generateQuote(dataDir, input);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n quoteNumber: quote.quoteNumber,\n htmlPath: quote.htmlPath,\n total: quote.total,\n subtotal: quote.subtotal,\n vat: quote.vat,\n vatPercent: quote.vatPercent,\n currency: quote.currency,\n validUntil: quote.validUntil,\n status: quote.status,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: (err as Error).message }) }],\n };\n }\n}\n\nexport function registerGenerateQuote(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"generate_quote\",\n {\n description: `Generate a professional HTML quote/offer for a customer deal.\nCalculates subtotal, VAT, and total. Saves JSON + HTML to .agentic/quotes/.\nReturns: { quoteNumber, htmlPath, total, currency, validUntil }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n dealName: z.string().describe(\"Name of the deal this quote is for\"),\n lineItems: z\n .array(\n z.object({\n description: z.string(),\n quantity: z.number().positive(),\n unitPrice: z.number().min(0),\n })\n )\n .min(1)\n .describe(\"Line items for the quote\"),\n vatPercent: z.number().min(0).max(100).optional().describe(\"VAT percentage (default 19)\"),\n validUntilDays: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Quote validity in days (default 30)\"),\n currency: z.string().optional().describe(\"Currency code (default EUR)\"),\n }),\n },\n ({ slug, dealName, lineItems, vatPercent, validUntilDays, currency }) =>\n handleGenerateQuote(\n {\n slug,\n dealName,\n lineItems,\n ...(vatPercent !== undefined ? { vatPercent } : {}),\n ...(validUntilDays !== undefined ? { validUntilDays } : {}),\n ...(currency !== undefined ? { currency } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readQuote, listQuotes } from \"../../core/quote-generator.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetQuoteStatus(\n input: { quoteNumber?: string; slug?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n if (input.quoteNumber) {\n const quote = readQuote(dataDir, input.quoteNumber);\n if (!quote) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ error: `Quote '${input.quoteNumber}' not found` }),\n },\n ],\n };\n }\n return { content: [{ type: \"text\", text: JSON.stringify(quote, null, 2) }] };\n }\n\n const quotes = listQuotes(dataDir, input.slug);\n return { content: [{ type: \"text\", text: JSON.stringify({ quotes }, null, 2) }] };\n}\n\nexport function registerGetQuoteStatus(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"get_quote_status\",\n {\n description: `Get quote status and details. Filter by quoteNumber (single quote) or slug (all quotes for a customer).\nReturns quote with status: draft | sent | viewed | accepted | declined`,\n inputSchema: z.object({\n quoteNumber: z.string().optional().describe(\"Specific quote number (e.g. Q-2026-001)\"),\n slug: z.string().optional().describe(\"Customer slug to list all quotes for\"),\n }),\n },\n ({ quoteNumber, slug }) =>\n handleGetQuoteStatus(\n {\n ...(quoteNumber !== undefined ? { quoteNumber } : {}),\n ...(slug !== undefined ? { slug } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport yaml from \"js-yaml\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\ninterface CalendlyConfig {\n apiKey?: string;\n defaultEventType?: string;\n autoLogMeetings?: boolean;\n}\n\nfunction loadCalendlyConfig(dataDir: string): CalendlyConfig {\n const p = path.join(dataDir, \".agentic\", \"integrations\", \"calendly.yaml\");\n if (!fs.existsSync(p)) return {};\n try {\n return (yaml.load(fs.readFileSync(p, \"utf-8\") as string) as CalendlyConfig) ?? {};\n } catch {\n return {};\n }\n}\n\nfunction readCustomerFacts(dataDir: string, slug: string): { name?: string; email?: string } {\n const p = path.join(dataDir, \"customers\", slug, \"main_facts.md\");\n if (!fs.existsSync(p)) return {};\n const content = fs.readFileSync(p, \"utf-8\") as string;\n const nameMatch = /^name:\\s*(.+)$/m.exec(content);\n const emailMatch = /^email:\\s*(.+)$/m.exec(content);\n const name = nameMatch?.[1]?.trim();\n const email = emailMatch?.[1]?.trim();\n return {\n ...(name ? { name } : {}),\n ...(email ? { email } : {}),\n };\n}\n\nexport async function handleGetBookingLink(\n input: { slug: string; eventType?: string; prefillName?: boolean },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const config = loadCalendlyConfig(dataDir);\n const apiKey = config.apiKey ?? process.env[\"CALENDLY_API_KEY\"] ?? \"\";\n\n if (!apiKey) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error:\n \"Calendly API key not configured. Set CALENDLY_API_KEY env var or configure .agentic/integrations/calendly.yaml\",\n }),\n },\n ],\n };\n }\n\n const eventTypeSlug = input.eventType ?? config.defaultEventType ?? \"30min\";\n\n try {\n const { getSchedulingLink, listEventTypes } = await import(\"../../sync/calendly.js\");\n const prefill = input.prefillName ? readCustomerFacts(dataDir, input.slug) : undefined;\n const bookingUrl = await getSchedulingLink(apiKey, eventTypeSlug, prefill);\n\n const eventTypes = await listEventTypes(apiKey);\n const eventType = eventTypes.find(\n (et) =>\n et.slug === eventTypeSlug || et.name.toLowerCase().includes(eventTypeSlug.toLowerCase())\n );\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n bookingUrl,\n eventType: eventType?.name ?? eventTypeSlug,\n duration: eventType?.duration ?? 30,\n slug: input.slug,\n },\n null,\n 2\n ),\n },\n ],\n };\n } catch (err) {\n return {\n content: [{ type: \"text\", text: JSON.stringify({ error: (err as Error).message }) }],\n };\n }\n}\n\nexport function registerGetBookingLink(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"get_booking_link\",\n {\n description: `Get a Calendly booking link for a customer. Optionally pre-fills the customer's name/email.\nRequires CALENDLY_API_KEY env var or .agentic/integrations/calendly.yaml config.\nReturns: { bookingUrl, eventType, duration }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n eventType: z\n .string()\n .optional()\n .describe(\n \"Calendly event type slug (e.g. '30min', '60min'). Uses default if not specified.\"\n ),\n prefillName: z\n .boolean()\n .optional()\n .describe(\"Pre-fill customer name and email in the booking link\"),\n }),\n },\n ({ slug, eventType, prefillName }) =>\n handleGetBookingLink(\n {\n slug,\n ...(eventType !== undefined ? { eventType } : {}),\n ...(prefillName !== undefined ? { prefillName } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readTickets, upsertTicket, nextTicketId } from \"../../fs/ticket-writer.js\";\nimport { calcSlaDue, loadSlaRules } from \"../../core/sla-engine.js\";\nimport type { Ticket } from \"../../schemas/ticket.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleCreateTicket(\n input: {\n slug: string;\n title: string;\n description?: string;\n priority?: Ticket[\"priority\"];\n assignee?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const today = new Date().toISOString().slice(0, 10);\n const rules = loadSlaRules(dataDir);\n const priority = input.priority ?? \"normal\";\n const existing = await readTickets(dataDir, input.slug);\n const id = nextTicketId(existing);\n const slaDue = calcSlaDue(today, priority, rules);\n\n const ticket: Ticket = {\n id,\n title: input.title,\n status: \"open\",\n priority,\n ...(input.assignee ? { assignee: input.assignee } : {}),\n created: today,\n slaDue,\n ...(input.description ? { description: input.description } : {}),\n };\n\n await upsertTicket(dataDir, input.slug, ticket);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify({ ticket }, null, 2) }],\n };\n}\n\nexport function registerCreateTicket(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"create_ticket\",\n {\n description: `Create a support ticket for a customer. Auto-calculates SLA due date based on priority.\nReturns: { ticket } with id T-NNN, status=open, slaDue`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n title: z.string().min(1).describe(\"Ticket title\"),\n description: z.string().optional().describe(\"Detailed description\"),\n priority: z\n .enum([\"urgent\", \"high\", \"normal\", \"low\"])\n .optional()\n .describe(\"Priority (default: normal)\"),\n assignee: z.string().optional().describe(\"Assignee name or email\"),\n }),\n },\n ({ slug, title, description, priority, assignee }) =>\n handleCreateTicket(\n {\n slug,\n title,\n ...(description !== undefined ? { description } : {}),\n ...(priority !== undefined ? { priority } : {}),\n ...(assignee !== undefined ? { assignee } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readTickets, upsertTicket } from \"../../fs/ticket-writer.js\";\nimport type { Ticket } from \"../../schemas/ticket.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleUpdateTicket(\n input: { slug: string; ticketId: string; status?: Ticket[\"status\"]; assignee?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const tickets = await readTickets(dataDir, input.slug);\n const ticket = tickets.find((t) => t.id === input.ticketId);\n\n if (!ticket) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error: `Ticket '${input.ticketId}' not found for customer '${input.slug}'`,\n }),\n },\n ],\n };\n }\n\n const today = new Date().toISOString().slice(0, 10);\n const updated: Ticket = {\n ...ticket,\n ...(input.status ? { status: input.status } : {}),\n ...(input.assignee !== undefined ? { assignee: input.assignee } : {}),\n ...(input.status === \"resolved\" && !ticket.resolved ? { resolved: today } : {}),\n };\n\n await upsertTicket(dataDir, input.slug, updated);\n\n return {\n content: [{ type: \"text\", text: JSON.stringify({ ticket: updated }, null, 2) }],\n };\n}\n\nexport function registerUpdateTicket(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"update_ticket\",\n {\n description: `Update a ticket's status or assignee. Setting status=resolved auto-sets resolved date.\nReturns: { ticket }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n ticketId: z.string().describe(\"Ticket ID (e.g. T-001)\"),\n status: z.enum([\"open\", \"in-progress\", \"waiting\", \"resolved\", \"closed\"]).optional(),\n assignee: z.string().optional().describe(\"New assignee\"),\n }),\n },\n ({ slug, ticketId, status, assignee }) =>\n handleUpdateTicket(\n {\n slug,\n ticketId,\n ...(status !== undefined ? { status } : {}),\n ...(assignee !== undefined ? { assignee } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { listAllTickets } from \"../../fs/ticket-writer.js\";\nimport type { Ticket } from \"../../schemas/ticket.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleListTickets(\n input: {\n slug?: string;\n status?: Ticket[\"status\"];\n priority?: Ticket[\"priority\"];\n assignee?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const results = await listAllTickets(dataDir, {\n ...(input.slug !== undefined ? { slug: input.slug } : {}),\n ...(input.status !== undefined ? { status: input.status } : {}),\n ...(input.priority !== undefined ? { priority: input.priority } : {}),\n ...(input.assignee !== undefined ? { assignee: input.assignee } : {}),\n });\n\n return {\n content: [{ type: \"text\", text: JSON.stringify({ tickets: results }, null, 2) }],\n };\n}\n\nexport function registerListTickets(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"list_tickets\",\n {\n description: `List support tickets. Filter by customer, status, priority, or assignee. Sorted by priority then date.\nReturns: { tickets: Array<{ slug, ticket }> }`,\n inputSchema: z.object({\n slug: z.string().optional().describe(\"Filter by customer slug\"),\n status: z.enum([\"open\", \"in-progress\", \"waiting\", \"resolved\", \"closed\"]).optional(),\n priority: z.enum([\"urgent\", \"high\", \"normal\", \"low\"]).optional(),\n assignee: z.string().optional().describe(\"Filter by assignee\"),\n }),\n },\n ({ slug, status, priority, assignee }) =>\n handleListTickets(\n {\n ...(slug !== undefined ? { slug } : {}),\n ...(status !== undefined ? { status } : {}),\n ...(priority !== undefined ? { priority } : {}),\n ...(assignee !== undefined ? { assignee } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readTickets, upsertTicket } from \"../../fs/ticket-writer.js\";\nimport { appendInteraction } from \"../../fs/interactions-writer.js\";\nimport type { Ticket } from \"../../schemas/ticket.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleCloseTicket(\n input: { slug: string; ticketId: string; resolution?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const tickets = await readTickets(dataDir, input.slug);\n const ticket = tickets.find((t) => t.id === input.ticketId);\n\n if (!ticket) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n error: `Ticket '${input.ticketId}' not found for '${input.slug}'`,\n }),\n },\n ],\n };\n }\n\n const today = new Date().toISOString().slice(0, 10);\n const updated: Ticket = {\n ...ticket,\n status: \"closed\",\n resolved: ticket.resolved ?? today,\n };\n\n await upsertTicket(dataDir, input.slug, updated);\n\n if (input.resolution) {\n await appendInteraction(dataDir, input.slug, {\n date: today,\n type: \"Note\",\n with: input.slug,\n summary: `Ticket ${input.ticketId} closed: ${input.resolution}`,\n nextSteps: [],\n sourceRef: `ticket://${input.ticketId}/close`,\n synced: new Date().toISOString(),\n });\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify({ ticket: updated }, null, 2) }],\n };\n}\n\nexport function registerCloseTicket(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"close_ticket\",\n {\n description: `Close a support ticket. Optionally logs the resolution as an interaction.\nReturns: { ticket } with status=closed`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n ticketId: z.string().describe(\"Ticket ID (e.g. T-001)\"),\n resolution: z.string().optional().describe(\"Resolution notes (logged as interaction)\"),\n }),\n },\n ({ slug, ticketId, resolution }) =>\n handleCloseTicket(\n {\n slug,\n ticketId,\n ...(resolution !== undefined ? { resolution } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport {\n getSurvey,\n generateSurveyToken,\n buildSurveyEmail,\n savePendingSurvey,\n} from \"../../core/survey-engine.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleSendNpsSurvey(\n input: { slug: string; contactEmail: string; surveyId: string; serverUrl?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const survey = getSurvey(dataDir, input.surveyId);\n if (!survey) {\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ error: `Survey '${input.surveyId}' not found` }) },\n ],\n };\n }\n\n const serverUrl = input.serverUrl ?? process.env[\"DXCRM_SERVER_URL\"] ?? \"http://localhost:3456\";\n const token = generateSurveyToken(input.slug, input.contactEmail, input.surveyId);\n const email = buildSurveyEmail(survey, serverUrl, token);\n\n await savePendingSurvey(dataDir, input.surveyId, input.slug, input.contactEmail, token);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n token,\n subject: email.subject,\n body: email.body,\n surveyUrl: `${serverUrl}/survey/respond?token=${token}`,\n note: \"Email draft ready. Use draft_email or Gmail to send.\",\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerSendNpsSurvey(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"send_nps_survey\",\n {\n description: `Generate an NPS/CSAT survey email for a customer contact. Returns subject, HTML body, and a token-based response URL.\nDoes NOT send automatically — returns draft for review.\nReturns: { token, subject, body, surveyUrl }`,\n inputSchema: z.object({\n slug: z.string().describe(\"Customer slug\"),\n contactEmail: z.string().email().describe(\"Contact email to send survey to\"),\n surveyId: z.string().describe(\"Survey definition ID from .agentic/surveys/\"),\n serverUrl: z\n .string()\n .optional()\n .describe(\n \"Server URL for response links (default: DXCRM_SERVER_URL env var or localhost:3456)\"\n ),\n }),\n },\n ({ slug, contactEmail, surveyId, serverUrl }) =>\n handleSendNpsSurvey(\n {\n slug,\n contactEmail,\n surveyId,\n ...(serverUrl !== undefined ? { serverUrl } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { loadSurveyResponses, calcNpsScore } from \"../../core/survey-engine.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetSurveyResults(\n input: { surveyId: string; slug?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const responses = loadSurveyResponses(dataDir, input.surveyId, input.slug);\n const nps = calcNpsScore(responses);\n const promoters = responses.filter((r) => r.score >= 9).length;\n const passives = responses.filter((r) => r.score >= 7 && r.score <= 8).length;\n const detractors = responses.filter((r) => r.score <= 6).length;\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n surveyId: input.surveyId,\n ...(input.slug ? { slug: input.slug } : {}),\n totalResponses: responses.length,\n npsScore: nps,\n promoters,\n passives,\n detractors,\n responses: responses.map((r) => ({\n slug: r.slug,\n email: r.contactEmail,\n score: r.score,\n ...(r.comment ? { comment: r.comment } : {}),\n respondedAt: r.respondedAt,\n })),\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerGetSurveyResults(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"get_survey_results\",\n {\n description: `Get NPS/CSAT survey results with score breakdown. Calculates Net Promoter Score.\nReturns: { npsScore, totalResponses, promoters, passives, detractors, responses[] }`,\n inputSchema: z.object({\n surveyId: z.string().describe(\"Survey ID\"),\n slug: z.string().optional().describe(\"Filter results to a specific customer\"),\n }),\n },\n ({ surveyId, slug }) =>\n handleGetSurveyResults(\n {\n surveyId,\n ...(slug !== undefined ? { slug } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { searchKbSimple, getKbMetaForExport } from \"../../fs/knowledge-base.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleSearchKnowledgeBase(\n input: { query: string; category?: string; publicOnly?: boolean; limit?: number },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const results = searchKbSimple(dataDir, input.query, {\n ...(input.publicOnly ? { publicOnly: true } : {}),\n });\n\n const filtered = input.category ? results.filter((a) => a.category === input.category) : results;\n const limited = filtered.slice(0, input.limit ?? 10);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n query: input.query,\n count: limited.length,\n articles: limited.map((a) => ({\n ...getKbMetaForExport(a),\n excerpt: a.body.slice(0, 300).trim(),\n })),\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerSearchKnowledgeBase(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"search_knowledge_base\",\n {\n description: `Search the knowledge base for articles. Text search on title, body, and tags.\nReturns: { count, articles[] } with excerpts`,\n inputSchema: z.object({\n query: z.string().describe(\"Search query\"),\n category: z\n .string()\n .optional()\n .describe(\"Filter by category (e.g. 'troubleshooting', 'howto')\"),\n publicOnly: z.boolean().optional().describe(\"Only return public articles\"),\n limit: z.number().int().positive().optional().describe(\"Max results (default 10)\"),\n }),\n },\n ({ query, category, publicOnly, limit }) =>\n handleSearchKnowledgeBase(\n {\n query,\n ...(category !== undefined ? { category } : {}),\n ...(publicOnly !== undefined ? { publicOnly } : {}),\n ...(limit !== undefined ? { limit } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { writeKbArticle, getKbArticle } from \"../../fs/knowledge-base.js\";\nimport type { KbArticle } from \"../../schemas/kb-article.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleCreateKbArticle(\n input: {\n id: string;\n title: string;\n body: string;\n category?: string;\n tags?: string[];\n public?: boolean;\n sourceTicketId?: string;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const existing = getKbArticle(dataDir, input.id);\n if (existing) {\n return {\n content: [\n { type: \"text\", text: JSON.stringify({ error: `Article '${input.id}' already exists` }) },\n ],\n };\n }\n\n const now = new Date().toISOString();\n const article: KbArticle = {\n id: input.id,\n title: input.title,\n body: input.body,\n category: input.category ?? \"general\",\n tags: input.tags ?? [],\n public: input.public ?? false,\n createdAt: now,\n updatedAt: now,\n ...(input.sourceTicketId ? { sourceTicketId: input.sourceTicketId } : {}),\n };\n\n writeKbArticle(dataDir, article);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n id: article.id,\n title: article.title,\n category: article.category,\n path: `.agentic/knowledge-base/${article.category}/${article.id}.md`,\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerCreateKbArticle(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"create_kb_article\",\n {\n description: `Create a new knowledge base article. Articles are stored as Markdown files in .agentic/knowledge-base/.\nReturns: { id, title, category, path }`,\n inputSchema: z.object({\n id: z.string().min(1).describe(\"Article ID (slug, e.g. 'troubleshoot-api-timeout')\"),\n title: z.string().min(1).describe(\"Article title\"),\n body: z.string().min(1).describe(\"Article body in Markdown\"),\n category: z.string().optional().describe(\"Category (default: 'general')\"),\n tags: z.array(z.string()).optional().describe(\"Tags for search\"),\n public: z\n .boolean()\n .optional()\n .describe(\"Make article publicly accessible (default: false)\"),\n sourceTicketId: z.string().optional().describe(\"Ticket ID this article was created from\"),\n }),\n },\n ({ id, title, body, category, tags, public: pub, sourceTicketId }) =>\n handleCreateKbArticle(\n {\n id,\n title,\n body,\n ...(category !== undefined ? { category } : {}),\n ...(tags !== undefined ? { tags } : {}),\n ...(pub !== undefined ? { public: pub } : {}),\n ...(sourceTicketId !== undefined ? { sourceTicketId } : {}),\n },\n dataDir\n )\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport { runBackup } from \"../../commands/backup.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleBackupNow(\n input: { remote?: string; note?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const zipPath = path.join(\n dataDir,\n `dxcrm-backup-${new Date().toISOString().replace(/[:.]/g, \"-\").slice(0, 19)}.zip`\n );\n\n const manifest = await runBackup(zipPath, dataDir, {\n ...(input.remote ? { remote: input.remote } : {}),\n }).catch(() => null);\n\n if (!manifest) {\n return {\n content: [{ type: \"text\", text: \"Backup failed. Check disk space and permissions.\" }],\n };\n }\n\n const sizeMb = fs.existsSync(zipPath)\n ? (fs.statSync(zipPath).size / 1024 / 1024).toFixed(1)\n : \"?\";\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n path: zipPath,\n createdAt: manifest.createdAt,\n customerCount: manifest.customerCount,\n fileCount: manifest.fileCount,\n sizeMb: `${sizeMb} MB`,\n directories: manifest.directories,\n verified: true,\n ...(input.remote ? { uploadedTo: input.remote } : {}),\n ...(input.note ? { note: input.note } : {}),\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerBackupNow(server: McpServer): void {\n server.registerTool(\n \"backup_now\",\n {\n description:\n \"Trigger an immediate backup of all CRM data (customers/ + .agentic/). Returns backup path, size, and integrity status. Use before risky operations or on user request.\",\n inputSchema: z.object({\n remote: z\n .string()\n .optional()\n .describe(\n \"Upload destination: s3://bucket/path/, rsync://user@host:/path/, or local directory\"\n ),\n note: z.string().optional().describe(\"Optional note to tag this backup\"),\n }),\n },\n ({ remote, note }) =>\n handleBackupNow({\n ...(remote !== undefined ? { remote } : {}),\n ...(note !== undefined ? { note } : {}),\n })\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readBackupLog, listBackupsInDir } from \"../../commands/backup.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleListBackups(\n input: { limit: number },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const logEntries = readBackupLog(dataDir);\n const fileEntries = listBackupsInDir(dataDir);\n\n // Prefer log entries (have richer metadata), fallback to file scan\n const entries = logEntries.length > 0 ? logEntries : fileEntries;\n const limited = entries.slice(0, input.limit);\n\n if (limited.length === 0) {\n return {\n content: [{ type: \"text\", text: \"No backups found. Run backup_now to create one.\" }],\n };\n }\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n count: limited.length,\n totalAvailable: entries.length,\n backups: limited.map((e) => ({\n filename: e.filename,\n createdAt: e.createdAt,\n sizeMb: e.sizeBytes > 0 ? `${(e.sizeBytes / 1024 / 1024).toFixed(1)} MB` : \"unknown\",\n verified: e.verified,\n encrypted: e.encrypted,\n customerCount: e.customerCount,\n fileCount: e.fileCount,\n })),\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerListBackups(server: McpServer): void {\n server.registerTool(\n \"list_backups\",\n {\n description:\n \"List available CRM backups with metadata (date, size, verification status, customer count). Shows log-tracked backups first, falls back to directory scan.\",\n inputSchema: z.object({\n limit: z\n .number()\n .int()\n .min(1)\n .max(50)\n .default(10)\n .describe(\"Maximum number of backups to return\"),\n }),\n },\n (input) => handleListBackups(input)\n );\n}\n","import path from \"path\";\nimport fs from \"fs\";\nimport { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { getGmailAuth } from \"../../core/oauth-store.js\";\nimport { updateSlugSyncState } from \"../../fs/sync-state.js\";\n\nconst DATA_DIR = process.cwd();\n\nexport async function handleTriggerSync(\n input: { slug?: string; since?: string },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const auth = getGmailAuth();\n if (!auth) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({\n success: false,\n error: \"Gmail auth not configured. Run `dxcrm sync gmail --init` first.\",\n }),\n },\n ],\n };\n }\n\n const customersDir = path.join(dataDir, \"customers\");\n if (!fs.existsSync(customersDir)) {\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify({ success: true, synced: 0, skipped: 0, customers: [] }),\n },\n ],\n };\n }\n\n const slugs = input.slug\n ? [input.slug]\n : fs.readdirSync(customersDir).filter((s) => {\n try {\n return fs.statSync(path.join(customersDir, s)).isDirectory();\n } catch {\n return false;\n }\n });\n\n const sinceDate = input.since\n ? new Date(input.since)\n : new Date(Date.now() - 24 * 60 * 60 * 1000);\n const results: Array<{ slug: string; synced: number; skipped: number }> = [];\n const errors: string[] = [];\n\n for (const slug of slugs) {\n const sourcesPath = path.join(customersDir, slug, \"sources.json\");\n if (!fs.existsSync(sourcesPath)) continue;\n try {\n const sources = JSON.parse(fs.readFileSync(sourcesPath, \"utf-8\") as string) as {\n gmail?: { query?: string; enabled?: boolean };\n };\n if (!sources.gmail?.enabled || !sources.gmail.query) continue;\n\n const { syncGmail } = await import(\"../../sync/gmail-sync.js\");\n const result = await syncGmail({\n slug,\n dataDir,\n auth,\n query: sources.gmail.query,\n since: sinceDate,\n });\n updateSlugSyncState(dataDir, slug, { lastGmailSync: new Date().toISOString() });\n results.push({ slug, ...result });\n } catch (err) {\n errors.push(`${slug}: ${(err as Error).message}`);\n }\n }\n\n const total = results.reduce(\n (acc, r) => ({ synced: acc.synced + r.synced, skipped: acc.skipped + r.skipped }),\n { synced: 0, skipped: 0 }\n );\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n success: true,\n ...total,\n customers: results,\n errors,\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerTriggerSync(server: McpServer): void {\n server.registerTool(\n \"trigger_sync\",\n {\n title: \"Trigger Sync\",\n description: `Immediately trigger a Gmail sync for one or all customers.\nUse when you need fresh email data before answering a question.\nThe background daemon syncs every 30 minutes automatically — this forces an immediate sync.\n\nArgs:\n slug: Customer slug to sync (leave empty to sync all customers)\n since: ISO date string — only fetch emails since this date (default: last 24 hours)\n\nReturns: { success: boolean, synced: number, skipped: number, customers: [...], errors: [...] }`,\n inputSchema: z.object({\n slug: z.string().optional().describe(\"Customer slug to sync (empty = all customers)\"),\n since: z\n .string()\n .optional()\n .describe(\"Sync emails since this ISO date (default: last 24h)\"),\n }),\n },\n async ({ slug, since }) => {\n const input: { slug?: string; since?: string } = {};\n if (slug !== undefined) input.slug = slug;\n if (since !== undefined) input.since = since;\n return handleTriggerSync(input);\n }\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { readAuditLog, filterAuditLog } from \"../../fs/audit-log.js\";\n\nconst DATA_DIR = process.cwd();\n\nexport async function handleGetAuditLog(\n input: { slug?: string; actor?: string; limit?: number },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const entries = readAuditLog(dataDir);\n const filterOpts: { slug?: string; actor?: string; limit?: number } = {\n limit: input.limit ?? 50,\n };\n if (input.slug !== undefined) filterOpts.slug = input.slug;\n if (input.actor !== undefined) filterOpts.actor = input.actor;\n const filtered = filterAuditLog(entries, filterOpts);\n\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n total: entries.length,\n returned: filtered.length,\n entries: filtered,\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerGetAuditLog(server: McpServer): void {\n server.registerTool(\n \"get_audit_log\",\n {\n title: \"Get Audit Log\",\n description: `Read the CRM audit log — all write operations with timestamp, actor, tool, and customer.\nUse to answer \"what changed recently?\", \"what did alice do?\", or \"show me all actions for acme-corp\".\n\nArgs:\n slug: Filter by customer slug (optional)\n actor: Filter by actor name (optional)\n limit: Max entries to return (default: 50, most recent)\n\nReturns: { total: number, returned: number, entries: [{timestamp, actor, tool, slug, summary}] }`,\n inputSchema: z.object({\n slug: z.string().optional().describe(\"Filter by customer slug\"),\n actor: z.string().optional().describe(\"Filter by actor (user or system)\"),\n limit: z.number().int().min(1).max(500).optional().describe(\"Max entries (default 50)\"),\n }),\n },\n async ({ slug, actor, limit }) => {\n const input: { slug?: string; actor?: string; limit?: number } = {};\n if (slug !== undefined) input.slug = slug;\n if (actor !== undefined) input.actor = actor;\n if (limit !== undefined) input.limit = limit;\n return handleGetAuditLog(input);\n }\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { queryLogs, summarizeLogs, type LogLevel } from \"../../core/logger.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetLogs(\n input: {\n level?: LogLevel;\n component?: string;\n since?: string;\n contains?: string;\n limit?: number;\n summary?: boolean;\n },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const query = {\n ...(input.level !== undefined ? { level: input.level } : {}),\n ...(input.component !== undefined ? { component: input.component } : {}),\n ...(input.since !== undefined ? { since: input.since } : {}),\n ...(input.contains !== undefined ? { contains: input.contains } : {}),\n limit: input.limit ?? 100,\n };\n\n const payload = input.summary\n ? summarizeLogs(dataDir, query)\n : (() => {\n const entries = queryLogs(dataDir, query);\n return { returned: entries.length, entries };\n })();\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n };\n}\n\nexport function registerGetLogs(server: McpServer): void {\n server.registerTool(\n \"get_logs\",\n {\n title: \"Get Logs\",\n description: `Read and analyze the structured application log (.agentic/logs.ndjson).\nUse to answer \"what went wrong recently?\", \"show errors from gmail sync\", or \"summarize today's activity\".\n\nArgs:\n level: Minimum level to include — debug | info | warn | error (optional)\n component: Filter by component, e.g. \"gmail-sync\", \"lancedb\" (optional)\n since: ISO timestamp; only entries at or after it (optional)\n contains: Case-insensitive substring of the message (optional)\n limit: Max entries to return (default 100, most recent)\n summary: When true, return aggregated counts (by level + component) and recent errors instead of raw entries\n\nReturns (entries): { returned: number, entries: [{ts, level, component, message, context?}] }\nReturns (summary): { total, byLevel, byComponent, firstTs, lastTs, recentErrors }`,\n inputSchema: z.object({\n level: z.enum([\"debug\", \"info\", \"warn\", \"error\"]).optional().describe(\"Minimum level\"),\n component: z.string().optional().describe(\"Filter by component\"),\n since: z.string().optional().describe(\"ISO timestamp lower bound\"),\n contains: z.string().optional().describe(\"Message substring filter\"),\n limit: z.number().int().min(1).max(1000).optional().describe(\"Max entries (default 100)\"),\n summary: z.boolean().optional().describe(\"Return aggregated summary instead of entries\"),\n }),\n },\n async ({ level, component, since, contains, limit, summary }) => {\n const input: Parameters<typeof handleGetLogs>[0] = {};\n if (level !== undefined) input.level = level;\n if (component !== undefined) input.component = component;\n if (since !== undefined) input.since = since;\n if (contains !== undefined) input.contains = contains;\n if (limit !== undefined) input.limit = limit;\n if (summary !== undefined) input.summary = summary;\n return handleGetLogs(input);\n }\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { runDiagnostics } from \"../../core/doctor.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nexport async function handleGetDiagnostics(\n input: { fix?: boolean },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n let cleaned = 0;\n if (input.fix) {\n const { cleanupTempFiles } = await import(\"../../core/doctor.js\");\n cleaned = cleanupTempFiles(dataDir).length;\n }\n const report = await runDiagnostics(dataDir);\n return {\n content: [\n {\n type: \"text\",\n text: JSON.stringify(\n {\n ok: report.ok,\n ...(input.fix ? { tempFilesRemoved: cleaned } : {}),\n checks: report.checks,\n },\n null,\n 2\n ),\n },\n ],\n };\n}\n\nexport function registerGetDiagnostics(server: McpServer): void {\n server.registerTool(\n \"get_diagnostics\",\n {\n title: \"Get Diagnostics\",\n description: `Run a self-diagnostic health check of the CRM workspace.\nVerifies the data directory, validates every customer's profile, detects orphaned\natomic-write temp files (a crash signature), surfaces recent log errors, and checks\nbackup freshness. Use to answer \"is everything healthy?\" before/after bulk operations.\n\nArgs:\n fix: When true, first remove orphaned temp files (the only safely auto-fixable issue)\n\nReturns: { ok: boolean, tempFilesRemoved?: number, checks: [{ name, status: \"ok\"|\"warn\"|\"fail\", detail }] }`,\n inputSchema: z.object({\n fix: z.boolean().optional().describe(\"Clean orphaned temp files before reporting\"),\n }),\n },\n async ({ fix }) => handleGetDiagnostics(fix !== undefined ? { fix } : {})\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { diffAgainstNow } from \"../../core/snapshots.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nfunction daysAgoIso(days: number): string {\n return new Date(Date.now() - days * 86_400_000).toISOString().slice(0, 10);\n}\n\nexport async function handleGetPipelineChanges(\n input: { since?: string; days?: number },\n dataDir: string = DATA_DIR\n): Promise<{ content: Array<{ type: \"text\"; text: string }> }> {\n const since = input.since ?? daysAgoIso(input.days ?? 7);\n const diff = diffAgainstNow(dataDir, since);\n const payload = diff\n ? diff\n : {\n error: `No pipeline snapshot at or before ${since}. Snapshots accrue daily via the daemon.`,\n };\n return { content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }] };\n}\n\nexport function registerGetPipelineChanges(server: McpServer): void {\n server.registerTool(\n \"get_pipeline_changes\",\n {\n title: \"Get Pipeline Changes\",\n description: `Pipeline time-travel: what changed in the pipeline since a baseline date.\nCompares the live pipeline against the most recent daily snapshot at/before the\nbaseline. Answers \"what moved since last week?\", \"what did we win/lose?\".\n\nArgs:\n since: Baseline date YYYY-MM-DD (optional)\n days: Look back this many days instead of a date (default 7)\n\nReturns: { fromId, toId, added[], removed[], advanced[{from,to}], won[], lost[],\nvalueChanged[{from,to}], openValueBefore, openValueAfter, openValueDelta }\nor { error } when no baseline snapshot exists yet.`,\n inputSchema: z.object({\n since: z.string().optional().describe(\"Baseline date YYYY-MM-DD\"),\n days: z\n .number()\n .int()\n .min(1)\n .max(365)\n .optional()\n .describe(\"Look-back window in days (default 7)\"),\n }),\n },\n async ({ since, days }) => {\n const input: { since?: string; days?: number } = {};\n if (since !== undefined) input.since = since;\n if (days !== undefined) input.days = days;\n return handleGetPipelineChanges(input);\n }\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n\nexport interface CrmPrompt {\n name: string;\n title: string;\n description: string;\n build: (args: { slug: string }) => string;\n}\n\n/**\n * CRM playbook prompts exposed via MCP `prompts/list` + `prompts/get`.\n * Each renders an actionable, tool-referencing instruction for the host LLM —\n * the agent-native equivalent of a Salesforce \"playbook\".\n */\nexport const CRM_PROMPTS: CrmPrompt[] = [\n {\n name: \"deal_risk_review\",\n title: \"Assess deal risk\",\n description:\n \"Evaluate the health and risk of a customer's open deals and recommend next steps.\",\n build: ({ slug }) =>\n `Assess the deal risk for customer \"${slug}\".\\n` +\n `1. Call open_deal_room({ slug: \"${slug}\" }) for a consolidated brief, or get_customer_context + get_deal_health.\\n` +\n `2. Identify stalled deals, approaching close dates, and silent champions (get_relationship_health).\\n` +\n `3. Summarise the top risks and recommend concrete next actions. Do not invent data — cite what you read.`,\n },\n {\n name: \"draft_follow_up\",\n title: \"Draft a follow-up email\",\n description:\n \"Draft a personalized follow-up email for a customer based on recent interactions.\",\n build: ({ slug }) =>\n `Draft a follow-up email for customer \"${slug}\".\\n` +\n `1. Read recent context with get_customer_context({ slug: \"${slug}\" }).\\n` +\n `2. Use draft_email({ slug: \"${slug}\", templateId, tone: \"friendly\" }) with an appropriate template.\\n` +\n `3. Reference the latest interaction concretely; keep it concise. Return the draft for review — do not send.`,\n },\n {\n name: \"account_brief\",\n title: \"Create an account brief\",\n description: \"Produce a concise executive brief for a customer account.\",\n build: ({ slug }) =>\n `Create an executive account brief for \"${slug}\".\\n` +\n `1. get_customer_context({ slug: \"${slug}\" }) and get_org_intelligence({ slug: \"${slug}\" }).\\n` +\n `2. Summarise: who the stakeholders are (champions/buyers/blockers), open pipeline, health, and risks.\\n` +\n `3. End with the single most important next action.`,\n },\n {\n name: \"pipeline_summary\",\n title: \"Summarize the pipeline\",\n description: \"Summarize pipeline and forecast, optionally focused on one customer.\",\n build: ({ slug }) =>\n `Summarize the sales pipeline (focus customer: \"${slug}\").\\n` +\n `1. get_pipeline_forecast() for the weighted total and per-stage breakdown.\\n` +\n `2. simulate_revenue() for P10/P50/P90 if a probabilistic view helps.\\n` +\n `3. Highlight at-risk revenue and the deals that most move the forecast.`,\n },\n];\n\nexport function registerPrompts(server: McpServer): void {\n for (const prompt of CRM_PROMPTS) {\n server.registerPrompt(\n prompt.name,\n {\n title: prompt.title,\n description: prompt.description,\n argsSchema: { slug: z.string().describe(\"Customer slug\") },\n },\n ({ slug }) => ({\n messages: [{ role: \"user\", content: { type: \"text\", text: prompt.build({ slug }) } }],\n })\n );\n }\n}\n","import { type McpServer, ResourceTemplate } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { listCustomerSlugs } from \"../fs/customer-dir.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\n/**\n * Read-only MCP Resources for CRM entities. Complements the action Tools:\n * agents can `resources/read` a customer briefing, pipeline or timeline by URI\n * instead of calling a tool.\n */\nexport function registerResources(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerResource(\n \"customers\",\n \"crm://customers\",\n {\n title: \"Customers\",\n description: \"List of all customer slugs\",\n mimeType: \"application/json\",\n },\n (uri) => ({\n contents: [\n {\n uri: uri.href,\n mimeType: \"application/json\",\n text: JSON.stringify(listCustomerSlugs(dataDir), null, 2),\n },\n ],\n })\n );\n\n server.registerResource(\n \"customer\",\n new ResourceTemplate(\"crm://customer/{slug}\", { list: undefined }),\n {\n title: \"Customer context\",\n description: \"LLM-ready briefing (main facts, recent interactions, pipeline) for a customer\",\n mimeType: \"text/markdown\",\n },\n async (uri, variables) => {\n const { buildContext } = await import(\"../core/context-builder.js\");\n const text = await buildContext(dataDir, String(variables[\"slug\"]));\n return { contents: [{ uri: uri.href, mimeType: \"text/markdown\", text }] };\n }\n );\n\n server.registerResource(\n \"pipeline\",\n new ResourceTemplate(\"crm://pipeline/{slug}\", { list: undefined }),\n {\n title: \"Pipeline\",\n description: \"Open and closed deals for a customer\",\n mimeType: \"application/json\",\n },\n async (uri, variables) => {\n const { readPipeline } = await import(\"../fs/pipeline-writer.js\");\n const deals = await readPipeline(dataDir, String(variables[\"slug\"]));\n return {\n contents: [\n { uri: uri.href, mimeType: \"application/json\", text: JSON.stringify(deals, null, 2) },\n ],\n };\n }\n );\n\n server.registerResource(\n \"timeline\",\n new ResourceTemplate(\"crm://timeline/{slug}\", { list: undefined }),\n {\n title: \"Interaction timeline\",\n description: \"Newest-first interaction history for a customer\",\n mimeType: \"text/markdown\",\n },\n async (uri, variables) => {\n const { readInteractions } = await import(\"../fs/interactions-writer.js\");\n const text = await readInteractions(dataDir, String(variables[\"slug\"]));\n return { contents: [{ uri: uri.href, mimeType: \"text/markdown\", text }] };\n }\n );\n}\n","import { type McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { enforceRbac } from \"../../core/rbac.js\";\nimport {\n defineCustomObject,\n loadCustomObjects,\n createRecord,\n listRecords,\n} from \"../../core/custom-objects.js\";\nimport type { CustomFieldType } from \"../../core/custom-fields.js\";\n\nconst DATA_DIR = process.env[\"DXCRM_DATA_DIR\"] ?? process.cwd();\n\nconst FIELD_TYPES = [\"text\", \"number\", \"boolean\", \"date\", \"select\"] as const;\n\nfunction json(data: unknown): { content: Array<{ type: \"text\"; text: string }> } {\n return { content: [{ type: \"text\", text: JSON.stringify(data, null, 2) }] };\n}\n\nexport function handleDefineCustomObject(\n input: {\n name: string;\n label?: string;\n fields: Array<{ name: string; type: CustomFieldType; label?: string; options?: string[] }>;\n },\n dataDir: string = DATA_DIR\n): { content: Array<{ type: \"text\"; text: string }> } {\n enforceRbac(dataDir, \"define_custom_object\");\n const objects = defineCustomObject(dataDir, {\n name: input.name,\n ...(input.label ? { label: input.label } : {}),\n fields: input.fields,\n });\n return json({ defined: input.name, objectCount: objects.length });\n}\n\nexport function handleCreateRecord(\n input: { object: string; values: Record<string, string> },\n dataDir: string = DATA_DIR\n): { content: Array<{ type: \"text\"; text: string }> } {\n enforceRbac(dataDir, \"create_record\");\n const res = createRecord(dataDir, input.object, input.values);\n if (!res.ok) return json({ error: (res.errors ?? []).join(\"; \") });\n // Fire-and-forget outbound webhook (event-driven; failures queue for replay).\n void import(\"../../core/webhooks.js\").then(({ emitEvent }) =>\n emitEvent(dataDir, \"record.created\", { object: input.object, record: res.record })\n );\n return json({ record: res.record });\n}\n\nexport function handleListRecords(\n input: { object: string },\n dataDir: string = DATA_DIR\n): { content: Array<{ type: \"text\"; text: string }> } {\n return json({ object: input.object, records: listRecords(dataDir, input.object) });\n}\n\nexport function handleListCustomObjects(dataDir: string = DATA_DIR): {\n content: Array<{ type: \"text\"; text: string }>;\n} {\n return json({ objects: loadCustomObjects(dataDir) });\n}\n\nexport function registerCustomObjectTools(server: McpServer, dataDir: string = DATA_DIR): void {\n server.registerTool(\n \"define_custom_object\",\n {\n description:\n \"Define a custom object (runtime entity type) with typed fields — no code migration. admin only.\",\n inputSchema: z.object({\n name: z.string().describe(\"Object name (e.g. contract)\"),\n label: z.string().optional(),\n fields: z\n .array(\n z.object({\n name: z.string(),\n type: z.enum(FIELD_TYPES),\n label: z.string().optional(),\n options: z.array(z.string()).optional(),\n })\n )\n .describe(\"Field definitions\"),\n }),\n },\n ({ name, label, fields }) =>\n handleDefineCustomObject(\n { name, ...(label ? { label } : {}), fields: fields as never },\n dataDir\n )\n );\n\n server.registerTool(\n \"create_record\",\n {\n description:\n \"Create a record of a custom object. Values are validated against the schema. rep+.\",\n inputSchema: z.object({\n object: z.string().describe(\"Custom object name\"),\n values: z.record(z.string()).describe(\"Field values (key=value)\"),\n }),\n },\n ({ object, values }) => handleCreateRecord({ object, values }, dataDir)\n );\n\n server.registerTool(\n \"list_records\",\n {\n description: \"List records of a custom object.\",\n inputSchema: z.object({ object: z.string().describe(\"Custom object name\") }),\n },\n ({ object }) => handleListRecords({ object }, dataDir)\n );\n\n server.registerTool(\n \"list_custom_objects\",\n {\n description: \"List all defined custom objects and their field schemas.\",\n inputSchema: z.object({}),\n },\n () => handleListCustomObjects(dataDir)\n );\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { initOAuthFromDisk } from \"../core/oauth-store.js\";\nimport {\n decodeGmailPubSubPayload,\n verifyGmailPubSubSignature,\n handleGmailPushEvent,\n} from \"../sync/gmail-webhook-handler.js\";\nimport {\n handleMicrosoftValidationRequest,\n verifyMicrosoftGraphSignature,\n handleMicrosoftPushEvent,\n type MicrosoftGraphNotification,\n} from \"../sync/microsoft-webhook-handler.js\";\nimport {\n verifySlackSignature,\n handleSlackUrlVerification,\n handleSlackPushEvent,\n type SlackEvent,\n} from \"../sync/slack-webhook-handler.js\";\nimport { registerGetCapabilities } from \"./tools/get-capabilities.js\";\nimport { registerGetActiveSession } from \"./tools/get-active-session.js\";\nimport { registerGetCustomerContext } from \"./tools/get-customer-context.js\";\nimport { registerSearchCustomerKnowledge } from \"./tools/search-customer-knowledge.js\";\nimport { registerListCustomers } from \"./tools/list-customers.js\";\nimport { registerLogInteraction } from \"./tools/log-interaction.js\";\nimport { registerUpdateDeal } from \"./tools/update-deal.js\";\nimport { registerExportCustomer } from \"./tools/export-customer.js\";\nimport { registerUpdateCustomerFacts } from \"./tools/update-customer-facts.js\";\nimport { registerGetDealHealth } from \"./tools/get-deal-health.js\";\nimport { registerGetPipelineForecast } from \"./tools/get-pipeline-forecast.js\";\nimport { registerSummarizeMeeting } from \"./tools/summarize-meeting.js\";\nimport { registerGetPipelineStages } from \"./tools/get-pipeline-stages.js\";\nimport { registerGetMarketIntelligence } from \"./tools/get-market-intelligence.js\";\nimport { registerGetRelationshipGraph } from \"./tools/get-relationship-graph.js\";\nimport { registerGetRelationshipHealth } from \"./tools/get-relationship-health.js\";\nimport { registerRunDealAgent } from \"./tools/run-deal-agent.js\";\nimport { registerApproveAgentAction } from \"./tools/approve-agent-action.js\";\nimport { registerSimulateRevenue } from \"./tools/simulate-revenue.js\";\nimport { registerGetPlaybook } from \"./tools/get-playbook.js\";\nimport { registerCreatePlaybook } from \"./tools/create-playbook.js\";\nimport { registerListPlaybooks } from \"./tools/list-playbooks.js\";\nimport { registerDistillPlaybook } from \"./tools/distill-playbook.js\";\nimport { registerPursueGoal } from \"./tools/pursue-goal.js\";\nimport { registerGetGoalStatus } from \"./tools/get-goal-status.js\";\nimport { registerRegisterPushSubscription } from \"./tools/register-push-subscription.js\";\nimport { registerGetPushStatus } from \"./tools/get-push-status.js\";\nimport { registerGetOrgIntelligence } from \"./tools/get-org-intelligence.js\";\nimport { registerOpenDealRoom } from \"./tools/open-deal-room.js\";\nimport { registerGetProactiveBriefing } from \"./tools/get-proactive-briefing.js\";\nimport { registerListEmailTemplates } from \"./tools/list-email-templates.js\";\nimport { registerGetEmailTemplate } from \"./tools/get-email-template.js\";\nimport { registerDraftEmail } from \"./tools/draft-email.js\";\nimport { registerEnrollInSequence } from \"./tools/enroll-in-sequence.js\";\nimport { registerListSequenceEnrollments } from \"./tools/list-sequence-enrollments.js\";\nimport { registerUnenrollFromSequence } from \"./tools/unenroll-from-sequence.js\";\nimport { registerListSequences } from \"./tools/list-sequences.js\";\nimport { registerGenerateQuote } from \"./tools/generate-quote.js\";\nimport { registerGetQuoteStatus } from \"./tools/get-quote-status.js\";\nimport { registerGetBookingLink } from \"./tools/get-booking-link.js\";\nimport { registerCreateTicket } from \"./tools/create-ticket.js\";\nimport { registerUpdateTicket } from \"./tools/update-ticket.js\";\nimport { registerListTickets } from \"./tools/list-tickets.js\";\nimport { registerCloseTicket } from \"./tools/close-ticket.js\";\nimport { registerSendNpsSurvey } from \"./tools/send-nps-survey.js\";\nimport { registerGetSurveyResults } from \"./tools/get-survey-results.js\";\nimport { registerSearchKnowledgeBase } from \"./tools/search-knowledge-base.js\";\nimport { registerCreateKbArticle } from \"./tools/create-kb-article.js\";\nimport { registerBackupNow } from \"./tools/backup-now.js\";\nimport { registerListBackups } from \"./tools/list-backups.js\";\nimport { registerTriggerSync } from \"./tools/trigger-sync.js\";\nimport { registerGetAuditLog } from \"./tools/get-audit-log.js\";\nimport { registerGetLogs } from \"./tools/get-logs.js\";\nimport { registerGetDiagnostics } from \"./tools/get-diagnostics.js\";\nimport { registerGetPipelineChanges } from \"./tools/get-pipeline-changes.js\";\nimport { logger } from \"../core/logger.js\";\nimport { registerPrompts } from \"./prompts.js\";\nimport { registerResources } from \"./resources.js\";\nimport { registerCustomObjectTools } from \"./tools/custom-objects.js\";\nimport {\n isAuthRequired,\n verifyBearer,\n protectedResourceMetadata,\n wwwAuthenticateHeader,\n} from \"./auth.js\";\n\nexport function surveyThankYouPage(score: number, comment?: string): string {\n const emoji = score >= 9 ? \"🎉\" : score >= 7 ? \"🙂\" : \"🙏\";\n return `<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Thank you</title>\n<style>body{font-family:sans-serif;max-width:480px;margin:80px auto;text-align:center;padding:0 20px}\nh1{font-size:2.5em;margin-bottom:.3em}p{color:#555;font-size:1.1em}</style></head>\n<body><h1>${emoji}</h1><h2>Thank you for your feedback!</h2>\n<p>You rated us <strong>${score}/10</strong>.${comment ? `<br>Your comment: <em>\"${String(comment).slice(0, 200).replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\")}\"</em>` : \"\"}</p>\n<p style=\"margin-top:40px;color:#aaa;font-size:.85em\">Powered by DatasynxOpenCRM</p>\n</body></html>`;\n}\n\nexport function createMcpServer(): McpServer {\n const server = new McpServer({\n name: \"datasynx-opencrm\",\n version: \"0.1.0\",\n });\n\n // Register all 59 tools\n // IMPORTANT: Use server.registerTool() — server.tool() is deprecated in v2\n registerGetCapabilities(server);\n registerGetActiveSession(server);\n registerGetCustomerContext(server);\n registerSearchCustomerKnowledge(server);\n registerListCustomers(server);\n registerLogInteraction(server);\n registerUpdateDeal(server);\n registerExportCustomer(server);\n registerUpdateCustomerFacts(server);\n registerGetDealHealth(server);\n registerGetPipelineForecast(server);\n registerSummarizeMeeting(server);\n registerGetPipelineStages(server);\n registerGetMarketIntelligence(server);\n registerGetRelationshipGraph(server);\n registerGetRelationshipHealth(server);\n registerRunDealAgent(server);\n registerApproveAgentAction(server);\n registerSimulateRevenue(server);\n registerGetPlaybook(server);\n registerCreatePlaybook(server);\n registerListPlaybooks(server);\n registerDistillPlaybook(server);\n registerPursueGoal(server);\n registerGetGoalStatus(server);\n registerRegisterPushSubscription(server);\n registerGetPushStatus(server);\n registerGetOrgIntelligence(server);\n registerOpenDealRoom(server);\n registerGetProactiveBriefing(server);\n registerListEmailTemplates(server);\n registerGetEmailTemplate(server);\n registerDraftEmail(server);\n registerEnrollInSequence(server);\n registerListSequenceEnrollments(server);\n registerUnenrollFromSequence(server);\n registerListSequences(server);\n registerGenerateQuote(server);\n registerGetQuoteStatus(server);\n registerGetBookingLink(server);\n registerCreateTicket(server);\n registerUpdateTicket(server);\n registerListTickets(server);\n registerCloseTicket(server);\n registerSendNpsSurvey(server);\n registerGetSurveyResults(server);\n registerSearchKnowledgeBase(server);\n registerCreateKbArticle(server);\n registerBackupNow(server);\n registerListBackups(server);\n registerTriggerSync(server);\n registerGetAuditLog(server);\n registerGetLogs(server);\n registerGetDiagnostics(server);\n registerGetPipelineChanges(server);\n registerCustomObjectTools(server);\n\n // MCP Prompts (playbooks) + Resources (read-only entities) — agent-native primitives\n registerPrompts(server);\n registerResources(server);\n\n return server;\n}\n\nexport async function startStdio(): Promise<void> {\n await initOAuthFromDisk(process.cwd());\n const server = createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n // IMPORTANT: stdout would corrupt the MCP stdio protocol — the logger writes\n // only to stderr (and the persistent ledger), never stdout.\n logger.info(\"mcp-server\", \"running via stdio\");\n}\n\nexport async function startHttp(port = 3847): Promise<void> {\n await initOAuthFromDisk(process.cwd());\n const { default: express } = await import(\"express\");\n const app = express();\n app.use(express.json());\n\n const server = createMcpServer();\n const dataDir = process.cwd();\n\n // RFC 9728 — OAuth 2.0 Protected Resource Metadata\n app.get(\"/.well-known/oauth-protected-resource\", (req, res) => {\n const base = `${req.protocol}://${req.get(\"host\") ?? \"localhost\"}`;\n res.json(protectedResourceMetadata(`${base}/mcp`));\n });\n\n app.post(\"/mcp\", async (req, res) => {\n // OAuth 2.1 resource-server gate: require a valid bearer token when auth is\n // enabled (a token is provisioned or DXCRM_MCP_AUTH=required).\n if (isAuthRequired(dataDir)) {\n const auth = verifyBearer(req.headers[\"authorization\"], dataDir);\n if (!auth.ok) {\n const base = `${req.protocol}://${req.get(\"host\") ?? \"localhost\"}`;\n res\n .status(401)\n .set(\n \"WWW-Authenticate\",\n wwwAuthenticateHeader(`${base}/.well-known/oauth-protected-resource`)\n )\n .json({ error: \"unauthorized\" });\n return;\n }\n // Attach the token's actor for RBAC enforcement on this request.\n if (auth.actor) process.env[\"DXCRM_ACTOR\"] = auth.actor;\n }\n\n const transport = new StreamableHTTPServerTransport({ enableJsonResponse: true });\n // Ensure onclose is always a function (required by Transport interface with exactOptionalPropertyTypes)\n transport.onclose = () => {\n /* no-op */\n };\n res.on(\"close\", () => {\n void transport.close();\n });\n await server.connect(transport as unknown as Transport);\n await transport.handleRequest(req, res, req.body as Record<string, unknown>);\n });\n\n app.get(\"/health\", (_req, res) => {\n res.json({ status: \"ok\", server: \"datasynx-opencrm\", version: \"0.1.0\" });\n });\n\n app.get(\"/sessions\", async (_req, res) => {\n try {\n const { readAllSessions } = await import(\"../commands/session.js\");\n const sessions = readAllSessions(dataDir);\n res.json({ sessions });\n } catch {\n res.json({ sessions: [] });\n }\n });\n\n // Gmail Pub/Sub webhook\n app.post(\"/webhooks/gmail\", async (req, res) => {\n const token = process.env[\"GMAIL_PUBSUB_TOKEN\"] ?? \"\";\n if (!verifyGmailPubSubSignature(req.headers[\"authorization\"] as string | undefined, token)) {\n res.status(401).json({ error: \"unauthorized\" });\n return;\n }\n const payload = decodeGmailPubSubPayload(req.body);\n if (!payload) {\n res.status(400).json({ error: \"invalid_payload\" });\n return;\n }\n const result = await handleGmailPushEvent(dataDir, payload, \"\").catch(() => ({\n processed: 0,\n slug: null,\n }));\n res.json({ ok: true, processed: result.processed });\n });\n\n // Microsoft Graph webhook\n app.all(\"/webhooks/microsoft\", async (req, res) => {\n const validation = handleMicrosoftValidationRequest(req.query as Record<string, string>);\n if (validation.isValidation) {\n res.setHeader(\"content-type\", \"text/plain\");\n res.status(200).send(validation.token);\n return;\n }\n const clientState = process.env[\"MS_GRAPH_CLIENT_STATE\"] ?? \"\";\n const body = req.body as { value?: MicrosoftGraphNotification[] };\n if (!verifyMicrosoftGraphSignature(body, clientState)) {\n res.status(401).json({ error: \"unauthorized\" });\n return;\n }\n const result = await handleMicrosoftPushEvent(dataDir, body.value ?? [], \"\").catch(() => ({\n processed: 0,\n skipped: 0,\n }));\n res.json({ ok: true, ...result });\n });\n\n // Slack Events API webhook\n app.post(\"/webhooks/slack\", express.text({ type: \"*/*\" }), async (req, res) => {\n const rawBody = req.body as string;\n const signingSecret = process.env[\"SLACK_SIGNING_SECRET\"] ?? \"\";\n if (\n !verifySlackSignature(\n rawBody,\n req.headers as { \"x-slack-signature\"?: string; \"x-slack-request-timestamp\"?: string },\n signingSecret\n )\n ) {\n res.status(401).json({ error: \"unauthorized\" });\n return;\n }\n let parsed: { type?: string; challenge?: string; event?: SlackEvent; team_id?: string };\n try {\n parsed = JSON.parse(rawBody) as typeof parsed;\n } catch {\n res.status(400).json({ error: \"invalid_json\" });\n return;\n }\n const verification = handleSlackUrlVerification(parsed);\n if (verification.isVerification) {\n res.json({ challenge: verification.challenge });\n return;\n }\n if (!parsed.event) {\n res.json({ ok: true, processed: 0 });\n return;\n }\n const botToken = process.env[\"SLACK_BOT_TOKEN\"] ?? \"\";\n const result = await handleSlackPushEvent(dataDir, parsed.event, botToken, {\n ...(parsed.team_id !== undefined ? { teamId: parsed.team_id } : {}),\n }).catch(() => ({ processed: 0, skipped: 1 }));\n res.json({ ok: true, ...result });\n });\n\n // NPS/CSAT survey response endpoint — linked from survey emails\n // GET /survey/respond?token=<t>&score=<0-10> → record score + thank-you page\n // GET /survey/respond?token=<t>&comment=true → show comment form\n // POST /survey/respond → record comment + thank-you page\n app.get(\"/survey/respond\", async (req, res) => {\n const { token, score, comment } = req.query as Record<string, string | undefined>;\n if (!token) {\n res.status(400).send(\"<h2>Invalid survey link.</h2>\");\n return;\n }\n\n if (comment === \"true\") {\n res.setHeader(\"content-type\", \"text/html\");\n res.send(`<!DOCTYPE html><html><head><meta charset=\"utf-8\"><title>Survey Comment</title>\n<style>body{font-family:sans-serif;max-width:520px;margin:60px auto;padding:0 20px}\ntextarea{width:100%;padding:10px;font-size:1em;border:1px solid #ccc;border-radius:4px}\ninput[type=number]{width:80px;padding:8px;font-size:1em}\nbutton{margin-top:12px;padding:12px 28px;background:#1a1a2e;color:#fff;border:none;border-radius:4px;font-size:1em;cursor:pointer}</style></head>\n<body><h2>Leave a comment</h2>\n<form method=\"POST\" action=\"/survey/respond\">\n<input type=\"hidden\" name=\"token\" value=\"${String(token).replace(/&/g, \"&amp;\").replace(/\"/g, \"&quot;\").replace(/</g, \"&lt;\")}\">\n<label>Your score (0–10):<br><input type=\"number\" name=\"score\" min=\"0\" max=\"10\" required></label><br><br>\n<label>Comment (optional):<br><textarea name=\"comment\" rows=\"5\" placeholder=\"What can we improve?\"></textarea></label><br>\n<button type=\"submit\">Submit</button>\n</form></body></html>`);\n return;\n }\n\n const numScore = score !== undefined ? parseInt(score, 10) : NaN;\n if (isNaN(numScore) || numScore < 0 || numScore > 10) {\n res.status(400).send(\"<h2>Invalid score. Please use the link from your email.</h2>\");\n return;\n }\n\n const { recordSurveyResponse } = await import(\"../core/survey-engine.js\");\n await recordSurveyResponse(dataDir, token, numScore).catch(() => null);\n res.setHeader(\"content-type\", \"text/html\");\n res.send(surveyThankYouPage(numScore));\n });\n\n app.post(\"/survey/respond\", express.urlencoded({ extended: false }), async (req, res) => {\n const { token, score, comment: commentText } = req.body as Record<string, string | undefined>;\n if (!token) {\n res.status(400).send(\"<h2>Invalid survey link.</h2>\");\n return;\n }\n const numScore = score !== undefined ? parseInt(score, 10) : NaN;\n if (isNaN(numScore) || numScore < 0 || numScore > 10) {\n res\n .status(400)\n .send(\"<h2>Invalid score. Please go back and enter a number between 0 and 10.</h2>\");\n return;\n }\n const { recordSurveyResponse } = await import(\"../core/survey-engine.js\");\n await recordSurveyResponse(dataDir, token, numScore, commentText || undefined).catch(\n () => null\n );\n res.setHeader(\"content-type\", \"text/html\");\n res.send(surveyThankYouPage(numScore, commentText));\n });\n\n app.listen(port, () => {\n logger.info(\"mcp-server\", \"running over http\", { url: `http://0.0.0.0:${port}/mcp` });\n });\n}\n\n// Entry point when run directly (e.g. node dist/mcp.js)\nconst mode = process.env[\"DXCRM_MCP_MODE\"] ?? \"stdio\";\nif (mode === \"http\") {\n const port = parseInt(process.env[\"DXCRM_MCP_PORT\"] ?? \"3847\", 10);\n startHttp(port).catch((err: unknown) => {\n logger.error(\"mcp-server\", \"fatal error\", { error: (err as Error).message });\n process.exit(1);\n });\n} else {\n startStdio().catch((err: unknown) => {\n logger.error(\"mcp-server\", \"fatal error\", { error: (err as Error).message });\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,IAAI,QAA6B;AAEjC,eAAsB,kBAAkB,SAAmC;CACzE,MAAM,WAAW,KAAK,KAAK,SAAS,YAAY,wBAAwB;CACxE,MAAM,YAAY,KAAK,KAAK,SAAS,YAAY,kBAAkB;CAEnE,IAAI,CAAC,GAAG,WAAW,QAAQ,KAAK,CAAC,GAAG,WAAW,SAAS,GACtD,OAAO;CAGT,IAAI;EACF,MAAM,EAAE,cAAc,aAAa,MAAM,OAAO;EAChD,QAAQ,MAAM,SAAS,UAAU,SAAS;EAC1C,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,eAAoC;CAClD,OAAO;AACT;;;ACfA,SAAgB,8BACd,MACA,qBACS;CACT,MAAM,gBAAgB,KAAK,SAAS,CAAC;CACrC,IAAI,cAAc,WAAW,GAAG,OAAO,wBAAwB;CAC/D,OAAO,cAAc,OAAO,MAAM,EAAE,gBAAgB,mBAAmB;AACzE;AAOA,SAAgB,iCACd,aACkB;CAClB,MAAM,QAAQ,YAAY;CAC1B,IAAI,OAAO,OAAO;EAAE,cAAc;EAAM;CAAM;CAC9C,OAAO,EAAE,cAAc,MAAM;AAC/B;AAuBA,SAAS,uBACP,MACA,gBACyB;CACzB,OACE,KAAK,MACF,MACC,EAAE,aAAa,qBACf,EAAE,WAAW,YACb,EAAE,aAAa,4BAA4B,cAC/C,KAAK;AAET;AAEA,eAAsB,yBACpB,SACA,eACA,aACA,UAAsC,CAAC,GACU;CACjD,MAAM,OAAO,MAAM,kBAAkB,OAAO;CAC5C,MAAM,EAAE,gBAAgB,sBAAsB,sBAAsB;CAEpE,IAAI,YAAY;CAChB,IAAI,UAAU;CACd,IAAI,eAAe;CAEnB,KAAK,MAAM,gBAAgB,eAAe;EACxC,MAAM,MAAM,uBAAuB,MAAM,aAAa,cAAc;EACpE,IAAI,CAAC,KAAK;GACR;GACA;EACF;EAEA,MAAM,YAAY,aAAa,cAAc;EAC7C,IAAI,CAAC,aAAa,CAAC,gBAAgB;GACjC;GACA;EACF;EAEA,IAAI;GACF,MAAM,UAAU,MAAM,eAAe,aAAa,SAAS;GAC3D,IAAI,CAAC,SAAS;IACZ;IACA;GACF;GAEA,MAAM,OAAO,QAAQ,MAAM,cAAc,WAAW;GACpD,MAAM,YAAY,qBAAqB,QAAQ;GAE/C,MAAM,oBAAoB,SAAS,IAAI,MAAM;IAC3C,MAAM,QAAQ,mBACV,IAAI,KAAK,QAAQ,gBAAgB,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,qBAC5D,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;IACxC,MAAM;IACN,WAAW;IACX,MAAM;IACN,SAAS,QAAQ,WAAW;IAC5B,SAAS,QAAQ,eAAe;IAChC,WAAW,CAAC;IACZ;IACA,yBAAQ,IAAI,KAAK,GAAE,YAAY;GACjC,CAAC;GAED;GACA,eAAe;GAGf,MAAM,MAAM,KAAK,WAAW,MAAM,EAAE,OAAO,IAAI,EAAE;GACjD,IAAI,QAAQ,IACV,KAAK,OAAO;IACV,GAAG,KAAK;IACR,iBAAiB,KAAK,KAAM,kBAAkB;IAC9C,8BAAa,IAAI,KAAK,GAAE,YAAY;GACtC;EAEJ,QAAQ;GACN;EACF;CACF;CAEA,IAAI,cACF,MAAM,mBAAmB,SAAS,IAAI;CAGxC,OAAO;EAAE;EAAW;CAAQ;AAC9B;;;AC9HA,SAAgB,qBACd,MACA,SACA,eACS;CACT,MAAM,MAAM,QAAQ;CACpB,MAAM,KAAK,QAAQ;CACnB,IAAI,CAAC,OAAO,CAAC,IAAI,OAAO;CAGxB,MAAM,QAAQ,OAAO,EAAE;CACvB,IAAI,KAAK,IAAI,KAAK,IAAI,IAAI,MAAO,KAAK,IAAI,KAAQ,OAAO;CAEzD,MAAM,UAAU,MAAM,GAAG,GAAG;CAC5B,MAAM,WAAW,QAAQ,OAAO,WAAW,UAAU,aAAa,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;CAEhG,IAAI;EACF,MAAM,SAAS,OAAO,KAAK,GAAG;EAC9B,MAAM,SAAS,OAAO,KAAK,QAAQ;EACnC,IAAI,OAAO,WAAW,OAAO,QAAQ,OAAO;EAC5C,OAAO,OAAO,gBAAgB,QAAQ,MAAM;CAC9C,QAAQ;EACN,OAAO;CACT;AACF;AAMA,SAAgB,2BAA2B,MAGZ;CAC7B,IAAI,KAAK,SAAS,oBAChB,OAAO;EAAE,gBAAgB;EAAM,WAAW,KAAK,aAAa;CAAG;CAEjE,OAAO,EAAE,gBAAgB,MAAM;AACjC;AAcA,SAAS,uBACP,MACA,QACyB;CACzB,OACE,KAAK,MACF,MACC,EAAE,aAAa,WACf,EAAE,WAAW,aACZ,CAAC,UAAU,EAAE,aAAa,gBAAgB,OAC/C,KAAK;AAET;AAEA,eAAsB,qBACpB,SACA,OACA,UACA,UAAkC,CAAC,GACc;CAEjD,IAAI,MAAM,SAAS,WAAW,OAAO;EAAE,WAAW;EAAG,SAAS;CAAE;CAGhE,IAAI,MAAM,QAAQ,OAAO;EAAE,WAAW;EAAG,SAAS;CAAE;CAGpD,IAAI,CAAC,MAAM,MAAM,KAAK,GAAG,OAAO;EAAE,WAAW;EAAG,SAAS;CAAE;CAE3D,MAAM,OAAO,MAAM,kBAAkB,OAAO;CAC5C,MAAM,MAAM,uBAAuB,MAAM,QAAQ,MAAM;CACvD,IAAI,CAAC,KAAK,OAAO;EAAE,WAAW;EAAG,SAAS;CAAE;CAE5C,MAAM,EAAE,sBAAsB,mBAAmB,oBAAoB;CAErE,IAAI,aAAa,MAAM,QAAQ;CAC/B,IAAI,mBAAmB,MAAM,MAC3B,IAAI;EACF,MAAM,OAAO,MAAM,gBAAgB,UAAU,MAAM,IAAI;EACvD,aAAa,KAAK,QAAQ,KAAK,SAAS,MAAM;CAChD,QAAQ,CAER;CAGF,MAAM,KAAK,MAAM,sBACb,IAAI,KAAK,OAAO,MAAM,EAAE,IAAI,GAAI,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,qBAC3D,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CACxC,MAAM,YAAY,mBAAmB,MAAM,WAAW,KAAK,MAAM,MAAM,MAAM,KAAK,IAAI;CAEtF,IAAI;EACF,MAAM,oBAAoB,SAAS,IAAI,MAAM;GAC3C,MAAM;GACN,MAAM;GACN,WAAW;GACX,MAAM;GACN,SAAS,oBAAoB,MAAM,WAAW;GAC9C,SAAS,MAAM,KAAK,MAAM,GAAG,GAAG;GAChC,WAAW,CAAC;GACZ;GACA,yBAAQ,IAAI,KAAK,GAAE,YAAY;EACjC,CAAC;EAGD,MAAM,MAAM,KAAK,WAAW,MAAM,EAAE,OAAO,IAAI,EAAE;EACjD,IAAI,QAAQ,IAAI;GACd,KAAK,OAAO;IACV,GAAG,KAAK;IACR,iBAAiB,KAAK,KAAM,kBAAkB;IAC9C,8BAAa,IAAI,KAAK,GAAE,YAAY;GACtC;GACA,MAAM,mBAAmB,SAAS,IAAI;EACxC;EAEA,OAAO;GAAE,WAAW;GAAG,SAAS;EAAE;CACpC,QAAQ;EACN,OAAO;GAAE,WAAW;GAAG,SAAS;EAAE;CACpC;AACF;;;AC3IA,eAAsB,wBAEnB;CACD,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM;CAAkB,CAAC,EACrD;AACF;AAEA,SAAgB,wBAAwB,QAAyB;CAC/D,OAAO,aACL,oBACA;EACE,OAAO;EACP,aACE;EAEF,aAAa,EAAE,OAAO,CAAC,CAAC;CAC1B,GACA,YAAY,sBAAsB,CACpC;AACF;;;ACZA,eAAsB,yBAEnB;CACD,MAAM,UAAU,WAAW;CAE3B,MAAM,SAA8B,UAChC;EACE,YAAY;EACZ,cAAc,QAAQ;EACtB,cAAc,QAAQ;EACtB,WAAW,QAAQ;EACnB,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;CAChE,IACA,EAAE,YAAY,MAAM;CAExB,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC;CAAE,CAAC,EACnE;AACF;AAEA,SAAgB,yBAAyB,QAAyB;CAChE,OAAO,aACL,sBACA;EACE,OAAO;EACP,aACE;EAEF,aAAa,EAAE,OAAO,CAAC,CAAC;CAC1B,GACA,YAAY,uBAAuB,CACrC;AACF;;;AClCA,MAAMA,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,SAAS,mBAAmB,SAAiB,MAAoB;CAC/D,MAAM,OAAO,aAAa;CAC1B,IAAI,CAAC,MAAM;CAEX,MAAM,WAAW,iBAAiB,SAAS,IAAI;CAC/C,MAAM,+BAAe,IAAI,KAAK,KAAK,IAAI,IAAI,OAAU,GAAI;CACzD,IAAI,YAAY,YAAY,cAAc;CAE1C,MAAM,cAAc,KAAK,KAAK,SAAS,aAAa,MAAM,cAAc;CACxE,IAAI,CAAC,GAAG,WAAW,WAAW,GAAG;CAEjC,IAAI;EACF,MAAM,UAAU,KAAK,MAAM,GAAG,aAAa,aAAa,OAAO,CAAW;EAG1E,IAAI,CAAC,QAAQ,OAAO,WAAW,CAAC,QAAQ,MAAM,OAAO;EAErD,MAAM,QAAQ,QAAQ,MAAM;EAC5B,OAAY,4BACT,MAAM,EAAE,gBACP,UAAU;GAAE;GAAM;GAAS;GAAM;EAAM,CAAC,EACrC,WACC,oBAAoB,SAAS,MAAM,EAAE,gCAAe,IAAI,KAAK,GAAE,YAAY,EAAE,CAAC,CAChF,EACC,YAAY,CAAC,CAAC,CACnB,EACC,YAAY,CAAC,CAAC;CACnB,QAAQ,CAER;AACF;AAEA,eAAsB,yBACpB,OACA,UAAkBA,aAIjB;CACD,MAAM,aAAa,MAAM,QAAQ,WAAW,GAAG;CAE/C,IAAI,CAAC,YACH,OAAO;EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM;EACR,CACF;EACA,SAAS;CACX;CAIF,MAAM,QAAQ,QAAQ,IAAI,kBAAkB;CAC5C,IAAI,CAAC,eAAe,SAAS,OAAO,UAAU,GAC5C,OAAO;EACL,SAAS,CACP;GAAE,MAAM;GAAQ,MAAM,mBAAmB,MAAM,0BAA0B,WAAW;EAAI,CAC1F;EACA,SAAS;CACX;CAIF,mBAAmB,SAAS,UAAU;CAEtC,IAAI;EAEF,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,MAFZ,aAAa,SAAS,UAAU;EAEZ,CAAC,EAC3C;CACF,SAAS,KAAK;EACZ,OAAO;GACL,SAAS,CACP;IACE,MAAM;IACN,MAAM,UAAW,IAAc;GACjC,CACF;GACA,SAAS;EACX;CACF;AACF;AAEA,SAAgB,2BAA2B,QAAyB;CAClE,OAAO,aACL,wBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;EAWb,aAAa,EAAE,OAAO,EACpB,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,4EAA4E,EAC1F,CAAC;CACH,GACA,OAAO,EAAE,WAAW,yBAAyB,EAAE,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC,EAAG,CAAC,CAC1F;AACF;;;ACtHA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,8BACpB,OACA,UAAkBA,aAGjB;CACD,MAAM,QAAQ,MAAM,SAAS;CAE7B,IAAI;EACF,MAAM,UAAU,MAAM,gBAAgB,SAAS,MAAM,MAAM,MAAM,OAAO,KAAK;EAE7E,MAAM,WACJ,QAAQ,WAAW,IACf;GACE,SAAS,CAAC;GACV,SACE,yBAAyB,MAAM,MAAM,iBAAiB,MAAM,KAAK;EAErE,IACA,EAAE,QAAQ;EAEhB,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC;EAAE,CAAC,EACrE;CACF,QAAQ;EACN,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IACnB,SAAS,CAAC;IACV,SAAS,oCAAoC,MAAM,KAAK;GAC1D,CAAC;EACH,CACF,EACF;CACF;AACF;AAEA,SAAgB,gCAAgC,QAAyB;CACvE,OAAO,aACL,6BACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;EAUb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC;GAC5D,OAAO,EAAE,OAAO,EAAE,SAAS,6CAA6C;GACxE,OAAO,EACJ,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,EAAE,EACN,SAAS,EACT,SAAS,mCAAmC;EACjD,CAAC;CACH,GACA,OAAO,EAAE,MAAM,OAAO,YACpB,8BAA8B;EAC5B;EACA;EACA,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;CACzC,CAAC,CACL;AACF;;;ACxEA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAU9D,SAAS,2BAA2B,kBAA8C;CAChF,IAAI,CAAC,GAAG,WAAW,gBAAgB,GAAG,OAAO,KAAA;CAE7C,MAAM,UAAU,GAAG,aAAa,kBAAkB,OAAO;CAEzD,MAAM,QAAQ,2BAA2B,KAAK,OAAO;CACrD,OAAO,QAAQ,MAAM,KAAK,KAAA;AAC5B;AAEA,eAAsB,oBACpB,OACA,UAAkBA,aAGjB;CACD,MAAM,eAAe,KAAK,KAAK,SAAS,WAAW;CACnD,MAAM,YAA+B,CAAC;CAEtC,IAAI,CAAC,GAAG,WAAW,YAAY,GAC7B,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,CAAC,GAAG,MAAM,CAAC;CAAE,CAAC,EAC/D;CAGF,MAAM,UAAU,GAAG,YAAY,YAAY;CAI3C,MAAM,SAAS,mBAAmB,SADpB,QAAQ,IAAI,kBAAkB,QACI;CAEhD,KAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,cAAc,KAAK,KAAK,cAAc,KAAK;EAGjD,IAAI;GAEF,IAAI,CADS,GAAG,SAAS,WACjB,EAAE,YAAY,GAAG;EAC3B,QAAQ;GACN;EACF;EAEA,MAAM,gBAAgB,KAAK,KAAK,aAAa,eAAe;EAC5D,IAAI,CAAC,GAAG,WAAW,aAAa,GAAG;EAEnC,IAAI;GAEF,MAAM,OADM,OAAO,GAAG,aAAa,eAAe,OAAO,CAC1C,EAAE;GAEjB,MAAM,OAAO,OAAO,KAAK,YAAY,WAAW,KAAK,UAAU;GAC/D,MAAM,QACJ,OAAO,KAAK,0BAA0B,WAAW,KAAK,wBAAwB;GAChF,MAAM,YAAY,OAAO,KAAK,kBAAkB,WAAW,KAAK,gBAAgB,KAAA;GAEhF,MAAM,kBAAkB,2BAA2B,KAAK,KAAK,aAAa,iBAAiB,CAAC;GAE5F,MAAM,UAA2B;IAC/B,MAAM;IACN;IACA;IACA,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;IAC3D,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;GACjD;GAGA,IAAI,MAAM,QAAQ;IAChB,MAAM,cAAc,MAAM,OAAO,YAAY;IAK7C,IAAI,EAHF,KAAK,YAAY,EAAE,SAAS,WAAW,KACvC,MAAM,YAAY,EAAE,SAAS,WAAW,KACxC,MAAM,YAAY,EAAE,SAAS,WAAW,IAC5B;GAChB;GAGA,IAAI,CAAC,OAAO,KAAK,GAAG;GAEpB,UAAU,KAAK,OAAO;EACxB,QAAQ;GAEN;EACF;CACF;CAEA,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,WAAW,MAAM,CAAC;CAAE,CAAC,EACtE;AACF;AAEA,SAAgB,sBAAsB,QAAyB;CAC7D,OAAO,aACL,kBACA;EACE,OAAO;EACP,aAAa;;;;;;;EAOb,aAAa,EAAE,OAAO,EACpB,QAAQ,EACL,OAAO,EACP,SAAS,EACT,SAAS,8DAA8D,EAC5E,CAAC;CACH,GACA,OAAO,EAAE,aAAa,oBAAoB,EAAE,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC,CAC3F;AACF;;;ACjHA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,qBACpB,OAUA,UAAkBA,aAGjB;CACD,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAClD,MAAM,kBAAkB,MAAM,QAAQ;CACtC,MAAM,YAAY,MAAM,UAAU,eAAe,KAAK,IAAI;CAE1D,MAAM,QAA0B;EAC9B,MAAM;EACN,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,SAAS,MAAM;EACf,WAAW,MAAM,aAAa,CAAC;EAC/B;EACA,yBAAQ,IAAI,KAAK,GAAE,YAAY;EAC/B,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;CACxE;CAEA,MAAM,mBAAmB,KAAK,KAAK,SAAS,aAAa,MAAM,MAAM,iBAAiB;CACtF,MAAM,YAAY,uBAAuB,KAAK;CAE9C,IAAI;EACF,YAAY,SAAS,iBAAiB;EAEtC,MAAM,kBAAkB,SAAS,MAAM,MAAM,KAAK;EAGlD,2BAA2B,SAAS,MAAM,MAAM;GAC9C,SAAS,MAAM;GACE;EACnB,CAAC,EAAE,YAAY,CAEf,CAAC;EAGD,4BAA4B,SAAS,MAAM,IAAI,EAAE,YAAY,CAE7D,CAAC;EAGD,MAAM,gBAAgB,KAAK,KAAK,SAAS,aAAa,MAAM,MAAM,eAAe;EACjF,IAAI,GAAG,WAAW,aAAa,GAC7B,IAAI;GACF,MAAM,MAAM,OAAO,GAAG,aAAa,eAAe,OAAO,CAAC;GAC1D,IAAI,KAAK,kBAAkB;GAE3B,IAAI,aAAa,OAAO,UAAU,IAAI,SAAS,IAAI,IAAI;GACvD,aAAa,WAAW,QACtB,sDACA,MACF;GACA,gBAAgB,eAAe,UAAU;EAC3C,QAAQ,CAER;EAGF,gBAAgB,SAAS;GACvB,4BAAW,IAAI,KAAK,GAAE,YAAY;GAClC,OAAO,SAAS;GAChB,MAAM;GACN,MAAM,MAAM;GACZ,SAAS,MAAM;EACjB,CAAC;EAED,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT,MAAM;IACN,OAAO;GACT,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT,OAAQ,IAAc;GACxB,GACA,MACA,CACF;EACF,CACF,EACF;CACF;AACF;AAEA,SAAgB,uBAAuB,QAAyB;CAC9D,OAAO,aACL,mBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;EAab,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC;GAC5D,MAAM,EACH,KAAK;IAAC;IAAS;IAAQ;IAAW;IAAQ;IAAQ;IAAY;IAAY;GAAO,CAAC,EAClF,SAAS,qBAAqB;GACjC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,uCAAuC;GAC3E,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC;GAC5D,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,4BAA4B;GAC/E,WAAW,EACR,KAAK,CAAC,WAAW,UAAU,CAAC,EAC5B,SAAS,EACT,SAAS,4BAA4B;GACxC,QAAQ,EACL,OAAO,EACP,SAAS,EACT,SAAS,wEAAwE;GACpF,MAAM,EACH,OAAO,EACP,MAAM,qBAAqB,EAC3B,SAAS,EACT,SAAS,sDAAsD;EACpE,CAAC;CACH,GACA,OAAO,EAAE,MAAM,MAAM,SAAS,MAAM,SAAS,WAAW,WAAW,QAAQ,WACzE,qBAAqB;EACnB;EACA;EACA;EACA,MAAM;EACN,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;EAC/C,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;EAC/C,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EACzC,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CACvC,CAAC,CACL;AACF;;;AC5KA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,SAAS,kBAAkB,SAAyB;CAElD,MAAM,UAAU,QAAQ,MAAM,yBAAyB;CACvD,OAAO,UAAU,QAAQ,SAAS;AACpC;AAEA,eAAsB,qBACpB,OACA,UAAkBA,aAIjB;CACD,YAAY,SAAS,iBAAiB;CAEtC,MAAM,cAAc,KAAK,KAAK,SAAS,aAAa,MAAM,IAAI;CAE9D,IAAI,CAAC,GAAG,WAAW,WAAW,GAC5B,OAAO;EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,oBAAoB,MAAM,KAAK;EACvC,CACF;EACA,SAAS;CACX;CAGF,MAAM,SAAS,MAAM,UAAU;CAG/B,MAAM,gBAAgB,KAAK,KAAK,aAAa,eAAe;CAC5D,IAAI,YAAqC,CAAC;CAC1C,IAAI,mBAAmB;CACvB,IAAI,GAAG,WAAW,aAAa,GAAG;EAChC,MAAM,MAAM,OAAO,GAAG,aAAa,eAAe,OAAO,CAAW;EACpE,YAAY,IAAI;EAChB,mBAAmB,IAAI,WAAW;CACpC;CAGA,MAAM,mBAAmB,KAAK,KAAK,aAAa,iBAAiB;CACjE,IAAI,sBAAsB;CAC1B,IAAI,oBAAoB;CACxB,IAAI,GAAG,WAAW,gBAAgB,GAAG;EACnC,sBAAsB,GAAG,aAAa,kBAAkB,OAAO;EAC/D,oBAAoB,kBAAkB,mBAAmB;CAC3D;CAGA,MAAM,WAAW,MAAM,aAAa,SAAS,MAAM,IAAI;CAGvD,MAAM,2BAA2B,MAAM,4BAA4B;CACnE,MAAM,iBAAiB,KAAK,KAAK,aAAa,aAAa;CAC3D,MAAM,cAAwB,CAAC;CAC/B,MAAM,qBAA6C,CAAC;CACpD,IAAI,GAAG,WAAW,cAAc,GAC9B,IAAI;EACF,MAAM,QAAQ,GAAG,YAAY,cAAc;EAC3C,KAAK,MAAM,KAAK,OACd,IAAI;GACF,IAAI,CAAC,GAAG,SAAS,KAAK,KAAK,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG;GACzD,YAAY,KAAK,CAAC;GAClB,IAAI,4BAA4B,EAAE,SAAS,KAAK,GAC9C,mBAAmB,KAAK,GAAG,aAAa,KAAK,KAAK,gBAAgB,CAAC,GAAG,OAAO;EAEjF,QAAQ,CAER;CAEJ,QAAQ,CAER;CAEF,MAAM,iCAA2C;EAC/C,MAAM,UAAU,OAAO,QAAQ,kBAAkB;EACjD,IAAI,CAAC,4BAA4B,QAAQ,WAAW,GAAG,OAAO,CAAC;EAC/D,OAAO;GACL;GACA,2BAA2B,QAAQ,OAAO;GAC1C,GAAG,QAAQ,KAAK,CAAC,MAAM,aAAa,SAAS,KAAK,MAAM,QAAQ,KAAK,GAAG;EAC1E;CACF;CAEA,IAAI,WAAW,YA8Bb,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MA9BX;GACf,aAAa,MAAM;GACnB;GACA;GACA,iBAAiB,KAAK,KAAK;GAC3B;GACA;GACA,OAAO,QAAQ,SAAS,EACrB,KAAK,CAAC,GAAG,OAAO,OAAO,EAAE,MAAM,KAAK,UAAU,CAAC,GAAG,EAClD,KAAK,IAAI,KAAK;GACjB;GACA,oBAAoB,kBAAkB;GACtC,oBAAoB,KAAK,KAAK;GAC9B;GACA;GACA,SAAS,SAAS,IACd,SACG,KACE,MACC,OAAO,EAAE,KAAK,OAAO,EAAE,QAAQ,EAAE,UAAU,KAAA,IAAY,OAAO,EAAE,UAAU,KAAK,EAAE,aAAa,aAAa,EAAE,eAAe,IAChI,EACC,KAAK,IAAI,IACZ;GACJ;GACA,mBAAmB,YAAY,OAAO;GACtC,YAAY,SAAS,IAAI,YAAY,KAAK,MAAM,KAAK,GAAG,EAAE,KAAK,IAAI,IAAI;GACvE,GAAG,yBAAyB;EAC9B,EAAE,KAAK,IAGkC;CAAE,CAAC,EAC5C;CAIF,MAAM,WAAW;EACf,MAAM,MAAM;EACZ,6BAAY,IAAI,KAAK,GAAE,YAAY;EACnC;EACA;EACA;EACA;EACA,GAAI,2BAA2B,EAAE,mBAAmB,IAAI,CAAC;CAC3D;CAEA,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC;CAAE,CAAC,EACrE;AACF;AAEA,SAAgB,uBAAuB,QAAyB;CAC9D,OAAO,aACL,mBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;EAab,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC;GAC5D,QAAQ,EACL,KAAK,CAAC,QAAQ,UAAU,CAAC,EACzB,SAAS,EACT,SAAS,+CAA+C;GAC3D,0BAA0B,EACvB,QAAQ,EACR,SAAS,EACT,SAAS,sEAAsE;EACpF,CAAC;CACH,GACA,OAAO,EAAE,MAAM,QAAQ,+BACrB,qBAAqB;EACnB;EACA,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EACzC,GAAI,6BAA6B,KAAA,IAAY,EAAE,yBAAyB,IAAI,CAAC;CAC/E,CAAC,CACL;AACF;;;AC5KA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,0BACpB,OAcA,UAAkBA,aAC2C;CAC7D,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAElD,IAAI;EACF,YAAY,SAAS,uBAAuB;EAE5C,IAAI;EACJ,IAAI,UAAU;EACd,IAAI,CAAC,eAAe,SAAS,MAAM,IAAI,GAAG;GACxC,MAAM,kBAAkB,SAAS,MAAM,IAAI;GAC3C,WAAW;IACT,MAAM,MAAM,QAAQ,MAAM;IAC1B,oBAAoB;IACpB,UAAU;IACV,MAAM,CAAC;IACP,SAAS;IACT,SAAS;GACX;GACA,UAAU;EACZ,OACE,WAAW,MAAM,cAAc,SAAS,MAAM,IAAI;EAGpD,MAAM,UAAU;GACd,GAAG;GACH,GAAI,MAAM,SAAS,KAAA,IAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;GACvD,GAAI,MAAM,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;GAC7D,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;GAC1D,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;GAC1D,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;GACnE,GAAI,MAAM,sBAAsB,KAAA,IAC5B,EAAE,oBAAoB,MAAM,kBAAkB,IAC9C,CAAC;GACL,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,YAAY,MAAM,UAAU,IAAI,CAAC;GACvE,GAAI,MAAM,mBAAmB,KAAA,IAAY,EAAE,iBAAiB,MAAM,eAAe,IAAI,CAAC;GACtF,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;GACnE,GAAI,MAAM,SAAS,KAAA,IAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;GACvD,SAAS;EACX;EAEA,MAAM,eAAe,SAAS,MAAM,MAAM,OAAO;EAEjD,gBAAgB,SAAS;GACvB,4BAAW,IAAI,KAAK,GAAE,YAAY;GAClC,OAAO,SAAS;GAChB,MAAM;GACN,MAAM,MAAM;GACZ,SAAS,OAAO,KAAK,KAAK,EACvB,QAAQ,MAAM,MAAM,MAAM,EAC1B,KAAK,IAAI;EACd,CAAC;EAED,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAM;IAAS,OAAO;GAAQ,GAAG,MAAM,CAAC;EAC1E,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,4BAA4B,QAAyB;CACnE,OAAO,aACL,yBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;;;;;;;;EAoBb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC;GAC5D,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,cAAc;GACnD,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gBAAgB;GACvD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uBAAuB;GAC7D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,cAAc;GACpD,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mBAAmB;GAC5D,mBAAmB,EAChB,KAAK;IAAC;IAAY;IAAU;IAAW;GAAQ,CAAC,EAChD,SAAS,EACT,SAAS,oBAAoB;GAChC,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4BAA4B;GACtE,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,6BAA6B;GAC5E,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+BAA+B;GACxE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,0BAA0B;EAC1E,CAAC;CACH,GACA,OAAO,UAAU,0BAA0B,KAAK,CAClD;AACF;;;AClIA,SAAS,MAAM,OAA4C;CACzD,IAAI,SAAS,IAAI,OAAO;CACxB,IAAI,SAAS,IAAI,OAAO;CACxB,IAAI,SAAS,IAAI,OAAO;CACxB,IAAI,SAAS,IAAI,OAAO;CACxB,OAAO;AACT;AAEA,SAAgB,UAAU,MAAoB,SAA6C;CACzF,IAAI,QAAQ;CACZ,MAAM,WAAqB,CAAC;CAG5B,IAAI,QAAQ,wBAAwB,IAAI;EACtC,SAAS;EACT,SAAS,KAAK,kBAAkB,QAAQ,sBAAsB,MAAM;CACtE,OAAO,IAAI,QAAQ,wBAAwB,IAAI;EAC7C,SAAS;EACT,SAAS,KAAK,6BAA6B,QAAQ,sBAAsB,UAAU;CACrF,OAAO,IAAI,QAAQ,wBAAwB,IACzC,SAAS;CAIX,IAAI,QAAQ,qBAAqB,IAAI;EACnC,SAAS;EACT,SAAS,KAAK,aAAa,KAAK,MAAM,QAAQ,QAAQ,mBAAmB,MAAM;CACjF,OAAO,IAAI,QAAQ,qBAAqB,IAAI;EAC1C,SAAS;EACT,SAAS,KAAK,qBAAqB,KAAK,MAAM,EAAE;CAClD;CAGA,IAAI,QAAQ,gBAAgB,KAAA;MACtB,QAAQ,cAAc,GAAG;GAC3B,SAAS;GACT,SAAS,KAAK,mBAAmB;EACnC,OAAO,IAAI,QAAQ,cAAc,GAAG;GAClC,SAAS;GACT,SAAS,KAAK,gCAAgC;EAChD;;CAIF,IAAI,QAAQ,gBAAgB,KAAA;MACtB,QAAQ,cAAc,MAAM,KAAK,UAAU,QAAQ;GACrD,SAAS;GACT,SAAS,KAAK,oBAAoB,QAAQ,YAAY,gBAAgB,KAAK,MAAM,EAAE;EACrF;;CAGF,QAAQ,KAAK,IAAI,GAAG,KAAK;CACzB,OAAO;EAAE;EAAO,OAAO,MAAM,KAAK;EAAG;EAAS;CAAS;AACzD;AAQA,MAAM,aAAa;;;;;;AAOnB,SAAgB,iBAAiB,MAAoB,WAA6B;CAChF,MAAM,cAAc,KAAK,UAAU,IAAI,KAAK,KAAK,OAAO,IAAI;CAC5D,MAAM,wBAAwB,KAAK,OAChC,UAAU,QAAQ,IAAI,YAAY,QAAQ,KAAK,UAClD;CACA,MAAM,SAAqB;EACzB;EACA,oBAAoB;CACtB;CACA,IAAI,KAAK,cAAc,KAAK,WAAW,KAAK,MAAM,IAChD,OAAO,cAAc,KAAK,OACvB,IAAI,KAAK,KAAK,UAAU,EAAE,QAAQ,IAAI,UAAU,QAAQ,KAAK,UAChE;CAEF,OAAO;AACT;;AAGA,SAAgB,kBAAkB,MAAoB,WAAkC;CACtF,MAAM,SAAS,iBAAiB,MAAM,SAAS;CAC/C,OAAO,UAAU,MAAM;EACrB,uBAAuB,OAAO;EAC9B,oBAAoB,OAAO;EAC3B,GAAI,OAAO,gBAAgB,KAAA,IAAY,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;EAC9E,GAAI,KAAK,gBAAgB,KAAA,IAAY,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;CAC5E,CAAC;AACH;;;ACxGA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,oBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,QAAQ,MAAM,aAAa,SAAS,MAAM,IAAI;EACpD,MAAM,wBAAQ,IAAI,KAAK;EAEvB,MAAM,UAAoE,CAAC;EAE3E,KAAK,MAAM,QAAQ,OAAO;GAExB,MAAM,cAAc,KAAK,UAAU,IAAI,KAAK,KAAK,OAAO,IAAI;GAC5D,MAAM,wBAAwB,KAAK,OAChC,MAAM,QAAQ,IAAI,YAAY,QAAQ,MAAM,MAAO,KAAK,KAAK,GAChE;GAEA,MAAM,cAAc,KAAK,aACrB,KAAK,OACF,IAAI,KAAK,KAAK,UAAU,EAAE,QAAQ,IAAI,MAAM,QAAQ,MAAM,MAAO,KAAK,KAAK,GAC9E,IACA,KAAA;GAEJ,MAAM,SAAS,UAAU,MAAM;IAC7B;IACA,oBAAoB;IACpB,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;IACnD,GAAI,KAAK,gBAAgB,KAAA,IAAY,EAAE,aAAa,KAAK,YAAY,IAAI,CAAC;GAC5E,CAAC;GAED,QAAQ,KAAK;IAAE,MAAM,KAAK;IAAM,OAAO,KAAK;IAAO,GAAG;GAAO,CAAC;EAChE;EAEA,OAAO,EACL,SAAS,CACP;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU;IAAE,MAAM,MAAM;IAAM,OAAO;GAAQ,GAAG,MAAM,CAAC;EAAE,CACtF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,sBAAsB,QAAyB;CAC7D,OAAO,aACL,mBACA;EACE,OAAO;EACP,aAAa;;;EAGb,aAAa,EAAE,OAAO,EACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe,EAC3C,CAAC;CACH,GACA,OAAO,EAAE,WAAW,oBAAoB,EAAE,KAAK,CAAC,CAClD;AACF;;;ACnEA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAY9D,eAAsB,0BACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,QAAQ,kBAAkB,OAAO,EAAE,QACtC,MAAM,CAAC,MAAM,UAAU,EAAE,SAAS,MAAM,MAAM,CACjD;EAEA,MAAM,WAA2B,CAAC;EAElC,KAAK,MAAM,QAAQ,OAAO;GAGxB,MAAM,QAAQ,iBAAiB,SAAS,IAAI;GAE5C,KAAK,MAAM,QAAQ,OAAO;IACxB,IAAI,KAAK,UAAU,SAAS,KAAK,UAAU,QAAQ;IACnD,MAAM,OAAO,KAAK,eAAe;IACjC,MAAM,QAAQ,KAAK,SAAS;IAC5B,MAAM,eAA6B;KACjC;KACA,UAAU,KAAK;KACf,OAAO,KAAK;KACZ;KACA,aAAa;KACb,eAAe,KAAK,MAAO,QAAQ,OAAQ,GAAG;IAChD;IACA,IAAI,KAAK,eAAe,KAAA,GAAW,aAAa,YAAY,KAAK;IACjE,SAAS,KAAK,YAAY;GAC5B;EACF;EAEA,MAAM,qBAAqB,SAAS,QAAQ,KAAK,MAAM,MAAM,EAAE,eAAe,CAAC;EAC/E,MAAM,UAAU,SAAS,QACtB,KAAK,MAAM;GACV,IAAI,CAAC,IAAI,EAAE,QAAQ,IAAI,EAAE,SAAS;IAAE,OAAO;IAAG,eAAe;GAAE;GAC/D,IAAI,EAAE,OAAQ;GACd,IAAI,EAAE,OAAQ,iBAAiB,EAAE;GACjC,OAAO;EACT,GACA,CAAC,CACH;EAEA,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,OAAO;IAAU;IAAoB;GAAQ,GAAG,MAAM,CAAC;EAChF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,4BAA4B,QAAyB;CACnE,OAAO,aACL,yBACA;EACE,OAAO;EACP,aAAa;;;EAGb,aAAa,EAAE,OAAO,EACpB,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mCAAmC,EAC5E,CAAC;CACH,GACA,OAAO,EAAE,aAAa,0BAA0B,EAAE,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC,CACjG;AACF;;;AC1FA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,uBACpB,OAMA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,IAAI,UAAU,MAAM,WAAW,MAAM,GAAG,GAAG;EAC3C,IAAI,YAAsB,CAAC;EAE3B,IAAI;GACF,MAAM,EAAE,YAAY,MAAM,OAAO;GAEjC,MAAM,WAAW,MAAM,QAAQ,gGADgF,MAAM,WAAW,MAAM,GAAG,GAAI,EAAE,gEAC1G;GACrC,MAAM,SAAS,KAAK,MAAM,QAAQ;GAClC,UAAU,OAAO,WAAW;GAC5B,YAAY,OAAO,aAAa,CAAC;EACnC,QAAQ,CAER;EAEA,MAAM,OAAO,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EAC/D,MAAM,YAAY,mBAAmB,KAAK,IAAI;EAE9C,MAAM,kBAAkB,SAAS,MAAM,MAAM;GAC3C;GACA,MAAM;GACN,MAAM,MAAM,QAAQ;GACpB;GACA;GACA;GACA,yBAAQ,IAAI,KAAK,GAAE,YAAY;EACjC,CAAC;EAED,gBAAgB,SAAS;GACvB,4BAAW,IAAI,KAAK,GAAE,YAAY;GAClC,OAAO,SAAS;GAChB,MAAM;GACN,MAAM,MAAM;GACZ,SAAS,QAAQ,MAAM,GAAG,GAAG;EAC/B,CAAC;EAED,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAM;IAAS;IAAW;GAAU,GAAG,MAAM,CAAC;EAChF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,yBAAyB,QAAyB;CAChE,OAAO,aACL,qBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;EASb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,yBAAyB;GAChE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mBAAmB;GACxD,MAAM,EACH,OAAO,EACP,MAAM,qBAAqB,EAC3B,SAAS,EACT,SAAS,cAAc;EAC5B,CAAC;CACH,GACA,OAAO,EAAE,MAAM,YAAY,MAAM,SAAS,WACxC,uBAAuB;EACrB;EACA;EACA,GAAI,YAAY,KAAA,IAAY,EAAE,MAAM,QAAQ,IAAI,CAAC;EACjD,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CACvC,CAAC,CACL;AACF;;;ACrGA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,wBACpB,QACA,UAAkBA,aAC2C;CAC7D,MAAM,SAAS,kBAAkB,OAAO;CACxC,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,GAAG,MAAM,CAAC;CAAE,CAAC,EACvE;AACF;AAEA,SAAgB,0BAA0B,QAAyB;CACjE,OAAO,aACL,uBACA;EACE,OAAO;EACP,aACE;EACF,aAAa,EAAE,OAAO,CAAC,CAAC;CAC1B,GACA,YAAY,wBAAwB,CAAC,CAAC,CACxC;AACF;;;AClBA,eAAsB,sBACpB,SACA,OACA,QAAQ,GACR,aACgC;CAChC,MAAM,QAAQ,kBAAkB,OAAO,EAAE,QAAQ,MAAM,MAAM,WAAW;CAexE,QAAO,MAXmB,QAAQ,IAChC,MAAM,IAAI,OAAO,SAAS;EAExB,QAAO,MADe,gBAAgB,SAAS,MAAM,OAAO,CAAC,GAC9C,KAAK,OAAO;GACzB;GACA,iBAAiB,EAAE,QAAQ,MAAM,GAAG,GAAG;GACvC,OAAO,EAAE;EACX,EAAE;CACJ,CAAC,CACH,GAGG,KAAK,EACL,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAChC,MAAM,GAAG,KAAK;AACnB;;;AC7BA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,4BACpB,OACA,UAAkBA,aAC2C;CAC7D,MAAM,cAAc,MAAM,yBAAyB,MAAM,OAAO,KAAA;CAGhE,MAAM,MAAM,kBAAkB,OAAO;CACrC,MAAM,yBAAyB,cAC3B,IAAI,QAAQ,MAAM,MAAM,WAAW,EAAE,SACrC,IAAI;CAER,MAAM,UAAiC,MAAM,sBAC3C,SACA,MAAM,OACN,IACA,WACF;CAEA,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU;GAAE,OAAO,MAAM;GAAO;GAAS;EAAuB,GAAG,MAAM,CAAC;CACvF,CACF,EACF;AACF;AAEA,SAAgB,8BAA8B,QAAyB;CACrE,OAAO,aACL,2BACA;EACE,OAAO;EACP,aACE;EACF,aAAa,EAAE,OAAO;GACpB,OAAO,EAAE,OAAO,EAAE,SAAS,yCAAyC;GACpE,wBAAwB,EACrB,QAAQ,EACR,SAAS,EACT,SAAS,2CAA2C;GACvD,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,0DAA0D;EACxE,CAAC;CACH,GACA,OAAO,EAAE,OAAO,wBAAwB,WACtC,4BAA4B;EAC1B;EACA,GAAI,2BAA2B,KAAA,IAAY,EAAE,uBAAuB,IAAI,CAAC;EACzE,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CACvC,CAAC,CACL;AACF;;;ACzDA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,SAAS,cAAc,GAAc;CACnC,OAAO;EAAE,IAAI,EAAE;EAAI,MAAM,EAAE;EAAO,OAAO,EAAE,WAAW;CAAS;AACjE;AAEA,eAAsB,2BACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,QAAQ,UAAU,SAAS,MAAM,IAAI;EAC3C,MAAM,eAAe,gBAAgB,KAAK;EAG1C,MAAM,kBAAkB,MAAM,MAC3B,QAAQ,MAAM,EAAE,SAAS,YAAY,EAAE,WAAW,sBAAsB,IAAI,EAC5E,KAAK,MAAM,EAAE,EAAE;EAClB,MAAM,mBAAmB,aAAa,eAAe,KAAK,MAAM,EAAE,EAAE;EAEpE,MAAM,iBAA4D,CAAC;EACnE,KAAK,MAAM,QAAQ,kBACjB,KAAK,MAAM,WAAW,iBAAiB;GACrC,MAAM,IAAI,SAAS,OAAO,SAAS,IAAI;GACvC,IAAI,EAAE,SAAS,GAAG;IAChB,eAAe,KAAK;KAAE,QAAQ;KAAM,MAAM;IAAE,CAAC;IAC7C;GACF;EACF;EAGF,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,MAAM,MAAM;IACZ,WAAW,MAAM,MAAM;IACvB,WAAW,MAAM,MAAM;IACvB,WAAW,MAAM;IACjB,cAAc;KACZ,WAAW,aAAa,UAAU,IAAI,aAAa;KACnD,UAAU,aAAa,SAAS,IAAI,aAAa;KACjD,gBAAgB,aAAa,eAAe,IAAI,aAAa;KAC7D,aAAa,aAAa,YAAY,IAAI,aAAa;KACvD,cAAc,aAAa;IAC7B;IACA;IACA,OAAO,MAAM;IACb,OAAO,MAAM;GACf,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,6BAA6B,QAAyB;CACpE,OAAO,aACL,0BACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;;EAcb,aAAa,EAAE,OAAO,EACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC,EAC9D,CAAC;CACH,GACA,OAAO,EAAE,WAAW,2BAA2B,EAAE,KAAK,CAAC,CACzD;AACF;;;AChGA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAC9D,MAAM,oBAAoB,OAAU;AAEpC,eAAsB,4BACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,IAAI,SAAS,WAAW,SAAS,MAAM,IAAI;EAC3C,IAAI,WAAW,QAAQ,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,SAAS,EAAE,QAAQ,IAAI,mBAAmB;GAC5F,SAAS,sBAAsB,SAAS,MAAM,IAAI;GAClD,YAAY,SAAS,MAAM,MAAM,MAAM;EACzC;EAEA,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,MAAM,MAAM;IACZ,eAAe,OAAO;IACtB,WAAW,OAAO;IAClB,gBAAgB,OAAO,SACpB,QAAQ,MAAM,EAAE,UAAU,SAAS,CAAC,EACpC,KAAK,MAAM,EAAE,SAAS,EAAE,SAAS;IACpC,cAAc,OAAO,SAClB,QAAQ,MAAM,EAAE,UAAU,MAAM,EAChC,KAAK,MAAM,EAAE,SAAS,EAAE,SAAS;IACpC,UAAU,OAAO;GACnB,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,8BAA8B,QAAyB;CACrE,OAAO,aACL,2BACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;;;;;;;;;EAqBb,aAAa,EAAE,OAAO,EACpB,MAAM,EAAE,OAAO,EAAE,SAAS,kCAAkC,EAC9D,CAAC;CACH,GACA,OAAO,EAAE,WAAW,4BAA4B,EAAE,KAAK,CAAC,CAC1D;AACF;;;AC5BA,SAAgB,aAAa,SAAiB,MAAsB;CAClE,OAAO,KAAK,KAAK,SAAS,aAAa,MAAM,WAAW;AAC1D;AAIA,SAAgB,cAAc,SAAiB,MAA0B;CACvE,MAAM,MAAM,aAAa,SAAS,IAAI;CACtC,IAAI,CAAC,GAAG,WAAW,GAAG,GAAG,OAAO,CAAC;CACjC,OAAO,GACJ,YAAY,GAAG,EACf,QAAQ,MAAM,EAAE,SAAS,KAAK,CAAC,EAC/B,KAAK,MAAgB;EACpB,MAAM,WAAW,KAAK,KAAK,KAAK,CAAC;EAEjC,MAAM,SAAS,OADH,GAAG,aAAa,UAAU,OACd,CAAC;EACzB,OAAO;GACL;GACA,MAAM,EAAE,QAAQ,SAAS,EAAE;GAC3B,aAAa,OAAO;GACpB,SAAS,OAAO,QAAQ,KAAK;GAC7B,MAAM;EACR;CACF,CAAC;AACL;AAgBA,eAAsB,cACpB,SACA,MACA,UACe;CACf,MAAM,MAAM,aAAa,SAAS,IAAI;CACtC,MAAM,WAAW,KAAK,KAAK,KAAK,GAAG,SAAS,KAAK,IAAI;CACrD,MAAM,cAAc,UAAU,YAAY;EACxC,GAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;EAErC,gBAAgB,UADJ,OAAO,UAAU,SAAS,SAAS,SAAS,WAC5B,CAAC;CAC/B,CAAC;AACH;AAIA,SAAgB,YAAY,MAAsB;CAChD,OAAO,KACJ,QAAQ,gBAAgB,GAAG,EAC3B,YAAY,EACZ,QAAQ,OAAO,GAAG,EAClB,QAAQ,UAAU,EAAE;AACzB;AASA,SAAS,YAAY,QAAsC;CACzD,OAAO,OAAO,SAAS,UAA8B;EACnD,IAAI,MAAM,WAAW,aAAa,GAChC,OAAO,CAAC;GAAE,MAAM;GAAS,OAAO,MAAM,MAAM,EAAoB;EAAE,CAAC;EAErE,MAAM,UAAU,MAAM,MAAM,qBAAqB;EACjD,IAAI,SAAS,OAAO,CAAC;GAAE,MAAM;GAAY,OAAO,OAAO,QAAQ,EAAE;EAAE,CAAC;EAEpE,MAAM,UAAU,MAAM,MAAM,qBAAqB;EACjD,IAAI,SAAS,OAAO,CAAC;GAAE,MAAM;GAAY,OAAO,OAAO,QAAQ,EAAE;EAAE,CAAC;EAEpE,MAAM,YAAY,MAAM,MAAM,4BAA4B;EAC1D,IAAI,WAAW,OAAO,CAAC;GAAE,MAAM;GAAmB,OAAO,OAAO,UAAU,EAAE;EAAE,CAAC;EAE/E,MAAM,YAAY,MAAM,MAAM,4BAA4B;EAC1D,IAAI,WAAW,OAAO,CAAC;GAAE,MAAM;GAAmB,OAAO,OAAO,UAAU,EAAE;EAAE,CAAC;EAE/E,MAAM,WAAW,MAAM,MAAM,sBAAsB;EACnD,IAAI,UAAU,OAAO,CAAC;GAAE,MAAM;GAAa,OAAO,OAAO,SAAS,EAAE;EAAE,CAAC;EAEvE,MAAM,WAAW,MAAM,MAAM,sBAAsB;EACnD,IAAI,UAAU,OAAO,CAAC;GAAE,MAAM;GAAa,OAAO,OAAO,SAAS,EAAE;EAAE,CAAC;EAEvE,IAAI,UAAU,eAAe,OAAO,CAAC,EAAE,MAAM,cAAc,CAAC;EAC5D,IAAI,UAAU,gBAAgB,OAAO,CAAC,EAAE,MAAM,eAAe,CAAC;EAE9D,OAAO,CAAC;CACV,CAAC;AACH;AAWA,SAAgB,iBAAiB,YAAsD;CACrF,IAAI,CAAC,YAAY,KAAK,GAAG,OAAO;EAAE,YAAY,CAAC;EAAG,UAAU;CAAM;CAClE,MAAM,WAAW,WACd,MAAM,UAAU,EAChB,KAAK,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;CACjB,IAAI,SAAS,SAAS,GACpB,OAAO;EAAE,YAAY,YAAY,QAAQ;EAAG,UAAU;CAAK;CAM7D,OAAO;EAAE,YAAY,YAJH,WACf,MAAM,WAAW,EACjB,KAAK,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAC+B,CAAC;EAAG,UAAU;CAAM;AAC/D;AAEA,SAAgB,kBACd,MACA,MACA,kBACS;CACT,QAAQ,KAAK,MAAb;EACE,KAAK,SACH,OAAO,KAAK,UAAU,KAAK;EAC7B,KAAK,YACH,OAAO,KAAK,SAAS,KAAK,SAAS;EACrC,KAAK,YACH,OAAO,KAAK,SAAS,KAAK,SAAS;EAErC,KAAK,mBACH,OAAO,oBAAoB,KAAK,SAAS;EAC3C,KAAK,mBACH,OAAO,oBAAoB,KAAK,SAAS;EAC3C,KAAK,aACH,OAAO,KAAK,eAAe,KAAK,SAAS;EAC3C,KAAK,aACH,OAAO,KAAK,eAAe,KAAK,SAAS;EAC3C,KAAK,eACH,OAAO,CAAC,KAAK;EACf,KAAK,gBACH,OAAO,KAAK;EACd,SACE,OAAO;CACX;AACF;AAgBA,SAAgB,eACd,WACA,MACA,mBAA2B,GACV;CACjB,MAAM,UAA2B,CAAC;CAClC,KAAK,MAAM,MAAM,WAAW;EAC1B,MAAM,EAAE,YAAY,aAAa,iBAAiB,GAAG,YAAY,OAAO;EACxE,IAAI,WAAW,WAAW,GAAG;EAC7B,MAAM,UAAU,WAAW,QAAQ,MAAM,kBAAkB,GAAG,MAAM,gBAAgB,CAAC;EAErF,IADgB,aAAa,OAAO,QAAQ,SAAS,IAAI,QAAQ,WAAW,WAAW,QAErF,QAAQ,KAAK;GACX,UAAU;GACV,OAAO;GACP,mBAAmB;GACnB,iBAAiB,WAAW;EAC9B,CAAC;CAEL;CACA,OAAO,QAAQ,MAAM,GAAG,MAAM;EAC5B,MAAM,YACH,EAAE,SAAS,YAAY,eAAe,MAAM,EAAE,SAAS,YAAY,eAAe;EACrF,OAAO,aAAa,IAChB,YACC,EAAE,SAAS,YAAY,aAAa,MAAM,EAAE,SAAS,YAAY,aAAa;CACrF,CAAC;AACH;AAaA,SAAgB,mBACd,MACA,UACA,SACA,cACQ;CACR,OAAO;;YAEG,KAAK;QACT,SAAS;WACN,QAAQ;;EAEjB,aAAa,MAAM,GAAG,GAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;AAuB9B;AAEA,SAAgB,qBACd,UACA,kBAA0B,IACF;CACxB,IAAI;EACF,MAAM,QAAQ,SAAS,MAAM,aAAa;EAC1C,IAAI,CAAC,OAAO,OAAO;EACnB,MAAM,SAAS,KAAK,MAAM,MAAM,EAAE;EAClC,IAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,WAAW,CAAC,OAAO,SAAS,OAAO;EAC/D,OAAO;GACL,MAAM,OAAO;GACb,SAAS,OAAO;GAChB,SAAS,OAAO;GAChB,aAAa,OAAO,OAAO,gBAAgB,WAAW,OAAO,cAAc;GAC3E,WAAW,OAAO,aAAa;EACjC;CACF,QAAQ;EACN,OAAO;CACT;AACF;AAMA,eAAsB,gBACpB,SACA,MACA,UACA,SACA,QAA6C,SACb;CAChC,MAAM,mBAAmB,KAAK,KAAK,SAAS,aAAa,MAAM,iBAAiB;CAChF,IAAI,CAAC,GAAG,WAAW,gBAAgB,GAAG,OAAO;EAAE,IAAI;EAAO,WAAW;CAAkB;CAOvF,MAAM,eAAe,qBAAqB,MAHnB,MADR,mBAAmB,MAAM,UAAU,SAD7B,GAAG,aAAa,kBAAkB,OACe,CACpC,CAAC,GAEX,YAAY,QAAQ,IAAM,CACiB;CACnE,IAAI,CAAC,cAAc,OAAO;EAAE,IAAI;EAAO,WAAW;CAAe;CAEjE,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAClD,MAAM,OAAO,YAAY,aAAa,IAAI;CAE1C,MAAM,WAAqB;EACzB;EACA;EACA,aAAa;GACX,SAAS,aAAa;GACtB,aAAa,aAAa;GAC1B,WAAW;GACX,aAAa;EACf;EACA,SAAS,aAAa;EACtB,MAAM,KAAK,KAAK,aAAa,SAAS,IAAI,GAAG,GAAG,KAAK,IAAI;CAC3D;CAEA,MAAM,cAAc,SAAS,MAAM,QAAQ;CAC3C,OAAO;EAAE,IAAI;EAAM;EAAU,WAAW,aAAa;CAAU;AACjE;;;ACjQA,SAAgB,eAAe,SAAiB,MAAsB;CACpE,OAAO,KAAK,KAAK,SAAS,aAAa,MAAM,kBAAkB;AACjE;AAIA,SAAgB,eAAe,SAAiB,MAA0B;CACxE,MAAM,IAAI,eAAe,SAAS,IAAI;CACtC,IAAI,CAAC,GAAG,WAAW,CAAC,GAClB,OAAO;EAAE,eAAe;EAAK;EAAM,gBAAgB,CAAC;EAAG,4BAAW,IAAI,KAAK,GAAE,YAAY;CAAE;CAE7F,IAAI;EACF,OAAO,KAAK,MAAM,GAAG,aAAa,GAAG,OAAO,CAAC;CAC/C,QAAQ;EACN,OAAO;GAAE,eAAe;GAAK;GAAM,gBAAgB,CAAC;GAAG,4BAAW,IAAI,KAAK,GAAE,YAAY;EAAE;CAC7F;AACF;AAEA,SAAgB,gBAAgB,SAAiB,MAAc,OAAyB;CACtF,MAAM,IAAI,eAAe,SAAS,IAAI;CACtC,MAAM,MAAM,KAAK,QAAQ,CAAC;CAC1B,IAAI,CAAC,GAAG,WAAW,GAAG,GAAG,GAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;CAE9D,cAAc,GAAG;EADa,GAAG;EAAO,4BAAW,IAAI,KAAK,GAAE,YAAY;CACnD,CAAC;AAC1B;AAIA,SAAgB,eAAuB;CACrC,OAAO,MAAM,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC;AAClE;AAIA,SAAS,+BAA+B,kBAAkC;CACxE,IAAI,CAAC,GAAG,WAAW,gBAAgB,GAAG,OAAO;CAM7C,OALgB,GAAG,aAAa,kBAAkB,OAC7B,EAClB,MAAM,4BAA4B,EAClC,QAAQ,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EACjC,MAAM,GAAG,CACA,EACT,KAAK,MAAM;EACV,MAAM,YAAY,EAAE,MAAM,kCAAkC;EAC5D,MAAM,eAAe,EAAE,MAAM,4BAA4B;EACzD,IAAI,CAAC,aAAa,CAAC,cAAc,OAAO;EACxC,OAAO,IAAI,UAAU,GAAI,GAAG,UAAU,GAAI,IAAI,aAAa,GAAI,KAAK;CACtE,CAAC,EACA,OAAO,OAAO,EACd,KAAK,IAAI;AACd;AAEA,SAAS,oBAAoB,MAYlB;CAgBT,OAAO;EAdL,SAAS,KAAK,KAAK,KAAK,YAAY,KAAK,KAAK,MAAM,aAAa,KAAK,KAAK,SAAS,IAAI,YAAY,KAAK,KAAK,cAAc;EAC5H,wBAAwB,KAAK,sBAAsB,oBAAoB,KAAK,eAAe;EAC3F,sBAAsB,KAAK,gBAAgB,MAAM,UAAU,KAAK,gBAAgB,MAAM;EACtF,aAAa,KAAK,gBAAgB,SAAS,KAAK,IAAI,KAAK;EACzD;EACA,wBAAwB,KAAK,OAAO,cAAc;EAClD,qBAAqB,KAAK,eAAe,KAAK,IAAI,KAAK;EACvD,kBAAkB,KAAK,aAAa,KAAK,IAAI,KAAK;EAClD,8BAA8B,KAAK,aAAa,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK;EACjF,yBAAyB,KAAK;EAC9B;EACA;EACA,KAAK,6BAA6B;CAEzB,EAAE,KAAK,IAAI;AACxB;AAIA,eAAsB,YACpB,SACA,MACA,UACA,OACiC;CAEjC,MAAM,QAAO,MADO,aAAa,SAAS,IAAI,EAAE,YAAY,CAAC,CAAmB,GAC7D,MAAM,MAAM,EAAE,KAAK,YAAY,MAAM,SAAS,YAAY,CAAC;CAC9E,IAAI,CAAC,MAAM,OAAO;CAElB,MAAM,YAAY,IAAI,KAAK,KAAK;CAChC,MAAM,EAAE,uBAAuB,oBAAoB,gBAAgB,iBACjE,MACA,SACF;CACA,MAAM,kBAAkB,kBAAkB,MAAM,SAAS;CAKzD,MAAM,SAAS,WAAW,SAAS,IAAI,KAAK,sBAAsB,SAAS,MAAM,KAAK;CACtF,MAAM,iBAAiB,OAAO,SAC3B,QAAQ,MAAM,EAAE,UAAU,SAAS,CAAC,EACpC,KAAK,MAAM,EAAE,SAAS,EAAE,SAAS;CACpC,MAAM,eAAe,OAAO,SACzB,QAAQ,MAAM,EAAE,UAAU,MAAM,EAChC,KAAK,MAAM,EAAE,SAAS,EAAE,SAAS;CAGpC,MAAM,eAAe,gBADP,UAAU,SAAS,IACQ,CAAC;CAC1C,MAAM,eAAe,aAAa,aAAa,KAAK,OAAO;EACzD,MAAM,EAAE;EACR,SAAS,EAAE;CACb,EAAE;CACF,MAAM,gBAAgB,aAAa,UAAU;CAG7C,MAAM,4BAA4B,+BADT,KAAK,KAAK,SAAS,aAAa,MAAM,iBACiB,CAAC;CAEjF,MAAM,iBAAiB,oBAAoB;EACzC;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,MAAM,MAAuB;EAC3B;EACA;EACA;EACA;EACA,2BAA2B,OAAO;EAClC;EACA;EACA;EACA;EACA;EACA;CACF;CACA,IAAI,gBAAgB,KAAA,GAAW,IAAI,cAAc;CAGjD,MAAM,WAAW;EACf;EACA,MAAM,KAAK;EACX,OAAO,KAAK;EACZ,OAAO,KAAK,SAAS;EACrB,aAAa,KAAK,eAAe;EACjC,aAAa,OAAO;EACpB,kBAAkB;EAClB,iBAAiB,gBAAgB;CACnC;CAEA,MAAM,oBAAoB,eADL,cAAc,SAAS,IACQ,GAAG,UAAU,qBAAqB;CACtF,IAAI,kBAAkB,SAAS,GAAG,IAAI,oBAAoB;CAE1D,OAAO;AACT;AAIA,SAAgB,eAAe,KAAsB,QAAiC;CACpF,MAAM,cAAc,OAAO,eAAe;CAE1C,MAAM,kBACJ,IAAI,qBAAqB,IAAI,kBAAkB,SAAS,IACpD,4BAA4B,IAAI,kBAAkB,OAAO,0CACzD,IAAI,kBACD,MAAM,GAAG,CAAC,EACV,KACE,MACC,OAAO,EAAE,SAAS,KAAK,IAAI,KAAK,MAAM,EAAE,SAAS,YAAY,cAAc,GAAG,EAAE,uBAAuB,EAAE,SAAS,YAAY,UAAU,MAAM,EAAE,SAAS,QAAQ,MAAM,GAAG,GAAG,GACjL,EACC,KAAK,MAAM,IACd;CAEN,OAAO;;;EAGP,IAAI,iBAAiB,gBAAgB;;eAExB,YAAY;;;;;;;;;;;;;;;;;;;;;;;;AAwB3B;AAIA,SAAgB,iBAAiB,UAA0C;CACzE,IAAI;EACF,MAAM,UAAU,SACb,QAAQ,qBAAqB,EAAE,EAC/B,QAAQ,YAAY,EAAE,EACtB,KAAK;EACR,MAAM,SAAS,KAAK,MAAM,OAAO;EACjC,IAAI,CAAC,OAAO,cAAc,CAAC,OAAO,aAAa,CAAC,MAAM,QAAQ,OAAO,IAAI,GACvE,OAAO;EAET,OAAO;GACL,YAAY,OAAO,OAAO,UAAU;GACpC,WAAW,OAAO;GAClB,MAAM,MAAM,QAAQ,OAAO,IAAI,IAAI,OAAO,OAAO,CAAC;GAClD,SAAS,MAAM,QAAQ,OAAO,OAAO,IAAI,OAAO,UAAU,CAAC;EAC7D;CACF,QAAQ;EACN,OAAO;CACT;AACF;AAIA,SAAgB,uBACd,KACA,QACiB;CACjB,MAAM,OAAuB,CAAC;CAC9B,MAAM,UAAsC,CAAC;CAC7C,IAAI,YAAuB;CAE3B,IAAI,IAAI,gBAAgB,UAAU,OAAO,IAAI,aAAa,SAAS,GAAG,YAAY;MAC7E,IAAI,IAAI,gBAAgB,UAAU,OAAO,IAAI,eAAe,SAAS,GAAG,YAAY;MACpF,IAAI,IAAI,gBAAgB,UAAU,KAAK,YAAY;CAExD,IAAI,OAAO;CAGX,IAAI,IAAI,qBAAqB,IAAI,kBAAkB,SAAS,GAC1D,KAAK,MAAM,SAAS,IAAI,kBAAkB,MAAM,GAAG,CAAC,GAAG;EACrD,KAAK,KAAK;GACR,MAAM;GACN,QAAQ,oBAAoB,MAAM,SAAS,KAAK;GAChD,UAAU;GACV,QAAQ,kBAAkB,KAAK,MAAM,MAAM,SAAS,YAAY,cAAc,GAAG,EAAE,kBAAkB,MAAM,SAAS,YAAY,UAAU,gBAAgB,MAAM,SAAS,YAAY;EACvL,CAAC;EACD,QAAQ,KAAK;GACX,MAAM;GACN,SAAS;IACP,MAAM,OAAO;IACb,SAAS,wBAAwB,MAAM,SAAS,KAAK,KAAK,KAAK,MAAM,MAAM,SAAS,YAAY,cAAc,GAAG,EAAE;IACnH,iBAAiB,MAAM,SAAS,QAAQ,MAAM,GAAG,GAAI;IACrD,SAAS;GACX;GACA,YAAY,MAAM,SAAS,YAAY;GACvC,WAAW,oBAAoB,MAAM,SAAS,YAAY;EAC5D,CAAC;CACH;CAGF,IAAI,IAAI,aAAa,SAAS,GAAG;EAC/B,KAAK,KAAK;GACR,MAAM;GACN,QAAQ,4BAA4B,IAAI,aAAa,KAAK,IAAI;GAC9D,UAAU;GACV,QAAQ;EACV,CAAC;EACD,QAAQ,KAAK;GACX,MAAM;GACN,SAAS;IACP,MAAM,OAAO;IACb,SAAS,kBAAkB,IAAI,aAAa,KAAK,IAAI;IACrD,SAAS;GACX;GACA,YAAY;GACZ,WAAW;EACb,CAAC;CACH;CAEA,IAAI,IAAI,eAAe,SAAS,GAAG;EACjC,KAAK,KAAK;GACR,MAAM;GACN,QAAQ;GACR,UAAU;GACV,QAAQ;EACV,CAAC;EACD,QAAQ,KAAK;GACX,MAAM;GACN,SAAS;IACP,MAAM,OAAO;IACb,MAAM,IAAI,eAAe,MAAM;IAC/B,OAAO;GACT;GACA,YAAY;GACZ,WAAW;EACb,CAAC;CACH;CAEA,IAAI,IAAI,aAAa,MAAM,MAAM,EAAE,SAAS,gBAAgB,GAC1D,KAAK,KAAK;EACR,MAAM;EACN,QAAQ;EACR,UAAU;EACV,QAAQ;CACV,CAAC;CAGH,IAAI,IAAI,gBAAgB,KAAA,KAAa,IAAI,cAAc,MAAM,IAAI,gBAAgB,UAAU,KAAK;EAC9F,KAAK,KAAK;GACR,MAAM;GACN,QAAQ;GACR,UAAU;GACV,QAAQ,iBAAiB,IAAI,YAAY,uBAAuB,IAAI,gBAAgB;EACtF,CAAC;EACD,QAAQ,KAAK;GACX,MAAM;GACN,SAAS;IACP,MAAM,OAAO;IACb,UAAU,OAAO;IACjB,OAAO,4BAA4B,IAAI,YAAY;GACrD;GACA,YAAY;GACZ,WAAW;EACb,CAAC;CACH;CAEA,IAAI,KAAK,WAAW,GAClB,KAAK,KAAK;EACR,MAAM;EACN,QAAQ;EACR,UAAU;EACV,QAAQ;CACV,CAAC;CAIH,OAAO;EAAE,YAAA,SADmB,OAAO,SAAS,cAAc,IAAI,KAAK,MAAM,mBAAmB,IAAI,gBAAgB,MAAM,IAAI,IAAI,gBAAgB,MAAM,eAAe,UAAU;EACxJ;EAAW;EAAM;CAAQ;AAChD;AAIA,SAAgB,cACd,UACA,KACA,QACmB;CACnB,OAAO,SAAS,QAAQ,KAAK,MAAM;EACjC,MAAM,YAAY,IAAI,KAAK,SAAS;EACpC,MAAM,iBACJ,OAAO,kBAAkB,SAAS,EAAE,cAAc,MAAO,YAAY,OAAO;EAE9E,OAAO;GACL,UAAU,aAAa;GACvB,MAAM,EAAE;GACR,SAAS,EAAE;GACX,YAAY,EAAE;GACd,WAAW,EAAE;GACb,uBAAuB,CAAC;GACxB,QAAQ;GACR,4BAAW,IAAI,KAAK,GAAE,YAAY;EACpC;CACF,CAAC;AACH;AAIA,MAAM,eAAe;CAAC;CAAQ;CAAa;CAAY;CAAe;CAAO;AAAM;AAEnF,eAAsB,cACpB,QACA,SACiC;CACjC,MAAM,OAAO,OAAO,QAAQ;CAC5B,IAAI,CAAC,MAAM,OAAO;CAElB,QAAQ,OAAO,MAAf;EACE,KAAK,mBAAmB;GACtB,MAAM,EAAE,sBAAsB,MAAM,OAAO;GAE3C,MAAM,kBAAkB,SAAS,MAAM;IACrC,uBAFY,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAEpC;IACV,MAAO,OAAO,QAAQ,WAAwC;IAC9D,MAAM,OAAO,OAAO,QAAQ,WAAW,OAAO;IAC9C,SAAS,OAAO,OAAO,QAAQ,cAAc,EAAE;IAC/C,WAAW,CAAC;IACZ,WAAW,sBAAsB,OAAO;IACxC,yBAAQ,IAAI,KAAK,GAAE,YAAY;GACjC,CAAC;GACD,OAAO;EACT;EAEA,KAAK,oBAAoB;GACvB,MAAM,EAAE,sBAAsB,MAAM,OAAO;GAE3C,MAAM,kBAAkB,SAAS,MAAM;IACrC,uBAFY,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAEpC;IACV,MAAM;IACN,MAAM,OAAO,OAAO,QAAQ,WAAW,EAAE;IACzC,SAAS,qBAAqB,OAAO,OAAO,QAAQ,YAAY,iCAAiC;IACjG,WAAW,CAAC,yBAAyB,OAAO,OAAO,QAAQ,WAAW,SAAS,GAAG;IAClF,WAAW,sBAAsB,OAAO;IACxC,yBAAQ,IAAI,KAAK,GAAE,YAAY;GACjC,CAAC;GACD,OAAO;EACT;EAEA,KAAK,eAAe;GAClB,MAAM,EAAE,qBAAqB,MAAM,OAAO;GAC1C,MAAM,UAAU,OAAO;GASvB,MAAM,aAAa,aAAa,MAAM,MAAM,MAAM,QAAQ,KAAK;GAC/D,MAAM,iBACJ;IACE,MAAM,QAAQ;IACd,UAAU,QAAQ;IAClB,GAAI,eAAe,KAAA,IAAY,EAAE,OAAO,WAAW,IAAI,CAAC;IACxD,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;IAC9D,GAAI,QAAQ,gBAAgB,KAAA,IAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;IAChF,GAAI,QAAQ,cAAc,KAAA,IAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;IAC1E,GAAI,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;GAChE,GACA,OACF;GACA,OAAO;EACT;EAEA,KAAK,SAAS;GACZ,MAAM,QAAQ,eAAe,SAAS,IAAI;GAC1C,MAAM,cAA+B;IAAE,GAAG;IAAQ,QAAQ;GAAU;GACpE,IAAI,CAAC,MAAM,eAAe,MAAM,MAAM,EAAE,aAAa,OAAO,QAAQ,GAAG;IACrE,MAAM,eAAe,KAAK,WAAW;IACrC,gBAAgB,SAAS,MAAM,KAAK;GACtC;GACA,OAAO;EACT;CACF;AACF;AAIA,eAAsB,aACpB,QACA,SACA,QAA6C,SACnB;CAC1B,MAAM,6BAAY,IAAI,KAAK,GAAE,YAAY;CAEzC,MAAM,MAAM,MAAM,YAAY,SAAS,OAAO,MAAM,OAAO,UAAU,OAAO,KAAK;CACjF,IAAI,CAAC,KACH,MAAM,IAAI,MAAM,SAAS,OAAO,SAAS,4BAA4B,OAAO,KAAK,EAAE;CAGrF,IAAI;CACJ,IAAI;EAGF,WAAW,iBAAiB,MADF,MADX,eAAe,KAAK,MACE,CAAC,CACC,KAAK,uBAAuB,KAAK,MAAM;CAChF,QAAQ;EACN,WAAW,uBAAuB,KAAK,MAAM;CAC/C;CAEA,MAAM,aAAa,cAAc,UAAU,KAAK,MAAM;CAEtD,MAAM,gBAAmC,CAAC;CAC1C,MAAM,kBAAqC,CAAC;CAE5C,IAAI,OAAO,kBAAkB,WAAW,CAExC,OAAO,IAAI,OAAO,kBAAkB;MAC9B,WAAW,SAAS,GAAG;GACzB,MAAM,QAAQ,eAAe,SAAS,OAAO,IAAI;GACjD,KAAK,MAAM,UAAU,YAAY;IAC/B,MAAM,eAAe,KAAK;KAAE,GAAG;KAAQ,uBAAuB;IAAK,CAAC;IACpE,cAAc,KAAK,MAAM;GAC3B;GACA,gBAAgB,SAAS,OAAO,MAAM,KAAK;EAC7C;QACK;EAEL,MAAM,QAAQ,eAAe,SAAS,OAAO,IAAI;EACjD,IAAI,aAAa;EACjB,KAAK,MAAM,UAAU,YACnB,IAAI,CAAC,OAAO,uBAAuB;GACjC,MAAM,UAAU,MAAM,cAAc,QAAQ,OAAO,EAAE,YAAY,SAAkB;GACnF,gBAAgB,KAAK;IACnB,GAAG;IACH,QAAQ,YAAY,aAAa,aAAa;GAChD,CAAC;EACH,OAAO;GACL,MAAM,eAAe,KAAK,MAAM;GAChC,cAAc,KAAK,MAAM;GACzB,aAAa;EACf;EAEF,IAAI,YAAY,gBAAgB,SAAS,OAAO,MAAM,KAAK;CAC7D;CAEA,MAAM,QAAwB;EAC5B;EACA,MAAM,OAAO;EACb,UAAU,OAAO;EACjB,eAAe,OAAO;EACtB,aAAa,IAAI;EACjB,MAAM,SAAS,KAAK,KAAK,MAAM,GAAG,EAAE,KAAK,IAAI,EAAE,OAAO,IAAI,EAAE,SAAS,EAAE;EACvE,mBAAmB;EACnB,aAAa,gBAAgB,MAAM;EACnC,SACE,gBAAgB,SAAS,IAAI,aAAa,cAAc,SAAS,IAAI,WAAW;CACpF;CAEA,OAAO;EACL,MAAM,OAAO;EACb,UAAU,OAAO;EACjB,YAAY,SAAS;EACrB,WAAW,SAAS;EACpB,MAAM,SAAS;EACf;EACA;EACA;CACF;AACF;;;AC5oBA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,mBACpB,OAOA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EAClD,MAAM,SAAS,MAAM,aACnB;GACE,MAAM,MAAM;GACZ,UAAU,MAAM;GAChB,eAAe,MAAM,iBAAiB;GACtC,gBAAgB,MAAM,kBAAkB;GACxC;GACA,GAAI,MAAM,gBAAgB,KAAA,IAAY,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;EAC9E,GACA,OACF;EACA,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC;EAAE,CAAC,EACnE;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,qBAAqB,QAAyB;CAC5D,OAAO,aACL,kBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;;;;;;EAkBb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,UAAU,EAAE,OAAO,EAAE,SAAS,iBAAiB;GAC/C,eAAe,EACZ,KAAK;IAAC;IAAW;IAAW;GAAK,CAAC,EAClC,SAAS,EACT,SAAS,mCAAmC;GAC/C,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oCAAoC;GAChF,gBAAgB,EACb,OAAO,EACP,SAAS,EACT,SAAS,0DAA0D;EACxE,CAAC;CACH,GACA,OAAO,EAAE,MAAM,UAAU,eAAe,aAAa,qBACnD,mBAAmB;EACjB;EACA;EACA,GAAI,kBAAkB,KAAA,IAAY,EAAE,cAAc,IAAI,CAAC;EACvD,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;EACnD,GAAI,mBAAmB,KAAA,IAAY,EAAE,eAAe,IAAI,CAAC;CAC3D,CAAC,CACL;AACF;;;ACpFA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,yBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,QAAQ,eAAe,SAAS,MAAM,IAAI;EAChD,MAAM,MAAM,MAAM,eAAe,WAAW,MAAM,EAAE,aAAa,MAAM,QAAQ;EAE/E,IAAI,QAAQ,IACV,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IAAE,SAAS;IAAO,OAAO,UAAU,MAAM,SAAS;GAAqB,GACvE,MACA,CACF;EACF,CACF,EACF;EAGF,MAAM,SAAS,MAAM,eAAe;EAEpC,IAAI,CAAC,MAAM,UAAU;GACnB,MAAM,eAAe,OAAO;IAAE,GAAG;IAAQ,QAAQ;GAAW;GAC5D,gBAAgB,SAAS,MAAM,MAAM,KAAK;GAC1C,OAAO,EACL,SAAS,CACP;IACE,MAAM;IACN,MAAM,KAAK,UACT;KAAE,SAAS;KAAM,UAAU,MAAM;KAAU,QAAQ;IAAW,GAC9D,MACA,CACF;GACF,CACF,EACF;EACF;EAEA,MAAM,UAAU,MAAM,cAAc,QAAQ,OAAO;EACnD,MAAM,eAAe,OAAO;GAC1B,GAAG;GACH,QAAQ,YAAY,aAAa,aAAa;EAChD;EACA,gBAAgB,SAAS,MAAM,MAAM,KAAK;EAE1C,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT,UAAU,MAAM;IAChB,QAAQ,MAAM,eAAe,KAAM;GACrC,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,2BAA2B,QAAyB;CAClE,OAAO,aACL,wBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;EAUb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO;GACf,UAAU,EAAE,OAAO;GACnB,UAAU,EAAE,QAAQ;EACtB,CAAC;CACH,GACA,OAAO,EAAE,MAAM,UAAU,eAAe,yBAAyB;EAAE;EAAM;EAAU;CAAS,CAAC,CAC/F;AACF;;;ACpGA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,sBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EAClD,MAAM,UAAU,MAAM,WAAW;EAEjC,MAAM,WAAW,MAAM,qBAAqB,SAAS,SAAS,KAAK;EACnE,IAAI,MAAM,eAAe,KAAA,GAAW,SAAS,aAAa,MAAM;EAEhE,MAAM,SAAS,cAAc,QAAQ;EACrC,MAAM,aAAa,uBAAuB,QAAQ,SAAS,MAAM,MAAM;EAEvE,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,UAAU;IACV;IACA,WAAW,SAAS,MAAM;IAC1B;IACA,8BAAa,IAAI,KAAK,GAAE,YAAY;GACtC,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,wBAAwB,QAAyB;CAC/D,OAAO,aACL,oBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;;;;EAgBb,aAAa,EAAE,OAAO;GACpB,SAAS,EACN,KAAK,CAAC,WAAW,MAAM,CAAC,EACxB,SAAS,EACT,SAAS,yCAAuC;GACnD,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yCAAyC;EACtF,CAAC;CACH,GACA,OAAO,EAAE,SAAS,iBAChB,sBAAsB;EACpB,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;EAC3C,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;CACnD,CAAC,CACL;AACF;;;ACpFA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,kBACpB,OAQA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,YAAY,cAAc,SAAS,MAAM,IAAI;EAKnD,IAAI,EAFF,MAAM,UAAU,KAAA,KAAa,MAAM,UAAU,KAAA,KAAa,MAAM,gBAAgB,KAAA,IAGhF,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS,UAAU,KAAK,QAAQ;KAC9B,MAAM,GAAG;KACT,SAAS,GAAG,YAAY;KACxB,aAAa,GAAG,YAAY;KAC5B,WAAW,GAAG,YAAY;KAC1B,aAAa,GAAG,YAAY;KAC5B,SAAS,GAAG;IACd,EAAE;IACF,gBAAgB,UAAU;IAC1B,MAAM,MAAM;GACd,GACA,MACA,CACF;EACF,CACF,EACF;EAcF,MAAM,UAAU,eAAe,WAAW;GAVxC,MAAM,MAAM;GACZ,MAAM;GACN,OAAO,MAAM,SAAS;GACtB,OAAO,MAAM,SAAS;GACtB,aAAa;GACb,aAAa,MAAM,eAAe;GAClC,kBAAkB,MAAM,oBAAoB;GAC5C,iBAAiB,MAAM,mBAAmB;EAGK,GAAG,MAAM,oBAAoB,CAAC;EAC/E,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS,QAAQ,KAAK,OAAO;KAC3B,MAAM,EAAE,SAAS;KACjB,OAAO,EAAE;KACT,mBAAmB,EAAE;KACrB,SAAS,EAAE,SAAS,YAAY;KAChC,aAAa,EAAE,SAAS,YAAY;KACpC,WAAW,EAAE,SAAS,YAAY;KAClC,SAAS,EAAE,SAAS;IACtB,EAAE;IACF,gBAAgB,UAAU;IAC1B,MAAM,MAAM;GACd,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,oBAAoB,QAAyB;CAC3D,OAAO,aACL,gBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;EAab,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa;GACvC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,YAAY;GAClD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qBAAqB;GAC3D,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oBAAoB;GAChE,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;GAC1E,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,qBAAqB;EACxE,CAAC;CACH,GACA,OAAO,EAAE,MAAM,OAAO,OAAO,aAAa,kBAAkB,sBAC1D,kBACE;EACE;EACA,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;EACnD,GAAI,qBAAqB,KAAA,IAAY,EAAE,iBAAiB,IAAI,CAAC;EAC7D,GAAI,oBAAoB,KAAA,IAAY,EAAE,gBAAgB,IAAI,CAAC;CAC7D,GACAA,WACF,CACJ;AACF;;;ACrIA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,qBACpB,OAOA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,OAAO,YAAY,MAAM,IAAI;EACnC,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EAClD,MAAM,WAAW,KAAK,KAAK,aAAa,SAAS,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI;EAE1E,MAAM,WAAW;GACf,MAAM,MAAM;GACZ;GACA,aAAa;IACX,SAAS,MAAM;IACf,aAAa,MAAM,eAAe;IAClC,WAAW;IACX,aAAa;GACf;GACA,SAAS,MAAM;GACf,MAAM;EACR;EAEA,MAAM,cAAc,SAAS,MAAM,MAAM,QAAQ;EAEjD,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT,UAAU;KACR;KACA,SAAS,MAAM;KACf,aAAa,SAAS,YAAY;KAClC,WAAW;KACX,aAAa;KACb,MAAM;IACR;GACF,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,uBAAuB,QAAyB;CAC9D,OAAO,aACL,mBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;;;EAeb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa;GACvC,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,SAAS,EAAE,OAAO,EAAE,SAAS,oBAAoB;GACjD,SAAS,EAAE,OAAO,EAAE,SAAS,wBAAwB;GACrD,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,SAAS,6BAA6B;EACzF,CAAC;CACH,GACA,OAAO,EAAE,MAAM,MAAM,SAAS,SAAS,kBACrC,qBACE;EACE;EACA;EACA;EACA;EACA,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;CACrD,GACAA,WACF,CACJ;AACF;;;AC3GA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,oBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,YAAY,cAAc,SAAS,MAAM,IAAI;EACnD,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,WAAW,UAAU,KAAK,QAAQ;KAChC,MAAM,GAAG;KACT,SAAS,GAAG,YAAY;KACxB,aAAa,GAAG,YAAY;KAC5B,WAAW,GAAG,YAAY;KAC1B,aAAa,GAAG,YAAY;IAC9B,EAAE;IACF,OAAO,UAAU;IACjB,MAAM,MAAM;GACd,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,sBAAsB,QAAyB;CAC7D,OAAO,aACL,kBACA;EACE,OAAO;EACP,aAAa;;;;;;;;EAQb,aAAa,EAAE,OAAO,EACpB,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa,EACzC,CAAC;CACH,GACA,OAAO,EAAE,WAAW,oBAAoB,EAAE,KAAK,GAAGA,WAAQ,CAC5D;AACF;;;AC5DA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,sBACpB,OACA,UAAkBA,aAClB,QAA6C,SACgB;CAC7D,IAAI;EACF,MAAM,SAAS,MAAM,gBAAgB,SAAS,MAAM,MAAM,MAAM,UAAU,MAAM,SAAS,KAAK;EAE9F,IAAI,CAAC,OAAO,IAAI;GACd,MAAM,QACJ,OAAO,cAAc,oBACjB,gCAAgC,MAAM,SACtC;GACN,OAAO,EACL,SAAS,CAAC;IAAE,MAAM;IAAQ,MAAM,KAAK,UAAU;KAAE,SAAS;KAAO;IAAM,GAAG,MAAM,CAAC;GAAE,CAAC,EACtF;EACF;EAEA,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,SAAS;IACT,UAAU;KACR,MAAM,OAAO,SAAS;KACtB,SAAS,OAAO,SAAS,YAAY;KACrC,aAAa,OAAO,SAAS,YAAY;KACzC,WAAW,OAAO,SAAS,YAAY;KACvC,MAAM,OAAO,SAAS;IACxB;IACA,WAAW,OAAO;GACpB,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,wBAAwB,QAAyB;CAC/D,OAAO,aACL,oBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;EAUb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,aAAa;GACvC,UAAU,EAAE,OAAO,EAAE,SAAS,sBAAsB;GACpD,SAAS,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS,cAAc;EAC1D,CAAC;CACH,GACA,OAAO,EAAE,MAAM,UAAU,cACvB,sBAAsB;EAAE;EAAM;EAAU;CAAQ,GAAGA,WAAQ,CAC/D;AACF;;;AC7EA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,iBACpB,OACA,UAAkBA,aAClB,UAAmF,CAAC,GACvB;CAC7D,IAAI;EACF,YAAY,SAAS,aAAa;EAElC,MAAM,OAAO,MAAM,WACjB,SACA;GACE,aAAa,MAAM;GACnB,UAAU,MAAM;GAChB,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;EACpD,GACA;GACE,OAAO,SAAS;GAChB,GAAI,QAAQ,eAAe,EAAE,cAAc,QAAQ,aAAa,IAAI,CAAC;GACrE,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;EAClD,CACF;EAEA,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,QAAQ,KAAK;IACb,aAAa,KAAK;IAClB,QAAQ,KAAK;IACb,UAAU,KAAK;IACf,MAAM,KAAK;IACX,eAAe;KACb,UAAU,KAAK,cAAc;KAC7B,iBAAiB,KAAK,cAAc;KACpC,KAAK,KAAK,cAAc;KACxB,UAAU,KAAK,cAAc;KAC7B,sBAAsB,KAAK,cAAc;IAC3C;GACF,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,mBAAmB,QAAyB;CAC1D,OAAO,aACL,eACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;EAYb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,6DAA6D;GACvF,UAAU,EAAE,OAAO,EAAE,SAAS,4BAA4B;GAC1D,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qCAAqC;EAC/E,CAAC;CACH,GACA,OAAO,EAAE,MAAM,UAAU,cACvB,iBAAiB;EAAE;EAAM;EAAU,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;CAAG,GAAGA,WAAQ,CAChG;AACF;;;ACzFA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,oBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EAClD,MAAM,WAAW,MAAM,SACnB,UAAU,OAAO,EAAE,QAAQ,MAAM,EAAE,OAAO,MAAM,MAAM,IACtD,eAAe,OAAO;EAE1B,IAAI,MAAM,UAAU,SAAS,WAAW,GACtC,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IAAE,SAAS;IAAO,OAAO,SAAS,MAAM,OAAO;GAAa,GAC5D,MACA,CACF;EACF,CACF,EACF;EAGF,MAAM,QAAQ,SAAS,KAAK,MAAM;GAChC,MAAM,aAAa,IAAI,KAAK,EAAE,QAAQ,EAAE,QAAQ;GAChD,MAAM,UAAU,IAAI,KAAK,KAAK,EAAE,QAAQ;GACxC,MAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,MAAM,aAAa,WAAW,KAAU,CAAC;GAChF,OAAO;IACL,IAAI,EAAE;IACN,aAAa,EAAE;IACf,QAAQ,EAAE;IACV,UAAU,EAAE;IACZ,QAAQ,EAAE;IACV,UAAU,EAAE;IACZ;IACA,UAAU,EAAE,cAAc,SAAS,MAAM,GAAG,CAAC;IAC7C,WAAW,EAAE;GACf;EACF,CAAC;EAED,MAAM,SAAS,SAAS,QAAQ,MAAM,EAAE,WAAW,QAAQ;EAC3D,MAAM,YAAY,SAAS,QAAQ,MAAM,EAAE,WAAW,WAAW;EAEjE,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IAAE;IAAO,aAAa,OAAO;IAAQ,gBAAgB,UAAU;GAAO,GACtE,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,sBAAsB,QAAyB;CAC7D,OAAO,aACL,mBACA;EACE,OAAO;EACP,aAAa;;;;;;;;EAQb,aAAa,EAAE,OAAO,EACpB,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,8CAA8C,EACvF,CAAC;CACH,GACA,OAAO,EAAE,aACP,oBAAoB,EAAE,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC,EAAG,GAAGA,WAAQ,CACjF;AACF;;;AC1FA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,MAAM,kBAAkC;CAAC;CAAS;CAAmB;AAAO;AAE5E,eAAsB,+BACpB,OAUA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,IAAI,CAAC,gBAAgB,SAAS,MAAM,QAAQ,GAC1C,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IAAE,SAAS;IAAO,OAAO,qBAAqB,MAAM;GAAW,GAC/D,MACA,CACF;EACF,CACF,EACF;EAGF,YAAY,SAAS,4BAA4B;EAEjD,MAAM,eAAuC,CAAC;EAC9C,IAAI,MAAM,gBAAgB,aAAa,oBAAoB,MAAM;EACjE,IAAI,MAAM,sBACR,aAAa,0BAA0B,MAAM;EAC/C,IAAI,MAAM,mBAAmB,aAAa,uBAAuB,MAAM;EACvE,IAAI,MAAM,aAAa,aAAa,iBAAiB,MAAM;EAC3D,IAAI,MAAM,gBAAgB,aAAa,oBAAoB,MAAM;EAEjE,MAAM,MAAM,MAAM,SAAS,SAAS,MAAM,UAAU,MAAM,MAAM;GAC9D,YAAY,MAAM;GAClB;EACF,CAAC;EAED,MAAM,UAAU,MAAM,WAAW,SAAS,WAAW,IACjD,4IACA,KAAA;EAEJ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,gBAAgB,IAAI;IACpB,UAAU,IAAI;IACd,MAAM,IAAI;IACV,QAAQ,IAAI;IACZ,WAAW,IAAI;IACf,WAAW,IAAI;IACf,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;GAC/B,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,iCAAiC,QAAyB;CACxE,OAAO,aACL,8BACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;;;;;EAiBb,aAAa,EAAE,OAAO;GACpB,UAAU,EAAE,KAAK;IAAC;IAAS;IAAmB;GAAO,CAAC,EAAE,SAAS,eAAe;GAChF,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,YAAY,EAAE,OAAO,EAAE,SAAS,yCAAyC;GACzE,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,iCAAiC;GAChF,sBAAsB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mCAAmC;GACxF,mBAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;GAC3E,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0BAA0B;GACtE,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,4BAA4B;EAC7E,CAAC;CACH,GACA,OAAO,EACL,UACA,MACA,YACA,gBACA,sBACA,mBACA,aACA,qBAEA,+BACE;EACE;EACA;EACA;EACA,GAAI,mBAAmB,KAAA,IAAY,EAAE,eAAe,IAAI,CAAC;EACzD,GAAI,yBAAyB,KAAA,IAAY,EAAE,qBAAqB,IAAI,CAAC;EACrE,GAAI,sBAAsB,KAAA,IAAY,EAAE,kBAAkB,IAAI,CAAC;EAC/D,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;EACnD,GAAI,mBAAmB,KAAA,IAAY,EAAE,eAAe,IAAI,CAAC;CAC3D,GACAA,WACF,CACJ;AACF;;;AC9IA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,oBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,IAAI,OAAO,MAAM,kBAAkB,OAAO;EAE1C,IAAI,MAAM,MAAM,OAAO,KAAK,QAAQ,MAAM,EAAE,SAAS,MAAM,IAAI;EAC/D,IAAI,MAAM,UAAU,OAAO,KAAK,QAAQ,MAAM,EAAE,aAAa,MAAM,QAAQ;EAE3E,MAAM,MAAM,KAAK,IAAI;EACrB,MAAM,uBAAuB,OAAU,KAAK;EAE5C,MAAM,gBAAgB,KAAK,KAAK,MAAM;GACpC,MAAM,iBAAiB,EAAE,YACrB,KAAK,OAAO,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,QAAQ,OAAU,IAAK,IACrE;GACJ,MAAM,eACJ,EAAE,cAAc,QAAQ,IAAI,KAAK,EAAE,SAAS,EAAE,QAAQ,IAAI,MAAM;GAElE,OAAO;IACL,IAAI,EAAE;IACN,UAAU,EAAE;IACZ,MAAM,EAAE;IACR,QAAQ,EAAE;IACV,WAAW,EAAE;IACb;IACA;IACA,aAAa,EAAE;IACf,iBAAiB,EAAE;IACnB,YAAY,EAAE;GAChB;EACF,CAAC;EAED,MAAM,iBAAiB,WAAuB,KAAK,QAAQ,MAAM,EAAE,WAAW,MAAM,EAAE;EAEtF,MAAM,UAAU;GACd,OAAO,KAAK;GACZ,QAAQ,cAAc,QAAQ;GAC9B,cAAc,cAAc,QAAQ,MAAM,EAAE,gBAAgB,EAAE,WAAW,QAAQ,EAAE;GACnF,SAAS,cAAc,SAAS;EAClC;EAEA,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE;IAAe;GAAQ,GAAG,MAAM,CAAC;EAC1D,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,sBAAsB,QAAyB;CAC7D,OAAO,aACL,mBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;EAWb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;GAC9D,UAAU,EACP,KAAK;IAAC;IAAS;IAAmB;GAAO,CAAC,EAC1C,SAAS,EACT,SAAS,oBAAoB;EAClC,CAAC;CACH,GACA,OAAO,EAAE,MAAM,eACb,oBACE;EACE,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EACrC,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;CAC/C,GACAA,WACF,CACJ;AACF;;;AClEA,SAAgB,oBACd,SACA,MACA,OACA,UACgB;CAChB,MAAM,QAAQ,UAAU,SAAS,IAAI;CACrC,MAAM,eAAe,gBAAgB,KAAK;CAC1C,MAAM,SAAS,WAAW,SAAS,IAAI;CAEvC,MAAM,WAAW,IAAI,IAAI,aAAa,UAAU,KAAK,MAAM,EAAE,EAAE,CAAC;CAChE,MAAM,WAAW,IAAI,IAAI,aAAa,eAAe,KAAK,MAAM,EAAE,EAAE,CAAC;CACrE,MAAM,aAAa,IAAI,IAAI,aAAa,SAAS,KAAK,MAAM,EAAE,EAAE,CAAC;CAEjE,MAAM,oBAAoB,IAAI,KAAK,QAAQ,YAAY,CAAC,GAAG,KAAK,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;CAIvF,MAAM,SAFc,MAAM,MAAM,QAAQ,MAAM,EAAE,SAAS,QAEV,EAAE,KAAK,SAAS;EAC7D,MAAM,gBAAgB,kBAAkB,IAAI,KAAK,EAAE;EAEnD,IAAI,OAAwB;EAC5B,IAAI,SAAS,IAAI,KAAK,EAAE,GAAG,OAAO;OAC7B,IAAI,SAAS,IAAI,KAAK,EAAE,GAAG,OAAO;OAClC,IAAI,WAAW,IAAI,KAAK,EAAE,GAAG,OAAO;EAEzC,MAAM,QAAQ,MAAM,MAAM,QAAQ,MAAM,EAAE,SAAS,KAAK,EAAE;EAC1D,MAAM,kBACJ,MAAM,SAAS,IAAI,KAAK,MAAM,KAAK,IAAI,GAAG,MAAM,KAAK,MAAM,EAAE,MAAM,CAAC,IAAI,GAAG,IAAI,MAAM;EAEvF,MAAM,UAA8B;GAClC,MAAM,KAAK;GACX;GACA,aAAa,eAAe,SAAS;GACrC,kBAAkB,eAAe,oBAAoB;GACrD;GACA,WAAW,eAAe,aAAa,CAAC;EAC1C;EACA,IAAI,KAAK,WAAW,OAClB,QAAQ,QAAQ,KAAK,WAAW;EAElC,OAAO;CACT,CAAC;CAED,MAAM,iBAAiB,oBAAoB,QAAQ,aAAa,cAAc,CAAC,CAAC;CAEhF,MAAM,iBAAiB,qBAAqB,QAAQ,aAAa,YAAY;CAE7E,OAAO;EACL;EACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;EAC/B,4BAAW,IAAI,KAAK,GAAG,MAAM,WAAW,GAAE,YAAY;EACtD;EACA,cAAc,aAAa;EAC3B;EACA;CACF;AACF;AAEA,SAAgB,oBACd,QACA,cACA,UAA4B,CAAC,GACrB;CACR,MAAM,QAAkB,CAAC;CAEzB,IAAI,aAAa,MAAM,MAAM,EAAE,SAAS,UAAU,GAChD,MAAM,KAAK,2DAA2D;CAExE,IAAI,aAAa,MAAM,MAAM,EAAE,SAAS,gBAAgB,GACtD,MAAM,KAAK,4DAA4D;CAGzE,MAAM,aAAa,OAAO,QAAQ,MAAM,EAAE,UAAU,SAAS,gBAAgB,CAAC;CAC9E,IAAI,WAAW,SAAS,GACtB,MAAM,KAAK,iCAAiC,WAAW,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,EAAE;CAGzF,MAAM,YAAY,OAAO,QAAQ,MAAM,EAAE,cAAc,EAAE;CACzD,IAAI,UAAU,SAAS,GACrB,MAAM,KAAK,2BAA2B,UAAU,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,EAAE;CAGlF,MAAM,kBAAkB,QAAQ,QAAQ,MAAM,EAAE,WAAW,UAAU;CACrE,KAAK,MAAM,OAAO,gBAAgB,MAAM,GAAG,CAAC,GAC1C,MAAM,KAAK,oBAAoB,IAAI,SAAS;CAG9C,OAAO,MAAM,SAAS,IAAI,MAAM,KAAK,GAAG,IAAI;AAC9C;AAIA,SAAS,qBAAqB,QAA8B,cAAqC;CAC/F,MAAM,WAAW,aAAa,MAAM,MAAM,EAAE,YAAY,UAAU;CAClE,IAAI,UAAU,OAAO,SAAS;CAE9B,MAAM,aAAa,OAAO,QAAQ,MAAM,EAAE,UAAU,SAAS,gBAAgB,CAAC;CAC9E,IAAI,WAAW,SAAS,GACtB,OAAO,aAAa,WAAW,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE;CAG/D,MAAM,YAAY,aAAa,MAAM,MAAM,EAAE,YAAY,WAAW;CACpE,IAAI,WAAW,OAAO,UAAU;CAMhC,OAAO,2BAHL,OAAO,SAAS,IACZ,KAAK,MAAM,OAAO,QAAQ,GAAG,MAAM,IAAI,EAAE,aAAa,CAAC,IAAI,OAAO,MAAM,IACxE,EACsC;AAC9C;;;AC9IA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,yBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EAClD,MAAM,MAAM,oBAAoB,SAAS,MAAM,MAAM,OAAO,MAAM,QAAQ;EAC1E,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,KAAK,MAAM,CAAC;EAAE,CAAC,EAChE;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,2BAA2B,QAAyB;CAClE,OAAO,aACL,wBACA;EACE,OAAO;EACP,aAAa;;;EAGb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;EACrF,CAAC;CACH,GACA,OAAO,EAAE,MAAM,eAAe,yBAAyB,WAAW;EAAE;EAAM;CAAS,IAAI,EAAE,KAAK,CAAC,CACjG;AACF;;;ACHA,eAAsB,cACpB,SACA,MACA,UACA,OACwB;CAExB,MAAM,CAAC,eAAe,YAAY,MAAM,QAAQ,IAAI,CAClD,aAAa,SAAS,IAAI,EAAE,YAAY,CAAC,CAAC,GAC1C,qBAAqB,SAAS,WAAW,KAAK,EAAE,aAAa;EAC3D,OAAO,CAAC;EACR,iBAAiB,CAAC;EAClB,YAAY;EACZ,SAAS;EACT;CACF,EAAE,CACJ,CAAC;CAGD,MAAM,eAAe,oBAAoB,SAAS,MAAM,OAAO,QAAQ;CACvE,MAAM,SAAS,WAAW,SAAS,IAAI;CACvC,MAAM,YAAY,cAAc;EAAE,GAAG;EAAU,YAAY;CAAK,CAAC;CAGjE,MAAM,YAAY,IAAI,KAAK,KAAK;CAChC,MAAM,aAAgC,cACnC,QAAQ,MAAM,EAAE,UAAU,SAAS,EAAE,UAAU,MAAM,EACrD,KAAK,SAAS;EACb,MAAM,SAA0B,kBAAkB,MAAM,SAAS;EACjE,OAAO;GACL,MAAM,KAAK;GACX,OAAO,KAAK;GACZ,OAAO,OAAO;GACd,OAAO,OAAO;GACd,UAAU,OAAO;EACnB;CACF,CAAC;CAGH,MAAM,kBAAkB,cAAc,MAAM,MAAM,EAAE,UAAU,SAAS,EAAE,UAAU,MAAM;CACzF,IAAI,sBAA4C;CAChD,IAAI,iBAAiB;EAEnB,MAAM,gBAAgB,aAAa,OAAO,MAAM,MAAM,EAAE,SAAS,UAAU,GAAG;EAO9E,MAAM,qBANe,gBACjB,QAAQ,SAAS,MACd,MAAM,EAAE,UAAU,iBAAiB,EAAE,cAAc,UAAU,eAChE,IACA,KAAA,MACkC,QAAQ,WAAW,KACjB,oBAAoB;EAC5D,MAAM,eAAe;GACnB;GACA,MAAM,gBAAgB;GACtB,OAAO,gBAAgB;GACvB,OAAO,gBAAgB,SAAS;GAChC,aAAa,gBAAgB,eAAe;GAC5C,aAAa,QAAQ,iBAAiB;GACtC;GACA,iBAAiB,aAAa,OAAO,MAAM,MAAM,EAAE,SAAS,UAAU;EACxE;EAEA,sBADgB,eAAe,cAAc,SAAS,IAAI,GAAG,cAAc,gBAC/C,EAAE,MAAM;CACtC;CAEA,MAAM,YAAY,iBAChB,aAAa,cACb,YACA,QAAQ,iBAAiB,GAC3B;CACA,MAAM,gBAAgB,mBAAmB,cAAc,UAAU;CACjE,MAAM,mBAAmB,sBACvB,MACA,UACA,cACA,QAAQ,iBAAiB,KACzB,WACA,SACF;CAEA,OAAO;EACL;EACA;EACA,8BAAa,IAAI,KAAK,GAAE,YAAY;EACpC;EACA,oBAAoB,QAAQ,YAAY,CAAC;EACzC;EACA,mBAAmB;GACjB,KAAK,UAAU;GACf,KAAK,UAAU;GACf,KAAK,UAAU;GACf,UAAU,UAAU;GACpB,eAAe,UAAU;EAC3B;EACA;EACA;EACA;EACA;CACF;AACF;AAIA,SAAS,iBACP,cACA,YACA,eACQ;CACR,IAAI,OAAO;CAEX,KAAK,MAAM,MAAM,cACf,QAAQ,GAAG,YAAY,aAAa,KAAK;CAG3C,MAAM,eACJ,WAAW,SAAS,IAAI,WAAW,QAAQ,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC,IAAI,WAAW,SAAS;CAC5F,QAAQ,KAAK,OAAO,MAAM,gBAAgB,EAAG;CAE7C,QAAQ,KAAK,OAAO,MAAM,iBAAiB,EAAG;CAE9C,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;AACxC;AAEA,SAAS,mBAAmB,cAA8B,YAAyC;CACjG,MAAM,aAAuB,CAAC;CAE9B,KAAK,MAAM,MAAM,aAAa,cAC5B,IAAI,GAAG,YAAY,YAAY,WAAW,KAAK,GAAG,UAAU;CAG9D,MAAM,aAAa,aAAa,OAAO,QAAQ,MAAM,EAAE,UAAU,SAAS,gBAAgB,CAAC;CAC3F,IAAI,WAAW,SAAS,GACtB,WAAW,KAAK,aAAa,WAAW,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,oBAAoB;CAG5F,MAAM,cAAc,WAAW,QAAQ,MAAM,EAAE,QAAQ,EAAE;CACzD,MAAM,YAAY,KAAK,IAAI,GAAG,YAAY,MAAM;CAChD,KAAK,MAAM,KAAK,YAAY,MAAM,GAAG,SAAS,GAC5C,WAAW,KACT,gBAAgB,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,EAAE,SAAS,MAAM,WACvE;CAEF,IAAI,YAAY,SAAS,WACvB,WAAW,KAAK,IAAI,YAAY,SAAS,UAAU,sCAAsC;CAG3F,KAAK,MAAM,MAAM,aAAa,cAC5B,IAAI,GAAG,YAAY,aAAa,WAAW,KAAK,GAAG,UAAU;CAG/D,IAAI,WAAW,WAAW,GACxB,WAAW,KAAK,qDAAqD;CAGvE,OAAO;AACT;AAEA,SAAS,sBACP,MACA,UACA,cACA,eACA,KACA,WACQ;CACR,MAAM,aAAa,aAAa,OAAO,QAAQ,MAAM,EAAE,SAAS,UAAU,EAAE;CAC5E,MAAM,kBAAkB,aAAa,aAAa,QAAQ,MAAM,EAAE,YAAY,UAAU,EAAE;CAE1F,MAAM,QAAkB,CAAC;CACzB,MAAM,KACJ,GAAG,KAAK,GAAG,SAAS,wBAAwB,cAAc,QAAQ,WAAW,yBAC/E;CACA,IAAI,IAAI,MAAM,GACZ,MAAM,KAAK,4BAA4B,IAAI,MAAM,KAAM,QAAQ,CAAC,EAAE,GAAG;CAEvE,IAAI,kBAAkB,GACpB,MAAM,KACJ,kBAAkB,gBAAgB,yCAAyC,UAAU,MACvF;MAEA,MAAM,KAAK,uBAAuB,UAAU,MAAM;CAEpD,OAAO,MAAM,KAAK,GAAG;AACvB;;;AC3NA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,mBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;EAClD,MAAM,QAAQ,MAAM,cAAc,SAAS,MAAM,MAAM,MAAM,UAAU,KAAK;EAC5E,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC;EAAE,CAAC,EAClE;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,qBAAqB,QAAyB;CAC5D,OAAO,aACL,kBACA;EACE,OAAO;EACP,aAAa;;;EAGb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,UAAU,EAAE,OAAO,EAAE,SAAS,6BAA6B;EAC7D,CAAC;CACH,GACA,OAAO,EAAE,MAAM,eAAe,mBAAmB;EAAE;EAAM;CAAS,CAAC,CACrE;AACF;;;ACvCA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,2BACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI;EAEF,MAAM,WAAW,MAAM,mBAAmB,SAD7B,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CACR;EACvD,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC;EAAE,CAAC,EACrE;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU;IAAE,SAAS;IAAO,OAAQ,IAAc;GAAQ,GAAG,MAAM,CAAC;EACjF,CACF,EACF;CACF;AACF;AAEA,SAAgB,6BAA6B,QAAyB;CACpE,OAAO,aACL,0BACA;EACE,OAAO;EACP,aAAa;;;EAGb,aAAa,EAAE,OAAO,EACpB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,2CAA2C,EAClF,CAAC;CACH,GACA,OAAO,EAAE,WAAW,2BAA2B,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,CACrE;AACF;;;ACtCA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,yBACpB,OACA,UAAkBA,aAC2C;CAE7D,MAAM,UADY,cAAc,SAAS,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC,CAClE,EAAE,KAAK,EAAE,MAAM,OAAO,GAAG,WAAW,IAAI;CAChE,OAAO,EAAE,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC;CAAE,CAAC,EAAE;AAC/E;AAEA,SAAgB,2BAA2B,QAAmB,UAAkBA,aAAgB;CAC9F,OAAO,aACL,wBACA;EACE,aACE;EACF,aAAa,EAAE,OAAO,EACpB,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oBAAoB,EAC/D,CAAC;CACH,IACC,EAAE,eAAe,yBAAyB,WAAW,EAAE,SAAS,IAAI,CAAC,GAAG,OAAO,CAClF;AACF;;;ACtBA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,uBACpB,OACA,UAAkBA,aAC2C;CAC7D,MAAM,OAAO,YAAY,SAAS,MAAM,EAAE;CAC1C,IAAI,CAAC,MACH,OAAO,EACL,SAAS,CACP;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,aAAa,MAAM,GAAG,aAAa,CAAC;CAAE,CACtF,EACF;CAEF,MAAM,UAAU,iBAAiB,GAAG,KAAK,QAAQ,IAAI,KAAK,MAAM;CAChE,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,OAAO,CAAC;CACnC,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU;GAAE,GAAG;GAAM,mBAAmB;EAAO,GAAG,MAAM,CAAC;CACtE,CACF,EACF;AACF;AAEA,SAAgB,yBAAyB,QAAmB,UAAkBA,aAAgB;CAC5F,OAAO,aACL,sBACA;EACE,aACE;EACF,aAAa,EAAE,OAAO,EACpB,IAAI,EAAE,OAAO,EAAE,SAAS,uCAAuC,EACjE,CAAC;CACH,IACC,EAAE,SAAS,uBAAuB,EAAE,GAAG,GAAG,OAAO,CACpD;AACF;;;ACrCA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,iBACpB,OAMA,UAAkBA,aAC2C;CAC7D,MAAM,OAAO,YAAY,SAAS,MAAM,UAAU;CAClD,IAAI,CAAC,MACH,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EAAE,OAAO,aAAa,MAAM,WAAW,aAAa,CAAC;CAC5E,CACF,EACF;CAIF,MAAM,OAAO;EAAE,GAAG,MADK,2BAA2B,SAAS,MAAM,IAAI;EACzC,GAAI,MAAM,aAAa,CAAC;CAAG;CAEvD,MAAM,UAAU,YAAY,KAAK,SAAS,IAAI;CAC9C,MAAM,mBAAmB,YAAY,KAAK,MAAM,IAAI;CAIpD,IAAI,gBAAgB,MAAM;CAC1B,IAAI,CAAC,eAAe;EAClB,MAAM,EAAE,aAAa,oBAAoB,MAAM,OAAO;EACtD,MAAM,QAAQ,gBAAgB,YAAY,SAAS,MAAM,IAAI,CAAC;EAC9D,IAAI,OAAO,gBAAgB;CAC7B;CAKA,IAAI,OAAO;CACX,IAAI,WAAW;CACf,IAAI,eACF,IAAI;EACF,MAAM,EAAE,YAAY,MAAM,OAAO;EACjC,MAAM,UAAU,MAAM,QACpB,oCAAoC,cAAc,qJAEc,kBAClE;EACA,IAAI,WAAW,QAAQ,KAAK,GAAG;GAE7B,MAAM,EAAE,mBAAmB,MAAM,OAAO;GACxC,OAAO,eAAe,QAAQ,KAAK,CAAC;GACpC,WAAW;EACb;CACF,QAAQ,CAER;CAKF,MAAM,MAAK,MADS,cAAc,SAAS,MAAM,IAAI,EAAE,YAAY,IAAI,IACrD,SAAS;CAE3B,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE;GACA;GACA;GACA,MAAM,MAAM;GACZ,YAAY,MAAM;GAClB,MAAM,iBAAiB;GACvB;GACA,mBAAmB;EACrB,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,mBAAmB,QAAmB,UAAkBA,aAAgB;CACtF,OAAO,aACL,eACA;EACE,aAAa;;;;;EAKb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,YAAY,EAAE,OAAO,EAAE,SAAS,oBAAoB;GACpD,WAAW,EACR,OAAO,EAAE,OAAO,CAAC,EACjB,SAAS,EACT,SAAS,4DAA4D;GACxE,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,6EAA6E;EAC3F,CAAC;CACH,IACC,EAAE,MAAM,YAAY,WAAW,WAC9B,iBACE;EACE;EACA;EACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;EAC/C,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CACvC,GACA,OACF,CACJ;AACF;;;AC3HA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,uBACpB,OACA,UAAkBA,aAC2C;CAC7D,MAAM,WAAW,YAAY,SAAS,MAAM,UAAU;CACtD,IAAI,CAAC,UACH,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EAAE,OAAO,aAAa,MAAM,WAAW,aAAa,CAAC;CAC5E,CACF,EACF;CAIF,MAAM,YAAY,SAAS,MAAM;CAEjC,IAAI,CADa,YAAY,SAAS,UAAU,UACpC,GACV,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EACnB,OAAO,aAAa,UAAU,WAAW,wBAC3C,CAAC;CACH,CACF,EACF;CAGF,MAAM,eAAe,UAAU,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC;CAClF,MAAM,uBAAM,IAAI,KAAK,GAAE,YAAY;CAanC,MAAM,gBAAgB,SAAS;EAV7B,IAAI;EACJ,YAAY,MAAM;EAClB,MAAM,MAAM;EACZ,cAAc,MAAM;EACpB,YAAY;EACZ,QAAQ;EACR,aAAa;EACb,gBAAgB,CAAC;CAGqB,CAAC;CAEzC,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU;GACnB;GACA,cAAc,SAAS;GACvB,YAAY,SAAS,MAAM;EAC7B,CAAC;CACH,CACF,EACF;AACF;AAEA,SAAgB,yBAAyB,QAAmB,UAAkBA,aAAgB;CAC5F,OAAO,aACL,sBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,wCAAwC;GAClF,YAAY,EAAE,OAAO,EAAE,SAAS,iCAAiC;EACnE,CAAC;CACH,IACC,EAAE,MAAM,cAAc,iBACrB,uBAAuB;EAAE;EAAM;EAAc;CAAW,GAAG,OAAO,CACtE;AACF;;;AC/EA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,8BACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI,cAAc,gBAAgB,OAAO;CAEzC,IAAI,MAAM,SAAS,KAAA,GACjB,cAAc,YAAY,QAAQ,MAA0B,EAAE,SAAS,MAAM,IAAI;CAGnF,IAAI,MAAM,WAAW,KAAA,GACnB,cAAc,YAAY,QAAQ,MAA0B,EAAE,WAAW,MAAM,MAAM;CAGvF,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EAAE,YAAY,GAAG,MAAM,CAAC;CAC/C,CACF,EACF;AACF;AAEA,SAAgB,gCACd,QACA,UAAkBA,aACZ;CACN,OAAO,aACL,6BACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;GAC9D,QAAQ,EACL,KAAK;IAAC;IAAU;IAAU;GAAW,CAAC,EACtC,SAAS,EACT,SAAS,6BAA6B;EAC3C,CAAC;CACH,IACC,EAAE,MAAM,aACP,8BACE;EACE,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EACrC,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;CAC3C,GACA,OACF,CACJ;AACF;;;ACrDA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,2BACpB,OACA,UAAkBA,aAC2C;CAG7D,IAAI,CAAC,MAFiB,iBAAiB,SAAS,MAAM,cAAc,EAAE,QAAQ,SAAS,CAAC,GAGtF,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU;GACnB,SAAS;GACT,OAAO,eAAe,MAAM,aAAa;EAC3C,CAAC;CACH,CACF,EACF;CAGF,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EAAE,SAAS,KAAK,CAAC;CACxC,CACF,EACF;AACF;AAEA,SAAgB,6BAA6B,QAAmB,UAAkBA,aAAgB;CAChG,OAAO,aACL,0BACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO,EACpB,cAAc,EAAE,OAAO,EAAE,SAAS,+BAA+B,EACnE,CAAC;CACH,IACC,EAAE,mBAAmB,2BAA2B,EAAE,aAAa,GAAG,OAAO,CAC5E;AACF;;;AC5CA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,oBACpB,QACA,UAAkBA,aAC2C;CAC7D,MAAM,YAAY,cAAc,OAAO;CACvC,MAAM,cAAc,gBAAgB,OAAO;CAE3C,MAAM,SAAS,UAAU,KAAK,SAAS;EACrC,IAAI,IAAI;EACR,MAAM,IAAI;EACV,WAAW,IAAI,MAAM;EACrB,iBAAiB,YAAY,QAAQ,MAAM,EAAE,eAAe,IAAI,EAAE,EAAE;CACtE,EAAE;CAEF,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EAAE,WAAW,OAAO,GAAG,MAAM,CAAC;CACrD,CACF,EACF;AACF;AAEA,SAAgB,sBAAsB,QAAmB,UAAkBA,aAAgB;CACzF,OAAO,aACL,kBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO,CAAC,CAAC;CAC1B,SACM,oBAAoB,CAAC,GAAG,OAAO,CACvC;AACF;;;ACpCA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,oBACpB,OAQA,UAAkBA,aAC2C;CAC7D,IAAI;EACF,MAAM,QAAQ,MAAM,cAAc,SAAS,KAAK;EAChD,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE,aAAa,MAAM;IACnB,UAAU,MAAM;IAChB,OAAO,MAAM;IACb,UAAU,MAAM;IAChB,KAAK,MAAM;IACX,YAAY,MAAM;IAClB,UAAU,MAAM;IAChB,YAAY,MAAM;IAClB,QAAQ,MAAM;GAChB,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,EAAE,OAAQ,IAAc,QAAQ,CAAC;EAAE,CAAC,EACrF;CACF;AACF;AAEA,SAAgB,sBAAsB,QAAmB,UAAkBA,aAAgB;CACzF,OAAO,aACL,kBACA;EACE,aAAa;;;EAGb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,UAAU,EAAE,OAAO,EAAE,SAAS,oCAAoC;GAClE,WAAW,EACR,MACC,EAAE,OAAO;IACP,aAAa,EAAE,OAAO;IACtB,UAAU,EAAE,OAAO,EAAE,SAAS;IAC9B,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;GAC7B,CAAC,CACH,EACC,IAAI,CAAC,EACL,SAAS,0BAA0B;GACtC,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,6BAA6B;GACxF,gBAAgB,EACb,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,qCAAqC;GACjD,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,6BAA6B;EACxE,CAAC;CACH,IACC,EAAE,MAAM,UAAU,WAAW,YAAY,gBAAgB,eACxD,oBACE;EACE;EACA;EACA;EACA,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;EACjD,GAAI,mBAAmB,KAAA,IAAY,EAAE,eAAe,IAAI,CAAC;EACzD,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;CAC/C,GACA,OACF,CACJ;AACF;;;ACvFA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,qBACpB,OACA,UAAkBA,aAC2C;CAC7D,IAAI,MAAM,aAAa;EACrB,MAAM,QAAQ,UAAU,SAAS,MAAM,WAAW;EAClD,IAAI,CAAC,OACH,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UAAU,EAAE,OAAO,UAAU,MAAM,YAAY,aAAa,CAAC;EAC1E,CACF,EACF;EAEF,OAAO,EAAE,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC;EAAE,CAAC,EAAE;CAC7E;CAEA,MAAM,SAAS,WAAW,SAAS,MAAM,IAAI;CAC7C,OAAO,EAAE,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,GAAG,MAAM,CAAC;CAAE,CAAC,EAAE;AAClF;AAEA,SAAgB,uBAAuB,QAAmB,UAAkBA,aAAgB;CAC1F,OAAO,aACL,oBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yCAAyC;GACrF,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sCAAsC;EAC7E,CAAC;CACH,IACC,EAAE,aAAa,WACd,qBACE;EACE,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;EACnD,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CACvC,GACA,OACF,CACJ;AACF;;;AC3CA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAQ9D,SAAS,mBAAmB,SAAiC;CAC3D,MAAM,IAAI,KAAK,KAAK,SAAS,YAAY,gBAAgB,eAAe;CACxE,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC;CAC/B,IAAI;EACF,OAAQ,KAAK,KAAK,GAAG,aAAa,GAAG,OAAO,CAAW,KAAwB,CAAC;CAClF,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS,kBAAkB,SAAiB,MAAiD;CAC3F,MAAM,IAAI,KAAK,KAAK,SAAS,aAAa,MAAM,eAAe;CAC/D,IAAI,CAAC,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC;CAC/B,MAAM,UAAU,GAAG,aAAa,GAAG,OAAO;CAC1C,MAAM,YAAY,kBAAkB,KAAK,OAAO;CAChD,MAAM,aAAa,mBAAmB,KAAK,OAAO;CAClD,MAAM,OAAO,YAAY,IAAI,KAAK;CAClC,MAAM,QAAQ,aAAa,IAAI,KAAK;CACpC,OAAO;EACL,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;EACvB,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC3B;AACF;AAEA,eAAsB,qBACpB,OACA,UAAkBA,aAC2C;CAC7D,MAAM,SAAS,mBAAmB,OAAO;CACzC,MAAM,SAAS,OAAO,UAAU,QAAQ,IAAI,uBAAuB;CAEnE,IAAI,CAAC,QACH,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EACnB,OACE,iHACJ,CAAC;CACH,CACF,EACF;CAGF,MAAM,gBAAgB,MAAM,aAAa,OAAO,oBAAoB;CAEpE,IAAI;EACF,MAAM,EAAE,mBAAmB,mBAAmB,MAAM,OAAO;EAE3D,MAAM,aAAa,MAAM,kBAAkB,QAAQ,eADnC,MAAM,cAAc,kBAAkB,SAAS,MAAM,IAAI,IAAI,KAAA,CACJ;EAGzE,MAAM,aAAY,MADO,eAAe,MAAM,GACjB,MAC1B,OACC,GAAG,SAAS,iBAAiB,GAAG,KAAK,YAAY,EAAE,SAAS,cAAc,YAAY,CAAC,CAC3F;EAEA,OAAO,EACL,SAAS,CACP;GACE,MAAM;GACN,MAAM,KAAK,UACT;IACE;IACA,WAAW,WAAW,QAAQ;IAC9B,UAAU,WAAW,YAAY;IACjC,MAAM,MAAM;GACd,GACA,MACA,CACF;EACF,CACF,EACF;CACF,SAAS,KAAK;EACZ,OAAO,EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAAM,KAAK,UAAU,EAAE,OAAQ,IAAc,QAAQ,CAAC;EAAE,CAAC,EACrF;CACF;AACF;AAEA,SAAgB,uBAAuB,QAAmB,UAAkBA,aAAgB;CAC1F,OAAO,aACL,oBACA;EACE,aAAa;;;EAGb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,WAAW,EACR,OAAO,EACP,SAAS,EACT,SACC,kFACF;GACF,aAAa,EACV,QAAQ,EACR,SAAS,EACT,SAAS,sDAAsD;EACpE,CAAC;CACH,IACC,EAAE,MAAM,WAAW,kBAClB,qBACE;EACE;EACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;EAC/C,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;CACrD,GACA,OACF,CACJ;AACF;;;ACzHA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,mBACpB,OAOA,UAAkBA,aAC2C;CAC7D,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAClD,MAAM,QAAQ,aAAa,OAAO;CAClC,MAAM,WAAW,MAAM,YAAY;CAEnC,MAAM,KAAK,aAAa,MADD,YAAY,SAAS,MAAM,IAAI,CACtB;CAChC,MAAM,SAAS,WAAW,OAAO,UAAU,KAAK;CAEhD,MAAM,SAAiB;EACrB;EACA,OAAO,MAAM;EACb,QAAQ;EACR;EACA,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;EACrD,SAAS;EACT;EACA,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;CAChE;CAEA,MAAM,aAAa,SAAS,MAAM,MAAM,MAAM;CAE9C,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,GAAG,MAAM,CAAC;CAAE,CAAC,EACvE;AACF;AAEA,SAAgB,qBAAqB,QAAmB,UAAkBA,aAAgB;CACxF,OAAO,aACL,iBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,cAAc;GAChD,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sBAAsB;GAClE,UAAU,EACP,KAAK;IAAC;IAAU;IAAQ;IAAU;GAAK,CAAC,EACxC,SAAS,EACT,SAAS,4BAA4B;GACxC,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,wBAAwB;EACnE,CAAC;CACH,IACC,EAAE,MAAM,OAAO,aAAa,UAAU,eACrC,mBACE;EACE;EACA;EACA,GAAI,gBAAgB,KAAA,IAAY,EAAE,YAAY,IAAI,CAAC;EACnD,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;CAC/C,GACA,OACF,CACJ;AACF;;;ACnEA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,mBACpB,OACA,UAAkBA,aAC2C;CAE7D,MAAM,UAAS,MADO,YAAY,SAAS,MAAM,IAAI,GAC9B,MAAM,MAAM,EAAE,OAAO,MAAM,QAAQ;CAE1D,IAAI,CAAC,QACH,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EACnB,OAAO,WAAW,MAAM,SAAS,4BAA4B,MAAM,KAAK,GAC1E,CAAC;CACH,CACF,EACF;CAGF,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAClD,MAAM,UAAkB;EACtB,GAAG;EACH,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;EAC/C,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;EACnE,GAAI,MAAM,WAAW,cAAc,CAAC,OAAO,WAAW,EAAE,UAAU,MAAM,IAAI,CAAC;CAC/E;CAEA,MAAM,aAAa,SAAS,MAAM,MAAM,OAAO;CAE/C,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,QAAQ,QAAQ,GAAG,MAAM,CAAC;CAAE,CAAC,EAChF;AACF;AAEA,SAAgB,qBAAqB,QAAmB,UAAkBA,aAAgB;CACxF,OAAO,aACL,iBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,UAAU,EAAE,OAAO,EAAE,SAAS,wBAAwB;GACtD,QAAQ,EAAE,KAAK;IAAC;IAAQ;IAAe;IAAW;IAAY;GAAQ,CAAC,EAAE,SAAS;GAClF,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,cAAc;EACzD,CAAC;CACH,IACC,EAAE,MAAM,UAAU,QAAQ,eACzB,mBACE;EACE;EACA;EACA,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EACzC,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;CAC/C,GACA,OACF,CACJ;AACF;;;AC7DA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,kBACpB,OAMA,UAAkBA,aAC2C;CAC7D,MAAM,UAAU,MAAM,eAAe,SAAS;EAC5C,GAAI,MAAM,SAAS,KAAA,IAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;EACvD,GAAI,MAAM,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;EAC7D,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;EACnE,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;CACrE,CAAC;CAED,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,SAAS,QAAQ,GAAG,MAAM,CAAC;CAAE,CAAC,EACjF;AACF;AAEA,SAAgB,oBAAoB,QAAmB,UAAkBA,aAAgB;CACvF,OAAO,aACL,gBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;GAC9D,QAAQ,EAAE,KAAK;IAAC;IAAQ;IAAe;IAAW;IAAY;GAAQ,CAAC,EAAE,SAAS;GAClF,UAAU,EAAE,KAAK;IAAC;IAAU;IAAQ;IAAU;GAAK,CAAC,EAAE,SAAS;GAC/D,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,oBAAoB;EAC/D,CAAC;CACH,IACC,EAAE,MAAM,QAAQ,UAAU,eACzB,kBACE;EACE,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EACrC,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EACzC,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;CAC/C,GACA,OACF,CACJ;AACF;;;AC9CA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,kBACpB,OACA,UAAkBA,aAC2C;CAE7D,MAAM,UAAS,MADO,YAAY,SAAS,MAAM,IAAI,GAC9B,MAAM,MAAM,EAAE,OAAO,MAAM,QAAQ;CAE1D,IAAI,CAAC,QACH,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU,EACnB,OAAO,WAAW,MAAM,SAAS,mBAAmB,MAAM,KAAK,GACjE,CAAC;CACH,CACF,EACF;CAGF,MAAM,yBAAQ,IAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;CAClD,MAAM,UAAkB;EACtB,GAAG;EACH,QAAQ;EACR,UAAU,OAAO,YAAY;CAC/B;CAEA,MAAM,aAAa,SAAS,MAAM,MAAM,OAAO;CAE/C,IAAI,MAAM,YACR,MAAM,kBAAkB,SAAS,MAAM,MAAM;EAC3C,MAAM;EACN,MAAM;EACN,MAAM,MAAM;EACZ,SAAS,UAAU,MAAM,SAAS,WAAW,MAAM;EACnD,WAAW,CAAC;EACZ,WAAW,YAAY,MAAM,SAAS;EACtC,yBAAQ,IAAI,KAAK,GAAE,YAAY;CACjC,CAAC;CAGH,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,QAAQ,QAAQ,GAAG,MAAM,CAAC;CAAE,CAAC,EAChF;AACF;AAEA,SAAgB,oBAAoB,QAAmB,UAAkBA,aAAgB;CACvF,OAAO,aACL,gBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,UAAU,EAAE,OAAO,EAAE,SAAS,wBAAwB;GACtD,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0CAA0C;EACvF,CAAC;CACH,IACC,EAAE,MAAM,UAAU,iBACjB,kBACE;EACE;EACA;EACA,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;CACnD,GACA,OACF,CACJ;AACF;;;ACnEA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,oBACpB,OACA,UAAkBA,aAC2C;CAC7D,MAAM,SAAS,UAAU,SAAS,MAAM,QAAQ;CAChD,IAAI,CAAC,QACH,OAAO,EACL,SAAS,CACP;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,WAAW,MAAM,SAAS,aAAa,CAAC;CAAE,CAC1F,EACF;CAGF,MAAM,YAAY,MAAM,aAAa,QAAQ,IAAI,uBAAuB;CACxE,MAAM,QAAQ,oBAAoB,MAAM,MAAM,MAAM,cAAc,MAAM,QAAQ;CAChF,MAAM,QAAQ,iBAAiB,QAAQ,WAAW,KAAK;CAEvD,MAAM,kBAAkB,SAAS,MAAM,UAAU,MAAM,MAAM,MAAM,cAAc,KAAK;CAEtF,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE;GACA,SAAS,MAAM;GACf,MAAM,MAAM;GACZ,WAAW,GAAG,UAAU,wBAAwB;GAChD,MAAM;EACR,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,sBAAsB,QAAmB,UAAkBA,aAAgB;CACzF,OAAO,aACL,mBACA;EACE,aAAa;;;EAGb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe;GACzC,cAAc,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,iCAAiC;GAC3E,UAAU,EAAE,OAAO,EAAE,SAAS,6CAA6C;GAC3E,WAAW,EACR,OAAO,EACP,SAAS,EACT,SACC,qFACF;EACJ,CAAC;CACH,IACC,EAAE,MAAM,cAAc,UAAU,gBAC/B,oBACE;EACE;EACA;EACA;EACA,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;CACjD,GACA,OACF,CACJ;AACF;;;AC5EA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,uBACpB,OACA,UAAkBA,aAC2C;CAC7D,MAAM,YAAY,oBAAoB,SAAS,MAAM,UAAU,MAAM,IAAI;CACzE,MAAM,MAAM,aAAa,SAAS;CAClC,MAAM,YAAY,UAAU,QAAQ,MAAM,EAAE,SAAS,CAAC,EAAE;CACxD,MAAM,WAAW,UAAU,QAAQ,MAAM,EAAE,SAAS,KAAK,EAAE,SAAS,CAAC,EAAE;CACvE,MAAM,aAAa,UAAU,QAAQ,MAAM,EAAE,SAAS,CAAC,EAAE;CAEzD,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,UAAU,MAAM;GAChB,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;GACzC,gBAAgB,UAAU;GAC1B,UAAU;GACV;GACA;GACA;GACA,WAAW,UAAU,KAAK,OAAO;IAC/B,MAAM,EAAE;IACR,OAAO,EAAE;IACT,OAAO,EAAE;IACT,GAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;IAC1C,aAAa,EAAE;GACjB,EAAE;EACJ,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,yBAAyB,QAAmB,UAAkBA,aAAgB;CAC5F,OAAO,aACL,sBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,UAAU,EAAE,OAAO,EAAE,SAAS,WAAW;GACzC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,uCAAuC;EAC9E,CAAC;CACH,IACC,EAAE,UAAU,WACX,uBACE;EACE;EACA,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CACvC,GACA,OACF,CACJ;AACF;;;AC7DA,MAAMC,cAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,0BACpB,OACA,UAAkBA,aAC2C;CAC7D,MAAM,UAAU,eAAe,SAAS,MAAM,OAAO,EACnD,GAAI,MAAM,aAAa,EAAE,YAAY,KAAK,IAAI,CAAC,EACjD,CAAC;CAGD,MAAM,WADW,MAAM,WAAW,QAAQ,QAAQ,MAAM,EAAE,aAAa,MAAM,QAAQ,IAAI,SAChE,MAAM,GAAG,MAAM,SAAS,EAAE;CAEnD,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,OAAO,MAAM;GACb,OAAO,QAAQ;GACf,UAAU,QAAQ,KAAK,OAAO;IAC5B,GAAG,mBAAmB,CAAC;IACvB,SAAS,EAAE,KAAK,MAAM,GAAG,GAAG,EAAE,KAAK;GACrC,EAAE;EACJ,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,4BAA4B,QAAmB,UAAkBA,aAAgB;CAC/F,OAAO,aACL,yBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,OAAO,EAAE,OAAO,EAAE,SAAS,cAAc;GACzC,UAAU,EACP,OAAO,EACP,SAAS,EACT,SAAS,sDAAsD;GAClE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,6BAA6B;GACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,0BAA0B;EACnF,CAAC;CACH,IACC,EAAE,OAAO,UAAU,YAAY,YAC9B,0BACE;EACE;EACA,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,eAAe,KAAA,IAAY,EAAE,WAAW,IAAI,CAAC;EACjD,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;CACzC,GACA,OACF,CACJ;AACF;;;AC5DA,MAAMC,aAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,sBACpB,OASA,UAAkBA,YAC2C;CAE7D,IADiB,aAAa,SAAS,MAAM,EAClC,GACT,OAAO,EACL,SAAS,CACP;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,EAAE,OAAO,YAAY,MAAM,GAAG,kBAAkB,CAAC;CAAE,CAC1F,EACF;CAGF,MAAM,uBAAM,IAAI,KAAK,GAAE,YAAY;CACnC,MAAM,UAAqB;EACzB,IAAI,MAAM;EACV,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,UAAU,MAAM,YAAY;EAC5B,MAAM,MAAM,QAAQ,CAAC;EACrB,QAAQ,MAAM,UAAU;EACxB,WAAW;EACX,WAAW;EACX,GAAI,MAAM,iBAAiB,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;CACzE;CAEA,eAAe,SAAS,OAAO;CAE/B,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,IAAI,QAAQ;GACZ,OAAO,QAAQ;GACf,UAAU,QAAQ;GAClB,MAAM,2BAA2B,QAAQ,SAAS,GAAG,QAAQ,GAAG;EAClE,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,wBAAwB,QAAmB,UAAkBA,YAAgB;CAC3F,OAAO,aACL,qBACA;EACE,aAAa;;EAEb,aAAa,EAAE,OAAO;GACpB,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oDAAoD;GACnF,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,eAAe;GACjD,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,0BAA0B;GAC3D,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+BAA+B;GACxE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,iBAAiB;GAC/D,QAAQ,EACL,QAAQ,EACR,SAAS,EACT,SAAS,mDAAmD;GAC/D,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yCAAyC;EAC1F,CAAC;CACH,IACC,EAAE,IAAI,OAAO,MAAM,UAAU,MAAM,QAAQ,KAAK,qBAC/C,sBACE;EACE;EACA;EACA;EACA,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EACrC,GAAI,QAAQ,KAAA,IAAY,EAAE,QAAQ,IAAI,IAAI,CAAC;EAC3C,GAAI,mBAAmB,KAAA,IAAY,EAAE,eAAe,IAAI,CAAC;CAC3D,GACA,OACF,CACJ;AACF;;;ACzFA,MAAMC,aAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,gBACpB,OACA,UAAkBA,YAC2C;CAC7D,MAAM,UAAU,KAAK,KACnB,SACA,iCAAgB,IAAI,KAAK,GAAE,YAAY,EAAE,QAAQ,SAAS,GAAG,EAAE,MAAM,GAAG,EAAE,EAAE,KAC9E;CAEA,MAAM,WAAW,MAAM,UAAU,SAAS,SAAS,EACjD,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC,EACjD,CAAC,EAAE,YAAY,IAAI;CAEnB,IAAI,CAAC,UACH,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM;CAAmD,CAAC,EACtF;CAGF,MAAM,SAAS,GAAG,WAAW,OAAO,KAC/B,GAAG,SAAS,OAAO,EAAE,OAAO,OAAO,MAAM,QAAQ,CAAC,IACnD;CAEJ,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,MAAM;GACN,WAAW,SAAS;GACpB,eAAe,SAAS;GACxB,WAAW,SAAS;GACpB,QAAQ,GAAG,OAAO;GAClB,aAAa,SAAS;GACtB,UAAU;GACV,GAAI,MAAM,SAAS,EAAE,YAAY,MAAM,OAAO,IAAI,CAAC;GACnD,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;EAC3C,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,kBAAkB,QAAyB;CACzD,OAAO,aACL,cACA;EACE,aACE;EACF,aAAa,EAAE,OAAO;GACpB,QAAQ,EACL,OAAO,EACP,SAAS,EACT,SACC,qFACF;GACF,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kCAAkC;EACzE,CAAC;CACH,IACC,EAAE,QAAQ,WACT,gBAAgB;EACd,GAAI,WAAW,KAAA,IAAY,EAAE,OAAO,IAAI,CAAC;EACzC,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;CACvC,CAAC,CACL;AACF;;;ACzEA,MAAMC,aAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,kBACpB,OACA,UAAkBA,YAC2C;CAC7D,MAAM,aAAa,cAAc,OAAO;CACxC,MAAM,cAAc,iBAAiB,OAAO;CAG5C,MAAM,UAAU,WAAW,SAAS,IAAI,aAAa;CACrD,MAAM,UAAU,QAAQ,MAAM,GAAG,MAAM,KAAK;CAE5C,IAAI,QAAQ,WAAW,GACrB,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM;CAAkD,CAAC,EACrF;CAGF,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,OAAO,QAAQ;GACf,gBAAgB,QAAQ;GACxB,SAAS,QAAQ,KAAK,OAAO;IAC3B,UAAU,EAAE;IACZ,WAAW,EAAE;IACb,QAAQ,EAAE,YAAY,IAAI,IAAI,EAAE,YAAY,OAAO,MAAM,QAAQ,CAAC,EAAE,OAAO;IAC3E,UAAU,EAAE;IACZ,WAAW,EAAE;IACb,eAAe,EAAE;IACjB,WAAW,EAAE;GACf,EAAE;EACJ,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,oBAAoB,QAAyB;CAC3D,OAAO,aACL,gBACA;EACE,aACE;EACF,aAAa,EAAE,OAAO,EACpB,OAAO,EACJ,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,EAAE,EACV,SAAS,qCAAqC,EACnD,CAAC;CACH,IACC,UAAU,kBAAkB,KAAK,CACpC;AACF;;;AC5DA,MAAMC,aAAW,QAAQ,IAAI;AAE7B,eAAsB,kBACpB,OACA,UAAkBA,YAC2C;CAC7D,MAAM,OAAO,aAAa;CAC1B,IAAI,CAAC,MACH,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU;GACnB,SAAS;GACT,OAAO;EACT,CAAC;CACH,CACF,EACF;CAGF,MAAM,eAAe,KAAK,KAAK,SAAS,WAAW;CACnD,IAAI,CAAC,GAAG,WAAW,YAAY,GAC7B,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UAAU;GAAE,SAAS;GAAM,QAAQ;GAAG,SAAS;GAAG,WAAW,CAAC;EAAE,CAAC;CAC9E,CACF,EACF;CAGF,MAAM,QAAQ,MAAM,OAChB,CAAC,MAAM,IAAI,IACX,GAAG,YAAY,YAAY,EAAE,QAAQ,MAAM;EACzC,IAAI;GACF,OAAO,GAAG,SAAS,KAAK,KAAK,cAAc,CAAC,CAAC,EAAE,YAAY;EAC7D,QAAQ;GACN,OAAO;EACT;CACF,CAAC;CAEL,MAAM,YAAY,MAAM,QACpB,IAAI,KAAK,MAAM,KAAK,oBACpB,IAAI,KAAK,KAAK,IAAI,IAAI,OAAU,KAAK,GAAI;CAC7C,MAAM,UAAoE,CAAC;CAC3E,MAAM,SAAmB,CAAC;CAE1B,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,cAAc,KAAK,KAAK,cAAc,MAAM,cAAc;EAChE,IAAI,CAAC,GAAG,WAAW,WAAW,GAAG;EACjC,IAAI;GACF,MAAM,UAAU,KAAK,MAAM,GAAG,aAAa,aAAa,OAAO,CAAW;GAG1E,IAAI,CAAC,QAAQ,OAAO,WAAW,CAAC,QAAQ,MAAM,OAAO;GAErD,MAAM,EAAE,cAAc,MAAM,OAAO;GACnC,MAAM,SAAS,MAAM,UAAU;IAC7B;IACA;IACA;IACA,OAAO,QAAQ,MAAM;IACrB,OAAO;GACT,CAAC;GACD,oBAAoB,SAAS,MAAM,EAAE,gCAAe,IAAI,KAAK,GAAE,YAAY,EAAE,CAAC;GAC9E,QAAQ,KAAK;IAAE;IAAM,GAAG;GAAO,CAAC;EAClC,SAAS,KAAK;GACZ,OAAO,KAAK,GAAG,KAAK,IAAK,IAAc,SAAS;EAClD;CACF;CAEA,MAAM,QAAQ,QAAQ,QACnB,KAAK,OAAO;EAAE,QAAQ,IAAI,SAAS,EAAE;EAAQ,SAAS,IAAI,UAAU,EAAE;CAAQ,IAC/E;EAAE,QAAQ;EAAG,SAAS;CAAE,CAC1B;CAEA,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,SAAS;GACT,GAAG;GACH,WAAW;GACX;EACF,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,oBAAoB,QAAyB;CAC3D,OAAO,aACL,gBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;EASb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,+CAA+C;GACpF,OAAO,EACJ,OAAO,EACP,SAAS,EACT,SAAS,qDAAqD;EACnE,CAAC;CACH,GACA,OAAO,EAAE,MAAM,YAAY;EACzB,MAAM,QAA2C,CAAC;EAClD,IAAI,SAAS,KAAA,GAAW,MAAM,OAAO;EACrC,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;EACvC,OAAO,kBAAkB,KAAK;CAChC,CACF;AACF;;;ACjIA,MAAMC,aAAW,QAAQ,IAAI;AAE7B,eAAsB,kBACpB,OACA,UAAkBA,YAC2C;CAC7D,MAAM,UAAU,aAAa,OAAO;CACpC,MAAM,aAAgE,EACpE,OAAO,MAAM,SAAS,GACxB;CACA,IAAI,MAAM,SAAS,KAAA,GAAW,WAAW,OAAO,MAAM;CACtD,IAAI,MAAM,UAAU,KAAA,GAAW,WAAW,QAAQ,MAAM;CACxD,MAAM,WAAW,eAAe,SAAS,UAAU;CAEnD,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,OAAO,QAAQ;GACf,UAAU,SAAS;GACnB,SAAS;EACX,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,oBAAoB,QAAyB;CAC3D,OAAO,aACL,iBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;EASb,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,yBAAyB;GAC9D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,kCAAkC;GACxE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS,EAAE,SAAS,0BAA0B;EACxF,CAAC;CACH,GACA,OAAO,EAAE,MAAM,OAAO,YAAY;EAChC,MAAM,QAA2D,CAAC;EAClE,IAAI,SAAS,KAAA,GAAW,MAAM,OAAO;EACrC,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;EACvC,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;EACvC,OAAO,kBAAkB,KAAK;CAChC,CACF;AACF;;;AC5DA,MAAMC,aAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,cACpB,OAQA,UAAkBA,YAC2C;CAC7D,MAAM,QAAQ;EACZ,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;EAC1D,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;EACtE,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;EAC1D,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;EACnE,OAAO,MAAM,SAAS;CACxB;CAEA,MAAM,UAAU,MAAM,UAClB,cAAc,SAAS,KAAK,WACrB;EACL,MAAM,UAAU,UAAU,SAAS,KAAK;EACxC,OAAO;GAAE,UAAU,QAAQ;GAAQ;EAAQ;CAC7C,GAAG;CAEP,OAAO,EACL,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC;CAAE,CAAC,EACpE;AACF;AAEA,SAAgB,gBAAgB,QAAyB;CACvD,OAAO,aACL,YACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;;;EAab,aAAa,EAAE,OAAO;GACpB,OAAO,EAAE,KAAK;IAAC;IAAS;IAAQ;IAAQ;GAAO,CAAC,EAAE,SAAS,EAAE,SAAS,eAAe;GACrF,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,qBAAqB;GAC/D,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,2BAA2B;GACjE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0BAA0B;GACnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAI,EAAE,SAAS,EAAE,SAAS,2BAA2B;GACxF,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,8CAA8C;EACzF,CAAC;CACH,GACA,OAAO,EAAE,OAAO,WAAW,OAAO,UAAU,OAAO,cAAc;EAC/D,MAAM,QAA6C,CAAC;EACpD,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;EACvC,IAAI,cAAc,KAAA,GAAW,MAAM,YAAY;EAC/C,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;EACvC,IAAI,aAAa,KAAA,GAAW,MAAM,WAAW;EAC7C,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;EACvC,IAAI,YAAY,KAAA,GAAW,MAAM,UAAU;EAC3C,OAAO,cAAc,KAAK;CAC5B,CACF;AACF;;;ACvEA,MAAMC,aAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,eAAsB,qBACpB,OACA,UAAkBA,YAC2C;CAC7D,IAAI,UAAU;CACd,IAAI,MAAM,KAAK;EACb,MAAM,EAAE,qBAAqB,MAAM,OAAO;EAC1C,UAAU,iBAAiB,OAAO,EAAE;CACtC;CACA,MAAM,SAAS,MAAM,eAAe,OAAO;CAC3C,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,KAAK,UACT;GACE,IAAI,OAAO;GACX,GAAI,MAAM,MAAM,EAAE,kBAAkB,QAAQ,IAAI,CAAC;GACjD,QAAQ,OAAO;EACjB,GACA,MACA,CACF;CACF,CACF,EACF;AACF;AAEA,SAAgB,uBAAuB,QAAyB;CAC9D,OAAO,aACL,mBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;EASb,aAAa,EAAE,OAAO,EACpB,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,4CAA4C,EACnF,CAAC;CACH,GACA,OAAO,EAAE,UAAU,qBAAqB,QAAQ,KAAA,IAAY,EAAE,IAAI,IAAI,CAAC,CAAC,CAC1E;AACF;;;AClDA,MAAMC,aAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,SAAS,WAAW,MAAsB;CACxC,wBAAO,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAU,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE;AAC3E;AAEA,eAAsB,yBACpB,OACA,UAAkBA,YAC2C;CAC7D,MAAM,QAAQ,MAAM,SAAS,WAAW,MAAM,QAAQ,CAAC;CACvD,MAAM,OAAO,eAAe,SAAS,KAAK;CAC1C,MAAM,UAAU,OACZ,OACA,EACE,OAAO,qCAAqC,MAAM,0CACpD;CACJ,OAAO,EAAE,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,SAAS,MAAM,CAAC;CAAE,CAAC,EAAE;AAC/E;AAEA,SAAgB,2BAA2B,QAAyB;CAClE,OAAO,aACL,wBACA;EACE,OAAO;EACP,aAAa;;;;;;;;;;;EAWb,aAAa,EAAE,OAAO;GACpB,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,0BAA0B;GAChE,MAAM,EACH,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,GAAG,EACP,SAAS,EACT,SAAS,sCAAsC;EACpD,CAAC;CACH,GACA,OAAO,EAAE,OAAO,WAAW;EACzB,MAAM,QAA2C,CAAC;EAClD,IAAI,UAAU,KAAA,GAAW,MAAM,QAAQ;EACvC,IAAI,SAAS,KAAA,GAAW,MAAM,OAAO;EACrC,OAAO,yBAAyB,KAAK;CACvC,CACF;AACF;;;;;;;;AC3CA,MAAa,cAA2B;CACtC;EACE,MAAM;EACN,OAAO;EACP,aACE;EACF,QAAQ,EAAE,WACR,sCAAsC,KAAK,sCACR,KAAK;CAG5C;CACA;EACE,MAAM;EACN,OAAO;EACP,aACE;EACF,QAAQ,EAAE,WACR,yCAAyC,KAAK,gEACe,KAAK,qCACnC,KAAK;CAExC;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,QAAQ,EAAE,WACR,0CAA0C,KAAK,uCACX,KAAK,yCAAyC,KAAK;CAG3F;CACA;EACE,MAAM;EACN,OAAO;EACP,aAAa;EACb,QAAQ,EAAE,WACR,kDAAkD,KAAK;CAI3D;AACF;AAEA,SAAgB,gBAAgB,QAAyB;CACvD,KAAK,MAAM,UAAU,aACnB,OAAO,eACL,OAAO,MACP;EACE,OAAO,OAAO;EACd,aAAa,OAAO;EACpB,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,eAAe,EAAE;CAC3D,IACC,EAAE,YAAY,EACb,UAAU,CAAC;EAAE,MAAM;EAAQ,SAAS;GAAE,MAAM;GAAQ,MAAM,OAAO,MAAM,EAAE,KAAK,CAAC;EAAE;CAAE,CAAC,EACtF,EACF;AAEJ;;;ACvEA,MAAMC,aAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;;;;;;AAO9D,SAAgB,kBAAkB,QAAmB,UAAkBA,YAAgB;CACrF,OAAO,iBACL,aACA,mBACA;EACE,OAAO;EACP,aAAa;EACb,UAAU;CACZ,IACC,SAAS,EACR,UAAU,CACR;EACE,KAAK,IAAI;EACT,UAAU;EACV,MAAM,KAAK,UAAU,kBAAkB,OAAO,GAAG,MAAM,CAAC;CAC1D,CACF,EACF,EACF;CAEA,OAAO,iBACL,YACA,IAAI,iBAAiB,yBAAyB,EAAE,MAAM,KAAA,EAAU,CAAC,GACjE;EACE,OAAO;EACP,aAAa;EACb,UAAU;CACZ,GACA,OAAO,KAAK,cAAc;EACxB,MAAM,EAAE,iBAAiB,MAAM,OAAO;EACtC,MAAM,OAAO,MAAM,aAAa,SAAS,OAAO,UAAU,OAAO,CAAC;EAClE,OAAO,EAAE,UAAU,CAAC;GAAE,KAAK,IAAI;GAAM,UAAU;GAAiB;EAAK,CAAC,EAAE;CAC1E,CACF;CAEA,OAAO,iBACL,YACA,IAAI,iBAAiB,yBAAyB,EAAE,MAAM,KAAA,EAAU,CAAC,GACjE;EACE,OAAO;EACP,aAAa;EACb,UAAU;CACZ,GACA,OAAO,KAAK,cAAc;EACxB,MAAM,EAAE,iBAAiB,MAAM,OAAO;EACtC,MAAM,QAAQ,MAAM,aAAa,SAAS,OAAO,UAAU,OAAO,CAAC;EACnE,OAAO,EACL,UAAU,CACR;GAAE,KAAK,IAAI;GAAM,UAAU;GAAoB,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC;EAAE,CACtF,EACF;CACF,CACF;CAEA,OAAO,iBACL,YACA,IAAI,iBAAiB,yBAAyB,EAAE,MAAM,KAAA,EAAU,CAAC,GACjE;EACE,OAAO;EACP,aAAa;EACb,UAAU;CACZ,GACA,OAAO,KAAK,cAAc;EACxB,MAAM,EAAE,qBAAqB,MAAM,OAAO;EAC1C,MAAM,OAAO,MAAM,iBAAiB,SAAS,OAAO,UAAU,OAAO,CAAC;EACtE,OAAO,EAAE,UAAU,CAAC;GAAE,KAAK,IAAI;GAAM,UAAU;GAAiB;EAAK,CAAC,EAAE;CAC1E,CACF;AACF;;;ACnEA,MAAM,WAAW,QAAQ,IAAI,qBAAqB,QAAQ,IAAI;AAE9D,MAAM,cAAc;CAAC;CAAQ;CAAU;CAAW;CAAQ;AAAQ;AAElE,SAAS,KAAK,MAAmE;CAC/E,OAAO,EAAE,SAAS,CAAC;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC;CAAE,CAAC,EAAE;AAC5E;AAEA,SAAgB,yBACd,OAKA,UAAkB,UACkC;CACpD,YAAY,SAAS,sBAAsB;CAC3C,MAAM,UAAU,mBAAmB,SAAS;EAC1C,MAAM,MAAM;EACZ,GAAI,MAAM,QAAQ,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;EAC5C,QAAQ,MAAM;CAChB,CAAC;CACD,OAAO,KAAK;EAAE,SAAS,MAAM;EAAM,aAAa,QAAQ;CAAO,CAAC;AAClE;AAEA,SAAgB,mBACd,OACA,UAAkB,UACkC;CACpD,YAAY,SAAS,eAAe;CACpC,MAAM,MAAM,aAAa,SAAS,MAAM,QAAQ,MAAM,MAAM;CAC5D,IAAI,CAAC,IAAI,IAAI,OAAO,KAAK,EAAE,QAAQ,IAAI,UAAU,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;CAEjE,OAAY,0BAA0B,MAAM,EAAE,gBAC5C,UAAU,SAAS,kBAAkB;EAAE,QAAQ,MAAM;EAAQ,QAAQ,IAAI;CAAO,CAAC,CACnF;CACA,OAAO,KAAK,EAAE,QAAQ,IAAI,OAAO,CAAC;AACpC;AAEA,SAAgB,kBACd,OACA,UAAkB,UACkC;CACpD,OAAO,KAAK;EAAE,QAAQ,MAAM;EAAQ,SAAS,YAAY,SAAS,MAAM,MAAM;CAAE,CAAC;AACnF;AAEA,SAAgB,wBAAwB,UAAkB,UAExD;CACA,OAAO,KAAK,EAAE,SAAS,kBAAkB,OAAO,EAAE,CAAC;AACrD;AAEA,SAAgB,0BAA0B,QAAmB,UAAkB,UAAgB;CAC7F,OAAO,aACL,wBACA;EACE,aACE;EACF,aAAa,EAAE,OAAO;GACpB,MAAM,EAAE,OAAO,EAAE,SAAS,6BAA6B;GACvD,OAAO,EAAE,OAAO,EAAE,SAAS;GAC3B,QAAQ,EACL,MACC,EAAE,OAAO;IACP,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,KAAK,WAAW;IACxB,OAAO,EAAE,OAAO,EAAE,SAAS;IAC3B,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;GACxC,CAAC,CACH,EACC,SAAS,mBAAmB;EACjC,CAAC;CACH,IACC,EAAE,MAAM,OAAO,aACd,yBACE;EAAE;EAAM,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;EAAY;CAAgB,GAC7D,OACF,CACJ;CAEA,OAAO,aACL,iBACA;EACE,aACE;EACF,aAAa,EAAE,OAAO;GACpB,QAAQ,EAAE,OAAO,EAAE,SAAS,oBAAoB;GAChD,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS,0BAA0B;EAClE,CAAC;CACH,IACC,EAAE,QAAQ,aAAa,mBAAmB;EAAE;EAAQ;CAAO,GAAG,OAAO,CACxE;CAEA,OAAO,aACL,gBACA;EACE,aAAa;EACb,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;CAC7E,IACC,EAAE,aAAa,kBAAkB,EAAE,OAAO,GAAG,OAAO,CACvD;CAEA,OAAO,aACL,uBACA;EACE,aAAa;EACb,aAAa,EAAE,OAAO,CAAC,CAAC;CAC1B,SACM,wBAAwB,OAAO,CACvC;AACF;;;ACjCA,SAAgB,mBAAmB,OAAe,SAA0B;CAE1E,OAAO;;;YADO,SAAS,IAAI,OAAO,SAAS,IAAI,OAAO,KAItC;0BACQ,MAAM,eAAe,UAAU,0BAA0B,OAAO,OAAO,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,MAAM,EAAE,QAAQ,MAAM,MAAM,EAAE,UAAU,GAAG;;;AAGjM;AAEA,SAAgB,kBAA6B;CAC3C,MAAM,SAAS,IAAI,UAAU;EAC3B,MAAM;EACN,SAAS;CACX,CAAC;CAID,wBAAwB,MAAM;CAC9B,yBAAyB,MAAM;CAC/B,2BAA2B,MAAM;CACjC,gCAAgC,MAAM;CACtC,sBAAsB,MAAM;CAC5B,uBAAuB,MAAM;CAC7B,mBAAmB,MAAM;CACzB,uBAAuB,MAAM;CAC7B,4BAA4B,MAAM;CAClC,sBAAsB,MAAM;CAC5B,4BAA4B,MAAM;CAClC,yBAAyB,MAAM;CAC/B,0BAA0B,MAAM;CAChC,8BAA8B,MAAM;CACpC,6BAA6B,MAAM;CACnC,8BAA8B,MAAM;CACpC,qBAAqB,MAAM;CAC3B,2BAA2B,MAAM;CACjC,wBAAwB,MAAM;CAC9B,oBAAoB,MAAM;CAC1B,uBAAuB,MAAM;CAC7B,sBAAsB,MAAM;CAC5B,wBAAwB,MAAM;CAC9B,mBAAmB,MAAM;CACzB,sBAAsB,MAAM;CAC5B,iCAAiC,MAAM;CACvC,sBAAsB,MAAM;CAC5B,2BAA2B,MAAM;CACjC,qBAAqB,MAAM;CAC3B,6BAA6B,MAAM;CACnC,2BAA2B,MAAM;CACjC,yBAAyB,MAAM;CAC/B,mBAAmB,MAAM;CACzB,yBAAyB,MAAM;CAC/B,gCAAgC,MAAM;CACtC,6BAA6B,MAAM;CACnC,sBAAsB,MAAM;CAC5B,sBAAsB,MAAM;CAC5B,uBAAuB,MAAM;CAC7B,uBAAuB,MAAM;CAC7B,qBAAqB,MAAM;CAC3B,qBAAqB,MAAM;CAC3B,oBAAoB,MAAM;CAC1B,oBAAoB,MAAM;CAC1B,sBAAsB,MAAM;CAC5B,yBAAyB,MAAM;CAC/B,4BAA4B,MAAM;CAClC,wBAAwB,MAAM;CAC9B,kBAAkB,MAAM;CACxB,oBAAoB,MAAM;CAC1B,oBAAoB,MAAM;CAC1B,oBAAoB,MAAM;CAC1B,gBAAgB,MAAM;CACtB,uBAAuB,MAAM;CAC7B,2BAA2B,MAAM;CACjC,0BAA0B,MAAM;CAGhC,gBAAgB,MAAM;CACtB,kBAAkB,MAAM;CAExB,OAAO;AACT;AAEA,eAAsB,aAA4B;CAChD,MAAM,kBAAkB,QAAQ,IAAI,CAAC;CACrC,MAAM,SAAS,gBAAgB;CAC/B,MAAM,YAAY,IAAI,qBAAqB;CAC3C,MAAM,OAAO,QAAQ,SAAS;CAG9B,OAAO,KAAK,cAAc,mBAAmB;AAC/C;AAEA,eAAsB,UAAU,OAAO,MAAqB;CAC1D,MAAM,kBAAkB,QAAQ,IAAI,CAAC;CACrC,MAAM,EAAE,SAAS,YAAY,MAAM,OAAO;CAC1C,MAAM,MAAM,QAAQ;CACpB,IAAI,IAAI,QAAQ,KAAK,CAAC;CAEtB,MAAM,SAAS,gBAAgB;CAC/B,MAAM,UAAU,QAAQ,IAAI;CAG5B,IAAI,IAAI,0CAA0C,KAAK,QAAQ;EAC7D,MAAM,OAAO,GAAG,IAAI,SAAS,KAAK,IAAI,IAAI,MAAM,KAAK;EACrD,IAAI,KAAK,0BAA0B,GAAG,KAAK,KAAK,CAAC;CACnD,CAAC;CAED,IAAI,KAAK,QAAQ,OAAO,KAAK,QAAQ;EAGnC,IAAI,eAAe,OAAO,GAAG;GAC3B,MAAM,OAAO,aAAa,IAAI,QAAQ,kBAAkB,OAAO;GAC/D,IAAI,CAAC,KAAK,IAAI;IACZ,MAAM,OAAO,GAAG,IAAI,SAAS,KAAK,IAAI,IAAI,MAAM,KAAK;IACrD,IACG,OAAO,GAAG,EACV,IACC,oBACA,sBAAsB,GAAG,KAAK,sCAAsC,CACtE,EACC,KAAK,EAAE,OAAO,eAAe,CAAC;IACjC;GACF;GAEA,IAAI,KAAK,OAAO,QAAQ,IAAI,iBAAiB,KAAK;EACpD;EAEA,MAAM,YAAY,IAAI,8BAA8B,EAAE,oBAAoB,KAAK,CAAC;EAEhF,UAAU,gBAAgB,CAE1B;EACA,IAAI,GAAG,eAAe;GACpB,UAAe,MAAM;EACvB,CAAC;EACD,MAAM,OAAO,QAAQ,SAAiC;EACtD,MAAM,UAAU,cAAc,KAAK,KAAK,IAAI,IAA+B;CAC7E,CAAC;CAED,IAAI,IAAI,YAAY,MAAM,QAAQ;EAChC,IAAI,KAAK;GAAE,QAAQ;GAAM,QAAQ;GAAoB,SAAS;EAAQ,CAAC;CACzE,CAAC;CAED,IAAI,IAAI,aAAa,OAAO,MAAM,QAAQ;EACxC,IAAI;GACF,MAAM,EAAE,oBAAoB,MAAM,OAAO;GACzC,MAAM,WAAW,gBAAgB,OAAO;GACxC,IAAI,KAAK,EAAE,SAAS,CAAC;EACvB,QAAQ;GACN,IAAI,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC;EAC3B;CACF,CAAC;CAGD,IAAI,KAAK,mBAAmB,OAAO,KAAK,QAAQ;EAC9C,MAAM,QAAQ,QAAQ,IAAI,yBAAyB;EACnD,IAAI,CAAC,2BAA2B,IAAI,QAAQ,kBAAwC,KAAK,GAAG;GAC1F,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;GAC9C;EACF;EACA,MAAM,UAAU,yBAAyB,IAAI,IAAI;EACjD,IAAI,CAAC,SAAS;GACZ,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,kBAAkB,CAAC;GACjD;EACF;EACA,MAAM,SAAS,MAAM,qBAAqB,SAAS,SAAS,EAAE,EAAE,aAAa;GAC3E,WAAW;GACX,MAAM;EACR,EAAE;EACF,IAAI,KAAK;GAAE,IAAI;GAAM,WAAW,OAAO;EAAU,CAAC;CACpD,CAAC;CAGD,IAAI,IAAI,uBAAuB,OAAO,KAAK,QAAQ;EACjD,MAAM,aAAa,iCAAiC,IAAI,KAA+B;EACvF,IAAI,WAAW,cAAc;GAC3B,IAAI,UAAU,gBAAgB,YAAY;GAC1C,IAAI,OAAO,GAAG,EAAE,KAAK,WAAW,KAAK;GACrC;EACF;EACA,MAAM,cAAc,QAAQ,IAAI,4BAA4B;EAC5D,MAAM,OAAO,IAAI;EACjB,IAAI,CAAC,8BAA8B,MAAM,WAAW,GAAG;GACrD,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;GAC9C;EACF;EACA,MAAM,SAAS,MAAM,yBAAyB,SAAS,KAAK,SAAS,CAAC,GAAG,EAAE,EAAE,aAAa;GACxF,WAAW;GACX,SAAS;EACX,EAAE;EACF,IAAI,KAAK;GAAE,IAAI;GAAM,GAAG;EAAO,CAAC;CAClC,CAAC;CAGD,IAAI,KAAK,mBAAmB,QAAQ,KAAK,EAAE,MAAM,MAAM,CAAC,GAAG,OAAO,KAAK,QAAQ;EAC7E,MAAM,UAAU,IAAI;EACpB,MAAM,gBAAgB,QAAQ,IAAI,2BAA2B;EAC7D,IACE,CAAC,qBACC,SACA,IAAI,SACJ,aACF,GACA;GACA,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;GAC9C;EACF;EACA,IAAI;EACJ,IAAI;GACF,SAAS,KAAK,MAAM,OAAO;EAC7B,QAAQ;GACN,IAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;GAC9C;EACF;EACA,MAAM,eAAe,2BAA2B,MAAM;EACtD,IAAI,aAAa,gBAAgB;GAC/B,IAAI,KAAK,EAAE,WAAW,aAAa,UAAU,CAAC;GAC9C;EACF;EACA,IAAI,CAAC,OAAO,OAAO;GACjB,IAAI,KAAK;IAAE,IAAI;IAAM,WAAW;GAAE,CAAC;GACnC;EACF;EACA,MAAM,WAAW,QAAQ,IAAI,sBAAsB;EACnD,MAAM,SAAS,MAAM,qBAAqB,SAAS,OAAO,OAAO,UAAU,EACzE,GAAI,OAAO,YAAY,KAAA,IAAY,EAAE,QAAQ,OAAO,QAAQ,IAAI,CAAC,EACnE,CAAC,EAAE,aAAa;GAAE,WAAW;GAAG,SAAS;EAAE,EAAE;EAC7C,IAAI,KAAK;GAAE,IAAI;GAAM,GAAG;EAAO,CAAC;CAClC,CAAC;CAMD,IAAI,IAAI,mBAAmB,OAAO,KAAK,QAAQ;EAC7C,MAAM,EAAE,OAAO,OAAO,YAAY,IAAI;EACtC,IAAI,CAAC,OAAO;GACV,IAAI,OAAO,GAAG,EAAE,KAAK,+BAA+B;GACpD;EACF;EAEA,IAAI,YAAY,QAAQ;GACtB,IAAI,UAAU,gBAAgB,WAAW;GACzC,IAAI,KAAK;;;;;;;2CAO4B,OAAO,KAAK,EAAE,QAAQ,MAAM,OAAO,EAAE,QAAQ,MAAM,QAAQ,EAAE,QAAQ,MAAM,MAAM,EAAE;;;;sBAIxG;GAChB;EACF;EAEA,MAAM,WAAW,UAAU,KAAA,IAAY,SAAS,OAAO,EAAE,IAAI;EAC7D,IAAI,MAAM,QAAQ,KAAK,WAAW,KAAK,WAAW,IAAI;GACpD,IAAI,OAAO,GAAG,EAAE,KAAK,8DAA8D;GACnF;EACF;EAEA,MAAM,EAAE,yBAAyB,MAAM,OAAO;EAC9C,MAAM,qBAAqB,SAAS,OAAO,QAAQ,EAAE,YAAY,IAAI;EACrE,IAAI,UAAU,gBAAgB,WAAW;EACzC,IAAI,KAAK,mBAAmB,QAAQ,CAAC;CACvC,CAAC;CAED,IAAI,KAAK,mBAAmB,QAAQ,WAAW,EAAE,UAAU,MAAM,CAAC,GAAG,OAAO,KAAK,QAAQ;EACvF,MAAM,EAAE,OAAO,OAAO,SAAS,gBAAgB,IAAI;EACnD,IAAI,CAAC,OAAO;GACV,IAAI,OAAO,GAAG,EAAE,KAAK,+BAA+B;GACpD;EACF;EACA,MAAM,WAAW,UAAU,KAAA,IAAY,SAAS,OAAO,EAAE,IAAI;EAC7D,IAAI,MAAM,QAAQ,KAAK,WAAW,KAAK,WAAW,IAAI;GACpD,IACG,OAAO,GAAG,EACV,KAAK,6EAA6E;GACrF;EACF;EACA,MAAM,EAAE,yBAAyB,MAAM,OAAO;EAC9C,MAAM,qBAAqB,SAAS,OAAO,UAAU,eAAe,KAAA,CAAS,EAAE,YACvE,IACR;EACA,IAAI,UAAU,gBAAgB,WAAW;EACzC,IAAI,KAAK,mBAAmB,UAAU,WAAW,CAAC;CACpD,CAAC;CAED,IAAI,OAAO,YAAY;EACrB,OAAO,KAAK,cAAc,qBAAqB,EAAE,KAAK,kBAAkB,KAAK,MAAM,CAAC;CACtF,CAAC;AACH;AAIA,KADa,QAAQ,IAAI,qBAAqB,aACjC,QAEX,UADa,SAAS,QAAQ,IAAI,qBAAqB,QAAQ,EAClD,CAAC,EAAE,OAAO,QAAiB;CACtC,OAAO,MAAM,cAAc,eAAe,EAAE,OAAQ,IAAc,QAAQ,CAAC;CAC3E,QAAQ,KAAK,CAAC;AAChB,CAAC;KAED,WAAW,EAAE,OAAO,QAAiB;CACnC,OAAO,MAAM,cAAc,eAAe,EAAE,OAAQ,IAAc,QAAQ,CAAC;CAC3E,QAAQ,KAAK,CAAC;AAChB,CAAC"}