@flamingo-stack/openframe-frontend-core 0.0.210-snapshot.20260528032637 → 0.0.210

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/{chunk-P5EE2VJX.cjs → chunk-6RZYJICV.cjs} +1 -1
  2. package/dist/chunk-6RZYJICV.cjs.map +1 -0
  3. package/dist/{chunk-ZG2YY5E7.js → chunk-7L4DWM7P.js} +1 -1
  4. package/dist/chunk-7L4DWM7P.js.map +1 -0
  5. package/dist/{chunk-QKFBZLIR.js → chunk-ATEUJQKU.js} +2 -2
  6. package/dist/{chunk-VTUIMMHO.cjs → chunk-MDTIOPVS.cjs} +24 -24
  7. package/dist/{chunk-VTUIMMHO.cjs.map → chunk-MDTIOPVS.cjs.map} +1 -1
  8. package/dist/{chunk-3E5ANY55.js → chunk-R5RNRH62.js} +5 -14
  9. package/dist/chunk-R5RNRH62.js.map +1 -0
  10. package/dist/{chunk-WI76ZUBE.cjs → chunk-TWKPYZNQ.cjs} +17 -26
  11. package/dist/chunk-TWKPYZNQ.cjs.map +1 -0
  12. package/dist/{chunk-ZFBLC5GV.cjs → chunk-VBFOCTMD.cjs} +17 -17
  13. package/dist/{chunk-ZFBLC5GV.cjs.map → chunk-VBFOCTMD.cjs.map} +1 -1
  14. package/dist/{chunk-5BNWGK6D.js → chunk-WJBPLMBX.js} +2 -2
  15. package/dist/components/chat/hooks/use-chat-identity.d.ts +3 -3
  16. package/dist/components/chat/hooks/use-chat-identity.d.ts.map +1 -1
  17. package/dist/components/chat/index.cjs +3 -3
  18. package/dist/components/chat/index.js +2 -2
  19. package/dist/components/contact/index.cjs +4 -4
  20. package/dist/components/contact/index.js +3 -3
  21. package/dist/components/features/index.cjs +3 -3
  22. package/dist/components/features/index.js +2 -2
  23. package/dist/components/footer-waitlist-button.d.ts +2 -21
  24. package/dist/components/footer-waitlist-button.d.ts.map +1 -1
  25. package/dist/components/index.cjs +91 -87
  26. package/dist/components/index.cjs.map +1 -1
  27. package/dist/components/index.js +16 -12
  28. package/dist/components/index.js.map +1 -1
  29. package/dist/components/navigation/index.cjs +3 -3
  30. package/dist/components/navigation/index.js +2 -2
  31. package/dist/components/navigation/sticky-section-nav.d.ts.map +1 -1
  32. package/dist/components/tickets/help-center-card.d.ts.map +1 -1
  33. package/dist/components/tickets/index.cjs +98 -139
  34. package/dist/components/tickets/index.cjs.map +1 -1
  35. package/dist/components/tickets/index.js +54 -95
  36. package/dist/components/tickets/index.js.map +1 -1
  37. package/dist/components/tickets/ticket-row.d.ts.map +1 -1
  38. package/dist/components/ui/index.cjs +3 -3
  39. package/dist/components/ui/index.js +2 -2
  40. package/dist/contexts/chat-runtime-context.d.ts +3 -6
  41. package/dist/contexts/chat-runtime-context.d.ts.map +1 -1
  42. package/dist/contexts/index.cjs +2 -2
  43. package/dist/contexts/index.js +1 -1
  44. package/dist/index.cjs +3 -5
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.js +2 -4
  47. package/dist/utils/index.cjs +0 -10
  48. package/dist/utils/index.cjs.map +1 -1
  49. package/dist/utils/index.d.ts +0 -1
  50. package/dist/utils/index.d.ts.map +1 -1
  51. package/dist/utils/index.js +1 -10
  52. package/dist/utils/index.js.map +1 -1
  53. package/package.json +1 -1
  54. package/src/components/chat/hooks/use-chat-identity.ts +7 -8
  55. package/src/components/footer-waitlist-button.tsx +16 -33
  56. package/src/components/navigation/sticky-section-nav.tsx +4 -6
  57. package/src/components/tickets/help-center-card.tsx +1 -55
  58. package/src/components/tickets/help-center-list.tsx +1 -9
  59. package/src/components/tickets/ticket-detail-drawer.tsx +4 -19
  60. package/src/components/tickets/ticket-row.tsx +19 -30
  61. package/src/contexts/chat-runtime-context.tsx +3 -6
  62. package/src/stories/EmbeddableChat.stories.tsx +1 -1
  63. package/src/utils/index.ts +0 -12
  64. package/dist/chunk-3E5ANY55.js.map +0 -1
  65. package/dist/chunk-P5EE2VJX.cjs.map +0 -1
  66. package/dist/chunk-WI76ZUBE.cjs.map +0 -1
  67. package/dist/chunk-ZG2YY5E7.js.map +0 -1
  68. package/dist/utils/scroll-into-view.d.ts +0 -63
  69. package/dist/utils/scroll-into-view.d.ts.map +0 -1
  70. package/src/utils/scroll-into-view.ts +0 -74
  71. /package/dist/{chunk-QKFBZLIR.js.map → chunk-ATEUJQKU.js.map} +0 -0
  72. /package/dist/{chunk-5BNWGK6D.js.map → chunk-WJBPLMBX.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/cn.ts","../../src/utils/format.ts","../../src/components/icons-v2-generated/media-playback/play-icon.tsx","../../src/utils/ods-color-utils.ts","../../src/utils/common.ts","../../src/components/icons/openmsp-logo.tsx","../../src/components/icons/openframe-logo.tsx","../../src/components/icons/flamingo-logo.tsx","../../src/components/icons/miami-cyber-gang-logo-face-only.tsx","../../src/components/icons/shell-icon.tsx","../../src/components/icons/github-icon.tsx","../../src/components/icons/slack-icon.tsx","../../src/components/icons/clickup-icon.tsx","../../src/components/icons/x-logo.tsx","../../src/components/icons/hubspot-icon.tsx","../../src/components/icons/linkedin-icon.tsx","../../src/components/icons/youtube-icon.tsx","../../src/components/icons/instagram-icon.tsx","../../src/components/icons/facebook-icon.tsx","../../src/components/icons/windows-icon.tsx","../../src/components/icons/macos-icon.tsx","../../src/components/icons/linux-icon.tsx","../../src/components/icons/cmd-icon.tsx","../../src/components/icons/bash-icon.tsx","../../src/components/icons/nushell-icon.tsx","../../src/components/icons/deno-icon.tsx","../../src/utils/platform-config.tsx","../../src/utils/os-platforms.ts","../../src/utils/access-code-client.ts","../../src/utils/validation-utils.ts","../../src/utils/confidence-helpers.ts","../../src/utils/date-formatters.ts","../../src/components/chat/utils/icon-registry.ts","../../src/types/tool.types.ts","../../src/utils/tool-utils.ts","../../src/components/icons-v2-generated/brand-logos/powershell-logo-icon.tsx","../../src/components/icons-v2-generated/brand-logos/python-logo-icon.tsx","../../src/types/shell.types.ts","../../src/utils/shell-utils.ts","../../src/components/icons-v2-generated/brand-logos/apple-logo-icon.tsx","../../src/components/icons-v2-generated/brand-logos/linux-logo-icon.tsx","../../src/components/icons-v2-generated/brand-logos/windows-logo-grey-icon.tsx","../../src/types/os.types.ts","../../src/utils/os-utils.ts","../../src/utils/country-phone-utils.ts","../../src/utils/generic-domain-utils.ts","../../src/utils/color-analysis.ts","../../src/utils/image-proxy.ts","../../src/utils/date-utils.ts","../../src/utils/source-icons.ts","../../src/utils/local-storage-adapter.ts","../../src/utils/app-config.ts","../../src/utils/embed-proxy-auth-storage.ts","../../src/utils/embed-authed-fetch.ts","../../src/utils/sse-decision-frame.ts","../../src/components/chat/utils/chat-attachment-markdown.ts","../../src/components/chat/utils/auto-continuation-directive.ts","../../src/components/chat/utils/flatten-assistant-content.ts","../../src/components/chat/types/message.types.ts","../../src/components/chat/utils/scroll-anchor.ts","../../src/components/chat/utils/slash-dispatch-utils.ts","../../src/components/chat/utils/clickup-task-type-utils.ts","../../src/components/chat/utils/agent-status-message.ts","../../src/components/chat/utils/external-app-urls.ts","../../src/components/chat/utils/is-cross-origin-url.ts","../../src/utils/fetch-priority.ts","../../src/types/product-release.ts","../../src/utils/dev-sections/openframe-dev-sections.ts","../../src/utils/scroll-into-view.ts"],"names":["platformColors","jsx","jsxs","Globe","Bell","Info","Megaphone","Package","Rocket","Star","b","React","MapIcon","GraduationCap"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { extendTailwindMerge } from \"tailwind-merge\"\n\nconst twMerge = extendTailwindMerge<'ods-typography'>({\n extend: {\n classGroups: {\n 'ods-typography': ['text-h1', 'text-h2', 'text-h3', 'text-h4', 'text-h5', 'text-h6'],\n },\n },\n})\n\n/**\n * Combine class names with Tailwind's merge utility\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n/**\n * Platform URL mappings for production (with environment variable overrides)\n */\nexport function getPlatformProductionUrl(platform: string): string {\n switch (platform) {\n // *-hub platforms — env var convention: NEXT_PUBLIC_<NAME>_HUB_URL\n case 'marketing-hub':\n return process.env.NEXT_PUBLIC_MARKETING_HUB_URL || 'https://marketing-hub.flamingo.so';\n case 'company-hub':\n return process.env.NEXT_PUBLIC_COMPANY_HUB_URL || 'https://company-hub.flamingo.so';\n case 'product-hub':\n return process.env.NEXT_PUBLIC_PRODUCT_HUB_URL || 'https://product-hub.flamingo.so';\n case 'revenue-hub':\n return process.env.NEXT_PUBLIC_REVENUE_HUB_URL || 'https://revenue-hub.flamingo.so';\n case 'people-hub':\n return process.env.NEXT_PUBLIC_PEOPLE_HUB_URL || 'https://people-hub.flamingo.so';\n // Standalone platforms — env var convention: NEXT_PUBLIC_<NAME>_URL\n case 'openmsp':\n return process.env.NEXT_PUBLIC_OPENMSP_URL || 'https://www.openmsp.ai';\n case 'flamingo':\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n case 'tmcg':\n return process.env.NEXT_PUBLIC_TMCG_URL || 'https://www.tmcg.miami';\n case 'flamingo-teaser':\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n case 'openframe':\n return process.env.NEXT_PUBLIC_OPENFRAME_URL || 'https://openframe.ai';\n case 'universal':\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n default:\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n }\n}\n\n/**\n * Get ALL unique base domains from getPlatformProductionUrl\n *\n * Extracts domains by calling getPlatformProductionUrl for each platform identifier.\n * Platform identifiers match the switch cases in getPlatformProductionUrl.\n *\n * Handles 3 cases:\n * 1. LOCALHOST DEBUG - No domain (hostname-specific cookies)\n * 2. VERCEL PREVIEW (*.vercel.app) - Use vercel.app domain\n * 3. PRODUCTION - Extract from ALL platform URLs via getPlatformProductionUrl\n *\n * @returns Array of all unique base domains (with and without wildcard)\n */\nexport function getAllPlatformBaseDomains(): string[] {\n if (typeof window === 'undefined') return []\n\n const hostname = window.location.hostname\n\n // Case 1: LOCALHOST DEBUG - no domains needed\n if (hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname.startsWith('127.')) {\n return []\n }\n\n // Case 2: VERCEL PREVIEW - use vercel.app domain\n const isVercelPreview = process.env.VERCEL_ENV === 'preview' ||\n process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' ||\n hostname.includes('.vercel.app')\n\n if (isVercelPreview) {\n return ['.vercel.app', 'vercel.app']\n }\n\n // Case 3: PRODUCTION - extract from ALL platforms using getPlatformProductionUrl\n // Platform identifiers MUST match switch cases in getPlatformProductionUrl —\n // otherwise the corresponding domain is omitted from cookie scope.\n const platformIdentifiers = [\n 'marketing-hub', 'company-hub', 'product-hub', 'revenue-hub', 'people-hub',\n 'openmsp', 'flamingo', 'tmcg', 'flamingo-teaser', 'openframe', 'universal'\n ]\n\n const baseDomains = new Set<string>()\n\n platformIdentifiers.forEach(platform => {\n try {\n const url = getPlatformProductionUrl(platform)\n const urlHostname = new URL(url).hostname\n const parts = urlHostname.split('.')\n\n if (parts.length >= 2) {\n const baseDomain = parts.slice(-2).join('.')\n baseDomains.add(`.${baseDomain}`) // Wildcard\n baseDomains.add(baseDomain) // Non-wildcard\n }\n } catch (error) {\n console.warn('[Platform Domains] Failed to parse URL for platform:', platform, error)\n }\n })\n\n return Array.from(baseDomains)\n}\n\n/**\n * Get the application base URL for the current environment\n *\n * @param platform - Optional platform name (openmsp, flamingo, tmcg, openframe, etc.)\n * @returns The base URL with protocol (https:// or http://)\n *\n * Priority order:\n * 1. Environment variable override (NEXT_PUBLIC_*_URL)\n * 2. Platform-specific URL (if platform parameter provided)\n * 3. VERCEL_PROJECT_PRODUCTION_URL (Vercel production domain)\n * 4. Production fallback (current app or openmsp)\n * 5. Development (http://localhost:3000)\n *\n * Environment Variables (optional overrides — only set when production domain\n * differs from the hardcoded default):\n *\n * Hub deployments (NEXT_PUBLIC_<NAME>_HUB_URL):\n * - NEXT_PUBLIC_MARKETING_HUB_URL -> marketing-hub.flamingo.so\n * - NEXT_PUBLIC_COMPANY_HUB_URL -> company-hub.flamingo.so\n * - NEXT_PUBLIC_PRODUCT_HUB_URL -> product-hub.flamingo.so\n * - NEXT_PUBLIC_REVENUE_HUB_URL -> revenue-hub.flamingo.so\n * - NEXT_PUBLIC_PEOPLE_HUB_URL -> people-hub.flamingo.so\n *\n * Standalone platforms (NEXT_PUBLIC_<NAME>_URL):\n * - NEXT_PUBLIC_OPENMSP_URL -> www.openmsp.ai\n * - NEXT_PUBLIC_FLAMINGO_URL -> www.flamingo.run\n * - NEXT_PUBLIC_TMCG_URL -> www.tmcg.miami\n * - NEXT_PUBLIC_FLAMINGO_TEASER_URL -> www.flamingo.cx\n * - NEXT_PUBLIC_OPENFRAME_URL -> openframe.ai\n *\n * @example\n * getBaseUrl() // Current app URL\n * getBaseUrl('flamingo') // https://www.flamingo.run (production) or http://localhost:3000 (dev)\n * getBaseUrl('openmsp') // https://www.openmsp.ai (or NEXT_PUBLIC_OPENMSP_URL if set)\n */\nexport function getBaseUrl(platform?: string): string {\n // In development, always use localhost (regardless of platform)\n if (process.env.NODE_ENV !== 'production') {\n return process.env.NEXT_PUBLIC_DEV_URL || 'http://localhost:3000'\n }\n\n // If platform is specified, return its production URL with env variable override support\n if (platform) {\n return getPlatformProductionUrl(platform)\n }\n\n // Production: Use Vercel domain if available\n if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {\n return `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`\n }\n\n // Production fallback: Use canonical www domain to avoid Google \"Page with redirect\" issue.\n // openmsp.ai redirects to www.openmsp.ai, so we set the base URL to the\n // final destination to ensure canonical URLs do not require a redirect.\n return 'https://www.openmsp.ai'\n}\n","/**\n * Utility functions for formatting data\n */\n\n/**\n * Format a date to a human-readable string\n * @param date - The date to format (Date object or ISO string)\n * @param options - Formatting options\n * @returns Formatted date string\n */\nexport function formatDate(\n date: Date | string,\n options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n },\n): string {\n const dateObj = typeof date === \"string\" ? new Date(date) : date\n \n // Check if the date is valid\n if (isNaN(dateObj.getTime())) {\n console.warn(\"Invalid date provided to formatDate:\", date)\n return \"Invalid Date\"\n }\n \n return dateObj.toLocaleDateString(\"en-US\", options)\n}\n\n/**\n * Format a number with thousands separators\n * @param num - The number to format\n * @returns Formatted number string\n */\nexport function formatNumber(num: number): string {\n return num.toLocaleString()\n}\n\n/**\n * Format a price with currency symbol\n * @param price - The price to format\n * @param currency - The currency code\n * @returns Formatted price string\n */\nexport function formatPrice(price: number, currency = \"USD\"): string {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency,\n }).format(price)\n}\n\n/**\n * Format bytes to a human-readable string (KB, MB, GB, etc.)\n * @param bytes - The number of bytes\n * @param decimals - Number of decimal places\n * @returns Formatted bytes string\n */\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) return \"0 Bytes\"\n\n const k = 1024\n const dm = decimals < 0 ? 0 : decimals\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"]\n\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n\n return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + \" \" + sizes[i]\n}\n\n/**\n * Compact bytes formatter using the single-letter unit `'B'` (not\n * `'Bytes'`). Used by upload-progress UIs where horizontal space is\n * tight and the longer \"Bytes\" string wraps. Tops out at `TB`.\n * @example formatBytesShort(0) → \"0 B\"; formatBytesShort(1536) → \"1.5 KB\"\n */\nexport function formatBytesShort(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n\n/**\n * Format large numbers to abbreviated form (K, M, B) with no decimal points\n * @param num - The number to format\n * @returns Formatted number string (e.g., \"1K\", \"2M\", \"3B\")\n */\nexport function formatLargeNumber(num: number): string {\n if (num === 0) return \"0\"\n \n // Handle negative numbers\n const isNegative = num < 0\n const absNum = Math.abs(num)\n \n let result: string\n \n if (absNum >= 1_000_000_000) {\n // Billions\n result = `${Math.floor(absNum / 1_000_000_000)}B`\n } else if (absNum >= 1_000_000) {\n // Millions\n result = `${Math.floor(absNum / 1_000_000)}M`\n } else if (absNum >= 1_000) {\n // Thousands\n result = `${Math.floor(absNum / 1_000)}K`\n } else {\n // Less than 1000, show as-is\n result = Math.floor(absNum).toString()\n }\n \n return isNegative ? `-${result}` : result\n}\n\n/**\n * Abbreviate large numbers for compact display.\n * 1 200 → 1.2K , 15 000 → 15K , 2 000 000 → 2M\n * @param n Number to format\n */\nexport function formatAbbreviatedNumber(n: number): string {\n if (n >= 1_000_000_000) {\n const value = n / 1_000_000_000;\n return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}B`;\n }\n if (n >= 1_000_000) {\n const value = n / 1_000_000;\n return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}M`;\n }\n if (n >= 1_000) {\n const value = n / 1_000;\n return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}K`;\n }\n return n.toLocaleString();\n}\n\n/**\n * Two-letter uppercase initials from the FIRST + LAST word of a name.\n * Used by avatar-style fallbacks (SquareAvatar, EntityImage) where\n * \"John Michael Doe\" → \"JD\" reads better than \"JM\".\n *\n * Returns `''` for empty / whitespace-only input. Single-word names\n * return a single uppercase letter. Pure — same input always produces\n * the same output, no locale or timezone surface.\n */\nexport function getFirstLastInitials(name?: string | null): string {\n if (!name) return ''\n const words = name.trim().split(/\\s+/)\n if (words.length === 0 || !words[0]) return ''\n if (words.length === 1) return words[0].charAt(0).toUpperCase()\n return (words[0].charAt(0) + words[words.length - 1].charAt(0)).toUpperCase()\n}\n\n/**\n * Two-letter uppercase initials from the FIRST + SECOND word of a name.\n * Used as SquareAvatar / EntityImage / EntityAuthorCard fallback across\n * admin and public pages in both the lib and the hub. Handles empty\n * strings, all-whitespace input, and single-word names cleanly — always\n * returns at least one character so the fallback slot is never empty.\n *\n * Single source of truth: every \"first-letter of each word, uppercase,\n * max 2 chars\" computation across hub + lib MUST come through here.\n */\nexport function nameInitials(\n name: string | null | undefined,\n fallback: string = 'E',\n): string {\n const source = typeof name === 'string' ? name.trim() : ''\n const words = source.length > 0 ? source.split(/\\s+/) : []\n const letters = words\n .map((w) => w[0])\n .filter(Boolean)\n .slice(0, 2)\n .join('')\n return (letters || fallback).toUpperCase()\n}\n\n/**\n * Format seconds to MM:SS or HH:MM:SS format\n * Used for media durations (podcasts, videos)\n * Returns: \"MM:SS\" or \"HH:MM:SS\" if hours > 0\n */\nexport function formatDurationMMSS(seconds: number | null | undefined): string {\n if (!seconds) return '';\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const secs = Math.floor(seconds % 60);\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }\n return `${minutes}:${secs.toString().padStart(2, '0')}`;\n}\n\n/**\n * Format seconds to compact human-readable duration\n * Used for displaying duration in cards and headers\n * Returns: \"Xh Xm\" or \"X min\"\n */\nexport function formatDurationCompact(seconds: number | null | undefined): string {\n if (!seconds) return '';\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n if (hours > 0) {\n return `${hours}h ${minutes}m`;\n }\n return `${minutes} min`;\n}\n\n/**\n * Format time with optional timezone\n * Used for webinar and event times\n * Returns: \"10:30 AM EST\" or \"10:30 AM\"\n */\nexport function formatTimeWithTimezone(\n date: Date | string | null | undefined,\n timezone?: string | null\n): string {\n if (!date) return '';\n\n const dateObj = typeof date === 'string' ? new Date(date) : date;\n const timeStr = dateObj.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n\n return timezone ? `${timeStr} ${timezone}` : timeStr;\n}\n\n/**\n * Calculate and format duration between two timestamps\n * Used for webinar durations\n * Returns: \"1h 30m\" or \"45m\"\n */\nexport function formatDurationFromRange(\n startAt: string | Date | null | undefined,\n endAt: string | Date | null | undefined\n): string {\n if (!startAt || !endAt) return '';\n\n const start = typeof startAt === 'string' ? new Date(startAt) : startAt;\n const end = typeof endAt === 'string' ? new Date(endAt) : endAt;\n const durationMs = end.getTime() - start.getTime();\n const minutes = Math.round(durationMs / 60000);\n\n if (minutes >= 60) {\n const hours = Math.floor(minutes / 60);\n const mins = minutes % 60;\n return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;\n }\n return `${minutes}m`;\n}\n\n/**\n * UTC-anchored date formatter — distinct from the local-rendering\n * `formatDate` above. RAG mappers + audit-style consumers want UTC anchor\n * so date-only strings (`'2024-08-15'`) don't drift across timezones, AND\n * a `'N/A'` (or caller-supplied) fallback for missing values so the LLM\n * never sees a blank.\n *\n * Accepts:\n * - ISO date or timestamp string (`'2024-08-15'` or `'2024-08-15T10:30:00Z'`)\n * - Numeric epoch milliseconds\n * - Numeric string (treated as epoch ms — Slack and GitHub timestamps\n * sometimes arrive that way)\n * - `null` / `undefined` / empty / unparseable → returns `options.fallback`\n *\n * Date-only strings (no `'T'`) get `T00:00:00Z` appended so they anchor to\n * UTC midnight rather than midnight in the runtime's local timezone.\n */\nexport interface FormatDateUTCOptions {\n /** Returned for null/undefined/empty/unparseable input. Defaults to 'N/A'. */\n fallback?: string\n /** 'UTC' (default) or 'local' — switch off the UTC anchor when audit\n * stability matters less than local relevance (chat-card timestamps). */\n timezone?: 'UTC' | 'local'\n}\n\nexport function formatDateUTC(\n value: string | number | null | undefined,\n options: FormatDateUTCOptions = {},\n): string {\n const { fallback = 'N/A', timezone = 'UTC' } = options\n\n if (value === null || value === undefined || value === '') return fallback\n\n let ms: number\n if (typeof value === 'number') {\n ms = value\n } else {\n // String input — first try to interpret as a numeric epoch (Slack/GitHub\n // sometimes arrive that way). Number('') is 0, but we already ruled out\n // empty strings above.\n const n = Number(value)\n if (Number.isFinite(n) && n > 0 && /^-?\\d+(\\.\\d+)?$/.test(value.trim())) {\n ms = n\n } else {\n // ISO string — for date-only forms, anchor to UTC midnight to avoid\n // timezone-offset drift (preserves the original RAG-mapper contract).\n ms = Date.parse(value.includes('T') ? value : value + 'T00:00:00Z')\n }\n }\n\n if (!Number.isFinite(ms)) return fallback\n\n return new Date(ms).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n timeZone: timezone === 'local' ? undefined : 'UTC',\n })\n}\n\n/**\n * Format a date string as `MM/DD/YYYY` for legal-document display\n * (privacy policy, terms of service). Locale-stable: always en-US.\n */\nexport function formatLegalDate(dateInput: string): string {\n return new Intl.DateTimeFormat('en-US', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n }).format(new Date(dateInput))\n}\n\n/**\n * Format a currency value as `$1,234`. Returns `'N/A'` for null/undefined.\n * USD-rounded (no cents). Used on KPI cards + investor pages.\n */\nexport function formatCurrency(value: number | null | undefined): string {\n if (value == null) return 'N/A'\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n maximumFractionDigits: 0,\n }).format(value)\n}\n\n/**\n * Format a percent value as `12.50%`. Returns `'N/A'` for null/undefined.\n */\nexport function formatPercent(value: number | null | undefined): string {\n if (value == null) return 'N/A'\n return `${value.toFixed(2)}%`\n}\n\n/**\n * Whole-dollar price (no cents) — `$1,234`. Configurable currency code.\n */\nexport function formatWholeDollars(price: number, currency = 'USD'): string {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n maximumFractionDigits: 0,\n }).format(price)\n}\n\n// =============================================================================\n// Metric Formatting (for KPI cards / investor updates)\n// =============================================================================\n\nexport type MetricFormat = 'number' | 'currency' | 'percentage' | 'months'\n\n/**\n * Polarity determines whether an increase is good or bad.\n * - 'positive': higher is better (revenue, users, MRR) → up = green, down = red\n * - 'negative': higher is worse (burn rate, churn, CAC) → up = red, down = green\n * - 'neutral': no judgment (headcount, runway) → always gray\n */\nexport type TrendPolarity = 'positive' | 'negative' | 'neutral'\n\n/**\n * Format a metric value with compact notation ($1.2M, 150K, 12 months).\n */\nexport function formatCompactMetric(\n value: number,\n format: MetricFormat = 'number',\n options?: { prefix?: string; suffix?: string },\n): string {\n if (value === 0 || value === null || value === undefined) {\n if (format === 'currency') return `${options?.prefix || '$'}0`\n if (format === 'percentage') return '0%'\n if (format === 'months') return `0 ${options?.suffix || 'months'}`\n return '0'\n }\n\n const absValue = Math.abs(value)\n const sign = value < 0 ? '-' : ''\n\n if (format === 'currency') {\n const prefix = options?.prefix || '$'\n const compact = (val: number, divisor: number, suffix: string) => {\n const divided = val / divisor\n const formatted = divided % 1 === 0 ? divided.toFixed(0) : divided.toFixed(1)\n return `${sign}${prefix}${formatted}${suffix}`\n }\n if (absValue >= 1_000_000_000) return compact(absValue, 1_000_000_000, 'B')\n if (absValue >= 1_000_000) return compact(absValue, 1_000_000, 'M')\n if (absValue >= 1_000) return `${sign}${prefix}${(absValue / 1_000).toFixed(0)}K`\n return `${sign}${prefix}${absValue.toLocaleString()}`\n }\n\n if (format === 'percentage') {\n return `${sign}${absValue}%`\n }\n\n if (format === 'months') {\n const rounded = Math.round(value * 10) / 10\n return `${rounded} ${options?.suffix || 'months'}`\n }\n\n if (absValue >= 1_000_000) return `${sign}${(absValue / 1_000_000).toFixed(1)}M`\n if (absValue >= 1_000) return `${sign}${(absValue / 1_000).toFixed(1)}K`\n return value.toLocaleString()\n}\n\n/**\n * Get ODS trend colors based on direction AND polarity. Single source\n * of truth for trend coloring across hub + lib.\n */\nexport function getTrendColors(\n direction: 'up' | 'down' | 'neutral',\n polarity: TrendPolarity = 'positive',\n): { textClass: string; badgeClass: string } {\n if (direction === 'neutral' || polarity === 'neutral') {\n return {\n textClass: 'text-ods-text-secondary',\n badgeClass: 'bg-ods-border text-ods-text-secondary',\n }\n }\n\n const isPositiveOutcome =\n (direction === 'up' && polarity === 'positive') ||\n (direction === 'down' && polarity === 'negative')\n\n if (isPositiveOutcome) {\n return {\n textClass: 'text-ods-success',\n badgeClass: 'bg-ods-success-secondary text-ods-success',\n }\n }\n\n return {\n textClass: 'text-ods-error',\n badgeClass: 'bg-ods-error-secondary text-ods-error',\n }\n}\n\n/**\n * Format a date range as `Apr 20, 2026 — Jul 20, 2026`. Used on review\n * cycle list/detail rows and summary headers.\n *\n * Accepts either full ISO timestamps or bare `YYYY-MM-DD` dates. Bare\n * dates are interpreted in the viewer's LOCAL timezone — otherwise\n * `\"2026-04-20\"` renders as `\"Apr 19\"` west of UTC. DB values for cycle\n * period are stored as plain dates, so local-tz parsing is correct.\n */\nexport function formatDateRange(\n start: string | null | undefined,\n end: string | null | undefined,\n): string {\n if (!start || !end) return ''\n const fmt = (s: string): string => {\n const bareMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(s)\n const d = bareMatch\n ? new Date(Number(bareMatch[1]), Number(bareMatch[2]) - 1, Number(bareMatch[3]))\n : new Date(s)\n if (Number.isNaN(d.getTime())) return s\n return d.toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })\n }\n return `${fmt(start)} — ${fmt(end)}`\n}\n\n/**\n * Format an ISO date string as `\"Jan 5, 2025 at 10:30 AM\"`. Used by\n * admin podcast/webinar cards where the display needs both the short\n * date AND wall-clock time in a single readable phrase.\n *\n * Uses `new Date(...).toLocale*` (NOT the TZ-safe split) because the\n * source columns store full timestamps + the wall-clock half MUST\n * render in the viewer's local timezone (a podcast scheduled \"10:30 AM\n * EST\" should display \"10:30 AM\" for the Eastern admin, \"7:30 AM\" for\n * the Pacific admin — viewer-local is the right semantics here, unlike\n * date-only fields).\n */\nexport function formatDateTimeAt(dateString: string): string {\n const date = new Date(dateString)\n const dateStr = date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })\n const timeStr = date.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n })\n return `${dateStr} at ${timeStr}`\n}\n\n/**\n * Format a duration measured in MILLISECONDS as a compact human-readable\n * string. Returns `\"0ms\"` for null/NaN/negative, then `Xms` → `X.Xs` →\n * `X.Xm` as the input grows. Used by job-runs / orchestrator dashboards\n * where elapsed milliseconds is the natural unit.\n *\n * Distinct from `formatDuration(seconds)` (verbose `\"X hours Y minutes\"`)\n * and `formatDurationMMSS(seconds)` (media timecode `MM:SS`).\n */\nexport function formatDurationFromMs(ms: number | null | undefined): string {\n if (!ms || isNaN(ms) || ms < 0) return '0ms'\n if (ms < 1000) return `${ms}ms`\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`\n return `${(ms / 60000).toFixed(1)}m`\n}\n\n/**\n * Format seconds to verbose human-readable duration: `\"X seconds\"`,\n * `\"X minutes\"`, `\"X hours Y minutes\"`. Use this for human-readable\n * spans; for media timecodes use `formatDurationMMSS`; for compact\n * media labels use `formatDurationCompact`; for elapsed milliseconds\n * use `formatDurationFromMs`.\n */\nexport function formatDuration(seconds: number): string {\n if (seconds < 60) return `${seconds} seconds`\n if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes`\n\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n\n if (minutes === 0) return `${hours} hour${hours > 1 ? 's' : ''}`\n return `${hours} hour${hours > 1 ? 's' : ''} ${minutes} minute${minutes > 1 ? 's' : ''}`\n}\n\n// =============================================================================\n// Text formatting helpers (proper-case, HTML strip, bio cleanup)\n// =============================================================================\n\n/**\n * Format underscore-separated text into proper case.\n * `\"self_hosted\"` → `\"Self Hosted\"`\n * `\"open_source\"` → `\"Open Source\"`\n */\nexport function formatUnderscoreText(text: string): string {\n return text\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n}\n\n/**\n * Strip HTML tags and decode common HTML entities from a string.\n * Useful for cleaning API responses that contain HTML content.\n *\n * @example\n * stripHtml('<p>Hello <strong>World</strong></p>') // \"Hello World\"\n * stripHtml('Test &amp; Example') // \"Test & Example\"\n */\nexport function stripHtml(html: string): string {\n // Iterative tag-strip — a single pass is bypass-able by inputs like\n // `<scr<script>ipt>`: stripping the inner `<script>` leaves the outer\n // `<script>` reassembled. Loop until the string is stable so multi-\n // character bypasses cannot survive (CodeQL\n // `js/incomplete-multi-character-sanitization`). `<[^<>]*>` rejects\n // `<` inside the tag body so each pass is itself ReDoS-safe (no\n // backtracking on `<<<<<...<>` inputs).\n let noTags = html\n let prev: string\n do {\n prev = noTags\n noTags = noTags.replace(/<[^<>]*>/g, '')\n } while (noTags !== prev)\n\n // Decode entities. `&amp;` MUST come LAST so we don't double-decode\n // sequences like `&amp;lt;` (which should render as the LITERAL text\n // `&lt;`, not as `<`). All other named/numeric entities decode first;\n // only after those have been replaced do we collapse `&amp;` → `&`.\n return noTags\n .replace(/&nbsp;/g, ' ')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&#x27;/g, \"'\")\n .replace(/&apos;/g, \"'\")\n .replace(/&amp;/g, '&')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/**\n * Display label for the openmsp `vendors.classification` enum.\n * Falls back to proper-cased underscore split for values not in the\n * curated mapping.\n */\nexport function formatClassification(classification: string): string {\n const customMappings: Record<string, string> = {\n openframe_selected: 'OpenFrame Selected',\n }\n return customMappings[classification] || formatUnderscoreText(classification)\n}\n\n/**\n * Display label for the openmsp `vendors.pricing_model` enum.\n * Falls back to proper-cased underscore split for values not in the\n * curated mapping.\n */\nexport function formatPricingModel(pricingModel: string): string {\n const customMappings: Record<string, string> = {\n one_time: 'One-time Purchase',\n self_hosted: 'Self-hosted',\n }\n return customMappings[pricingModel] || formatUnderscoreText(pricingModel)\n}\n\n/**\n * Format a bio/about text from the profiles table for display.\n * Handles HTML content (e.g. `<p>` tags from rich text editors),\n * plain text passthrough, and null/undefined values.\n */\nexport function formatBioText(\n aboutHtml: string | null | undefined,\n fallback: string = '',\n): string {\n if (!aboutHtml || !aboutHtml.trim()) return fallback\n\n if (aboutHtml.includes('<p')) {\n // `<p[^<>]*>` rejects `<` inside the tag so the automaton can't\n // backtrack on `<<<<<...<p>` inputs (ReDoS class fix vs. `<p[^>]*>`).\n const paragraphs = aboutHtml\n .split(/<p[^<>]*>/)\n .slice(1)\n .map((part) => part.split('</p>')[0])\n .map((text) => stripHtml(text).trim())\n .filter((text) => text.length > 0)\n\n if (paragraphs.length > 0) return paragraphs.join(' ')\n }\n\n return stripHtml(aboutHtml).trim() || fallback\n}\n","import type { SVGProps } from \"react\";\n\n/** SVG path data for the play icon — exported for reuse in server-side image generation */\nexport const PLAY_ICON_PATH = \"M4.875 5.006c0-2.501 2.793-3.989 4.87-2.592l9.78 6.578c2.135 1.437 2.135 4.58 0 6.016l-9.78 6.579c-2.077 1.396-4.87-.091-4.87-2.593zm2.25 13.988c0 .7.783 1.118 1.364.727l9.78-6.58c.81-.545.81-1.738 0-2.283L8.488 4.28a.875.875 0 0 0-1.364.726v13.988Z\";\n\nexport interface PlayIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function PlayIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: PlayIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d={PLAY_ICON_PATH}\n />\n </svg>\n );\n}\n","/**\n * ODS Color Token Utility Functions\n * \n * Provides runtime utilities for working with ODS color tokens\n */\n\nimport { colorTokens as odsTokens } from './ods-color-tokens-stub';\n\nexport type Platform = 'openmsp' | 'openframe' | 'flamingo';\nexport type ColorCategory = 'open' | 'flamingo' | 'system' | 'attention';\nexport type ColorVariant = 'base' | 'hover' | 'active' | 'focus' | 'disabled';\n\n/**\n * Gets the raw ODS token value for a specific color\n */\nexport function getODSToken(\n category: ColorCategory,\n color: string,\n variant: ColorVariant = 'base'\n): string | undefined {\n const tokenKey = `${category}-${color}-${variant}`;\n return (odsTokens as any)[tokenKey];\n}\n\n/**\n * Gets the current platform's accent color\n */\nexport function getPlatformAccentColor(platform?: Platform): string {\n const currentPlatform = platform || getCurrentPlatform();\n \n const platformColors = {\n 'openmsp': 'var(--ods-open-yellow-base)', // CSS variable instead of hex\n 'openframe': 'var(--ods-open-yellow-base)', // CSS variable instead of hex\n 'flamingo': 'var(--ods-flamingo-pink-base)' // CSS variable instead of hex\n };\n \n return platformColors[currentPlatform];\n}\n\n/**\n * Gets the current platform from environment or DOM\n */\nexport function getCurrentPlatform(): Platform {\n // Server-side: use environment variable\n if (typeof window === 'undefined') {\n return (process.env.NEXT_PUBLIC_APP_TYPE as Platform) || 'openmsp';\n }\n \n // Client-side: check DOM attribute first, fallback to environment\n const domPlatform = document.documentElement.getAttribute('data-app-type');\n if (domPlatform) {\n return domPlatform as Platform;\n }\n \n return (process.env.NEXT_PUBLIC_APP_TYPE as Platform) || 'openmsp';\n}\n\n/**\n * Switches the platform theme by updating CSS custom properties\n */\nexport function switchPlatformTheme(platform: Platform): void {\n if (typeof window === 'undefined') return;\n \n const root = document.documentElement;\n root.setAttribute('data-app-type', platform);\n \n // Note: Cannot modify process.env at runtime in production\n // This would only work in development/test environments\n \n // Dispatch custom event for components to react to platform changes\n window.dispatchEvent(new CustomEvent('platformThemeChanged', {\n detail: { platform }\n }));\n}\n\n/**\n * Gets a semantic color value for the current platform\n */\nexport function getSemanticColor(semanticName: string, platform?: Platform): string | undefined {\n if (typeof window === 'undefined') return undefined;\n \n const currentPlatform = platform || getCurrentPlatform();\n \n // Switch platform temporarily to get the color\n const originalPlatform = getCurrentPlatform();\n if (currentPlatform !== originalPlatform) {\n switchPlatformTheme(currentPlatform);\n }\n \n const testElement = document.createElement('div');\n document.body.appendChild(testElement);\n \n const computedStyle = getComputedStyle(testElement);\n const colorValue = computedStyle.getPropertyValue(`--color-${semanticName}`);\n \n document.body.removeChild(testElement);\n \n // Restore original platform\n if (currentPlatform !== originalPlatform) {\n switchPlatformTheme(originalPlatform);\n }\n \n return colorValue.trim() || undefined;\n}\n\n/**\n * Converts an ODS token to its corresponding Tailwind class\n */\nexport function tokenToTailwindClass(\n tokenKey: string,\n type: 'bg' | 'text' | 'border' = 'bg'\n): string | undefined {\n // Map common tokens to Tailwind classes\n const tokenMappings: Record<string, string> = {\n // Accent colors\n 'accent-primary': 'accent',\n 'accent-hover': 'accent-hover',\n 'accent-active': 'accent-active',\n \n // Background colors\n 'bg': 'bg',\n 'bg-card': 'card',\n 'bg-hover': 'bg-hover',\n 'bg-active': 'bg-active',\n \n // Text colors\n 'text-primary': 'text-primary',\n 'text-secondary': 'text-secondary',\n 'text-muted': 'text-muted',\n 'text-disabled': 'text-disabled',\n 'text-on-accent': 'text-on-accent',\n 'text-on-dark': 'text-on-dark',\n \n // Border colors\n 'border-default': 'border',\n 'border-hover': 'border-hover',\n 'border-focus': 'border-focus',\n \n // Status colors\n 'success': 'success',\n 'error': 'error',\n 'warning': 'warning',\n 'info': 'info'\n };\n \n const mappedToken = tokenMappings[tokenKey];\n if (!mappedToken) return undefined;\n \n return `${type}-ods-${mappedToken}`;\n}\n\n/**\n * Gets all available ODS tokens for a category\n */\nexport function getTokensByCategory(category: ColorCategory): Record<string, string> {\n const tokens: Record<string, string> = {};\n \n Object.entries(odsTokens).forEach(([key, value]) => {\n if (key.startsWith(`${category}-`)) {\n tokens[key] = value as string;\n }\n });\n \n return tokens;\n}\n\n/**\n * Validates if a color token exists in the ODS system\n */\nexport function isValidODSToken(tokenKey: string): boolean {\n return tokenKey in odsTokens;\n}\n\n/**\n * Gets the platform configuration for theming\n */\nexport function getPlatformConfig(platform?: Platform) {\n const currentPlatform = platform || getCurrentPlatform();\n \n return {\n platform: currentPlatform,\n accentColor: getPlatformAccentColor(currentPlatform),\n isDarkTheme: currentPlatform !== 'flamingo',\n isLightTheme: currentPlatform === 'flamingo',\n brandName: {\n 'openmsp': 'OpenMSP',\n 'openframe': 'OpenFrame',\n 'flamingo': 'Flamingo'\n }[currentPlatform]\n };\n}\n\n/**\n * Generates CSS custom property declarations for a platform\n */\nexport function generatePlatformCSS(platform: Platform): string {\n const accentColor = getPlatformAccentColor(platform);\n const tokens = getTokensByCategory('system');\n \n let css = `[data-app-type=\"${platform}\"] {\\n`;\n css += ` --color-accent-primary: ${accentColor};\\n`;\n \n // Add platform-specific overrides\n if (platform === 'flamingo') {\n css += ` --color-bg: var(--ods-system-greys-white);\\n`;\n css += ` --color-text-primary: var(--ods-system-greys-background);\\n`;\n }\n \n if (platform === 'openframe') {\n css += ` --color-bg: var(--ods-system-greys-darker);\\n`;\n }\n \n css += `}\\n`;\n \n return css;\n}\n\n/**\n * Applies a color token as a CSS custom property\n */\nexport function applyColorToken(\n element: HTMLElement,\n property: string,\n tokenKey: string\n): void {\n const tokenValue = (odsTokens as any)[tokenKey];\n if (tokenValue) {\n element.style.setProperty(`--${property}`, tokenValue);\n }\n}\n\n/**\n * Creates a color interpolation between two ODS tokens\n */\nexport function interpolateColors(\n startToken: string,\n endToken: string,\n progress: number\n): string {\n const startColor = (odsTokens as any)[startToken];\n const endColor = (odsTokens as any)[endToken];\n \n if (!startColor || !endColor) {\n return startColor || endColor || '#000000';\n }\n \n // Simple hex color interpolation\n const hexToRgb = (hex: string) => {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16)\n } : { r: 0, g: 0, b: 0 };\n };\n \n const rgbToHex = (r: number, g: number, b: number) => {\n return \"#\" + ((1 << 24) + (Math.round(r) << 16) + (Math.round(g) << 8) + Math.round(b)).toString(16).slice(1);\n };\n \n const start = hexToRgb(startColor);\n const end = hexToRgb(endColor);\n \n const interpolated = {\n r: start.r + (end.r - start.r) * progress,\n g: start.g + (end.g - start.g) * progress,\n b: start.b + (end.b - start.b) * progress\n };\n \n return rgbToHex(interpolated.r, interpolated.g, interpolated.b);\n}\n\n/**\n * Hook for React components to use platform-aware colors\n */\nexport function usePlatformColors(platform?: Platform) {\n const currentPlatform = platform || getCurrentPlatform();\n const config = getPlatformConfig(currentPlatform);\n \n return {\n platform: currentPlatform,\n accentColor: config.accentColor,\n isDarkTheme: config.isDarkTheme,\n isLightTheme: config.isLightTheme,\n brandName: config.brandName,\n getToken: (category: ColorCategory, color: string, variant?: ColorVariant) =>\n getODSToken(category, color, variant),\n switchTheme: (newPlatform: Platform) => switchPlatformTheme(newPlatform),\n getSemanticColor: (semanticName: string) => getSemanticColor(semanticName, currentPlatform)\n };\n}\n\n/**\n * Picks a near-black or near-white text color with adequate contrast on `hex`.\n * Uses Rec. 601 luminance.\n */\nexport function getReadableTextColor(hex: string): string {\n const n = parseInt(hex.replace('#', ''), 16)\n const r = (n >> 16) & 0xff\n const g = (n >> 8) & 0xff\n const b = n & 0xff\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255\n return luminance > 0.5 ? '#212121' : '#fafafa'\n}\n\nexport default {\n getODSToken,\n getPlatformAccentColor,\n getCurrentPlatform,\n switchPlatformTheme,\n getSemanticColor,\n tokenToTailwindClass,\n getTokensByCategory,\n isValidODSToken,\n getPlatformConfig,\n generatePlatformCSS,\n applyColorToken,\n interpolateColors,\n usePlatformColors\n};","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\n/**\n * Utility functions for common operations\n */\n\n/**\n * Merge class names with Tailwind CSS\n * @param inputs - Class names to merge\n * @returns Merged class names\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n/**\n * Delay execution for a specified time\n * @param ms - Milliseconds to delay\n * @returns Promise that resolves after the delay\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Generate a random string of specified length\n * @param length - Length of the string\n * @returns Random string\n */\nexport function generateRandomString(length = 8): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"\n let result = \"\"\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length))\n }\n return result\n}\n\n/**\n * Truncate a string to a specified length\n * @param str - String to truncate\n * @param maxLength - Maximum length\n * @param suffix - Suffix to add to truncated string\n * @returns Truncated string\n */\nexport function truncateString(str: string, maxLength: number, suffix = \"...\"): string {\n if (str.length <= maxLength) return str\n return str.substring(0, maxLength - suffix.length) + suffix\n}\n\n/**\n * Deep clone an object\n * @param obj - Object to clone\n * @returns Cloned object\n */\nexport function deepClone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\n/**\n * Get the Slack community join URL from environment variables\n * @returns Slack community join URL or fallback URL\n */\nexport function getSlackCommunityJoinUrl(): string {\n const url = process.env.NEXT_PUBLIC_SLACK_COMMUNITY_JOIN_URL\n if (!url) {\n console.warn('NEXT_PUBLIC_SLACK_COMMUNITY_JOIN_URL is not defined in environment variables')\n return 'https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA'\n }\n return url\n}\n\n","import React from 'react';\n\ninterface OpenmspLogoProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n frontBubbleColor?: string;\n innerFrontBubbleColor?: string;\n backBubbleColor?: string;\n color?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function OpenmspLogo({ className = '', frontBubbleColor = '#000000', innerFrontBubbleColor = '#ffffff', backBubbleColor = '#ffffff', ...props }: OpenmspLogoProps) {\n return (\n <svg\n width=\"97\"\n height=\"96\"\n viewBox=\"0 0 97 96\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path\n d=\"M73.933 0C75.7003 0 77.133 1.43269 77.133 3.2V54.4C77.133 56.1673 75.7003 57.6 73.933 57.6H3.53301C1.7657 57.6 0.333008 56.1673 0.333008 54.4V3.2C0.333008 1.43269 1.7657 0 3.53301 0H73.933ZM10.1076 47.6494C10.1076 48.0912 10.4658 48.4494 10.9076 48.4494H66.5584C67.0002 48.4494 67.3584 48.0912 67.3584 47.6494V9.95059C67.3584 9.50876 67.0002 9.15059 66.5584 9.15059H10.9076C10.4658 9.15059 10.1076 9.50876 10.1076 9.95059V47.6494Z\"\n fill={backBubbleColor} />\n <path\n d=\"M19.5332 22.4C19.5332 20.6326 20.9659 19.2 22.7332 19.2H93.1332C94.9005 19.2 96.3332 20.6326 96.3332 22.4V76.8C96.3332 78.2222 95.3945 79.4737 94.0292 79.8719L39.7572 95.7013C39.2452 95.8506 38.7332 95.4666 38.7332 94.9333V80C38.7332 79.5581 38.375 79.2 37.9332 79.2H22.7332C20.9659 79.2 19.5332 77.7673 19.5332 76V22.4Z\"\n fill={innerFrontBubbleColor} />\n <path\n d=\"M93.1332 19.2C94.9005 19.2 96.3332 20.6326 96.3332 22.4V76.8C96.3332 78.2222 95.3945 79.4737 94.0292 79.8719L39.7572 95.7013C39.2452 95.8506 38.7332 95.4666 38.7332 94.9333V80C38.7332 79.5581 38.375 79.2 37.9332 79.2H22.7332C20.9659 79.2 19.5332 77.7673 19.5332 76V22.4C19.5332 20.6326 20.9659 19.2 22.7332 19.2H93.1332ZM48.3377 82.1286C48.3355 82.6633 48.8484 83.0497 49.3617 82.9L86.1572 72.1672C86.4985 72.0676 86.7332 71.7547 86.7332 71.3992V29.6C86.7332 29.1581 86.375 28.8 85.9332 28.8H29.9332C29.4914 28.8 29.1332 29.1581 29.1332 29.6V68.8C29.1332 69.2418 29.4914 69.6 29.9332 69.6H47.5869C48.03 69.6 48.3887 69.9602 48.3869 70.4033L48.3377 82.1286Z\"\n fill={frontBubbleColor} />\n <circle\n cx=\"45.1334\" cy=\"44.8\" r=\"6.4\"\n fill={frontBubbleColor} />\n </svg>\n );\n}\n","import React from 'react';\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const OpenFrameLogo = ({ className, lowerPathColor, upperPathColor, ...props }: { className?: string, lowerPathColor?: string, upperPathColor?: string } & React.SVGProps<SVGSVGElement>) => {\n return (\n <svg\n {...props}\n className={className}\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{\n '--fill-0': 'currentColor',\n ...props.style\n } as React.CSSProperties}\n >\n <g>\n <g>\n {/* White squares - top right, bottom left, bottom right, bottom center */}\n <path\n d=\"M21.3333 16.5333C21.3333 16.2388 21.5721 16 21.8667 16H26.1333C26.4279 16 26.6667 16.2388 26.6667 16.5333V20.8C26.6667 21.0946 26.4279 21.3333 26.1333 21.3333H21.8667C21.5721 21.3333 21.3333 21.0946 21.3333 20.8V16.5333Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n <path\n d=\"M16 21.8667C16 21.5721 16.2388 21.3333 16.5333 21.3333H20.8C21.0946 21.3333 21.3333 21.5721 21.3333 21.8667V26.1333C21.3333 26.4279 21.0946 26.6667 20.8 26.6667H16.5333C16.2388 26.6667 16 26.4279 16 26.1333V21.8667Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n <path\n d=\"M26.6667 21.8667C26.6667 21.5721 26.9054 21.3333 27.2 21.3333H31.4667C31.7612 21.3333 32 21.5721 32 21.8667V26.1333C32 26.4279 31.7612 26.6667 31.4667 26.6667H27.2C26.9054 26.6667 26.6667 26.4279 26.6667 26.1333V21.8667Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n <path\n d=\"M21.3333 27.2C21.3333 26.9054 21.5721 26.6667 21.8667 26.6667H26.1333C26.4279 26.6667 26.6667 26.9054 26.6667 27.2V31.4667C26.6667 31.7612 26.4279 32 26.1333 32H21.8667C21.5721 32 21.3333 31.7612 21.3333 31.4667V27.2Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n </g>\n {/* Black frame/border */}\n <path\n d=\"M30.9333 0H1.06667C0.477563 0 0 0.477564 0 1.06667V30.9333C0 31.5224 0.477563 32 1.06667 32H14.9333C15.5224 32 16 31.5224 16 30.9333V27.7333C16 27.1442 15.5224 26.6667 14.9333 26.6667H5.86667C5.57211 26.6667 5.33333 26.4279 5.33333 26.1333V5.86667C5.33333 5.57211 5.57211 5.33333 5.86667 5.33333H26.1333C26.4279 5.33333 26.6667 5.57212 26.6667 5.86667V14.9333C26.6667 15.5224 27.1442 16 27.7333 16H30.9333C31.5224 16 32 15.5224 32 14.9333V1.06667C32 0.477563 31.5224 0 30.9333 0Z\"\n fill={upperPathColor ?? '#1A1A1A'}\n />\n </g>\n </svg>\n );\n}; ","import React from 'react';\n\n/** Raw SVG path data — single source of truth for the Flamingo logo.\n * Used by the React component and exported for non-React contexts (e.g. email HTML). */\nexport const FLAMINGO_LOGO_SVG_PATH = 'M20.8645 77.9756C20.6306 78.095 20.3452 77.9582 20.3369 77.7002C20.2055 73.6173 23.4398 62.2314 27.7657 59.0452C31.477 45.9806 61.8811 24.0208 81.7715 48.2044C83.1662 49.7884 84.0264 52.0978 84.7512 54.0436C86.0615 57.5613 86.9291 59.8908 89.7117 54.5977C92.4782 49.335 87.2725 42.2381 81.701 34.6426C75.7955 26.5918 69.4791 17.9808 71.8102 10.4001C75.4609 -1.47146 91.9849 -4.33245 94.5422 7.89834C98.4226 10.7002 104.422 17.0815 96.2751 25.8554C96.0466 26.1014 95.6263 25.9453 95.6104 25.6132C95.417 21.5769 93.9498 16.1177 90.5641 14.5697C89.0187 13.8632 88.0307 13.6723 87.1405 13.5003C85.585 13.1998 84.3282 12.9569 80.919 10.1221C75.236 5.39658 75.236 20.1291 87.7386 32.3599C97.1156 41.533 106.493 66.2324 84.0287 70.9981C74.9174 72.9311 68.0892 72.0015 61.3076 71.0782C61.0953 71.0493 60.8831 71.0204 60.6708 70.9916V89.3274L66.3745 91.8104C67.0914 92.1225 67.4139 92.944 67.0949 93.6453C66.7759 94.3466 65.9362 94.6621 65.2193 94.35L60.6708 92.37V118.61C60.6708 119.378 60.0347 120 59.2501 120C58.4654 120 57.8293 119.378 57.8293 118.61V91.133L42.4873 84.4542C42.0611 84.2686 41.7551 83.8902 41.6687 83.4417C41.5824 82.9931 41.7266 82.5317 42.0546 82.2072L54.1527 70.2377C45.537 69.536 35.8193 70.3474 20.8645 77.9756ZM57.7692 70.613L45.5202 82.732L57.8293 88.0905V70.6204C57.8093 70.618 57.7893 70.6155 57.7692 70.613Z';\n\nexport const FLAMINGO_LOGO_VIEWBOX = '0 0 121 120';\n\ninterface FlamingoLogoProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n fill?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function FlamingoLogo({ className = '', fill = 'var(--ods-flamingo-pink-base)', ...props }: FlamingoLogoProps) {\n return (\n <svg\n width=\"121\"\n height=\"120\"\n viewBox={FLAMINGO_LOGO_VIEWBOX}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d={FLAMINGO_LOGO_SVG_PATH}\n fill={fill}\n />\n </svg>\n );\n} ","import React from 'react';\n\ninterface MiamiCyberGangLogoFaceOnlyProps {\n size?: number;\n /** Pink color used for accent elements. Defaults to ODS accent color */\n originalPink?: string;\n /** White color used for text and details. Defaults to ODS text-on-accent color */\n originalWhite?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const MiamiCyberGangLogoFaceOnly: React.FC<MiamiCyberGangLogoFaceOnlyProps> = ({\n size = 64,\n originalPink = \"var(--ods-accent, #F357BB)\",\n originalWhite = \"var(--ods-text-on-accent, #FAFAFA)\",\n className = ''\n}) => {\n return (\n <svg className={className} width={size} height={size} viewBox=\"0 0 120 120\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M102.395 53.6809C90.4125 50.7582 80.6974 44.729 74.1665 33.9873C73.8956 34.2151 73.7234 34.299 73.6447 34.4355C68.7714 42.9024 61.1392 47.742 52.0761 50.5062C47.3393 51.9497 42.4555 52.9072 37.5024 53.8814C38.8546 50.9314 40.3233 48.1903 39.8929 44.7238C32.5693 50.9692 23.5986 52.1744 14.4546 53.8478C14.7695 52.1649 14.9501 50.6658 15.3375 49.2212C16.6004 44.5086 17.6723 39.7203 19.3048 35.1347C22.3566 26.5661 28.8445 21.5521 37.3439 18.9685C43.3699 17.1376 49.5848 16.6746 55.8502 16.7114C57.7094 16.7229 59.5676 16.7135 61.4972 16.5234C58.6459 13.5482 55.13 11.7205 51.3055 10.3305C52.8141 9.65024 59.3786 10.0628 64.043 11.1714C68.2685 12.1761 72.1833 13.8527 75.4588 16.9087C80.9704 13.8873 86.8746 13.1651 93.1336 13.3834C91.7416 14.0102 90.444 14.5036 89.2356 15.1618C87.9706 15.8505 86.7423 16.6326 85.5864 17.4935C84.4379 18.348 83.3997 19.3506 82.1021 20.4697C82.7572 20.8256 83.1697 21.0776 83.6054 21.2812C89.3312 23.9698 93.9283 27.9151 97.25 33.3406C99.2404 36.5919 100.029 40.2327 100.817 43.8682C101.477 46.9085 101.961 49.9887 102.51 53.0531C102.538 53.2127 102.451 53.3922 102.395 53.6809Z\"\n fill={originalWhite} />\n <path\n d=\"M45.7357 106.481C44.8472 105.838 44.7949 104.555 45.5033 103.717C46.1854 102.911 47.3459 102.791 48.2538 103.331C54.1019 106.808 59.9027 106.818 65.7439 103.334C66.6566 102.79 67.8521 102.94 68.5404 103.749C69.2297 104.56 69.1869 105.767 68.3442 106.417C62.4972 110.926 52.5717 111.432 45.7357 106.481Z\"\n fill={originalWhite} />\n <path\n d=\"M81.9671 69.9535C85.2121 69.9577 87.8881 72.2967 87.9564 75.1869C88.0246 78.1117 85.1533 80.7006 81.8768 80.6691C78.6203 80.6376 76.0892 78.2996 76.0724 75.3087C76.0545 72.2222 78.5573 69.9493 81.9671 69.9535Z\"\n fill={originalWhite} />\n <path\n d=\"M35.5036 80.7335C33.1909 80.7356 31.549 79.9891 30.3942 78.3535C28.684 75.9337 29.2792 72.7863 31.761 71.1675C33.8239 69.8216 36.0149 69.6893 38.2321 70.7706C40.5449 71.8971 41.6063 74.0303 41.1632 76.5237C40.8011 78.5551 38.6815 80.4238 36.4369 80.6768C36.0212 80.723 35.6013 80.7282 35.5036 80.7335Z\"\n fill={originalWhite} />\n <path\n d=\"M16.2685 72.4296C16.743 61.5083 30.7046 61.3183 31.8437 61.2228C31.8437 61.2228 43.4306 60.0837 48.749 65.0221C54.0674 69.9605 50.9326 86.6757 45.1397 90.285C39.0119 94.1022 28.71 94.2733 23.9606 91.2341C19.2122 88.1948 15.794 83.351 16.2685 72.4296ZM95.1911 91.2341C90.4427 94.2733 80.1408 94.1022 74.013 90.285C68.219 86.6757 65.0853 69.9605 70.4037 65.0221C75.7221 60.0837 87.309 61.2238 87.309 61.2238C88.4481 61.3183 102.41 61.5083 102.884 72.4307C103.359 83.352 99.9405 88.1948 95.1911 91.2341ZM59.5758 68.9474C59.9538 68.9999 60.422 69.0817 61.0015 69.2014C64.7053 69.9605 64.4208 76.419 66.8899 83.162C69.3591 89.905 74.1075 96.458 88.7336 95.3179C103.359 94.1788 105.163 81.0728 105.638 78.3181C106.113 75.5644 107.253 72.9052 107.253 72.9052L108.687 71.4711C108.985 71.173 109.153 70.7688 109.153 70.3478V63.6174C109.153 62.8762 108.641 62.2369 107.92 62.071C105.532 61.522 99.8575 60.2958 92.5319 59.2292C82.7496 57.8045 72.7784 59.7037 70.6882 61.1283C68.5991 62.5529 66.8899 63.0274 66.8899 63.0274H52.2627C52.2627 63.0274 50.5536 62.5529 48.4645 61.1283C46.3753 59.7037 36.4031 57.8045 26.6208 59.2281C19.2951 60.2947 13.6208 61.522 11.2325 62.071C10.5113 62.2369 10 62.8762 10 63.6164V70.3468C10 70.7688 10.168 71.1719 10.4651 71.4701L11.9002 72.9042C11.9002 72.9042 13.0392 75.5634 13.5148 78.3181C13.9893 81.0718 15.7929 94.1778 30.4191 95.3179C45.0442 96.458 49.7936 89.905 52.2627 83.162C54.7319 76.419 54.4474 69.9605 58.1512 69.2014C58.7307 69.0817 59.1989 68.9999 59.5758 68.9474Z\"\n fill={originalPink} />\n </svg>\n\n\n );\n};","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function ShellIcon({ className = \"w-5 h-5\", size = 22, color = 'white' }: { className?: string; size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 48 48\" >\n <path\n fill='transparent'\n stroke={color}\n d=\"M6.5 8.4a2 2 0 0 0-2 2v27.2a2 2 0 0 0 2 2h35a2 2 0 0 0 2-2V10.4a2 2 0 0 0-2-2zM9 23.16l7.72 6L9 35.13v-12zm20.46 11.97h-11\" />\n </svg >\n )\n}\n","import React from 'react';\n\ninterface GitHubIconProps {\n color?: string;\n className?: string;\n width?: number;\n height?: number;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const GitHubIcon: React.FC<GitHubIconProps> = ({\n className = \"\",\n width = 15,\n height = 14,\n color = 'white'\n}) => {\n return (\n <svg \n width={width} \n height={height} \n viewBox=\"0 0 15 14\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <path d=\"M7.18173 0.333008C3.40523 0.333008 0.346436 3.3918 0.346436 7.1683C0.346436 10.1929 2.30304 12.7476 5.02007 13.6533C5.36183 13.7131 5.48999 13.508 5.48999 13.3286C5.48999 13.1663 5.48145 12.628 5.48145 12.0555C3.76408 12.3717 3.31979 11.6369 3.18308 11.2524C3.10618 11.0559 2.77296 10.4492 2.48246 10.2869C2.24323 10.1587 1.90146 9.84261 2.47392 9.83406C3.0122 9.82552 3.39668 10.3296 3.52485 10.5347C4.14002 11.5685 5.1226 11.278 5.51563 11.0986C5.57543 10.6543 5.75486 10.3553 5.95137 10.1844C4.43052 10.0135 2.84132 9.42395 2.84132 6.80945C2.84132 6.06611 3.10618 5.45093 3.54193 4.97246C3.47358 4.80158 3.23435 4.10096 3.61029 3.16111C3.61029 3.16111 4.18274 2.98168 5.48999 3.86173C6.03682 3.70793 6.61782 3.63104 7.19882 3.63104C7.77982 3.63104 8.36082 3.70793 8.90764 3.86173C10.2149 2.97314 10.7873 3.16111 10.7873 3.16111C11.1633 4.10096 10.9241 4.80158 10.8557 4.97246C11.2914 5.45093 11.5563 6.05757 11.5563 6.80945C11.5563 9.43249 9.95856 10.0135 8.43771 10.1844C8.68549 10.398 8.8991 10.8081 8.8991 11.4489C8.8991 12.3631 8.89055 13.0979 8.89055 13.3286C8.89055 13.508 9.01871 13.7216 9.36048 13.6533C10.7174 13.1952 11.8965 12.3231 12.7318 11.1597C13.5671 9.99643 14.0166 8.60046 14.017 7.1683C14.017 3.3918 10.9582 0.333008 7.18173 0.333008Z\" fill={color}/>\n </svg>\n );\n}; ","import { color } from 'framer-motion'\nimport React from 'react'\n\ninterface SlackIconProps {\n width?: number | string\n height?: number | string\n className?: string\n injectedColor?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function SlackIcon({ \n width = 24, \n height = 24, \n className = \"text-current\" ,\n injectedColor \n}: SlackIconProps) {\n\n const redColor = injectedColor || \"#E01E5A\";\n const blueColor = injectedColor || \"#36C5F0\";\n const greenColor = injectedColor || \"#2EB67D\";\n const yellowColor = injectedColor || \"#ECB22E\";\n\n return (\n <svg \n width={width} \n height={height} \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <g>\n <path \n d=\"M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313z\" \n fill={redColor} \n />\n <path \n d=\"M8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312z\" \n fill={blueColor} \n />\n <path \n d=\"M18.956 8.834a2.528 2.528 0 0 1 2.521-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.523 2.521h-2.521V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312z\" \n fill={greenColor} \n />\n <path \n d=\"M15.165 18.956a2.528 2.528 0 0 1 2.523 2.521A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.523v-2.521h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.528 2.528 0 0 1 2.52-2.521h6.313A2.528 2.528 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z\" \n fill={yellowColor}\n />\n </g>\n </svg>\n )\n} ","import React from 'react'\n\ninterface ClickUpIconProps {\n width?: number | string\n height?: number | string\n className?: string\n}\n\nexport function ClickUpIcon({\n width = 24,\n height = 24,\n className = '',\n}: ClickUpIconProps) {\n return (\n <svg\n width={width}\n height={height}\n viewBox=\"0 0 54.8 65.8\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <defs>\n <linearGradient id=\"clickup-grad-1\" gradientUnits=\"userSpaceOnUse\" x1=\"0\" y1=\"15.0492\" x2=\"54.8446\" y2=\"15.0492\" gradientTransform=\"matrix(1 0 0 -1 0 69.3604)\">\n <stop offset=\"0\" stopColor=\"#8930FD\" />\n <stop offset=\"1\" stopColor=\"#49CCF9\" />\n </linearGradient>\n <linearGradient id=\"clickup-grad-2\" gradientUnits=\"userSpaceOnUse\" x1=\"1.1953\" y1=\"53.166\" x2=\"53.7447\" y2=\"53.166\" gradientTransform=\"matrix(1 0 0 -1 0 69.3604)\">\n <stop offset=\"0\" stopColor=\"#FF02F0\" />\n <stop offset=\"1\" stopColor=\"#FFC800\" />\n </linearGradient>\n </defs>\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0,50.6l10.1-7.8c5.4,7,11.1,10.3,17.4,10.3c6.3,0,11.9-3.2,17-10.2l10.3,7.6c-7.4,10-16.6,15.3-27.3,15.3 C16.9,65.8,7.6,60.5,0,50.6z\"\n fill=\"url(#clickup-grad-1)\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M27.5,16.9l-18,15.5l-8.3-9.7L27.6,0l26.2,22.7l-8.4,9.6L27.5,16.9z\"\n fill=\"url(#clickup-grad-2)\"\n />\n </svg>\n )\n}\n","import React from 'react';\n\ninterface XLogoProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function XLogo({ className = '', color = 'white', ...props }: XLogoProps) {\n return (\n <svg\n width={24}\n height={24}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M9.75292 12.6562C10.1923 12.2169 10.9044 12.2169 11.3437 12.6562C11.7831 13.0956 11.7831 13.8077 11.3437 14.2471L3.7954 21.7954C3.35606 22.2348 2.64392 22.2348 2.20458 21.7954C1.76524 21.3561 1.76524 20.6439 2.20458 20.2046L9.75292 12.6562ZM20.2046 2.20459C20.6439 1.76525 21.3561 1.76525 21.7954 2.20459C22.2347 2.64393 22.2347 3.35607 21.7954 3.79541L14.2471 11.3438C13.8077 11.7831 13.0956 11.7831 12.6562 11.3438C12.2169 10.9044 12.2169 10.1923 12.6562 9.75293L20.2046 2.20459Z\" fill=\"#FAFAFA\" />\n <path d=\"M7.9995 1.875L8.13426 1.88232C8.444 1.91951 8.72702 2.08473 8.9121 2.34082L21.9126 20.3408C22.1599 20.6833 22.1943 21.1365 22.0019 21.5127C21.8096 21.8887 21.4223 22.125 21 22.125H16.0005C15.6393 22.125 15.2994 21.9519 15.0879 21.6592L2.08739 3.65918C1.84004 3.31669 1.8057 2.86346 1.99803 2.4873C2.19042 2.11133 2.57763 1.875 2.99999 1.875H7.9995ZM16.5747 19.875H18.7983L7.42528 4.125H5.20165L16.5747 19.875Z\" fill=\"#FAFAFA\" />\n </svg>\n );\n} ","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * HubSpot brand logo (solid orange)\n * Usage: <HubspotIcon className=\"h-4 w-4\" />\n */\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function HubspotIcon({ className, fill = '#FF7A59', ...props }: React.SVGProps<SVGSVGElement>) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 512 512\"\n fill={fill}\n className={cn('inline-block', className)}\n {...props}\n >\n <path d=\"M266.197 216.109c-22.551 21.293-36.655 51.48-36.655 84.991 0 26.326 8.714 50.582 23.359 70.08l-44.473 44.74c-3.953-1.438-8.176-2.245-12.579-2.245-9.702 0-18.776 3.774-25.605 10.602-6.828 6.827-10.602 15.989-10.602 25.696 0 9.701 3.773 18.775 10.602 25.605 6.829 6.826 15.993 10.42 25.605 10.42 9.703 0 18.777-3.505 25.695-10.42 6.829-6.83 10.602-15.994 10.602-25.605 0-3.774-.538-7.369-1.707-10.873l44.923-45.102c19.765 15.183 44.381 24.169 71.244 24.169 64.599 0 116.797-52.38 116.797-116.977 0-58.578-42.854-107.093-99.007-115.628v-55.343c15.723-6.65 25.335-21.384 25.335-38.545 0-23.449-18.777-43.034-42.227-43.034-23.448 0-41.956 19.585-41.956 43.034 0 17.161 9.613 31.895 25.335 38.545v54.983c-13.655 1.887-26.593 6.019-38.362 12.219-24.796-18.778-105.565-76.997-151.746-112.126 1.078-3.953 1.798-8.085 1.798-12.397 0-25.875-21.113-46.898-47.078-46.898-25.875 0-46.898 21.023-46.898 46.898 0 25.965 21.023 46.988 46.898 46.988 8.805 0 16.98-2.606 24.078-6.828L266.197 216.109zM346.606 363.095c-34.229 0-61.991-27.763-61.991-61.994 0-34.229 27.762-61.99 61.991-61.99 34.23 0 61.992 27.761 61.992 61.99 0 34.231-27.762 61.994-61.992 61.994z\" />\n </svg>\n );\n} ","import React from 'react';\n\ninterface LinkedInIconProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n size?: number;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function LinkedInIcon({ className = '', size = 24, color = 'white', ...props }: LinkedInIconProps) {\n return (\n <svg \n width={size} \n height={size} \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path \n d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" \n fill={color}\n />\n </svg>\n );\n}","import React from 'react';\n\ninterface YouTubeIconProps {\n color?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function YouTubeIcon({ className ,\n color = 'white'\n}: YouTubeIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17\" />\n <path d=\"m10 15 5-3-5-3z\" />\n </svg>\n );\n}","import React from 'react';\n\ninterface InstagramIconProps {\n color?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function InstagramIcon({ className ,\n color = 'white'\n}: InstagramIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <rect width=\"20\" height=\"20\" x=\"2\" y=\"2\" rx=\"5\" ry=\"5\" />\n <path d=\"m16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z\" />\n <line x1=\"17.5\" x2=\"17.51\" y1=\"6.5\" y2=\"6.5\" />\n </svg>\n );\n}","import React from 'react';\n\ninterface FacebookIconProps {\n color?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function FacebookIcon({ className ,\n color = 'white'\n}: FacebookIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z\" />\n </svg>\n );\n}","import React from \"react\"\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface WindowsIconProps extends React.SVGProps<SVGSVGElement> {}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function WindowsIcon({ className, color = 'white', ...props }: WindowsIconProps) {\n return (\n <svg \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 16 16\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M0.833374 2.22562L6.28233 1.48656L6.28468 6.72147L0.838322 6.75234L0.833374 2.22567V2.22562ZM6.27973 7.32457L6.2839 12.564L0.837593 11.8182L0.83728 7.28945L6.27973 7.32457ZM6.94025 1.38981L14.165 0.3396V6.65486L6.94025 6.71192V1.38981ZM14.1667 7.37385L14.165 13.6606L6.9402 12.645L6.93009 7.36207L14.1667 7.37385Z\" fill={color}/>\n </svg>\n )\n}","import React from \"react\"\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface MacOSIconProps extends React.SVGProps<SVGSVGElement> {\n color?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function MacOSIcon({ className, color = 'white', ...props }: MacOSIconProps) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M12.2131 8.41846C12.1971 6.7312 13.5884 5.92054 13.651 5.88193C12.8678 4.73511 11.6515 4.57748 11.2182 4.55979C10.1831 4.45363 9.1978 5.171 8.67145 5.171C8.14509 5.171 7.3347 4.57427 6.47616 4.59196C5.34642 4.60804 4.30494 5.24981 3.72242 6.26314C2.55096 8.29943 3.42394 11.3233 4.56812 12.9784C5.12818 13.7875 5.79254 14.6994 6.66873 14.6657C7.51282 14.6319 7.83056 14.1188 8.84797 14.1188C9.86538 14.1188 10.1526 14.6657 11.0433 14.6496C11.9499 14.6319 12.5244 13.8228 13.0797 13.0106C13.7184 12.0696 13.9831 11.1609 13.9992 11.1126C13.9783 11.1046 12.2324 10.4338 12.2131 8.41846Z\" fill={color} />\n <path d=\"M10.5393 3.46284C11.0047 2.89827 11.3176 2.11496 11.2326 1.33325C10.5634 1.3606 9.75299 1.7804 9.27317 2.34497C8.8431 2.84359 8.46598 3.64138 8.56869 4.407C9.31168 4.4649 10.0755 4.02579 10.5393 3.46284Z\" fill={color} />\n </svg>\n )\n}","import React from \"react\"\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface LinuxIconProps extends React.SVGProps<SVGSVGElement> {}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function LinuxIcon({ className, color = 'white', ...props }: LinuxIconProps) {\n return (\n <svg \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 17 20\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M16.5665 16.3141C16.0389 16.0972 15.6042 15.7556 15.6357 15.1013C15.6664 14.448 15.1694 14.015 15.1694 14.015C15.1694 14.015 15.6042 12.5845 15.2002 11.4033C14.797 10.2204 13.4629 8.32531 12.4392 6.8956C11.4171 5.46507 12.2849 3.81673 11.3549 1.7038C10.4232 -0.409119 8.00404 -0.285272 6.70073 0.616579C5.39654 1.51677 5.79974 3.75437 5.86111 4.8134C5.92335 5.86899 5.88924 6.62142 5.76903 6.89473C5.64629 7.16804 4.8075 8.1707 4.24833 9.00936C3.68999 9.84806 3.2868 11.5894 2.88191 12.3043C2.47872 13.0191 2.7583 13.6716 2.7583 13.6716C2.7583 13.6716 2.47872 13.7639 2.26133 14.2328C2.04395 14.6973 1.61009 14.9151 0.834407 15.0689C0.0587253 15.2243 0.0587252 15.7239 0.244535 16.2834C0.431214 16.8419 0.245404 17.1545 0.0280204 17.8676C-0.189363 18.5808 0.896647 18.8002 1.95108 18.9224C3.00639 19.0479 4.18526 19.732 5.1792 19.8559C6.17056 19.9806 6.48168 19.1726 6.48168 19.1726C6.48168 19.1726 7.59836 18.9224 8.7764 18.8933C9.95615 18.8617 11.0711 19.1419 11.0711 19.1419C11.0711 19.1419 11.2885 19.6389 11.6917 19.8558C12.0958 20.0736 12.9644 20.1052 13.5227 19.5159C14.0819 18.9241 15.5711 18.1793 16.4081 17.7122C17.2476 17.2442 17.0942 16.5302 16.5665 16.3141ZM9.30566 2.60573C9.83756 2.60573 10.2672 3.13438 10.2672 3.78604C10.2672 4.24893 10.0515 4.64779 9.73699 4.84163C9.65685 4.80663 9.57248 4.77076 9.48297 4.73232C9.67222 4.63836 9.80689 4.39669 9.80689 4.11482C9.80689 3.7476 9.58014 3.4495 9.29969 3.4495C9.02267 3.4495 8.79506 3.74843 8.79506 4.11482C8.79506 4.25063 8.82746 4.38129 8.88286 4.48803C8.71748 4.42226 8.56491 4.36078 8.44557 4.31552C8.3808 4.15667 8.34413 3.97732 8.34413 3.786C8.34413 3.13438 8.77376 2.60573 9.30566 2.60573ZM9.23662 5.09444C9.50257 5.18669 9.79836 5.36006 9.76769 5.5317C9.73616 5.70421 9.59634 5.70421 9.23662 5.92458C8.87607 6.14322 8.09525 6.62831 7.84546 6.6599C7.59401 6.6915 7.4542 6.55059 7.18825 6.37891C6.9223 6.20641 6.42193 5.79729 6.54807 5.57953C6.54807 5.57953 6.93763 5.2806 7.10898 5.12433C7.28115 4.96718 7.71932 4.59224 7.98527 4.64094C8.25122 4.68619 8.97067 5.00048 9.23662 5.09444ZM6.83876 2.79277C7.25816 2.79277 7.59911 3.29323 7.59911 3.91072C7.59911 4.02431 7.58804 4.12935 7.56671 4.23099C7.46444 4.26599 7.36043 4.32237 7.25985 4.40777C7.20872 4.44962 7.16351 4.4889 7.12004 4.52818C7.18655 4.4035 7.21295 4.22584 7.18311 4.03881C7.12684 3.70147 6.90266 3.45548 6.68018 3.49052C6.45857 3.52897 6.32472 3.83213 6.38099 4.1712C6.4381 4.51028 6.66145 4.75623 6.88306 4.71949C6.89586 4.71692 6.9078 4.71351 6.92056 4.70923C6.81232 4.81344 6.71258 4.90312 6.61114 4.9791C6.30429 4.83649 6.07924 4.41201 6.07924 3.90981C6.07928 3.2924 6.41936 2.79277 6.83876 2.79277ZM6.01961 18.4997C5.92074 18.9455 5.3999 19.2691 5.3999 19.2691C4.92767 19.4177 3.61495 18.8472 3.01994 18.597C2.4258 18.3502 0.91277 18.2733 0.714157 18.053C0.517243 17.8275 0.813028 17.3313 0.888901 16.8607C0.962206 16.3867 0.740593 16.0903 0.813898 15.7667C0.888901 15.4447 1.85553 15.4447 2.22636 15.2218C2.59885 14.9972 2.67302 14.3515 2.97051 14.1782C3.26799 14.0031 3.8127 14.624 4.03601 14.9733C4.25849 15.3191 5.10151 16.8103 5.44847 17.1827C5.79626 17.5551 6.11848 18.0538 6.01961 18.4997ZM11.5066 14.1679C11.4171 14.606 11.4171 16.1894 11.4171 16.1894C11.4171 16.1894 10.4556 17.5243 8.9647 17.743C7.47554 17.9616 6.73052 17.8044 6.73052 17.8044L5.89343 16.8419C5.89343 16.8419 6.5438 16.7471 6.45177 16.0947C6.35799 15.4422 4.46651 14.5403 4.12468 13.7315C3.78456 12.9244 4.06331 11.5554 4.49804 10.8713C4.93194 10.188 5.20982 8.69685 5.64455 8.19806C6.07928 7.70271 6.4194 6.64537 6.26426 6.17822C6.26426 6.17822 7.19509 7.29787 7.8455 7.11253C8.49674 6.9255 9.95694 5.83657 10.1726 6.02448C10.3891 6.21151 12.2508 10.3135 12.4357 11.6194C12.6224 12.9244 12.3113 13.9185 12.3113 13.9185C12.3113 13.9185 11.5986 13.7323 11.5066 14.1679ZM16.2682 17.0964C15.9784 17.3629 14.3656 18.0154 13.8823 18.5244C13.4015 19.0291 12.7732 19.44 12.3888 19.3204C12.0018 19.1982 11.6651 18.6679 11.8339 17.8941C12.0018 17.1229 12.1476 16.2774 12.1237 15.794C12.0998 15.3106 12.0018 14.6572 12.1237 14.5607C12.2439 14.4668 12.4357 14.5138 12.4357 14.5138C12.4357 14.5138 12.3411 15.4302 12.8943 15.6736C13.4475 15.9127 14.2437 15.5771 14.4849 15.3337C14.727 15.0937 14.8958 14.7316 14.8958 14.7316C14.8958 14.7316 15.1361 14.8537 15.1123 15.2389C15.0884 15.6249 15.2802 16.1818 15.6433 16.3739C16.0039 16.5644 16.558 16.8317 16.2682 17.0964Z\" fill={color}/>\n </svg>\n )\n}","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface CmdIconProps {\n size?: number\n className?: string\n color?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const CmdIcon: React.FC<CmdIconProps> = ({ size = 16, className = '', color='white'}) => {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <path\n d=\"M3 4C3 3.44772 3.44772 3 4 3H20C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4Z\"\n stroke={color}\n />\n <text\n x=\"12\"\n y=\"16\"\n textAnchor=\"middle\"\n fill={color}\n fontSize=\"10\"\n fontFamily=\"monospace\"\n fontWeight=\"bold\"\n >\n \\&gt;\n </text>\n </svg>\n )\n}\n\nCmdIcon.displayName = 'CmdIcon'\n","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface BashIconProps {\n size?: number\n className?: string\n color?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const BashIcon: React.FC<BashIconProps> = ({ size = 16, className = '' , color = 'white'}) => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n className={className}\n viewBox=\"0 0 24 24\">\n <path fill={color}\n d=\"M5 9h2.31l.32-3h2l-.32 3h2l.32-3h2l-.32 3H15v2h-1.9l-.2 2H15v2h-2.31l-.32 3h-2l.32-3h-2l-.32 3h-2l.32-3H5v-2h1.9l.2-2H5zm4.1 2l-.2 2h2l.2-2M19 6h-2v8h2m0 2h-2v2h2Z\" />\n </svg>\n )\n}\n\nBashIcon.displayName = 'BashIcon'\n","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface NushellIconProps {\n size?: number\n className?: string\n color?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const NushellIcon: React.FC<NushellIconProps> = ({ size = 16, className = '', color = 'white' }) => {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n className={className}\n viewBox=\"0 0 24 24\">\n <path\n fill={color}\n d=\"M0 16.338h1.25v-5.7c.417-.624 1.205-1.309 2.127-1.309c1.176 0 1.34.64 1.34 2.247v4.762h1.25v-5.685c0-1.458-.67-2.32-2.202-2.32c-.923 0-1.964.46-2.59 1.264l-.103-1.1H0Zm10.177-7.842h-1.25v5.698c0 1.46.745 2.307 2.263 2.307c.921 0 1.889-.431 2.514-1.22l.104 1.057h1.072V8.496h-1.25v5.773c-.432.67-1.265 1.25-2.129 1.25c-.907 0-1.324-.446-1.324-1.458zm8.11-.997l-.61.952l5.251 3.229l-5.251 3.244l.669.922L24 12.32v-1.28z\" />\n </svg>\n )\n}\n\nNushellIcon.displayName = 'NushellIcon'\n","import React from 'react'\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface DenoIconProps {\n size?: number\n className?: string\n color?: string\n}\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const DenoIcon: React.FC<DenoIconProps> = ({ size = 16, className = '', color = 'white' }) => {\n return (\n <svg\n version=\"1.1\"\n width={size}\n height={size}\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 122.87 122.88\">\n <g>\n <path\n fill={color}\n d=\"M56.6,0.03c-0.29,0.03-1.21,0.14-2.04,0.21C42.74,1.48,31.11,6.48,21.62,14.43c-1.75,1.45-5.74,5.44-7.19,7.19 C6.57,31.01,1.98,41.54,0.28,54.01c-0.38,2.77-0.38,12.1,0,14.87c1.69,12.47,6.29,23,14.14,32.38c1.45,1.75,5.44,5.74,7.19,7.19 C31,116.31,41.54,120.9,54,122.6c2.77,0.38,12.1,0.38,14.87,0c12.47-1.69,23-6.29,32.38-14.14c1.75-1.45,5.74-5.44,7.19-7.19 c7.86-9.38,12.45-19.92,14.14-32.38c0.38-2.77,0.38-12.1,0-14.87c-1.69-12.47-6.29-23-14.14-32.38c-1.45-1.75-5.44-5.74-7.19-7.19 C91.9,6.6,81.26,1.95,68.96,0.3c-1.33-0.18-3.26-0.26-6.85-0.29C59.38-0.01,56.89,0,56.6,0.03L56.6,0.03z M57.36,6.56 c0,1.77,0.12,5.61,0.29,9.25c0.09,1.78,0.2,4.34,0.24,5.67c0.17,4.71,0.67,17.09,0.74,18.19l0.08,1.1l-0.68-0.08 c-0.38-0.03-0.73-0.12-0.79-0.17c-0.05-0.06-0.15-1.1-0.21-2.33c-0.27-5.38-1.16-26.25-1.25-29.3l-0.09-3.35l0.42-0.06 c0.23-0.03,0.6-0.08,0.85-0.09l0.41-0.01L57.36,6.56L57.36,6.56L57.36,6.56z M71.82,6.2c0.02,0.02,0.06,4.58,0.11,10.14 c0.06,5.58,0.14,10.58,0.18,11.12c0.05,0.56,0.03,1.04-0.05,1.07c-0.06,0.05-0.44,0.05-0.82,0l-0.7-0.06l-0.11-4.4 c-0.06-2.43-0.14-5.12-0.17-6c-0.12-2.67-0.23-11.76-0.14-11.98C70.2,5.93,70.37,5.91,71,6.02C71.44,6.11,71.8,6.18,71.82,6.2 L71.82,6.2L71.82,6.2z M36.87,11.26c0.09,0.14,0.8,8.46,1.68,19.36c0.29,3.7,0.57,7.09,0.62,7.51c0.08,0.77,0.06,0.8-0.42,1.1 c-0.27,0.17-0.54,0.3-0.6,0.3c-0.05,0-0.14-0.39-0.18-0.88c-0.21-1.96-1.03-11.45-1.6-18.31c-0.33-4.03-0.63-7.65-0.68-8.04 c-0.08-0.67-0.06-0.73,0.33-0.94C36.49,11.11,36.76,11.06,36.87,11.26L36.87,11.26L36.87,11.26z M78.47,14.3 c0.42,0.15,0.47,0.23,0.56,1.09c0.15,1.51,0.11,8.73-0.06,8.73c-0.44,0-1.35-0.51-1.42-0.8c-0.05-0.18-0.09-2.33-0.09-4.76 C77.45,13.65,77.39,13.93,78.47,14.3L78.47,14.3z M50.56,15.01c0,0.41,0.11,2.66,0.23,5.03c0.12,2.37,0.26,5.38,0.32,6.68 c0.11,2.63,0.14,2.54-0.88,2.6c-0.5,0.02-0.5,0.02-0.53-0.74c-0.03-0.42-0.11-1.74-0.2-2.95c-0.08-1.21-0.26-3.82-0.38-5.82 c-0.12-1.99-0.27-3.97-0.32-4.4c-0.09-0.76-0.08-0.79,0.33-0.94c0.24-0.09,0.67-0.17,0.94-0.17C50.56,14.3,50.56,14.3,50.56,15.01 L50.56,15.01L50.56,15.01z M92.47,17.08l0.51,0.21l0.11,2.02c0.05,1.1,0.08,3.49,0.05,5.29l-0.05,3.29l-0.63-0.32l-0.63-0.3 l-0.05-5.02c-0.03-2.77-0.02-5.11,0.02-5.21C91.85,16.82,91.85,16.82,92.47,17.08L92.47,17.08L92.47,17.08z M64.88,19.06 c0.09,0.09,0.3,7.42,0.32,11.14l0.02,2.24l-0.71-0.11c-0.41-0.05-0.74-0.09-0.76-0.11c-0.05-0.03-0.5-11.23-0.5-12.32v-1.12 l0.77,0.09C64.46,18.94,64.84,19.01,64.88,19.06L64.88,19.06L64.88,19.06z M99.68,20.13c0.18,0.21,0.21,3.52,0.26,21.77 c0.05,20.96,0.05,21.5-0.23,21.5c-0.17,0-0.39-0.09-0.53-0.2c-0.23-0.17-0.26-1.99-0.33-19.9c-0.06-10.85-0.14-20.7-0.18-21.9 l-0.09-2.18l0.44,0.32C99.27,19.74,99.56,19.99,99.68,20.13L99.68,20.13L99.68,20.13z M86.13,23.23c0.08,0.06,0.15,0.92,0.17,1.9 c0.08,3.34,0.09,23.81,0.02,23.88c-0.03,0.03-0.3-0.05-0.6-0.17l-0.54-0.23l0-25.7L85.58,23C85.81,23.06,86.05,23.15,86.13,23.23 L86.13,23.23L86.13,23.23z M44.42,24.07c0.05,0.41,0.12,1.33,0.17,2.09c0.05,0.74,0.15,2.43,0.24,3.75 c0.18,2.66,0.15,2.83-0.71,2.83c-0.45,0-0.51-0.05-0.57-0.5c-0.15-0.89-0.68-8.33-0.6-8.45c0.08-0.11,0.86-0.38,1.22-0.41 C44.26,23.36,44.38,23.68,44.42,24.07L44.42,24.07z M19.43,27.93c0.17,1.6,0.5,4.96,0.74,7.45c0.26,2.49,0.47,4.61,0.47,4.7 c0,0.18-1.16,0.76-1.28,0.63c-0.08-0.08-1.59-13.45-1.59-14.05c0-0.36,1.16-1.89,1.31-1.72C19.13,24.96,19.28,26.31,19.43,27.93 L19.43,27.93z M78.68,29.51l0.44,0.26l0.02,3.26c0.01,1.78,0.05,3.78,0.05,4.43c0.03,1.36-0.14,1.59-0.95,1.3l-0.47-0.17v-1.3 c0-0.73-0.05-2.83-0.11-4.68l-0.09-3.35h0.35C78.09,29.26,78.44,29.38,78.68,29.51L78.68,29.51L78.68,29.51z M26.06,35.38 c0.27,2.9,0.71,7.8,1,10.88l0.51,5.59l-0.59,0.59l-0.57,0.59l-0.11-1.19c-0.06-0.67-0.36-3.75-0.68-6.86 c-0.32-3.11-0.77-7.63-1-10.03l-0.42-4.35l0.59-0.54c0.53-0.5,0.59-0.51,0.7-0.24C25.55,29.95,25.81,32.46,26.06,35.38L26.06,35.38 L26.06,35.38z M14.74,37.2c0.33,2.98,1.21,10.89,1.96,17.59c0.76,6.69,1.47,13.15,1.6,14.36c0.12,1.21,0.33,3.04,0.45,4.08 c0.21,1.77,0.21,1.89-0.03,2.07c-0.36,0.27-0.51,0.24-0.51-0.08c0-0.14-0.14-1.28-0.3-2.52c-0.27-2.07-0.73-5.58-1.74-13.45 c-0.21-1.59-0.62-4.74-0.91-7.03c-0.3-2.28-0.74-5.68-0.98-7.56c-0.24-1.87-0.65-5.08-0.91-7.15c-0.27-2.05-0.44-3.88-0.39-4.08 c0.11-0.41,1-1.83,1.09-1.74C14.11,31.75,14.41,34.21,14.74,37.2L14.74,37.2L14.74,37.2z M10.12,43.72 c0.23,1.81,0.65,5.12,0.94,7.37c0.29,2.24,0.65,5.03,0.82,6.2l0.29,2.12l-0.32,0.27c-0.18,0.15-0.36,0.21-0.42,0.15 c-0.06-0.06-0.18-0.67-0.27-1.33c-0.09-0.67-0.65-4.55-1.25-8.61l-1.07-7.4l0.35-1.03c0.18-0.56,0.38-1.01,0.42-1.01 C9.65,40.44,9.88,41.92,10.12,43.72L10.12,43.72L10.12,43.72z M93.08,41.74c0.21,0.21,0.24,1.15,0.24,8.08v7.84H92.9 c-0.92,0-0.91,0.23-0.97-8.36l-0.05-7.81h0.48C92.63,41.5,92.96,41.6,93.08,41.74L93.08,41.74z M60,44.44 c3.41,0.51,6.39,1.47,9.34,2.98c1.9,0.98,2.81,1.66,4.93,3.69c3.14,3.01,5.08,5.64,6.89,9.35c2.64,5.41,3.67,10.2,4.97,23.04 c0.59,5.76,1.36,16.2,1.53,20.48c0.05,1.24,0.15,3.28,0.24,4.53c0.17,2.66,0.36,2.3-1.98,3.43c-3.25,1.57-6.38,2.66-10.5,3.67 c-5.05,1.24-8.31,1.63-13.3,1.65l-3.63,0.01l0.03-1.74c0-0.95,0.09-3.17,0.18-4.91c0.45-8.42,0.36-19.04-0.23-24.93 c-0.33-3.38-0.98-7.49-1.35-8.4c-0.08-0.2,0.27-0.36,1.77-0.88c2.74-0.95,5.11-2.15,5.47-2.73c0.65-1.12-0.51-2.72-1.99-2.72 c-0.26,0-1.03,0.27-1.74,0.59c-3.39,1.56-10.17,3.39-14.08,3.79c-2.7,0.29-6.91,0.12-9.82-0.41c-1.59-0.29-4.43-1.36-6.8-2.58 c-2.73-1.42-4.41-3.31-4.91-5.55c-0.27-1.21-0.2-3.63,0.15-4.99c0.38-1.5,1.44-3.67,2.4-4.94c4.31-5.67,13.19-10.58,22.3-12.3 C52.78,44.03,56.89,43.97,60,44.44L60,44.44L60,44.44z M106.62,44.91c0.54,0.23,0.6,0.29,0.6,0.8c0.03,4.13-0.06,13.55-0.14,13.95 c-0.02,0.14-0.8,0.15-1.13,0.03c-0.21-0.08-0.24-0.89-0.24-7.56c0-4.77,0.06-7.46,0.15-7.46 C105.94,44.67,106.29,44.77,106.62,44.91L106.62,44.91z M113.22,53.21l0.54,0.23l-0.11,12.51c-0.12,15.94-0.14,16.41-0.71,17.79 c-0.94,2.25-0.89,2.7-0.8-7.18c0.03-4.94,0.11-9.94,0.14-11.11c0.03-1.16,0.06-4.44,0.08-7.3c0-3.45,0.05-5.17,0.15-5.17 C112.6,52.98,112.92,53.09,113.22,53.21L113.22,53.21z M22.34,56.97c0.09,1.22,0.06,1.35-0.38,2.31l-0.48,1.03L21.3,58.8 c-0.29-2.42-0.29-2.52,0.29-2.89c0.26-0.18,0.53-0.3,0.57-0.27C22.21,55.67,22.3,56.27,22.34,56.97L22.34,56.97z M13.01,66.08 c0.14,1.24,1.19,9.46,1.74,13.49c0.82,6.24,0.88,7.13,0.51,6.75c-0.05-0.05-0.39-2.15-0.76-4.67c-2.36-16.29-2.34-16.18-2.15-16.3 C12.76,65.08,12.9,65.23,13.01,66.08L13.01,66.08L13.01,66.08z M23.89,73c0.09,0.38,0.53,4.47,0.53,4.97 c0,0.42-0.54,0.82-0.79,0.57c-0.08-0.08-0.27-1.36-0.42-2.84c-0.17-1.5-0.33-3.05-0.38-3.46l-0.09-0.76l0.53,0.6 C23.57,72.43,23.84,72.84,23.89,73L23.89,73L23.89,73z M36.08,78.7c0.17,0.15,0.27,0.76,0.41,2.39c0.23,2.95,0.26,2.72-0.36,2.72 c-0.63,0-0.62,0.05-0.83-2.61c-0.21-2.7-0.21-2.67,0.2-2.67C35.69,78.52,35.94,78.61,36.08,78.7L36.08,78.7z M48.05,78.93 c0.03,0.15,0.11,1.06,0.17,2.01c0.05,0.95,0.18,3.1,0.3,4.76c0.42,6.1,0.44,6.88,0.18,6.88c-0.29,0-0.32-0.23-0.65-4.53 c-0.12-1.78-0.35-4.59-0.5-6.24c-0.14-1.65-0.23-3.02-0.18-3.05C47.54,78.56,47.97,78.7,48.05,78.93L48.05,78.93L48.05,78.93z M19.64,81.83c0.09,0.14,0.67,4.97,1.37,11.57c0.21,1.99,0.42,3.91,0.47,4.28l0.08,0.65l-0.38-0.24c-0.29-0.2-0.39-0.39-0.39-0.74 c0-0.95-0.65-7.22-1.15-11.06c-0.29-2.18-0.51-4.09-0.51-4.28C19.13,81.69,19.49,81.57,19.64,81.83L19.64,81.83z M106.85,88.14 l-0.11,6.32l-0.38,0.56c-0.86,1.27-0.82,1.51-0.77-5.56l0.03-6.48l0.56-0.57c0.3-0.3,0.6-0.56,0.67-0.56 C106.89,81.84,106.89,84.68,106.85,88.14L106.85,88.14L106.85,88.14z M92.87,98.16c0.08,8.78,0.06,9.46-0.18,9.73 c-0.15,0.17-0.29,0.27-0.33,0.23c-0.11-0.12-0.26-19.27-0.14-19.37c0.06-0.06,0.21-0.09,0.35-0.08 C92.76,88.72,92.81,89.79,92.87,98.16L92.87,98.16L92.87,98.16z M43.52,92.15c0.11,0.94,0.48,5.42,0.63,7.54 c0.09,1.42,0.09,1.47-0.24,1.57c-0.18,0.06-0.39,0.05-0.45-0.03c-0.11-0.11-0.44-3.46-0.85-8.63l-0.11-1.24h0.47 C43.41,91.36,43.44,91.39,43.52,92.15L43.52,92.15z M31.64,97.44c0.11,0.11,0.18,0.48,0.18,0.86c0,0.39,0.18,2.43,0.38,4.55 c0.57,5.79,0.62,6.57,0.36,6.42c-0.39-0.23-0.74-0.57-0.67-0.67c0.03-0.06-0.03-0.82-0.15-1.68c-0.11-0.88-0.24-2.3-0.3-3.17 c-0.06-0.88-0.2-2.48-0.32-3.55c-0.29-2.64-0.27-2.95,0.06-2.95C31.34,97.25,31.53,97.33,31.64,97.44L31.64,97.44L31.64,97.44z M38.79,107.61c0.05,0.33,0.14,1.57,0.2,2.75c0.11,2.27,0.06,2.43-0.56,1.96c-0.18-0.14-0.3-0.71-0.48-2.43 c-0.32-3.11-0.33-2.99,0.26-2.93C38.63,107,38.7,107.06,38.79,107.61L38.79,107.61L38.79,107.61z\" />\n <path\n fill={color}\n d=\"M33.39,51.68c-1.57,0.68-1.69,2.81-0.21,3.57c1.07,0.54,2.16,0.29,2.72-0.65 C36.96,52.87,35.23,50.88,33.39,51.68L33.39,51.68L33.39,51.68z M43.64,53.13c-1.45,0.89-1.45,3.04,0,3.93 c1.44,0.86,3.29-0.27,3.29-1.99C46.93,53.4,45.03,52.29,43.64,53.13L43.64,53.13z\" />\n </g>\n </svg>\n )\n}\nDenoIcon.displayName = 'DenoIcon'","import React from 'react';\nimport { OpenmspLogo, FlamingoLogo, OpenFrameLogo, MiamiCyberGangLogoFaceOnly } from '../components/icons';\nimport { Globe } from 'lucide-react';\nimport type { SelectableOption } from '../components/features';\nimport type { PlatformConfig } from '../types/platform';\n\n// Platform icons mapping with consistent colors matching app theme\nexport const platformIcons = {\n openframe: <OpenFrameLogo className=\"h-5 w-5\" lowerPathColor=\"#FFC008\" upperPathColor=\"#ffffff\" />,\n openmsp: <OpenmspLogo className=\"h-5 w-5\" />,\n flamingo: <FlamingoLogo className=\"h-5 w-5\" fill=\"#EC4899\" />,\n 'flamingo-teaser': <FlamingoLogo className=\"h-5 w-5\" fill=\"#EC4899\" />,\n 'marketing-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#F357BB\" />,\n 'product-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#5EA62E\" />,\n 'revenue-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#FFC008\" />,\n 'people-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#5EFAF0\" />,\n 'company-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#f36666\" />,\n tmcg: <MiamiCyberGangLogoFaceOnly className=\"h-5 w-5\" />,\n universal: <Globe className=\"h-5 w-5 text-[#10B981]\" />\n};\n\n// Platform colors mapping\nexport const platformColors = {\n openmsp: 'bg-[#3B82F6]',\n openframe: 'bg-[#8B5CF6]',\n flamingo: 'bg-[#EC4899]',\n 'flamingo-teaser': 'bg-[#F59E0B]',\n 'marketing-hub': 'bg-[#F357BB]',\n 'product-hub': 'bg-[#5EA62E]',\n 'revenue-hub': 'bg-[#FFC008]',\n 'people-hub': 'bg-[#5EFAF0]',\n 'company-hub': 'bg-[#f36666]',\n tmcg: 'bg-[#FF6B6B]',\n universal: 'bg-[#10B981]'\n};\n\n// Platform display names for consistent naming across the app\nexport const platformDisplayNames = {\n openmsp: 'OpenMSP',\n openframe: 'OpenFrame',\n flamingo: 'Flamingo',\n 'flamingo-teaser': 'Flamingo Teaser',\n 'marketing-hub': 'Flamingo Marketing Hub',\n 'product-hub': 'Flamingo Product Hub',\n 'revenue-hub': 'Flamingo Revenue Hub',\n 'people-hub': 'Flamingo People Hub',\n 'company-hub': 'Flamingo Company Hub',\n tmcg: 'TMCG',\n universal: 'Universal'\n};\n\n// Platform descriptions for consistent messaging across the app\nexport const platformDescriptions = {\n openmsp: 'Comprehensive directory and comparison platform for managed service providers (MSPs) and technology vendors. Reduce vendor costs and discover open-source alternatives.',\n openframe: 'AI-driven open-source security operations center (SOC) and endpoint detection platform for MSPs.',\n flamingo: 'AI-driven open-source OS for MSPs. Swap bloated vendor tools for open ones. Automate the boring crap. Take your margin back.',\n 'flamingo-teaser': 'Preview of Flamingo - the AI-driven open-source OS for MSPs.',\n tmcg: 'The Miami Cyber Gang - A cybersecurity community focused on education and collaboration.',\n universal: 'Cross-platform universal content.'\n};\n\n// Platform slogans for branding consistency\nexport const platformSlogans = {\n openmsp: 'Find Your Perfect MSP Partner',\n openframe: 'Open-Source Security Operations',\n flamingo: 'Open-Source OS for MSPs',\n 'flamingo-teaser': 'Coming Soon: Open-Source OS for MSPs',\n tmcg: 'Miami Cyber Community',\n universal: 'Universal Platform'\n};\n\n// Platform hex colors for default configuration\nexport const platformHexColors = {\n openmsp: '#FFC008',\n openframe: '#FFC008',\n flamingo: '#FF6B9D',\n universal: '#FFC008',\n 'flamingo-teaser': '#F59E0B',\n 'marketing-hub': '#F357BB',\n 'product-hub': '#5EA62E',\n 'revenue-hub': '#FFC008',\n 'people-hub': '#5EFAF0',\n 'company-hub': '#f36666',\n tmcg: '#FF6B6B'\n};\n\n// Platform icon names for default configuration\nexport const platformIconNames = {\n openmsp: 'openmsp-logo',\n openframe: 'openframe-logo',\n flamingo: 'flamingo-logo',\n universal: 'globe',\n 'flamingo-teaser': 'flamingo-logo',\n 'marketing-hub': 'flamingo-logo',\n 'product-hub': 'flamingo-logo',\n 'revenue-hub': 'flamingo-logo',\n 'people-hub': 'flamingo-logo',\n 'company-hub': 'flamingo-logo',\n tmcg: 'tmcg-logo'\n};\n\n/**\n * Get default color for platform\n */\nexport function getDefaultColorForPlatform(platformName: string): string {\n return platformHexColors[platformName as keyof typeof platformHexColors] || platformHexColors.universal;\n}\n\n/**\n * Get default icon name for platform\n */\nexport function getDefaultIconForPlatform(platformName: string): string {\n return platformIconNames[platformName as keyof typeof platformIconNames] || platformIconNames.universal;\n}\n\nexport function transformPlatformConfigsToOptions(platformConfigs: PlatformConfig[]): SelectableOption[] {\n return platformConfigs.map((platform: PlatformConfig) => ({\n id: platform.id, // Database UUID for matching\n name: platform.name, // Platform name enum\n displayName: platform.display_name, // Human-readable name\n description: platform.description,\n icon: platformIcons[platform.name as keyof typeof platformIcons] || platformIcons.universal,\n color: platformColors[platform.name as keyof typeof platformColors] || platformColors.universal\n }));\n}\n\n/**\n * Get platform icon by name\n */\nexport function getPlatformIcon(platformName: string) {\n return platformIcons[platformName as keyof typeof platformIcons] || platformIcons.universal;\n}\n\n/**\n * Get platform color by name\n */\nexport function getPlatformColor(platformName: string) {\n return platformColors[platformName as keyof typeof platformColors] || platformColors.universal;\n}\n\n/**\n * Get platform display name by name\n */\nexport function getPlatformDisplayName(platformName: string): string {\n return platformDisplayNames[platformName as keyof typeof platformDisplayNames] || platformName;\n}\n\n/**\n * Get platform description by name\n */\nexport function getPlatformDescription(platformName: string): string {\n return platformDescriptions[platformName as keyof typeof platformDescriptions] || platformName;\n}\n\n/**\n * Get platform slogan by name\n */\nexport function getPlatformSlogan(platformName: string): string {\n return platformSlogans[platformName as keyof typeof platformSlogans] || platformName;\n}\n\n/**\n * Get small platform icon for filter buttons with white colors (4x4 size)\n */\nexport function getSmallPlatformIcon(platformName: string): React.ReactNode {\n const className = \"h-4 w-4 flex-shrink-0\";\n\n switch (platformName) {\n case 'openframe':\n return <OpenFrameLogo className={className} lowerPathColor=\"#FFC008\" upperPathColor=\"#ffffff\" />;\n case 'openmsp':\n return <OpenmspLogo className={className} frontBubbleColor=\"#f1f1f1\" innerFrontBubbleColor=\"#000000\" backBubbleColor=\"#FFC008\" />;\n case 'flamingo':\n case 'flamingo-teaser':\n return <FlamingoLogo className={`${className}`} fill=\"#EC4899\" />;\n case 'marketing-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-pink-base)\" />;\n case 'product-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-green-success)\" />;\n case 'revenue-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-yellow-warning)\" />;\n case 'people-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-cyan-base)\" />;\n case 'company-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-red-error)\" />;\n case 'tmcg':\n return <MiamiCyberGangLogoFaceOnly className={className} />;\n case 'universal':\n default:\n return <Globe className={className} />;\n }\n}\n\n/**\n * Get platform icon for admin/selector components (standard 6x6 size)\n */\nexport function getPlatformIconComponent(platformName: string, className: string = \"h-6 w-6\"): React.ReactNode {\n switch (platformName) {\n case 'openframe':\n return <OpenFrameLogo className={className} />;\n case 'openmsp':\n return <OpenmspLogo className={className} color=\"#f1f1f1\" />;\n case 'flamingo':\n case 'flamingo-teaser':\n return <FlamingoLogo className={`${className} text-white`} />;\n case 'marketing-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-pink-base)\" />;\n case 'product-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-green-success)\" />;\n case 'revenue-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-yellow-warning)\" />;\n case 'people-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-cyan-base)\" />;\n case 'company-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-red-error)\" />;\n case 'tmcg':\n return <MiamiCyberGangLogoFaceOnly size={24} className={className} />;\n case 'universal':\n default:\n return <Globe className={className} />;\n }\n}","import type { ComponentType } from 'react';\nimport { WindowsIcon, LinuxIcon, MacOSIcon } from '../components/icons';\n\n// OS-level platforms (Windows, Linux, MacOS)\n\nexport type OSPlatformId = 'windows' | 'linux' | 'darwin';\n\nexport interface OSPlatformOption {\n id: OSPlatformId;\n name: string;\n icon: ComponentType<any>;\n}\n\nexport const OS_PLATFORMS: OSPlatformOption[] = [\n { id: 'windows', name: 'Windows', icon: WindowsIcon },\n { id: 'linux', name: 'Linux', icon: LinuxIcon },\n { id: 'darwin', name: 'MacOS', icon: MacOSIcon }\n];\n\nexport const DEFAULT_OS_PLATFORM: OSPlatformId = 'windows';\n\n\n","/**\n * Access Code Client Utilities — pure standalone functions.\n *\n * Endpoint paths are NOT hardcoded — every function takes an\n * `endpoints` argument. The React-side wrapper that binds them from\n * `EndpointsRuntimeContext` lives separately at\n * `hooks/use-access-code-integration.ts` (`useAccessCodeIntegration`).\n *\n * Keep this file **free of React imports** — it lives in the\n * server-safe `utils/index` tsup bundle. Any module-top-level call\n * into `createContext()` (which the runtime context file does) would\n * be pulled into the server bundle and crash SSR with\n * `createContext is not a function`.\n */\n\nimport {\n AccessCodeValidation,\n AccessCodeValidationResponse,\n AccessCodeConsumptionResponse\n} from '../types/access-code-cohorts';\n\n/** Endpoints required by the standalone client utilities. The\n * `useAccessCodeIntegration` hook (in `hooks/`) resolves these from\n * `EndpointsRuntimeContext.accessCode` automatically. */\nexport interface AccessCodeEndpoints {\n validateUrl: string\n consumeUrl: string\n}\n\n/**\n * Validate an access code for a given email\n *\n * @param email - User's email address\n * @param code - Access code to validate\n * @returns Promise with validation result\n *\n * @example\n * const result = await validateAccessCode('user@example.com', 'ABC123XY');\n * if (result.valid) {\n * // Allow user to proceed with registration\n * console.log(`Welcome to ${result.cohort_name}!`);\n * } else {\n * // Show error message\n * console.error(result.message);\n * }\n */\nexport async function validateAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeValidationResponse> {\n try {\n const response = await fetch(endpoints.validateUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email, code } as AccessCodeValidation),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || 'Validation request failed');\n }\n\n return await response.json() as AccessCodeValidationResponse;\n } catch (error) {\n return {\n valid: false,\n message: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n}\n\n/**\n * Consume an access code after successful registration\n *\n * Call this ONLY after the user has successfully completed registration.\n * This marks the code as used and prevents further usage.\n *\n * @param email - User's email address\n * @param code - Access code to consume\n * @returns Promise with consumption result\n *\n * @example\n * // After successful registration\n * const result = await consumeAccessCode('user@example.com', 'ABC123XY');\n * if (result.consumed) {\n * console.log('Access code consumed successfully');\n * } else {\n * console.warn('Failed to consume access code:', result.message);\n * }\n */\nexport async function consumeAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeConsumptionResponse> {\n try {\n const response = await fetch(endpoints.consumeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email, code } as AccessCodeValidation),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || 'Consumption request failed');\n }\n\n return await response.json() as AccessCodeConsumptionResponse;\n } catch (error) {\n return {\n success: false,\n consumed: false,\n message: error instanceof Error ? error.message : 'Consumption failed',\n };\n }\n}\n\n/**\n * Complete access code flow: validate then consume\n *\n * This is a convenience function that validates an access code and,\n * if valid, immediately consumes it. Use this when you want to\n * validate and consume in one step during registration.\n *\n * @param email - User's email address\n * @param code - Access code to validate and consume\n * @returns Promise with validation and consumption results\n *\n * @example\n * const result = await validateAndConsumeAccessCode('user@example.com', 'ABC123XY');\n * if (result.valid && result.consumed) {\n * // Registration successful\n * console.log(`Welcome to ${result.cohort_name}!`);\n * } else {\n * console.error(result.message);\n * }\n */\nexport async function validateAndConsumeAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeValidationResponse & { consumed?: boolean }> {\n // First validate\n const validation = await validateAccessCode(email, code, endpoints);\n\n if (!validation.valid) {\n return validation;\n }\n\n // If valid, consume the code\n const consumption = await consumeAccessCode(email, code, endpoints);\n\n return {\n ...validation,\n consumed: consumption.consumed,\n message: consumption.consumed\n ? `Access granted for ${validation.cohort_name}`\n : consumption.message || validation.message,\n };\n}\n\n// `useAccessCodeIntegration` (the React-side wrapper) lives in\n// `hooks/use-access-code-integration.ts`. It binds the endpoints from\n// `EndpointsRuntimeContext` so React callers don't have to plumb URLs.\n","/**\n * Email Domain Validation Utilities\n *\n * Validates email domain formats (the part after @ in email addresses)\n * Used for SSO domain allowlist feature to restrict auto-provisioning to specific domains.\n */\n\n/**\n * Validates an email domain format (the part after @ in email addresses)\n * Valid: example.com, sub.domain.org, my-company.co.uk\n * Invalid: http://example.com, @example.com, example, .com\n *\n * @param domain - The domain string to validate\n * @returns true if the domain is a valid email domain format\n */\nexport function isValidEmailDomain(domain: string): boolean {\n if (!domain || typeof domain !== 'string') {\n return false\n }\n\n const trimmed = domain.trim()\n if (!trimmed) {\n return false\n }\n\n // Domain regex: must have at least one dot, valid characters, and proper TLD\n // Allows subdomains, hyphens (not at start/end of labels), alphanumeric characters\n const domainRegex = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\\.[A-Za-z0-9-]{1,63})*\\.[A-Za-z]{2,}$/\n return domainRegex.test(trimmed)\n}\n\n/**\n * Validation result type\n */\nexport interface EmailDomainValidationResult {\n valid: boolean\n error?: string\n cleanedDomain?: string\n}\n\n/**\n * Validates an email domain with detailed error messages\n * Also cleans the input (removes leading @, trims whitespace)\n *\n * @param domain - The domain string to validate\n * @returns Validation result with error message if invalid\n */\nexport function validateEmailDomain(domain: string): EmailDomainValidationResult {\n if (!domain || typeof domain !== 'string') {\n return { valid: false, error: 'Email domain is required' }\n }\n\n // Clean the input: trim and remove leading @ if user enters it\n let trimmed = domain.trim()\n if (trimmed.startsWith('@')) {\n trimmed = trimmed.substring(1)\n }\n\n // Check for empty after cleaning\n if (!trimmed) {\n return { valid: false, error: 'Email domain is required' }\n }\n\n // Check for protocol (common mistake: entering full URL)\n if (trimmed.includes('://')) {\n return { valid: false, error: 'Enter email domain only (e.g., openframe.ai), not a URL' }\n }\n\n // Check for @ symbol (common mistake: entering full email address)\n if (trimmed.includes('@')) {\n return { valid: false, error: 'Enter domain only, not a full email address' }\n }\n\n // Check for spaces\n if (trimmed.includes(' ')) {\n return { valid: false, error: 'Domain cannot contain spaces' }\n }\n\n // Check for trailing slash\n if (trimmed.includes('/')) {\n return { valid: false, error: 'Enter domain only, without paths' }\n }\n\n // Validate the domain format\n if (!isValidEmailDomain(trimmed)) {\n return { valid: false, error: 'Invalid domain format (e.g., openframe.ai)' }\n }\n\n // Return success with the cleaned domain\n return { valid: true, cleanedDomain: trimmed.toLowerCase() }\n}\n\n/**\n * Validates a list of email domains\n * Returns the first error encountered or success if all domains are valid\n *\n * @param domains - Array of domain strings to validate\n * @returns Validation result with array of cleaned domains if valid\n */\nexport function validateEmailDomainList(domains: string[]): {\n valid: boolean\n error?: string\n cleanedDomains?: string[]\n} {\n if (!Array.isArray(domains)) {\n return { valid: false, error: 'Domains must be an array' }\n }\n\n const cleanedDomains: string[] = []\n const seenDomains = new Set<string>()\n\n for (const domain of domains) {\n const result = validateEmailDomain(domain)\n\n if (!result.valid) {\n return { valid: false, error: `Invalid domain \"${domain}\": ${result.error}` }\n }\n\n const cleanedDomain = result.cleanedDomain!\n\n // Check for duplicates (case-insensitive)\n if (seenDomains.has(cleanedDomain)) {\n return { valid: false, error: `Duplicate domain: ${cleanedDomain}` }\n }\n\n seenDomains.add(cleanedDomain)\n cleanedDomains.push(cleanedDomain)\n }\n\n return { valid: true, cleanedDomains }\n}\n\n/**\n * Cleans a domain string by removing common user input mistakes\n * Does NOT validate - use validateEmailDomain for validation\n *\n * @param domain - The domain string to clean\n * @returns Cleaned domain string\n */\nexport function cleanEmailDomain(domain: string): string {\n if (!domain || typeof domain !== 'string') {\n return ''\n }\n\n let cleaned = domain.trim().toLowerCase()\n\n // Remove leading @\n if (cleaned.startsWith('@')) {\n cleaned = cleaned.substring(1)\n }\n\n // Remove protocol if present\n cleaned = cleaned.replace(/^https?:\\/\\//, '')\n\n // Remove trailing slash and path\n cleaned = cleaned.split('/')[0]\n\n // Remove www. prefix\n cleaned = cleaned.replace(/^www\\./, '')\n\n return cleaned\n}\n","/**\n * Confidence helpers for AI enrichment\n * Shared utilities for displaying confidence levels from AI operations\n */\n\n/**\n * Get Tailwind CSS classes for confidence badge display (border and text color)\n * @param confidence - Confidence score (0-100)\n * @returns CSS classes for border and text color\n */\nexport function getConfidenceColorClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'border-green-500 text-green-500';\n if (confidence >= 50) return 'border-yellow-500 text-yellow-500';\n return 'border-red-500 text-red-500';\n}\n\n/**\n * Get confidence level category\n * @param confidence - Confidence score (0-100)\n * @returns Confidence level category\n */\nexport function getConfidenceLevel(confidence?: number): 'high' | 'medium' | 'low' | 'none' {\n if (!confidence && confidence !== 0) return 'none';\n if (confidence >= 80) return 'high';\n if (confidence >= 50) return 'medium';\n return 'low';\n}\n\n/**\n * Get Tailwind CSS class for border color only\n * @param confidence - Confidence score (0-100)\n * @returns CSS class for border color\n */\nexport function getConfidenceBorderClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'border-green-500';\n if (confidence >= 50) return 'border-yellow-500';\n return 'border-red-500';\n}\n\n/**\n * Get Tailwind CSS class for text color only\n * @param confidence - Confidence score (0-100)\n * @returns CSS class for text color\n */\nexport function getConfidenceTextClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'text-green-500';\n if (confidence >= 50) return 'text-yellow-500';\n return 'text-red-500';\n}\n\n/**\n * Get Tailwind CSS class for background color (subtle)\n * @param confidence - Confidence score (0-100)\n * @returns CSS class for subtle background color\n */\nexport function getConfidenceBgClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'bg-green-500/10';\n if (confidence >= 50) return 'bg-yellow-500/10';\n return 'bg-red-500/10';\n}\n\n/**\n * Get descriptive label for confidence level\n * @param confidence - Confidence score (0-100)\n * @returns Human-readable confidence label\n */\nexport function getConfidenceLabel(confidence?: number): string {\n if (!confidence && confidence !== 0) return 'Unknown';\n if (confidence >= 80) return 'High';\n if (confidence >= 50) return 'Medium';\n return 'Low';\n}\n","/**\n * Shared Date Formatting Utilities\n * Single source of truth for date formatting across the application\n */\n\nconst MONTHS_LONG = [\n 'January', 'February', 'March', 'April', 'May', 'June',\n 'July', 'August', 'September', 'October', 'November', 'December',\n] as const\n\nconst MONTHS_SHORT = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\n] as const\n\n/**\n * Split an ISO date / date-time string into `[year, month, day]` strings.\n * Internal — date-only inputs avoid the `new Date(...)` timezone shift\n * (which renders `\"2025-11-11\"` as Nov 10 west of UTC).\n */\nfunction splitYmd(dateString: string): [string, string, string] | null {\n const head = dateString.split('T')[0]\n const parts = head.split('-')\n if (parts.length !== 3) return null\n return [parts[0], parts[1], parts[2]]\n}\n\n/**\n * Format release date — avoids timezone shifts.\n * @returns e.g. `\"November 11, 2025\"`\n */\nexport function formatReleaseDate(dateString: string): string {\n const ymd = splitYmd(dateString)\n if (!ymd) return dateString\n const [year, month, day] = ymd\n return `${MONTHS_LONG[parseInt(month) - 1]} ${parseInt(day)}, ${year}`\n}\n\n/**\n * Short-form date — `\"Jan 5, 2025\"`. Same TZ-safe parsing as\n * `formatReleaseDate`; differs only in month abbreviation. Single source\n * of truth for the short-month-day-year shape used across hub admin\n * cards (waitlist, publication, media, investor, campaign, etc.) and\n * lib chat cards (campaign-card-admin).\n */\nexport function formatDateShort(dateString: string): string {\n const ymd = splitYmd(dateString)\n if (!ymd) return dateString\n const [year, month, day] = ymd\n return `${MONTHS_SHORT[parseInt(month) - 1]} ${parseInt(day)}, ${year}`\n}\n\n/**\n * Slash-form date — `\"11/11/2025\"`. TZ-safe (string-split, no\n * `new Date(...)`). Used by hub admin product-release + customer-\n * interview cards where the compact MM/DD/YYYY layout is desired.\n */\nexport function formatDateSlashUTC(dateString: string): string {\n const ymd = splitYmd(dateString)\n if (!ymd) return dateString\n const [year, month, day] = ymd\n return `${month}/${day}/${year}`\n}\n","/**\n * Icon registry — string `icon_name` → React component.\n *\n * SINGLE SOURCE OF TRUTH (no, really this time) for every icon-name →\n * React-component lookup across the lib + the hub. Two DB columns feed\n * in with DIFFERENT conventions:\n *\n * - `chat_admin_slash_commands.icon_name` — kebab-case (`'rocket'`,\n * `'hubspot'`, `'github'`, `'dollar-sign'`).\n * - `social_platforms.icon_name` — PascalCase component names\n * (`'LinkedInIcon'`, `'XLogo'`, `'YouTubeIcon'`, `'Github'`).\n *\n * The registry stores entries under kebab-case keys (URL/DB-friendly,\n * shell-safe, matches `lucide-react`'s own file-naming convention).\n * The PascalCase variants come in via `normalizeIconKey()`, which maps\n * known PascalCase aliases → kebab-case before the lookup runs.\n *\n * Adding a new icon: import the component below, add a `'name': Component`\n * entry in `ICON_REGISTRY`, and (if the same icon also flows in from a DB\n * column that uses PascalCase) add a `PascalName → 'name'` row to\n * `PASCAL_TO_KEBAB_ALIASES`.\n *\n * Fallback: an unknown / null icon_name resolves to `FileText` so a chip\n * never renders without an icon.\n */\n\nimport { createElement, type ComponentType, type ReactNode } from 'react'\nimport {\n Activity,\n Banknote,\n Bell,\n BookOpen,\n Box,\n Briefcase,\n Calendar,\n CheckSquare,\n DollarSign,\n Facebook,\n FileText,\n Github,\n Globe,\n GraduationCap,\n Headphones,\n Info,\n Instagram,\n Mail,\n Megaphone,\n MessageCircle,\n MessageSquare,\n Newspaper,\n Package,\n PenSquare,\n Rocket,\n Search,\n Send,\n Shield,\n Star,\n TableProperties,\n TrendingUp,\n Twitter,\n Users,\n Video,\n Youtube,\n} from 'lucide-react'\n// Brand icons — lib-local exports.\nimport {\n SlackIcon,\n GitHubIcon,\n ClickUpIcon,\n HubspotIcon,\n LinkedInIcon,\n FacebookIcon,\n InstagramIcon,\n YouTubeIcon,\n XLogo,\n OpenFrameLogo as RawOpenFrameLogo,\n} from '../../icons'\n\n// Wrapper so the OpenFrame logo's outer frame inherits the parent's text\n// color instead of its hardcoded default — that default is invisible on\n// dark chat surfaces. The white squares stay white (visible on dark).\n// With this, the parent's `text-ods-text-primary` propagates via\n// `currentColor` and the frame renders in the same primary text color\n// as the lucide icons next to it. Uses `createElement` (not JSX) so this\n// stays a `.ts` file. Accepts `color` for shape-compat with the registry's\n// IconComponent type, but ignores it — the logo's outer frame is wired\n// to `currentColor` via the upperPathColor pass-through.\nconst OpenFrameLogoIcon: ComponentType<{ className?: string; color?: string }> = ({ className }) =>\n createElement(RawOpenFrameLogo, { className, upperPathColor: 'currentColor' })\n\n/**\n * Loose icon-component shape: every entry accepts `className`; `color` is\n * optional (lucide + most brand icons accept it; OpenFrameLogo doesn't,\n * but `color` is optional so passing `undefined` is a no-op). Loose enough\n * to accept both lucide's `LucideIcon` and our brand SVG components.\n */\ntype IconComponent = ComponentType<{ className?: string; color?: string }>\n\n/**\n * The kebab-case registry. ALL lookups go through here; PascalCase\n * aliases route through `normalizeIconKey()` first.\n */\nexport const ICON_REGISTRY: Record<string, IconComponent> = {\n // lucide-react (kebab-case)\n activity: Activity,\n banknote: Banknote,\n bell: Bell,\n 'book-open': BookOpen,\n box: Box,\n briefcase: Briefcase,\n calendar: Calendar,\n 'check-square': CheckSquare,\n 'dollar-sign': DollarSign,\n // For brand-vs-lucide variants the kebab key is the BRAND (most-common\n // social-platform intent); `'<name>-lucide'` carries the lucide outline.\n facebook: FacebookIcon,\n 'facebook-lucide': Facebook,\n 'file-text': FileText,\n // `'github-lucide'` is the lucide outline glyph (used by\n // `social_platforms.icon_name='Github'`); `'github'` is the brand icon\n // (used by `chat_admin_slash_commands.icon_name='github'`). The PascalCase\n // alias `'Github' → 'github-lucide'` routes the lucide glyph for\n // social-platform DB rows; `'GitHubIcon' → 'github'` keeps brand routing\n // consistent for callers that store the PascalCase component name.\n github: GitHubIcon,\n 'github-lucide': Github,\n globe: Globe,\n 'graduation-cap': GraduationCap,\n headphones: Headphones,\n info: Info,\n instagram: InstagramIcon,\n 'instagram-lucide': Instagram,\n mail: Mail,\n megaphone: Megaphone,\n 'message-circle': MessageCircle,\n 'message-square': MessageSquare,\n newspaper: Newspaper,\n package: Package,\n 'pen-square': PenSquare,\n rocket: Rocket,\n search: Search,\n send: Send,\n shield: Shield,\n star: Star,\n table: TableProperties,\n 'trending-up': TrendingUp,\n twitter: Twitter,\n users: Users,\n video: Video,\n youtube: YouTubeIcon,\n 'youtube-lucide': Youtube,\n // brand-only icons (no lucide variant in current use)\n slack: SlackIcon,\n clickup: ClickUpIcon,\n hubspot: HubspotIcon,\n linkedin: LinkedInIcon,\n x: XLogo,\n openframe: OpenFrameLogoIcon,\n}\n\n/**\n * PascalCase → kebab-case alias table for DB columns that store icon\n * names as component identifiers (currently `social_platforms.icon_name`).\n * Keep these in sync with the actual rows in those tables.\n */\nconst PASCAL_TO_KEBAB_ALIASES: Record<string, string> = {\n // Lucide PascalCase names → kebab equivalents\n Activity: 'activity',\n Banknote: 'banknote',\n Bell: 'bell',\n BookOpen: 'book-open',\n Box: 'box',\n Briefcase: 'briefcase',\n Calendar: 'calendar',\n CheckSquare: 'check-square',\n DollarSign: 'dollar-sign',\n // Lucide PascalCase → the `-lucide` kebab variant (kebab default is the\n // brand icon for the social-platform names below).\n Facebook: 'facebook-lucide',\n FileText: 'file-text',\n Github: 'github-lucide',\n Globe: 'globe',\n GraduationCap: 'graduation-cap',\n Headphones: 'headphones',\n Info: 'info',\n Instagram: 'instagram-lucide',\n Mail: 'mail',\n Megaphone: 'megaphone',\n MessageCircle: 'message-circle',\n MessageSquare: 'message-square',\n Newspaper: 'newspaper',\n Package: 'package',\n PenSquare: 'pen-square',\n Rocket: 'rocket',\n Search: 'search',\n Send: 'send',\n Shield: 'shield',\n Star: 'star',\n TableProperties: 'table',\n TrendingUp: 'trending-up',\n Twitter: 'twitter',\n Users: 'users',\n Video: 'video',\n Youtube: 'youtube-lucide',\n // Brand-icon PascalCase exports → kebab (kebab default is the brand)\n SlackIcon: 'slack',\n GitHubIcon: 'github',\n ClickUpIcon: 'clickup',\n HubspotIcon: 'hubspot',\n LinkedInIcon: 'linkedin',\n FacebookIcon: 'facebook',\n InstagramIcon: 'instagram',\n YouTubeIcon: 'youtube',\n XLogo: 'x',\n OpenFrameLogo: 'openframe',\n}\n\n/**\n * Normalize an icon key to the registry's canonical kebab-case form.\n * Accepts PascalCase variants (from `social_platforms.icon_name`-style\n * columns) and passes kebab-case keys through unchanged.\n */\nexport function normalizeIconKey(key: string): string {\n return PASCAL_TO_KEBAB_ALIASES[key] ?? key\n}\n\n/**\n * Resolve an `icon_name` to its React component. Accepts both PascalCase\n * and kebab-case keys (normalizes PascalCase first). Unknown / null /\n * undefined names fall back to `FileText` — chips always render with\n * SOMETHING rather than a missing glyph. The fallback is intentional:\n * a typo in a new admin-authored row shouldn't crash render.\n */\nexport function getIconComponent(\n iconName: string | null | undefined,\n): ComponentType<{ className?: string; color?: string }> {\n if (!iconName) return FileText\n return ICON_REGISTRY[normalizeIconKey(iconName)] ?? FileText\n}\n\n// ---------------------------------------------------------------------------\n// Sized-icon rendering helper (migrated from `src/utils/dynamic-icons.tsx`)\n// ---------------------------------------------------------------------------\n\nexport type DynamicIconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n\nconst SIZE_CLASSES: Record<DynamicIconSize, string> = {\n xs: 'w-3 h-3', // 12px\n sm: 'w-4 h-4', // 16px\n md: 'w-6 h-6', // 24px\n lg: 'w-8 h-8', // 32px\n xl: 'w-12 h-12', // 48px\n}\n\n/**\n * Optional per-icon color overrides. Keys are kebab-case (canonical\n * registry form) — pass any incoming key through `normalizeIconKey()`\n * before lookup.\n */\nconst ICON_COLORS: Record<string, { color?: string; fill?: string }> = {\n linkedin: { color: '#0A66C2' },\n facebook: { color: '#1877F2' },\n youtube: { color: '#FF0000' },\n}\n\n/**\n * Render an icon by name with a size preset + optional className.\n * Replaces the old `src/utils/dynamic-icons.tsx#getDynamicIcon`. Accepts\n * both PascalCase and kebab-case keys (via `normalizeIconKey()`).\n */\nexport function getDynamicIcon(\n iconName: string | undefined | null,\n size: DynamicIconSize = 'md',\n className?: string,\n): ReactNode {\n if (!iconName) {\n console.warn('[getDynamicIcon] No iconName provided, using Globe fallback')\n return createElement(Globe, { className: SIZE_CLASSES[size] })\n }\n\n const sizeClass = SIZE_CLASSES[size]\n const finalClassName = className ? `${sizeClass} ${className}` : sizeClass\n\n const canonicalKey = normalizeIconKey(iconName)\n const IconComponent = ICON_REGISTRY[canonicalKey]\n\n if (IconComponent) {\n const colorConfig = ICON_COLORS[canonicalKey] || {}\n return createElement(IconComponent, { className: finalClassName, ...colorConfig })\n }\n\n console.error(\n `[getDynamicIcon] Icon NOT found in registry: \"${iconName}\" (normalized to \"${canonicalKey}\"). Available icons:`,\n Object.keys(ICON_REGISTRY),\n )\n return createElement(Globe, { className: finalClassName })\n}\n","/**\n * Centralized Tool Types\n *\n * Single source of truth for all tool-related types across the entire platform.\n * Used by ToolBadge, ToolIcon, and any component that needs tool type information.\n */\n\nexport const ToolTypeValues = {\n TACTICAL_RMM: 'TACTICAL_RMM',\n FLEET_MDM: 'FLEET_MDM',\n MESHCENTRAL: 'MESHCENTRAL',\n AUTHENTIK: 'AUTHENTIK',\n OPENFRAME: 'OPENFRAME',\n OPENFRAME_CHAT: 'OPENFRAME_CHAT',\n OPENFRAME_CLIENT: 'OPENFRAME_CLIENT',\n OSQUERY: 'OSQUERY',\n SYSTEM: 'SYSTEM'\n} as const\n\nexport type ToolType = (typeof ToolTypeValues)[keyof typeof ToolTypeValues]\n\n/**\n * Maps tool types to display labels\n */\nexport const toolLabels: Record<ToolType, string> = {\n TACTICAL_RMM: 'Tactical',\n FLEET_MDM: 'Fleet',\n MESHCENTRAL: 'MeshCentral',\n AUTHENTIK: 'Authentik',\n OPENFRAME: 'OpenFrame',\n OPENFRAME_CHAT: 'OpenFrame Chat',\n OPENFRAME_CLIENT: 'OpenFrame Client',\n OSQUERY: 'Osquery',\n SYSTEM: 'System'\n}\n","/**\n * Tool Utilities\n *\n * Provides normalization and conversion utilities for tool types.\n * Handles various input formats (aliases, case variations) and converts\n * them to the canonical ToolType used throughout the platform.\n */\n\nimport { ToolType, toolLabels } from '../types/tool.types'\n\n/**\n * Map of common tool name variants to canonical ToolType\n */\nconst toolAliasMap: Record<string, ToolType> = {\n // Tactical RMM\n 'TACTICAL': 'TACTICAL_RMM',\n 'TACTICAL_RMM': 'TACTICAL_RMM',\n 'TACTICAL-RMM': 'TACTICAL_RMM',\n 'TACTICALRMM': 'TACTICAL_RMM',\n 'tactical': 'TACTICAL_RMM',\n 'tactical_rmm': 'TACTICAL_RMM',\n 'tactical-rmm': 'TACTICAL_RMM',\n 'tacticalrmm': 'TACTICAL_RMM',\n 'tacticalrmm-agent': 'TACTICAL_RMM',\n\n // Fleet MDM\n 'FLEET': 'FLEET_MDM',\n 'FLEET_MDM': 'FLEET_MDM',\n 'FLEET-MDM': 'FLEET_MDM',\n 'FLEETMDM': 'FLEET_MDM',\n 'fleet': 'FLEET_MDM',\n 'fleet_mdm': 'FLEET_MDM',\n 'fleet-mdm': 'FLEET_MDM',\n 'fleetmdm': 'FLEET_MDM',\n 'fleetmdm-agent': 'FLEET_MDM',\n\n // MeshCentral\n 'MESHCENTRAL': 'MESHCENTRAL',\n 'MESH': 'MESHCENTRAL',\n 'MESH_CENTRAL': 'MESHCENTRAL',\n 'MESH-CENTRAL': 'MESHCENTRAL',\n 'mesh': 'MESHCENTRAL',\n 'meshcentral': 'MESHCENTRAL',\n 'mesh_central': 'MESHCENTRAL',\n 'mesh-central': 'MESHCENTRAL',\n 'meshcentral-agent': 'MESHCENTRAL',\n\n // Authentik\n 'AUTHENTIK': 'AUTHENTIK',\n 'authentik': 'AUTHENTIK',\n\n // OpenFrame\n 'OPENFRAME': 'OPENFRAME',\n 'openframe': 'OPENFRAME',\n 'OPEN_FRAME': 'OPENFRAME',\n 'OPEN-FRAME': 'OPENFRAME',\n 'open_frame': 'OPENFRAME',\n 'open-frame': 'OPENFRAME',\n\n // OpenFrame Chat\n 'OPENFRAME_CHAT': 'OPENFRAME_CHAT',\n 'OPENFRAME-CHAT': 'OPENFRAME_CHAT',\n 'OPENFRAMECHAT': 'OPENFRAME_CHAT',\n 'openframe_chat': 'OPENFRAME_CHAT',\n 'openframe-chat': 'OPENFRAME_CHAT',\n 'openframechat': 'OPENFRAME_CHAT',\n\n // OpenFrame Client\n 'OPENFRAME_CLIENT': 'OPENFRAME_CLIENT',\n 'OPENFRAME-CLIENT': 'OPENFRAME_CLIENT',\n 'OPENFRAMECLIENT': 'OPENFRAME_CLIENT',\n 'openframe_client': 'OPENFRAME_CLIENT',\n 'openframe-client': 'OPENFRAME_CLIENT',\n 'openframeclient': 'OPENFRAME_CLIENT',\n\n // OSQUERY\n 'OSQUERY': 'OSQUERY',\n\n // System\n 'SYSTEM': 'SYSTEM',\n 'system': 'SYSTEM',\n}\n\n/**\n * Normalizes a tool name string to the canonical ToolType.\n * Handles various formats like 'tactical', 'TACTICAL_RMM', 'tactical-rmm', etc.\n *\n * @param input - The tool name string to normalize\n * @returns The canonical ToolType, or undefined if no match found\n *\n * @example\n * normalizeToolType('tactical') // => 'TACTICAL_RMM'\n * normalizeToolType('FLEET-MDM') // => 'FLEET_MDM'\n * normalizeToolType('unknown') // => undefined\n */\nexport function normalizeToolType(input?: string): ToolType | undefined {\n if (!input) return undefined\n\n // Try exact match first\n const exact = toolAliasMap[input]\n if (exact) return exact\n\n // Try uppercase\n const upper = input.toUpperCase()\n if (toolAliasMap[upper]) return toolAliasMap[upper]\n\n // Try lowercase\n const lower = input.toLowerCase()\n if (toolAliasMap[lower]) return toolAliasMap[lower]\n\n return undefined\n}\n\n/**\n * Normalizes a tool name string to the canonical ToolType with a fallback.\n * Returns 'SYSTEM' as the default if no match is found.\n *\n * @param input - The tool name string to normalize\n * @returns The canonical ToolType, defaults to 'SYSTEM' if no match\n *\n * @example\n * normalizeToolTypeWithFallback('tactical') // => 'TACTICAL_RMM'\n * normalizeToolTypeWithFallback('unknown') // => 'SYSTEM'\n */\nexport function normalizeToolTypeWithFallback(input?: string): ToolType {\n return normalizeToolType(input) ?? 'SYSTEM'\n}\n\n/**\n * Converts any tool name variant to its display label.\n * Handles normalization internally.\n *\n * @param input - The tool name string (any format)\n * @returns The display label, or the original input if no match\n *\n * @example\n * toToolLabel('tactical') // => 'Tactical'\n * toToolLabel('FLEET-MDM') // => 'Fleet'\n * toToolLabel('unknown') // => 'unknown'\n */\nexport function toToolLabel(input?: string): string {\n if (!input) return ''\n\n const toolType = normalizeToolType(input)\n if (toolType) {\n return toolLabels[toolType]\n }\n\n return input\n}\n\n/**\n * Checks if a string is a valid tool type (or can be normalized to one).\n *\n * @param input - The string to check\n * @returns True if the input can be normalized to a valid ToolType\n *\n * @example\n * isValidToolType('tactical') // => true\n * isValidToolType('FLEET_MDM') // => true\n * isValidToolType('unknown') // => false\n */\nexport function isValidToolType(input?: string): boolean {\n return normalizeToolType(input) !== undefined\n}\n\n/**\n * Gets all valid tool type aliases for a given canonical ToolType.\n * Useful for documentation or validation purposes.\n *\n * @param toolType - The canonical ToolType\n * @returns Array of all aliases that map to this tool type\n */\nexport function getToolTypeAliases(toolType: ToolType): string[] {\n return Object.entries(toolAliasMap)\n .filter(([_, value]) => value === toolType)\n .map(([key]) => key)\n}\n\n/**\n * Get display label for a tool type\n */\nexport function getToolLabel(toolType: ToolType): string {\n return toolLabels[toolType] || toolType\n}\n","import type { SVGProps } from \"react\";\nexport interface PowershellLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function PowershellLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: PowershellLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill=\"#2671BE\"\n fillRule=\"evenodd\"\n d=\"M10.274 19.708c-2.345 0-4.69.01-7.034-.005-1.19-.008-1.405-.287-1.138-1.442.908-3.919 1.844-7.83 2.732-11.754C5.07 5.455 5.584 4.99 6.719 5c4.69.043 9.379.014 14.068.019 1.176 0 1.374.25 1.11 1.436-.857 3.848-1.72 7.694-2.598 11.537-.328 1.438-.707 1.713-2.23 1.716-2.265.005-4.53.001-6.795 0\"\n clipRule=\"evenodd\"\n />\n <path\n fill=\"#FDFDFE\"\n fillRule=\"evenodd\"\n d=\"M12.269 12.029c-.157-.184-.33-.395-.513-.596-1.036-1.144-2.063-2.297-3.118-3.423C8.155 7.494 8 6.993 8.58 6.484c.573-.503 1.136-.458 1.661.12 1.464 1.612 2.925 3.225 4.413 4.815.556.593.426.997-.185 1.437a942 942 0 0 0-7.016 5.106c-.524.385-1.024.481-1.448-.087-.467-.626-.035-1 .45-1.35a759 759 0 0 0 5.186-3.782c.24-.177.584-.28.627-.714\"\n clipRule=\"evenodd\"\n />\n <path\n fill=\"#FCFDFD\"\n fillRule=\"evenodd\"\n d=\"M13.011 18.09c-.631 0-1.263.02-1.893-.008-.502-.022-.805-.301-.799-.827.006-.497.259-.871.76-.885a90 90 0 0 1 4.142-.002c.439.009.763.293.76.747-.003.52-.279.925-.84.958-.708.043-1.42.01-2.13.01z\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n","import type { SVGProps } from \"react\";\nexport interface PythonLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function PythonLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: PythonLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"M11.966 2C7.244 2 7.193 3.833 7.193 4.21V6.5h4.864v.687H5.26C3.816 7.187 2 8.067 2 11.96c0 3.577 1.417 4.96 2.847 4.96h1.698v-2.386c0-.998.495-2.847 2.802-2.847h4.823c.71 0 2.71-.308 2.71-2.619V4.665C16.88 4.09 16.784 2 11.967 2M9.284 3.54a.874.874 0 1 1 0 1.75.874.874 0 1 1 0-1.75\"\n />\n <path\n fill={color}\n d=\"M12.034 22c4.72 0 4.778-1.867 4.778-2.21V17.5h-4.869v-.687h6.795c1.457 0 3.262-.901 3.262-4.773 0-4.24-1.916-4.96-2.847-4.96h-1.699v2.386c0 .998-.478 2.847-2.8 2.847H9.828c-.707 0-2.71.344-2.71 2.619v4.403c0 .951.581 2.665 4.915 2.665m2.682-1.54a.874.874 0 1 1-.002-1.748.874.874 0 0 1 .002 1.748\"\n />\n </svg>\n );\n}\n","/**\n * Centralized Shell Types\n *\n * Single source of truth for all shell/script type information across the platform.\n * Based on Tactical RMM supported shell types.\n */\nimport { PowershellLogoIcon } from '../components/icons-v2-generated/brand-logos/powershell-logo-icon'\nimport { PythonLogoIcon } from '../components/icons-v2-generated/brand-logos/python-logo-icon'\nimport {\n BashIcon,\n CmdIcon,\n DenoIcon,\n NushellIcon,\n ShellIcon\n} from '../components/icons'\nimport type { IconProps } from './icons'\n\n\n\nexport const ShellTypeValues = {\n POWERSHELL: 'POWERSHELL',\n CMD: 'CMD',\n BASH: 'BASH',\n PYTHON: 'PYTHON',\n NUSHELL: 'NUSHELL',\n DENO: 'DENO',\n SHELL: 'SHELL'\n} as const\n\nexport type ShellType = (typeof ShellTypeValues)[keyof typeof ShellTypeValues]\n\n/**\n * Shell type definition with all metadata\n */\nexport interface ShellTypeDefinition {\n id: ShellType\n label: string\n value: string\n icon: React.ComponentType<IconProps>\n}\n\n/**\n * Complete list of all shell types with icons and labels\n * SINGLE SOURCE OF TRUTH - Use this everywhere\n */\nexport const SHELL_TYPES: ShellTypeDefinition[] = [\n { id: ShellTypeValues.POWERSHELL, label: 'PowerShell', value: 'powershell', icon: PowershellLogoIcon },\n { id: ShellTypeValues.CMD, label: 'Batch', value: 'cmd', icon: CmdIcon },\n { id: ShellTypeValues.BASH, label: 'Bash', value: 'bash', icon: BashIcon },\n { id: ShellTypeValues.PYTHON, label: 'Python', value: 'python', icon: PythonLogoIcon },\n { id: ShellTypeValues.NUSHELL, label: 'Nu', value: 'nushell', icon: NushellIcon },\n { id: ShellTypeValues.DENO, label: 'Deno', value: 'deno', icon: DenoIcon },\n { id: ShellTypeValues.SHELL, label: 'Shell', value: 'shell', icon: ShellIcon },\n]\n\n/**\n * Maps shell types to display labels\n */\nexport const shellLabels: Record<ShellType, string> = {\n [ShellTypeValues.POWERSHELL]: 'PowerShell',\n [ShellTypeValues.CMD]: 'Batch',\n [ShellTypeValues.BASH]: 'Bash',\n [ShellTypeValues.PYTHON]: 'Python',\n [ShellTypeValues.NUSHELL]: 'Nu',\n [ShellTypeValues.DENO]: 'Deno',\n [ShellTypeValues.SHELL]: 'Shell'\n}\n","/**\n * Shell Type Utilities\n *\n * Helper functions for working with shell types.\n */\n\nimport React from 'react'\nimport { ShellType, SHELL_TYPES, shellLabels } from '../types/shell.types'\n\n/**\n * Get display label for a shell type\n */\nexport function getShellLabel(shellType?: string): string {\n if (!shellType) return 'Unknown'\n const normalized = shellType.toUpperCase() as ShellType\n return shellLabels[normalized] || shellType\n}\n\n/**\n * Get icon component for a shell type\n */\nexport function getShellIcon(shellType?: string): React.ComponentType<{ className?: string }> | undefined {\n if (!shellType) return undefined\n const normalized = shellType.toUpperCase() as ShellType\n const shellDef = SHELL_TYPES.find(s => s.id === normalized)\n return shellDef?.icon\n}\n","import type { SVGProps } from \"react\";\nexport interface AppleLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function AppleLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: AppleLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"M17.57 12.628c-.024-2.531 2.062-3.747 2.156-3.805-1.174-1.72-2.999-1.957-3.649-1.983-1.552-.16-3.03.917-3.82.917s-2.005-.895-3.293-.869c-1.694.024-3.257.987-4.13 2.507-1.758 3.054-.448 7.59 1.268 10.073.84 1.213 1.837 2.581 3.151 2.53 1.266-.05 1.743-.82 3.269-.82s1.957.82 3.293.796c1.36-.026 2.222-1.24 3.054-2.458.958-1.411 1.356-2.775 1.38-2.847-.032-.012-2.65-1.018-2.68-4.041M15.06 5.194c.697-.846 1.167-2.021 1.039-3.194-1.004.041-2.22.67-2.94 1.518-.644.748-1.21 1.944-1.056 3.093 1.115.086 2.26-.572 2.956-1.417\"\n />\n </svg>\n );\n}\n","import type { SVGProps } from \"react\";\nexport interface LinuxLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function LinuxLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: LinuxLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"M19.567 18.314c-.528-.217-.963-.558-.931-1.213.03-.653-.467-1.086-.467-1.086s.435-1.43.031-2.612c-.403-1.183-1.737-3.078-2.76-4.507-1.023-1.43-.155-3.08-1.085-5.192-.932-2.113-3.351-1.99-4.654-1.087-1.304.9-.901 3.137-.84 4.196.062 1.056.028 1.808-.092 2.082-.123.273-.961 1.276-1.52 2.114-.559.84-.962 2.58-1.367 3.295-.403.715-.124 1.368-.124 1.368s-.28.092-.497.56c-.217.465-.65.683-1.427.837-.775.155-.775.655-.59 1.214.187.559.001.871-.216 1.585-.217.713.869.932 1.923 1.054 1.055.126 2.234.81 3.228.934.992.125 1.303-.683 1.303-.683s1.116-.25 2.294-.28c1.18-.031 2.295.249 2.295.249s.218.497.62.714c.405.218 1.273.25 1.832-.34.559-.592 2.048-1.337 2.885-1.804.84-.468.686-1.182.159-1.398M12.306 4.606c.532 0 .961.528.961 1.18 0 .463-.215.862-.53 1.056l-.254-.11c.19-.094.324-.335.324-.617 0-.367-.227-.666-.507-.666-.277 0-.505.3-.505.666a.8.8 0 0 0 .088.373c-.165-.066-.318-.127-.437-.172a1.4 1.4 0 0 1-.102-.53c0-.652.43-1.18.962-1.18m-.07 2.488c.267.093.562.266.532.438-.032.172-.172.172-.531.393-.36.218-1.142.703-1.392.735-.251.031-.39-.11-.657-.281-.266-.173-.766-.582-.64-.8 0 0 .39-.298.561-.455s.61-.532.876-.483c.266.045.986.36 1.252.453M9.84 4.793c.42 0 .76.5.76 1.118q0 .168-.032.32a1 1 0 0 0-.307.177 4 4 0 0 0-.14.12.8.8 0 0 0 .063-.49c-.056-.337-.28-.583-.503-.547-.221.038-.355.341-.299.68.057.34.28.585.502.548l.038-.01a3 3 0 0 1-.31.27c-.307-.143-.532-.567-.532-1.07 0-.617.34-1.116.76-1.116M9.019 20.5c-.098.445-.62.77-.62.77-.471.148-1.784-.423-2.38-.673-.593-.247-2.106-.324-2.305-.544-.197-.226.099-.722.175-1.192.073-.474-.148-.77-.075-1.094.075-.322 1.042-.322 1.412-.545.373-.225.447-.87.745-1.044.297-.175.842.446 1.065.795.222.346 1.066 1.837 1.412 2.21.348.372.67.87.572 1.317m5.488-4.332c-.09.438-.09 2.021-.09 2.021s-.961 1.335-2.452 1.554c-1.49.219-2.234.061-2.234.061l-.838-.962s.65-.095.559-.747c-.094-.653-1.985-1.555-2.327-2.363-.34-.808-.062-2.177.373-2.86.434-.684.712-2.175 1.147-2.674.434-.495.774-1.553.62-2.02 0 0 .93 1.12 1.58.935.652-.187 2.112-1.276 2.328-1.089s2.078 4.29 2.263 5.595-.125 2.3-.125 2.3-.712-.187-.804.249m4.761 2.928c-.29.267-1.902.92-2.386 1.428-.48.505-1.109.916-1.493.796-.387-.122-.724-.652-.555-1.426.168-.771.314-1.617.29-2.1s-.122-1.137 0-1.233c.12-.094.312-.047.312-.047s-.095.916.458 1.16c.554.239 1.35-.097 1.59-.34.243-.24.412-.602.412-.602s.24.122.216.507c-.024.386.168.943.531 1.135.36.19.915.458.625.722\"\n />\n </svg>\n );\n}\n","import type { SVGProps } from \"react\";\nexport interface WindowsLogoGreyIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function WindowsLogoGreyIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: WindowsLogoGreyIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"m2 4.832 8.173-1.11.004 7.86-8.17.046zm8.17 7.655.006 7.867-8.17-1.12v-6.8zm.99-8.91L21.997 2v9.482l-10.837.085zM22 12.56 21.997 22 11.16 20.475l-.015-7.932z\"\n />\n </svg>\n );\n}\n","/**\n * Centralized OS Types\n *\n * Single source of truth for all operating system type information across the platform.\n * Handles normalization of OS values from various sources (Fleet MDM, Tactical RMM, GraphQL).\n */\n\nimport { AppleLogoIcon } from '../components/icons-v2-generated/brand-logos/apple-logo-icon'\nimport { LinuxLogoIcon } from '../components/icons-v2-generated/brand-logos/linux-logo-icon'\nimport { WindowsLogoGreyIcon } from '../components/icons-v2-generated/brand-logos/windows-logo-grey-icon'\nimport React from 'react'\nimport type { OSPlatformId } from '../utils/os-platforms'\n\nexport const OSTypeValues = {\n WINDOWS: 'WINDOWS',\n MACOS: 'MACOS',\n LINUX: 'LINUX'\n} as const\n\nexport type OSType = (typeof OSTypeValues)[keyof typeof OSTypeValues]\n\n/**\n * OS type definition with all metadata\n */\nexport interface OSTypeDefinition {\n id: OSType\n label: string\n value: string\n icon: React.ComponentType<any>\n platformId: OSPlatformId\n aliases: string[] // Alternative names/values that map to this OS\n}\n\n/**\n * Complete list of all OS types with icons and labels\n * SINGLE SOURCE OF TRUTH - Use this everywhere\n */\nexport const OS_TYPES: OSTypeDefinition[] = [\n {\n id: OSTypeValues.MACOS,\n label: 'macOS',\n value: OSTypeValues.MACOS,\n icon: AppleLogoIcon,\n platformId: 'darwin',\n aliases: ['darwin', 'macos', 'mac os', 'osx', 'os x', 'mac'] // Put more specific ones first, 'mac' last to avoid false matches\n },\n {\n id: OSTypeValues.WINDOWS,\n label: 'Windows',\n value: OSTypeValues.WINDOWS,\n icon: WindowsLogoGreyIcon,\n platformId: 'windows',\n aliases: ['windows', 'win32', 'win64', 'win'] // 'win' last since it's shortest\n },\n {\n id: OSTypeValues.LINUX,\n label: 'Linux',\n value: OSTypeValues.LINUX,\n icon: LinuxLogoIcon,\n platformId: 'linux',\n aliases: ['linux', 'ubuntu', 'debian', 'centos', 'redhat', 'fedora', 'pop', 'pop!_os', 'arch', 'manjaro']\n }\n]\n\n/**\n * Maps OS types to display labels\n */\nexport const osLabels: Record<OSType, string> = {\n [OSTypeValues.WINDOWS]: 'Windows',\n [OSTypeValues.MACOS]: 'macOS',\n [OSTypeValues.LINUX]: 'Linux'\n}\n","/**\n * OS Type Utilities\n *\n * Helper functions for working with OS types.\n */\n\nimport React from 'react'\nimport type { OSPlatformId } from './os-platforms'\nimport { OSType, OSTypeDefinition, OS_TYPES, osLabels } from '../types/os.types'\n\n/**\n * Normalize OS type string to standard OSType enum\n * Handles case-insensitive matching and various OS name variations\n *\n * @param osType - Raw OS type string from API or device data\n * @returns Normalized OSType or undefined if not recognized\n *\n * @example\n * normalizeOSType('windows') // 'WINDOWS'\n * normalizeOSType('Darwin') // 'MACOS'\n * normalizeOSType('Ubuntu') // 'LINUX'\n */\nexport function normalizeOSType(osType?: string): OSType | undefined {\n if (!osType) return undefined\n\n const normalized = osType.toLowerCase().trim()\n\n // Check for exact matches first, then partial matches\n // This prevents \"win\" from matching \"darwin\"\n for (const osTypeDef of OS_TYPES) {\n // Check for exact word match first\n if (osTypeDef.aliases.some(alias => {\n // Exact match\n if (normalized === alias) return true\n // Word boundary match (e.g., \"mac\" in \"mac os\" but not in \"vmac\")\n const wordBoundaryRegex = new RegExp(`\\\\b${alias}\\\\b`, 'i')\n return wordBoundaryRegex.test(osType)\n })) {\n return osTypeDef.id\n }\n }\n\n // Fallback to partial matching for version strings like \"macOS 26.0.1\"\n for (const osTypeDef of OS_TYPES) {\n if (osTypeDef.aliases.some(alias => normalized.includes(alias))) {\n return osTypeDef.id\n }\n }\n\n return undefined\n}\n\n/**\n * Get display label for an OS type\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Display label\n */\nexport function getOSLabel(osType?: string): string {\n if (!osType) return 'Unknown'\n\n const normalized = normalizeOSType(osType)\n return normalized ? osLabels[normalized] : osType\n}\n\n/**\n * Get icon component for an OS type\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Icon component or undefined\n */\nexport function getOSIcon(osType?: string): React.ComponentType<any> | undefined {\n if (!osType) return undefined\n\n const normalized = normalizeOSType(osType)\n if (!normalized) return undefined\n\n const osTypeDef = OS_TYPES.find(t => t.id === normalized)\n return osTypeDef?.icon\n}\n\n/**\n * Get OS type definition by OS type string\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Complete OS type definition or undefined\n */\nexport function getOSTypeDefinition(osType?: string): OSTypeDefinition | undefined {\n if (!osType) return undefined\n\n const normalized = normalizeOSType(osType)\n if (!normalized) return undefined\n\n return OS_TYPES.find(t => t.id === normalized)\n}\n\n/**\n * Get platform ID for an OS type (for cross-referencing with OS_PLATFORMS)\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Platform ID or undefined\n */\nexport function getOSPlatformId(osType?: string): OSPlatformId | undefined {\n const osTypeDef = getOSTypeDefinition(osType)\n return osTypeDef?.platformId\n}\n\n/**\n * Check if device OS matches a specific platform\n *\n * @param deviceOS - Device OS string\n * @param targetPlatform - Target platform to check against\n * @returns True if OS matches platform\n *\n * @example\n * isOSPlatform('Darwin', 'darwin') // true\n * isOSPlatform('Windows 10', 'windows') // true\n * isOSPlatform('Ubuntu', 'linux') // true\n */\nexport function isOSPlatform(deviceOS?: string, targetPlatform?: OSPlatformId): boolean {\n if (!deviceOS || !targetPlatform) return false\n\n const platformId = getOSPlatformId(deviceOS)\n return platformId === targetPlatform\n}\n","import { getCountries, getCountryCallingCode, isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js'\nimport type { CountryCode } from 'libphonenumber-js'\n\nexport interface CountryPhoneData {\n code: CountryCode\n name: string\n dialCode: string\n flag: string\n}\n\n/**\n * Priority country codes shown at the top of country selectors\n */\nconst PRIORITY_CODES: CountryCode[] = ['US', 'CA', 'GB', 'AU']\n\n/**\n * Convert ISO 3166-1 alpha-2 country code to flag emoji\n */\nfunction countryCodeToFlag(code: string): string {\n return code\n .toUpperCase()\n .split('')\n .map(char => String.fromCodePoint(0x1F1E6 + char.charCodeAt(0) - 65))\n .join('')\n}\n\n/**\n * Build country phone data from libphonenumber-js metadata + Intl.DisplayNames\n */\nfunction buildCountryData(): { priority: CountryPhoneData[]; others: CountryPhoneData[] } {\n const displayNames = new Intl.DisplayNames(['en'], { type: 'region' })\n const allCodes = getCountries()\n\n const toData = (code: CountryCode): CountryPhoneData => ({\n code,\n name: displayNames.of(code) || code,\n dialCode: `+${getCountryCallingCode(code)}`,\n flag: countryCodeToFlag(code),\n })\n\n const priority = PRIORITY_CODES.map(toData)\n\n const prioritySet = new Set(PRIORITY_CODES)\n const others = allCodes\n .filter(c => !prioritySet.has(c))\n .map(toData)\n .sort((a, b) => a.name.localeCompare(b.name))\n\n return { priority, others }\n}\n\nlet _cache: { priority: CountryPhoneData[]; others: CountryPhoneData[] } | null = null\n\n/**\n * Get all countries split into priority (US, CA, GB, AU) and the rest alphabetically\n */\nexport function getCountryPhoneData() {\n if (!_cache) {\n _cache = buildCountryData()\n }\n return _cache\n}\n\n/**\n * Find country data by ISO code\n */\nexport function getCountryByCode(code: CountryCode): CountryPhoneData | undefined {\n const { priority, others } = getCountryPhoneData()\n return priority.find(c => c.code === code) || others.find(c => c.code === code)\n}\n\n/**\n * Validate a phone number for a specific country using libphonenumber\n */\nexport function validatePhoneNumber(phoneNumber: string, countryCode: CountryCode): boolean {\n if (!phoneNumber.trim()) return true // optional field\n return isValidPhoneNumber(phoneNumber, countryCode)\n}\n\n/**\n * Format a phone number to E.164 format (e.g., +14155552671)\n */\nexport function formatPhoneE164(phoneNumber: string, countryCode: CountryCode): string {\n try {\n const parsed = parsePhoneNumber(phoneNumber, countryCode)\n if (parsed && parsed.isValid()) {\n return parsed.format('E.164')\n }\n } catch {\n // fall through to manual formatting\n }\n const dialCode = `+${getCountryCallingCode(countryCode)}`\n const digits = phoneNumber.replace(/\\D/g, '')\n return `${dialCode}${digits}`\n}\n","/**\n * Generic Domain Detection\n * Detects personal/generic email providers (gmail, yahoo, etc.)\n */\n\nexport const GENERIC_EMAIL_DOMAINS = [\n // Major providers\n 'gmail.com',\n 'yahoo.com',\n 'hotmail.com',\n 'outlook.com',\n 'live.com',\n 'msn.com',\n // Apple\n 'icloud.com',\n 'me.com',\n 'mac.com',\n // Other providers\n 'aol.com',\n 'protonmail.com',\n 'mail.com',\n 'yandex.com',\n 'zoho.com',\n 'gmx.com',\n 'fastmail.com',\n // ISP-based\n 'comcast.net',\n 'verizon.net',\n 'att.net',\n 'sbcglobal.net',\n 'bellsouth.net',\n 'cox.net',\n // International\n 'qq.com',\n '163.com',\n '126.com',\n 'web.de',\n 't-online.de',\n] as const\n\nexport type GenericEmailDomain = (typeof GENERIC_EMAIL_DOMAINS)[number]\n\nexport function extractDomainFromEmail(email: string): string | null {\n if (!email || !email.includes('@')) return null\n return email.split('@')[1]?.toLowerCase() || null\n}\n\nexport function normalizeDomain(domain: string): string {\n return (\n domain\n ?.toLowerCase()\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .split('/')[0]\n .trim() || ''\n )\n}\n\nexport function isGenericDomain(domain: string): boolean {\n const normalized = normalizeDomain(domain)\n return GENERIC_EMAIL_DOMAINS.includes(normalized as GenericEmailDomain)\n}\n\nexport function hasGenericEmailDomain(email: string): boolean {\n const domain = extractDomainFromEmail(email)\n return domain ? isGenericDomain(domain) : false\n}\n\nexport function isGenericWebsiteDomain(website: string): boolean {\n return isGenericDomain(normalizeDomain(website))\n}\n","// Color analysis utilities for dynamic badge colors\n\nexport interface ColorPalette {\n name: string;\n hex: string;\n rgb: [number, number, number];\n}\n\n// Your design system color palette - Star colors only\nexport const DESIGN_PALETTE: ColorPalette[] = [\n { name: 'yellow', hex: '#FFC008', rgb: [255, 192, 8] },\n { name: 'black', hex: '#161616', rgb: [22, 22, 22] },\n { name: 'gray', hex: '#888888', rgb: [136, 136, 136] },\n];\n\n/**\n * Convert hex color to RGB\n */\nexport function hexToRgb(hex: string): [number, number, number] {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result\n ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]\n : [0, 0, 0];\n}\n\n/**\n * Calculate relative luminance for contrast calculations\n */\nfunction getLuminance(rgb: [number, number, number]): number {\n const [r, g, b] = rgb.map(c => {\n c = c / 255;\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n });\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/**\n * Calculate contrast ratio between two colors\n */\nexport function getContrastRatio(color1: [number, number, number], color2: [number, number, number]): number {\n const lum1 = getLuminance(color1);\n const lum2 = getLuminance(color2);\n const brightest = Math.max(lum1, lum2);\n const darkest = Math.min(lum1, lum2);\n return (brightest + 0.05) / (darkest + 0.05);\n}\n\n/**\n * Extract dominant color from image canvas\n */\nexport function extractDominantColor(canvas: HTMLCanvasElement): [number, number, number] {\n const ctx = canvas.getContext('2d');\n if (!ctx) return [128, 128, 128]; // fallback gray\n\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n const data = imageData.data;\n\n // Sample pixels in a grid pattern for performance\n const sampleSize = Math.max(1, Math.floor(data.length / (4 * 1000))); // ~1000 samples\n const colorCounts: { [key: string]: number } = {};\n\n for (let i = 0; i < data.length; i += 4 * sampleSize) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const alpha = data[i + 3];\n\n // Skip transparent pixels\n if (alpha < 128) continue;\n\n // Bucket colors to reduce noise (round to nearest 32)\n const bucketR = Math.round(r / 32) * 32;\n const bucketG = Math.round(g / 32) * 32;\n const bucketB = Math.round(b / 32) * 32;\n\n const key = `${bucketR},${bucketG},${bucketB}`;\n colorCounts[key] = (colorCounts[key] || 0) + 1;\n }\n\n // Find most common color\n let maxCount = 0;\n let dominantColor: [number, number, number] = [128, 128, 128];\n\n for (const [colorKey, count] of Object.entries(colorCounts)) {\n if (count > maxCount) {\n maxCount = count;\n const [r, g, b] = colorKey.split(',').map(Number);\n dominantColor = [r, g, b];\n }\n }\n\n return dominantColor;\n}\n\n/**\n * Find the best contrasting color from the design palette\n */\nexport function getBestContrastColor(imageColor: [number, number, number]): ColorPalette {\n let bestColor = DESIGN_PALETTE[0];\n let bestContrast = 0;\n\n for (const color of DESIGN_PALETTE) {\n const contrast = getContrastRatio(imageColor, color.rgb);\n if (contrast > bestContrast) {\n bestContrast = contrast;\n bestColor = color;\n }\n }\n\n // Ensure minimum contrast ratio of 3:1 for readability\n return bestContrast >= 3 ? bestColor : DESIGN_PALETTE.find(c => c.name === 'black') || bestColor;\n}\n\n/**\n * Load image and analyze its dominant color\n */\nexport function analyzeImageColor(imageSrc: string): Promise<ColorPalette> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n\n img.onload = () => {\n try {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n reject(new Error('Could not get canvas context'));\n return;\n }\n\n // Resize to smaller canvas for performance\n const maxSize = 100;\n const scale = Math.min(maxSize / img.width, maxSize / img.height);\n canvas.width = img.width * scale;\n canvas.height = img.height * scale;\n\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n\n const dominantColor = extractDominantColor(canvas);\n const bestContrastColor = getBestContrastColor(dominantColor);\n\n resolve(bestContrastColor);\n } catch (error) {\n reject(error);\n }\n };\n\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = imageSrc;\n });\n}\n\n/**\n * Extract the dominant edge/corner color from an image URL.\n * Used for background fill behind images in emails and cards.\n * Client-side only (uses canvas). Returns hex color string.\n */\nexport async function extractImageEdgeColorAsync(imageUrl: string): Promise<string> {\n return new Promise((resolve) => {\n if (typeof window === 'undefined') { resolve('#000000'); return }\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => {\n try {\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx) { resolve('#000000'); return }\n const maxSize = 50\n const scale = Math.min(maxSize / img.naturalWidth, maxSize / img.naturalHeight)\n const w = Math.round(img.naturalWidth * scale)\n const h = Math.round(img.naturalHeight * scale)\n canvas.width = w; canvas.height = h\n ctx.drawImage(img, 0, 0, w, h)\n const data = ctx.getImageData(0, 0, w, h).data\n // Sample edge pixels (15% band on all sides) with color bucketing\n const edgeW = Math.max(2, Math.round(w * 0.15))\n const edgeH = Math.max(2, Math.round(h * 0.15))\n const bucketSize = 32\n const buckets = new Map<string, { r: number; g: number; b: number; count: number }>()\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < w; x++) {\n if (!(x < edgeW || x >= w - edgeW || y < edgeH || y >= h - edgeH)) continue\n const i = (y * w + x) * 4\n if (data[i + 3] < 128) continue\n const br = Math.floor(data[i] / bucketSize) * bucketSize\n const bg = Math.floor(data[i + 1] / bucketSize) * bucketSize\n const bb = Math.floor(data[i + 2] / bucketSize) * bucketSize\n const key = `${br},${bg},${bb}`\n const existing = buckets.get(key)\n if (existing) { existing.r += data[i]; existing.g += data[i + 1]; existing.b += data[i + 2]; existing.count++ }\n else { buckets.set(key, { r: data[i], g: data[i + 1], b: data[i + 2], count: 1 }) }\n }\n }\n let best = { r: 0, g: 0, b: 0, count: 0 }\n for (const b of buckets.values()) { if (b.count > best.count) best = b }\n if (best.count === 0) { resolve('#000000'); return }\n const r = Math.round(best.r / best.count), g = Math.round(best.g / best.count), b = Math.round(best.b / best.count)\n resolve(`#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`)\n } catch { resolve('#000000') }\n }\n img.onerror = () => resolve('#000000')\n img.src = imageUrl\n })\n}\n","/**\n * Pure image-proxy URL builder + helpers.\n *\n * Lib-side replacement for the hub's `lib/utils/image-proxy.ts`. The\n * hub used to hardcode `/api/image-proxy` + an `openmsp.ai` skip-domain;\n * this version takes BOTH as parameters so embedded apps (and other\n * platforms that host the lib) can wire their own proxy prefix + skip\n * list at the runtime layer.\n *\n * Pure function — no side effects, no env reads. Callers thread the\n * proxy config through (typically from `ChatRuntime.endpoints.imageProxyUrlPrefix`).\n */\n\nexport type GetProxiedImageUrlOptions = {\n /**\n * URL prefix for the image proxy (`<prefix>?url=<encoded>`). When unset,\n * `getProxiedImageUrl` returns the original URL unchanged — relative\n * URLs always pass through. Hub default: `/api/image-proxy`.\n */\n proxyPrefix?: string;\n /**\n * Domains that should bypass the proxy (e.g. own-CDN hosts whose\n * `Content-Type` is reliable and that already serve CORS-permitting\n * headers). Matched as `imageUrl.includes(domain)` so subdomains\n * inherit. Default: `[]`.\n */\n skipDomains?: string[];\n /**\n * Return the original `https://` URL so the browser loads it directly\n * (no proxy). Use when upstream `Content-Type` breaks the proxy (common\n * with SVG on some CDNs) or you want the origin to see the client\n * request. HTTP stays proxied (mixed content / legacy).\n */\n directHttps?: boolean;\n};\n\n/**\n * Resolve an external image URL through (or around) the image proxy.\n *\n * Resolution order:\n * 1. `imageUrl` already contains `proxyPrefix` → return unchanged\n * (self-skip — prevents double-wrap).\n * 2. `directHttps` set AND `imageUrl` starts with `https://` → return\n * unchanged.\n * 3. `imageUrl` doesn't start with `http://` or `https://` → return\n * unchanged (relative URLs pass through).\n * 4. `proxyPrefix` unset → return unchanged.\n * 5. `skipDomains` matches the URL's host → return unchanged.\n * 6. Else return `<proxyPrefix>?url=<encoded>`.\n */\nexport function getProxiedImageUrl(\n imageUrl: string | null,\n options?: GetProxiedImageUrlOptions,\n): string | null {\n if (!imageUrl) return null;\n\n const proxyPrefix = options?.proxyPrefix;\n const skipDomains = options?.skipDomains ?? [];\n const directHttps = options?.directHttps ?? false;\n\n // (1) Self-skip — already proxied. Check this BEFORE the http/https\n // gate so an absolute proxy URL passed in (e.g. `https://hub.example/api/image-proxy?url=…`)\n // is treated as already-proxied even though it starts with https://.\n if (proxyPrefix && imageUrl.includes(proxyPrefix)) {\n return imageUrl;\n }\n\n // (3) Relative URLs / data: / blob: — return as-is.\n if (!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://')) {\n return imageUrl;\n }\n\n // (2) Direct-https opt-out — only applies to https (http stays proxied).\n if (directHttps && imageUrl.startsWith('https://')) {\n return imageUrl;\n }\n\n // (4) No proxy configured — return as-is.\n if (!proxyPrefix) {\n return imageUrl;\n }\n\n // (5) Skip-list match.\n for (const domain of skipDomains) {\n if (imageUrl.includes(domain)) {\n return imageUrl;\n }\n }\n\n // (6) Proxy.\n return `${proxyPrefix}?url=${encodeURIComponent(imageUrl)}`;\n}\n\n/**\n * Heuristic: URL path looks like an SVG. Useful with `{ directHttps: true }`\n * when only SVGs misbehave through the proxy; raster images can stay\n * proxied if you prefer.\n */\nexport function urlPathLooksLikeSvg(imageUrl: string): boolean {\n try {\n return /\\.svg$/i.test(new URL(imageUrl).pathname);\n } catch {\n return /\\.svg(\\?|#|$)/i.test(imageUrl);\n }\n}\n\n/**\n * Check if an image URL needs to be proxied. `proxyPrefix` is the same\n * value passed to `getProxiedImageUrl` — used to short-circuit the\n * self-skip case.\n */\nexport function shouldProxyImage(\n imageUrl: string | null,\n proxyPrefix?: string,\n): boolean {\n if (!imageUrl) return false;\n if (!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://')) return false;\n if (proxyPrefix && imageUrl.includes(proxyPrefix)) return false;\n return true;\n}\n\n/**\n * Generate a responsive `sizes` attribute for `<img>` / `<Image>` tags.\n * Pure utility — kept here for backwards-compatibility with the previous\n * stub.\n */\nexport function generateImageSizes(_url: string): string {\n return `(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw`;\n}\n","/**\n * Unified Date Utilities for OpenMSP Platform\n * Provides consistent date formatting across all components\n */\n\n/**\n * Format relative time from ISO timestamp\n * This is the single source of truth for all relative time formatting\n * \n * @param timestamp - ISO timestamp string or Date object\n * @returns Formatted relative time string\n * \n * @example\n * formatRelativeTime('2024-01-01T12:00:00Z') // '2 hours ago'\n * formatRelativeTime(new Date()) // 'Just now'\n */\nexport function formatRelativeTime(timestamp: string | Date): string {\n const now = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n // Validate the date\n if (isNaN(targetTime.getTime())) {\n console.warn('⚠️ Invalid timestamp in formatRelativeTime:', timestamp);\n return 'Unknown time';\n }\n \n const diffInMs = now.getTime() - targetTime.getTime();\n const diffInMinutes = Math.floor(diffInMs / (1000 * 60));\n \n // Handle future dates (should not happen but graceful fallback)\n if (diffInMinutes < 0) {\n return 'Just now';\n }\n \n // Less than 1 minute\n if (diffInMinutes < 1) return 'Just now';\n \n // 1-59 minutes\n if (diffInMinutes < 60) return `${diffInMinutes}m ago`;\n \n // 1-23 hours \n const diffInHours = Math.floor(diffInMinutes / 60);\n if (diffInHours < 24) return `${diffInHours}h ago`;\n \n // 1-6 days\n const diffInDays = Math.floor(diffInHours / 24);\n if (diffInDays < 7) return `${diffInDays}d ago`;\n \n // 1-4 weeks\n if (diffInDays < 30) {\n const weeks = Math.floor(diffInDays / 7);\n return `${weeks}w ago`;\n }\n \n // Older than 30 days - show formatted date\n return targetTime.toLocaleDateString('en-US', { \n month: 'short', \n day: 'numeric',\n year: targetTime.getFullYear() !== now.getFullYear() ? 'numeric' : undefined\n });\n}\n\n/**\n * Format absolute date for display\n * \n * @param timestamp - ISO timestamp string or Date object\n * @param options - Intl.DateTimeFormatOptions for customization\n * @returns Formatted date string\n */\nexport function formatAbsoluteDate(\n timestamp: string | Date,\n options: Intl.DateTimeFormatOptions = {}\n): string {\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n if (isNaN(targetTime.getTime())) {\n console.warn('⚠️ Invalid timestamp in formatAbsoluteDate:', timestamp);\n return 'Invalid date';\n }\n \n const defaultOptions: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n ...options\n };\n \n return targetTime.toLocaleDateString('en-US', defaultOptions);\n}\n\n/**\n * Format timestamp with time included\n * \n * @param timestamp - ISO timestamp string or Date object\n * @param options - Intl.DateTimeFormatOptions for customization\n * @returns Formatted datetime string\n */\nexport function formatDateTime(\n timestamp: string | Date,\n options: Intl.DateTimeFormatOptions = {}\n): string {\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n if (isNaN(targetTime.getTime())) {\n console.warn('⚠️ Invalid timestamp in formatDateTime:', timestamp);\n return 'Invalid date';\n }\n \n const defaultOptions: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n ...options\n };\n \n return targetTime.toLocaleDateString('en-US', defaultOptions);\n}\n\n/**\n * Get time difference in human readable format (detailed)\n * \n * @param timestamp - ISO timestamp string or Date object\n * @returns Detailed time difference string\n */\nexport function getDetailedTimeDifference(timestamp: string | Date): string {\n const now = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n if (isNaN(targetTime.getTime())) {\n return 'Invalid date';\n }\n \n const diffInMs = now.getTime() - targetTime.getTime();\n const diffInSeconds = Math.floor(diffInMs / 1000);\n const diffInMinutes = Math.floor(diffInSeconds / 60);\n const diffInHours = Math.floor(diffInMinutes / 60);\n const diffInDays = Math.floor(diffInHours / 24);\n \n if (diffInSeconds < 60) return `${diffInSeconds} seconds ago`;\n if (diffInMinutes < 60) return `${diffInMinutes} minutes ago`;\n if (diffInHours < 24) return `${diffInHours} hours ago`;\n if (diffInDays < 30) return `${diffInDays} days ago`;\n \n const diffInMonths = Math.floor(diffInDays / 30);\n if (diffInMonths < 12) return `${diffInMonths} months ago`;\n \n const diffInYears = Math.floor(diffInDays / 365);\n return `${diffInYears} years ago`;\n}\n\n/**\n * Check if a timestamp is today\n */\nexport function isToday(timestamp: string | Date): boolean {\n const today = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n return today.toDateString() === targetTime.toDateString();\n}\n\n/**\n * Check if a timestamp is within the last N minutes\n */\nexport function isWithinMinutes(timestamp: string | Date, minutes: number): boolean {\n const now = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n const diffInMs = now.getTime() - targetTime.getTime();\n const diffInMinutes = diffInMs / (1000 * 60);\n \n return diffInMinutes <= minutes && diffInMinutes >= 0;\n}\n\n/**\n * Create a UTC timestamp string for database insertion\n */\nexport function createUTCTimestamp(): string {\n return new Date().toISOString();\n} ","/**\n * Per-source icon-name + label lookup. Keyed by `RagTableConfig.id` (the same\n * id used in `chat_source_rag_tables.rag_table_id` and on each\n * `ChatRef.sourceRepo`).\n *\n * Server-safe — lives in `src/utils/` (no `'use client'` banner) so\n * hub server-side rag-mappers + chat route handlers can call\n * `getSourceLabel()` / `getSourceIconName()` directly. The client-side\n * chat barrel re-exports from here for ergonomic client imports.\n *\n * Used by SOURCE-LEVEL chip surfaces:\n * - The chip strip below an assistant message.\n * - The tracking-row source glyph on inline entity cards.\n *\n * Why a small map here instead of a column on RAG_TABLE_CONFIGS:\n * - The icon NAME is a small string; the resolver (icon-name → React\n * component) lives in `src/components/chat/utils/icon-registry.ts`\n * where it can stay client-only. Server-side consumers stay\n * icon-component-free.\n * - The mapping is intrinsic to the TABLE, not per-platform — same\n * entry serves every (platform, source) binding.\n *\n * Per-table admin-UI bucket id (`SOURCE_CATEGORIES_BY_TABLE`) stays\n * hub-side because it depends on the hub's `RagSourceCategoryId` enum.\n */\n\n/** Map RagTableConfig.id → icon_name (resolvable via `getIconComponent`). */\nexport const SOURCE_ICON_NAMES: Record<string, string> = {\n // Doc tables\n 'openframe-docs': 'openframe',\n 'data-room-docs': 'shield',\n\n // CMS / programs\n 'blog-posts': 'newspaper',\n 'product-releases': 'rocket',\n 'case-studies': 'briefcase',\n 'onboarding-guides': 'graduation-cap',\n webinars: 'video',\n events: 'calendar',\n podcasts: 'headphones',\n 'customer-interviews': 'users',\n\n // Financials\n 'investor-updates': 'mail',\n 'financial-kpis': 'activity',\n 'financial-cap-table': 'table',\n 'financial-pnl': 'trending-up',\n 'financial-balance-sheet': 'dollar-sign',\n 'financial-cash-flow': 'banknote',\n\n // ClickUp\n 'clickup-roadmap': 'clickup',\n 'clickup-delivery': 'clickup',\n 'clickup-tasks-internal': 'clickup',\n\n // GitHub\n 'github-commits': 'github',\n 'github-pull-requests': 'github',\n 'github-pr-reviews': 'github',\n 'github-commits-public': 'github',\n 'github-pull-requests-public': 'github',\n 'github-pr-reviews-public': 'github',\n\n // HubSpot\n 'hubspot-tickets': 'hubspot',\n 'hubspot-tickets-anon': 'hubspot',\n 'hubspot-tickets-self': 'hubspot',\n\n // Communications\n 'slack-messages': 'slack',\n}\n\n/** Lookup an icon name by RagTableConfig.id. Returns undefined when\n * unknown so callers can decide whether to fall back to documentType\n * or to the generic FileText glyph in the icon registry. */\nexport function getSourceIconName(tableId: string | null | undefined): string | undefined {\n if (!tableId) return undefined\n return SOURCE_ICON_NAMES[tableId]\n}\n\n/**\n * Per-table display LABEL — used by SERVER-SIDE chip-strip rendering\n * (the row's \"Customer Interviews (8 records)\" chip below an assistant\n * message).\n *\n * The chip GRID + autocomplete DROPDOWN read their command label\n * from the DB (per-source `chat_admin_slash_commands.label`) — those\n * surfaces can carry per-source labels (e.g. \"OpenFrame Commits\" vs\n * \"GitHub Commits\" for the same table). This map is the TABLE-LEVEL\n * label used by sub-message chips where a SINGLE label per table is\n * sufficient regardless of which source's chat is rendering.\n */\nexport const SOURCE_LABELS_BY_TABLE: Record<string, string> = {\n // Doc tables\n 'openframe-docs': 'OpenFrame Docs',\n 'data-room-docs': 'Data Room',\n\n // CMS / programs\n 'blog-posts': 'Blog Posts',\n 'product-releases': 'Product Releases',\n 'case-studies': 'Case Studies',\n 'onboarding-guides': 'Onboarding Guides',\n webinars: 'Webinars',\n events: 'Events',\n podcasts: 'Podcasts',\n 'customer-interviews': 'Customer Interviews',\n\n // Financials\n 'investor-updates': 'Investor Updates',\n 'financial-kpis': 'Financial KPIs',\n 'financial-cap-table': 'Cap Table',\n 'financial-pnl': 'Profit & Loss',\n 'financial-balance-sheet': 'Balance Sheet',\n 'financial-cash-flow': 'Cash Flow',\n\n // ClickUp\n 'clickup-roadmap': 'ClickUp Roadmap',\n 'clickup-delivery': 'ClickUp Delivery',\n 'clickup-tasks-internal': 'ClickUp Tasks',\n\n // GitHub\n 'github-commits': 'GitHub Commits',\n 'github-pull-requests': 'GitHub Pull Requests',\n 'github-pr-reviews': 'GitHub PR Reviews',\n 'github-commits-public': 'OpenFrame Commits',\n 'github-pull-requests-public': 'OpenFrame Pull Requests',\n 'github-pr-reviews-public': 'OpenFrame PR Reviews',\n\n // HubSpot\n 'hubspot-tickets': 'HubSpot Tickets',\n 'hubspot-tickets-anon': 'Known Issues',\n 'hubspot-tickets-self': 'My Tickets',\n\n // Communications\n 'slack-messages': 'OpenMSP Community',\n}\n\n/** Lookup a human-readable label by RagTableConfig.id. Falls back\n * to the raw id (chip text becomes the table slug — visible bug\n * that prompts an entry to land in `SOURCE_LABELS_BY_TABLE`). */\nexport function getSourceLabel(tableId: string): string {\n return SOURCE_LABELS_BY_TABLE[tableId] ?? tableId\n}\n\n/**\n * Default `documentType → RagTableConfig.id` reverse map.\n *\n * Mirrors the canonical lookup the hub registers via\n * `lib/config/rag-table-config.ts:tableIdForDocumentType()` — same vocabulary\n * the LLM emits inside `[card://<type>:<id>]` markers, same tableIds the\n * retrieval layer routes by, and same set of keys covered by\n * `SOURCE_ICON_NAMES` / `SOURCE_LABELS_BY_TABLE` above.\n *\n * Server-safe (no `'use client'` banner), keyed by string for forward\n * compatibility — adding a new RAG table is a single-line edit here so\n * lib-based embedders pick it up without re-publishing.\n *\n * Embedders that need a CUSTOM mapping (e.g. polymorphic types whose\n * tableId depends on per-tenant config) still pass their own\n * `tableIdForDocumentType` callback to `useEmbeddedChat`; this default\n * only applies when no callback is supplied.\n *\n * Inverse mapping audited 2026-05-24 against the hub registry — every\n * entry in `RAG_TABLE_CONFIGS` with a `documentType` is represented.\n */\nexport const DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID: Record<string, string> = {\n // Doc tables\n markdown: 'openframe-docs',\n data_room_doc: 'data-room-docs',\n\n // CMS / programs\n blog_post: 'blog-posts',\n product_release: 'product-releases',\n case_study: 'case-studies',\n onboarding_guide: 'onboarding-guides',\n webinar: 'webinars',\n event: 'events',\n podcast: 'podcasts',\n customer_interview: 'customer-interviews',\n\n // Financials\n investor_update: 'investor-updates',\n financial_kpi: 'financial-kpis',\n cap_table: 'financial-cap-table',\n profit_loss: 'financial-pnl',\n balance_sheet: 'financial-balance-sheet',\n cash_flow: 'financial-cash-flow',\n\n // ClickUp\n roadmap_item: 'clickup-roadmap',\n delivery_item: 'clickup-delivery',\n internal_task: 'clickup-tasks-internal',\n\n // GitHub\n github_commit: 'github-commits',\n github_pull_request: 'github-pull-requests',\n github_pr_review: 'github-pr-reviews',\n github_commit_public: 'github-commits-public',\n github_pull_request_public: 'github-pull-requests-public',\n github_pr_review_public: 'github-pr-reviews-public',\n\n // HubSpot\n hubspot_ticket: 'hubspot-tickets',\n hubspot_ticket_anon: 'hubspot-tickets-anon',\n hubspot_ticket_self: 'hubspot-tickets-self',\n\n // Communications\n slack_message: 'slack-messages',\n}\n\n/**\n * Default `tableIdForDocumentType` resolver used by `useEmbeddedChat` when\n * the caller didn't pass an explicit callback. Returns `null` for\n * unrecognized document types so downstream `discussRef` / `displayRef`\n * still short-circuits gracefully on stale or custom types.\n */\nexport function defaultTableIdForDocumentType(documentType: string): string | null {\n return DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID[documentType] ?? null\n}\n","/**\n * Thin JSON-typed Web-Storage adapter (localStorage or sessionStorage).\n *\n * Centralizes the SSR-guard + try/catch + silent quota-failure pattern\n * that every per-feature storage util would otherwise re-implement.\n *\n * Optional `namespace` prefix supports platform / user partitioning —\n * the resolver runs lazily at call time so the namespace can vary across\n * the lifetime of the page (e.g. proxy-auth switches user, which switches\n * the key suffix).\n *\n * Backend selection (`backend: 'local' | 'session'`):\n * - `'local'` (default): persists across browser sessions. Use for\n * UI state, chat history metadata, feature-flag opt-ins.\n * - `'session'`: cleared when the tab closes. Use for ANY auth-adjacent\n * value (bearer tokens, act-as identity, proxy credentials). Reduces\n * the XSS-exfiltration attack window from \"indefinite\" to \"until tab\n * close\" without losing per-session ergonomics.\n */\n\nexport type WebStorageBackend = 'local' | 'session'\n\nexport interface LocalStorageAdapter<T> {\n load(): T | null\n save(value: T): void\n clear(): void\n /** Resolved storage key for the current call. Useful for tests. */\n resolveKey(): string\n}\n\nexport interface LocalStorageAdapterOptions<T> {\n /** Base storage key. Combined with `namespace()` when provided. */\n key: string\n /** Optional dynamic namespace prefix appended via `.` separator.\n * Called on EVERY read/write so the key can vary across the page\n * lifetime (e.g. when the platform or user identity changes). */\n namespace?: () => string | null | undefined\n /** Runtime shape check. Falsey return → `load()` yields null. */\n validate?: (parsed: unknown) => parsed is T\n /** Diagnostic prefix written to `console.warn` on parse / write\n * failures. Defaults to `'[local-storage]'`. */\n logTag?: string\n /** Which Web-Storage backend to use. Defaults to `'local'`. Pass\n * `'session'` for anything auth-adjacent so the value evaporates\n * when the tab closes. */\n backend?: WebStorageBackend\n}\n\nfunction getStorage(backend: WebStorageBackend): Storage | null {\n if (typeof window === 'undefined') return null\n try {\n return backend === 'session' ? window.sessionStorage : window.localStorage\n } catch {\n // Some sandboxed contexts (Safari private mode older versions,\n // strict CSP) throw on storage access — treat as unavailable.\n return null\n }\n}\n\nexport function createLocalStorageAdapter<T>(\n options: LocalStorageAdapterOptions<T>,\n): LocalStorageAdapter<T> {\n const tag = options.logTag ?? '[local-storage]'\n const backend: WebStorageBackend = options.backend ?? 'local'\n const resolveKey = (): string => {\n const ns = options.namespace?.()\n return ns ? `${ns}.${options.key}` : options.key\n }\n\n return {\n resolveKey,\n load() {\n const storage = getStorage(backend)\n if (!storage) return null\n try {\n const raw = storage.getItem(resolveKey())\n if (!raw) return null\n const parsed = JSON.parse(raw) as unknown\n if (options.validate && !options.validate(parsed)) return null\n return parsed as T\n } catch (err) {\n console.warn(`${tag} parse failed for key ${resolveKey()}:`, err)\n return null\n }\n },\n save(value: T) {\n const storage = getStorage(backend)\n if (!storage) return\n try {\n storage.setItem(resolveKey(), JSON.stringify(value))\n } catch (err) {\n console.warn(`${tag} write failed for key ${resolveKey()}:`, err)\n }\n },\n clear() {\n const storage = getStorage(backend)\n if (!storage) return\n try {\n storage.removeItem(resolveKey())\n } catch (err) {\n console.warn(`${tag} clear failed for key ${resolveKey()}:`, err)\n }\n },\n }\n}\n","// Stub app config\nexport const APP_CONFIG = {\n app: {\n type: 'openmsp',\n name: 'OpenMSP',\n domain: 'openmsp.ai'\n },\n features: {\n announcements: true,\n notifications: true\n }\n} as const;\n\nexport function getAppConfig() {\n return APP_CONFIG;\n}\n\nexport function getAppType() {\n return process.env.NEXT_PUBLIC_APP_TYPE || 'openmsp';\n}","'use client'\n\n/**\n * Client-side persistence for embed-surface proxy credentials\n * (`CHAT_PROXY_SECRET` + impersonation email). Used by every embedded\n * surface — the chat widget AND the ticket center AND any future\n * embedded React component that needs to identify itself as the\n * impersonated customer.\n *\n * When set, the surface attaches the creds as\n * `Authorization: Bearer <secret>` + `X-Chat-Act-As: <email>`\n * on every call to `/api/docs/chat`, `/api/chat/*`, and any other route\n * gated by `requireChatAuth` — proving to the server that this session\n * is acting on behalf of <email>.\n *\n * **Naming history:** the wire-side header names are still `X-Chat-*`\n * and the env var is `CHAT_PROXY_SECRET`. Those are server contracts;\n * renaming them would require a coordinated deploy + customer-side\n * env-var migration. The CLIENT-side helpers were renamed `Embed*` so\n * non-chat surfaces (e.g. ticket center) don't have to import a\n * chat-prefixed symbol just to send the same headers.\n *\n * Persists to **`localStorage`** so the bearer token + act-as identity\n * survive tab close, new-tab opens, and browser restarts — the\n * `/debug` paste-creds UI is an admin tool and re-pasting every tab\n * cycle was rejected as a dev-experience tradeoff that wasn't worth\n * the security gain. An XSS sink on this origin can read the value\n * indefinitely (vs only-this-tab with sessionStorage), but `/debug`\n * is admin-gated behind the platform's `askAI.enabled` flag and the\n * impersonation header it sets is server-validated against\n * `CHAT_PROXY_SECRET` anyway. Explicit \"Clear\" button on the creds\n * bar is the supported logout path; closing the tab is no longer.\n *\n * Namespaced under `<platform>.chat.proxy-auth.v1` (the storage key is\n * unchanged from the old chat-prefixed helper — that's a storage\n * contract; renaming it would log everyone out).\n */\n\nimport { createLocalStorageAdapter } from './local-storage-adapter'\nimport { getAppType } from './app-config'\n\nexport interface EmbedProxyAuth {\n secret: string\n email: string\n /** Optional identity passthrough — empty/omitted = not sent. Server\n * parses these as `X-Chat-{First,Last}-Name` / `X-Chat-Avatar-Url` and\n * threads them through `resolveChatProxyIdentity`'s returned user. */\n firstName?: string\n lastName?: string\n avatarUrl?: string\n}\n\nfunction isValidPersistedAuth(value: unknown): value is EmbedProxyAuth {\n if (!value || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (\n typeof v.secret !== 'string' || v.secret.trim().length === 0 ||\n typeof v.email !== 'string' || v.email.trim().length === 0\n ) return false\n // Optional fields: when present must be strings. Empty string is treated\n // as absent later (in `getEmbedProxyAuth`).\n if (v.firstName != null && typeof v.firstName !== 'string') return false\n if (v.lastName != null && typeof v.lastName !== 'string') return false\n if (v.avatarUrl != null && typeof v.avatarUrl !== 'string') return false\n return true\n}\n\nconst adapter = createLocalStorageAdapter<EmbedProxyAuth>({\n // Storage key unchanged from the legacy chat-prefixed helper. Renaming\n // it would silently log every existing admin out — the key is a\n // storage contract, not a code identifier.\n key: 'chat.proxy-auth.v1',\n namespace: () => getAppType(),\n validate: isValidPersistedAuth,\n logTag: '[embed-proxy-auth-storage]',\n // localStorage — survives tab close, new tabs, and browser restarts.\n // Admin re-pasting creds every tab cycle was the dev-experience\n // tradeoff prior `sessionStorage` setup demanded — rejected. See\n // file-level doc comment for the security tradeoff rationale.\n backend: 'local',\n})\n\n/** Trim + null-coerce an optional identity field so consumers can do\n * `auth.firstName ?? ''` without worrying about whitespace-only strings. */\nfunction normalizeOptional(value: string | undefined): string | undefined {\n if (!value) return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\n/**\n * Returns full credentials (secret + email + optional identity passthrough)\n * when secret + email are available. Returns `null` when nothing is saved —\n * callers treat that as \"fall back to cookie auth\".\n */\nexport function getEmbedProxyAuth(): EmbedProxyAuth | null {\n const persisted = adapter.load()\n if (!persisted) return null\n return {\n secret: persisted.secret,\n email: persisted.email.trim().toLowerCase(),\n firstName: normalizeOptional(persisted.firstName),\n lastName: normalizeOptional(persisted.lastName),\n avatarUrl: normalizeOptional(persisted.avatarUrl),\n }\n}\n\n/**\n * Returns the LAST email the admin saved. The proxy creds bar reads\n * this to pre-fill the email field on mount.\n */\nexport function getPersistedProxyEmail(): string | null {\n const persisted = adapter.load()\n return persisted?.email.trim().toLowerCase() ?? null\n}\n\n/** Save the proxy creds. Secret + email are required; identity-passthrough\n * fields are persisted only when non-empty. */\nexport function setEmbedProxyAuth(value: EmbedProxyAuth): void {\n adapter.save({\n secret: value.secret,\n email: value.email.trim().toLowerCase(),\n firstName: normalizeOptional(value.firstName),\n lastName: normalizeOptional(value.lastName),\n avatarUrl: normalizeOptional(value.avatarUrl),\n })\n}\n\n/** Drop the persisted creds. */\nexport function clearEmbedProxyAuth(): void {\n adapter.clear()\n}\n\n/**\n * Apply the embed-proxy auth (Bearer + X-Chat-Act-As) to a fetch call's\n * URL + headers. Used by every embedded-surface route that needs to\n * identify itself as the proxied customer (chat stream, agent-* routes,\n * ticket-center actions). When proxy auth is absent (regular\n * cookie-session users), returns the inputs unchanged so the cookie-auth\n * path still works.\n *\n * `X-Chat-Act-As` header (vs a URL query param) keeps PII out of access\n * logs, Sentry breadcrumbs, browser history, and CDN analytics.\n */\nexport function applyProxyAuth(\n url: string,\n baseHeaders: Record<string, string> = { 'Content-Type': 'application/json' },\n): { url: string; headers: Record<string, string> } {\n const auth = getEmbedProxyAuth()\n const headers = { ...baseHeaders }\n if (auth?.secret) {\n headers.Authorization = `Bearer ${auth.secret}`\n }\n if (auth?.email) {\n headers['X-Chat-Act-As'] = auth.email\n }\n // Optional identity passthrough — only attached when present so the\n // server's \"required vs optional\" header shape stays exact.\n if (auth?.firstName) headers['X-Chat-First-Name'] = auth.firstName\n if (auth?.lastName) headers['X-Chat-Last-Name'] = auth.lastName\n if (auth?.avatarUrl) headers['X-Chat-Avatar-Url'] = auth.avatarUrl\n return { url, headers }\n}\n","'use client'\n\n/**\n * Shared `fetch` wrapper for any embedded surface (chat, ticket center,\n * future widgets) that needs to carry the bearer-act-as identity\n * (proxy `Authorization` + `X-Chat-Act-As` headers from\n * `embed-proxy-auth-storage.ts`).\n *\n * Wire header names are `X-Chat-*` for historical reasons — that's a\n * server contract, not a UI namespace. The wrapper itself is generic.\n *\n * Drop-in replacement for `fetch()` — `Authorization` / `X-Chat-Act-As`\n * are merged into `init.headers` when proxy creds are stashed in\n * sessionStorage, otherwise the call falls through to the cookie-auth\n * path unchanged.\n *\n * Use this for any client-side fetch hitting `/api/chat/*`, `/api/docs/chat/*`,\n * or `/api/storage/generate-upload-url` (chat-attachment surface — shared\n * with the ticket center). Routes that do NOT need bearer-act-as\n * (e.g. `/api/profile/me`) keep using vanilla `fetch`.\n */\n\nimport { applyProxyAuth } from './embed-proxy-auth-storage'\n\n/**\n * `fetch` wrapper that attaches embed-proxy bearer headers (when\n * present in sessionStorage) and forces `credentials: 'same-origin'`\n * so Supabase auth cookies travel too.\n *\n * **Header merge direction (proxy WINS over caller):** the implementation\n * spreads `baseHeaders` first inside `applyProxyAuth`, then sets the\n * `Authorization` / `X-Chat-*` keys — so the proxy values take precedence\n * over anything the caller passed. The motivation is that the bearer +\n * act-as identity is the source of truth for embedded auth; a caller\n * accidentally passing a stale `Authorization` header should NOT override\n * the live proxy creds.\n *\n * **Cross-origin defense:** the wrapper assumes a same-origin `/api/…`\n * relative URL. Absolute URLs are accepted only when their origin matches\n * the current window's origin; cross-origin URLs throw before the bearer\n * leaves the page. This is a defense-in-depth guard for future call sites\n * — there is no legitimate cross-origin use of this fetch wrapper.\n */\nexport function embedAuthedFetch(url: string, init: RequestInit = {}): Promise<Response> {\n assertSameOrigin(url)\n\n // `applyProxyAuth` accepts `Record<string, string>`; normalize the\n // caller's headers to that shape. RequestInit accepts `HeadersInit`\n // which is broader (Headers instance OR array of tuples).\n //\n // When the caller passes no headers, fall back to the same default\n // `applyProxyAuth` uses internally — `Content-Type: application/json` —\n // so JSON POSTs keep their content-type when only `embedAuthedFetch(url)`\n // is used at the call site. GET callers that explicitly want no body\n // headers can pass `init.headers = {}` to opt out.\n let baseHeaders: Record<string, string>\n if (init.headers === undefined) {\n baseHeaders = { 'Content-Type': 'application/json' }\n } else {\n baseHeaders = {}\n if (init.headers instanceof Headers) {\n init.headers.forEach((v, k) => {\n baseHeaders[k] = v\n })\n } else if (Array.isArray(init.headers)) {\n for (const [k, v] of init.headers) baseHeaders[k] = v\n } else {\n Object.assign(baseHeaders, init.headers as Record<string, string>)\n }\n }\n\n const { url: authedUrl, headers } = applyProxyAuth(url, baseHeaders)\n return fetch(authedUrl, {\n ...init,\n headers,\n // Always include Supabase auth cookies. `applyProxyAuth` handles\n // the bearer header layer; cookies are the session-tier carrier.\n credentials: init.credentials ?? 'same-origin',\n })\n}\n\n/**\n * Reject any URL that resolves to a cross-origin destination or to a\n * non-http(s) scheme. Every input is resolved against\n * `window.location.href` so the same rule covers path-only\n * (`/api/...`), absolute (`https://...`), protocol-relative\n * (`//host/...`), AND whitespace-prefixed forms (`\\t//evil.com/...`) —\n * the WHATWG fetch spec strips leading ASCII whitespace before\n * parsing, so any regex-based \"skip relative\" shortcut is bypassable\n * with a leading `\\t`/`\\n`/`\\r`/space. We resolve unconditionally\n * instead and compare origins.\n *\n * Also blocks `javascript:` / `data:` / `blob:` etc. — only `http(s):`\n * is allowed. This is explicit allowlisting rather than relying on\n * `origin === 'null'` to fall out wrong.\n *\n * Server-side rendering: when `typeof window === 'undefined'` we skip\n * the check — the bearer comes from sessionStorage which doesn't exist\n * on the server, so there's nothing to leak anyway.\n */\nfunction assertSameOrigin(url: string): void {\n if (typeof window === 'undefined') return\n let target: URL\n let pageOrigin: string\n try {\n target = new URL(url, window.location.href)\n // Derive the page origin from `href` rather than reading\n // `window.location.origin` directly so the check works in test\n // environments that mock `window.location` to a plain object\n // without an `origin` field (jsdom setups do this).\n pageOrigin = new URL(window.location.href).origin\n } catch {\n throw new Error(`embedAuthedFetch: refusing to fetch malformed URL (${JSON.stringify(url)})`)\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') {\n throw new Error(\n `embedAuthedFetch: refusing non-http(s) URL (${target.protocol}) — pass a relative /api/* path instead`,\n )\n }\n if (target.origin !== pageOrigin) {\n throw new Error(\n `embedAuthedFetch: refusing cross-origin fetch to ${target.origin} — pass a relative /api/* path instead`,\n )\n }\n}\n","'use client'\n\n/**\n * Shared decoder for the `decision_resolved` leading frame the\n * `confirm-tool` route emits as the first chunk of its SSE response.\n *\n * Wire format (matches `use-embedded-chat.ts:270-394`):\n * - Frames are JSON objects separated by `\\0` (NUL).\n * - `\\x1E` (record separator) marks the transition from leading\n * metadata frames into the text body (chat path).\n * - For the tickets-UI path, the request body carries `messages: []`\n * which makes phase-2 (text body) structurally unreachable —\n * `confirm-tool/route.ts:569` skips the `runDocsChat` call. So the\n * stream contains exactly ONE frame (`decision_resolved`) followed\n * by EOF.\n *\n * This helper drains the stream defensively (reads all remaining bytes\n * after the leading frame so the server-side `composed.start()` doesn't\n * hang on a half-closed connection) and returns the first decoded\n * `decision_resolved` frame. Throws on:\n * - Empty body\n * - First frame is not `decision_resolved`\n * - Malformed JSON before the first `\\0`\n *\n * Migration note: `use-embedded-chat.ts` still inlines the full decoder\n * including phase-2 text + trailing usage parsing. A future refactor\n * could move the leading-frame loop here and have the chat shell\n * compose with that — out of scope for this PR.\n */\n\nexport interface DecisionResolvedFrame {\n kind: 'decision_resolved'\n ok: boolean\n action: 'approved' | 'rejected'\n toolName?: string\n willAutoContinue?: boolean\n proposalId?: string\n /** Approve-path result envelope. `mirror_synced=false` means the\n * HubSpot REST call succeeded but the local mirror upsert lagged —\n * callers should optimistic-render and schedule a delayed refetch. */\n result?: {\n ticket_id?: string\n status?: string | null\n mirror_synced?: boolean\n } | null\n card?: {\n type?: string\n marker?: string\n ref?: unknown\n } | null\n receiptText?: string\n}\n\n/**\n * Read the leading `decision_resolved` frame from a confirm-tool SSE\n * response. Drains the stream to end-of-file before resolving so the\n * server doesn't sit on a half-closed socket.\n *\n * @throws {Error} when the body is empty, the first frame is not\n * `decision_resolved`, or the leading JSON is malformed.\n */\nexport async function readLeadingDecisionFrame(\n response: Response,\n): Promise<DecisionResolvedFrame> {\n const reader = response.body?.getReader()\n if (!reader) throw new Error('readLeadingDecisionFrame: response has no body')\n\n const decoder = new TextDecoder()\n let buffer = ''\n let frame: DecisionResolvedFrame | null = null\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n\n // Try to extract the leading frame ASAP — we only need the first\n // chunk that contains a `\\0`. Everything after is either phase-2\n // text (unexpected for tickets-UI but tolerated) or end-of-stream.\n if (frame === null) {\n const nullIdx = buffer.indexOf('\\0')\n const recIdx = buffer.indexOf('\\x1E')\n // If `\\x1E` (text-body marker) shows up before `\\0`, the server\n // emitted phase-2 without a leading frame — protocol violation.\n if (recIdx !== -1 && (nullIdx === -1 || recIdx < nullIdx)) {\n throw new Error(\n 'readLeadingDecisionFrame: text-body sentinel arrived before leading frame',\n )\n }\n if (nullIdx !== -1) {\n const raw = buffer.slice(0, nullIdx)\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n throw new Error(\n `readLeadingDecisionFrame: leading JSON parse failed: ${(err as Error).message}`,\n )\n }\n const obj = parsed as Record<string, unknown>\n if (obj?.kind !== 'decision_resolved') {\n throw new Error(\n `readLeadingDecisionFrame: expected decision_resolved, got kind=${String(obj?.kind)}`,\n )\n }\n frame = normalizeDecisionFrame(obj)\n // Continue draining so the server-side stream closes cleanly.\n buffer = buffer.slice(nullIdx + 1)\n }\n }\n // Past the leading frame: just consume + discard the remainder.\n // Don't allocate a parser for phase-2 text; the tickets-UI path\n // is supposed to be a single frame.\n }\n } finally {\n // Release the lock even if we threw mid-loop.\n try {\n reader.releaseLock()\n } catch {\n // No-op: reader may already be released if the stream ended cleanly.\n }\n }\n\n if (frame === null) {\n throw new Error('readLeadingDecisionFrame: stream closed before leading frame arrived')\n }\n return frame\n}\n\nfunction normalizeDecisionFrame(obj: Record<string, unknown>): DecisionResolvedFrame {\n const action = obj.action === 'rejected' ? 'rejected' : 'approved'\n const result = (obj.result ?? null) as DecisionResolvedFrame['result']\n const card = (obj.card ?? null) as DecisionResolvedFrame['card']\n return {\n kind: 'decision_resolved',\n ok: obj.ok === true,\n action,\n ...(typeof obj.toolName === 'string' ? { toolName: obj.toolName } : {}),\n ...(obj.willAutoContinue === true ? { willAutoContinue: true } : {}),\n ...(typeof obj.proposalId === 'string' ? { proposalId: obj.proposalId } : {}),\n ...(result ? { result } : {}),\n ...(card ? { card } : {}),\n ...(typeof obj.receiptText === 'string' ? { receiptText: obj.receiptText } : {}),\n }\n}\n","/**\n * Shared helper for the host-side markdown formatter ↔ server-side\n * parser pair. Single source of truth so the host-side build (chat\n * bubble render) and the server-side strip (LLM input cleanup) can\n * never drift.\n *\n * Lib-side replacement for the hub's `lib/utils/chat-attachment-markdown.ts`.\n * The hub file pulled its constants from `lib/config/chat-attachment-config`\n * + its `ChatAttachment` type from `lib/types/chat-attachment`. Both are\n * inlined here as lib-local constants/types — they're stable wire-format\n * contracts (the hub's view-route owns the prefix + token-param name; any\n * change is a coordinated migration).\n *\n * URL flavors at a glance:\n * - HOST-SIDE (user-bubble render): uses the runtime's\n * `attachmentViewUrlPrefix` (hub default = `/api/storage/view/chat-attachments/`).\n * Embedded apps override per their reverse-proxy topology.\n * - SERVER-SIDE (strip regex): uses the constant\n * `CHAT_ATTACHMENT_VIEW_URL_PREFIX` directly. The chat ROUTE always\n * runs on the hub, so it always strips on the hub default.\n * - ANTHROPIC image-blocks: uses the RAW Supabase signed URL — NOT the\n * proxy URL — because Anthropic's image fetcher doesn't reliably\n * follow 302 redirects.\n *\n * Security gates inside the formatter:\n * - Filename markdown chars escaped via `escapeMarkdownInline` so a\n * name like `screenshot](https://evil.com).png` cannot terminate\n * the markdown image early and embed an attacker-controlled URL.\n * - `<` and `>` escaped too — prevents CommonMark autolink expansion\n * for filenames containing URL-shaped text.\n */\n\n// ---------------------------------------------------------------------------\n// Lib-local constants + types (mirror the hub's chat-attachment-config /\n// chat-attachment.ts). These are wire-format contracts owned by the hub's\n// view route; embedders that want to override the prefix do so via\n// `ChatRuntime.endpoints.attachmentViewUrlPrefix`, not by changing these.\n// ---------------------------------------------------------------------------\n\n/** Hub-default prefix for the view-proxy URL. Embedders override via the\n * runtime. The server-side strip regex always uses THIS value (server\n * runs on the hub). */\nexport const CHAT_ATTACHMENT_VIEW_URL_PREFIX = '/api/storage/view/chat-attachments/'\n\n/** Query parameter name for the HMAC view token. */\nexport const CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM = 't'\n\n/** Subset Anthropic's image content-block API supports. HEIC / video\n * attachments fall through to the text-marker form so the LLM still sees\n * a reference even when it can't visually parse the file. */\nexport const ANTHROPIC_SUPPORTED_IMAGE_MIME = [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/gif',\n] as const\n\n/**\n * Wire shape for a single chat attachment.\n *\n * `viewToken` is server-issued (HMAC-signed) and embedded in the markdown\n * URL's `?t=` query parameter. The client never generates it — the upload\n * route returns it alongside the storage path.\n */\nexport interface ChatAttachment {\n storagePath: string\n viewToken: string\n contentType: string\n fileName: string\n size: number\n}\n\n// ---------------------------------------------------------------------------\n// URL building\n// ---------------------------------------------------------------------------\n\n/**\n * Build the markdown view-URL for a chat attachment.\n *\n * `viewUrlPrefix` is parameterized (NOT pulled from the constant) so\n * host-side callers can pass the runtime's prefix\n * (`ChatRuntime.endpoints.attachmentViewUrlPrefix`) — embedded apps\n * supply an absolute URL against the hub's origin so chat-history\n * markdown works cross-origin.\n *\n * Server-side callers (the strip regex source) should pass\n * `CHAT_ATTACHMENT_VIEW_URL_PREFIX` directly.\n */\nexport function buildChatAttachmentViewUrl(\n viewUrlPrefix: string,\n storagePath: string,\n viewToken: string,\n): string {\n return `${viewUrlPrefix}${storagePath}?${CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM}=${encodeURIComponent(viewToken)}`\n}\n\n// ---------------------------------------------------------------------------\n// Markdown formatter\n// ---------------------------------------------------------------------------\n\n/**\n * Escape inline-markdown special characters from a filename before\n * interpolation. Closes the markdown-injection / phishing primitive:\n * a filename like `screenshot](https://evil.com).png` would otherwise\n * terminate `![filename](...)` early and emit an attacker-controlled\n * URL in the user's bubble.\n *\n * Escapes: `[`, `]`, `(`, `)`, `\\`, `\\n`, `\\r`, `<`, `>`, `\"`.\n */\nexport function escapeMarkdownInline(text: string): string {\n return text.replace(/[[\\]()\\\\\\n\\r<>\"]/g, (ch) => {\n switch (ch) {\n case '\\n':\n return ' '\n case '\\r':\n return ''\n default:\n return `\\\\${ch}`\n }\n })\n}\n\n/**\n * Format a single chat-attachment as a markdown line to append to the\n * user's bubble text BEFORE sending.\n *\n * Images (MIME in `ANTHROPIC_SUPPORTED_IMAGE_MIME`) emit the `![]()`\n * image form so the browser renders the attachment inline. Everything\n * else (HEIC, video, audio) emits the `[Attached: ...]` link form so the\n * bubble shows a clickable file pill instead of a broken-image icon.\n */\nexport function formatChatAttachmentMarkdownForBubble(\n att: ChatAttachment,\n viewUrlPrefix: string,\n): string {\n const safeName = escapeMarkdownInline(att.fileName)\n const url = buildChatAttachmentViewUrl(viewUrlPrefix, att.storagePath, att.viewToken)\n const isImage = (ANTHROPIC_SUPPORTED_IMAGE_MIME as readonly string[]).includes(att.contentType)\n return isImage ? `\\n\\n![${safeName}](${url})` : `\\n\\n[Attached: ${safeName}](${url})`\n}\n\n// ---------------------------------------------------------------------------\n// Server-side strip regex + parser\n// ---------------------------------------------------------------------------\n\n/**\n * Module-private: the `CHAT_ATTACHMENT_VIEW_URL_PREFIX` with regex\n * meta-characters escaped, so it can be safely interpolated into\n * regex sources. Computed ONCE at module load. Exported so other\n * regex-building call sites can share the same source of truth.\n */\nexport const CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED =\n CHAT_ATTACHMENT_VIEW_URL_PREFIX.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n/**\n * Single anchored regex matching both the image (`![]()`) and link\n * (`[Attached: ...]`) forms keyed on the server-side prefix.\n *\n * `gm` flags — multi-line anchored so the regex matches per-line.\n * Non-chat markdown links/images stay untouched because the regex\n * requires the literal `/api/storage/view/chat-attachments/` prefix.\n */\nexport const CHAT_ATTACHMENT_MARKDOWN_PATTERN = new RegExp(\n `^\\\\s*!?\\\\[[^\\\\]]*\\\\]\\\\(${CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED}[^)]+\\\\)\\\\s*$`,\n 'gm',\n)\n\n/**\n * Strip pre-embedded chat-attachment markdown lines from `text`.\n * Returns the cleaned text + the storage paths extracted from the\n * matched URLs.\n */\nexport function stripChatAttachmentMarkdown(text: string): {\n stripped: string\n storagePaths: string[]\n} {\n const storagePaths: string[] = []\n const pathExtract = new RegExp(\n `\\\\(${CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED}([^?)]+)`,\n )\n const stripped = text.replace(CHAT_ATTACHMENT_MARKDOWN_PATTERN, (match) => {\n const m = match.match(pathExtract)\n if (m && m[1]) storagePaths.push(m[1])\n return ''\n })\n return {\n stripped: stripped.replace(/\\n{3,}/g, '\\n\\n').trim(),\n storagePaths,\n }\n}\n","/**\n * Shared cross-process contract for the post-approval auto-continuation\n * directive. The client emits a hidden synthetic user message starting\n * with `AUTO_CONTINUATION_DIRECTIVE_PREFIX`; the server's `decideRoute`\n * matches that exact prefix on the RAW user query (pre-rewriter) and\n * hard-disables tools for the directive turn, forcing the LLM to\n * respond with prose follow-up questions instead of duplicating the\n * just-approved tool call.\n *\n * Single source of truth — both server-side `decideRoute` AND\n * client-side `autoContinueRef` import from here. Drifting the literal\n * on either side would silently break the duplicate-ticket guard\n * (server would route normally with tools wired; LLM would propose the\n * same tool again).\n *\n * `toolName` is typed as `string` (not a const-union) so the lib stays\n * generic across hub deployments — host code that has a sharper\n * `KnownWriteToolName` type can pass that through; this builder only\n * cares about a handful of string-equal branches.\n */\n\nexport const AUTO_CONTINUATION_DIRECTIVE_PREFIX = '[internal-auto-continuation]'\n\nexport interface BuildAutoContinuationOptions {\n ticketId?: string\n /** Reading of `args.status` on the just-approved tool call. Used to\n * branch the directive between \"post-create diagnostic Qs\",\n * \"post-close resolution ask\", and \"post-update acknowledgement\". */\n status?: string\n}\n\n/**\n * Build the directive text the client sends as a HIDDEN user message\n * after every successful Approve. The LLM treats it as the user\n * speaking; the chat shell filters it out at render time.\n *\n * Branch logic mirrors `TICKET_TOOL_PROTOCOL` §1a/§1b — keep them in\n * sync: the directive tells the model WHICH section to follow.\n */\nexport function buildAutoContinuationDirective(\n toolName: string,\n opts: BuildAutoContinuationOptions = {},\n): string {\n const ticketRef = opts.ticketId ? ` (ticket #${opts.ticketId})` : ''\n const ticketHash = opts.ticketId ? ` #${opts.ticketId}` : ''\n const isClose = toolName === 'update_ticket' && opts.status?.toUpperCase() === 'CLOSED'\n if (toolName === 'create_ticket') {\n return (\n `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved create_ticket${ticketRef}. ` +\n `Per ticket-protocol §1a, ask 2-4 SHORT, issue-specific diagnostic follow-up questions ` +\n `tailored to the symptom they reported in their original message. When they answer, ` +\n `propose an update_ticket with content_addendum carrying a clean Q&A digest. ` +\n `Do NOT call any tool in this turn — just write the questions as prose.`\n )\n }\n if (isClose) {\n return (\n `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved closing ticket${ticketHash}. ` +\n `Per ticket-protocol §1b, ask ONE short question: \"How was this resolved? I'll add it ` +\n `to the ticket as a closing note.\" Phrase kindly even if the user was curt. When they ` +\n `answer, propose an update_ticket with content_addendum=\"[Resolution] <their words>\". ` +\n `Do NOT call any tool in this turn — just write the prose ask.`\n )\n }\n return (\n `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved update_ticket${ticketHash}. ` +\n `Acknowledge the change in ONE short sentence; if anything else looks like it needs ` +\n `attention, ask. Do NOT call any tool in this turn.`\n )\n}\n","/**\n * `flattenAssistantContent` — coerce a chat message's `content` field\n * (string OR `MessageSegment[]`) into a plain string for wire transport.\n *\n * Background: useChat populates assistant messages with a structured\n * segment array as the streamed SSE arrives (text segments, approval\n * cards, tool_execution blocks, thinking blocks). The local React\n * state holds `content: MessageSegment[]` for those turns. When the\n * client serializes the conversation back to the server for the NEXT\n * turn, a naive `typeof content === 'string' ? content : ''` strip-\n * to-empty silently drops every post-approve receipt, every Sonnet-\n * streamed answer, and every diagnostic Q — Anthropic receives\n * `assistant: \"\"` for those turns and has no context to follow.\n *\n * The function:\n * 1. Returns plain strings as-is.\n * 2. For arrays, joins every `text`-typed segment's `text` field\n * with `\\n\\n` separators. Non-text segments (approval_request,\n * tool_execution, thinking) have no LLM-visible textual content\n * and are intentionally skipped — they shouldn't bloat the\n * request body.\n * 3. Returns `''` for anything else (null, undefined, unknown shape).\n */\nexport function flattenAssistantContent(raw: unknown): string {\n if (typeof raw === 'string') return raw\n if (!Array.isArray(raw)) return ''\n const parts: string[] = []\n for (const seg of raw) {\n if (seg && typeof seg === 'object' && (seg as { type?: string }).type === 'text') {\n const t = (seg as { text?: unknown }).text\n if (typeof t === 'string' && t.length > 0) parts.push(t)\n }\n }\n return parts.join('\\n\\n')\n}\n","/**\n * Message-related types\n * Contains all message structures, segments, and content types\n */\n\nimport type { AssistantType, AuthorType, ChatApprovalStatus, MessageOwner } from './chat.types'\n\n// ========== Message Type Definitions ==========\n\nexport const MESSAGE_TYPE = {\n TEXT: 'TEXT',\n THINKING: 'THINKING',\n EXECUTING_TOOL: 'EXECUTING_TOOL',\n EXECUTED_TOOL: 'EXECUTED_TOOL',\n APPROVAL_REQUEST: 'APPROVAL_REQUEST',\n APPROVAL_RESULT: 'APPROVAL_RESULT',\n ERROR: 'ERROR',\n MESSAGE_START: 'MESSAGE_START',\n MESSAGE_END: 'MESSAGE_END',\n MESSAGE_REQUEST: 'MESSAGE_REQUEST',\n AI_METADATA: 'AI_METADATA',\n TOKEN_USAGE: 'TOKEN_USAGE',\n CONTEXT_COMPACTION_START: 'CONTEXT_COMPACTION_START',\n CONTEXT_COMPACTION_END: 'CONTEXT_COMPACTION_END',\n DIRECT_MESSAGE: 'DIRECT_MESSAGE',\n SYSTEM: 'SYSTEM',\n DIALOG_CLOSED: 'DIALOG_CLOSED',\n} as const\n\nexport type MessageType = typeof MESSAGE_TYPE[keyof typeof MESSAGE_TYPE]\n\n// ========== Scroll Anchor (per-message render hint) ==========\n\n/** Per-message viewport-positioning hint sent on the per-turn metadata\n * leading frame at the START of every assistant response. The chat\n * message-list reads it to override the default `use-stick-to-bottom`\n * tail behaviour for a single message. Field is OPTIONAL — when omitted\n * (or set to `'bottom'`) the chat tails as today. Only `'top'` opts in\n * to the alternative behaviour (used by display-action answers whose\n * body is a long article and should be read top-down). */\nexport const SCROLL_ANCHOR = { TOP: 'top', BOTTOM: 'bottom' } as const\n\nexport type ScrollAnchor = typeof SCROLL_ANCHOR[keyof typeof SCROLL_ANCHOR]\n\n// ========== Tool Execution Types ==========\n\nexport interface ToolExecutionData {\n type: 'EXECUTING_TOOL' | 'EXECUTED_TOOL'\n integratedToolType: string\n toolFunction: string\n /** Backend-issued human-readable title (mirrors `PendingToolCallData.toolTitle`). */\n toolTitle?: string\n parameters?: Record<string, any>\n result?: string\n success?: boolean\n /**\n * Backend-issued id (matches `PendingToolCallData.toolExecutionRequestId`).\n * When present, lets the accumulator merge this execution event into the\n * matching approval batch row instead of emitting a standalone segment.\n */\n toolExecutionRequestId?: string\n}\n\n/**\n * Snapshot of an in-flight tool kept between the `EXECUTING_TOOL` and\n * `EXECUTED_TOOL` events. The backend only sends `toolTitle` on\n * `EXECUTING_TOOL`; carrying this state lets the accumulator restore it onto\n * the merged `EXECUTED_TOOL` segment instead of falling back to the raw\n * `toolFunction`.\n */\nexport interface ExecutingToolState {\n integratedToolType: string\n toolFunction: string\n /** Mirrors {@link ToolExecutionData.toolTitle}; absent on `EXECUTED_TOOL`. */\n toolTitle?: string\n parameters?: Record<string, any>\n}\n\n// ========== Approval Request Types ==========\n\nexport interface ApprovalRequestField {\n /** Short label — e.g. \"Subject\", \"Priority\". Rendered in a muted\n * caps style above the value. */\n label: string\n /** Free-text value. Wraps and line-breaks are preserved\n * (`whitespace-pre-wrap`). */\n value: string\n}\n\nexport interface ApprovalRequestData {\n command: string\n /** Structured field list — preferred over `explanation`. When set,\n * the approval card renders a vertical label/value stack with\n * proper spacing. Falls back to `explanation` (a single paragraph)\n * when omitted. Keep BOTH when you want hosts on older lib\n * versions to still see the prose; new hosts should send only\n * `fields`. */\n fields?: ApprovalRequestField[]\n explanation?: string\n icon?: React.ReactNode\n requestId?: string\n approvalRequestId?: string\n approvalType?: string\n}\n\nexport interface ApprovalResultData {\n approvalRequestId: string\n approved: boolean\n approvalType?: string\n}\n\n/**\n * Single tool call inside a batch approval request.\n * Mirrors backend PendingToolCallDto.\n */\nexport interface PendingToolCallData {\n toolExecutionRequestId: string\n toolName: string\n toolTitle?: string\n toolExplanation?: string\n toolType?: string\n requiresApproval: boolean\n approvalType?: string | null\n toolCallArguments?: Record<string, any> | null\n}\n\n/**\n * Per-tool execution state inside an approval batch.\n * Populated by EXECUTING_TOOL / EXECUTED_TOOL chunks that carry a\n * `toolExecutionRequestId` matching one of the batch's tool calls.\n */\nexport interface ApprovalBatchExecutionState {\n status: 'executing' | 'done'\n result?: string\n success?: boolean\n}\n\nexport interface ApprovalBatchData {\n approvalRequestId: string\n /** Highest approval type required across the batch (e.g. ADMIN beats CLIENT). */\n approvalType: string\n toolCalls: PendingToolCallData[]\n /**\n * Keyed by `PendingToolCallData.toolExecutionRequestId`. Absent before\n * approval; rows without an entry render as \"queued\" (loader) once the\n * batch itself is approved.\n */\n executions?: Record<string, ApprovalBatchExecutionState>\n}\n\n// ========== Message Segment Types ==========\n\nexport type TextSegment = {\n type: 'text'\n text: string\n}\n\nexport type ThinkingSegment = {\n type: 'thinking'\n text: string\n}\n\nexport type ToolExecutionSegment = {\n type: 'tool_execution'\n data: ToolExecutionData\n}\n\nexport type ApprovalRequestSegment = {\n type: 'approval_request'\n data: ApprovalRequestData & { approvalType?: string }\n status?: ChatApprovalStatus\n onApprove?: (requestId?: string) => void | Promise<void>\n onReject?: (requestId?: string) => void | Promise<void>\n}\n\nexport type ApprovalBatchSegment = {\n type: 'approval_batch'\n data: ApprovalBatchData\n status?: ChatApprovalStatus\n onApprove?: (requestId?: string) => void | Promise<void>\n onReject?: (requestId?: string) => void | Promise<void>\n}\n\nexport type ErrorSegment = {\n type: 'error'\n title: string\n details?: string\n}\n\nexport type ContextCompactionSegment = {\n type: 'context_compaction'\n status: 'started' | 'completed'\n summary?: string\n}\n\nexport type MessageSegment = TextSegment | ThinkingSegment | ToolExecutionSegment | ApprovalRequestSegment | ApprovalBatchSegment | ErrorSegment | ContextCompactionSegment\n\nexport type MessageContent = string | MessageSegment[]\n\n// ========== Message Data Types (from GraphQL/API) ==========\n\nexport interface MessageDataBase {\n type: MessageType\n}\n\nexport interface TextMessageData extends MessageDataBase {\n type: 'TEXT'\n text?: string\n}\n\nexport interface ThinkingMessageData extends MessageDataBase {\n type: 'THINKING'\n text?: string\n}\n\nexport interface ExecutingToolMessageData extends MessageDataBase {\n type: 'EXECUTING_TOOL'\n integratedToolType?: string\n toolFunction?: string\n /** Backend-issued human-readable title (wire field, mirrors `ChunkData.title`). */\n title?: string\n parameters?: Record<string, any>\n toolExecutionRequestId?: string\n}\n\nexport interface ExecutedToolMessageData extends MessageDataBase {\n type: 'EXECUTED_TOOL'\n integratedToolType?: string\n toolFunction?: string\n /** Backend-issued human-readable title (wire field, mirrors `ChunkData.title`). */\n title?: string\n parameters?: Record<string, any>\n result?: string\n success?: boolean\n toolExecutionRequestId?: string\n}\n\nexport interface ApprovalRequestMessageData extends MessageDataBase {\n type: 'APPROVAL_REQUEST'\n approvalRequestId?: string\n approvalType?: string\n command?: string\n explanation?: string\n /** Present when the approval is a batch of tool calls (new format). */\n toolCalls?: PendingToolCallData[]\n}\n\nexport interface ApprovalResultMessageData extends MessageDataBase {\n type: 'APPROVAL_RESULT'\n approvalRequestId?: string\n approved?: boolean\n approvalType?: string\n}\n\nexport interface ErrorMessageData extends MessageDataBase {\n type: 'ERROR'\n error?: string\n details?: string\n}\n\nexport interface AIMetadataMessageData extends MessageDataBase {\n type: 'AI_METADATA'\n modelName?: string\n providerName?: string\n provider?: string\n contextWindow?: number\n}\n\nexport interface TokenUsageData {\n inputTokensSize: number\n outputTokensSize: number\n totalTokensSize: number\n contextSize: number\n}\n\nexport interface SystemMessageData extends MessageDataBase {\n type: 'SYSTEM'\n text?: string\n}\n\nexport interface ContextCompactionStartMessageData extends MessageDataBase {\n type: 'CONTEXT_COMPACTION_START'\n}\n\nexport interface ContextCompactionEndMessageData extends MessageDataBase {\n type: 'CONTEXT_COMPACTION_END'\n summary?: string\n}\n\nexport type MessageData =\n | TextMessageData\n | ThinkingMessageData\n | ExecutingToolMessageData\n | ExecutedToolMessageData\n | ApprovalRequestMessageData\n | ApprovalResultMessageData\n | ErrorMessageData\n | AIMetadataMessageData\n | SystemMessageData\n | ContextCompactionStartMessageData\n | ContextCompactionEndMessageData\n\n// ========== Historical Message Types ==========\n\nexport interface HistoricalMessage {\n id: string\n dialogId?: string\n chatType?: string\n createdAt: string\n owner?: MessageOwner\n messageData?: MessageData | MessageData[]\n}\n\n// ========== Processed Message Types ==========\n\nexport interface ProcessedMessage {\n id: string\n role: 'user' | 'assistant' | 'error' // Limited to display roles\n content: MessageContent\n name?: string\n assistantType?: AssistantType\n authorType?: AuthorType\n timestamp: Date\n avatar?: string\n}\n\n// ========== Base Message Interface ==========\n\nimport type { ChatRef as MessageChatRef } from '../chat-ref.types'\n\nexport interface Message {\n id: string\n role: 'user' | 'assistant' | 'error' // Limited to display roles\n content: MessageContent\n name?: string\n assistantType?: AssistantType\n authorType?: AuthorType\n timestamp?: Date\n avatar?: string | null\n /** Per-row metadata for inline entity-card rendering on this message\n * (v6.1 §B.2.6). Keyed by `<documentType>:<primaryKey>`. Optional —\n * user messages and legacy turns omit this field. The host's\n * `renderEntityCard` callback resolves keys to inline components. */\n chatRefs?: Record<string, MessageChatRef>\n /** Per-message viewport-positioning hint. OPTIONAL — when omitted (the\n * default for every LLM Q&A / browse / search / find / Discuss path)\n * the chat tails as today via `use-stick-to-bottom`. Only `'top'` opts\n * in to the alternative top-anchor behaviour (display-action answers\n * whose body is a long article). The server is the sole decision-\n * maker — set on the metadata leading frame. */\n scrollAnchor?: ScrollAnchor\n /** When true the message is part of the API conversation history (sent\n * to the LLM so it has context) but is NOT rendered in the chat UI.\n *\n * Used for \"synthetic continuation\" turns: when the user clicks Approve\n * on a tool proposal, the host auto-fires a follow-up `sendMessage`\n * with `hidden: true` carrying a directive like \"the user just\n * approved <tool>; ask follow-up questions per protocol\". The LLM's\n * response IS rendered (as a normal assistant message); only the\n * trigger prompt is suppressed so the chat reads naturally:\n *\n * user: \"open a ticket\"\n * assistant: preamble + approval card\n * [user clicks Approve]\n * assistant: \"Now to triage faster, can you share...\" ← auto-fires\n *\n * Without this flag the trigger prompt would surface as a confusing\n * bubble like \"(continue per protocol)\" between the approval card\n * and the AI's follow-up. */\n hidden?: boolean\n}","/**\n * Wire glue + canonical const for the per-message `scrollAnchor`\n * render hint.\n *\n * The actual `SCROLL_ANCHOR` const + `ScrollAnchor` type lives in\n * `../types/message.types.ts` (it's part of the `Message` shape). This\n * module re-exports them alongside the wire-key + a `parseScrollAnchor`\n * narrower so server-side code that emits the metadata leading frame and\n * client-side code that consumes it agree on the literal value AND the\n * key on the wire frame.\n *\n * Consumed by:\n * - SERVER: emits the field into the metadata leading frame\n * (`...(scrollAnchor ? { [SCROLL_ANCHOR_WIRE_KEY]: x } : {})`).\n * - CLIENT: parses each leading frame and feeds the value through\n * `parseScrollAnchor` before storing it for the chat-message-list\n * to consume. Malformed wire values return `null` and are filtered\n * by metadata-merge logic — they never clobber a prior value.\n */\n\nimport { SCROLL_ANCHOR, type ScrollAnchor } from '../types/message.types'\n\nexport { SCROLL_ANCHOR, type ScrollAnchor }\n\n/** Wire-frame key for the `scrollAnchor` field on the metadata leading\n * frame. Used as a computed property name on both the emit side\n * (server) and the parse side (client) so a rename is one-file. */\nexport const SCROLL_ANCHOR_WIRE_KEY = \"scrollAnchor\" as const\n\n/** Narrow + validate a wire-supplied value. Returns the literal when\n * it matches one of the registry's known values; returns `null`\n * otherwise (which the metadata-merge null-skip filter then drops). */\nexport function parseScrollAnchor(raw: unknown): ScrollAnchor | null {\n return raw === SCROLL_ANCHOR.TOP || raw === SCROLL_ANCHOR.BOTTOM ? raw : null\n}\n","/**\n * Lib-side portable subset of the hub's `lib/utils/slash-dispatch-utils.ts`.\n *\n * The full hub file owns the SERVER-SIDE parser/dispatcher (depends on\n * `slash-commands-config`, `slash-commands-static`, `doc-source-config-utils`,\n * `chat-admin-types`, `rag-table-config`) which stays hub-side.\n *\n * What MIGRATES here is the wire contract + the small text helpers consumed\n * by chat surfaces in the lib + the hub UI:\n * - `WireCommandOverride` — wire-shape (chat request body)\n * - `parseWireCommandOverride` — wire validator\n * - `CommandOverride` — server-built dispatch result type\n * (presentation typed as `string` here; the hub narrows via its own\n * `SlashCommandPresentation` union)\n * - `extractEntityIdFilter` — `CommandOverride` → narrowed filter\n * - `sanitizeTitleForChat` — collapse control chars in titles\n * - `formatSingularLookupInvocation` — `/cmd \"value\"` builder\n * - `buildDiscussAddendum` — server-side Discuss addendum prose\n *\n * Validation constants (regex + length caps) are duplicated here verbatim\n * to keep the lib's wire validator self-contained.\n */\n\nconst WIRE_TABLE_ID_REGEX = /^[a-z][a-z0-9-]*$/\nconst WIRE_ID_REGEX = /^[A-Za-z0-9._:/-]+$/\nconst WIRE_TABLE_ID_MAX = 60\nconst WIRE_ID_MAX = 200\nconst WIRE_QUERY_MAX = 2000\n\n/** Wire-supplied `CommandOverride` — the subset of fields a client (chat\n * shell) is allowed to send on the request body. Excludes\n * `systemPromptAddendum` by construction: addendum injection is a\n * Rule-5b bypass vector, so we never accept it from the wire. */\nexport interface WireCommandOverride {\n entityIdFilter?: { tableId: string; id: string }\n retrievalQueryOverride?: string\n}\n\n/**\n * Parse + validate a wire-supplied `commandOverride` from the chat\n * request body. Returns the validated subset OR `null` if the input is\n * missing / malformed in every field.\n */\nexport function parseWireCommandOverride(raw: unknown): WireCommandOverride | null {\n if (!raw || typeof raw !== 'object') return null\n const out: WireCommandOverride = {}\n const r = raw as Record<string, unknown>\n\n if (r.entityIdFilter && typeof r.entityIdFilter === 'object') {\n const f = r.entityIdFilter as Record<string, unknown>\n if (\n typeof f.tableId === 'string'\n && f.tableId.length > 0\n && f.tableId.length <= WIRE_TABLE_ID_MAX\n && WIRE_TABLE_ID_REGEX.test(f.tableId)\n && typeof f.id === 'string'\n && f.id.length > 0\n && f.id.length <= WIRE_ID_MAX\n && WIRE_ID_REGEX.test(f.id)\n ) {\n out.entityIdFilter = { tableId: f.tableId, id: f.id }\n }\n }\n if (\n typeof r.retrievalQueryOverride === 'string'\n && r.retrievalQueryOverride.length > 0\n && r.retrievalQueryOverride.length <= WIRE_QUERY_MAX\n ) {\n out.retrievalQueryOverride = r.retrievalQueryOverride\n }\n if (out.entityIdFilter === undefined && out.retrievalQueryOverride === undefined) {\n return null\n }\n return out\n}\n\n/**\n * Sanitize a free-text title for use inside a chat-visible string:\n * collapse control chars (\\r \\n \\t) to single spaces and trim. Defends\n * against a row title containing embedded newlines (which would split\n * the rendered prompt across visible lines + survive into ILIKE in a\n * confusing way) and tab/CR artifacts from sloppy imports.\n */\nexport function sanitizeTitleForChat(value: string | null | undefined): string {\n return (value ?? '').replace(/[\\r\\n\\t]+/g, ' ').trim()\n}\n\n/**\n * Compose a singular-lookup slash invocation as the user-visible chat\n * message: `/<cmd> \"<value>\"` (or `/<cmd>` when value is empty).\n *\n * SINGLE SOURCE OF TRUTH for the quoting convention `parseSlashCommand`\n * consumes: outer `\"`-pair triggers `singularLookup`; unquoted args run\n * FTS; empty args browse. Internal `\"` chars are backslash-escaped so\n * the visible string is paste-able / re-runnable.\n */\nexport function formatSingularLookupInvocation(cmdId: string, value?: string | null): string {\n // Escape `\\` BEFORE `\"` — otherwise a value ending in `\\` survives the\n // `\"`-escape pass and, when wrapped in `\"...\"`, the trailing `\\\"`\n // becomes a literal `\"` to a parser that processes backslash escapes,\n // breaking the close quote. CodeQL's `js/incomplete-sanitization` fires\n // on the previous one-pass `\\\"` escape for exactly this reason.\n const safe = sanitizeTitleForChat(value)\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n return safe ? `/${cmdId} \"${safe}\"` : `/${cmdId}`\n}\n\n/** Command-override structure passed to `buildChatContext.opts.commandOverride`. */\nexport interface CommandOverride {\n retrievalScope?: string[]\n systemPromptAddendum?: string\n retrievalQueryOverride?: string | null\n /** Singular-item lookup. When set, retrieval bypasses FTS and queries the\n * named table directly via ILIKE on the matchFields. */\n entityLookup?: {\n tableId: string\n value: string\n matchFields: string[]\n }\n /** Singular row by primary key. Used by the inline object-card\n * \"Discuss\" action — the client knows the exact row id from a prior\n * chip. Higher precedence than `entityLookup` (route enforces) and\n * `retrievalQueryOverride`. The retrieval layer still runs the table's\n * `searchFilter` so privacy invariants hold. */\n entityIdFilter?: {\n tableId: string\n id: string\n }\n /** \"Browse\" bypass for bare slash list commands. The search layer\n * treats this as \"skip FTS — return rows from these tableIds ordered\n * by the configured `primaryDateColumn` DESC\". */\n browseScope?: string[]\n /** Presentation hint propagated from the slash command. Hub narrows to\n * its `SlashCommandPresentation` union; lib leaves as `string` for\n * decoupling. */\n presentation?: string\n}\n\n/**\n * Resolve the wire `entityIdFilter` from a `CommandOverride`, optionally\n * narrowed to a specific `tableId`. Returns the validated `{ tableId, id }`\n * pair only when both fields are present, non-empty, and (when an expected\n * tableId is passed) match. Returns `null` otherwise.\n */\nexport function extractEntityIdFilter(\n override: CommandOverride | null | undefined,\n expectedTableId?: string,\n): { tableId: string; id: string } | null {\n const f = override?.entityIdFilter\n if (!f) return null\n const tableId = typeof f.tableId === 'string' ? f.tableId : ''\n const id = typeof f.id === 'string' ? f.id : ''\n if (!tableId || !id) return null\n if (expectedTableId && tableId !== expectedTableId) return null\n return { tableId, id }\n}\n\n/**\n * Server-only synthesizer for the Discuss-action system-prompt addendum.\n * Called by the chat route AFTER `parseWireCommandOverride` accepts an\n * `entityIdFilter` — the addendum text is composed from server-trusted\n * values (the row's tableId + id) so a malicious client can't inject\n * arbitrary prompt content.\n */\nexport function buildDiscussAddendum(args: { tableId: string; id: string }): string {\n const idTag = args.id.length > 24 ? args.id.slice(0, 24) + '…' : args.id\n return (\n `Ask drill-in for row id=\"${args.id}\" in table \"${args.tableId}\". Focus the ` +\n `answer on this single record. If retrieval returns 0 rows (privacy ` +\n `filter), say so plainly per Rule 5b.\\n\\n` +\n `OPEN with the inline card on the FIRST line, immediately followed by ` +\n `the chip and a mono-font id tag — no prose before the card:\\n` +\n ` [card://<type>:${args.id}] [N] \\`${args.tableId} · ${idTag}\\`\\n` +\n `Use the EXACT <type> from the row's <document type=\"...\" id=\"${args.id}\"> tag.\\n\\n` +\n `SURFACE EVERY FIELD PRESENT in the retrieved record — the user already ` +\n `knows the title from the card; the value of Ask is the BODY (description, ` +\n `status, vote counts, dates, linked URLs, …). Walk each non-empty field. ` +\n `Don't invent fields, don't hallucinate values, silently omit absent fields.\\n\\n` +\n `FORMAT: card+chip+id-tag opener, then ONE framing sentence, then a compact ` +\n `bulleted \"**Field** — value\" list. Don't restate fields already in the list.`\n )\n}\n","/**\n * ClickUp custom_item_id → human-readable label resolver.\n *\n * Lib-side subset of the hub's `lib/utils/clickup-task-type-utils.ts`.\n * The hub file also exports delivery / workspace slug helpers used by\n * the sync engine; only the chat-surfaced label resolver migrates here\n * because chat-inline cards and activity feeds need it.\n *\n * Reference: ClickUp's standard task types (custom_item_id values):\n * null/1000=Task, 1001=Milestone, 1002=Recurring, 1003=Subtask,\n * 1004=Form, 1006=Plan, 1007=Strategy, 1008=Bug, 1009=Request,\n * 1010=Feature, 1011=Story, 1012=Epic, 1013=Component, 1014=Initiative.\n */\n\nexport const CUSTOM_ITEM_ID = {\n TASK: 1000,\n MILESTONE: 1001,\n RECURRING: 1002,\n SUBTASK: 1003,\n FORM: 1004,\n PLAN: 1006,\n STRATEGY: 1007,\n BUG: 1008,\n REQUEST: 1009,\n FEATURE: 1010,\n STORY: 1011,\n EPIC: 1012,\n COMPONENT: 1013,\n INITIATIVE: 1014,\n} as const\n\n/**\n * Display name for a ClickUp task type — used in chat-inline cards and\n * activity feeds where the type badge would otherwise show a numeric ID.\n *\n * Returning `null` for unknown IDs lets callers fall back to a generic\n * \"Task\" affordance rather than printing `task-1100` or similar.\n */\nexport function getTaskTypeLabel(\n customItemId: number | null | undefined,\n): string | null {\n switch (customItemId) {\n case CUSTOM_ITEM_ID.TASK: return 'Task'\n case CUSTOM_ITEM_ID.MILESTONE: return 'Milestone'\n case CUSTOM_ITEM_ID.RECURRING: return 'Recurring'\n case CUSTOM_ITEM_ID.SUBTASK: return 'Subtask'\n case CUSTOM_ITEM_ID.FORM: return 'Form'\n case CUSTOM_ITEM_ID.PLAN: return 'Plan'\n case CUSTOM_ITEM_ID.STRATEGY: return 'Strategy'\n case CUSTOM_ITEM_ID.BUG: return 'Bug'\n case CUSTOM_ITEM_ID.REQUEST: return 'Request'\n case CUSTOM_ITEM_ID.FEATURE: return 'Feature'\n case CUSTOM_ITEM_ID.STORY: return 'Story'\n case CUSTOM_ITEM_ID.EPIC: return 'Epic'\n case CUSTOM_ITEM_ID.COMPONENT: return 'Component'\n case CUSTOM_ITEM_ID.INITIATIVE: return 'Initiative'\n default: return null\n }\n}\n","/**\n * Status color-scheme resolver used by chat-adjacent badges (StatusBadge\n * components rendering job, ClickUp task, and log-level statuses).\n *\n * Lib-side subset of the hub's `lib/utils/agent-status-message.ts`. The\n * hub file also carries CSS-class resolvers + an `AgentStatusMessage`\n * builder for the SSE-status surface; those live hub-side because they\n * reference hub-only ODS class names. This function returns the abstract\n * color scheme name only — the consuming `StatusBadge` (in this lib)\n * maps it to concrete colors.\n */\n\nexport type ColorScheme = 'success' | 'error' | 'warning' | 'cyan' | 'default'\n\n/**\n * Map a status to a color scheme name for StatusBadge components.\n * Supports job/processing statuses, ClickUp task statuses, and log levels.\n */\nexport function getStatusColorScheme(status: string): ColorScheme {\n const s = status?.toLowerCase() || ''\n\n // Exact matches first (most common)\n switch (status) {\n case 'completed':\n case 'success':\n case 'active': // review cycles, feature flags, etc.\n return 'success'\n case 'failed':\n case 'failure':\n case 'cancelled':\n case 'error':\n return 'error'\n case 'running':\n case 'processing':\n case 'closed': // review cycles past their active window\n return 'cyan'\n case 'pending':\n case 'warning':\n return 'warning'\n case 'draft': // review cycles not yet opened to reviewers\n case 'info':\n return 'default'\n }\n\n // Partial matches for ClickUp-style statuses (Complete, Done, Working, etc.)\n if (s.includes('complete') || s.includes('done')) return 'success'\n if (s.includes('review')) return 'cyan'\n if (s.includes('working') || s.includes('progress')) return 'warning'\n if (s.includes('blocked') || s.includes('failed')) return 'error'\n\n return 'default'\n}\n","/**\n * Unified URL builders for the third-party app deep-links used by chat\n * surfaces (chip clicks, inline-card tracking rows).\n *\n * Lib-side subset of the hub's `lib/utils/external-app-urls.ts`. Today\n * it carries the ClickUp deep-link helper only — HubSpot and admin\n * routes stay hub-side because they're consumed exclusively by\n * hub-internal mappers.\n */\n\nconst CLICKUP_APP_BASE = 'https://app.clickup.com'\n\n/** ClickUp task detail page in the ClickUp UI. Returns `null` when the\n * external id is missing so consumers don't end up with a\n * `.../t/undefined` link. */\nexport function clickupTaskUrl(externalId: string | null | undefined): string | null {\n if (!externalId) return null\n return `${CLICKUP_APP_BASE}/t/${externalId}`\n}\n","/**\n * Pure utility — true iff `url` has an explicit host (i.e. would resolve\n * to a different origin than where the consumer is running). Used by\n * chat nav decisions and the extracted `decideNewTab` helper.\n *\n * SSR-deterministic: any URL with an explicit host (http://, https://,\n * or protocol-relative //) is treated as cross-origin. By convention\n * same-origin same-app navigation uses RELATIVE paths; an absolute URL\n * with a host is external.\n *\n * Why deterministic: an earlier `window`-dependent implementation\n * returned different values during SSR (false — no window) vs client\n * hydration (true — origin differs), causing React hydration mismatches\n * on every anchor that fell into the no-targetPlatform fallback (e.g.\n * footer \"Support\" links to flamingo.run/support). Same-platform\n * absolute URLs (rare — they only happen when a composer like\n * `buildContentURL` returns an absolute URL for a non-current platform)\n * flow through `decideNewTab`'s PLATFORM branch first (which uses\n * `targetPlatform !== currentSource`) and never reach this fallback.\n */\nexport function isCrossOriginUrl(url: string | null | undefined): boolean {\n if (!url) return false\n // Relative URL — by definition same origin.\n if (url.startsWith('/') && !url.startsWith('//')) return false\n // Anything else — absolute URL (http(s)://) or protocol-relative (//)\n // — is treated as cross-origin.\n return true\n}\n","import React from 'react';\n\n/**\n * `fetchPriorityProp(priority)` — build the right shape for the `<img>` /\n * `<iframe>` fetch-priority hint based on the React major version detected\n * at module load.\n *\n * React 18 only recognizes the lowercase HTML attribute `fetchpriority`\n * and emits a console warning when it sees the camelCase prop. React 19+\n * recognizes the camelCase prop `fetchPriority` (matching the DOM's IDL\n * property) and warns when it sees the lowercase form.\n *\n * Spread the returned object into the element so the rendered DOM ends\n * up with the canonical lowercase `fetchpriority` attribute either way,\n * with zero console warnings on both React versions.\n *\n * Accepts either a boolean (for the simple \"high vs low\" hint at LCP\n * candidates) or an explicit HTML `fetchpriority` value (`'high' | 'low'\n * | 'auto'`) for call sites that always want one specific value.\n */\nconst REACT_MAJOR = parseInt((React.version || '0').split('.')[0], 10);\nconst USE_CAMEL_CASE_FETCH_PRIORITY = REACT_MAJOR >= 19;\n\nexport type FetchPriorityValue = 'high' | 'low' | 'auto';\n\nexport function fetchPriorityProp(\n priority: boolean | FetchPriorityValue | undefined,\n): Record<string, string> {\n // `undefined` → `'auto'` so callers can spread `{...fetchPriorityProp(maybeBool)}`\n // without a separate null-check at every callsite. `'auto'` is the\n // DOM default and emits no warning on either React major.\n const value: FetchPriorityValue =\n priority === undefined\n ? 'auto'\n : typeof priority === 'boolean'\n ? priority ? 'high' : 'low'\n : priority;\n return USE_CAMEL_CASE_FETCH_PRIORITY\n ? { fetchPriority: value }\n : { fetchpriority: value };\n}\n","// Product Release Types\n// Following the blog.ts pattern for consistency\n\nimport type { PlatformRecord } from './platform'\nimport type { BlogTag } from './blog'\nimport type { VideoTeaser, TranscriptWord, SpeakerMapping } from './video-processing'\n\nexport interface ChangelogEntry {\n title: string\n description?: string\n /**\n * Per-entry visibility flag. Optional so product releases (which always render\n * publicly) remain backwards compatible. Investor updates require this field\n * because each entry can be marked internal — see investor-update-utils.ts.\n */\n visibility?: 'public' | 'internal'\n}\n\nexport interface ReleaseMedia {\n id: number\n release_id: number\n media_type: 'image' | 'video' | 'screenshot' | 'demo'\n media_url: string\n display_order: number | null\n title: string | null\n description: string | null\n created_at: string\n updated_at: string\n created_by: string\n}\n\nexport interface ProductReleaseGitHubLink {\n id: number\n release_id: number\n github_release_url: string // Full URL (e.g., https://github.com/org/repo/releases/tag/v2.0.0)\n display_order: number | null\n created_at: string\n}\n\nexport interface KnowledgeBaseLink {\n id: number\n release_id: number\n kb_article_path: string // Relative path (e.g., /api/authentication/api-keys.md)\n display_order: number | null\n created_at: string\n}\n\nexport interface ClickUpRoadmapTask {\n id: number\n release_id: number\n clickup_task_id: string // Just the task ID - details from roadmap folder\n display_order: number | null\n created_at: string\n}\n\nexport interface ClickUpDeliveryTask {\n id: number\n release_id: number\n clickup_task_id: string // Just the task ID - details from delivery list\n display_order: number | null\n created_at: string\n}\n\nexport interface ProductRelease {\n id: number\n title: string\n slug: string\n version: string\n summary: string | null\n content: string | null\n\n // Release metadata\n release_type: 'major' | 'minor' | 'patch' | 'beta' | 'alpha'\n release_status: 'alpha' | 'beta' | 'stable' | 'deprecated'\n release_date: string\n\n // Changelog (JSONB arrays)\n features_added: ChangelogEntry[]\n bugs_fixed: ChangelogEntry[]\n improvements: ChangelogEntry[]\n breaking_changes: ChangelogEntry[]\n\n // External relationships (one-to-many)\n github_releases?: ProductReleaseGitHubLink[]\n knowledge_base_links?: KnowledgeBaseLink[]\n clickup_roadmap_tasks?: ClickUpRoadmapTask[]\n clickup_delivery_tasks?: ClickUpDeliveryTask[]\n release_media?: ReleaseMedia[]\n\n // Media (keeping featured_image for hero)\n featured_image: string | null\n\n // Documentation\n migration_guide_url: string | null\n documentation_url: string | null\n\n // Video (youtube_url for embeds, main_video_url for AI processing)\n youtube_url: string | null\n main_video_url: string | null\n transcript: string | null\n transcript_words_data?: TranscriptWord[]\n srt_content?: string | null\n video_summary: string | null // AI-generated summary from video transcription\n video_bites: VideoTeaser[] // JSONB array of extracted video clips\n highlight_video_url: string | null\n highlight_video_thumbnail: string | null\n highlight_video_duration_ms: number | null\n highlight_video_source: 'manual' | 'ai_generated' | null\n main_video_thumbnail: string | null\n ai_transcript_formatted?: string\n speaker_mapping?: SpeakerMapping\n ai_confidence_transcript: number | null\n ai_confidence_video_summary: number | null // Confidence for video-generated summary\n ai_confidence_summary: number | null // Confidence for entity summary (Release Content Generation)\n\n // SEO\n seo_title: string | null\n seo_description: string | null\n seo_keywords: string | null\n og_image_url: string | null\n\n // Publishing\n status: 'draft' | 'published' | 'archived'\n published_at: string | null\n author_id: string | null\n /**\n * Hydrated by `getRelease` (detail) and `getReleases` (list) via\n * `hydrateAuthor` in the hub DAL. Optional so admin form + every existing\n * consumer that doesn't read author stay backward-compatible.\n */\n author?: {\n id: string\n full_name: string\n avatar_url: string | null\n job_title: string | null\n email?: string | null\n }\n\n // Timestamps\n created_at: string\n updated_at: string\n\n // Editor-provided AI generation instructions (steers Generate Content prompt)\n custom_instructions: string | null\n\n // Analytics\n view_count: number\n download_count: number\n\n // Relations (populated by joins)\n platforms?: PlatformRecord[]\n tags?: BlogTag[]\n product_release_platforms?: Array<{\n platform_id: string\n is_featured: boolean\n featured_order: number | null\n }>\n product_release_tags?: Array<{\n tag_id: number\n }>\n blog_tags?: BlogTag[]\n}\n\nexport interface CreateProductReleaseData {\n title: string\n slug: string\n version: string\n summary?: string\n content?: string\n release_type: 'major' | 'minor' | 'patch' | 'beta' | 'alpha'\n release_status: 'alpha' | 'beta' | 'stable' | 'deprecated'\n release_date: string\n features_added?: ChangelogEntry[]\n bugs_fixed?: ChangelogEntry[]\n improvements?: ChangelogEntry[]\n breaking_changes?: ChangelogEntry[]\n github_releases?: Array<{ github_release_url: string; display_order?: number }>\n knowledge_base_links?: Array<{ kb_article_path: string; display_order?: number }>\n clickup_roadmap_tasks?: Array<{ clickup_task_id: string; display_order?: number }>\n clickup_delivery_tasks?: Array<{ clickup_task_id: string; display_order?: number }>\n release_media?: Array<{ media_type: 'image' | 'video' | 'screenshot' | 'demo'; media_url: string; title?: string; description?: string; display_order?: number }>\n featured_image?: string\n migration_guide_url?: string\n documentation_url?: string\n youtube_url?: string\n main_video_url?: string\n transcript?: string\n srt_content?: string | null\n video_summary?: string // AI-generated summary from video transcription\n video_bites?: VideoTeaser[]\n highlight_video_url?: string | null\n highlight_video_thumbnail?: string | null\n highlight_video_duration_ms?: number | null\n highlight_video_source?: 'manual' | 'ai_generated' | null\n main_video_thumbnail?: string | null\n seo_title?: string\n seo_description?: string\n seo_keywords?: string\n og_image_url?: string\n status: 'draft' | 'published' | 'archived'\n published_at?: string | null\n author_id: string\n platforms: string[] // Array of platform IDs (UUIDs)\n featured_platform?: string // Platform ID for featured\n tags: number[] // Array of tag IDs\n custom_instructions?: string | null\n}\n\nexport type UpdateProductReleaseData = Partial<CreateProductReleaseData>\n\nexport interface ProductReleaseFilters {\n platform?: string | 'all'\n tags?: string[]\n version?: string\n release_type?: ('major' | 'minor' | 'patch' | 'beta' | 'alpha')[]\n release_status?: ('alpha' | 'beta' | 'stable' | 'deprecated')[]\n has_breaking_changes?: boolean\n search?: string\n featured?: boolean\n status?: string\n limit?: number\n offset?: number\n ids?: (number | string)[]\n}\n\nexport interface ProductReleaseListResponse {\n data: ProductRelease[]\n count: number\n}\n\n// GitHub Release interface (for wizard)\nexport interface GitHubRelease {\n id: string\n tag_name: string\n name: string\n body: string\n published_at: string\n html_url: string\n prerelease: boolean\n draft: boolean\n}\n\n// Release type options for dropdowns\nexport const releaseTypeOptions = [\n { value: 'major', label: 'Major Release', description: 'Breaking changes, new architecture', color: 'red' },\n { value: 'minor', label: 'Minor Release', description: 'New features, backward compatible', color: 'blue' },\n { value: 'patch', label: 'Patch Release', description: 'Bug fixes only', color: 'green' },\n { value: 'beta', label: 'Beta Release', description: 'Pre-release testing version', color: 'yellow' },\n { value: 'alpha', label: 'Alpha Release', description: 'Early testing version', color: 'orange' }\n] as const\n\n// Release status options\nexport const releaseStatusOptions = [\n { value: 'alpha', label: 'Alpha', description: 'Early development, unstable', color: 'orange' },\n { value: 'beta', label: 'Beta', description: 'Feature complete, testing', color: 'yellow' },\n { value: 'stable', label: 'Stable', description: 'Production ready', color: 'green' },\n { value: 'deprecated', label: 'Deprecated', description: 'No longer supported', color: 'gray' }\n] as const\n\n// Changelog category labels\nexport const changelogLabels = {\n features_added: 'Features Added',\n bugs_fixed: 'Bugs Fixed',\n improvements: 'Improvements',\n breaking_changes: 'Breaking Changes'\n} as const\n\n// Semantic versioning validation regex\nexport const SEMVER_REGEX = /^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$/\n","/**\n * Canonical per-section metadata for the OpenFrame dev-center surfaces\n * (Roadmap / Bug-fixes & Enhancements / Releases / Onboarding Guides).\n *\n * One file co-locates every per-section value the openframe homepage\n * navigator card AND the destination full-page hero both consume —\n * icon, brief navigator description, longer hero paragraph, search\n * config (placeholder + paramKey), filter config (paramKey + options).\n *\n * Adding a 5th section is one edit here and zero edits across the\n * page files / navigator grid.\n *\n * EMBEDDER NOTE — `onboarding`:\n * The `onboarding` entry is INERT on `hero`/`search`/`filter` because\n * `/onboarding-guides` is owned by `OnboardingGuidesCatalogView` (a\n * hub-side full-page view), not the shared `DevSectionView` chrome.\n * This entry exists ONLY to drive the homepage navigator card. Any\n * embedder iterating the registry must SKIP `onboarding` if they\n * don't host the `/onboarding-guides` route — e.g.\n * `Object.values(OPENFRAME_DEV_SECTIONS).filter(s => s.href !== '/onboarding-guides')`.\n *\n * SERVER-BUNDLE SAFETY:\n * This module imports lucide-react icon components as JSX values but\n * never RENDERS them at module load. Lib's tsup config places `utils/`\n * in the server bundle (no `\"use client\"` banner), which is safe\n * because component-function references don't execute on import.\n * Precedent: `src/utils/platform-config.tsx` (also lucide imports,\n * also server-bundle, also imported by route-page `metadata` exports).\n */\n\nimport { Map as MapIcon, Wrench, Rocket, GraduationCap, LifeBuoy, type LucideIcon } from 'lucide-react'\nimport { releaseStatusOptions } from '../../types'\n\n// Roadmap status options — `as const` preserves readonly tuple typing\n// across the registry boundary.\nexport const ROADMAP_STATUS_OPTIONS = [\n { value: 'all', label: 'All' },\n { value: 'completed', label: 'Completed' },\n { value: 'in_progress', label: 'In Progress' },\n] as const\n\n// Delivery (ClickUp custom item type) filter options. `Bug` and `Request`\n// are the ClickUp `custom_item_id` labels — 1008 / 1009.\nexport const DELIVERY_TASK_TYPE_OPTIONS = [\n { value: 'all', label: 'All' },\n { value: 'Bug', label: 'Bug-fix' },\n { value: 'Request', label: 'Enhancement' },\n] as const\n\n// Ticket status filter for the Help Center. Lowercase wire values\n// match what `/api/chat/agent/find-ticket` accepts in `body.status`\n// (the route normalizes to lowercase + allowlists 'open' | 'closed'\n// before threading into `findTicketExecutor`'s `selfStatus` scope).\nexport const TICKET_STATUS_OPTIONS = [\n { value: 'all', label: 'All' },\n { value: 'open', label: 'Open' },\n { value: 'closed', label: 'Closed' },\n] as const\n\nexport interface OpenframeDevSection {\n /** Route href the navigator card and any internal cross-link composes. */\n href: string\n icon: LucideIcon\n /** Brief copy for the homepage navigator card (≈50 char teaser). */\n navigator: {\n title: string\n description: string\n }\n /** Longer copy for the destination page hero (≈120-150 char marketing paragraph). */\n hero: {\n title: string\n description: string\n }\n /** Inline search bar configuration. */\n search: {\n /** Placeholder text shown in the search input. */\n placeholder: string\n /** URL search param the input writes on submit and the list reads on fetch. */\n paramKey: string\n } | null\n /** Filter pill row configuration. `null` when the section has no filter (e.g. onboarding-guides). */\n filter: {\n label: string\n /** URL search param the pills write and the list reads. */\n paramKey: string\n /** The option value that maps to \"no filter applied\". When selected,\n * the URL param is removed instead of being set. Defaults to the\n * first option's value if omitted — explicit field guards against\n * brittleness if `options` is later reordered. */\n defaultValue: string\n options: readonly { value: string; label: string }[]\n } | null\n}\n\nexport const OPENFRAME_DEV_SECTIONS = {\n roadmap: {\n href: '/roadmap',\n icon: MapIcon,\n navigator: {\n title: 'Development Roadmap',\n description: \"What we're building next — vote on upcoming features.\",\n },\n hero: {\n title: 'Development Roadmap',\n description:\n \"See what's in flight, what's planned, and what's up for community vote. The entire OpenFrame roadmap is public.\",\n },\n search: { placeholder: 'Search roadmap items...', paramKey: 'search' },\n filter: { label: 'Status', paramKey: 'status', defaultValue: 'all', options: ROADMAP_STATUS_OPTIONS },\n },\n delivery: {\n href: '/bug-fixes-and-enhancements',\n icon: Wrench,\n navigator: {\n title: 'Bug-fixes & Enhancements',\n description: 'Recently shipped fixes and improvements.',\n },\n hero: {\n title: 'Bug-fixes & Enhancements',\n description:\n 'A running log of fixes and improvements shipping into OpenFrame — recently completed and actively in progress.',\n },\n search: { placeholder: 'Search tasks...', paramKey: 'search' },\n filter: { label: 'Type', paramKey: 'task_type', defaultValue: 'all', options: DELIVERY_TASK_TYPE_OPTIONS },\n },\n releases: {\n href: '/releases',\n icon: Rocket,\n navigator: {\n title: 'Product Releases',\n description: 'Version history and release notes.',\n },\n hero: {\n title: 'Product Releases',\n description:\n 'Version notes, change summaries, and stability tier (alpha / beta / stable) for every OpenFrame release.',\n },\n search: { placeholder: 'Search releases...', paramKey: 'search' },\n filter: { label: 'Status', paramKey: 'release_status', defaultValue: 'all', options: releaseStatusOptions },\n },\n onboarding: {\n href: '/onboarding-guides',\n icon: GraduationCap,\n navigator: {\n title: 'Onboarding Guides',\n description: 'Step-by-step product walkthroughs.',\n },\n // `hero` / `search` / `filter` are intentionally inert here —\n // /onboarding-guides is owned by OnboardingGuidesCatalogView, not\n // DevSectionView. This entry exists ONLY to drive the homepage\n // navigator card so all 4 cards stay in one registry.\n hero: { title: '', description: '' },\n search: null,\n filter: null,\n },\n tickets: {\n href: '/tickets',\n icon: LifeBuoy,\n navigator: {\n title: 'Help Center',\n description: 'Open and manage your support tickets.',\n },\n hero: {\n title: 'Help Center',\n description:\n 'Open new tickets, follow up on existing ones, and track responses from the team — all in one place.',\n },\n search: { placeholder: 'Search your tickets...', paramKey: 'search' },\n filter: {\n label: 'Status',\n paramKey: 'status',\n defaultValue: 'all',\n options: TICKET_STATUS_OPTIONS,\n },\n },\n} as const satisfies Record<string, OpenframeDevSection>\n\nexport type OpenframeDevSectionKey = keyof typeof OPENFRAME_DEV_SECTIONS\n","/**\n * `scrollElementIntoView` — canonical \"smooth scroll element to top\n * of viewport, account for sticky chrome, optionally adjust for\n * known layout shifts\" helper.\n *\n * Before this util existed, ~3 different call sites in the lib + hub\n * had the same 5-line snippet copy-pasted with subtle differences:\n *\n * - `useUnifiedNav` same-URL re-scroll branch (hub)\n * - `<HelpCenterCard>` click-to-expand (lib, with cross-row\n * layout-shift adjustment)\n * - Future ticket-row / docs anchor scrolls\n *\n * The canonical pattern is `window.scrollTo({top, behavior:'smooth'})`\n * with a pre-computed pixel target — NOT `element.scrollIntoView()`.\n * Pre-computing the target lets the browser run a clean uninterrupted\n * smooth animation to a fixed pixel value. `scrollIntoView` re-targets\n * continuously as the page layout shifts during the animation, which\n * causes visible jitter when content above the target is also moving\n * (a sibling collapsing, an async image loading, …).\n *\n * The `adjustTargetY` callback is the escape hatch for cases where\n * the consumer KNOWS about an upcoming layout shift and can compute\n * the correct FINAL target before the animation starts. Example: in\n * `HelpCenterCard`, clicking row B while row A above is currently\n * expanded — A's drawer collapses simultaneously with B's expansion,\n * shifting B's tile up by A's drawer height. The consumer passes\n * `adjustTargetY: raw => raw - getAboveDrawerHeight()` and the\n * browser smooth-scrolls to the post-collapse position directly.\n */\n\nexport interface ScrollElementIntoViewOptions {\n /** Pixels to subtract from the target element's `top` so it lands\n * BELOW sticky chrome. Defaults to 0. Pass `96` (matches\n * `scroll-mt-24`) for the standard hub header offset. */\n headerOffset?: number\n /** Scroll animation style. Defaults to `'smooth'`. Use `'instant'`\n * for imperative jumps where animation would feel laggy (deep\n * link land, programmatic focus moves). */\n behavior?: ScrollBehavior\n /** Optional adjustment applied to the computed pixel target. The\n * callback receives the \"raw\" Y (`element.top + scrollY -\n * headerOffset`) and returns the FINAL pixel target. Use this\n * when the caller knows about a layout shift that will happen\n * between the call and the animation completing — the browser's\n * smooth-scroll commits to a single pixel value, so providing the\n * post-shift target up front lands the element correctly even as\n * content above it moves. */\n adjustTargetY?: (rawTargetY: number) => number\n}\n\n/**\n * Scroll the page so `target` lands at the top of the viewport,\n * accounting for sticky chrome via `headerOffset`. Returns void; the\n * scroll runs async via the browser's smooth-scroll engine.\n *\n * Accepts:\n * - `HTMLElement` — direct reference (most common from `useRef`).\n * - `null` / `undefined` — no-op so callers can pass refs without\n * defensive branching.\n *\n * SSR-safe: short-circuits when `window` is undefined.\n */\nexport function scrollElementIntoView(\n target: HTMLElement | null | undefined,\n options: ScrollElementIntoViewOptions = {},\n): void {\n if (typeof window === 'undefined' || !target) return\n const { headerOffset = 0, behavior = 'smooth', adjustTargetY } = options\n const rawTargetY =\n target.getBoundingClientRect().top + window.scrollY - headerOffset\n const finalY = adjustTargetY ? adjustTargetY(rawTargetY) : rawTargetY\n window.scrollTo({ top: Math.max(0, finalY), behavior })\n}\n"]}
1
+ {"version":3,"sources":["../../src/utils/cn.ts","../../src/utils/format.ts","../../src/components/icons-v2-generated/media-playback/play-icon.tsx","../../src/utils/ods-color-utils.ts","../../src/utils/common.ts","../../src/components/icons/openmsp-logo.tsx","../../src/components/icons/openframe-logo.tsx","../../src/components/icons/flamingo-logo.tsx","../../src/components/icons/miami-cyber-gang-logo-face-only.tsx","../../src/components/icons/shell-icon.tsx","../../src/components/icons/github-icon.tsx","../../src/components/icons/slack-icon.tsx","../../src/components/icons/clickup-icon.tsx","../../src/components/icons/x-logo.tsx","../../src/components/icons/hubspot-icon.tsx","../../src/components/icons/linkedin-icon.tsx","../../src/components/icons/youtube-icon.tsx","../../src/components/icons/instagram-icon.tsx","../../src/components/icons/facebook-icon.tsx","../../src/components/icons/windows-icon.tsx","../../src/components/icons/macos-icon.tsx","../../src/components/icons/linux-icon.tsx","../../src/components/icons/cmd-icon.tsx","../../src/components/icons/bash-icon.tsx","../../src/components/icons/nushell-icon.tsx","../../src/components/icons/deno-icon.tsx","../../src/utils/platform-config.tsx","../../src/utils/os-platforms.ts","../../src/utils/access-code-client.ts","../../src/utils/validation-utils.ts","../../src/utils/confidence-helpers.ts","../../src/utils/date-formatters.ts","../../src/components/chat/utils/icon-registry.ts","../../src/types/tool.types.ts","../../src/utils/tool-utils.ts","../../src/components/icons-v2-generated/brand-logos/powershell-logo-icon.tsx","../../src/components/icons-v2-generated/brand-logos/python-logo-icon.tsx","../../src/types/shell.types.ts","../../src/utils/shell-utils.ts","../../src/components/icons-v2-generated/brand-logos/apple-logo-icon.tsx","../../src/components/icons-v2-generated/brand-logos/linux-logo-icon.tsx","../../src/components/icons-v2-generated/brand-logos/windows-logo-grey-icon.tsx","../../src/types/os.types.ts","../../src/utils/os-utils.ts","../../src/utils/country-phone-utils.ts","../../src/utils/generic-domain-utils.ts","../../src/utils/color-analysis.ts","../../src/utils/image-proxy.ts","../../src/utils/date-utils.ts","../../src/utils/source-icons.ts","../../src/utils/local-storage-adapter.ts","../../src/utils/app-config.ts","../../src/utils/embed-proxy-auth-storage.ts","../../src/utils/embed-authed-fetch.ts","../../src/utils/sse-decision-frame.ts","../../src/components/chat/utils/chat-attachment-markdown.ts","../../src/components/chat/utils/auto-continuation-directive.ts","../../src/components/chat/utils/flatten-assistant-content.ts","../../src/components/chat/types/message.types.ts","../../src/components/chat/utils/scroll-anchor.ts","../../src/components/chat/utils/slash-dispatch-utils.ts","../../src/components/chat/utils/clickup-task-type-utils.ts","../../src/components/chat/utils/agent-status-message.ts","../../src/components/chat/utils/external-app-urls.ts","../../src/components/chat/utils/is-cross-origin-url.ts","../../src/utils/fetch-priority.ts","../../src/types/product-release.ts","../../src/utils/dev-sections/openframe-dev-sections.ts"],"names":["platformColors","jsx","jsxs","Globe","Bell","Info","Megaphone","Package","Rocket","Star","b","React","MapIcon","GraduationCap"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { extendTailwindMerge } from \"tailwind-merge\"\n\nconst twMerge = extendTailwindMerge<'ods-typography'>({\n extend: {\n classGroups: {\n 'ods-typography': ['text-h1', 'text-h2', 'text-h3', 'text-h4', 'text-h5', 'text-h6'],\n },\n },\n})\n\n/**\n * Combine class names with Tailwind's merge utility\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n/**\n * Platform URL mappings for production (with environment variable overrides)\n */\nexport function getPlatformProductionUrl(platform: string): string {\n switch (platform) {\n // *-hub platforms — env var convention: NEXT_PUBLIC_<NAME>_HUB_URL\n case 'marketing-hub':\n return process.env.NEXT_PUBLIC_MARKETING_HUB_URL || 'https://marketing-hub.flamingo.so';\n case 'company-hub':\n return process.env.NEXT_PUBLIC_COMPANY_HUB_URL || 'https://company-hub.flamingo.so';\n case 'product-hub':\n return process.env.NEXT_PUBLIC_PRODUCT_HUB_URL || 'https://product-hub.flamingo.so';\n case 'revenue-hub':\n return process.env.NEXT_PUBLIC_REVENUE_HUB_URL || 'https://revenue-hub.flamingo.so';\n case 'people-hub':\n return process.env.NEXT_PUBLIC_PEOPLE_HUB_URL || 'https://people-hub.flamingo.so';\n // Standalone platforms — env var convention: NEXT_PUBLIC_<NAME>_URL\n case 'openmsp':\n return process.env.NEXT_PUBLIC_OPENMSP_URL || 'https://www.openmsp.ai';\n case 'flamingo':\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n case 'tmcg':\n return process.env.NEXT_PUBLIC_TMCG_URL || 'https://www.tmcg.miami';\n case 'flamingo-teaser':\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n case 'openframe':\n return process.env.NEXT_PUBLIC_OPENFRAME_URL || 'https://openframe.ai';\n case 'universal':\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n default:\n return process.env.NEXT_PUBLIC_FLAMINGO_URL || 'https://www.flamingo.run';\n }\n}\n\n/**\n * Get ALL unique base domains from getPlatformProductionUrl\n *\n * Extracts domains by calling getPlatformProductionUrl for each platform identifier.\n * Platform identifiers match the switch cases in getPlatformProductionUrl.\n *\n * Handles 3 cases:\n * 1. LOCALHOST DEBUG - No domain (hostname-specific cookies)\n * 2. VERCEL PREVIEW (*.vercel.app) - Use vercel.app domain\n * 3. PRODUCTION - Extract from ALL platform URLs via getPlatformProductionUrl\n *\n * @returns Array of all unique base domains (with and without wildcard)\n */\nexport function getAllPlatformBaseDomains(): string[] {\n if (typeof window === 'undefined') return []\n\n const hostname = window.location.hostname\n\n // Case 1: LOCALHOST DEBUG - no domains needed\n if (hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n hostname.startsWith('127.')) {\n return []\n }\n\n // Case 2: VERCEL PREVIEW - use vercel.app domain\n const isVercelPreview = process.env.VERCEL_ENV === 'preview' ||\n process.env.NEXT_PUBLIC_VERCEL_ENV === 'preview' ||\n hostname.includes('.vercel.app')\n\n if (isVercelPreview) {\n return ['.vercel.app', 'vercel.app']\n }\n\n // Case 3: PRODUCTION - extract from ALL platforms using getPlatformProductionUrl\n // Platform identifiers MUST match switch cases in getPlatformProductionUrl —\n // otherwise the corresponding domain is omitted from cookie scope.\n const platformIdentifiers = [\n 'marketing-hub', 'company-hub', 'product-hub', 'revenue-hub', 'people-hub',\n 'openmsp', 'flamingo', 'tmcg', 'flamingo-teaser', 'openframe', 'universal'\n ]\n\n const baseDomains = new Set<string>()\n\n platformIdentifiers.forEach(platform => {\n try {\n const url = getPlatformProductionUrl(platform)\n const urlHostname = new URL(url).hostname\n const parts = urlHostname.split('.')\n\n if (parts.length >= 2) {\n const baseDomain = parts.slice(-2).join('.')\n baseDomains.add(`.${baseDomain}`) // Wildcard\n baseDomains.add(baseDomain) // Non-wildcard\n }\n } catch (error) {\n console.warn('[Platform Domains] Failed to parse URL for platform:', platform, error)\n }\n })\n\n return Array.from(baseDomains)\n}\n\n/**\n * Get the application base URL for the current environment\n *\n * @param platform - Optional platform name (openmsp, flamingo, tmcg, openframe, etc.)\n * @returns The base URL with protocol (https:// or http://)\n *\n * Priority order:\n * 1. Environment variable override (NEXT_PUBLIC_*_URL)\n * 2. Platform-specific URL (if platform parameter provided)\n * 3. VERCEL_PROJECT_PRODUCTION_URL (Vercel production domain)\n * 4. Production fallback (current app or openmsp)\n * 5. Development (http://localhost:3000)\n *\n * Environment Variables (optional overrides — only set when production domain\n * differs from the hardcoded default):\n *\n * Hub deployments (NEXT_PUBLIC_<NAME>_HUB_URL):\n * - NEXT_PUBLIC_MARKETING_HUB_URL -> marketing-hub.flamingo.so\n * - NEXT_PUBLIC_COMPANY_HUB_URL -> company-hub.flamingo.so\n * - NEXT_PUBLIC_PRODUCT_HUB_URL -> product-hub.flamingo.so\n * - NEXT_PUBLIC_REVENUE_HUB_URL -> revenue-hub.flamingo.so\n * - NEXT_PUBLIC_PEOPLE_HUB_URL -> people-hub.flamingo.so\n *\n * Standalone platforms (NEXT_PUBLIC_<NAME>_URL):\n * - NEXT_PUBLIC_OPENMSP_URL -> www.openmsp.ai\n * - NEXT_PUBLIC_FLAMINGO_URL -> www.flamingo.run\n * - NEXT_PUBLIC_TMCG_URL -> www.tmcg.miami\n * - NEXT_PUBLIC_FLAMINGO_TEASER_URL -> www.flamingo.cx\n * - NEXT_PUBLIC_OPENFRAME_URL -> openframe.ai\n *\n * @example\n * getBaseUrl() // Current app URL\n * getBaseUrl('flamingo') // https://www.flamingo.run (production) or http://localhost:3000 (dev)\n * getBaseUrl('openmsp') // https://www.openmsp.ai (or NEXT_PUBLIC_OPENMSP_URL if set)\n */\nexport function getBaseUrl(platform?: string): string {\n // In development, always use localhost (regardless of platform)\n if (process.env.NODE_ENV !== 'production') {\n return process.env.NEXT_PUBLIC_DEV_URL || 'http://localhost:3000'\n }\n\n // If platform is specified, return its production URL with env variable override support\n if (platform) {\n return getPlatformProductionUrl(platform)\n }\n\n // Production: Use Vercel domain if available\n if (process.env.VERCEL_PROJECT_PRODUCTION_URL) {\n return `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`\n }\n\n // Production fallback: Use canonical www domain to avoid Google \"Page with redirect\" issue.\n // openmsp.ai redirects to www.openmsp.ai, so we set the base URL to the\n // final destination to ensure canonical URLs do not require a redirect.\n return 'https://www.openmsp.ai'\n}\n","/**\n * Utility functions for formatting data\n */\n\n/**\n * Format a date to a human-readable string\n * @param date - The date to format (Date object or ISO string)\n * @param options - Formatting options\n * @returns Formatted date string\n */\nexport function formatDate(\n date: Date | string,\n options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n },\n): string {\n const dateObj = typeof date === \"string\" ? new Date(date) : date\n \n // Check if the date is valid\n if (isNaN(dateObj.getTime())) {\n console.warn(\"Invalid date provided to formatDate:\", date)\n return \"Invalid Date\"\n }\n \n return dateObj.toLocaleDateString(\"en-US\", options)\n}\n\n/**\n * Format a number with thousands separators\n * @param num - The number to format\n * @returns Formatted number string\n */\nexport function formatNumber(num: number): string {\n return num.toLocaleString()\n}\n\n/**\n * Format a price with currency symbol\n * @param price - The price to format\n * @param currency - The currency code\n * @returns Formatted price string\n */\nexport function formatPrice(price: number, currency = \"USD\"): string {\n return new Intl.NumberFormat(\"en-US\", {\n style: \"currency\",\n currency,\n }).format(price)\n}\n\n/**\n * Format bytes to a human-readable string (KB, MB, GB, etc.)\n * @param bytes - The number of bytes\n * @param decimals - Number of decimal places\n * @returns Formatted bytes string\n */\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) return \"0 Bytes\"\n\n const k = 1024\n const dm = decimals < 0 ? 0 : decimals\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"]\n\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n\n return Number.parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + \" \" + sizes[i]\n}\n\n/**\n * Compact bytes formatter using the single-letter unit `'B'` (not\n * `'Bytes'`). Used by upload-progress UIs where horizontal space is\n * tight and the longer \"Bytes\" string wraps. Tops out at `TB`.\n * @example formatBytesShort(0) → \"0 B\"; formatBytesShort(1536) → \"1.5 KB\"\n */\nexport function formatBytesShort(bytes: number): string {\n if (bytes === 0) return '0 B'\n const k = 1024\n const sizes = ['B', 'KB', 'MB', 'GB', 'TB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`\n}\n\n/**\n * Format large numbers to abbreviated form (K, M, B) with no decimal points\n * @param num - The number to format\n * @returns Formatted number string (e.g., \"1K\", \"2M\", \"3B\")\n */\nexport function formatLargeNumber(num: number): string {\n if (num === 0) return \"0\"\n \n // Handle negative numbers\n const isNegative = num < 0\n const absNum = Math.abs(num)\n \n let result: string\n \n if (absNum >= 1_000_000_000) {\n // Billions\n result = `${Math.floor(absNum / 1_000_000_000)}B`\n } else if (absNum >= 1_000_000) {\n // Millions\n result = `${Math.floor(absNum / 1_000_000)}M`\n } else if (absNum >= 1_000) {\n // Thousands\n result = `${Math.floor(absNum / 1_000)}K`\n } else {\n // Less than 1000, show as-is\n result = Math.floor(absNum).toString()\n }\n \n return isNegative ? `-${result}` : result\n}\n\n/**\n * Abbreviate large numbers for compact display.\n * 1 200 → 1.2K , 15 000 → 15K , 2 000 000 → 2M\n * @param n Number to format\n */\nexport function formatAbbreviatedNumber(n: number): string {\n if (n >= 1_000_000_000) {\n const value = n / 1_000_000_000;\n return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}B`;\n }\n if (n >= 1_000_000) {\n const value = n / 1_000_000;\n return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}M`;\n }\n if (n >= 1_000) {\n const value = n / 1_000;\n return `${Number.isInteger(value) ? value.toFixed(0) : value.toFixed(1)}K`;\n }\n return n.toLocaleString();\n}\n\n/**\n * Two-letter uppercase initials from the FIRST + LAST word of a name.\n * Used by avatar-style fallbacks (SquareAvatar, EntityImage) where\n * \"John Michael Doe\" → \"JD\" reads better than \"JM\".\n *\n * Returns `''` for empty / whitespace-only input. Single-word names\n * return a single uppercase letter. Pure — same input always produces\n * the same output, no locale or timezone surface.\n */\nexport function getFirstLastInitials(name?: string | null): string {\n if (!name) return ''\n const words = name.trim().split(/\\s+/)\n if (words.length === 0 || !words[0]) return ''\n if (words.length === 1) return words[0].charAt(0).toUpperCase()\n return (words[0].charAt(0) + words[words.length - 1].charAt(0)).toUpperCase()\n}\n\n/**\n * Two-letter uppercase initials from the FIRST + SECOND word of a name.\n * Used as SquareAvatar / EntityImage / EntityAuthorCard fallback across\n * admin and public pages in both the lib and the hub. Handles empty\n * strings, all-whitespace input, and single-word names cleanly — always\n * returns at least one character so the fallback slot is never empty.\n *\n * Single source of truth: every \"first-letter of each word, uppercase,\n * max 2 chars\" computation across hub + lib MUST come through here.\n */\nexport function nameInitials(\n name: string | null | undefined,\n fallback: string = 'E',\n): string {\n const source = typeof name === 'string' ? name.trim() : ''\n const words = source.length > 0 ? source.split(/\\s+/) : []\n const letters = words\n .map((w) => w[0])\n .filter(Boolean)\n .slice(0, 2)\n .join('')\n return (letters || fallback).toUpperCase()\n}\n\n/**\n * Format seconds to MM:SS or HH:MM:SS format\n * Used for media durations (podcasts, videos)\n * Returns: \"MM:SS\" or \"HH:MM:SS\" if hours > 0\n */\nexport function formatDurationMMSS(seconds: number | null | undefined): string {\n if (!seconds) return '';\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const secs = Math.floor(seconds % 60);\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }\n return `${minutes}:${secs.toString().padStart(2, '0')}`;\n}\n\n/**\n * Format seconds to compact human-readable duration\n * Used for displaying duration in cards and headers\n * Returns: \"Xh Xm\" or \"X min\"\n */\nexport function formatDurationCompact(seconds: number | null | undefined): string {\n if (!seconds) return '';\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n if (hours > 0) {\n return `${hours}h ${minutes}m`;\n }\n return `${minutes} min`;\n}\n\n/**\n * Format time with optional timezone\n * Used for webinar and event times\n * Returns: \"10:30 AM EST\" or \"10:30 AM\"\n */\nexport function formatTimeWithTimezone(\n date: Date | string | null | undefined,\n timezone?: string | null\n): string {\n if (!date) return '';\n\n const dateObj = typeof date === 'string' ? new Date(date) : date;\n const timeStr = dateObj.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n });\n\n return timezone ? `${timeStr} ${timezone}` : timeStr;\n}\n\n/**\n * Calculate and format duration between two timestamps\n * Used for webinar durations\n * Returns: \"1h 30m\" or \"45m\"\n */\nexport function formatDurationFromRange(\n startAt: string | Date | null | undefined,\n endAt: string | Date | null | undefined\n): string {\n if (!startAt || !endAt) return '';\n\n const start = typeof startAt === 'string' ? new Date(startAt) : startAt;\n const end = typeof endAt === 'string' ? new Date(endAt) : endAt;\n const durationMs = end.getTime() - start.getTime();\n const minutes = Math.round(durationMs / 60000);\n\n if (minutes >= 60) {\n const hours = Math.floor(minutes / 60);\n const mins = minutes % 60;\n return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;\n }\n return `${minutes}m`;\n}\n\n/**\n * UTC-anchored date formatter — distinct from the local-rendering\n * `formatDate` above. RAG mappers + audit-style consumers want UTC anchor\n * so date-only strings (`'2024-08-15'`) don't drift across timezones, AND\n * a `'N/A'` (or caller-supplied) fallback for missing values so the LLM\n * never sees a blank.\n *\n * Accepts:\n * - ISO date or timestamp string (`'2024-08-15'` or `'2024-08-15T10:30:00Z'`)\n * - Numeric epoch milliseconds\n * - Numeric string (treated as epoch ms — Slack and GitHub timestamps\n * sometimes arrive that way)\n * - `null` / `undefined` / empty / unparseable → returns `options.fallback`\n *\n * Date-only strings (no `'T'`) get `T00:00:00Z` appended so they anchor to\n * UTC midnight rather than midnight in the runtime's local timezone.\n */\nexport interface FormatDateUTCOptions {\n /** Returned for null/undefined/empty/unparseable input. Defaults to 'N/A'. */\n fallback?: string\n /** 'UTC' (default) or 'local' — switch off the UTC anchor when audit\n * stability matters less than local relevance (chat-card timestamps). */\n timezone?: 'UTC' | 'local'\n}\n\nexport function formatDateUTC(\n value: string | number | null | undefined,\n options: FormatDateUTCOptions = {},\n): string {\n const { fallback = 'N/A', timezone = 'UTC' } = options\n\n if (value === null || value === undefined || value === '') return fallback\n\n let ms: number\n if (typeof value === 'number') {\n ms = value\n } else {\n // String input — first try to interpret as a numeric epoch (Slack/GitHub\n // sometimes arrive that way). Number('') is 0, but we already ruled out\n // empty strings above.\n const n = Number(value)\n if (Number.isFinite(n) && n > 0 && /^-?\\d+(\\.\\d+)?$/.test(value.trim())) {\n ms = n\n } else {\n // ISO string — for date-only forms, anchor to UTC midnight to avoid\n // timezone-offset drift (preserves the original RAG-mapper contract).\n ms = Date.parse(value.includes('T') ? value : value + 'T00:00:00Z')\n }\n }\n\n if (!Number.isFinite(ms)) return fallback\n\n return new Date(ms).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n timeZone: timezone === 'local' ? undefined : 'UTC',\n })\n}\n\n/**\n * Format a date string as `MM/DD/YYYY` for legal-document display\n * (privacy policy, terms of service). Locale-stable: always en-US.\n */\nexport function formatLegalDate(dateInput: string): string {\n return new Intl.DateTimeFormat('en-US', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n }).format(new Date(dateInput))\n}\n\n/**\n * Format a currency value as `$1,234`. Returns `'N/A'` for null/undefined.\n * USD-rounded (no cents). Used on KPI cards + investor pages.\n */\nexport function formatCurrency(value: number | null | undefined): string {\n if (value == null) return 'N/A'\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: 'USD',\n maximumFractionDigits: 0,\n }).format(value)\n}\n\n/**\n * Format a percent value as `12.50%`. Returns `'N/A'` for null/undefined.\n */\nexport function formatPercent(value: number | null | undefined): string {\n if (value == null) return 'N/A'\n return `${value.toFixed(2)}%`\n}\n\n/**\n * Whole-dollar price (no cents) — `$1,234`. Configurable currency code.\n */\nexport function formatWholeDollars(price: number, currency = 'USD'): string {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n maximumFractionDigits: 0,\n }).format(price)\n}\n\n// =============================================================================\n// Metric Formatting (for KPI cards / investor updates)\n// =============================================================================\n\nexport type MetricFormat = 'number' | 'currency' | 'percentage' | 'months'\n\n/**\n * Polarity determines whether an increase is good or bad.\n * - 'positive': higher is better (revenue, users, MRR) → up = green, down = red\n * - 'negative': higher is worse (burn rate, churn, CAC) → up = red, down = green\n * - 'neutral': no judgment (headcount, runway) → always gray\n */\nexport type TrendPolarity = 'positive' | 'negative' | 'neutral'\n\n/**\n * Format a metric value with compact notation ($1.2M, 150K, 12 months).\n */\nexport function formatCompactMetric(\n value: number,\n format: MetricFormat = 'number',\n options?: { prefix?: string; suffix?: string },\n): string {\n if (value === 0 || value === null || value === undefined) {\n if (format === 'currency') return `${options?.prefix || '$'}0`\n if (format === 'percentage') return '0%'\n if (format === 'months') return `0 ${options?.suffix || 'months'}`\n return '0'\n }\n\n const absValue = Math.abs(value)\n const sign = value < 0 ? '-' : ''\n\n if (format === 'currency') {\n const prefix = options?.prefix || '$'\n const compact = (val: number, divisor: number, suffix: string) => {\n const divided = val / divisor\n const formatted = divided % 1 === 0 ? divided.toFixed(0) : divided.toFixed(1)\n return `${sign}${prefix}${formatted}${suffix}`\n }\n if (absValue >= 1_000_000_000) return compact(absValue, 1_000_000_000, 'B')\n if (absValue >= 1_000_000) return compact(absValue, 1_000_000, 'M')\n if (absValue >= 1_000) return `${sign}${prefix}${(absValue / 1_000).toFixed(0)}K`\n return `${sign}${prefix}${absValue.toLocaleString()}`\n }\n\n if (format === 'percentage') {\n return `${sign}${absValue}%`\n }\n\n if (format === 'months') {\n const rounded = Math.round(value * 10) / 10\n return `${rounded} ${options?.suffix || 'months'}`\n }\n\n if (absValue >= 1_000_000) return `${sign}${(absValue / 1_000_000).toFixed(1)}M`\n if (absValue >= 1_000) return `${sign}${(absValue / 1_000).toFixed(1)}K`\n return value.toLocaleString()\n}\n\n/**\n * Get ODS trend colors based on direction AND polarity. Single source\n * of truth for trend coloring across hub + lib.\n */\nexport function getTrendColors(\n direction: 'up' | 'down' | 'neutral',\n polarity: TrendPolarity = 'positive',\n): { textClass: string; badgeClass: string } {\n if (direction === 'neutral' || polarity === 'neutral') {\n return {\n textClass: 'text-ods-text-secondary',\n badgeClass: 'bg-ods-border text-ods-text-secondary',\n }\n }\n\n const isPositiveOutcome =\n (direction === 'up' && polarity === 'positive') ||\n (direction === 'down' && polarity === 'negative')\n\n if (isPositiveOutcome) {\n return {\n textClass: 'text-ods-success',\n badgeClass: 'bg-ods-success-secondary text-ods-success',\n }\n }\n\n return {\n textClass: 'text-ods-error',\n badgeClass: 'bg-ods-error-secondary text-ods-error',\n }\n}\n\n/**\n * Format a date range as `Apr 20, 2026 — Jul 20, 2026`. Used on review\n * cycle list/detail rows and summary headers.\n *\n * Accepts either full ISO timestamps or bare `YYYY-MM-DD` dates. Bare\n * dates are interpreted in the viewer's LOCAL timezone — otherwise\n * `\"2026-04-20\"` renders as `\"Apr 19\"` west of UTC. DB values for cycle\n * period are stored as plain dates, so local-tz parsing is correct.\n */\nexport function formatDateRange(\n start: string | null | undefined,\n end: string | null | undefined,\n): string {\n if (!start || !end) return ''\n const fmt = (s: string): string => {\n const bareMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(s)\n const d = bareMatch\n ? new Date(Number(bareMatch[1]), Number(bareMatch[2]) - 1, Number(bareMatch[3]))\n : new Date(s)\n if (Number.isNaN(d.getTime())) return s\n return d.toLocaleDateString(undefined, {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })\n }\n return `${fmt(start)} — ${fmt(end)}`\n}\n\n/**\n * Format an ISO date string as `\"Jan 5, 2025 at 10:30 AM\"`. Used by\n * admin podcast/webinar cards where the display needs both the short\n * date AND wall-clock time in a single readable phrase.\n *\n * Uses `new Date(...).toLocale*` (NOT the TZ-safe split) because the\n * source columns store full timestamps + the wall-clock half MUST\n * render in the viewer's local timezone (a podcast scheduled \"10:30 AM\n * EST\" should display \"10:30 AM\" for the Eastern admin, \"7:30 AM\" for\n * the Pacific admin — viewer-local is the right semantics here, unlike\n * date-only fields).\n */\nexport function formatDateTimeAt(dateString: string): string {\n const date = new Date(dateString)\n const dateStr = date.toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n })\n const timeStr = date.toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n })\n return `${dateStr} at ${timeStr}`\n}\n\n/**\n * Format a duration measured in MILLISECONDS as a compact human-readable\n * string. Returns `\"0ms\"` for null/NaN/negative, then `Xms` → `X.Xs` →\n * `X.Xm` as the input grows. Used by job-runs / orchestrator dashboards\n * where elapsed milliseconds is the natural unit.\n *\n * Distinct from `formatDuration(seconds)` (verbose `\"X hours Y minutes\"`)\n * and `formatDurationMMSS(seconds)` (media timecode `MM:SS`).\n */\nexport function formatDurationFromMs(ms: number | null | undefined): string {\n if (!ms || isNaN(ms) || ms < 0) return '0ms'\n if (ms < 1000) return `${ms}ms`\n if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`\n return `${(ms / 60000).toFixed(1)}m`\n}\n\n/**\n * Format seconds to verbose human-readable duration: `\"X seconds\"`,\n * `\"X minutes\"`, `\"X hours Y minutes\"`. Use this for human-readable\n * spans; for media timecodes use `formatDurationMMSS`; for compact\n * media labels use `formatDurationCompact`; for elapsed milliseconds\n * use `formatDurationFromMs`.\n */\nexport function formatDuration(seconds: number): string {\n if (seconds < 60) return `${seconds} seconds`\n if (seconds < 3600) return `${Math.floor(seconds / 60)} minutes`\n\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n\n if (minutes === 0) return `${hours} hour${hours > 1 ? 's' : ''}`\n return `${hours} hour${hours > 1 ? 's' : ''} ${minutes} minute${minutes > 1 ? 's' : ''}`\n}\n\n// =============================================================================\n// Text formatting helpers (proper-case, HTML strip, bio cleanup)\n// =============================================================================\n\n/**\n * Format underscore-separated text into proper case.\n * `\"self_hosted\"` → `\"Self Hosted\"`\n * `\"open_source\"` → `\"Open Source\"`\n */\nexport function formatUnderscoreText(text: string): string {\n return text\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ')\n}\n\n/**\n * Strip HTML tags and decode common HTML entities from a string.\n * Useful for cleaning API responses that contain HTML content.\n *\n * @example\n * stripHtml('<p>Hello <strong>World</strong></p>') // \"Hello World\"\n * stripHtml('Test &amp; Example') // \"Test & Example\"\n */\nexport function stripHtml(html: string): string {\n // Iterative tag-strip — a single pass is bypass-able by inputs like\n // `<scr<script>ipt>`: stripping the inner `<script>` leaves the outer\n // `<script>` reassembled. Loop until the string is stable so multi-\n // character bypasses cannot survive (CodeQL\n // `js/incomplete-multi-character-sanitization`). `<[^<>]*>` rejects\n // `<` inside the tag body so each pass is itself ReDoS-safe (no\n // backtracking on `<<<<<...<>` inputs).\n let noTags = html\n let prev: string\n do {\n prev = noTags\n noTags = noTags.replace(/<[^<>]*>/g, '')\n } while (noTags !== prev)\n\n // Decode entities. `&amp;` MUST come LAST so we don't double-decode\n // sequences like `&amp;lt;` (which should render as the LITERAL text\n // `&lt;`, not as `<`). All other named/numeric entities decode first;\n // only after those have been replaced do we collapse `&amp;` → `&`.\n return noTags\n .replace(/&nbsp;/g, ' ')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&quot;/g, '\"')\n .replace(/&#39;/g, \"'\")\n .replace(/&#x27;/g, \"'\")\n .replace(/&apos;/g, \"'\")\n .replace(/&amp;/g, '&')\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/**\n * Display label for the openmsp `vendors.classification` enum.\n * Falls back to proper-cased underscore split for values not in the\n * curated mapping.\n */\nexport function formatClassification(classification: string): string {\n const customMappings: Record<string, string> = {\n openframe_selected: 'OpenFrame Selected',\n }\n return customMappings[classification] || formatUnderscoreText(classification)\n}\n\n/**\n * Display label for the openmsp `vendors.pricing_model` enum.\n * Falls back to proper-cased underscore split for values not in the\n * curated mapping.\n */\nexport function formatPricingModel(pricingModel: string): string {\n const customMappings: Record<string, string> = {\n one_time: 'One-time Purchase',\n self_hosted: 'Self-hosted',\n }\n return customMappings[pricingModel] || formatUnderscoreText(pricingModel)\n}\n\n/**\n * Format a bio/about text from the profiles table for display.\n * Handles HTML content (e.g. `<p>` tags from rich text editors),\n * plain text passthrough, and null/undefined values.\n */\nexport function formatBioText(\n aboutHtml: string | null | undefined,\n fallback: string = '',\n): string {\n if (!aboutHtml || !aboutHtml.trim()) return fallback\n\n if (aboutHtml.includes('<p')) {\n // `<p[^<>]*>` rejects `<` inside the tag so the automaton can't\n // backtrack on `<<<<<...<p>` inputs (ReDoS class fix vs. `<p[^>]*>`).\n const paragraphs = aboutHtml\n .split(/<p[^<>]*>/)\n .slice(1)\n .map((part) => part.split('</p>')[0])\n .map((text) => stripHtml(text).trim())\n .filter((text) => text.length > 0)\n\n if (paragraphs.length > 0) return paragraphs.join(' ')\n }\n\n return stripHtml(aboutHtml).trim() || fallback\n}\n","import type { SVGProps } from \"react\";\n\n/** SVG path data for the play icon — exported for reuse in server-side image generation */\nexport const PLAY_ICON_PATH = \"M4.875 5.006c0-2.501 2.793-3.989 4.87-2.592l9.78 6.578c2.135 1.437 2.135 4.58 0 6.016l-9.78 6.579c-2.077 1.396-4.87-.091-4.87-2.593zm2.25 13.988c0 .7.783 1.118 1.364.727l9.78-6.58c.81-.545.81-1.738 0-2.283L8.488 4.28a.875.875 0 0 0-1.364.726v13.988Z\";\n\nexport interface PlayIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function PlayIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: PlayIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d={PLAY_ICON_PATH}\n />\n </svg>\n );\n}\n","/**\n * ODS Color Token Utility Functions\n * \n * Provides runtime utilities for working with ODS color tokens\n */\n\nimport { colorTokens as odsTokens } from './ods-color-tokens-stub';\n\nexport type Platform = 'openmsp' | 'openframe' | 'flamingo';\nexport type ColorCategory = 'open' | 'flamingo' | 'system' | 'attention';\nexport type ColorVariant = 'base' | 'hover' | 'active' | 'focus' | 'disabled';\n\n/**\n * Gets the raw ODS token value for a specific color\n */\nexport function getODSToken(\n category: ColorCategory,\n color: string,\n variant: ColorVariant = 'base'\n): string | undefined {\n const tokenKey = `${category}-${color}-${variant}`;\n return (odsTokens as any)[tokenKey];\n}\n\n/**\n * Gets the current platform's accent color\n */\nexport function getPlatformAccentColor(platform?: Platform): string {\n const currentPlatform = platform || getCurrentPlatform();\n \n const platformColors = {\n 'openmsp': 'var(--ods-open-yellow-base)', // CSS variable instead of hex\n 'openframe': 'var(--ods-open-yellow-base)', // CSS variable instead of hex\n 'flamingo': 'var(--ods-flamingo-pink-base)' // CSS variable instead of hex\n };\n \n return platformColors[currentPlatform];\n}\n\n/**\n * Gets the current platform from environment or DOM\n */\nexport function getCurrentPlatform(): Platform {\n // Server-side: use environment variable\n if (typeof window === 'undefined') {\n return (process.env.NEXT_PUBLIC_APP_TYPE as Platform) || 'openmsp';\n }\n \n // Client-side: check DOM attribute first, fallback to environment\n const domPlatform = document.documentElement.getAttribute('data-app-type');\n if (domPlatform) {\n return domPlatform as Platform;\n }\n \n return (process.env.NEXT_PUBLIC_APP_TYPE as Platform) || 'openmsp';\n}\n\n/**\n * Switches the platform theme by updating CSS custom properties\n */\nexport function switchPlatformTheme(platform: Platform): void {\n if (typeof window === 'undefined') return;\n \n const root = document.documentElement;\n root.setAttribute('data-app-type', platform);\n \n // Note: Cannot modify process.env at runtime in production\n // This would only work in development/test environments\n \n // Dispatch custom event for components to react to platform changes\n window.dispatchEvent(new CustomEvent('platformThemeChanged', {\n detail: { platform }\n }));\n}\n\n/**\n * Gets a semantic color value for the current platform\n */\nexport function getSemanticColor(semanticName: string, platform?: Platform): string | undefined {\n if (typeof window === 'undefined') return undefined;\n \n const currentPlatform = platform || getCurrentPlatform();\n \n // Switch platform temporarily to get the color\n const originalPlatform = getCurrentPlatform();\n if (currentPlatform !== originalPlatform) {\n switchPlatformTheme(currentPlatform);\n }\n \n const testElement = document.createElement('div');\n document.body.appendChild(testElement);\n \n const computedStyle = getComputedStyle(testElement);\n const colorValue = computedStyle.getPropertyValue(`--color-${semanticName}`);\n \n document.body.removeChild(testElement);\n \n // Restore original platform\n if (currentPlatform !== originalPlatform) {\n switchPlatformTheme(originalPlatform);\n }\n \n return colorValue.trim() || undefined;\n}\n\n/**\n * Converts an ODS token to its corresponding Tailwind class\n */\nexport function tokenToTailwindClass(\n tokenKey: string,\n type: 'bg' | 'text' | 'border' = 'bg'\n): string | undefined {\n // Map common tokens to Tailwind classes\n const tokenMappings: Record<string, string> = {\n // Accent colors\n 'accent-primary': 'accent',\n 'accent-hover': 'accent-hover',\n 'accent-active': 'accent-active',\n \n // Background colors\n 'bg': 'bg',\n 'bg-card': 'card',\n 'bg-hover': 'bg-hover',\n 'bg-active': 'bg-active',\n \n // Text colors\n 'text-primary': 'text-primary',\n 'text-secondary': 'text-secondary',\n 'text-muted': 'text-muted',\n 'text-disabled': 'text-disabled',\n 'text-on-accent': 'text-on-accent',\n 'text-on-dark': 'text-on-dark',\n \n // Border colors\n 'border-default': 'border',\n 'border-hover': 'border-hover',\n 'border-focus': 'border-focus',\n \n // Status colors\n 'success': 'success',\n 'error': 'error',\n 'warning': 'warning',\n 'info': 'info'\n };\n \n const mappedToken = tokenMappings[tokenKey];\n if (!mappedToken) return undefined;\n \n return `${type}-ods-${mappedToken}`;\n}\n\n/**\n * Gets all available ODS tokens for a category\n */\nexport function getTokensByCategory(category: ColorCategory): Record<string, string> {\n const tokens: Record<string, string> = {};\n \n Object.entries(odsTokens).forEach(([key, value]) => {\n if (key.startsWith(`${category}-`)) {\n tokens[key] = value as string;\n }\n });\n \n return tokens;\n}\n\n/**\n * Validates if a color token exists in the ODS system\n */\nexport function isValidODSToken(tokenKey: string): boolean {\n return tokenKey in odsTokens;\n}\n\n/**\n * Gets the platform configuration for theming\n */\nexport function getPlatformConfig(platform?: Platform) {\n const currentPlatform = platform || getCurrentPlatform();\n \n return {\n platform: currentPlatform,\n accentColor: getPlatformAccentColor(currentPlatform),\n isDarkTheme: currentPlatform !== 'flamingo',\n isLightTheme: currentPlatform === 'flamingo',\n brandName: {\n 'openmsp': 'OpenMSP',\n 'openframe': 'OpenFrame',\n 'flamingo': 'Flamingo'\n }[currentPlatform]\n };\n}\n\n/**\n * Generates CSS custom property declarations for a platform\n */\nexport function generatePlatformCSS(platform: Platform): string {\n const accentColor = getPlatformAccentColor(platform);\n const tokens = getTokensByCategory('system');\n \n let css = `[data-app-type=\"${platform}\"] {\\n`;\n css += ` --color-accent-primary: ${accentColor};\\n`;\n \n // Add platform-specific overrides\n if (platform === 'flamingo') {\n css += ` --color-bg: var(--ods-system-greys-white);\\n`;\n css += ` --color-text-primary: var(--ods-system-greys-background);\\n`;\n }\n \n if (platform === 'openframe') {\n css += ` --color-bg: var(--ods-system-greys-darker);\\n`;\n }\n \n css += `}\\n`;\n \n return css;\n}\n\n/**\n * Applies a color token as a CSS custom property\n */\nexport function applyColorToken(\n element: HTMLElement,\n property: string,\n tokenKey: string\n): void {\n const tokenValue = (odsTokens as any)[tokenKey];\n if (tokenValue) {\n element.style.setProperty(`--${property}`, tokenValue);\n }\n}\n\n/**\n * Creates a color interpolation between two ODS tokens\n */\nexport function interpolateColors(\n startToken: string,\n endToken: string,\n progress: number\n): string {\n const startColor = (odsTokens as any)[startToken];\n const endColor = (odsTokens as any)[endToken];\n \n if (!startColor || !endColor) {\n return startColor || endColor || '#000000';\n }\n \n // Simple hex color interpolation\n const hexToRgb = (hex: string) => {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result ? {\n r: parseInt(result[1], 16),\n g: parseInt(result[2], 16),\n b: parseInt(result[3], 16)\n } : { r: 0, g: 0, b: 0 };\n };\n \n const rgbToHex = (r: number, g: number, b: number) => {\n return \"#\" + ((1 << 24) + (Math.round(r) << 16) + (Math.round(g) << 8) + Math.round(b)).toString(16).slice(1);\n };\n \n const start = hexToRgb(startColor);\n const end = hexToRgb(endColor);\n \n const interpolated = {\n r: start.r + (end.r - start.r) * progress,\n g: start.g + (end.g - start.g) * progress,\n b: start.b + (end.b - start.b) * progress\n };\n \n return rgbToHex(interpolated.r, interpolated.g, interpolated.b);\n}\n\n/**\n * Hook for React components to use platform-aware colors\n */\nexport function usePlatformColors(platform?: Platform) {\n const currentPlatform = platform || getCurrentPlatform();\n const config = getPlatformConfig(currentPlatform);\n \n return {\n platform: currentPlatform,\n accentColor: config.accentColor,\n isDarkTheme: config.isDarkTheme,\n isLightTheme: config.isLightTheme,\n brandName: config.brandName,\n getToken: (category: ColorCategory, color: string, variant?: ColorVariant) =>\n getODSToken(category, color, variant),\n switchTheme: (newPlatform: Platform) => switchPlatformTheme(newPlatform),\n getSemanticColor: (semanticName: string) => getSemanticColor(semanticName, currentPlatform)\n };\n}\n\n/**\n * Picks a near-black or near-white text color with adequate contrast on `hex`.\n * Uses Rec. 601 luminance.\n */\nexport function getReadableTextColor(hex: string): string {\n const n = parseInt(hex.replace('#', ''), 16)\n const r = (n >> 16) & 0xff\n const g = (n >> 8) & 0xff\n const b = n & 0xff\n const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255\n return luminance > 0.5 ? '#212121' : '#fafafa'\n}\n\nexport default {\n getODSToken,\n getPlatformAccentColor,\n getCurrentPlatform,\n switchPlatformTheme,\n getSemanticColor,\n tokenToTailwindClass,\n getTokensByCategory,\n isValidODSToken,\n getPlatformConfig,\n generatePlatformCSS,\n applyColorToken,\n interpolateColors,\n usePlatformColors\n};","import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\n/**\n * Utility functions for common operations\n */\n\n/**\n * Merge class names with Tailwind CSS\n * @param inputs - Class names to merge\n * @returns Merged class names\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n\n/**\n * Delay execution for a specified time\n * @param ms - Milliseconds to delay\n * @returns Promise that resolves after the delay\n */\nexport function delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Generate a random string of specified length\n * @param length - Length of the string\n * @returns Random string\n */\nexport function generateRandomString(length = 8): string {\n const chars = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"\n let result = \"\"\n for (let i = 0; i < length; i++) {\n result += chars.charAt(Math.floor(Math.random() * chars.length))\n }\n return result\n}\n\n/**\n * Truncate a string to a specified length\n * @param str - String to truncate\n * @param maxLength - Maximum length\n * @param suffix - Suffix to add to truncated string\n * @returns Truncated string\n */\nexport function truncateString(str: string, maxLength: number, suffix = \"...\"): string {\n if (str.length <= maxLength) return str\n return str.substring(0, maxLength - suffix.length) + suffix\n}\n\n/**\n * Deep clone an object\n * @param obj - Object to clone\n * @returns Cloned object\n */\nexport function deepClone<T>(obj: T): T {\n return JSON.parse(JSON.stringify(obj))\n}\n\n/**\n * Get the Slack community join URL from environment variables\n * @returns Slack community join URL or fallback URL\n */\nexport function getSlackCommunityJoinUrl(): string {\n const url = process.env.NEXT_PUBLIC_SLACK_COMMUNITY_JOIN_URL\n if (!url) {\n console.warn('NEXT_PUBLIC_SLACK_COMMUNITY_JOIN_URL is not defined in environment variables')\n return 'https://join.slack.com/t/openmsp/shared_invite/zt-36bl7mx0h-3~U2nFH6nqHqoTPXMaHEHA'\n }\n return url\n}\n\n","import React from 'react';\n\ninterface OpenmspLogoProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n frontBubbleColor?: string;\n innerFrontBubbleColor?: string;\n backBubbleColor?: string;\n color?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function OpenmspLogo({ className = '', frontBubbleColor = '#000000', innerFrontBubbleColor = '#ffffff', backBubbleColor = '#ffffff', ...props }: OpenmspLogoProps) {\n return (\n <svg\n width=\"97\"\n height=\"96\"\n viewBox=\"0 0 97 96\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path\n d=\"M73.933 0C75.7003 0 77.133 1.43269 77.133 3.2V54.4C77.133 56.1673 75.7003 57.6 73.933 57.6H3.53301C1.7657 57.6 0.333008 56.1673 0.333008 54.4V3.2C0.333008 1.43269 1.7657 0 3.53301 0H73.933ZM10.1076 47.6494C10.1076 48.0912 10.4658 48.4494 10.9076 48.4494H66.5584C67.0002 48.4494 67.3584 48.0912 67.3584 47.6494V9.95059C67.3584 9.50876 67.0002 9.15059 66.5584 9.15059H10.9076C10.4658 9.15059 10.1076 9.50876 10.1076 9.95059V47.6494Z\"\n fill={backBubbleColor} />\n <path\n d=\"M19.5332 22.4C19.5332 20.6326 20.9659 19.2 22.7332 19.2H93.1332C94.9005 19.2 96.3332 20.6326 96.3332 22.4V76.8C96.3332 78.2222 95.3945 79.4737 94.0292 79.8719L39.7572 95.7013C39.2452 95.8506 38.7332 95.4666 38.7332 94.9333V80C38.7332 79.5581 38.375 79.2 37.9332 79.2H22.7332C20.9659 79.2 19.5332 77.7673 19.5332 76V22.4Z\"\n fill={innerFrontBubbleColor} />\n <path\n d=\"M93.1332 19.2C94.9005 19.2 96.3332 20.6326 96.3332 22.4V76.8C96.3332 78.2222 95.3945 79.4737 94.0292 79.8719L39.7572 95.7013C39.2452 95.8506 38.7332 95.4666 38.7332 94.9333V80C38.7332 79.5581 38.375 79.2 37.9332 79.2H22.7332C20.9659 79.2 19.5332 77.7673 19.5332 76V22.4C19.5332 20.6326 20.9659 19.2 22.7332 19.2H93.1332ZM48.3377 82.1286C48.3355 82.6633 48.8484 83.0497 49.3617 82.9L86.1572 72.1672C86.4985 72.0676 86.7332 71.7547 86.7332 71.3992V29.6C86.7332 29.1581 86.375 28.8 85.9332 28.8H29.9332C29.4914 28.8 29.1332 29.1581 29.1332 29.6V68.8C29.1332 69.2418 29.4914 69.6 29.9332 69.6H47.5869C48.03 69.6 48.3887 69.9602 48.3869 70.4033L48.3377 82.1286Z\"\n fill={frontBubbleColor} />\n <circle\n cx=\"45.1334\" cy=\"44.8\" r=\"6.4\"\n fill={frontBubbleColor} />\n </svg>\n );\n}\n","import React from 'react';\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const OpenFrameLogo = ({ className, lowerPathColor, upperPathColor, ...props }: { className?: string, lowerPathColor?: string, upperPathColor?: string } & React.SVGProps<SVGSVGElement>) => {\n return (\n <svg\n {...props}\n className={className}\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 32 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n style={{\n '--fill-0': 'currentColor',\n ...props.style\n } as React.CSSProperties}\n >\n <g>\n <g>\n {/* White squares - top right, bottom left, bottom right, bottom center */}\n <path\n d=\"M21.3333 16.5333C21.3333 16.2388 21.5721 16 21.8667 16H26.1333C26.4279 16 26.6667 16.2388 26.6667 16.5333V20.8C26.6667 21.0946 26.4279 21.3333 26.1333 21.3333H21.8667C21.5721 21.3333 21.3333 21.0946 21.3333 20.8V16.5333Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n <path\n d=\"M16 21.8667C16 21.5721 16.2388 21.3333 16.5333 21.3333H20.8C21.0946 21.3333 21.3333 21.5721 21.3333 21.8667V26.1333C21.3333 26.4279 21.0946 26.6667 20.8 26.6667H16.5333C16.2388 26.6667 16 26.4279 16 26.1333V21.8667Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n <path\n d=\"M26.6667 21.8667C26.6667 21.5721 26.9054 21.3333 27.2 21.3333H31.4667C31.7612 21.3333 32 21.5721 32 21.8667V26.1333C32 26.4279 31.7612 26.6667 31.4667 26.6667H27.2C26.9054 26.6667 26.6667 26.4279 26.6667 26.1333V21.8667Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n <path\n d=\"M21.3333 27.2C21.3333 26.9054 21.5721 26.6667 21.8667 26.6667H26.1333C26.4279 26.6667 26.6667 26.9054 26.6667 27.2V31.4667C26.6667 31.7612 26.4279 32 26.1333 32H21.8667C21.5721 32 21.3333 31.7612 21.3333 31.4667V27.2Z\"\n fill={lowerPathColor ?? '#ffffff'}\n />\n </g>\n {/* Black frame/border */}\n <path\n d=\"M30.9333 0H1.06667C0.477563 0 0 0.477564 0 1.06667V30.9333C0 31.5224 0.477563 32 1.06667 32H14.9333C15.5224 32 16 31.5224 16 30.9333V27.7333C16 27.1442 15.5224 26.6667 14.9333 26.6667H5.86667C5.57211 26.6667 5.33333 26.4279 5.33333 26.1333V5.86667C5.33333 5.57211 5.57211 5.33333 5.86667 5.33333H26.1333C26.4279 5.33333 26.6667 5.57212 26.6667 5.86667V14.9333C26.6667 15.5224 27.1442 16 27.7333 16H30.9333C31.5224 16 32 15.5224 32 14.9333V1.06667C32 0.477563 31.5224 0 30.9333 0Z\"\n fill={upperPathColor ?? '#1A1A1A'}\n />\n </g>\n </svg>\n );\n}; ","import React from 'react';\n\n/** Raw SVG path data — single source of truth for the Flamingo logo.\n * Used by the React component and exported for non-React contexts (e.g. email HTML). */\nexport const FLAMINGO_LOGO_SVG_PATH = 'M20.8645 77.9756C20.6306 78.095 20.3452 77.9582 20.3369 77.7002C20.2055 73.6173 23.4398 62.2314 27.7657 59.0452C31.477 45.9806 61.8811 24.0208 81.7715 48.2044C83.1662 49.7884 84.0264 52.0978 84.7512 54.0436C86.0615 57.5613 86.9291 59.8908 89.7117 54.5977C92.4782 49.335 87.2725 42.2381 81.701 34.6426C75.7955 26.5918 69.4791 17.9808 71.8102 10.4001C75.4609 -1.47146 91.9849 -4.33245 94.5422 7.89834C98.4226 10.7002 104.422 17.0815 96.2751 25.8554C96.0466 26.1014 95.6263 25.9453 95.6104 25.6132C95.417 21.5769 93.9498 16.1177 90.5641 14.5697C89.0187 13.8632 88.0307 13.6723 87.1405 13.5003C85.585 13.1998 84.3282 12.9569 80.919 10.1221C75.236 5.39658 75.236 20.1291 87.7386 32.3599C97.1156 41.533 106.493 66.2324 84.0287 70.9981C74.9174 72.9311 68.0892 72.0015 61.3076 71.0782C61.0953 71.0493 60.8831 71.0204 60.6708 70.9916V89.3274L66.3745 91.8104C67.0914 92.1225 67.4139 92.944 67.0949 93.6453C66.7759 94.3466 65.9362 94.6621 65.2193 94.35L60.6708 92.37V118.61C60.6708 119.378 60.0347 120 59.2501 120C58.4654 120 57.8293 119.378 57.8293 118.61V91.133L42.4873 84.4542C42.0611 84.2686 41.7551 83.8902 41.6687 83.4417C41.5824 82.9931 41.7266 82.5317 42.0546 82.2072L54.1527 70.2377C45.537 69.536 35.8193 70.3474 20.8645 77.9756ZM57.7692 70.613L45.5202 82.732L57.8293 88.0905V70.6204C57.8093 70.618 57.7893 70.6155 57.7692 70.613Z';\n\nexport const FLAMINGO_LOGO_VIEWBOX = '0 0 121 120';\n\ninterface FlamingoLogoProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n fill?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function FlamingoLogo({ className = '', fill = 'var(--ods-flamingo-pink-base)', ...props }: FlamingoLogoProps) {\n return (\n <svg\n width=\"121\"\n height=\"120\"\n viewBox={FLAMINGO_LOGO_VIEWBOX}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d={FLAMINGO_LOGO_SVG_PATH}\n fill={fill}\n />\n </svg>\n );\n} ","import React from 'react';\n\ninterface MiamiCyberGangLogoFaceOnlyProps {\n size?: number;\n /** Pink color used for accent elements. Defaults to ODS accent color */\n originalPink?: string;\n /** White color used for text and details. Defaults to ODS text-on-accent color */\n originalWhite?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const MiamiCyberGangLogoFaceOnly: React.FC<MiamiCyberGangLogoFaceOnlyProps> = ({\n size = 64,\n originalPink = \"var(--ods-accent, #F357BB)\",\n originalWhite = \"var(--ods-text-on-accent, #FAFAFA)\",\n className = ''\n}) => {\n return (\n <svg className={className} width={size} height={size} viewBox=\"0 0 120 120\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M102.395 53.6809C90.4125 50.7582 80.6974 44.729 74.1665 33.9873C73.8956 34.2151 73.7234 34.299 73.6447 34.4355C68.7714 42.9024 61.1392 47.742 52.0761 50.5062C47.3393 51.9497 42.4555 52.9072 37.5024 53.8814C38.8546 50.9314 40.3233 48.1903 39.8929 44.7238C32.5693 50.9692 23.5986 52.1744 14.4546 53.8478C14.7695 52.1649 14.9501 50.6658 15.3375 49.2212C16.6004 44.5086 17.6723 39.7203 19.3048 35.1347C22.3566 26.5661 28.8445 21.5521 37.3439 18.9685C43.3699 17.1376 49.5848 16.6746 55.8502 16.7114C57.7094 16.7229 59.5676 16.7135 61.4972 16.5234C58.6459 13.5482 55.13 11.7205 51.3055 10.3305C52.8141 9.65024 59.3786 10.0628 64.043 11.1714C68.2685 12.1761 72.1833 13.8527 75.4588 16.9087C80.9704 13.8873 86.8746 13.1651 93.1336 13.3834C91.7416 14.0102 90.444 14.5036 89.2356 15.1618C87.9706 15.8505 86.7423 16.6326 85.5864 17.4935C84.4379 18.348 83.3997 19.3506 82.1021 20.4697C82.7572 20.8256 83.1697 21.0776 83.6054 21.2812C89.3312 23.9698 93.9283 27.9151 97.25 33.3406C99.2404 36.5919 100.029 40.2327 100.817 43.8682C101.477 46.9085 101.961 49.9887 102.51 53.0531C102.538 53.2127 102.451 53.3922 102.395 53.6809Z\"\n fill={originalWhite} />\n <path\n d=\"M45.7357 106.481C44.8472 105.838 44.7949 104.555 45.5033 103.717C46.1854 102.911 47.3459 102.791 48.2538 103.331C54.1019 106.808 59.9027 106.818 65.7439 103.334C66.6566 102.79 67.8521 102.94 68.5404 103.749C69.2297 104.56 69.1869 105.767 68.3442 106.417C62.4972 110.926 52.5717 111.432 45.7357 106.481Z\"\n fill={originalWhite} />\n <path\n d=\"M81.9671 69.9535C85.2121 69.9577 87.8881 72.2967 87.9564 75.1869C88.0246 78.1117 85.1533 80.7006 81.8768 80.6691C78.6203 80.6376 76.0892 78.2996 76.0724 75.3087C76.0545 72.2222 78.5573 69.9493 81.9671 69.9535Z\"\n fill={originalWhite} />\n <path\n d=\"M35.5036 80.7335C33.1909 80.7356 31.549 79.9891 30.3942 78.3535C28.684 75.9337 29.2792 72.7863 31.761 71.1675C33.8239 69.8216 36.0149 69.6893 38.2321 70.7706C40.5449 71.8971 41.6063 74.0303 41.1632 76.5237C40.8011 78.5551 38.6815 80.4238 36.4369 80.6768C36.0212 80.723 35.6013 80.7282 35.5036 80.7335Z\"\n fill={originalWhite} />\n <path\n d=\"M16.2685 72.4296C16.743 61.5083 30.7046 61.3183 31.8437 61.2228C31.8437 61.2228 43.4306 60.0837 48.749 65.0221C54.0674 69.9605 50.9326 86.6757 45.1397 90.285C39.0119 94.1022 28.71 94.2733 23.9606 91.2341C19.2122 88.1948 15.794 83.351 16.2685 72.4296ZM95.1911 91.2341C90.4427 94.2733 80.1408 94.1022 74.013 90.285C68.219 86.6757 65.0853 69.9605 70.4037 65.0221C75.7221 60.0837 87.309 61.2238 87.309 61.2238C88.4481 61.3183 102.41 61.5083 102.884 72.4307C103.359 83.352 99.9405 88.1948 95.1911 91.2341ZM59.5758 68.9474C59.9538 68.9999 60.422 69.0817 61.0015 69.2014C64.7053 69.9605 64.4208 76.419 66.8899 83.162C69.3591 89.905 74.1075 96.458 88.7336 95.3179C103.359 94.1788 105.163 81.0728 105.638 78.3181C106.113 75.5644 107.253 72.9052 107.253 72.9052L108.687 71.4711C108.985 71.173 109.153 70.7688 109.153 70.3478V63.6174C109.153 62.8762 108.641 62.2369 107.92 62.071C105.532 61.522 99.8575 60.2958 92.5319 59.2292C82.7496 57.8045 72.7784 59.7037 70.6882 61.1283C68.5991 62.5529 66.8899 63.0274 66.8899 63.0274H52.2627C52.2627 63.0274 50.5536 62.5529 48.4645 61.1283C46.3753 59.7037 36.4031 57.8045 26.6208 59.2281C19.2951 60.2947 13.6208 61.522 11.2325 62.071C10.5113 62.2369 10 62.8762 10 63.6164V70.3468C10 70.7688 10.168 71.1719 10.4651 71.4701L11.9002 72.9042C11.9002 72.9042 13.0392 75.5634 13.5148 78.3181C13.9893 81.0718 15.7929 94.1778 30.4191 95.3179C45.0442 96.458 49.7936 89.905 52.2627 83.162C54.7319 76.419 54.4474 69.9605 58.1512 69.2014C58.7307 69.0817 59.1989 68.9999 59.5758 68.9474Z\"\n fill={originalPink} />\n </svg>\n\n\n );\n};","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function ShellIcon({ className = \"w-5 h-5\", size = 22, color = 'white' }: { className?: string; size?: number; color?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 48 48\" >\n <path\n fill='transparent'\n stroke={color}\n d=\"M6.5 8.4a2 2 0 0 0-2 2v27.2a2 2 0 0 0 2 2h35a2 2 0 0 0 2-2V10.4a2 2 0 0 0-2-2zM9 23.16l7.72 6L9 35.13v-12zm20.46 11.97h-11\" />\n </svg >\n )\n}\n","import React from 'react';\n\ninterface GitHubIconProps {\n color?: string;\n className?: string;\n width?: number;\n height?: number;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const GitHubIcon: React.FC<GitHubIconProps> = ({\n className = \"\",\n width = 15,\n height = 14,\n color = 'white'\n}) => {\n return (\n <svg \n width={width} \n height={height} \n viewBox=\"0 0 15 14\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <path d=\"M7.18173 0.333008C3.40523 0.333008 0.346436 3.3918 0.346436 7.1683C0.346436 10.1929 2.30304 12.7476 5.02007 13.6533C5.36183 13.7131 5.48999 13.508 5.48999 13.3286C5.48999 13.1663 5.48145 12.628 5.48145 12.0555C3.76408 12.3717 3.31979 11.6369 3.18308 11.2524C3.10618 11.0559 2.77296 10.4492 2.48246 10.2869C2.24323 10.1587 1.90146 9.84261 2.47392 9.83406C3.0122 9.82552 3.39668 10.3296 3.52485 10.5347C4.14002 11.5685 5.1226 11.278 5.51563 11.0986C5.57543 10.6543 5.75486 10.3553 5.95137 10.1844C4.43052 10.0135 2.84132 9.42395 2.84132 6.80945C2.84132 6.06611 3.10618 5.45093 3.54193 4.97246C3.47358 4.80158 3.23435 4.10096 3.61029 3.16111C3.61029 3.16111 4.18274 2.98168 5.48999 3.86173C6.03682 3.70793 6.61782 3.63104 7.19882 3.63104C7.77982 3.63104 8.36082 3.70793 8.90764 3.86173C10.2149 2.97314 10.7873 3.16111 10.7873 3.16111C11.1633 4.10096 10.9241 4.80158 10.8557 4.97246C11.2914 5.45093 11.5563 6.05757 11.5563 6.80945C11.5563 9.43249 9.95856 10.0135 8.43771 10.1844C8.68549 10.398 8.8991 10.8081 8.8991 11.4489C8.8991 12.3631 8.89055 13.0979 8.89055 13.3286C8.89055 13.508 9.01871 13.7216 9.36048 13.6533C10.7174 13.1952 11.8965 12.3231 12.7318 11.1597C13.5671 9.99643 14.0166 8.60046 14.017 7.1683C14.017 3.3918 10.9582 0.333008 7.18173 0.333008Z\" fill={color}/>\n </svg>\n );\n}; ","import { color } from 'framer-motion'\nimport React from 'react'\n\ninterface SlackIconProps {\n width?: number | string\n height?: number | string\n className?: string\n injectedColor?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function SlackIcon({ \n width = 24, \n height = 24, \n className = \"text-current\" ,\n injectedColor \n}: SlackIconProps) {\n\n const redColor = injectedColor || \"#E01E5A\";\n const blueColor = injectedColor || \"#36C5F0\";\n const greenColor = injectedColor || \"#2EB67D\";\n const yellowColor = injectedColor || \"#ECB22E\";\n\n return (\n <svg \n width={width} \n height={height} \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <g>\n <path \n d=\"M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52zM6.313 15.165a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313z\" \n fill={redColor} \n />\n <path \n d=\"M8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834zM8.834 6.313a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312z\" \n fill={blueColor} \n />\n <path \n d=\"M18.956 8.834a2.528 2.528 0 0 1 2.521-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.523 2.521h-2.521V8.834zM17.688 8.834a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312z\" \n fill={greenColor} \n />\n <path \n d=\"M15.165 18.956a2.528 2.528 0 0 1 2.523 2.521A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.523v-2.521h2.52zM15.165 17.688a2.527 2.527 0 0 1-2.52-2.523 2.528 2.528 0 0 1 2.52-2.521h6.313A2.528 2.528 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313z\" \n fill={yellowColor}\n />\n </g>\n </svg>\n )\n} ","import React from 'react'\n\ninterface ClickUpIconProps {\n width?: number | string\n height?: number | string\n className?: string\n}\n\nexport function ClickUpIcon({\n width = 24,\n height = 24,\n className = '',\n}: ClickUpIconProps) {\n return (\n <svg\n width={width}\n height={height}\n viewBox=\"0 0 54.8 65.8\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <defs>\n <linearGradient id=\"clickup-grad-1\" gradientUnits=\"userSpaceOnUse\" x1=\"0\" y1=\"15.0492\" x2=\"54.8446\" y2=\"15.0492\" gradientTransform=\"matrix(1 0 0 -1 0 69.3604)\">\n <stop offset=\"0\" stopColor=\"#8930FD\" />\n <stop offset=\"1\" stopColor=\"#49CCF9\" />\n </linearGradient>\n <linearGradient id=\"clickup-grad-2\" gradientUnits=\"userSpaceOnUse\" x1=\"1.1953\" y1=\"53.166\" x2=\"53.7447\" y2=\"53.166\" gradientTransform=\"matrix(1 0 0 -1 0 69.3604)\">\n <stop offset=\"0\" stopColor=\"#FF02F0\" />\n <stop offset=\"1\" stopColor=\"#FFC800\" />\n </linearGradient>\n </defs>\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M0,50.6l10.1-7.8c5.4,7,11.1,10.3,17.4,10.3c6.3,0,11.9-3.2,17-10.2l10.3,7.6c-7.4,10-16.6,15.3-27.3,15.3 C16.9,65.8,7.6,60.5,0,50.6z\"\n fill=\"url(#clickup-grad-1)\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M27.5,16.9l-18,15.5l-8.3-9.7L27.6,0l26.2,22.7l-8.4,9.6L27.5,16.9z\"\n fill=\"url(#clickup-grad-2)\"\n />\n </svg>\n )\n}\n","import React from 'react';\n\ninterface XLogoProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function XLogo({ className = '', color = 'white', ...props }: XLogoProps) {\n return (\n <svg\n width={24}\n height={24}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M9.75292 12.6562C10.1923 12.2169 10.9044 12.2169 11.3437 12.6562C11.7831 13.0956 11.7831 13.8077 11.3437 14.2471L3.7954 21.7954C3.35606 22.2348 2.64392 22.2348 2.20458 21.7954C1.76524 21.3561 1.76524 20.6439 2.20458 20.2046L9.75292 12.6562ZM20.2046 2.20459C20.6439 1.76525 21.3561 1.76525 21.7954 2.20459C22.2347 2.64393 22.2347 3.35607 21.7954 3.79541L14.2471 11.3438C13.8077 11.7831 13.0956 11.7831 12.6562 11.3438C12.2169 10.9044 12.2169 10.1923 12.6562 9.75293L20.2046 2.20459Z\" fill=\"#FAFAFA\" />\n <path d=\"M7.9995 1.875L8.13426 1.88232C8.444 1.91951 8.72702 2.08473 8.9121 2.34082L21.9126 20.3408C22.1599 20.6833 22.1943 21.1365 22.0019 21.5127C21.8096 21.8887 21.4223 22.125 21 22.125H16.0005C15.6393 22.125 15.2994 21.9519 15.0879 21.6592L2.08739 3.65918C1.84004 3.31669 1.8057 2.86346 1.99803 2.4873C2.19042 2.11133 2.57763 1.875 2.99999 1.875H7.9995ZM16.5747 19.875H18.7983L7.42528 4.125H5.20165L16.5747 19.875Z\" fill=\"#FAFAFA\" />\n </svg>\n );\n} ","import * as React from 'react';\nimport { cn } from '../../utils/cn';\n\n/**\n * HubSpot brand logo (solid orange)\n * Usage: <HubspotIcon className=\"h-4 w-4\" />\n */\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function HubspotIcon({ className, fill = '#FF7A59', ...props }: React.SVGProps<SVGSVGElement>) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 512 512\"\n fill={fill}\n className={cn('inline-block', className)}\n {...props}\n >\n <path d=\"M266.197 216.109c-22.551 21.293-36.655 51.48-36.655 84.991 0 26.326 8.714 50.582 23.359 70.08l-44.473 44.74c-3.953-1.438-8.176-2.245-12.579-2.245-9.702 0-18.776 3.774-25.605 10.602-6.828 6.827-10.602 15.989-10.602 25.696 0 9.701 3.773 18.775 10.602 25.605 6.829 6.826 15.993 10.42 25.605 10.42 9.703 0 18.777-3.505 25.695-10.42 6.829-6.83 10.602-15.994 10.602-25.605 0-3.774-.538-7.369-1.707-10.873l44.923-45.102c19.765 15.183 44.381 24.169 71.244 24.169 64.599 0 116.797-52.38 116.797-116.977 0-58.578-42.854-107.093-99.007-115.628v-55.343c15.723-6.65 25.335-21.384 25.335-38.545 0-23.449-18.777-43.034-42.227-43.034-23.448 0-41.956 19.585-41.956 43.034 0 17.161 9.613 31.895 25.335 38.545v54.983c-13.655 1.887-26.593 6.019-38.362 12.219-24.796-18.778-105.565-76.997-151.746-112.126 1.078-3.953 1.798-8.085 1.798-12.397 0-25.875-21.113-46.898-47.078-46.898-25.875 0-46.898 21.023-46.898 46.898 0 25.965 21.023 46.988 46.898 46.988 8.805 0 16.98-2.606 24.078-6.828L266.197 216.109zM346.606 363.095c-34.229 0-61.991-27.763-61.991-61.994 0-34.229 27.762-61.99 61.991-61.99 34.23 0 61.992 27.761 61.992 61.99 0 34.231-27.762 61.994-61.992 61.994z\" />\n </svg>\n );\n} ","import React from 'react';\n\ninterface LinkedInIconProps extends React.SVGProps<SVGSVGElement> {\n className?: string;\n size?: number;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function LinkedInIcon({ className = '', size = 24, color = 'white', ...props }: LinkedInIconProps) {\n return (\n <svg \n width={size} \n height={size} \n viewBox=\"0 0 24 24\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path \n d=\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\" \n fill={color}\n />\n </svg>\n );\n}","import React from 'react';\n\ninterface YouTubeIconProps {\n color?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function YouTubeIcon({ className ,\n color = 'white'\n}: YouTubeIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17\" />\n <path d=\"m10 15 5-3-5-3z\" />\n </svg>\n );\n}","import React from 'react';\n\ninterface InstagramIconProps {\n color?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function InstagramIcon({ className ,\n color = 'white'\n}: InstagramIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <rect width=\"20\" height=\"20\" x=\"2\" y=\"2\" rx=\"5\" ry=\"5\" />\n <path d=\"m16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z\" />\n <line x1=\"17.5\" x2=\"17.51\" y1=\"6.5\" y2=\"6.5\" />\n </svg>\n );\n}","import React from 'react';\n\ninterface FacebookIconProps {\n color?: string;\n className?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function FacebookIcon({ className ,\n color = 'white'\n}: FacebookIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke={color}\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n >\n <path d=\"M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z\" />\n </svg>\n );\n}","import React from \"react\"\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface WindowsIconProps extends React.SVGProps<SVGSVGElement> {}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function WindowsIcon({ className, color = 'white', ...props }: WindowsIconProps) {\n return (\n <svg \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 16 16\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M0.833374 2.22562L6.28233 1.48656L6.28468 6.72147L0.838322 6.75234L0.833374 2.22567V2.22562ZM6.27973 7.32457L6.2839 12.564L0.837593 11.8182L0.83728 7.28945L6.27973 7.32457ZM6.94025 1.38981L14.165 0.3396V6.65486L6.94025 6.71192V1.38981ZM14.1667 7.37385L14.165 13.6606L6.9402 12.645L6.93009 7.36207L14.1667 7.37385Z\" fill={color}/>\n </svg>\n )\n}","import React from \"react\"\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface MacOSIconProps extends React.SVGProps<SVGSVGElement> {\n color?: string;\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function MacOSIcon({ className, color = 'white', ...props }: MacOSIconProps) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M12.2131 8.41846C12.1971 6.7312 13.5884 5.92054 13.651 5.88193C12.8678 4.73511 11.6515 4.57748 11.2182 4.55979C10.1831 4.45363 9.1978 5.171 8.67145 5.171C8.14509 5.171 7.3347 4.57427 6.47616 4.59196C5.34642 4.60804 4.30494 5.24981 3.72242 6.26314C2.55096 8.29943 3.42394 11.3233 4.56812 12.9784C5.12818 13.7875 5.79254 14.6994 6.66873 14.6657C7.51282 14.6319 7.83056 14.1188 8.84797 14.1188C9.86538 14.1188 10.1526 14.6657 11.0433 14.6496C11.9499 14.6319 12.5244 13.8228 13.0797 13.0106C13.7184 12.0696 13.9831 11.1609 13.9992 11.1126C13.9783 11.1046 12.2324 10.4338 12.2131 8.41846Z\" fill={color} />\n <path d=\"M10.5393 3.46284C11.0047 2.89827 11.3176 2.11496 11.2326 1.33325C10.5634 1.3606 9.75299 1.7804 9.27317 2.34497C8.8431 2.84359 8.46598 3.64138 8.56869 4.407C9.31168 4.4649 10.0755 4.02579 10.5393 3.46284Z\" fill={color} />\n </svg>\n )\n}","import React from \"react\"\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface LinuxIconProps extends React.SVGProps<SVGSVGElement> {}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport function LinuxIcon({ className, color = 'white', ...props }: LinuxIconProps) {\n return (\n <svg \n width=\"16\" \n height=\"16\" \n viewBox=\"0 0 17 20\" \n fill=\"none\" \n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n {...props}\n >\n <path d=\"M16.5665 16.3141C16.0389 16.0972 15.6042 15.7556 15.6357 15.1013C15.6664 14.448 15.1694 14.015 15.1694 14.015C15.1694 14.015 15.6042 12.5845 15.2002 11.4033C14.797 10.2204 13.4629 8.32531 12.4392 6.8956C11.4171 5.46507 12.2849 3.81673 11.3549 1.7038C10.4232 -0.409119 8.00404 -0.285272 6.70073 0.616579C5.39654 1.51677 5.79974 3.75437 5.86111 4.8134C5.92335 5.86899 5.88924 6.62142 5.76903 6.89473C5.64629 7.16804 4.8075 8.1707 4.24833 9.00936C3.68999 9.84806 3.2868 11.5894 2.88191 12.3043C2.47872 13.0191 2.7583 13.6716 2.7583 13.6716C2.7583 13.6716 2.47872 13.7639 2.26133 14.2328C2.04395 14.6973 1.61009 14.9151 0.834407 15.0689C0.0587253 15.2243 0.0587252 15.7239 0.244535 16.2834C0.431214 16.8419 0.245404 17.1545 0.0280204 17.8676C-0.189363 18.5808 0.896647 18.8002 1.95108 18.9224C3.00639 19.0479 4.18526 19.732 5.1792 19.8559C6.17056 19.9806 6.48168 19.1726 6.48168 19.1726C6.48168 19.1726 7.59836 18.9224 8.7764 18.8933C9.95615 18.8617 11.0711 19.1419 11.0711 19.1419C11.0711 19.1419 11.2885 19.6389 11.6917 19.8558C12.0958 20.0736 12.9644 20.1052 13.5227 19.5159C14.0819 18.9241 15.5711 18.1793 16.4081 17.7122C17.2476 17.2442 17.0942 16.5302 16.5665 16.3141ZM9.30566 2.60573C9.83756 2.60573 10.2672 3.13438 10.2672 3.78604C10.2672 4.24893 10.0515 4.64779 9.73699 4.84163C9.65685 4.80663 9.57248 4.77076 9.48297 4.73232C9.67222 4.63836 9.80689 4.39669 9.80689 4.11482C9.80689 3.7476 9.58014 3.4495 9.29969 3.4495C9.02267 3.4495 8.79506 3.74843 8.79506 4.11482C8.79506 4.25063 8.82746 4.38129 8.88286 4.48803C8.71748 4.42226 8.56491 4.36078 8.44557 4.31552C8.3808 4.15667 8.34413 3.97732 8.34413 3.786C8.34413 3.13438 8.77376 2.60573 9.30566 2.60573ZM9.23662 5.09444C9.50257 5.18669 9.79836 5.36006 9.76769 5.5317C9.73616 5.70421 9.59634 5.70421 9.23662 5.92458C8.87607 6.14322 8.09525 6.62831 7.84546 6.6599C7.59401 6.6915 7.4542 6.55059 7.18825 6.37891C6.9223 6.20641 6.42193 5.79729 6.54807 5.57953C6.54807 5.57953 6.93763 5.2806 7.10898 5.12433C7.28115 4.96718 7.71932 4.59224 7.98527 4.64094C8.25122 4.68619 8.97067 5.00048 9.23662 5.09444ZM6.83876 2.79277C7.25816 2.79277 7.59911 3.29323 7.59911 3.91072C7.59911 4.02431 7.58804 4.12935 7.56671 4.23099C7.46444 4.26599 7.36043 4.32237 7.25985 4.40777C7.20872 4.44962 7.16351 4.4889 7.12004 4.52818C7.18655 4.4035 7.21295 4.22584 7.18311 4.03881C7.12684 3.70147 6.90266 3.45548 6.68018 3.49052C6.45857 3.52897 6.32472 3.83213 6.38099 4.1712C6.4381 4.51028 6.66145 4.75623 6.88306 4.71949C6.89586 4.71692 6.9078 4.71351 6.92056 4.70923C6.81232 4.81344 6.71258 4.90312 6.61114 4.9791C6.30429 4.83649 6.07924 4.41201 6.07924 3.90981C6.07928 3.2924 6.41936 2.79277 6.83876 2.79277ZM6.01961 18.4997C5.92074 18.9455 5.3999 19.2691 5.3999 19.2691C4.92767 19.4177 3.61495 18.8472 3.01994 18.597C2.4258 18.3502 0.91277 18.2733 0.714157 18.053C0.517243 17.8275 0.813028 17.3313 0.888901 16.8607C0.962206 16.3867 0.740593 16.0903 0.813898 15.7667C0.888901 15.4447 1.85553 15.4447 2.22636 15.2218C2.59885 14.9972 2.67302 14.3515 2.97051 14.1782C3.26799 14.0031 3.8127 14.624 4.03601 14.9733C4.25849 15.3191 5.10151 16.8103 5.44847 17.1827C5.79626 17.5551 6.11848 18.0538 6.01961 18.4997ZM11.5066 14.1679C11.4171 14.606 11.4171 16.1894 11.4171 16.1894C11.4171 16.1894 10.4556 17.5243 8.9647 17.743C7.47554 17.9616 6.73052 17.8044 6.73052 17.8044L5.89343 16.8419C5.89343 16.8419 6.5438 16.7471 6.45177 16.0947C6.35799 15.4422 4.46651 14.5403 4.12468 13.7315C3.78456 12.9244 4.06331 11.5554 4.49804 10.8713C4.93194 10.188 5.20982 8.69685 5.64455 8.19806C6.07928 7.70271 6.4194 6.64537 6.26426 6.17822C6.26426 6.17822 7.19509 7.29787 7.8455 7.11253C8.49674 6.9255 9.95694 5.83657 10.1726 6.02448C10.3891 6.21151 12.2508 10.3135 12.4357 11.6194C12.6224 12.9244 12.3113 13.9185 12.3113 13.9185C12.3113 13.9185 11.5986 13.7323 11.5066 14.1679ZM16.2682 17.0964C15.9784 17.3629 14.3656 18.0154 13.8823 18.5244C13.4015 19.0291 12.7732 19.44 12.3888 19.3204C12.0018 19.1982 11.6651 18.6679 11.8339 17.8941C12.0018 17.1229 12.1476 16.2774 12.1237 15.794C12.0998 15.3106 12.0018 14.6572 12.1237 14.5607C12.2439 14.4668 12.4357 14.5138 12.4357 14.5138C12.4357 14.5138 12.3411 15.4302 12.8943 15.6736C13.4475 15.9127 14.2437 15.5771 14.4849 15.3337C14.727 15.0937 14.8958 14.7316 14.8958 14.7316C14.8958 14.7316 15.1361 14.8537 15.1123 15.2389C15.0884 15.6249 15.2802 16.1818 15.6433 16.3739C16.0039 16.5644 16.558 16.8317 16.2682 17.0964Z\" fill={color}/>\n </svg>\n )\n}","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface CmdIconProps {\n size?: number\n className?: string\n color?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const CmdIcon: React.FC<CmdIconProps> = ({ size = 16, className = '', color='white'}) => {\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={className}\n >\n <path\n d=\"M3 4C3 3.44772 3.44772 3 4 3H20C20.5523 3 21 3.44772 21 4V20C21 20.5523 20.5523 21 20 21H4C3.44772 21 3 20.5523 3 20V4Z\"\n stroke={color}\n />\n <text\n x=\"12\"\n y=\"16\"\n textAnchor=\"middle\"\n fill={color}\n fontSize=\"10\"\n fontFamily=\"monospace\"\n fontWeight=\"bold\"\n >\n \\&gt;\n </text>\n </svg>\n )\n}\n\nCmdIcon.displayName = 'CmdIcon'\n","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface BashIconProps {\n size?: number\n className?: string\n color?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const BashIcon: React.FC<BashIconProps> = ({ size = 16, className = '' , color = 'white'}) => {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n className={className}\n viewBox=\"0 0 24 24\">\n <path fill={color}\n d=\"M5 9h2.31l.32-3h2l-.32 3h2l.32-3h2l-.32 3H15v2h-1.9l-.2 2H15v2h-2.31l-.32 3h-2l.32-3h-2l-.32 3h-2l.32-3H5v-2h1.9l.2-2H5zm4.1 2l-.2 2h2l.2-2M19 6h-2v8h2m0 2h-2v2h2Z\" />\n </svg>\n )\n}\n\nBashIcon.displayName = 'BashIcon'\n","import React from 'react'\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface NushellIconProps {\n size?: number\n className?: string\n color?: string\n}\n\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const NushellIcon: React.FC<NushellIconProps> = ({ size = 16, className = '', color = 'white' }) => {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n className={className}\n viewBox=\"0 0 24 24\">\n <path\n fill={color}\n d=\"M0 16.338h1.25v-5.7c.417-.624 1.205-1.309 2.127-1.309c1.176 0 1.34.64 1.34 2.247v4.762h1.25v-5.685c0-1.458-.67-2.32-2.202-2.32c-.923 0-1.964.46-2.59 1.264l-.103-1.1H0Zm10.177-7.842h-1.25v5.698c0 1.46.745 2.307 2.263 2.307c.921 0 1.889-.431 2.514-1.22l.104 1.057h1.072V8.496h-1.25v5.773c-.432.67-1.265 1.25-2.129 1.25c-.907 0-1.324-.446-1.324-1.458zm8.11-.997l-.61.952l5.251 3.229l-5.251 3.244l.669.922L24 12.32v-1.28z\" />\n </svg>\n )\n}\n\nNushellIcon.displayName = 'NushellIcon'\n","import React from 'react'\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport interface DenoIconProps {\n size?: number\n className?: string\n color?: string\n}\n/** @deprecated Use icons from icons-v2-generated instead. */\nexport const DenoIcon: React.FC<DenoIconProps> = ({ size = 16, className = '', color = 'white' }) => {\n return (\n <svg\n version=\"1.1\"\n width={size}\n height={size}\n className={className}\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 122.87 122.88\">\n <g>\n <path\n fill={color}\n d=\"M56.6,0.03c-0.29,0.03-1.21,0.14-2.04,0.21C42.74,1.48,31.11,6.48,21.62,14.43c-1.75,1.45-5.74,5.44-7.19,7.19 C6.57,31.01,1.98,41.54,0.28,54.01c-0.38,2.77-0.38,12.1,0,14.87c1.69,12.47,6.29,23,14.14,32.38c1.45,1.75,5.44,5.74,7.19,7.19 C31,116.31,41.54,120.9,54,122.6c2.77,0.38,12.1,0.38,14.87,0c12.47-1.69,23-6.29,32.38-14.14c1.75-1.45,5.74-5.44,7.19-7.19 c7.86-9.38,12.45-19.92,14.14-32.38c0.38-2.77,0.38-12.1,0-14.87c-1.69-12.47-6.29-23-14.14-32.38c-1.45-1.75-5.44-5.74-7.19-7.19 C91.9,6.6,81.26,1.95,68.96,0.3c-1.33-0.18-3.26-0.26-6.85-0.29C59.38-0.01,56.89,0,56.6,0.03L56.6,0.03z M57.36,6.56 c0,1.77,0.12,5.61,0.29,9.25c0.09,1.78,0.2,4.34,0.24,5.67c0.17,4.71,0.67,17.09,0.74,18.19l0.08,1.1l-0.68-0.08 c-0.38-0.03-0.73-0.12-0.79-0.17c-0.05-0.06-0.15-1.1-0.21-2.33c-0.27-5.38-1.16-26.25-1.25-29.3l-0.09-3.35l0.42-0.06 c0.23-0.03,0.6-0.08,0.85-0.09l0.41-0.01L57.36,6.56L57.36,6.56L57.36,6.56z M71.82,6.2c0.02,0.02,0.06,4.58,0.11,10.14 c0.06,5.58,0.14,10.58,0.18,11.12c0.05,0.56,0.03,1.04-0.05,1.07c-0.06,0.05-0.44,0.05-0.82,0l-0.7-0.06l-0.11-4.4 c-0.06-2.43-0.14-5.12-0.17-6c-0.12-2.67-0.23-11.76-0.14-11.98C70.2,5.93,70.37,5.91,71,6.02C71.44,6.11,71.8,6.18,71.82,6.2 L71.82,6.2L71.82,6.2z M36.87,11.26c0.09,0.14,0.8,8.46,1.68,19.36c0.29,3.7,0.57,7.09,0.62,7.51c0.08,0.77,0.06,0.8-0.42,1.1 c-0.27,0.17-0.54,0.3-0.6,0.3c-0.05,0-0.14-0.39-0.18-0.88c-0.21-1.96-1.03-11.45-1.6-18.31c-0.33-4.03-0.63-7.65-0.68-8.04 c-0.08-0.67-0.06-0.73,0.33-0.94C36.49,11.11,36.76,11.06,36.87,11.26L36.87,11.26L36.87,11.26z M78.47,14.3 c0.42,0.15,0.47,0.23,0.56,1.09c0.15,1.51,0.11,8.73-0.06,8.73c-0.44,0-1.35-0.51-1.42-0.8c-0.05-0.18-0.09-2.33-0.09-4.76 C77.45,13.65,77.39,13.93,78.47,14.3L78.47,14.3z M50.56,15.01c0,0.41,0.11,2.66,0.23,5.03c0.12,2.37,0.26,5.38,0.32,6.68 c0.11,2.63,0.14,2.54-0.88,2.6c-0.5,0.02-0.5,0.02-0.53-0.74c-0.03-0.42-0.11-1.74-0.2-2.95c-0.08-1.21-0.26-3.82-0.38-5.82 c-0.12-1.99-0.27-3.97-0.32-4.4c-0.09-0.76-0.08-0.79,0.33-0.94c0.24-0.09,0.67-0.17,0.94-0.17C50.56,14.3,50.56,14.3,50.56,15.01 L50.56,15.01L50.56,15.01z M92.47,17.08l0.51,0.21l0.11,2.02c0.05,1.1,0.08,3.49,0.05,5.29l-0.05,3.29l-0.63-0.32l-0.63-0.3 l-0.05-5.02c-0.03-2.77-0.02-5.11,0.02-5.21C91.85,16.82,91.85,16.82,92.47,17.08L92.47,17.08L92.47,17.08z M64.88,19.06 c0.09,0.09,0.3,7.42,0.32,11.14l0.02,2.24l-0.71-0.11c-0.41-0.05-0.74-0.09-0.76-0.11c-0.05-0.03-0.5-11.23-0.5-12.32v-1.12 l0.77,0.09C64.46,18.94,64.84,19.01,64.88,19.06L64.88,19.06L64.88,19.06z M99.68,20.13c0.18,0.21,0.21,3.52,0.26,21.77 c0.05,20.96,0.05,21.5-0.23,21.5c-0.17,0-0.39-0.09-0.53-0.2c-0.23-0.17-0.26-1.99-0.33-19.9c-0.06-10.85-0.14-20.7-0.18-21.9 l-0.09-2.18l0.44,0.32C99.27,19.74,99.56,19.99,99.68,20.13L99.68,20.13L99.68,20.13z M86.13,23.23c0.08,0.06,0.15,0.92,0.17,1.9 c0.08,3.34,0.09,23.81,0.02,23.88c-0.03,0.03-0.3-0.05-0.6-0.17l-0.54-0.23l0-25.7L85.58,23C85.81,23.06,86.05,23.15,86.13,23.23 L86.13,23.23L86.13,23.23z M44.42,24.07c0.05,0.41,0.12,1.33,0.17,2.09c0.05,0.74,0.15,2.43,0.24,3.75 c0.18,2.66,0.15,2.83-0.71,2.83c-0.45,0-0.51-0.05-0.57-0.5c-0.15-0.89-0.68-8.33-0.6-8.45c0.08-0.11,0.86-0.38,1.22-0.41 C44.26,23.36,44.38,23.68,44.42,24.07L44.42,24.07z M19.43,27.93c0.17,1.6,0.5,4.96,0.74,7.45c0.26,2.49,0.47,4.61,0.47,4.7 c0,0.18-1.16,0.76-1.28,0.63c-0.08-0.08-1.59-13.45-1.59-14.05c0-0.36,1.16-1.89,1.31-1.72C19.13,24.96,19.28,26.31,19.43,27.93 L19.43,27.93z M78.68,29.51l0.44,0.26l0.02,3.26c0.01,1.78,0.05,3.78,0.05,4.43c0.03,1.36-0.14,1.59-0.95,1.3l-0.47-0.17v-1.3 c0-0.73-0.05-2.83-0.11-4.68l-0.09-3.35h0.35C78.09,29.26,78.44,29.38,78.68,29.51L78.68,29.51L78.68,29.51z M26.06,35.38 c0.27,2.9,0.71,7.8,1,10.88l0.51,5.59l-0.59,0.59l-0.57,0.59l-0.11-1.19c-0.06-0.67-0.36-3.75-0.68-6.86 c-0.32-3.11-0.77-7.63-1-10.03l-0.42-4.35l0.59-0.54c0.53-0.5,0.59-0.51,0.7-0.24C25.55,29.95,25.81,32.46,26.06,35.38L26.06,35.38 L26.06,35.38z M14.74,37.2c0.33,2.98,1.21,10.89,1.96,17.59c0.76,6.69,1.47,13.15,1.6,14.36c0.12,1.21,0.33,3.04,0.45,4.08 c0.21,1.77,0.21,1.89-0.03,2.07c-0.36,0.27-0.51,0.24-0.51-0.08c0-0.14-0.14-1.28-0.3-2.52c-0.27-2.07-0.73-5.58-1.74-13.45 c-0.21-1.59-0.62-4.74-0.91-7.03c-0.3-2.28-0.74-5.68-0.98-7.56c-0.24-1.87-0.65-5.08-0.91-7.15c-0.27-2.05-0.44-3.88-0.39-4.08 c0.11-0.41,1-1.83,1.09-1.74C14.11,31.75,14.41,34.21,14.74,37.2L14.74,37.2L14.74,37.2z M10.12,43.72 c0.23,1.81,0.65,5.12,0.94,7.37c0.29,2.24,0.65,5.03,0.82,6.2l0.29,2.12l-0.32,0.27c-0.18,0.15-0.36,0.21-0.42,0.15 c-0.06-0.06-0.18-0.67-0.27-1.33c-0.09-0.67-0.65-4.55-1.25-8.61l-1.07-7.4l0.35-1.03c0.18-0.56,0.38-1.01,0.42-1.01 C9.65,40.44,9.88,41.92,10.12,43.72L10.12,43.72L10.12,43.72z M93.08,41.74c0.21,0.21,0.24,1.15,0.24,8.08v7.84H92.9 c-0.92,0-0.91,0.23-0.97-8.36l-0.05-7.81h0.48C92.63,41.5,92.96,41.6,93.08,41.74L93.08,41.74z M60,44.44 c3.41,0.51,6.39,1.47,9.34,2.98c1.9,0.98,2.81,1.66,4.93,3.69c3.14,3.01,5.08,5.64,6.89,9.35c2.64,5.41,3.67,10.2,4.97,23.04 c0.59,5.76,1.36,16.2,1.53,20.48c0.05,1.24,0.15,3.28,0.24,4.53c0.17,2.66,0.36,2.3-1.98,3.43c-3.25,1.57-6.38,2.66-10.5,3.67 c-5.05,1.24-8.31,1.63-13.3,1.65l-3.63,0.01l0.03-1.74c0-0.95,0.09-3.17,0.18-4.91c0.45-8.42,0.36-19.04-0.23-24.93 c-0.33-3.38-0.98-7.49-1.35-8.4c-0.08-0.2,0.27-0.36,1.77-0.88c2.74-0.95,5.11-2.15,5.47-2.73c0.65-1.12-0.51-2.72-1.99-2.72 c-0.26,0-1.03,0.27-1.74,0.59c-3.39,1.56-10.17,3.39-14.08,3.79c-2.7,0.29-6.91,0.12-9.82-0.41c-1.59-0.29-4.43-1.36-6.8-2.58 c-2.73-1.42-4.41-3.31-4.91-5.55c-0.27-1.21-0.2-3.63,0.15-4.99c0.38-1.5,1.44-3.67,2.4-4.94c4.31-5.67,13.19-10.58,22.3-12.3 C52.78,44.03,56.89,43.97,60,44.44L60,44.44L60,44.44z M106.62,44.91c0.54,0.23,0.6,0.29,0.6,0.8c0.03,4.13-0.06,13.55-0.14,13.95 c-0.02,0.14-0.8,0.15-1.13,0.03c-0.21-0.08-0.24-0.89-0.24-7.56c0-4.77,0.06-7.46,0.15-7.46 C105.94,44.67,106.29,44.77,106.62,44.91L106.62,44.91z M113.22,53.21l0.54,0.23l-0.11,12.51c-0.12,15.94-0.14,16.41-0.71,17.79 c-0.94,2.25-0.89,2.7-0.8-7.18c0.03-4.94,0.11-9.94,0.14-11.11c0.03-1.16,0.06-4.44,0.08-7.3c0-3.45,0.05-5.17,0.15-5.17 C112.6,52.98,112.92,53.09,113.22,53.21L113.22,53.21z M22.34,56.97c0.09,1.22,0.06,1.35-0.38,2.31l-0.48,1.03L21.3,58.8 c-0.29-2.42-0.29-2.52,0.29-2.89c0.26-0.18,0.53-0.3,0.57-0.27C22.21,55.67,22.3,56.27,22.34,56.97L22.34,56.97z M13.01,66.08 c0.14,1.24,1.19,9.46,1.74,13.49c0.82,6.24,0.88,7.13,0.51,6.75c-0.05-0.05-0.39-2.15-0.76-4.67c-2.36-16.29-2.34-16.18-2.15-16.3 C12.76,65.08,12.9,65.23,13.01,66.08L13.01,66.08L13.01,66.08z M23.89,73c0.09,0.38,0.53,4.47,0.53,4.97 c0,0.42-0.54,0.82-0.79,0.57c-0.08-0.08-0.27-1.36-0.42-2.84c-0.17-1.5-0.33-3.05-0.38-3.46l-0.09-0.76l0.53,0.6 C23.57,72.43,23.84,72.84,23.89,73L23.89,73L23.89,73z M36.08,78.7c0.17,0.15,0.27,0.76,0.41,2.39c0.23,2.95,0.26,2.72-0.36,2.72 c-0.63,0-0.62,0.05-0.83-2.61c-0.21-2.7-0.21-2.67,0.2-2.67C35.69,78.52,35.94,78.61,36.08,78.7L36.08,78.7z M48.05,78.93 c0.03,0.15,0.11,1.06,0.17,2.01c0.05,0.95,0.18,3.1,0.3,4.76c0.42,6.1,0.44,6.88,0.18,6.88c-0.29,0-0.32-0.23-0.65-4.53 c-0.12-1.78-0.35-4.59-0.5-6.24c-0.14-1.65-0.23-3.02-0.18-3.05C47.54,78.56,47.97,78.7,48.05,78.93L48.05,78.93L48.05,78.93z M19.64,81.83c0.09,0.14,0.67,4.97,1.37,11.57c0.21,1.99,0.42,3.91,0.47,4.28l0.08,0.65l-0.38-0.24c-0.29-0.2-0.39-0.39-0.39-0.74 c0-0.95-0.65-7.22-1.15-11.06c-0.29-2.18-0.51-4.09-0.51-4.28C19.13,81.69,19.49,81.57,19.64,81.83L19.64,81.83z M106.85,88.14 l-0.11,6.32l-0.38,0.56c-0.86,1.27-0.82,1.51-0.77-5.56l0.03-6.48l0.56-0.57c0.3-0.3,0.6-0.56,0.67-0.56 C106.89,81.84,106.89,84.68,106.85,88.14L106.85,88.14L106.85,88.14z M92.87,98.16c0.08,8.78,0.06,9.46-0.18,9.73 c-0.15,0.17-0.29,0.27-0.33,0.23c-0.11-0.12-0.26-19.27-0.14-19.37c0.06-0.06,0.21-0.09,0.35-0.08 C92.76,88.72,92.81,89.79,92.87,98.16L92.87,98.16L92.87,98.16z M43.52,92.15c0.11,0.94,0.48,5.42,0.63,7.54 c0.09,1.42,0.09,1.47-0.24,1.57c-0.18,0.06-0.39,0.05-0.45-0.03c-0.11-0.11-0.44-3.46-0.85-8.63l-0.11-1.24h0.47 C43.41,91.36,43.44,91.39,43.52,92.15L43.52,92.15z M31.64,97.44c0.11,0.11,0.18,0.48,0.18,0.86c0,0.39,0.18,2.43,0.38,4.55 c0.57,5.79,0.62,6.57,0.36,6.42c-0.39-0.23-0.74-0.57-0.67-0.67c0.03-0.06-0.03-0.82-0.15-1.68c-0.11-0.88-0.24-2.3-0.3-3.17 c-0.06-0.88-0.2-2.48-0.32-3.55c-0.29-2.64-0.27-2.95,0.06-2.95C31.34,97.25,31.53,97.33,31.64,97.44L31.64,97.44L31.64,97.44z M38.79,107.61c0.05,0.33,0.14,1.57,0.2,2.75c0.11,2.27,0.06,2.43-0.56,1.96c-0.18-0.14-0.3-0.71-0.48-2.43 c-0.32-3.11-0.33-2.99,0.26-2.93C38.63,107,38.7,107.06,38.79,107.61L38.79,107.61L38.79,107.61z\" />\n <path\n fill={color}\n d=\"M33.39,51.68c-1.57,0.68-1.69,2.81-0.21,3.57c1.07,0.54,2.16,0.29,2.72-0.65 C36.96,52.87,35.23,50.88,33.39,51.68L33.39,51.68L33.39,51.68z M43.64,53.13c-1.45,0.89-1.45,3.04,0,3.93 c1.44,0.86,3.29-0.27,3.29-1.99C46.93,53.4,45.03,52.29,43.64,53.13L43.64,53.13z\" />\n </g>\n </svg>\n )\n}\nDenoIcon.displayName = 'DenoIcon'","import React from 'react';\nimport { OpenmspLogo, FlamingoLogo, OpenFrameLogo, MiamiCyberGangLogoFaceOnly } from '../components/icons';\nimport { Globe } from 'lucide-react';\nimport type { SelectableOption } from '../components/features';\nimport type { PlatformConfig } from '../types/platform';\n\n// Platform icons mapping with consistent colors matching app theme\nexport const platformIcons = {\n openframe: <OpenFrameLogo className=\"h-5 w-5\" lowerPathColor=\"#FFC008\" upperPathColor=\"#ffffff\" />,\n openmsp: <OpenmspLogo className=\"h-5 w-5\" />,\n flamingo: <FlamingoLogo className=\"h-5 w-5\" fill=\"#EC4899\" />,\n 'flamingo-teaser': <FlamingoLogo className=\"h-5 w-5\" fill=\"#EC4899\" />,\n 'marketing-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#F357BB\" />,\n 'product-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#5EA62E\" />,\n 'revenue-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#FFC008\" />,\n 'people-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#5EFAF0\" />,\n 'company-hub': <FlamingoLogo className=\"h-5 w-5\" fill=\"#f36666\" />,\n tmcg: <MiamiCyberGangLogoFaceOnly className=\"h-5 w-5\" />,\n universal: <Globe className=\"h-5 w-5 text-[#10B981]\" />\n};\n\n// Platform colors mapping\nexport const platformColors = {\n openmsp: 'bg-[#3B82F6]',\n openframe: 'bg-[#8B5CF6]',\n flamingo: 'bg-[#EC4899]',\n 'flamingo-teaser': 'bg-[#F59E0B]',\n 'marketing-hub': 'bg-[#F357BB]',\n 'product-hub': 'bg-[#5EA62E]',\n 'revenue-hub': 'bg-[#FFC008]',\n 'people-hub': 'bg-[#5EFAF0]',\n 'company-hub': 'bg-[#f36666]',\n tmcg: 'bg-[#FF6B6B]',\n universal: 'bg-[#10B981]'\n};\n\n// Platform display names for consistent naming across the app\nexport const platformDisplayNames = {\n openmsp: 'OpenMSP',\n openframe: 'OpenFrame',\n flamingo: 'Flamingo',\n 'flamingo-teaser': 'Flamingo Teaser',\n 'marketing-hub': 'Flamingo Marketing Hub',\n 'product-hub': 'Flamingo Product Hub',\n 'revenue-hub': 'Flamingo Revenue Hub',\n 'people-hub': 'Flamingo People Hub',\n 'company-hub': 'Flamingo Company Hub',\n tmcg: 'TMCG',\n universal: 'Universal'\n};\n\n// Platform descriptions for consistent messaging across the app\nexport const platformDescriptions = {\n openmsp: 'Comprehensive directory and comparison platform for managed service providers (MSPs) and technology vendors. Reduce vendor costs and discover open-source alternatives.',\n openframe: 'AI-driven open-source security operations center (SOC) and endpoint detection platform for MSPs.',\n flamingo: 'AI-driven open-source OS for MSPs. Swap bloated vendor tools for open ones. Automate the boring crap. Take your margin back.',\n 'flamingo-teaser': 'Preview of Flamingo - the AI-driven open-source OS for MSPs.',\n tmcg: 'The Miami Cyber Gang - A cybersecurity community focused on education and collaboration.',\n universal: 'Cross-platform universal content.'\n};\n\n// Platform slogans for branding consistency\nexport const platformSlogans = {\n openmsp: 'Find Your Perfect MSP Partner',\n openframe: 'Open-Source Security Operations',\n flamingo: 'Open-Source OS for MSPs',\n 'flamingo-teaser': 'Coming Soon: Open-Source OS for MSPs',\n tmcg: 'Miami Cyber Community',\n universal: 'Universal Platform'\n};\n\n// Platform hex colors for default configuration\nexport const platformHexColors = {\n openmsp: '#FFC008',\n openframe: '#FFC008',\n flamingo: '#FF6B9D',\n universal: '#FFC008',\n 'flamingo-teaser': '#F59E0B',\n 'marketing-hub': '#F357BB',\n 'product-hub': '#5EA62E',\n 'revenue-hub': '#FFC008',\n 'people-hub': '#5EFAF0',\n 'company-hub': '#f36666',\n tmcg: '#FF6B6B'\n};\n\n// Platform icon names for default configuration\nexport const platformIconNames = {\n openmsp: 'openmsp-logo',\n openframe: 'openframe-logo',\n flamingo: 'flamingo-logo',\n universal: 'globe',\n 'flamingo-teaser': 'flamingo-logo',\n 'marketing-hub': 'flamingo-logo',\n 'product-hub': 'flamingo-logo',\n 'revenue-hub': 'flamingo-logo',\n 'people-hub': 'flamingo-logo',\n 'company-hub': 'flamingo-logo',\n tmcg: 'tmcg-logo'\n};\n\n/**\n * Get default color for platform\n */\nexport function getDefaultColorForPlatform(platformName: string): string {\n return platformHexColors[platformName as keyof typeof platformHexColors] || platformHexColors.universal;\n}\n\n/**\n * Get default icon name for platform\n */\nexport function getDefaultIconForPlatform(platformName: string): string {\n return platformIconNames[platformName as keyof typeof platformIconNames] || platformIconNames.universal;\n}\n\nexport function transformPlatformConfigsToOptions(platformConfigs: PlatformConfig[]): SelectableOption[] {\n return platformConfigs.map((platform: PlatformConfig) => ({\n id: platform.id, // Database UUID for matching\n name: platform.name, // Platform name enum\n displayName: platform.display_name, // Human-readable name\n description: platform.description,\n icon: platformIcons[platform.name as keyof typeof platformIcons] || platformIcons.universal,\n color: platformColors[platform.name as keyof typeof platformColors] || platformColors.universal\n }));\n}\n\n/**\n * Get platform icon by name\n */\nexport function getPlatformIcon(platformName: string) {\n return platformIcons[platformName as keyof typeof platformIcons] || platformIcons.universal;\n}\n\n/**\n * Get platform color by name\n */\nexport function getPlatformColor(platformName: string) {\n return platformColors[platformName as keyof typeof platformColors] || platformColors.universal;\n}\n\n/**\n * Get platform display name by name\n */\nexport function getPlatformDisplayName(platformName: string): string {\n return platformDisplayNames[platformName as keyof typeof platformDisplayNames] || platformName;\n}\n\n/**\n * Get platform description by name\n */\nexport function getPlatformDescription(platformName: string): string {\n return platformDescriptions[platformName as keyof typeof platformDescriptions] || platformName;\n}\n\n/**\n * Get platform slogan by name\n */\nexport function getPlatformSlogan(platformName: string): string {\n return platformSlogans[platformName as keyof typeof platformSlogans] || platformName;\n}\n\n/**\n * Get small platform icon for filter buttons with white colors (4x4 size)\n */\nexport function getSmallPlatformIcon(platformName: string): React.ReactNode {\n const className = \"h-4 w-4 flex-shrink-0\";\n\n switch (platformName) {\n case 'openframe':\n return <OpenFrameLogo className={className} lowerPathColor=\"#FFC008\" upperPathColor=\"#ffffff\" />;\n case 'openmsp':\n return <OpenmspLogo className={className} frontBubbleColor=\"#f1f1f1\" innerFrontBubbleColor=\"#000000\" backBubbleColor=\"#FFC008\" />;\n case 'flamingo':\n case 'flamingo-teaser':\n return <FlamingoLogo className={`${className}`} fill=\"#EC4899\" />;\n case 'marketing-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-pink-base)\" />;\n case 'product-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-green-success)\" />;\n case 'revenue-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-yellow-warning)\" />;\n case 'people-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-cyan-base)\" />;\n case 'company-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-red-error)\" />;\n case 'tmcg':\n return <MiamiCyberGangLogoFaceOnly className={className} />;\n case 'universal':\n default:\n return <Globe className={className} />;\n }\n}\n\n/**\n * Get platform icon for admin/selector components (standard 6x6 size)\n */\nexport function getPlatformIconComponent(platformName: string, className: string = \"h-6 w-6\"): React.ReactNode {\n switch (platformName) {\n case 'openframe':\n return <OpenFrameLogo className={className} />;\n case 'openmsp':\n return <OpenmspLogo className={className} color=\"#f1f1f1\" />;\n case 'flamingo':\n case 'flamingo-teaser':\n return <FlamingoLogo className={`${className} text-white`} />;\n case 'marketing-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-pink-base)\" />;\n case 'product-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-green-success)\" />;\n case 'revenue-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-yellow-warning)\" />;\n case 'people-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-flamingo-cyan-base)\" />;\n case 'company-hub':\n return <FlamingoLogo className={className} fill=\"var(--ods-attention-red-error)\" />;\n case 'tmcg':\n return <MiamiCyberGangLogoFaceOnly size={24} className={className} />;\n case 'universal':\n default:\n return <Globe className={className} />;\n }\n}","import type { ComponentType } from 'react';\nimport { WindowsIcon, LinuxIcon, MacOSIcon } from '../components/icons';\n\n// OS-level platforms (Windows, Linux, MacOS)\n\nexport type OSPlatformId = 'windows' | 'linux' | 'darwin';\n\nexport interface OSPlatformOption {\n id: OSPlatformId;\n name: string;\n icon: ComponentType<any>;\n}\n\nexport const OS_PLATFORMS: OSPlatformOption[] = [\n { id: 'windows', name: 'Windows', icon: WindowsIcon },\n { id: 'linux', name: 'Linux', icon: LinuxIcon },\n { id: 'darwin', name: 'MacOS', icon: MacOSIcon }\n];\n\nexport const DEFAULT_OS_PLATFORM: OSPlatformId = 'windows';\n\n\n","/**\n * Access Code Client Utilities — pure standalone functions.\n *\n * Endpoint paths are NOT hardcoded — every function takes an\n * `endpoints` argument. The React-side wrapper that binds them from\n * `EndpointsRuntimeContext` lives separately at\n * `hooks/use-access-code-integration.ts` (`useAccessCodeIntegration`).\n *\n * Keep this file **free of React imports** — it lives in the\n * server-safe `utils/index` tsup bundle. Any module-top-level call\n * into `createContext()` (which the runtime context file does) would\n * be pulled into the server bundle and crash SSR with\n * `createContext is not a function`.\n */\n\nimport {\n AccessCodeValidation,\n AccessCodeValidationResponse,\n AccessCodeConsumptionResponse\n} from '../types/access-code-cohorts';\n\n/** Endpoints required by the standalone client utilities. The\n * `useAccessCodeIntegration` hook (in `hooks/`) resolves these from\n * `EndpointsRuntimeContext.accessCode` automatically. */\nexport interface AccessCodeEndpoints {\n validateUrl: string\n consumeUrl: string\n}\n\n/**\n * Validate an access code for a given email\n *\n * @param email - User's email address\n * @param code - Access code to validate\n * @returns Promise with validation result\n *\n * @example\n * const result = await validateAccessCode('user@example.com', 'ABC123XY');\n * if (result.valid) {\n * // Allow user to proceed with registration\n * console.log(`Welcome to ${result.cohort_name}!`);\n * } else {\n * // Show error message\n * console.error(result.message);\n * }\n */\nexport async function validateAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeValidationResponse> {\n try {\n const response = await fetch(endpoints.validateUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email, code } as AccessCodeValidation),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || 'Validation request failed');\n }\n\n return await response.json() as AccessCodeValidationResponse;\n } catch (error) {\n return {\n valid: false,\n message: error instanceof Error ? error.message : 'Validation failed',\n };\n }\n}\n\n/**\n * Consume an access code after successful registration\n *\n * Call this ONLY after the user has successfully completed registration.\n * This marks the code as used and prevents further usage.\n *\n * @param email - User's email address\n * @param code - Access code to consume\n * @returns Promise with consumption result\n *\n * @example\n * // After successful registration\n * const result = await consumeAccessCode('user@example.com', 'ABC123XY');\n * if (result.consumed) {\n * console.log('Access code consumed successfully');\n * } else {\n * console.warn('Failed to consume access code:', result.message);\n * }\n */\nexport async function consumeAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeConsumptionResponse> {\n try {\n const response = await fetch(endpoints.consumeUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ email, code } as AccessCodeValidation),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n throw new Error(error.error || 'Consumption request failed');\n }\n\n return await response.json() as AccessCodeConsumptionResponse;\n } catch (error) {\n return {\n success: false,\n consumed: false,\n message: error instanceof Error ? error.message : 'Consumption failed',\n };\n }\n}\n\n/**\n * Complete access code flow: validate then consume\n *\n * This is a convenience function that validates an access code and,\n * if valid, immediately consumes it. Use this when you want to\n * validate and consume in one step during registration.\n *\n * @param email - User's email address\n * @param code - Access code to validate and consume\n * @returns Promise with validation and consumption results\n *\n * @example\n * const result = await validateAndConsumeAccessCode('user@example.com', 'ABC123XY');\n * if (result.valid && result.consumed) {\n * // Registration successful\n * console.log(`Welcome to ${result.cohort_name}!`);\n * } else {\n * console.error(result.message);\n * }\n */\nexport async function validateAndConsumeAccessCode(\n email: string,\n code: string,\n endpoints: AccessCodeEndpoints,\n): Promise<AccessCodeValidationResponse & { consumed?: boolean }> {\n // First validate\n const validation = await validateAccessCode(email, code, endpoints);\n\n if (!validation.valid) {\n return validation;\n }\n\n // If valid, consume the code\n const consumption = await consumeAccessCode(email, code, endpoints);\n\n return {\n ...validation,\n consumed: consumption.consumed,\n message: consumption.consumed\n ? `Access granted for ${validation.cohort_name}`\n : consumption.message || validation.message,\n };\n}\n\n// `useAccessCodeIntegration` (the React-side wrapper) lives in\n// `hooks/use-access-code-integration.ts`. It binds the endpoints from\n// `EndpointsRuntimeContext` so React callers don't have to plumb URLs.\n","/**\n * Email Domain Validation Utilities\n *\n * Validates email domain formats (the part after @ in email addresses)\n * Used for SSO domain allowlist feature to restrict auto-provisioning to specific domains.\n */\n\n/**\n * Validates an email domain format (the part after @ in email addresses)\n * Valid: example.com, sub.domain.org, my-company.co.uk\n * Invalid: http://example.com, @example.com, example, .com\n *\n * @param domain - The domain string to validate\n * @returns true if the domain is a valid email domain format\n */\nexport function isValidEmailDomain(domain: string): boolean {\n if (!domain || typeof domain !== 'string') {\n return false\n }\n\n const trimmed = domain.trim()\n if (!trimmed) {\n return false\n }\n\n // Domain regex: must have at least one dot, valid characters, and proper TLD\n // Allows subdomains, hyphens (not at start/end of labels), alphanumeric characters\n const domainRegex = /^(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\\.[A-Za-z0-9-]{1,63})*\\.[A-Za-z]{2,}$/\n return domainRegex.test(trimmed)\n}\n\n/**\n * Validation result type\n */\nexport interface EmailDomainValidationResult {\n valid: boolean\n error?: string\n cleanedDomain?: string\n}\n\n/**\n * Validates an email domain with detailed error messages\n * Also cleans the input (removes leading @, trims whitespace)\n *\n * @param domain - The domain string to validate\n * @returns Validation result with error message if invalid\n */\nexport function validateEmailDomain(domain: string): EmailDomainValidationResult {\n if (!domain || typeof domain !== 'string') {\n return { valid: false, error: 'Email domain is required' }\n }\n\n // Clean the input: trim and remove leading @ if user enters it\n let trimmed = domain.trim()\n if (trimmed.startsWith('@')) {\n trimmed = trimmed.substring(1)\n }\n\n // Check for empty after cleaning\n if (!trimmed) {\n return { valid: false, error: 'Email domain is required' }\n }\n\n // Check for protocol (common mistake: entering full URL)\n if (trimmed.includes('://')) {\n return { valid: false, error: 'Enter email domain only (e.g., openframe.ai), not a URL' }\n }\n\n // Check for @ symbol (common mistake: entering full email address)\n if (trimmed.includes('@')) {\n return { valid: false, error: 'Enter domain only, not a full email address' }\n }\n\n // Check for spaces\n if (trimmed.includes(' ')) {\n return { valid: false, error: 'Domain cannot contain spaces' }\n }\n\n // Check for trailing slash\n if (trimmed.includes('/')) {\n return { valid: false, error: 'Enter domain only, without paths' }\n }\n\n // Validate the domain format\n if (!isValidEmailDomain(trimmed)) {\n return { valid: false, error: 'Invalid domain format (e.g., openframe.ai)' }\n }\n\n // Return success with the cleaned domain\n return { valid: true, cleanedDomain: trimmed.toLowerCase() }\n}\n\n/**\n * Validates a list of email domains\n * Returns the first error encountered or success if all domains are valid\n *\n * @param domains - Array of domain strings to validate\n * @returns Validation result with array of cleaned domains if valid\n */\nexport function validateEmailDomainList(domains: string[]): {\n valid: boolean\n error?: string\n cleanedDomains?: string[]\n} {\n if (!Array.isArray(domains)) {\n return { valid: false, error: 'Domains must be an array' }\n }\n\n const cleanedDomains: string[] = []\n const seenDomains = new Set<string>()\n\n for (const domain of domains) {\n const result = validateEmailDomain(domain)\n\n if (!result.valid) {\n return { valid: false, error: `Invalid domain \"${domain}\": ${result.error}` }\n }\n\n const cleanedDomain = result.cleanedDomain!\n\n // Check for duplicates (case-insensitive)\n if (seenDomains.has(cleanedDomain)) {\n return { valid: false, error: `Duplicate domain: ${cleanedDomain}` }\n }\n\n seenDomains.add(cleanedDomain)\n cleanedDomains.push(cleanedDomain)\n }\n\n return { valid: true, cleanedDomains }\n}\n\n/**\n * Cleans a domain string by removing common user input mistakes\n * Does NOT validate - use validateEmailDomain for validation\n *\n * @param domain - The domain string to clean\n * @returns Cleaned domain string\n */\nexport function cleanEmailDomain(domain: string): string {\n if (!domain || typeof domain !== 'string') {\n return ''\n }\n\n let cleaned = domain.trim().toLowerCase()\n\n // Remove leading @\n if (cleaned.startsWith('@')) {\n cleaned = cleaned.substring(1)\n }\n\n // Remove protocol if present\n cleaned = cleaned.replace(/^https?:\\/\\//, '')\n\n // Remove trailing slash and path\n cleaned = cleaned.split('/')[0]\n\n // Remove www. prefix\n cleaned = cleaned.replace(/^www\\./, '')\n\n return cleaned\n}\n","/**\n * Confidence helpers for AI enrichment\n * Shared utilities for displaying confidence levels from AI operations\n */\n\n/**\n * Get Tailwind CSS classes for confidence badge display (border and text color)\n * @param confidence - Confidence score (0-100)\n * @returns CSS classes for border and text color\n */\nexport function getConfidenceColorClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'border-green-500 text-green-500';\n if (confidence >= 50) return 'border-yellow-500 text-yellow-500';\n return 'border-red-500 text-red-500';\n}\n\n/**\n * Get confidence level category\n * @param confidence - Confidence score (0-100)\n * @returns Confidence level category\n */\nexport function getConfidenceLevel(confidence?: number): 'high' | 'medium' | 'low' | 'none' {\n if (!confidence && confidence !== 0) return 'none';\n if (confidence >= 80) return 'high';\n if (confidence >= 50) return 'medium';\n return 'low';\n}\n\n/**\n * Get Tailwind CSS class for border color only\n * @param confidence - Confidence score (0-100)\n * @returns CSS class for border color\n */\nexport function getConfidenceBorderClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'border-green-500';\n if (confidence >= 50) return 'border-yellow-500';\n return 'border-red-500';\n}\n\n/**\n * Get Tailwind CSS class for text color only\n * @param confidence - Confidence score (0-100)\n * @returns CSS class for text color\n */\nexport function getConfidenceTextClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'text-green-500';\n if (confidence >= 50) return 'text-yellow-500';\n return 'text-red-500';\n}\n\n/**\n * Get Tailwind CSS class for background color (subtle)\n * @param confidence - Confidence score (0-100)\n * @returns CSS class for subtle background color\n */\nexport function getConfidenceBgClass(confidence?: number): string {\n if (!confidence && confidence !== 0) return '';\n if (confidence >= 80) return 'bg-green-500/10';\n if (confidence >= 50) return 'bg-yellow-500/10';\n return 'bg-red-500/10';\n}\n\n/**\n * Get descriptive label for confidence level\n * @param confidence - Confidence score (0-100)\n * @returns Human-readable confidence label\n */\nexport function getConfidenceLabel(confidence?: number): string {\n if (!confidence && confidence !== 0) return 'Unknown';\n if (confidence >= 80) return 'High';\n if (confidence >= 50) return 'Medium';\n return 'Low';\n}\n","/**\n * Shared Date Formatting Utilities\n * Single source of truth for date formatting across the application\n */\n\nconst MONTHS_LONG = [\n 'January', 'February', 'March', 'April', 'May', 'June',\n 'July', 'August', 'September', 'October', 'November', 'December',\n] as const\n\nconst MONTHS_SHORT = [\n 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',\n 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',\n] as const\n\n/**\n * Split an ISO date / date-time string into `[year, month, day]` strings.\n * Internal — date-only inputs avoid the `new Date(...)` timezone shift\n * (which renders `\"2025-11-11\"` as Nov 10 west of UTC).\n */\nfunction splitYmd(dateString: string): [string, string, string] | null {\n const head = dateString.split('T')[0]\n const parts = head.split('-')\n if (parts.length !== 3) return null\n return [parts[0], parts[1], parts[2]]\n}\n\n/**\n * Format release date — avoids timezone shifts.\n * @returns e.g. `\"November 11, 2025\"`\n */\nexport function formatReleaseDate(dateString: string): string {\n const ymd = splitYmd(dateString)\n if (!ymd) return dateString\n const [year, month, day] = ymd\n return `${MONTHS_LONG[parseInt(month) - 1]} ${parseInt(day)}, ${year}`\n}\n\n/**\n * Short-form date — `\"Jan 5, 2025\"`. Same TZ-safe parsing as\n * `formatReleaseDate`; differs only in month abbreviation. Single source\n * of truth for the short-month-day-year shape used across hub admin\n * cards (waitlist, publication, media, investor, campaign, etc.) and\n * lib chat cards (campaign-card-admin).\n */\nexport function formatDateShort(dateString: string): string {\n const ymd = splitYmd(dateString)\n if (!ymd) return dateString\n const [year, month, day] = ymd\n return `${MONTHS_SHORT[parseInt(month) - 1]} ${parseInt(day)}, ${year}`\n}\n\n/**\n * Slash-form date — `\"11/11/2025\"`. TZ-safe (string-split, no\n * `new Date(...)`). Used by hub admin product-release + customer-\n * interview cards where the compact MM/DD/YYYY layout is desired.\n */\nexport function formatDateSlashUTC(dateString: string): string {\n const ymd = splitYmd(dateString)\n if (!ymd) return dateString\n const [year, month, day] = ymd\n return `${month}/${day}/${year}`\n}\n","/**\n * Icon registry — string `icon_name` → React component.\n *\n * SINGLE SOURCE OF TRUTH (no, really this time) for every icon-name →\n * React-component lookup across the lib + the hub. Two DB columns feed\n * in with DIFFERENT conventions:\n *\n * - `chat_admin_slash_commands.icon_name` — kebab-case (`'rocket'`,\n * `'hubspot'`, `'github'`, `'dollar-sign'`).\n * - `social_platforms.icon_name` — PascalCase component names\n * (`'LinkedInIcon'`, `'XLogo'`, `'YouTubeIcon'`, `'Github'`).\n *\n * The registry stores entries under kebab-case keys (URL/DB-friendly,\n * shell-safe, matches `lucide-react`'s own file-naming convention).\n * The PascalCase variants come in via `normalizeIconKey()`, which maps\n * known PascalCase aliases → kebab-case before the lookup runs.\n *\n * Adding a new icon: import the component below, add a `'name': Component`\n * entry in `ICON_REGISTRY`, and (if the same icon also flows in from a DB\n * column that uses PascalCase) add a `PascalName → 'name'` row to\n * `PASCAL_TO_KEBAB_ALIASES`.\n *\n * Fallback: an unknown / null icon_name resolves to `FileText` so a chip\n * never renders without an icon.\n */\n\nimport { createElement, type ComponentType, type ReactNode } from 'react'\nimport {\n Activity,\n Banknote,\n Bell,\n BookOpen,\n Box,\n Briefcase,\n Calendar,\n CheckSquare,\n DollarSign,\n Facebook,\n FileText,\n Github,\n Globe,\n GraduationCap,\n Headphones,\n Info,\n Instagram,\n Mail,\n Megaphone,\n MessageCircle,\n MessageSquare,\n Newspaper,\n Package,\n PenSquare,\n Rocket,\n Search,\n Send,\n Shield,\n Star,\n TableProperties,\n TrendingUp,\n Twitter,\n Users,\n Video,\n Youtube,\n} from 'lucide-react'\n// Brand icons — lib-local exports.\nimport {\n SlackIcon,\n GitHubIcon,\n ClickUpIcon,\n HubspotIcon,\n LinkedInIcon,\n FacebookIcon,\n InstagramIcon,\n YouTubeIcon,\n XLogo,\n OpenFrameLogo as RawOpenFrameLogo,\n} from '../../icons'\n\n// Wrapper so the OpenFrame logo's outer frame inherits the parent's text\n// color instead of its hardcoded default — that default is invisible on\n// dark chat surfaces. The white squares stay white (visible on dark).\n// With this, the parent's `text-ods-text-primary` propagates via\n// `currentColor` and the frame renders in the same primary text color\n// as the lucide icons next to it. Uses `createElement` (not JSX) so this\n// stays a `.ts` file. Accepts `color` for shape-compat with the registry's\n// IconComponent type, but ignores it — the logo's outer frame is wired\n// to `currentColor` via the upperPathColor pass-through.\nconst OpenFrameLogoIcon: ComponentType<{ className?: string; color?: string }> = ({ className }) =>\n createElement(RawOpenFrameLogo, { className, upperPathColor: 'currentColor' })\n\n/**\n * Loose icon-component shape: every entry accepts `className`; `color` is\n * optional (lucide + most brand icons accept it; OpenFrameLogo doesn't,\n * but `color` is optional so passing `undefined` is a no-op). Loose enough\n * to accept both lucide's `LucideIcon` and our brand SVG components.\n */\ntype IconComponent = ComponentType<{ className?: string; color?: string }>\n\n/**\n * The kebab-case registry. ALL lookups go through here; PascalCase\n * aliases route through `normalizeIconKey()` first.\n */\nexport const ICON_REGISTRY: Record<string, IconComponent> = {\n // lucide-react (kebab-case)\n activity: Activity,\n banknote: Banknote,\n bell: Bell,\n 'book-open': BookOpen,\n box: Box,\n briefcase: Briefcase,\n calendar: Calendar,\n 'check-square': CheckSquare,\n 'dollar-sign': DollarSign,\n // For brand-vs-lucide variants the kebab key is the BRAND (most-common\n // social-platform intent); `'<name>-lucide'` carries the lucide outline.\n facebook: FacebookIcon,\n 'facebook-lucide': Facebook,\n 'file-text': FileText,\n // `'github-lucide'` is the lucide outline glyph (used by\n // `social_platforms.icon_name='Github'`); `'github'` is the brand icon\n // (used by `chat_admin_slash_commands.icon_name='github'`). The PascalCase\n // alias `'Github' → 'github-lucide'` routes the lucide glyph for\n // social-platform DB rows; `'GitHubIcon' → 'github'` keeps brand routing\n // consistent for callers that store the PascalCase component name.\n github: GitHubIcon,\n 'github-lucide': Github,\n globe: Globe,\n 'graduation-cap': GraduationCap,\n headphones: Headphones,\n info: Info,\n instagram: InstagramIcon,\n 'instagram-lucide': Instagram,\n mail: Mail,\n megaphone: Megaphone,\n 'message-circle': MessageCircle,\n 'message-square': MessageSquare,\n newspaper: Newspaper,\n package: Package,\n 'pen-square': PenSquare,\n rocket: Rocket,\n search: Search,\n send: Send,\n shield: Shield,\n star: Star,\n table: TableProperties,\n 'trending-up': TrendingUp,\n twitter: Twitter,\n users: Users,\n video: Video,\n youtube: YouTubeIcon,\n 'youtube-lucide': Youtube,\n // brand-only icons (no lucide variant in current use)\n slack: SlackIcon,\n clickup: ClickUpIcon,\n hubspot: HubspotIcon,\n linkedin: LinkedInIcon,\n x: XLogo,\n openframe: OpenFrameLogoIcon,\n}\n\n/**\n * PascalCase → kebab-case alias table for DB columns that store icon\n * names as component identifiers (currently `social_platforms.icon_name`).\n * Keep these in sync with the actual rows in those tables.\n */\nconst PASCAL_TO_KEBAB_ALIASES: Record<string, string> = {\n // Lucide PascalCase names → kebab equivalents\n Activity: 'activity',\n Banknote: 'banknote',\n Bell: 'bell',\n BookOpen: 'book-open',\n Box: 'box',\n Briefcase: 'briefcase',\n Calendar: 'calendar',\n CheckSquare: 'check-square',\n DollarSign: 'dollar-sign',\n // Lucide PascalCase → the `-lucide` kebab variant (kebab default is the\n // brand icon for the social-platform names below).\n Facebook: 'facebook-lucide',\n FileText: 'file-text',\n Github: 'github-lucide',\n Globe: 'globe',\n GraduationCap: 'graduation-cap',\n Headphones: 'headphones',\n Info: 'info',\n Instagram: 'instagram-lucide',\n Mail: 'mail',\n Megaphone: 'megaphone',\n MessageCircle: 'message-circle',\n MessageSquare: 'message-square',\n Newspaper: 'newspaper',\n Package: 'package',\n PenSquare: 'pen-square',\n Rocket: 'rocket',\n Search: 'search',\n Send: 'send',\n Shield: 'shield',\n Star: 'star',\n TableProperties: 'table',\n TrendingUp: 'trending-up',\n Twitter: 'twitter',\n Users: 'users',\n Video: 'video',\n Youtube: 'youtube-lucide',\n // Brand-icon PascalCase exports → kebab (kebab default is the brand)\n SlackIcon: 'slack',\n GitHubIcon: 'github',\n ClickUpIcon: 'clickup',\n HubspotIcon: 'hubspot',\n LinkedInIcon: 'linkedin',\n FacebookIcon: 'facebook',\n InstagramIcon: 'instagram',\n YouTubeIcon: 'youtube',\n XLogo: 'x',\n OpenFrameLogo: 'openframe',\n}\n\n/**\n * Normalize an icon key to the registry's canonical kebab-case form.\n * Accepts PascalCase variants (from `social_platforms.icon_name`-style\n * columns) and passes kebab-case keys through unchanged.\n */\nexport function normalizeIconKey(key: string): string {\n return PASCAL_TO_KEBAB_ALIASES[key] ?? key\n}\n\n/**\n * Resolve an `icon_name` to its React component. Accepts both PascalCase\n * and kebab-case keys (normalizes PascalCase first). Unknown / null /\n * undefined names fall back to `FileText` — chips always render with\n * SOMETHING rather than a missing glyph. The fallback is intentional:\n * a typo in a new admin-authored row shouldn't crash render.\n */\nexport function getIconComponent(\n iconName: string | null | undefined,\n): ComponentType<{ className?: string; color?: string }> {\n if (!iconName) return FileText\n return ICON_REGISTRY[normalizeIconKey(iconName)] ?? FileText\n}\n\n// ---------------------------------------------------------------------------\n// Sized-icon rendering helper (migrated from `src/utils/dynamic-icons.tsx`)\n// ---------------------------------------------------------------------------\n\nexport type DynamicIconSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'\n\nconst SIZE_CLASSES: Record<DynamicIconSize, string> = {\n xs: 'w-3 h-3', // 12px\n sm: 'w-4 h-4', // 16px\n md: 'w-6 h-6', // 24px\n lg: 'w-8 h-8', // 32px\n xl: 'w-12 h-12', // 48px\n}\n\n/**\n * Optional per-icon color overrides. Keys are kebab-case (canonical\n * registry form) — pass any incoming key through `normalizeIconKey()`\n * before lookup.\n */\nconst ICON_COLORS: Record<string, { color?: string; fill?: string }> = {\n linkedin: { color: '#0A66C2' },\n facebook: { color: '#1877F2' },\n youtube: { color: '#FF0000' },\n}\n\n/**\n * Render an icon by name with a size preset + optional className.\n * Replaces the old `src/utils/dynamic-icons.tsx#getDynamicIcon`. Accepts\n * both PascalCase and kebab-case keys (via `normalizeIconKey()`).\n */\nexport function getDynamicIcon(\n iconName: string | undefined | null,\n size: DynamicIconSize = 'md',\n className?: string,\n): ReactNode {\n if (!iconName) {\n console.warn('[getDynamicIcon] No iconName provided, using Globe fallback')\n return createElement(Globe, { className: SIZE_CLASSES[size] })\n }\n\n const sizeClass = SIZE_CLASSES[size]\n const finalClassName = className ? `${sizeClass} ${className}` : sizeClass\n\n const canonicalKey = normalizeIconKey(iconName)\n const IconComponent = ICON_REGISTRY[canonicalKey]\n\n if (IconComponent) {\n const colorConfig = ICON_COLORS[canonicalKey] || {}\n return createElement(IconComponent, { className: finalClassName, ...colorConfig })\n }\n\n console.error(\n `[getDynamicIcon] Icon NOT found in registry: \"${iconName}\" (normalized to \"${canonicalKey}\"). Available icons:`,\n Object.keys(ICON_REGISTRY),\n )\n return createElement(Globe, { className: finalClassName })\n}\n","/**\n * Centralized Tool Types\n *\n * Single source of truth for all tool-related types across the entire platform.\n * Used by ToolBadge, ToolIcon, and any component that needs tool type information.\n */\n\nexport const ToolTypeValues = {\n TACTICAL_RMM: 'TACTICAL_RMM',\n FLEET_MDM: 'FLEET_MDM',\n MESHCENTRAL: 'MESHCENTRAL',\n AUTHENTIK: 'AUTHENTIK',\n OPENFRAME: 'OPENFRAME',\n OPENFRAME_CHAT: 'OPENFRAME_CHAT',\n OPENFRAME_CLIENT: 'OPENFRAME_CLIENT',\n OSQUERY: 'OSQUERY',\n SYSTEM: 'SYSTEM'\n} as const\n\nexport type ToolType = (typeof ToolTypeValues)[keyof typeof ToolTypeValues]\n\n/**\n * Maps tool types to display labels\n */\nexport const toolLabels: Record<ToolType, string> = {\n TACTICAL_RMM: 'Tactical',\n FLEET_MDM: 'Fleet',\n MESHCENTRAL: 'MeshCentral',\n AUTHENTIK: 'Authentik',\n OPENFRAME: 'OpenFrame',\n OPENFRAME_CHAT: 'OpenFrame Chat',\n OPENFRAME_CLIENT: 'OpenFrame Client',\n OSQUERY: 'Osquery',\n SYSTEM: 'System'\n}\n","/**\n * Tool Utilities\n *\n * Provides normalization and conversion utilities for tool types.\n * Handles various input formats (aliases, case variations) and converts\n * them to the canonical ToolType used throughout the platform.\n */\n\nimport { ToolType, toolLabels } from '../types/tool.types'\n\n/**\n * Map of common tool name variants to canonical ToolType\n */\nconst toolAliasMap: Record<string, ToolType> = {\n // Tactical RMM\n 'TACTICAL': 'TACTICAL_RMM',\n 'TACTICAL_RMM': 'TACTICAL_RMM',\n 'TACTICAL-RMM': 'TACTICAL_RMM',\n 'TACTICALRMM': 'TACTICAL_RMM',\n 'tactical': 'TACTICAL_RMM',\n 'tactical_rmm': 'TACTICAL_RMM',\n 'tactical-rmm': 'TACTICAL_RMM',\n 'tacticalrmm': 'TACTICAL_RMM',\n 'tacticalrmm-agent': 'TACTICAL_RMM',\n\n // Fleet MDM\n 'FLEET': 'FLEET_MDM',\n 'FLEET_MDM': 'FLEET_MDM',\n 'FLEET-MDM': 'FLEET_MDM',\n 'FLEETMDM': 'FLEET_MDM',\n 'fleet': 'FLEET_MDM',\n 'fleet_mdm': 'FLEET_MDM',\n 'fleet-mdm': 'FLEET_MDM',\n 'fleetmdm': 'FLEET_MDM',\n 'fleetmdm-agent': 'FLEET_MDM',\n\n // MeshCentral\n 'MESHCENTRAL': 'MESHCENTRAL',\n 'MESH': 'MESHCENTRAL',\n 'MESH_CENTRAL': 'MESHCENTRAL',\n 'MESH-CENTRAL': 'MESHCENTRAL',\n 'mesh': 'MESHCENTRAL',\n 'meshcentral': 'MESHCENTRAL',\n 'mesh_central': 'MESHCENTRAL',\n 'mesh-central': 'MESHCENTRAL',\n 'meshcentral-agent': 'MESHCENTRAL',\n\n // Authentik\n 'AUTHENTIK': 'AUTHENTIK',\n 'authentik': 'AUTHENTIK',\n\n // OpenFrame\n 'OPENFRAME': 'OPENFRAME',\n 'openframe': 'OPENFRAME',\n 'OPEN_FRAME': 'OPENFRAME',\n 'OPEN-FRAME': 'OPENFRAME',\n 'open_frame': 'OPENFRAME',\n 'open-frame': 'OPENFRAME',\n\n // OpenFrame Chat\n 'OPENFRAME_CHAT': 'OPENFRAME_CHAT',\n 'OPENFRAME-CHAT': 'OPENFRAME_CHAT',\n 'OPENFRAMECHAT': 'OPENFRAME_CHAT',\n 'openframe_chat': 'OPENFRAME_CHAT',\n 'openframe-chat': 'OPENFRAME_CHAT',\n 'openframechat': 'OPENFRAME_CHAT',\n\n // OpenFrame Client\n 'OPENFRAME_CLIENT': 'OPENFRAME_CLIENT',\n 'OPENFRAME-CLIENT': 'OPENFRAME_CLIENT',\n 'OPENFRAMECLIENT': 'OPENFRAME_CLIENT',\n 'openframe_client': 'OPENFRAME_CLIENT',\n 'openframe-client': 'OPENFRAME_CLIENT',\n 'openframeclient': 'OPENFRAME_CLIENT',\n\n // OSQUERY\n 'OSQUERY': 'OSQUERY',\n\n // System\n 'SYSTEM': 'SYSTEM',\n 'system': 'SYSTEM',\n}\n\n/**\n * Normalizes a tool name string to the canonical ToolType.\n * Handles various formats like 'tactical', 'TACTICAL_RMM', 'tactical-rmm', etc.\n *\n * @param input - The tool name string to normalize\n * @returns The canonical ToolType, or undefined if no match found\n *\n * @example\n * normalizeToolType('tactical') // => 'TACTICAL_RMM'\n * normalizeToolType('FLEET-MDM') // => 'FLEET_MDM'\n * normalizeToolType('unknown') // => undefined\n */\nexport function normalizeToolType(input?: string): ToolType | undefined {\n if (!input) return undefined\n\n // Try exact match first\n const exact = toolAliasMap[input]\n if (exact) return exact\n\n // Try uppercase\n const upper = input.toUpperCase()\n if (toolAliasMap[upper]) return toolAliasMap[upper]\n\n // Try lowercase\n const lower = input.toLowerCase()\n if (toolAliasMap[lower]) return toolAliasMap[lower]\n\n return undefined\n}\n\n/**\n * Normalizes a tool name string to the canonical ToolType with a fallback.\n * Returns 'SYSTEM' as the default if no match is found.\n *\n * @param input - The tool name string to normalize\n * @returns The canonical ToolType, defaults to 'SYSTEM' if no match\n *\n * @example\n * normalizeToolTypeWithFallback('tactical') // => 'TACTICAL_RMM'\n * normalizeToolTypeWithFallback('unknown') // => 'SYSTEM'\n */\nexport function normalizeToolTypeWithFallback(input?: string): ToolType {\n return normalizeToolType(input) ?? 'SYSTEM'\n}\n\n/**\n * Converts any tool name variant to its display label.\n * Handles normalization internally.\n *\n * @param input - The tool name string (any format)\n * @returns The display label, or the original input if no match\n *\n * @example\n * toToolLabel('tactical') // => 'Tactical'\n * toToolLabel('FLEET-MDM') // => 'Fleet'\n * toToolLabel('unknown') // => 'unknown'\n */\nexport function toToolLabel(input?: string): string {\n if (!input) return ''\n\n const toolType = normalizeToolType(input)\n if (toolType) {\n return toolLabels[toolType]\n }\n\n return input\n}\n\n/**\n * Checks if a string is a valid tool type (or can be normalized to one).\n *\n * @param input - The string to check\n * @returns True if the input can be normalized to a valid ToolType\n *\n * @example\n * isValidToolType('tactical') // => true\n * isValidToolType('FLEET_MDM') // => true\n * isValidToolType('unknown') // => false\n */\nexport function isValidToolType(input?: string): boolean {\n return normalizeToolType(input) !== undefined\n}\n\n/**\n * Gets all valid tool type aliases for a given canonical ToolType.\n * Useful for documentation or validation purposes.\n *\n * @param toolType - The canonical ToolType\n * @returns Array of all aliases that map to this tool type\n */\nexport function getToolTypeAliases(toolType: ToolType): string[] {\n return Object.entries(toolAliasMap)\n .filter(([_, value]) => value === toolType)\n .map(([key]) => key)\n}\n\n/**\n * Get display label for a tool type\n */\nexport function getToolLabel(toolType: ToolType): string {\n return toolLabels[toolType] || toolType\n}\n","import type { SVGProps } from \"react\";\nexport interface PowershellLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function PowershellLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: PowershellLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill=\"#2671BE\"\n fillRule=\"evenodd\"\n d=\"M10.274 19.708c-2.345 0-4.69.01-7.034-.005-1.19-.008-1.405-.287-1.138-1.442.908-3.919 1.844-7.83 2.732-11.754C5.07 5.455 5.584 4.99 6.719 5c4.69.043 9.379.014 14.068.019 1.176 0 1.374.25 1.11 1.436-.857 3.848-1.72 7.694-2.598 11.537-.328 1.438-.707 1.713-2.23 1.716-2.265.005-4.53.001-6.795 0\"\n clipRule=\"evenodd\"\n />\n <path\n fill=\"#FDFDFE\"\n fillRule=\"evenodd\"\n d=\"M12.269 12.029c-.157-.184-.33-.395-.513-.596-1.036-1.144-2.063-2.297-3.118-3.423C8.155 7.494 8 6.993 8.58 6.484c.573-.503 1.136-.458 1.661.12 1.464 1.612 2.925 3.225 4.413 4.815.556.593.426.997-.185 1.437a942 942 0 0 0-7.016 5.106c-.524.385-1.024.481-1.448-.087-.467-.626-.035-1 .45-1.35a759 759 0 0 0 5.186-3.782c.24-.177.584-.28.627-.714\"\n clipRule=\"evenodd\"\n />\n <path\n fill=\"#FCFDFD\"\n fillRule=\"evenodd\"\n d=\"M13.011 18.09c-.631 0-1.263.02-1.893-.008-.502-.022-.805-.301-.799-.827.006-.497.259-.871.76-.885a90 90 0 0 1 4.142-.002c.439.009.763.293.76.747-.003.52-.279.925-.84.958-.708.043-1.42.01-2.13.01z\"\n clipRule=\"evenodd\"\n />\n </svg>\n );\n}\n","import type { SVGProps } from \"react\";\nexport interface PythonLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function PythonLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: PythonLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"M11.966 2C7.244 2 7.193 3.833 7.193 4.21V6.5h4.864v.687H5.26C3.816 7.187 2 8.067 2 11.96c0 3.577 1.417 4.96 2.847 4.96h1.698v-2.386c0-.998.495-2.847 2.802-2.847h4.823c.71 0 2.71-.308 2.71-2.619V4.665C16.88 4.09 16.784 2 11.967 2M9.284 3.54a.874.874 0 1 1 0 1.75.874.874 0 1 1 0-1.75\"\n />\n <path\n fill={color}\n d=\"M12.034 22c4.72 0 4.778-1.867 4.778-2.21V17.5h-4.869v-.687h6.795c1.457 0 3.262-.901 3.262-4.773 0-4.24-1.916-4.96-2.847-4.96h-1.699v2.386c0 .998-.478 2.847-2.8 2.847H9.828c-.707 0-2.71.344-2.71 2.619v4.403c0 .951.581 2.665 4.915 2.665m2.682-1.54a.874.874 0 1 1-.002-1.748.874.874 0 0 1 .002 1.748\"\n />\n </svg>\n );\n}\n","/**\n * Centralized Shell Types\n *\n * Single source of truth for all shell/script type information across the platform.\n * Based on Tactical RMM supported shell types.\n */\nimport { PowershellLogoIcon } from '../components/icons-v2-generated/brand-logos/powershell-logo-icon'\nimport { PythonLogoIcon } from '../components/icons-v2-generated/brand-logos/python-logo-icon'\nimport {\n BashIcon,\n CmdIcon,\n DenoIcon,\n NushellIcon,\n ShellIcon\n} from '../components/icons'\nimport type { IconProps } from './icons'\n\n\n\nexport const ShellTypeValues = {\n POWERSHELL: 'POWERSHELL',\n CMD: 'CMD',\n BASH: 'BASH',\n PYTHON: 'PYTHON',\n NUSHELL: 'NUSHELL',\n DENO: 'DENO',\n SHELL: 'SHELL'\n} as const\n\nexport type ShellType = (typeof ShellTypeValues)[keyof typeof ShellTypeValues]\n\n/**\n * Shell type definition with all metadata\n */\nexport interface ShellTypeDefinition {\n id: ShellType\n label: string\n value: string\n icon: React.ComponentType<IconProps>\n}\n\n/**\n * Complete list of all shell types with icons and labels\n * SINGLE SOURCE OF TRUTH - Use this everywhere\n */\nexport const SHELL_TYPES: ShellTypeDefinition[] = [\n { id: ShellTypeValues.POWERSHELL, label: 'PowerShell', value: 'powershell', icon: PowershellLogoIcon },\n { id: ShellTypeValues.CMD, label: 'Batch', value: 'cmd', icon: CmdIcon },\n { id: ShellTypeValues.BASH, label: 'Bash', value: 'bash', icon: BashIcon },\n { id: ShellTypeValues.PYTHON, label: 'Python', value: 'python', icon: PythonLogoIcon },\n { id: ShellTypeValues.NUSHELL, label: 'Nu', value: 'nushell', icon: NushellIcon },\n { id: ShellTypeValues.DENO, label: 'Deno', value: 'deno', icon: DenoIcon },\n { id: ShellTypeValues.SHELL, label: 'Shell', value: 'shell', icon: ShellIcon },\n]\n\n/**\n * Maps shell types to display labels\n */\nexport const shellLabels: Record<ShellType, string> = {\n [ShellTypeValues.POWERSHELL]: 'PowerShell',\n [ShellTypeValues.CMD]: 'Batch',\n [ShellTypeValues.BASH]: 'Bash',\n [ShellTypeValues.PYTHON]: 'Python',\n [ShellTypeValues.NUSHELL]: 'Nu',\n [ShellTypeValues.DENO]: 'Deno',\n [ShellTypeValues.SHELL]: 'Shell'\n}\n","/**\n * Shell Type Utilities\n *\n * Helper functions for working with shell types.\n */\n\nimport React from 'react'\nimport { ShellType, SHELL_TYPES, shellLabels } from '../types/shell.types'\n\n/**\n * Get display label for a shell type\n */\nexport function getShellLabel(shellType?: string): string {\n if (!shellType) return 'Unknown'\n const normalized = shellType.toUpperCase() as ShellType\n return shellLabels[normalized] || shellType\n}\n\n/**\n * Get icon component for a shell type\n */\nexport function getShellIcon(shellType?: string): React.ComponentType<{ className?: string }> | undefined {\n if (!shellType) return undefined\n const normalized = shellType.toUpperCase() as ShellType\n const shellDef = SHELL_TYPES.find(s => s.id === normalized)\n return shellDef?.icon\n}\n","import type { SVGProps } from \"react\";\nexport interface AppleLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function AppleLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: AppleLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"M17.57 12.628c-.024-2.531 2.062-3.747 2.156-3.805-1.174-1.72-2.999-1.957-3.649-1.983-1.552-.16-3.03.917-3.82.917s-2.005-.895-3.293-.869c-1.694.024-3.257.987-4.13 2.507-1.758 3.054-.448 7.59 1.268 10.073.84 1.213 1.837 2.581 3.151 2.53 1.266-.05 1.743-.82 3.269-.82s1.957.82 3.293.796c1.36-.026 2.222-1.24 3.054-2.458.958-1.411 1.356-2.775 1.38-2.847-.032-.012-2.65-1.018-2.68-4.041M15.06 5.194c.697-.846 1.167-2.021 1.039-3.194-1.004.041-2.22.67-2.94 1.518-.644.748-1.21 1.944-1.056 3.093 1.115.086 2.26-.572 2.956-1.417\"\n />\n </svg>\n );\n}\n","import type { SVGProps } from \"react\";\nexport interface LinuxLogoIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function LinuxLogoIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: LinuxLogoIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"M19.567 18.314c-.528-.217-.963-.558-.931-1.213.03-.653-.467-1.086-.467-1.086s.435-1.43.031-2.612c-.403-1.183-1.737-3.078-2.76-4.507-1.023-1.43-.155-3.08-1.085-5.192-.932-2.113-3.351-1.99-4.654-1.087-1.304.9-.901 3.137-.84 4.196.062 1.056.028 1.808-.092 2.082-.123.273-.961 1.276-1.52 2.114-.559.84-.962 2.58-1.367 3.295-.403.715-.124 1.368-.124 1.368s-.28.092-.497.56c-.217.465-.65.683-1.427.837-.775.155-.775.655-.59 1.214.187.559.001.871-.216 1.585-.217.713.869.932 1.923 1.054 1.055.126 2.234.81 3.228.934.992.125 1.303-.683 1.303-.683s1.116-.25 2.294-.28c1.18-.031 2.295.249 2.295.249s.218.497.62.714c.405.218 1.273.25 1.832-.34.559-.592 2.048-1.337 2.885-1.804.84-.468.686-1.182.159-1.398M12.306 4.606c.532 0 .961.528.961 1.18 0 .463-.215.862-.53 1.056l-.254-.11c.19-.094.324-.335.324-.617 0-.367-.227-.666-.507-.666-.277 0-.505.3-.505.666a.8.8 0 0 0 .088.373c-.165-.066-.318-.127-.437-.172a1.4 1.4 0 0 1-.102-.53c0-.652.43-1.18.962-1.18m-.07 2.488c.267.093.562.266.532.438-.032.172-.172.172-.531.393-.36.218-1.142.703-1.392.735-.251.031-.39-.11-.657-.281-.266-.173-.766-.582-.64-.8 0 0 .39-.298.561-.455s.61-.532.876-.483c.266.045.986.36 1.252.453M9.84 4.793c.42 0 .76.5.76 1.118q0 .168-.032.32a1 1 0 0 0-.307.177 4 4 0 0 0-.14.12.8.8 0 0 0 .063-.49c-.056-.337-.28-.583-.503-.547-.221.038-.355.341-.299.68.057.34.28.585.502.548l.038-.01a3 3 0 0 1-.31.27c-.307-.143-.532-.567-.532-1.07 0-.617.34-1.116.76-1.116M9.019 20.5c-.098.445-.62.77-.62.77-.471.148-1.784-.423-2.38-.673-.593-.247-2.106-.324-2.305-.544-.197-.226.099-.722.175-1.192.073-.474-.148-.77-.075-1.094.075-.322 1.042-.322 1.412-.545.373-.225.447-.87.745-1.044.297-.175.842.446 1.065.795.222.346 1.066 1.837 1.412 2.21.348.372.67.87.572 1.317m5.488-4.332c-.09.438-.09 2.021-.09 2.021s-.961 1.335-2.452 1.554c-1.49.219-2.234.061-2.234.061l-.838-.962s.65-.095.559-.747c-.094-.653-1.985-1.555-2.327-2.363-.34-.808-.062-2.177.373-2.86.434-.684.712-2.175 1.147-2.674.434-.495.774-1.553.62-2.02 0 0 .93 1.12 1.58.935.652-.187 2.112-1.276 2.328-1.089s2.078 4.29 2.263 5.595-.125 2.3-.125 2.3-.712-.187-.804.249m4.761 2.928c-.29.267-1.902.92-2.386 1.428-.48.505-1.109.916-1.493.796-.387-.122-.724-.652-.555-1.426.168-.771.314-1.617.29-2.1s-.122-1.137 0-1.233c.12-.094.312-.047.312-.047s-.095.916.458 1.16c.554.239 1.35-.097 1.59-.34.243-.24.412-.602.412-.602s.24.122.216.507c-.024.386.168.943.531 1.135.36.19.915.458.625.722\"\n />\n </svg>\n );\n}\n","import type { SVGProps } from \"react\";\nexport interface WindowsLogoGreyIconProps\n extends Omit<SVGProps<SVGSVGElement>, \"width\" | \"height\"> {\n className?: string;\n size?: number;\n color?: string;\n}\nexport function WindowsLogoGreyIcon({\n className = \"\",\n size = 24,\n color = \"currentColor\",\n ...props\n}: WindowsLogoGreyIconProps) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n className={className}\n {...props}\n >\n <path\n fill={color}\n d=\"m2 4.832 8.173-1.11.004 7.86-8.17.046zm8.17 7.655.006 7.867-8.17-1.12v-6.8zm.99-8.91L21.997 2v9.482l-10.837.085zM22 12.56 21.997 22 11.16 20.475l-.015-7.932z\"\n />\n </svg>\n );\n}\n","/**\n * Centralized OS Types\n *\n * Single source of truth for all operating system type information across the platform.\n * Handles normalization of OS values from various sources (Fleet MDM, Tactical RMM, GraphQL).\n */\n\nimport { AppleLogoIcon } from '../components/icons-v2-generated/brand-logos/apple-logo-icon'\nimport { LinuxLogoIcon } from '../components/icons-v2-generated/brand-logos/linux-logo-icon'\nimport { WindowsLogoGreyIcon } from '../components/icons-v2-generated/brand-logos/windows-logo-grey-icon'\nimport React from 'react'\nimport type { OSPlatformId } from '../utils/os-platforms'\n\nexport const OSTypeValues = {\n WINDOWS: 'WINDOWS',\n MACOS: 'MACOS',\n LINUX: 'LINUX'\n} as const\n\nexport type OSType = (typeof OSTypeValues)[keyof typeof OSTypeValues]\n\n/**\n * OS type definition with all metadata\n */\nexport interface OSTypeDefinition {\n id: OSType\n label: string\n value: string\n icon: React.ComponentType<any>\n platformId: OSPlatformId\n aliases: string[] // Alternative names/values that map to this OS\n}\n\n/**\n * Complete list of all OS types with icons and labels\n * SINGLE SOURCE OF TRUTH - Use this everywhere\n */\nexport const OS_TYPES: OSTypeDefinition[] = [\n {\n id: OSTypeValues.MACOS,\n label: 'macOS',\n value: OSTypeValues.MACOS,\n icon: AppleLogoIcon,\n platformId: 'darwin',\n aliases: ['darwin', 'macos', 'mac os', 'osx', 'os x', 'mac'] // Put more specific ones first, 'mac' last to avoid false matches\n },\n {\n id: OSTypeValues.WINDOWS,\n label: 'Windows',\n value: OSTypeValues.WINDOWS,\n icon: WindowsLogoGreyIcon,\n platformId: 'windows',\n aliases: ['windows', 'win32', 'win64', 'win'] // 'win' last since it's shortest\n },\n {\n id: OSTypeValues.LINUX,\n label: 'Linux',\n value: OSTypeValues.LINUX,\n icon: LinuxLogoIcon,\n platformId: 'linux',\n aliases: ['linux', 'ubuntu', 'debian', 'centos', 'redhat', 'fedora', 'pop', 'pop!_os', 'arch', 'manjaro']\n }\n]\n\n/**\n * Maps OS types to display labels\n */\nexport const osLabels: Record<OSType, string> = {\n [OSTypeValues.WINDOWS]: 'Windows',\n [OSTypeValues.MACOS]: 'macOS',\n [OSTypeValues.LINUX]: 'Linux'\n}\n","/**\n * OS Type Utilities\n *\n * Helper functions for working with OS types.\n */\n\nimport React from 'react'\nimport type { OSPlatformId } from './os-platforms'\nimport { OSType, OSTypeDefinition, OS_TYPES, osLabels } from '../types/os.types'\n\n/**\n * Normalize OS type string to standard OSType enum\n * Handles case-insensitive matching and various OS name variations\n *\n * @param osType - Raw OS type string from API or device data\n * @returns Normalized OSType or undefined if not recognized\n *\n * @example\n * normalizeOSType('windows') // 'WINDOWS'\n * normalizeOSType('Darwin') // 'MACOS'\n * normalizeOSType('Ubuntu') // 'LINUX'\n */\nexport function normalizeOSType(osType?: string): OSType | undefined {\n if (!osType) return undefined\n\n const normalized = osType.toLowerCase().trim()\n\n // Check for exact matches first, then partial matches\n // This prevents \"win\" from matching \"darwin\"\n for (const osTypeDef of OS_TYPES) {\n // Check for exact word match first\n if (osTypeDef.aliases.some(alias => {\n // Exact match\n if (normalized === alias) return true\n // Word boundary match (e.g., \"mac\" in \"mac os\" but not in \"vmac\")\n const wordBoundaryRegex = new RegExp(`\\\\b${alias}\\\\b`, 'i')\n return wordBoundaryRegex.test(osType)\n })) {\n return osTypeDef.id\n }\n }\n\n // Fallback to partial matching for version strings like \"macOS 26.0.1\"\n for (const osTypeDef of OS_TYPES) {\n if (osTypeDef.aliases.some(alias => normalized.includes(alias))) {\n return osTypeDef.id\n }\n }\n\n return undefined\n}\n\n/**\n * Get display label for an OS type\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Display label\n */\nexport function getOSLabel(osType?: string): string {\n if (!osType) return 'Unknown'\n\n const normalized = normalizeOSType(osType)\n return normalized ? osLabels[normalized] : osType\n}\n\n/**\n * Get icon component for an OS type\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Icon component or undefined\n */\nexport function getOSIcon(osType?: string): React.ComponentType<any> | undefined {\n if (!osType) return undefined\n\n const normalized = normalizeOSType(osType)\n if (!normalized) return undefined\n\n const osTypeDef = OS_TYPES.find(t => t.id === normalized)\n return osTypeDef?.icon\n}\n\n/**\n * Get OS type definition by OS type string\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Complete OS type definition or undefined\n */\nexport function getOSTypeDefinition(osType?: string): OSTypeDefinition | undefined {\n if (!osType) return undefined\n\n const normalized = normalizeOSType(osType)\n if (!normalized) return undefined\n\n return OS_TYPES.find(t => t.id === normalized)\n}\n\n/**\n * Get platform ID for an OS type (for cross-referencing with OS_PLATFORMS)\n *\n * @param osType - OS type string (can be raw or normalized)\n * @returns Platform ID or undefined\n */\nexport function getOSPlatformId(osType?: string): OSPlatformId | undefined {\n const osTypeDef = getOSTypeDefinition(osType)\n return osTypeDef?.platformId\n}\n\n/**\n * Check if device OS matches a specific platform\n *\n * @param deviceOS - Device OS string\n * @param targetPlatform - Target platform to check against\n * @returns True if OS matches platform\n *\n * @example\n * isOSPlatform('Darwin', 'darwin') // true\n * isOSPlatform('Windows 10', 'windows') // true\n * isOSPlatform('Ubuntu', 'linux') // true\n */\nexport function isOSPlatform(deviceOS?: string, targetPlatform?: OSPlatformId): boolean {\n if (!deviceOS || !targetPlatform) return false\n\n const platformId = getOSPlatformId(deviceOS)\n return platformId === targetPlatform\n}\n","import { getCountries, getCountryCallingCode, isValidPhoneNumber, parsePhoneNumber } from 'libphonenumber-js'\nimport type { CountryCode } from 'libphonenumber-js'\n\nexport interface CountryPhoneData {\n code: CountryCode\n name: string\n dialCode: string\n flag: string\n}\n\n/**\n * Priority country codes shown at the top of country selectors\n */\nconst PRIORITY_CODES: CountryCode[] = ['US', 'CA', 'GB', 'AU']\n\n/**\n * Convert ISO 3166-1 alpha-2 country code to flag emoji\n */\nfunction countryCodeToFlag(code: string): string {\n return code\n .toUpperCase()\n .split('')\n .map(char => String.fromCodePoint(0x1F1E6 + char.charCodeAt(0) - 65))\n .join('')\n}\n\n/**\n * Build country phone data from libphonenumber-js metadata + Intl.DisplayNames\n */\nfunction buildCountryData(): { priority: CountryPhoneData[]; others: CountryPhoneData[] } {\n const displayNames = new Intl.DisplayNames(['en'], { type: 'region' })\n const allCodes = getCountries()\n\n const toData = (code: CountryCode): CountryPhoneData => ({\n code,\n name: displayNames.of(code) || code,\n dialCode: `+${getCountryCallingCode(code)}`,\n flag: countryCodeToFlag(code),\n })\n\n const priority = PRIORITY_CODES.map(toData)\n\n const prioritySet = new Set(PRIORITY_CODES)\n const others = allCodes\n .filter(c => !prioritySet.has(c))\n .map(toData)\n .sort((a, b) => a.name.localeCompare(b.name))\n\n return { priority, others }\n}\n\nlet _cache: { priority: CountryPhoneData[]; others: CountryPhoneData[] } | null = null\n\n/**\n * Get all countries split into priority (US, CA, GB, AU) and the rest alphabetically\n */\nexport function getCountryPhoneData() {\n if (!_cache) {\n _cache = buildCountryData()\n }\n return _cache\n}\n\n/**\n * Find country data by ISO code\n */\nexport function getCountryByCode(code: CountryCode): CountryPhoneData | undefined {\n const { priority, others } = getCountryPhoneData()\n return priority.find(c => c.code === code) || others.find(c => c.code === code)\n}\n\n/**\n * Validate a phone number for a specific country using libphonenumber\n */\nexport function validatePhoneNumber(phoneNumber: string, countryCode: CountryCode): boolean {\n if (!phoneNumber.trim()) return true // optional field\n return isValidPhoneNumber(phoneNumber, countryCode)\n}\n\n/**\n * Format a phone number to E.164 format (e.g., +14155552671)\n */\nexport function formatPhoneE164(phoneNumber: string, countryCode: CountryCode): string {\n try {\n const parsed = parsePhoneNumber(phoneNumber, countryCode)\n if (parsed && parsed.isValid()) {\n return parsed.format('E.164')\n }\n } catch {\n // fall through to manual formatting\n }\n const dialCode = `+${getCountryCallingCode(countryCode)}`\n const digits = phoneNumber.replace(/\\D/g, '')\n return `${dialCode}${digits}`\n}\n","/**\n * Generic Domain Detection\n * Detects personal/generic email providers (gmail, yahoo, etc.)\n */\n\nexport const GENERIC_EMAIL_DOMAINS = [\n // Major providers\n 'gmail.com',\n 'yahoo.com',\n 'hotmail.com',\n 'outlook.com',\n 'live.com',\n 'msn.com',\n // Apple\n 'icloud.com',\n 'me.com',\n 'mac.com',\n // Other providers\n 'aol.com',\n 'protonmail.com',\n 'mail.com',\n 'yandex.com',\n 'zoho.com',\n 'gmx.com',\n 'fastmail.com',\n // ISP-based\n 'comcast.net',\n 'verizon.net',\n 'att.net',\n 'sbcglobal.net',\n 'bellsouth.net',\n 'cox.net',\n // International\n 'qq.com',\n '163.com',\n '126.com',\n 'web.de',\n 't-online.de',\n] as const\n\nexport type GenericEmailDomain = (typeof GENERIC_EMAIL_DOMAINS)[number]\n\nexport function extractDomainFromEmail(email: string): string | null {\n if (!email || !email.includes('@')) return null\n return email.split('@')[1]?.toLowerCase() || null\n}\n\nexport function normalizeDomain(domain: string): string {\n return (\n domain\n ?.toLowerCase()\n .replace(/^https?:\\/\\//, '')\n .replace(/^www\\./, '')\n .split('/')[0]\n .trim() || ''\n )\n}\n\nexport function isGenericDomain(domain: string): boolean {\n const normalized = normalizeDomain(domain)\n return GENERIC_EMAIL_DOMAINS.includes(normalized as GenericEmailDomain)\n}\n\nexport function hasGenericEmailDomain(email: string): boolean {\n const domain = extractDomainFromEmail(email)\n return domain ? isGenericDomain(domain) : false\n}\n\nexport function isGenericWebsiteDomain(website: string): boolean {\n return isGenericDomain(normalizeDomain(website))\n}\n","// Color analysis utilities for dynamic badge colors\n\nexport interface ColorPalette {\n name: string;\n hex: string;\n rgb: [number, number, number];\n}\n\n// Your design system color palette - Star colors only\nexport const DESIGN_PALETTE: ColorPalette[] = [\n { name: 'yellow', hex: '#FFC008', rgb: [255, 192, 8] },\n { name: 'black', hex: '#161616', rgb: [22, 22, 22] },\n { name: 'gray', hex: '#888888', rgb: [136, 136, 136] },\n];\n\n/**\n * Convert hex color to RGB\n */\nexport function hexToRgb(hex: string): [number, number, number] {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n return result\n ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)]\n : [0, 0, 0];\n}\n\n/**\n * Calculate relative luminance for contrast calculations\n */\nfunction getLuminance(rgb: [number, number, number]): number {\n const [r, g, b] = rgb.map(c => {\n c = c / 255;\n return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n });\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/**\n * Calculate contrast ratio between two colors\n */\nexport function getContrastRatio(color1: [number, number, number], color2: [number, number, number]): number {\n const lum1 = getLuminance(color1);\n const lum2 = getLuminance(color2);\n const brightest = Math.max(lum1, lum2);\n const darkest = Math.min(lum1, lum2);\n return (brightest + 0.05) / (darkest + 0.05);\n}\n\n/**\n * Extract dominant color from image canvas\n */\nexport function extractDominantColor(canvas: HTMLCanvasElement): [number, number, number] {\n const ctx = canvas.getContext('2d');\n if (!ctx) return [128, 128, 128]; // fallback gray\n\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\n const data = imageData.data;\n\n // Sample pixels in a grid pattern for performance\n const sampleSize = Math.max(1, Math.floor(data.length / (4 * 1000))); // ~1000 samples\n const colorCounts: { [key: string]: number } = {};\n\n for (let i = 0; i < data.length; i += 4 * sampleSize) {\n const r = data[i];\n const g = data[i + 1];\n const b = data[i + 2];\n const alpha = data[i + 3];\n\n // Skip transparent pixels\n if (alpha < 128) continue;\n\n // Bucket colors to reduce noise (round to nearest 32)\n const bucketR = Math.round(r / 32) * 32;\n const bucketG = Math.round(g / 32) * 32;\n const bucketB = Math.round(b / 32) * 32;\n\n const key = `${bucketR},${bucketG},${bucketB}`;\n colorCounts[key] = (colorCounts[key] || 0) + 1;\n }\n\n // Find most common color\n let maxCount = 0;\n let dominantColor: [number, number, number] = [128, 128, 128];\n\n for (const [colorKey, count] of Object.entries(colorCounts)) {\n if (count > maxCount) {\n maxCount = count;\n const [r, g, b] = colorKey.split(',').map(Number);\n dominantColor = [r, g, b];\n }\n }\n\n return dominantColor;\n}\n\n/**\n * Find the best contrasting color from the design palette\n */\nexport function getBestContrastColor(imageColor: [number, number, number]): ColorPalette {\n let bestColor = DESIGN_PALETTE[0];\n let bestContrast = 0;\n\n for (const color of DESIGN_PALETTE) {\n const contrast = getContrastRatio(imageColor, color.rgb);\n if (contrast > bestContrast) {\n bestContrast = contrast;\n bestColor = color;\n }\n }\n\n // Ensure minimum contrast ratio of 3:1 for readability\n return bestContrast >= 3 ? bestColor : DESIGN_PALETTE.find(c => c.name === 'black') || bestColor;\n}\n\n/**\n * Load image and analyze its dominant color\n */\nexport function analyzeImageColor(imageSrc: string): Promise<ColorPalette> {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = 'anonymous';\n\n img.onload = () => {\n try {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n\n if (!ctx) {\n reject(new Error('Could not get canvas context'));\n return;\n }\n\n // Resize to smaller canvas for performance\n const maxSize = 100;\n const scale = Math.min(maxSize / img.width, maxSize / img.height);\n canvas.width = img.width * scale;\n canvas.height = img.height * scale;\n\n ctx.drawImage(img, 0, 0, canvas.width, canvas.height);\n\n const dominantColor = extractDominantColor(canvas);\n const bestContrastColor = getBestContrastColor(dominantColor);\n\n resolve(bestContrastColor);\n } catch (error) {\n reject(error);\n }\n };\n\n img.onerror = () => reject(new Error('Failed to load image'));\n img.src = imageSrc;\n });\n}\n\n/**\n * Extract the dominant edge/corner color from an image URL.\n * Used for background fill behind images in emails and cards.\n * Client-side only (uses canvas). Returns hex color string.\n */\nexport async function extractImageEdgeColorAsync(imageUrl: string): Promise<string> {\n return new Promise((resolve) => {\n if (typeof window === 'undefined') { resolve('#000000'); return }\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => {\n try {\n const canvas = document.createElement('canvas')\n const ctx = canvas.getContext('2d')\n if (!ctx) { resolve('#000000'); return }\n const maxSize = 50\n const scale = Math.min(maxSize / img.naturalWidth, maxSize / img.naturalHeight)\n const w = Math.round(img.naturalWidth * scale)\n const h = Math.round(img.naturalHeight * scale)\n canvas.width = w; canvas.height = h\n ctx.drawImage(img, 0, 0, w, h)\n const data = ctx.getImageData(0, 0, w, h).data\n // Sample edge pixels (15% band on all sides) with color bucketing\n const edgeW = Math.max(2, Math.round(w * 0.15))\n const edgeH = Math.max(2, Math.round(h * 0.15))\n const bucketSize = 32\n const buckets = new Map<string, { r: number; g: number; b: number; count: number }>()\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < w; x++) {\n if (!(x < edgeW || x >= w - edgeW || y < edgeH || y >= h - edgeH)) continue\n const i = (y * w + x) * 4\n if (data[i + 3] < 128) continue\n const br = Math.floor(data[i] / bucketSize) * bucketSize\n const bg = Math.floor(data[i + 1] / bucketSize) * bucketSize\n const bb = Math.floor(data[i + 2] / bucketSize) * bucketSize\n const key = `${br},${bg},${bb}`\n const existing = buckets.get(key)\n if (existing) { existing.r += data[i]; existing.g += data[i + 1]; existing.b += data[i + 2]; existing.count++ }\n else { buckets.set(key, { r: data[i], g: data[i + 1], b: data[i + 2], count: 1 }) }\n }\n }\n let best = { r: 0, g: 0, b: 0, count: 0 }\n for (const b of buckets.values()) { if (b.count > best.count) best = b }\n if (best.count === 0) { resolve('#000000'); return }\n const r = Math.round(best.r / best.count), g = Math.round(best.g / best.count), b = Math.round(best.b / best.count)\n resolve(`#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`)\n } catch { resolve('#000000') }\n }\n img.onerror = () => resolve('#000000')\n img.src = imageUrl\n })\n}\n","/**\n * Pure image-proxy URL builder + helpers.\n *\n * Lib-side replacement for the hub's `lib/utils/image-proxy.ts`. The\n * hub used to hardcode `/api/image-proxy` + an `openmsp.ai` skip-domain;\n * this version takes BOTH as parameters so embedded apps (and other\n * platforms that host the lib) can wire their own proxy prefix + skip\n * list at the runtime layer.\n *\n * Pure function — no side effects, no env reads. Callers thread the\n * proxy config through (typically from `ChatRuntime.endpoints.imageProxyUrlPrefix`).\n */\n\nexport type GetProxiedImageUrlOptions = {\n /**\n * URL prefix for the image proxy (`<prefix>?url=<encoded>`). When unset,\n * `getProxiedImageUrl` returns the original URL unchanged — relative\n * URLs always pass through. Hub default: `/api/image-proxy`.\n */\n proxyPrefix?: string;\n /**\n * Domains that should bypass the proxy (e.g. own-CDN hosts whose\n * `Content-Type` is reliable and that already serve CORS-permitting\n * headers). Matched as `imageUrl.includes(domain)` so subdomains\n * inherit. Default: `[]`.\n */\n skipDomains?: string[];\n /**\n * Return the original `https://` URL so the browser loads it directly\n * (no proxy). Use when upstream `Content-Type` breaks the proxy (common\n * with SVG on some CDNs) or you want the origin to see the client\n * request. HTTP stays proxied (mixed content / legacy).\n */\n directHttps?: boolean;\n};\n\n/**\n * Resolve an external image URL through (or around) the image proxy.\n *\n * Resolution order:\n * 1. `imageUrl` already contains `proxyPrefix` → return unchanged\n * (self-skip — prevents double-wrap).\n * 2. `directHttps` set AND `imageUrl` starts with `https://` → return\n * unchanged.\n * 3. `imageUrl` doesn't start with `http://` or `https://` → return\n * unchanged (relative URLs pass through).\n * 4. `proxyPrefix` unset → return unchanged.\n * 5. `skipDomains` matches the URL's host → return unchanged.\n * 6. Else return `<proxyPrefix>?url=<encoded>`.\n */\nexport function getProxiedImageUrl(\n imageUrl: string | null,\n options?: GetProxiedImageUrlOptions,\n): string | null {\n if (!imageUrl) return null;\n\n const proxyPrefix = options?.proxyPrefix;\n const skipDomains = options?.skipDomains ?? [];\n const directHttps = options?.directHttps ?? false;\n\n // (1) Self-skip — already proxied. Check this BEFORE the http/https\n // gate so an absolute proxy URL passed in (e.g. `https://hub.example/api/image-proxy?url=…`)\n // is treated as already-proxied even though it starts with https://.\n if (proxyPrefix && imageUrl.includes(proxyPrefix)) {\n return imageUrl;\n }\n\n // (3) Relative URLs / data: / blob: — return as-is.\n if (!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://')) {\n return imageUrl;\n }\n\n // (2) Direct-https opt-out — only applies to https (http stays proxied).\n if (directHttps && imageUrl.startsWith('https://')) {\n return imageUrl;\n }\n\n // (4) No proxy configured — return as-is.\n if (!proxyPrefix) {\n return imageUrl;\n }\n\n // (5) Skip-list match.\n for (const domain of skipDomains) {\n if (imageUrl.includes(domain)) {\n return imageUrl;\n }\n }\n\n // (6) Proxy.\n return `${proxyPrefix}?url=${encodeURIComponent(imageUrl)}`;\n}\n\n/**\n * Heuristic: URL path looks like an SVG. Useful with `{ directHttps: true }`\n * when only SVGs misbehave through the proxy; raster images can stay\n * proxied if you prefer.\n */\nexport function urlPathLooksLikeSvg(imageUrl: string): boolean {\n try {\n return /\\.svg$/i.test(new URL(imageUrl).pathname);\n } catch {\n return /\\.svg(\\?|#|$)/i.test(imageUrl);\n }\n}\n\n/**\n * Check if an image URL needs to be proxied. `proxyPrefix` is the same\n * value passed to `getProxiedImageUrl` — used to short-circuit the\n * self-skip case.\n */\nexport function shouldProxyImage(\n imageUrl: string | null,\n proxyPrefix?: string,\n): boolean {\n if (!imageUrl) return false;\n if (!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://')) return false;\n if (proxyPrefix && imageUrl.includes(proxyPrefix)) return false;\n return true;\n}\n\n/**\n * Generate a responsive `sizes` attribute for `<img>` / `<Image>` tags.\n * Pure utility — kept here for backwards-compatibility with the previous\n * stub.\n */\nexport function generateImageSizes(_url: string): string {\n return `(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw`;\n}\n","/**\n * Unified Date Utilities for OpenMSP Platform\n * Provides consistent date formatting across all components\n */\n\n/**\n * Format relative time from ISO timestamp\n * This is the single source of truth for all relative time formatting\n * \n * @param timestamp - ISO timestamp string or Date object\n * @returns Formatted relative time string\n * \n * @example\n * formatRelativeTime('2024-01-01T12:00:00Z') // '2 hours ago'\n * formatRelativeTime(new Date()) // 'Just now'\n */\nexport function formatRelativeTime(timestamp: string | Date): string {\n const now = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n // Validate the date\n if (isNaN(targetTime.getTime())) {\n console.warn('⚠️ Invalid timestamp in formatRelativeTime:', timestamp);\n return 'Unknown time';\n }\n \n const diffInMs = now.getTime() - targetTime.getTime();\n const diffInMinutes = Math.floor(diffInMs / (1000 * 60));\n \n // Handle future dates (should not happen but graceful fallback)\n if (diffInMinutes < 0) {\n return 'Just now';\n }\n \n // Less than 1 minute\n if (diffInMinutes < 1) return 'Just now';\n \n // 1-59 minutes\n if (diffInMinutes < 60) return `${diffInMinutes}m ago`;\n \n // 1-23 hours \n const diffInHours = Math.floor(diffInMinutes / 60);\n if (diffInHours < 24) return `${diffInHours}h ago`;\n \n // 1-6 days\n const diffInDays = Math.floor(diffInHours / 24);\n if (diffInDays < 7) return `${diffInDays}d ago`;\n \n // 1-4 weeks\n if (diffInDays < 30) {\n const weeks = Math.floor(diffInDays / 7);\n return `${weeks}w ago`;\n }\n \n // Older than 30 days - show formatted date\n return targetTime.toLocaleDateString('en-US', { \n month: 'short', \n day: 'numeric',\n year: targetTime.getFullYear() !== now.getFullYear() ? 'numeric' : undefined\n });\n}\n\n/**\n * Format absolute date for display\n * \n * @param timestamp - ISO timestamp string or Date object\n * @param options - Intl.DateTimeFormatOptions for customization\n * @returns Formatted date string\n */\nexport function formatAbsoluteDate(\n timestamp: string | Date,\n options: Intl.DateTimeFormatOptions = {}\n): string {\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n if (isNaN(targetTime.getTime())) {\n console.warn('⚠️ Invalid timestamp in formatAbsoluteDate:', timestamp);\n return 'Invalid date';\n }\n \n const defaultOptions: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n ...options\n };\n \n return targetTime.toLocaleDateString('en-US', defaultOptions);\n}\n\n/**\n * Format timestamp with time included\n * \n * @param timestamp - ISO timestamp string or Date object\n * @param options - Intl.DateTimeFormatOptions for customization\n * @returns Formatted datetime string\n */\nexport function formatDateTime(\n timestamp: string | Date,\n options: Intl.DateTimeFormatOptions = {}\n): string {\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n if (isNaN(targetTime.getTime())) {\n console.warn('⚠️ Invalid timestamp in formatDateTime:', timestamp);\n return 'Invalid date';\n }\n \n const defaultOptions: Intl.DateTimeFormatOptions = {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n ...options\n };\n \n return targetTime.toLocaleDateString('en-US', defaultOptions);\n}\n\n/**\n * Get time difference in human readable format (detailed)\n * \n * @param timestamp - ISO timestamp string or Date object\n * @returns Detailed time difference string\n */\nexport function getDetailedTimeDifference(timestamp: string | Date): string {\n const now = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n if (isNaN(targetTime.getTime())) {\n return 'Invalid date';\n }\n \n const diffInMs = now.getTime() - targetTime.getTime();\n const diffInSeconds = Math.floor(diffInMs / 1000);\n const diffInMinutes = Math.floor(diffInSeconds / 60);\n const diffInHours = Math.floor(diffInMinutes / 60);\n const diffInDays = Math.floor(diffInHours / 24);\n \n if (diffInSeconds < 60) return `${diffInSeconds} seconds ago`;\n if (diffInMinutes < 60) return `${diffInMinutes} minutes ago`;\n if (diffInHours < 24) return `${diffInHours} hours ago`;\n if (diffInDays < 30) return `${diffInDays} days ago`;\n \n const diffInMonths = Math.floor(diffInDays / 30);\n if (diffInMonths < 12) return `${diffInMonths} months ago`;\n \n const diffInYears = Math.floor(diffInDays / 365);\n return `${diffInYears} years ago`;\n}\n\n/**\n * Check if a timestamp is today\n */\nexport function isToday(timestamp: string | Date): boolean {\n const today = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n \n return today.toDateString() === targetTime.toDateString();\n}\n\n/**\n * Check if a timestamp is within the last N minutes\n */\nexport function isWithinMinutes(timestamp: string | Date, minutes: number): boolean {\n const now = new Date();\n const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;\n const diffInMs = now.getTime() - targetTime.getTime();\n const diffInMinutes = diffInMs / (1000 * 60);\n \n return diffInMinutes <= minutes && diffInMinutes >= 0;\n}\n\n/**\n * Create a UTC timestamp string for database insertion\n */\nexport function createUTCTimestamp(): string {\n return new Date().toISOString();\n} ","/**\n * Per-source icon-name + label lookup. Keyed by `RagTableConfig.id` (the same\n * id used in `chat_source_rag_tables.rag_table_id` and on each\n * `ChatRef.sourceRepo`).\n *\n * Server-safe — lives in `src/utils/` (no `'use client'` banner) so\n * hub server-side rag-mappers + chat route handlers can call\n * `getSourceLabel()` / `getSourceIconName()` directly. The client-side\n * chat barrel re-exports from here for ergonomic client imports.\n *\n * Used by SOURCE-LEVEL chip surfaces:\n * - The chip strip below an assistant message.\n * - The tracking-row source glyph on inline entity cards.\n *\n * Why a small map here instead of a column on RAG_TABLE_CONFIGS:\n * - The icon NAME is a small string; the resolver (icon-name → React\n * component) lives in `src/components/chat/utils/icon-registry.ts`\n * where it can stay client-only. Server-side consumers stay\n * icon-component-free.\n * - The mapping is intrinsic to the TABLE, not per-platform — same\n * entry serves every (platform, source) binding.\n *\n * Per-table admin-UI bucket id (`SOURCE_CATEGORIES_BY_TABLE`) stays\n * hub-side because it depends on the hub's `RagSourceCategoryId` enum.\n */\n\n/** Map RagTableConfig.id → icon_name (resolvable via `getIconComponent`). */\nexport const SOURCE_ICON_NAMES: Record<string, string> = {\n // Doc tables\n 'openframe-docs': 'openframe',\n 'data-room-docs': 'shield',\n\n // CMS / programs\n 'blog-posts': 'newspaper',\n 'product-releases': 'rocket',\n 'case-studies': 'briefcase',\n 'onboarding-guides': 'graduation-cap',\n webinars: 'video',\n events: 'calendar',\n podcasts: 'headphones',\n 'customer-interviews': 'users',\n\n // Financials\n 'investor-updates': 'mail',\n 'financial-kpis': 'activity',\n 'financial-cap-table': 'table',\n 'financial-pnl': 'trending-up',\n 'financial-balance-sheet': 'dollar-sign',\n 'financial-cash-flow': 'banknote',\n\n // ClickUp\n 'clickup-roadmap': 'clickup',\n 'clickup-delivery': 'clickup',\n 'clickup-tasks-internal': 'clickup',\n\n // GitHub\n 'github-commits': 'github',\n 'github-pull-requests': 'github',\n 'github-pr-reviews': 'github',\n 'github-commits-public': 'github',\n 'github-pull-requests-public': 'github',\n 'github-pr-reviews-public': 'github',\n\n // HubSpot\n 'hubspot-tickets': 'hubspot',\n 'hubspot-tickets-anon': 'hubspot',\n 'hubspot-tickets-self': 'hubspot',\n\n // Communications\n 'slack-messages': 'slack',\n}\n\n/** Lookup an icon name by RagTableConfig.id. Returns undefined when\n * unknown so callers can decide whether to fall back to documentType\n * or to the generic FileText glyph in the icon registry. */\nexport function getSourceIconName(tableId: string | null | undefined): string | undefined {\n if (!tableId) return undefined\n return SOURCE_ICON_NAMES[tableId]\n}\n\n/**\n * Per-table display LABEL — used by SERVER-SIDE chip-strip rendering\n * (the row's \"Customer Interviews (8 records)\" chip below an assistant\n * message).\n *\n * The chip GRID + autocomplete DROPDOWN read their command label\n * from the DB (per-source `chat_admin_slash_commands.label`) — those\n * surfaces can carry per-source labels (e.g. \"OpenFrame Commits\" vs\n * \"GitHub Commits\" for the same table). This map is the TABLE-LEVEL\n * label used by sub-message chips where a SINGLE label per table is\n * sufficient regardless of which source's chat is rendering.\n */\nexport const SOURCE_LABELS_BY_TABLE: Record<string, string> = {\n // Doc tables\n 'openframe-docs': 'OpenFrame Docs',\n 'data-room-docs': 'Data Room',\n\n // CMS / programs\n 'blog-posts': 'Blog Posts',\n 'product-releases': 'Product Releases',\n 'case-studies': 'Case Studies',\n 'onboarding-guides': 'Onboarding Guides',\n webinars: 'Webinars',\n events: 'Events',\n podcasts: 'Podcasts',\n 'customer-interviews': 'Customer Interviews',\n\n // Financials\n 'investor-updates': 'Investor Updates',\n 'financial-kpis': 'Financial KPIs',\n 'financial-cap-table': 'Cap Table',\n 'financial-pnl': 'Profit & Loss',\n 'financial-balance-sheet': 'Balance Sheet',\n 'financial-cash-flow': 'Cash Flow',\n\n // ClickUp\n 'clickup-roadmap': 'ClickUp Roadmap',\n 'clickup-delivery': 'ClickUp Delivery',\n 'clickup-tasks-internal': 'ClickUp Tasks',\n\n // GitHub\n 'github-commits': 'GitHub Commits',\n 'github-pull-requests': 'GitHub Pull Requests',\n 'github-pr-reviews': 'GitHub PR Reviews',\n 'github-commits-public': 'OpenFrame Commits',\n 'github-pull-requests-public': 'OpenFrame Pull Requests',\n 'github-pr-reviews-public': 'OpenFrame PR Reviews',\n\n // HubSpot\n 'hubspot-tickets': 'HubSpot Tickets',\n 'hubspot-tickets-anon': 'Known Issues',\n 'hubspot-tickets-self': 'My Tickets',\n\n // Communications\n 'slack-messages': 'OpenMSP Community',\n}\n\n/** Lookup a human-readable label by RagTableConfig.id. Falls back\n * to the raw id (chip text becomes the table slug — visible bug\n * that prompts an entry to land in `SOURCE_LABELS_BY_TABLE`). */\nexport function getSourceLabel(tableId: string): string {\n return SOURCE_LABELS_BY_TABLE[tableId] ?? tableId\n}\n\n/**\n * Default `documentType → RagTableConfig.id` reverse map.\n *\n * Mirrors the canonical lookup the hub registers via\n * `lib/config/rag-table-config.ts:tableIdForDocumentType()` — same vocabulary\n * the LLM emits inside `[card://<type>:<id>]` markers, same tableIds the\n * retrieval layer routes by, and same set of keys covered by\n * `SOURCE_ICON_NAMES` / `SOURCE_LABELS_BY_TABLE` above.\n *\n * Server-safe (no `'use client'` banner), keyed by string for forward\n * compatibility — adding a new RAG table is a single-line edit here so\n * lib-based embedders pick it up without re-publishing.\n *\n * Embedders that need a CUSTOM mapping (e.g. polymorphic types whose\n * tableId depends on per-tenant config) still pass their own\n * `tableIdForDocumentType` callback to `useEmbeddedChat`; this default\n * only applies when no callback is supplied.\n *\n * Inverse mapping audited 2026-05-24 against the hub registry — every\n * entry in `RAG_TABLE_CONFIGS` with a `documentType` is represented.\n */\nexport const DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID: Record<string, string> = {\n // Doc tables\n markdown: 'openframe-docs',\n data_room_doc: 'data-room-docs',\n\n // CMS / programs\n blog_post: 'blog-posts',\n product_release: 'product-releases',\n case_study: 'case-studies',\n onboarding_guide: 'onboarding-guides',\n webinar: 'webinars',\n event: 'events',\n podcast: 'podcasts',\n customer_interview: 'customer-interviews',\n\n // Financials\n investor_update: 'investor-updates',\n financial_kpi: 'financial-kpis',\n cap_table: 'financial-cap-table',\n profit_loss: 'financial-pnl',\n balance_sheet: 'financial-balance-sheet',\n cash_flow: 'financial-cash-flow',\n\n // ClickUp\n roadmap_item: 'clickup-roadmap',\n delivery_item: 'clickup-delivery',\n internal_task: 'clickup-tasks-internal',\n\n // GitHub\n github_commit: 'github-commits',\n github_pull_request: 'github-pull-requests',\n github_pr_review: 'github-pr-reviews',\n github_commit_public: 'github-commits-public',\n github_pull_request_public: 'github-pull-requests-public',\n github_pr_review_public: 'github-pr-reviews-public',\n\n // HubSpot\n hubspot_ticket: 'hubspot-tickets',\n hubspot_ticket_anon: 'hubspot-tickets-anon',\n hubspot_ticket_self: 'hubspot-tickets-self',\n\n // Communications\n slack_message: 'slack-messages',\n}\n\n/**\n * Default `tableIdForDocumentType` resolver used by `useEmbeddedChat` when\n * the caller didn't pass an explicit callback. Returns `null` for\n * unrecognized document types so downstream `discussRef` / `displayRef`\n * still short-circuits gracefully on stale or custom types.\n */\nexport function defaultTableIdForDocumentType(documentType: string): string | null {\n return DEFAULT_DOCUMENT_TYPE_TO_TABLE_ID[documentType] ?? null\n}\n","/**\n * Thin JSON-typed Web-Storage adapter (localStorage or sessionStorage).\n *\n * Centralizes the SSR-guard + try/catch + silent quota-failure pattern\n * that every per-feature storage util would otherwise re-implement.\n *\n * Optional `namespace` prefix supports platform / user partitioning —\n * the resolver runs lazily at call time so the namespace can vary across\n * the lifetime of the page (e.g. proxy-auth switches user, which switches\n * the key suffix).\n *\n * Backend selection (`backend: 'local' | 'session'`):\n * - `'local'` (default): persists across browser sessions. Use for\n * UI state, chat history metadata, feature-flag opt-ins.\n * - `'session'`: cleared when the tab closes. Use for ANY auth-adjacent\n * value (bearer tokens, act-as identity, proxy credentials). Reduces\n * the XSS-exfiltration attack window from \"indefinite\" to \"until tab\n * close\" without losing per-session ergonomics.\n */\n\nexport type WebStorageBackend = 'local' | 'session'\n\nexport interface LocalStorageAdapter<T> {\n load(): T | null\n save(value: T): void\n clear(): void\n /** Resolved storage key for the current call. Useful for tests. */\n resolveKey(): string\n}\n\nexport interface LocalStorageAdapterOptions<T> {\n /** Base storage key. Combined with `namespace()` when provided. */\n key: string\n /** Optional dynamic namespace prefix appended via `.` separator.\n * Called on EVERY read/write so the key can vary across the page\n * lifetime (e.g. when the platform or user identity changes). */\n namespace?: () => string | null | undefined\n /** Runtime shape check. Falsey return → `load()` yields null. */\n validate?: (parsed: unknown) => parsed is T\n /** Diagnostic prefix written to `console.warn` on parse / write\n * failures. Defaults to `'[local-storage]'`. */\n logTag?: string\n /** Which Web-Storage backend to use. Defaults to `'local'`. Pass\n * `'session'` for anything auth-adjacent so the value evaporates\n * when the tab closes. */\n backend?: WebStorageBackend\n}\n\nfunction getStorage(backend: WebStorageBackend): Storage | null {\n if (typeof window === 'undefined') return null\n try {\n return backend === 'session' ? window.sessionStorage : window.localStorage\n } catch {\n // Some sandboxed contexts (Safari private mode older versions,\n // strict CSP) throw on storage access — treat as unavailable.\n return null\n }\n}\n\nexport function createLocalStorageAdapter<T>(\n options: LocalStorageAdapterOptions<T>,\n): LocalStorageAdapter<T> {\n const tag = options.logTag ?? '[local-storage]'\n const backend: WebStorageBackend = options.backend ?? 'local'\n const resolveKey = (): string => {\n const ns = options.namespace?.()\n return ns ? `${ns}.${options.key}` : options.key\n }\n\n return {\n resolveKey,\n load() {\n const storage = getStorage(backend)\n if (!storage) return null\n try {\n const raw = storage.getItem(resolveKey())\n if (!raw) return null\n const parsed = JSON.parse(raw) as unknown\n if (options.validate && !options.validate(parsed)) return null\n return parsed as T\n } catch (err) {\n console.warn(`${tag} parse failed for key ${resolveKey()}:`, err)\n return null\n }\n },\n save(value: T) {\n const storage = getStorage(backend)\n if (!storage) return\n try {\n storage.setItem(resolveKey(), JSON.stringify(value))\n } catch (err) {\n console.warn(`${tag} write failed for key ${resolveKey()}:`, err)\n }\n },\n clear() {\n const storage = getStorage(backend)\n if (!storage) return\n try {\n storage.removeItem(resolveKey())\n } catch (err) {\n console.warn(`${tag} clear failed for key ${resolveKey()}:`, err)\n }\n },\n }\n}\n","// Stub app config\nexport const APP_CONFIG = {\n app: {\n type: 'openmsp',\n name: 'OpenMSP',\n domain: 'openmsp.ai'\n },\n features: {\n announcements: true,\n notifications: true\n }\n} as const;\n\nexport function getAppConfig() {\n return APP_CONFIG;\n}\n\nexport function getAppType() {\n return process.env.NEXT_PUBLIC_APP_TYPE || 'openmsp';\n}","'use client'\n\n/**\n * Client-side persistence for embed-surface proxy credentials\n * (`CHAT_PROXY_SECRET` + impersonation email). Used by every embedded\n * surface — the chat widget AND the ticket center AND any future\n * embedded React component that needs to identify itself as the\n * impersonated customer.\n *\n * When set, the surface attaches the creds as\n * `Authorization: Bearer <secret>` + `X-Chat-Act-As: <email>`\n * on every call to `/api/docs/chat`, `/api/chat/*`, and any other route\n * gated by `requireChatAuth` — proving to the server that this session\n * is acting on behalf of <email>.\n *\n * **Naming history:** the wire-side header names are still `X-Chat-*`\n * and the env var is `CHAT_PROXY_SECRET`. Those are server contracts;\n * renaming them would require a coordinated deploy + customer-side\n * env-var migration. The CLIENT-side helpers were renamed `Embed*` so\n * non-chat surfaces (e.g. ticket center) don't have to import a\n * chat-prefixed symbol just to send the same headers.\n *\n * Persists to **`localStorage`** so the bearer token + act-as identity\n * survive tab close, new-tab opens, and browser restarts — the\n * `/debug` paste-creds UI is an admin tool and re-pasting every tab\n * cycle was rejected as a dev-experience tradeoff that wasn't worth\n * the security gain. An XSS sink on this origin can read the value\n * indefinitely (vs only-this-tab with sessionStorage), but `/debug`\n * is admin-gated behind the platform's `askAI.enabled` flag and the\n * impersonation header it sets is server-validated against\n * `CHAT_PROXY_SECRET` anyway. Explicit \"Clear\" button on the creds\n * bar is the supported logout path; closing the tab is no longer.\n *\n * Namespaced under `<platform>.chat.proxy-auth.v1` (the storage key is\n * unchanged from the old chat-prefixed helper — that's a storage\n * contract; renaming it would log everyone out).\n */\n\nimport { createLocalStorageAdapter } from './local-storage-adapter'\nimport { getAppType } from './app-config'\n\nexport interface EmbedProxyAuth {\n secret: string\n email: string\n /** Optional identity passthrough — empty/omitted = not sent. Server\n * parses these as `X-Chat-{First,Last}-Name` / `X-Chat-Avatar-Url` and\n * threads them through `resolveChatProxyIdentity`'s returned user. */\n firstName?: string\n lastName?: string\n avatarUrl?: string\n}\n\nfunction isValidPersistedAuth(value: unknown): value is EmbedProxyAuth {\n if (!value || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n if (\n typeof v.secret !== 'string' || v.secret.trim().length === 0 ||\n typeof v.email !== 'string' || v.email.trim().length === 0\n ) return false\n // Optional fields: when present must be strings. Empty string is treated\n // as absent later (in `getEmbedProxyAuth`).\n if (v.firstName != null && typeof v.firstName !== 'string') return false\n if (v.lastName != null && typeof v.lastName !== 'string') return false\n if (v.avatarUrl != null && typeof v.avatarUrl !== 'string') return false\n return true\n}\n\nconst adapter = createLocalStorageAdapter<EmbedProxyAuth>({\n // Storage key unchanged from the legacy chat-prefixed helper. Renaming\n // it would silently log every existing admin out — the key is a\n // storage contract, not a code identifier.\n key: 'chat.proxy-auth.v1',\n namespace: () => getAppType(),\n validate: isValidPersistedAuth,\n logTag: '[embed-proxy-auth-storage]',\n // localStorage — survives tab close, new tabs, and browser restarts.\n // Admin re-pasting creds every tab cycle was the dev-experience\n // tradeoff prior `sessionStorage` setup demanded — rejected. See\n // file-level doc comment for the security tradeoff rationale.\n backend: 'local',\n})\n\n/** Trim + null-coerce an optional identity field so consumers can do\n * `auth.firstName ?? ''` without worrying about whitespace-only strings. */\nfunction normalizeOptional(value: string | undefined): string | undefined {\n if (!value) return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\n/**\n * Returns full credentials (secret + email + optional identity passthrough)\n * when secret + email are available. Returns `null` when nothing is saved —\n * callers treat that as \"fall back to cookie auth\".\n */\nexport function getEmbedProxyAuth(): EmbedProxyAuth | null {\n const persisted = adapter.load()\n if (!persisted) return null\n return {\n secret: persisted.secret,\n email: persisted.email.trim().toLowerCase(),\n firstName: normalizeOptional(persisted.firstName),\n lastName: normalizeOptional(persisted.lastName),\n avatarUrl: normalizeOptional(persisted.avatarUrl),\n }\n}\n\n/**\n * Returns the LAST email the admin saved. The proxy creds bar reads\n * this to pre-fill the email field on mount.\n */\nexport function getPersistedProxyEmail(): string | null {\n const persisted = adapter.load()\n return persisted?.email.trim().toLowerCase() ?? null\n}\n\n/** Save the proxy creds. Secret + email are required; identity-passthrough\n * fields are persisted only when non-empty. */\nexport function setEmbedProxyAuth(value: EmbedProxyAuth): void {\n adapter.save({\n secret: value.secret,\n email: value.email.trim().toLowerCase(),\n firstName: normalizeOptional(value.firstName),\n lastName: normalizeOptional(value.lastName),\n avatarUrl: normalizeOptional(value.avatarUrl),\n })\n}\n\n/** Drop the persisted creds. */\nexport function clearEmbedProxyAuth(): void {\n adapter.clear()\n}\n\n/**\n * Apply the embed-proxy auth (Bearer + X-Chat-Act-As) to a fetch call's\n * URL + headers. Used by every embedded-surface route that needs to\n * identify itself as the proxied customer (chat stream, agent-* routes,\n * ticket-center actions). When proxy auth is absent (regular\n * cookie-session users), returns the inputs unchanged so the cookie-auth\n * path still works.\n *\n * `X-Chat-Act-As` header (vs a URL query param) keeps PII out of access\n * logs, Sentry breadcrumbs, browser history, and CDN analytics.\n */\nexport function applyProxyAuth(\n url: string,\n baseHeaders: Record<string, string> = { 'Content-Type': 'application/json' },\n): { url: string; headers: Record<string, string> } {\n const auth = getEmbedProxyAuth()\n const headers = { ...baseHeaders }\n if (auth?.secret) {\n headers.Authorization = `Bearer ${auth.secret}`\n }\n if (auth?.email) {\n headers['X-Chat-Act-As'] = auth.email\n }\n // Optional identity passthrough — only attached when present so the\n // server's \"required vs optional\" header shape stays exact.\n if (auth?.firstName) headers['X-Chat-First-Name'] = auth.firstName\n if (auth?.lastName) headers['X-Chat-Last-Name'] = auth.lastName\n if (auth?.avatarUrl) headers['X-Chat-Avatar-Url'] = auth.avatarUrl\n return { url, headers }\n}\n","'use client'\n\n/**\n * Shared `fetch` wrapper for any embedded surface (chat, ticket center,\n * future widgets) that needs to carry the bearer-act-as identity\n * (proxy `Authorization` + `X-Chat-Act-As` headers from\n * `embed-proxy-auth-storage.ts`).\n *\n * Wire header names are `X-Chat-*` for historical reasons — that's a\n * server contract, not a UI namespace. The wrapper itself is generic.\n *\n * Drop-in replacement for `fetch()` — `Authorization` / `X-Chat-Act-As`\n * are merged into `init.headers` when proxy creds are stashed in\n * sessionStorage, otherwise the call falls through to the cookie-auth\n * path unchanged.\n *\n * Use this for any client-side fetch hitting `/api/chat/*`, `/api/docs/chat/*`,\n * or `/api/storage/generate-upload-url` (chat-attachment surface — shared\n * with the ticket center). Routes that do NOT need bearer-act-as\n * (e.g. `/api/profile/me`) keep using vanilla `fetch`.\n */\n\nimport { applyProxyAuth } from './embed-proxy-auth-storage'\n\n/**\n * `fetch` wrapper that attaches embed-proxy bearer headers (when\n * present in sessionStorage) and forces `credentials: 'same-origin'`\n * so Supabase auth cookies travel too.\n *\n * **Header merge direction (proxy WINS over caller):** the implementation\n * spreads `baseHeaders` first inside `applyProxyAuth`, then sets the\n * `Authorization` / `X-Chat-*` keys — so the proxy values take precedence\n * over anything the caller passed. The motivation is that the bearer +\n * act-as identity is the source of truth for embedded auth; a caller\n * accidentally passing a stale `Authorization` header should NOT override\n * the live proxy creds.\n *\n * **Cross-origin defense:** the wrapper assumes a same-origin `/api/…`\n * relative URL. Absolute URLs are accepted only when their origin matches\n * the current window's origin; cross-origin URLs throw before the bearer\n * leaves the page. This is a defense-in-depth guard for future call sites\n * — there is no legitimate cross-origin use of this fetch wrapper.\n */\nexport function embedAuthedFetch(url: string, init: RequestInit = {}): Promise<Response> {\n assertSameOrigin(url)\n\n // `applyProxyAuth` accepts `Record<string, string>`; normalize the\n // caller's headers to that shape. RequestInit accepts `HeadersInit`\n // which is broader (Headers instance OR array of tuples).\n //\n // When the caller passes no headers, fall back to the same default\n // `applyProxyAuth` uses internally — `Content-Type: application/json` —\n // so JSON POSTs keep their content-type when only `embedAuthedFetch(url)`\n // is used at the call site. GET callers that explicitly want no body\n // headers can pass `init.headers = {}` to opt out.\n let baseHeaders: Record<string, string>\n if (init.headers === undefined) {\n baseHeaders = { 'Content-Type': 'application/json' }\n } else {\n baseHeaders = {}\n if (init.headers instanceof Headers) {\n init.headers.forEach((v, k) => {\n baseHeaders[k] = v\n })\n } else if (Array.isArray(init.headers)) {\n for (const [k, v] of init.headers) baseHeaders[k] = v\n } else {\n Object.assign(baseHeaders, init.headers as Record<string, string>)\n }\n }\n\n const { url: authedUrl, headers } = applyProxyAuth(url, baseHeaders)\n return fetch(authedUrl, {\n ...init,\n headers,\n // Always include Supabase auth cookies. `applyProxyAuth` handles\n // the bearer header layer; cookies are the session-tier carrier.\n credentials: init.credentials ?? 'same-origin',\n })\n}\n\n/**\n * Reject any URL that resolves to a cross-origin destination or to a\n * non-http(s) scheme. Every input is resolved against\n * `window.location.href` so the same rule covers path-only\n * (`/api/...`), absolute (`https://...`), protocol-relative\n * (`//host/...`), AND whitespace-prefixed forms (`\\t//evil.com/...`) —\n * the WHATWG fetch spec strips leading ASCII whitespace before\n * parsing, so any regex-based \"skip relative\" shortcut is bypassable\n * with a leading `\\t`/`\\n`/`\\r`/space. We resolve unconditionally\n * instead and compare origins.\n *\n * Also blocks `javascript:` / `data:` / `blob:` etc. — only `http(s):`\n * is allowed. This is explicit allowlisting rather than relying on\n * `origin === 'null'` to fall out wrong.\n *\n * Server-side rendering: when `typeof window === 'undefined'` we skip\n * the check — the bearer comes from sessionStorage which doesn't exist\n * on the server, so there's nothing to leak anyway.\n */\nfunction assertSameOrigin(url: string): void {\n if (typeof window === 'undefined') return\n let target: URL\n let pageOrigin: string\n try {\n target = new URL(url, window.location.href)\n // Derive the page origin from `href` rather than reading\n // `window.location.origin` directly so the check works in test\n // environments that mock `window.location` to a plain object\n // without an `origin` field (jsdom setups do this).\n pageOrigin = new URL(window.location.href).origin\n } catch {\n throw new Error(`embedAuthedFetch: refusing to fetch malformed URL (${JSON.stringify(url)})`)\n }\n if (target.protocol !== 'http:' && target.protocol !== 'https:') {\n throw new Error(\n `embedAuthedFetch: refusing non-http(s) URL (${target.protocol}) — pass a relative /api/* path instead`,\n )\n }\n if (target.origin !== pageOrigin) {\n throw new Error(\n `embedAuthedFetch: refusing cross-origin fetch to ${target.origin} — pass a relative /api/* path instead`,\n )\n }\n}\n","'use client'\n\n/**\n * Shared decoder for the `decision_resolved` leading frame the\n * `confirm-tool` route emits as the first chunk of its SSE response.\n *\n * Wire format (matches `use-embedded-chat.ts:270-394`):\n * - Frames are JSON objects separated by `\\0` (NUL).\n * - `\\x1E` (record separator) marks the transition from leading\n * metadata frames into the text body (chat path).\n * - For the tickets-UI path, the request body carries `messages: []`\n * which makes phase-2 (text body) structurally unreachable —\n * `confirm-tool/route.ts:569` skips the `runDocsChat` call. So the\n * stream contains exactly ONE frame (`decision_resolved`) followed\n * by EOF.\n *\n * This helper drains the stream defensively (reads all remaining bytes\n * after the leading frame so the server-side `composed.start()` doesn't\n * hang on a half-closed connection) and returns the first decoded\n * `decision_resolved` frame. Throws on:\n * - Empty body\n * - First frame is not `decision_resolved`\n * - Malformed JSON before the first `\\0`\n *\n * Migration note: `use-embedded-chat.ts` still inlines the full decoder\n * including phase-2 text + trailing usage parsing. A future refactor\n * could move the leading-frame loop here and have the chat shell\n * compose with that — out of scope for this PR.\n */\n\nexport interface DecisionResolvedFrame {\n kind: 'decision_resolved'\n ok: boolean\n action: 'approved' | 'rejected'\n toolName?: string\n willAutoContinue?: boolean\n proposalId?: string\n /** Approve-path result envelope. `mirror_synced=false` means the\n * HubSpot REST call succeeded but the local mirror upsert lagged —\n * callers should optimistic-render and schedule a delayed refetch. */\n result?: {\n ticket_id?: string\n status?: string | null\n mirror_synced?: boolean\n } | null\n card?: {\n type?: string\n marker?: string\n ref?: unknown\n } | null\n receiptText?: string\n}\n\n/**\n * Read the leading `decision_resolved` frame from a confirm-tool SSE\n * response. Drains the stream to end-of-file before resolving so the\n * server doesn't sit on a half-closed socket.\n *\n * @throws {Error} when the body is empty, the first frame is not\n * `decision_resolved`, or the leading JSON is malformed.\n */\nexport async function readLeadingDecisionFrame(\n response: Response,\n): Promise<DecisionResolvedFrame> {\n const reader = response.body?.getReader()\n if (!reader) throw new Error('readLeadingDecisionFrame: response has no body')\n\n const decoder = new TextDecoder()\n let buffer = ''\n let frame: DecisionResolvedFrame | null = null\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true })\n\n // Try to extract the leading frame ASAP — we only need the first\n // chunk that contains a `\\0`. Everything after is either phase-2\n // text (unexpected for tickets-UI but tolerated) or end-of-stream.\n if (frame === null) {\n const nullIdx = buffer.indexOf('\\0')\n const recIdx = buffer.indexOf('\\x1E')\n // If `\\x1E` (text-body marker) shows up before `\\0`, the server\n // emitted phase-2 without a leading frame — protocol violation.\n if (recIdx !== -1 && (nullIdx === -1 || recIdx < nullIdx)) {\n throw new Error(\n 'readLeadingDecisionFrame: text-body sentinel arrived before leading frame',\n )\n }\n if (nullIdx !== -1) {\n const raw = buffer.slice(0, nullIdx)\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (err) {\n throw new Error(\n `readLeadingDecisionFrame: leading JSON parse failed: ${(err as Error).message}`,\n )\n }\n const obj = parsed as Record<string, unknown>\n if (obj?.kind !== 'decision_resolved') {\n throw new Error(\n `readLeadingDecisionFrame: expected decision_resolved, got kind=${String(obj?.kind)}`,\n )\n }\n frame = normalizeDecisionFrame(obj)\n // Continue draining so the server-side stream closes cleanly.\n buffer = buffer.slice(nullIdx + 1)\n }\n }\n // Past the leading frame: just consume + discard the remainder.\n // Don't allocate a parser for phase-2 text; the tickets-UI path\n // is supposed to be a single frame.\n }\n } finally {\n // Release the lock even if we threw mid-loop.\n try {\n reader.releaseLock()\n } catch {\n // No-op: reader may already be released if the stream ended cleanly.\n }\n }\n\n if (frame === null) {\n throw new Error('readLeadingDecisionFrame: stream closed before leading frame arrived')\n }\n return frame\n}\n\nfunction normalizeDecisionFrame(obj: Record<string, unknown>): DecisionResolvedFrame {\n const action = obj.action === 'rejected' ? 'rejected' : 'approved'\n const result = (obj.result ?? null) as DecisionResolvedFrame['result']\n const card = (obj.card ?? null) as DecisionResolvedFrame['card']\n return {\n kind: 'decision_resolved',\n ok: obj.ok === true,\n action,\n ...(typeof obj.toolName === 'string' ? { toolName: obj.toolName } : {}),\n ...(obj.willAutoContinue === true ? { willAutoContinue: true } : {}),\n ...(typeof obj.proposalId === 'string' ? { proposalId: obj.proposalId } : {}),\n ...(result ? { result } : {}),\n ...(card ? { card } : {}),\n ...(typeof obj.receiptText === 'string' ? { receiptText: obj.receiptText } : {}),\n }\n}\n","/**\n * Shared helper for the host-side markdown formatter ↔ server-side\n * parser pair. Single source of truth so the host-side build (chat\n * bubble render) and the server-side strip (LLM input cleanup) can\n * never drift.\n *\n * Lib-side replacement for the hub's `lib/utils/chat-attachment-markdown.ts`.\n * The hub file pulled its constants from `lib/config/chat-attachment-config`\n * + its `ChatAttachment` type from `lib/types/chat-attachment`. Both are\n * inlined here as lib-local constants/types — they're stable wire-format\n * contracts (the hub's view-route owns the prefix + token-param name; any\n * change is a coordinated migration).\n *\n * URL flavors at a glance:\n * - HOST-SIDE (user-bubble render): uses the runtime's\n * `attachmentViewUrlPrefix` (hub default = `/api/storage/view/chat-attachments/`).\n * Embedded apps override per their reverse-proxy topology.\n * - SERVER-SIDE (strip regex): uses the constant\n * `CHAT_ATTACHMENT_VIEW_URL_PREFIX` directly. The chat ROUTE always\n * runs on the hub, so it always strips on the hub default.\n * - ANTHROPIC image-blocks: uses the RAW Supabase signed URL — NOT the\n * proxy URL — because Anthropic's image fetcher doesn't reliably\n * follow 302 redirects.\n *\n * Security gates inside the formatter:\n * - Filename markdown chars escaped via `escapeMarkdownInline` so a\n * name like `screenshot](https://evil.com).png` cannot terminate\n * the markdown image early and embed an attacker-controlled URL.\n * - `<` and `>` escaped too — prevents CommonMark autolink expansion\n * for filenames containing URL-shaped text.\n */\n\n// ---------------------------------------------------------------------------\n// Lib-local constants + types (mirror the hub's chat-attachment-config /\n// chat-attachment.ts). These are wire-format contracts owned by the hub's\n// view route; embedders that want to override the prefix do so via\n// `ChatRuntime.endpoints.attachmentViewUrlPrefix`, not by changing these.\n// ---------------------------------------------------------------------------\n\n/** Hub-default prefix for the view-proxy URL. Embedders override via the\n * runtime. The server-side strip regex always uses THIS value (server\n * runs on the hub). */\nexport const CHAT_ATTACHMENT_VIEW_URL_PREFIX = '/api/storage/view/chat-attachments/'\n\n/** Query parameter name for the HMAC view token. */\nexport const CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM = 't'\n\n/** Subset Anthropic's image content-block API supports. HEIC / video\n * attachments fall through to the text-marker form so the LLM still sees\n * a reference even when it can't visually parse the file. */\nexport const ANTHROPIC_SUPPORTED_IMAGE_MIME = [\n 'image/jpeg',\n 'image/png',\n 'image/webp',\n 'image/gif',\n] as const\n\n/**\n * Wire shape for a single chat attachment.\n *\n * `viewToken` is server-issued (HMAC-signed) and embedded in the markdown\n * URL's `?t=` query parameter. The client never generates it — the upload\n * route returns it alongside the storage path.\n */\nexport interface ChatAttachment {\n storagePath: string\n viewToken: string\n contentType: string\n fileName: string\n size: number\n}\n\n// ---------------------------------------------------------------------------\n// URL building\n// ---------------------------------------------------------------------------\n\n/**\n * Build the markdown view-URL for a chat attachment.\n *\n * `viewUrlPrefix` is parameterized (NOT pulled from the constant) so\n * host-side callers can pass the runtime's prefix\n * (`ChatRuntime.endpoints.attachmentViewUrlPrefix`) — embedded apps\n * supply an absolute URL against the hub's origin so chat-history\n * markdown works cross-origin.\n *\n * Server-side callers (the strip regex source) should pass\n * `CHAT_ATTACHMENT_VIEW_URL_PREFIX` directly.\n */\nexport function buildChatAttachmentViewUrl(\n viewUrlPrefix: string,\n storagePath: string,\n viewToken: string,\n): string {\n return `${viewUrlPrefix}${storagePath}?${CHAT_ATTACHMENT_VIEW_TOKEN_QUERY_PARAM}=${encodeURIComponent(viewToken)}`\n}\n\n// ---------------------------------------------------------------------------\n// Markdown formatter\n// ---------------------------------------------------------------------------\n\n/**\n * Escape inline-markdown special characters from a filename before\n * interpolation. Closes the markdown-injection / phishing primitive:\n * a filename like `screenshot](https://evil.com).png` would otherwise\n * terminate `![filename](...)` early and emit an attacker-controlled\n * URL in the user's bubble.\n *\n * Escapes: `[`, `]`, `(`, `)`, `\\`, `\\n`, `\\r`, `<`, `>`, `\"`.\n */\nexport function escapeMarkdownInline(text: string): string {\n return text.replace(/[[\\]()\\\\\\n\\r<>\"]/g, (ch) => {\n switch (ch) {\n case '\\n':\n return ' '\n case '\\r':\n return ''\n default:\n return `\\\\${ch}`\n }\n })\n}\n\n/**\n * Format a single chat-attachment as a markdown line to append to the\n * user's bubble text BEFORE sending.\n *\n * Images (MIME in `ANTHROPIC_SUPPORTED_IMAGE_MIME`) emit the `![]()`\n * image form so the browser renders the attachment inline. Everything\n * else (HEIC, video, audio) emits the `[Attached: ...]` link form so the\n * bubble shows a clickable file pill instead of a broken-image icon.\n */\nexport function formatChatAttachmentMarkdownForBubble(\n att: ChatAttachment,\n viewUrlPrefix: string,\n): string {\n const safeName = escapeMarkdownInline(att.fileName)\n const url = buildChatAttachmentViewUrl(viewUrlPrefix, att.storagePath, att.viewToken)\n const isImage = (ANTHROPIC_SUPPORTED_IMAGE_MIME as readonly string[]).includes(att.contentType)\n return isImage ? `\\n\\n![${safeName}](${url})` : `\\n\\n[Attached: ${safeName}](${url})`\n}\n\n// ---------------------------------------------------------------------------\n// Server-side strip regex + parser\n// ---------------------------------------------------------------------------\n\n/**\n * Module-private: the `CHAT_ATTACHMENT_VIEW_URL_PREFIX` with regex\n * meta-characters escaped, so it can be safely interpolated into\n * regex sources. Computed ONCE at module load. Exported so other\n * regex-building call sites can share the same source of truth.\n */\nexport const CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED =\n CHAT_ATTACHMENT_VIEW_URL_PREFIX.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n/**\n * Single anchored regex matching both the image (`![]()`) and link\n * (`[Attached: ...]`) forms keyed on the server-side prefix.\n *\n * `gm` flags — multi-line anchored so the regex matches per-line.\n * Non-chat markdown links/images stay untouched because the regex\n * requires the literal `/api/storage/view/chat-attachments/` prefix.\n */\nexport const CHAT_ATTACHMENT_MARKDOWN_PATTERN = new RegExp(\n `^\\\\s*!?\\\\[[^\\\\]]*\\\\]\\\\(${CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED}[^)]+\\\\)\\\\s*$`,\n 'gm',\n)\n\n/**\n * Strip pre-embedded chat-attachment markdown lines from `text`.\n * Returns the cleaned text + the storage paths extracted from the\n * matched URLs.\n */\nexport function stripChatAttachmentMarkdown(text: string): {\n stripped: string\n storagePaths: string[]\n} {\n const storagePaths: string[] = []\n const pathExtract = new RegExp(\n `\\\\(${CHAT_ATTACHMENT_VIEW_URL_PREFIX_REGEX_ESCAPED}([^?)]+)`,\n )\n const stripped = text.replace(CHAT_ATTACHMENT_MARKDOWN_PATTERN, (match) => {\n const m = match.match(pathExtract)\n if (m && m[1]) storagePaths.push(m[1])\n return ''\n })\n return {\n stripped: stripped.replace(/\\n{3,}/g, '\\n\\n').trim(),\n storagePaths,\n }\n}\n","/**\n * Shared cross-process contract for the post-approval auto-continuation\n * directive. The client emits a hidden synthetic user message starting\n * with `AUTO_CONTINUATION_DIRECTIVE_PREFIX`; the server's `decideRoute`\n * matches that exact prefix on the RAW user query (pre-rewriter) and\n * hard-disables tools for the directive turn, forcing the LLM to\n * respond with prose follow-up questions instead of duplicating the\n * just-approved tool call.\n *\n * Single source of truth — both server-side `decideRoute` AND\n * client-side `autoContinueRef` import from here. Drifting the literal\n * on either side would silently break the duplicate-ticket guard\n * (server would route normally with tools wired; LLM would propose the\n * same tool again).\n *\n * `toolName` is typed as `string` (not a const-union) so the lib stays\n * generic across hub deployments — host code that has a sharper\n * `KnownWriteToolName` type can pass that through; this builder only\n * cares about a handful of string-equal branches.\n */\n\nexport const AUTO_CONTINUATION_DIRECTIVE_PREFIX = '[internal-auto-continuation]'\n\nexport interface BuildAutoContinuationOptions {\n ticketId?: string\n /** Reading of `args.status` on the just-approved tool call. Used to\n * branch the directive between \"post-create diagnostic Qs\",\n * \"post-close resolution ask\", and \"post-update acknowledgement\". */\n status?: string\n}\n\n/**\n * Build the directive text the client sends as a HIDDEN user message\n * after every successful Approve. The LLM treats it as the user\n * speaking; the chat shell filters it out at render time.\n *\n * Branch logic mirrors `TICKET_TOOL_PROTOCOL` §1a/§1b — keep them in\n * sync: the directive tells the model WHICH section to follow.\n */\nexport function buildAutoContinuationDirective(\n toolName: string,\n opts: BuildAutoContinuationOptions = {},\n): string {\n const ticketRef = opts.ticketId ? ` (ticket #${opts.ticketId})` : ''\n const ticketHash = opts.ticketId ? ` #${opts.ticketId}` : ''\n const isClose = toolName === 'update_ticket' && opts.status?.toUpperCase() === 'CLOSED'\n if (toolName === 'create_ticket') {\n return (\n `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved create_ticket${ticketRef}. ` +\n `Per ticket-protocol §1a, ask 2-4 SHORT, issue-specific diagnostic follow-up questions ` +\n `tailored to the symptom they reported in their original message. When they answer, ` +\n `propose an update_ticket with content_addendum carrying a clean Q&A digest. ` +\n `Do NOT call any tool in this turn — just write the questions as prose.`\n )\n }\n if (isClose) {\n return (\n `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved closing ticket${ticketHash}. ` +\n `Per ticket-protocol §1b, ask ONE short question: \"How was this resolved? I'll add it ` +\n `to the ticket as a closing note.\" Phrase kindly even if the user was curt. When they ` +\n `answer, propose an update_ticket with content_addendum=\"[Resolution] <their words>\". ` +\n `Do NOT call any tool in this turn — just write the prose ask.`\n )\n }\n return (\n `${AUTO_CONTINUATION_DIRECTIVE_PREFIX} The user just approved update_ticket${ticketHash}. ` +\n `Acknowledge the change in ONE short sentence; if anything else looks like it needs ` +\n `attention, ask. Do NOT call any tool in this turn.`\n )\n}\n","/**\n * `flattenAssistantContent` — coerce a chat message's `content` field\n * (string OR `MessageSegment[]`) into a plain string for wire transport.\n *\n * Background: useChat populates assistant messages with a structured\n * segment array as the streamed SSE arrives (text segments, approval\n * cards, tool_execution blocks, thinking blocks). The local React\n * state holds `content: MessageSegment[]` for those turns. When the\n * client serializes the conversation back to the server for the NEXT\n * turn, a naive `typeof content === 'string' ? content : ''` strip-\n * to-empty silently drops every post-approve receipt, every Sonnet-\n * streamed answer, and every diagnostic Q — Anthropic receives\n * `assistant: \"\"` for those turns and has no context to follow.\n *\n * The function:\n * 1. Returns plain strings as-is.\n * 2. For arrays, joins every `text`-typed segment's `text` field\n * with `\\n\\n` separators. Non-text segments (approval_request,\n * tool_execution, thinking) have no LLM-visible textual content\n * and are intentionally skipped — they shouldn't bloat the\n * request body.\n * 3. Returns `''` for anything else (null, undefined, unknown shape).\n */\nexport function flattenAssistantContent(raw: unknown): string {\n if (typeof raw === 'string') return raw\n if (!Array.isArray(raw)) return ''\n const parts: string[] = []\n for (const seg of raw) {\n if (seg && typeof seg === 'object' && (seg as { type?: string }).type === 'text') {\n const t = (seg as { text?: unknown }).text\n if (typeof t === 'string' && t.length > 0) parts.push(t)\n }\n }\n return parts.join('\\n\\n')\n}\n","/**\n * Message-related types\n * Contains all message structures, segments, and content types\n */\n\nimport type { AssistantType, AuthorType, ChatApprovalStatus, MessageOwner } from './chat.types'\n\n// ========== Message Type Definitions ==========\n\nexport const MESSAGE_TYPE = {\n TEXT: 'TEXT',\n THINKING: 'THINKING',\n EXECUTING_TOOL: 'EXECUTING_TOOL',\n EXECUTED_TOOL: 'EXECUTED_TOOL',\n APPROVAL_REQUEST: 'APPROVAL_REQUEST',\n APPROVAL_RESULT: 'APPROVAL_RESULT',\n ERROR: 'ERROR',\n MESSAGE_START: 'MESSAGE_START',\n MESSAGE_END: 'MESSAGE_END',\n MESSAGE_REQUEST: 'MESSAGE_REQUEST',\n AI_METADATA: 'AI_METADATA',\n TOKEN_USAGE: 'TOKEN_USAGE',\n CONTEXT_COMPACTION_START: 'CONTEXT_COMPACTION_START',\n CONTEXT_COMPACTION_END: 'CONTEXT_COMPACTION_END',\n DIRECT_MESSAGE: 'DIRECT_MESSAGE',\n SYSTEM: 'SYSTEM',\n DIALOG_CLOSED: 'DIALOG_CLOSED',\n} as const\n\nexport type MessageType = typeof MESSAGE_TYPE[keyof typeof MESSAGE_TYPE]\n\n// ========== Scroll Anchor (per-message render hint) ==========\n\n/** Per-message viewport-positioning hint sent on the per-turn metadata\n * leading frame at the START of every assistant response. The chat\n * message-list reads it to override the default `use-stick-to-bottom`\n * tail behaviour for a single message. Field is OPTIONAL — when omitted\n * (or set to `'bottom'`) the chat tails as today. Only `'top'` opts in\n * to the alternative behaviour (used by display-action answers whose\n * body is a long article and should be read top-down). */\nexport const SCROLL_ANCHOR = { TOP: 'top', BOTTOM: 'bottom' } as const\n\nexport type ScrollAnchor = typeof SCROLL_ANCHOR[keyof typeof SCROLL_ANCHOR]\n\n// ========== Tool Execution Types ==========\n\nexport interface ToolExecutionData {\n type: 'EXECUTING_TOOL' | 'EXECUTED_TOOL'\n integratedToolType: string\n toolFunction: string\n /** Backend-issued human-readable title (mirrors `PendingToolCallData.toolTitle`). */\n toolTitle?: string\n parameters?: Record<string, any>\n result?: string\n success?: boolean\n /**\n * Backend-issued id (matches `PendingToolCallData.toolExecutionRequestId`).\n * When present, lets the accumulator merge this execution event into the\n * matching approval batch row instead of emitting a standalone segment.\n */\n toolExecutionRequestId?: string\n}\n\n/**\n * Snapshot of an in-flight tool kept between the `EXECUTING_TOOL` and\n * `EXECUTED_TOOL` events. The backend only sends `toolTitle` on\n * `EXECUTING_TOOL`; carrying this state lets the accumulator restore it onto\n * the merged `EXECUTED_TOOL` segment instead of falling back to the raw\n * `toolFunction`.\n */\nexport interface ExecutingToolState {\n integratedToolType: string\n toolFunction: string\n /** Mirrors {@link ToolExecutionData.toolTitle}; absent on `EXECUTED_TOOL`. */\n toolTitle?: string\n parameters?: Record<string, any>\n}\n\n// ========== Approval Request Types ==========\n\nexport interface ApprovalRequestField {\n /** Short label — e.g. \"Subject\", \"Priority\". Rendered in a muted\n * caps style above the value. */\n label: string\n /** Free-text value. Wraps and line-breaks are preserved\n * (`whitespace-pre-wrap`). */\n value: string\n}\n\nexport interface ApprovalRequestData {\n command: string\n /** Structured field list — preferred over `explanation`. When set,\n * the approval card renders a vertical label/value stack with\n * proper spacing. Falls back to `explanation` (a single paragraph)\n * when omitted. Keep BOTH when you want hosts on older lib\n * versions to still see the prose; new hosts should send only\n * `fields`. */\n fields?: ApprovalRequestField[]\n explanation?: string\n icon?: React.ReactNode\n requestId?: string\n approvalRequestId?: string\n approvalType?: string\n}\n\nexport interface ApprovalResultData {\n approvalRequestId: string\n approved: boolean\n approvalType?: string\n}\n\n/**\n * Single tool call inside a batch approval request.\n * Mirrors backend PendingToolCallDto.\n */\nexport interface PendingToolCallData {\n toolExecutionRequestId: string\n toolName: string\n toolTitle?: string\n toolExplanation?: string\n toolType?: string\n requiresApproval: boolean\n approvalType?: string | null\n toolCallArguments?: Record<string, any> | null\n}\n\n/**\n * Per-tool execution state inside an approval batch.\n * Populated by EXECUTING_TOOL / EXECUTED_TOOL chunks that carry a\n * `toolExecutionRequestId` matching one of the batch's tool calls.\n */\nexport interface ApprovalBatchExecutionState {\n status: 'executing' | 'done'\n result?: string\n success?: boolean\n}\n\nexport interface ApprovalBatchData {\n approvalRequestId: string\n /** Highest approval type required across the batch (e.g. ADMIN beats CLIENT). */\n approvalType: string\n toolCalls: PendingToolCallData[]\n /**\n * Keyed by `PendingToolCallData.toolExecutionRequestId`. Absent before\n * approval; rows without an entry render as \"queued\" (loader) once the\n * batch itself is approved.\n */\n executions?: Record<string, ApprovalBatchExecutionState>\n}\n\n// ========== Message Segment Types ==========\n\nexport type TextSegment = {\n type: 'text'\n text: string\n}\n\nexport type ThinkingSegment = {\n type: 'thinking'\n text: string\n}\n\nexport type ToolExecutionSegment = {\n type: 'tool_execution'\n data: ToolExecutionData\n}\n\nexport type ApprovalRequestSegment = {\n type: 'approval_request'\n data: ApprovalRequestData & { approvalType?: string }\n status?: ChatApprovalStatus\n onApprove?: (requestId?: string) => void | Promise<void>\n onReject?: (requestId?: string) => void | Promise<void>\n}\n\nexport type ApprovalBatchSegment = {\n type: 'approval_batch'\n data: ApprovalBatchData\n status?: ChatApprovalStatus\n onApprove?: (requestId?: string) => void | Promise<void>\n onReject?: (requestId?: string) => void | Promise<void>\n}\n\nexport type ErrorSegment = {\n type: 'error'\n title: string\n details?: string\n}\n\nexport type ContextCompactionSegment = {\n type: 'context_compaction'\n status: 'started' | 'completed'\n summary?: string\n}\n\nexport type MessageSegment = TextSegment | ThinkingSegment | ToolExecutionSegment | ApprovalRequestSegment | ApprovalBatchSegment | ErrorSegment | ContextCompactionSegment\n\nexport type MessageContent = string | MessageSegment[]\n\n// ========== Message Data Types (from GraphQL/API) ==========\n\nexport interface MessageDataBase {\n type: MessageType\n}\n\nexport interface TextMessageData extends MessageDataBase {\n type: 'TEXT'\n text?: string\n}\n\nexport interface ThinkingMessageData extends MessageDataBase {\n type: 'THINKING'\n text?: string\n}\n\nexport interface ExecutingToolMessageData extends MessageDataBase {\n type: 'EXECUTING_TOOL'\n integratedToolType?: string\n toolFunction?: string\n /** Backend-issued human-readable title (wire field, mirrors `ChunkData.title`). */\n title?: string\n parameters?: Record<string, any>\n toolExecutionRequestId?: string\n}\n\nexport interface ExecutedToolMessageData extends MessageDataBase {\n type: 'EXECUTED_TOOL'\n integratedToolType?: string\n toolFunction?: string\n /** Backend-issued human-readable title (wire field, mirrors `ChunkData.title`). */\n title?: string\n parameters?: Record<string, any>\n result?: string\n success?: boolean\n toolExecutionRequestId?: string\n}\n\nexport interface ApprovalRequestMessageData extends MessageDataBase {\n type: 'APPROVAL_REQUEST'\n approvalRequestId?: string\n approvalType?: string\n command?: string\n explanation?: string\n /** Present when the approval is a batch of tool calls (new format). */\n toolCalls?: PendingToolCallData[]\n}\n\nexport interface ApprovalResultMessageData extends MessageDataBase {\n type: 'APPROVAL_RESULT'\n approvalRequestId?: string\n approved?: boolean\n approvalType?: string\n}\n\nexport interface ErrorMessageData extends MessageDataBase {\n type: 'ERROR'\n error?: string\n details?: string\n}\n\nexport interface AIMetadataMessageData extends MessageDataBase {\n type: 'AI_METADATA'\n modelName?: string\n providerName?: string\n provider?: string\n contextWindow?: number\n}\n\nexport interface TokenUsageData {\n inputTokensSize: number\n outputTokensSize: number\n totalTokensSize: number\n contextSize: number\n}\n\nexport interface SystemMessageData extends MessageDataBase {\n type: 'SYSTEM'\n text?: string\n}\n\nexport interface ContextCompactionStartMessageData extends MessageDataBase {\n type: 'CONTEXT_COMPACTION_START'\n}\n\nexport interface ContextCompactionEndMessageData extends MessageDataBase {\n type: 'CONTEXT_COMPACTION_END'\n summary?: string\n}\n\nexport type MessageData =\n | TextMessageData\n | ThinkingMessageData\n | ExecutingToolMessageData\n | ExecutedToolMessageData\n | ApprovalRequestMessageData\n | ApprovalResultMessageData\n | ErrorMessageData\n | AIMetadataMessageData\n | SystemMessageData\n | ContextCompactionStartMessageData\n | ContextCompactionEndMessageData\n\n// ========== Historical Message Types ==========\n\nexport interface HistoricalMessage {\n id: string\n dialogId?: string\n chatType?: string\n createdAt: string\n owner?: MessageOwner\n messageData?: MessageData | MessageData[]\n}\n\n// ========== Processed Message Types ==========\n\nexport interface ProcessedMessage {\n id: string\n role: 'user' | 'assistant' | 'error' // Limited to display roles\n content: MessageContent\n name?: string\n assistantType?: AssistantType\n authorType?: AuthorType\n timestamp: Date\n avatar?: string\n}\n\n// ========== Base Message Interface ==========\n\nimport type { ChatRef as MessageChatRef } from '../chat-ref.types'\n\nexport interface Message {\n id: string\n role: 'user' | 'assistant' | 'error' // Limited to display roles\n content: MessageContent\n name?: string\n assistantType?: AssistantType\n authorType?: AuthorType\n timestamp?: Date\n avatar?: string | null\n /** Per-row metadata for inline entity-card rendering on this message\n * (v6.1 §B.2.6). Keyed by `<documentType>:<primaryKey>`. Optional —\n * user messages and legacy turns omit this field. The host's\n * `renderEntityCard` callback resolves keys to inline components. */\n chatRefs?: Record<string, MessageChatRef>\n /** Per-message viewport-positioning hint. OPTIONAL — when omitted (the\n * default for every LLM Q&A / browse / search / find / Discuss path)\n * the chat tails as today via `use-stick-to-bottom`. Only `'top'` opts\n * in to the alternative top-anchor behaviour (display-action answers\n * whose body is a long article). The server is the sole decision-\n * maker — set on the metadata leading frame. */\n scrollAnchor?: ScrollAnchor\n /** When true the message is part of the API conversation history (sent\n * to the LLM so it has context) but is NOT rendered in the chat UI.\n *\n * Used for \"synthetic continuation\" turns: when the user clicks Approve\n * on a tool proposal, the host auto-fires a follow-up `sendMessage`\n * with `hidden: true` carrying a directive like \"the user just\n * approved <tool>; ask follow-up questions per protocol\". The LLM's\n * response IS rendered (as a normal assistant message); only the\n * trigger prompt is suppressed so the chat reads naturally:\n *\n * user: \"open a ticket\"\n * assistant: preamble + approval card\n * [user clicks Approve]\n * assistant: \"Now to triage faster, can you share...\" ← auto-fires\n *\n * Without this flag the trigger prompt would surface as a confusing\n * bubble like \"(continue per protocol)\" between the approval card\n * and the AI's follow-up. */\n hidden?: boolean\n}","/**\n * Wire glue + canonical const for the per-message `scrollAnchor`\n * render hint.\n *\n * The actual `SCROLL_ANCHOR` const + `ScrollAnchor` type lives in\n * `../types/message.types.ts` (it's part of the `Message` shape). This\n * module re-exports them alongside the wire-key + a `parseScrollAnchor`\n * narrower so server-side code that emits the metadata leading frame and\n * client-side code that consumes it agree on the literal value AND the\n * key on the wire frame.\n *\n * Consumed by:\n * - SERVER: emits the field into the metadata leading frame\n * (`...(scrollAnchor ? { [SCROLL_ANCHOR_WIRE_KEY]: x } : {})`).\n * - CLIENT: parses each leading frame and feeds the value through\n * `parseScrollAnchor` before storing it for the chat-message-list\n * to consume. Malformed wire values return `null` and are filtered\n * by metadata-merge logic — they never clobber a prior value.\n */\n\nimport { SCROLL_ANCHOR, type ScrollAnchor } from '../types/message.types'\n\nexport { SCROLL_ANCHOR, type ScrollAnchor }\n\n/** Wire-frame key for the `scrollAnchor` field on the metadata leading\n * frame. Used as a computed property name on both the emit side\n * (server) and the parse side (client) so a rename is one-file. */\nexport const SCROLL_ANCHOR_WIRE_KEY = \"scrollAnchor\" as const\n\n/** Narrow + validate a wire-supplied value. Returns the literal when\n * it matches one of the registry's known values; returns `null`\n * otherwise (which the metadata-merge null-skip filter then drops). */\nexport function parseScrollAnchor(raw: unknown): ScrollAnchor | null {\n return raw === SCROLL_ANCHOR.TOP || raw === SCROLL_ANCHOR.BOTTOM ? raw : null\n}\n","/**\n * Lib-side portable subset of the hub's `lib/utils/slash-dispatch-utils.ts`.\n *\n * The full hub file owns the SERVER-SIDE parser/dispatcher (depends on\n * `slash-commands-config`, `slash-commands-static`, `doc-source-config-utils`,\n * `chat-admin-types`, `rag-table-config`) which stays hub-side.\n *\n * What MIGRATES here is the wire contract + the small text helpers consumed\n * by chat surfaces in the lib + the hub UI:\n * - `WireCommandOverride` — wire-shape (chat request body)\n * - `parseWireCommandOverride` — wire validator\n * - `CommandOverride` — server-built dispatch result type\n * (presentation typed as `string` here; the hub narrows via its own\n * `SlashCommandPresentation` union)\n * - `extractEntityIdFilter` — `CommandOverride` → narrowed filter\n * - `sanitizeTitleForChat` — collapse control chars in titles\n * - `formatSingularLookupInvocation` — `/cmd \"value\"` builder\n * - `buildDiscussAddendum` — server-side Discuss addendum prose\n *\n * Validation constants (regex + length caps) are duplicated here verbatim\n * to keep the lib's wire validator self-contained.\n */\n\nconst WIRE_TABLE_ID_REGEX = /^[a-z][a-z0-9-]*$/\nconst WIRE_ID_REGEX = /^[A-Za-z0-9._:/-]+$/\nconst WIRE_TABLE_ID_MAX = 60\nconst WIRE_ID_MAX = 200\nconst WIRE_QUERY_MAX = 2000\n\n/** Wire-supplied `CommandOverride` — the subset of fields a client (chat\n * shell) is allowed to send on the request body. Excludes\n * `systemPromptAddendum` by construction: addendum injection is a\n * Rule-5b bypass vector, so we never accept it from the wire. */\nexport interface WireCommandOverride {\n entityIdFilter?: { tableId: string; id: string }\n retrievalQueryOverride?: string\n}\n\n/**\n * Parse + validate a wire-supplied `commandOverride` from the chat\n * request body. Returns the validated subset OR `null` if the input is\n * missing / malformed in every field.\n */\nexport function parseWireCommandOverride(raw: unknown): WireCommandOverride | null {\n if (!raw || typeof raw !== 'object') return null\n const out: WireCommandOverride = {}\n const r = raw as Record<string, unknown>\n\n if (r.entityIdFilter && typeof r.entityIdFilter === 'object') {\n const f = r.entityIdFilter as Record<string, unknown>\n if (\n typeof f.tableId === 'string'\n && f.tableId.length > 0\n && f.tableId.length <= WIRE_TABLE_ID_MAX\n && WIRE_TABLE_ID_REGEX.test(f.tableId)\n && typeof f.id === 'string'\n && f.id.length > 0\n && f.id.length <= WIRE_ID_MAX\n && WIRE_ID_REGEX.test(f.id)\n ) {\n out.entityIdFilter = { tableId: f.tableId, id: f.id }\n }\n }\n if (\n typeof r.retrievalQueryOverride === 'string'\n && r.retrievalQueryOverride.length > 0\n && r.retrievalQueryOverride.length <= WIRE_QUERY_MAX\n ) {\n out.retrievalQueryOverride = r.retrievalQueryOverride\n }\n if (out.entityIdFilter === undefined && out.retrievalQueryOverride === undefined) {\n return null\n }\n return out\n}\n\n/**\n * Sanitize a free-text title for use inside a chat-visible string:\n * collapse control chars (\\r \\n \\t) to single spaces and trim. Defends\n * against a row title containing embedded newlines (which would split\n * the rendered prompt across visible lines + survive into ILIKE in a\n * confusing way) and tab/CR artifacts from sloppy imports.\n */\nexport function sanitizeTitleForChat(value: string | null | undefined): string {\n return (value ?? '').replace(/[\\r\\n\\t]+/g, ' ').trim()\n}\n\n/**\n * Compose a singular-lookup slash invocation as the user-visible chat\n * message: `/<cmd> \"<value>\"` (or `/<cmd>` when value is empty).\n *\n * SINGLE SOURCE OF TRUTH for the quoting convention `parseSlashCommand`\n * consumes: outer `\"`-pair triggers `singularLookup`; unquoted args run\n * FTS; empty args browse. Internal `\"` chars are backslash-escaped so\n * the visible string is paste-able / re-runnable.\n */\nexport function formatSingularLookupInvocation(cmdId: string, value?: string | null): string {\n // Escape `\\` BEFORE `\"` — otherwise a value ending in `\\` survives the\n // `\"`-escape pass and, when wrapped in `\"...\"`, the trailing `\\\"`\n // becomes a literal `\"` to a parser that processes backslash escapes,\n // breaking the close quote. CodeQL's `js/incomplete-sanitization` fires\n // on the previous one-pass `\\\"` escape for exactly this reason.\n const safe = sanitizeTitleForChat(value)\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/\"/g, '\\\\\"')\n return safe ? `/${cmdId} \"${safe}\"` : `/${cmdId}`\n}\n\n/** Command-override structure passed to `buildChatContext.opts.commandOverride`. */\nexport interface CommandOverride {\n retrievalScope?: string[]\n systemPromptAddendum?: string\n retrievalQueryOverride?: string | null\n /** Singular-item lookup. When set, retrieval bypasses FTS and queries the\n * named table directly via ILIKE on the matchFields. */\n entityLookup?: {\n tableId: string\n value: string\n matchFields: string[]\n }\n /** Singular row by primary key. Used by the inline object-card\n * \"Discuss\" action — the client knows the exact row id from a prior\n * chip. Higher precedence than `entityLookup` (route enforces) and\n * `retrievalQueryOverride`. The retrieval layer still runs the table's\n * `searchFilter` so privacy invariants hold. */\n entityIdFilter?: {\n tableId: string\n id: string\n }\n /** \"Browse\" bypass for bare slash list commands. The search layer\n * treats this as \"skip FTS — return rows from these tableIds ordered\n * by the configured `primaryDateColumn` DESC\". */\n browseScope?: string[]\n /** Presentation hint propagated from the slash command. Hub narrows to\n * its `SlashCommandPresentation` union; lib leaves as `string` for\n * decoupling. */\n presentation?: string\n}\n\n/**\n * Resolve the wire `entityIdFilter` from a `CommandOverride`, optionally\n * narrowed to a specific `tableId`. Returns the validated `{ tableId, id }`\n * pair only when both fields are present, non-empty, and (when an expected\n * tableId is passed) match. Returns `null` otherwise.\n */\nexport function extractEntityIdFilter(\n override: CommandOverride | null | undefined,\n expectedTableId?: string,\n): { tableId: string; id: string } | null {\n const f = override?.entityIdFilter\n if (!f) return null\n const tableId = typeof f.tableId === 'string' ? f.tableId : ''\n const id = typeof f.id === 'string' ? f.id : ''\n if (!tableId || !id) return null\n if (expectedTableId && tableId !== expectedTableId) return null\n return { tableId, id }\n}\n\n/**\n * Server-only synthesizer for the Discuss-action system-prompt addendum.\n * Called by the chat route AFTER `parseWireCommandOverride` accepts an\n * `entityIdFilter` — the addendum text is composed from server-trusted\n * values (the row's tableId + id) so a malicious client can't inject\n * arbitrary prompt content.\n */\nexport function buildDiscussAddendum(args: { tableId: string; id: string }): string {\n const idTag = args.id.length > 24 ? args.id.slice(0, 24) + '…' : args.id\n return (\n `Ask drill-in for row id=\"${args.id}\" in table \"${args.tableId}\". Focus the ` +\n `answer on this single record. If retrieval returns 0 rows (privacy ` +\n `filter), say so plainly per Rule 5b.\\n\\n` +\n `OPEN with the inline card on the FIRST line, immediately followed by ` +\n `the chip and a mono-font id tag — no prose before the card:\\n` +\n ` [card://<type>:${args.id}] [N] \\`${args.tableId} · ${idTag}\\`\\n` +\n `Use the EXACT <type> from the row's <document type=\"...\" id=\"${args.id}\"> tag.\\n\\n` +\n `SURFACE EVERY FIELD PRESENT in the retrieved record — the user already ` +\n `knows the title from the card; the value of Ask is the BODY (description, ` +\n `status, vote counts, dates, linked URLs, …). Walk each non-empty field. ` +\n `Don't invent fields, don't hallucinate values, silently omit absent fields.\\n\\n` +\n `FORMAT: card+chip+id-tag opener, then ONE framing sentence, then a compact ` +\n `bulleted \"**Field** — value\" list. Don't restate fields already in the list.`\n )\n}\n","/**\n * ClickUp custom_item_id → human-readable label resolver.\n *\n * Lib-side subset of the hub's `lib/utils/clickup-task-type-utils.ts`.\n * The hub file also exports delivery / workspace slug helpers used by\n * the sync engine; only the chat-surfaced label resolver migrates here\n * because chat-inline cards and activity feeds need it.\n *\n * Reference: ClickUp's standard task types (custom_item_id values):\n * null/1000=Task, 1001=Milestone, 1002=Recurring, 1003=Subtask,\n * 1004=Form, 1006=Plan, 1007=Strategy, 1008=Bug, 1009=Request,\n * 1010=Feature, 1011=Story, 1012=Epic, 1013=Component, 1014=Initiative.\n */\n\nexport const CUSTOM_ITEM_ID = {\n TASK: 1000,\n MILESTONE: 1001,\n RECURRING: 1002,\n SUBTASK: 1003,\n FORM: 1004,\n PLAN: 1006,\n STRATEGY: 1007,\n BUG: 1008,\n REQUEST: 1009,\n FEATURE: 1010,\n STORY: 1011,\n EPIC: 1012,\n COMPONENT: 1013,\n INITIATIVE: 1014,\n} as const\n\n/**\n * Display name for a ClickUp task type — used in chat-inline cards and\n * activity feeds where the type badge would otherwise show a numeric ID.\n *\n * Returning `null` for unknown IDs lets callers fall back to a generic\n * \"Task\" affordance rather than printing `task-1100` or similar.\n */\nexport function getTaskTypeLabel(\n customItemId: number | null | undefined,\n): string | null {\n switch (customItemId) {\n case CUSTOM_ITEM_ID.TASK: return 'Task'\n case CUSTOM_ITEM_ID.MILESTONE: return 'Milestone'\n case CUSTOM_ITEM_ID.RECURRING: return 'Recurring'\n case CUSTOM_ITEM_ID.SUBTASK: return 'Subtask'\n case CUSTOM_ITEM_ID.FORM: return 'Form'\n case CUSTOM_ITEM_ID.PLAN: return 'Plan'\n case CUSTOM_ITEM_ID.STRATEGY: return 'Strategy'\n case CUSTOM_ITEM_ID.BUG: return 'Bug'\n case CUSTOM_ITEM_ID.REQUEST: return 'Request'\n case CUSTOM_ITEM_ID.FEATURE: return 'Feature'\n case CUSTOM_ITEM_ID.STORY: return 'Story'\n case CUSTOM_ITEM_ID.EPIC: return 'Epic'\n case CUSTOM_ITEM_ID.COMPONENT: return 'Component'\n case CUSTOM_ITEM_ID.INITIATIVE: return 'Initiative'\n default: return null\n }\n}\n","/**\n * Status color-scheme resolver used by chat-adjacent badges (StatusBadge\n * components rendering job, ClickUp task, and log-level statuses).\n *\n * Lib-side subset of the hub's `lib/utils/agent-status-message.ts`. The\n * hub file also carries CSS-class resolvers + an `AgentStatusMessage`\n * builder for the SSE-status surface; those live hub-side because they\n * reference hub-only ODS class names. This function returns the abstract\n * color scheme name only — the consuming `StatusBadge` (in this lib)\n * maps it to concrete colors.\n */\n\nexport type ColorScheme = 'success' | 'error' | 'warning' | 'cyan' | 'default'\n\n/**\n * Map a status to a color scheme name for StatusBadge components.\n * Supports job/processing statuses, ClickUp task statuses, and log levels.\n */\nexport function getStatusColorScheme(status: string): ColorScheme {\n const s = status?.toLowerCase() || ''\n\n // Exact matches first (most common)\n switch (status) {\n case 'completed':\n case 'success':\n case 'active': // review cycles, feature flags, etc.\n return 'success'\n case 'failed':\n case 'failure':\n case 'cancelled':\n case 'error':\n return 'error'\n case 'running':\n case 'processing':\n case 'closed': // review cycles past their active window\n return 'cyan'\n case 'pending':\n case 'warning':\n return 'warning'\n case 'draft': // review cycles not yet opened to reviewers\n case 'info':\n return 'default'\n }\n\n // Partial matches for ClickUp-style statuses (Complete, Done, Working, etc.)\n if (s.includes('complete') || s.includes('done')) return 'success'\n if (s.includes('review')) return 'cyan'\n if (s.includes('working') || s.includes('progress')) return 'warning'\n if (s.includes('blocked') || s.includes('failed')) return 'error'\n\n return 'default'\n}\n","/**\n * Unified URL builders for the third-party app deep-links used by chat\n * surfaces (chip clicks, inline-card tracking rows).\n *\n * Lib-side subset of the hub's `lib/utils/external-app-urls.ts`. Today\n * it carries the ClickUp deep-link helper only — HubSpot and admin\n * routes stay hub-side because they're consumed exclusively by\n * hub-internal mappers.\n */\n\nconst CLICKUP_APP_BASE = 'https://app.clickup.com'\n\n/** ClickUp task detail page in the ClickUp UI. Returns `null` when the\n * external id is missing so consumers don't end up with a\n * `.../t/undefined` link. */\nexport function clickupTaskUrl(externalId: string | null | undefined): string | null {\n if (!externalId) return null\n return `${CLICKUP_APP_BASE}/t/${externalId}`\n}\n","/**\n * Pure utility — true iff `url` has an explicit host (i.e. would resolve\n * to a different origin than where the consumer is running). Used by\n * chat nav decisions and the extracted `decideNewTab` helper.\n *\n * SSR-deterministic: any URL with an explicit host (http://, https://,\n * or protocol-relative //) is treated as cross-origin. By convention\n * same-origin same-app navigation uses RELATIVE paths; an absolute URL\n * with a host is external.\n *\n * Why deterministic: an earlier `window`-dependent implementation\n * returned different values during SSR (false — no window) vs client\n * hydration (true — origin differs), causing React hydration mismatches\n * on every anchor that fell into the no-targetPlatform fallback (e.g.\n * footer \"Support\" links to flamingo.run/support). Same-platform\n * absolute URLs (rare — they only happen when a composer like\n * `buildContentURL` returns an absolute URL for a non-current platform)\n * flow through `decideNewTab`'s PLATFORM branch first (which uses\n * `targetPlatform !== currentSource`) and never reach this fallback.\n */\nexport function isCrossOriginUrl(url: string | null | undefined): boolean {\n if (!url) return false\n // Relative URL — by definition same origin.\n if (url.startsWith('/') && !url.startsWith('//')) return false\n // Anything else — absolute URL (http(s)://) or protocol-relative (//)\n // — is treated as cross-origin.\n return true\n}\n","import React from 'react';\n\n/**\n * `fetchPriorityProp(priority)` — build the right shape for the `<img>` /\n * `<iframe>` fetch-priority hint based on the React major version detected\n * at module load.\n *\n * React 18 only recognizes the lowercase HTML attribute `fetchpriority`\n * and emits a console warning when it sees the camelCase prop. React 19+\n * recognizes the camelCase prop `fetchPriority` (matching the DOM's IDL\n * property) and warns when it sees the lowercase form.\n *\n * Spread the returned object into the element so the rendered DOM ends\n * up with the canonical lowercase `fetchpriority` attribute either way,\n * with zero console warnings on both React versions.\n *\n * Accepts either a boolean (for the simple \"high vs low\" hint at LCP\n * candidates) or an explicit HTML `fetchpriority` value (`'high' | 'low'\n * | 'auto'`) for call sites that always want one specific value.\n */\nconst REACT_MAJOR = parseInt((React.version || '0').split('.')[0], 10);\nconst USE_CAMEL_CASE_FETCH_PRIORITY = REACT_MAJOR >= 19;\n\nexport type FetchPriorityValue = 'high' | 'low' | 'auto';\n\nexport function fetchPriorityProp(\n priority: boolean | FetchPriorityValue | undefined,\n): Record<string, string> {\n // `undefined` → `'auto'` so callers can spread `{...fetchPriorityProp(maybeBool)}`\n // without a separate null-check at every callsite. `'auto'` is the\n // DOM default and emits no warning on either React major.\n const value: FetchPriorityValue =\n priority === undefined\n ? 'auto'\n : typeof priority === 'boolean'\n ? priority ? 'high' : 'low'\n : priority;\n return USE_CAMEL_CASE_FETCH_PRIORITY\n ? { fetchPriority: value }\n : { fetchpriority: value };\n}\n","// Product Release Types\n// Following the blog.ts pattern for consistency\n\nimport type { PlatformRecord } from './platform'\nimport type { BlogTag } from './blog'\nimport type { VideoTeaser, TranscriptWord, SpeakerMapping } from './video-processing'\n\nexport interface ChangelogEntry {\n title: string\n description?: string\n /**\n * Per-entry visibility flag. Optional so product releases (which always render\n * publicly) remain backwards compatible. Investor updates require this field\n * because each entry can be marked internal — see investor-update-utils.ts.\n */\n visibility?: 'public' | 'internal'\n}\n\nexport interface ReleaseMedia {\n id: number\n release_id: number\n media_type: 'image' | 'video' | 'screenshot' | 'demo'\n media_url: string\n display_order: number | null\n title: string | null\n description: string | null\n created_at: string\n updated_at: string\n created_by: string\n}\n\nexport interface ProductReleaseGitHubLink {\n id: number\n release_id: number\n github_release_url: string // Full URL (e.g., https://github.com/org/repo/releases/tag/v2.0.0)\n display_order: number | null\n created_at: string\n}\n\nexport interface KnowledgeBaseLink {\n id: number\n release_id: number\n kb_article_path: string // Relative path (e.g., /api/authentication/api-keys.md)\n display_order: number | null\n created_at: string\n}\n\nexport interface ClickUpRoadmapTask {\n id: number\n release_id: number\n clickup_task_id: string // Just the task ID - details from roadmap folder\n display_order: number | null\n created_at: string\n}\n\nexport interface ClickUpDeliveryTask {\n id: number\n release_id: number\n clickup_task_id: string // Just the task ID - details from delivery list\n display_order: number | null\n created_at: string\n}\n\nexport interface ProductRelease {\n id: number\n title: string\n slug: string\n version: string\n summary: string | null\n content: string | null\n\n // Release metadata\n release_type: 'major' | 'minor' | 'patch' | 'beta' | 'alpha'\n release_status: 'alpha' | 'beta' | 'stable' | 'deprecated'\n release_date: string\n\n // Changelog (JSONB arrays)\n features_added: ChangelogEntry[]\n bugs_fixed: ChangelogEntry[]\n improvements: ChangelogEntry[]\n breaking_changes: ChangelogEntry[]\n\n // External relationships (one-to-many)\n github_releases?: ProductReleaseGitHubLink[]\n knowledge_base_links?: KnowledgeBaseLink[]\n clickup_roadmap_tasks?: ClickUpRoadmapTask[]\n clickup_delivery_tasks?: ClickUpDeliveryTask[]\n release_media?: ReleaseMedia[]\n\n // Media (keeping featured_image for hero)\n featured_image: string | null\n\n // Documentation\n migration_guide_url: string | null\n documentation_url: string | null\n\n // Video (youtube_url for embeds, main_video_url for AI processing)\n youtube_url: string | null\n main_video_url: string | null\n transcript: string | null\n transcript_words_data?: TranscriptWord[]\n srt_content?: string | null\n video_summary: string | null // AI-generated summary from video transcription\n video_bites: VideoTeaser[] // JSONB array of extracted video clips\n highlight_video_url: string | null\n highlight_video_thumbnail: string | null\n highlight_video_duration_ms: number | null\n highlight_video_source: 'manual' | 'ai_generated' | null\n main_video_thumbnail: string | null\n ai_transcript_formatted?: string\n speaker_mapping?: SpeakerMapping\n ai_confidence_transcript: number | null\n ai_confidence_video_summary: number | null // Confidence for video-generated summary\n ai_confidence_summary: number | null // Confidence for entity summary (Release Content Generation)\n\n // SEO\n seo_title: string | null\n seo_description: string | null\n seo_keywords: string | null\n og_image_url: string | null\n\n // Publishing\n status: 'draft' | 'published' | 'archived'\n published_at: string | null\n author_id: string | null\n /**\n * Hydrated by `getRelease` (detail) and `getReleases` (list) via\n * `hydrateAuthor` in the hub DAL. Optional so admin form + every existing\n * consumer that doesn't read author stay backward-compatible.\n */\n author?: {\n id: string\n full_name: string\n avatar_url: string | null\n job_title: string | null\n email?: string | null\n }\n\n // Timestamps\n created_at: string\n updated_at: string\n\n // Editor-provided AI generation instructions (steers Generate Content prompt)\n custom_instructions: string | null\n\n // Analytics\n view_count: number\n download_count: number\n\n // Relations (populated by joins)\n platforms?: PlatformRecord[]\n tags?: BlogTag[]\n product_release_platforms?: Array<{\n platform_id: string\n is_featured: boolean\n featured_order: number | null\n }>\n product_release_tags?: Array<{\n tag_id: number\n }>\n blog_tags?: BlogTag[]\n}\n\nexport interface CreateProductReleaseData {\n title: string\n slug: string\n version: string\n summary?: string\n content?: string\n release_type: 'major' | 'minor' | 'patch' | 'beta' | 'alpha'\n release_status: 'alpha' | 'beta' | 'stable' | 'deprecated'\n release_date: string\n features_added?: ChangelogEntry[]\n bugs_fixed?: ChangelogEntry[]\n improvements?: ChangelogEntry[]\n breaking_changes?: ChangelogEntry[]\n github_releases?: Array<{ github_release_url: string; display_order?: number }>\n knowledge_base_links?: Array<{ kb_article_path: string; display_order?: number }>\n clickup_roadmap_tasks?: Array<{ clickup_task_id: string; display_order?: number }>\n clickup_delivery_tasks?: Array<{ clickup_task_id: string; display_order?: number }>\n release_media?: Array<{ media_type: 'image' | 'video' | 'screenshot' | 'demo'; media_url: string; title?: string; description?: string; display_order?: number }>\n featured_image?: string\n migration_guide_url?: string\n documentation_url?: string\n youtube_url?: string\n main_video_url?: string\n transcript?: string\n srt_content?: string | null\n video_summary?: string // AI-generated summary from video transcription\n video_bites?: VideoTeaser[]\n highlight_video_url?: string | null\n highlight_video_thumbnail?: string | null\n highlight_video_duration_ms?: number | null\n highlight_video_source?: 'manual' | 'ai_generated' | null\n main_video_thumbnail?: string | null\n seo_title?: string\n seo_description?: string\n seo_keywords?: string\n og_image_url?: string\n status: 'draft' | 'published' | 'archived'\n published_at?: string | null\n author_id: string\n platforms: string[] // Array of platform IDs (UUIDs)\n featured_platform?: string // Platform ID for featured\n tags: number[] // Array of tag IDs\n custom_instructions?: string | null\n}\n\nexport type UpdateProductReleaseData = Partial<CreateProductReleaseData>\n\nexport interface ProductReleaseFilters {\n platform?: string | 'all'\n tags?: string[]\n version?: string\n release_type?: ('major' | 'minor' | 'patch' | 'beta' | 'alpha')[]\n release_status?: ('alpha' | 'beta' | 'stable' | 'deprecated')[]\n has_breaking_changes?: boolean\n search?: string\n featured?: boolean\n status?: string\n limit?: number\n offset?: number\n ids?: (number | string)[]\n}\n\nexport interface ProductReleaseListResponse {\n data: ProductRelease[]\n count: number\n}\n\n// GitHub Release interface (for wizard)\nexport interface GitHubRelease {\n id: string\n tag_name: string\n name: string\n body: string\n published_at: string\n html_url: string\n prerelease: boolean\n draft: boolean\n}\n\n// Release type options for dropdowns\nexport const releaseTypeOptions = [\n { value: 'major', label: 'Major Release', description: 'Breaking changes, new architecture', color: 'red' },\n { value: 'minor', label: 'Minor Release', description: 'New features, backward compatible', color: 'blue' },\n { value: 'patch', label: 'Patch Release', description: 'Bug fixes only', color: 'green' },\n { value: 'beta', label: 'Beta Release', description: 'Pre-release testing version', color: 'yellow' },\n { value: 'alpha', label: 'Alpha Release', description: 'Early testing version', color: 'orange' }\n] as const\n\n// Release status options\nexport const releaseStatusOptions = [\n { value: 'alpha', label: 'Alpha', description: 'Early development, unstable', color: 'orange' },\n { value: 'beta', label: 'Beta', description: 'Feature complete, testing', color: 'yellow' },\n { value: 'stable', label: 'Stable', description: 'Production ready', color: 'green' },\n { value: 'deprecated', label: 'Deprecated', description: 'No longer supported', color: 'gray' }\n] as const\n\n// Changelog category labels\nexport const changelogLabels = {\n features_added: 'Features Added',\n bugs_fixed: 'Bugs Fixed',\n improvements: 'Improvements',\n breaking_changes: 'Breaking Changes'\n} as const\n\n// Semantic versioning validation regex\nexport const SEMVER_REGEX = /^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$/\n","/**\n * Canonical per-section metadata for the OpenFrame dev-center surfaces\n * (Roadmap / Bug-fixes & Enhancements / Releases / Onboarding Guides).\n *\n * One file co-locates every per-section value the openframe homepage\n * navigator card AND the destination full-page hero both consume —\n * icon, brief navigator description, longer hero paragraph, search\n * config (placeholder + paramKey), filter config (paramKey + options).\n *\n * Adding a 5th section is one edit here and zero edits across the\n * page files / navigator grid.\n *\n * EMBEDDER NOTE — `onboarding`:\n * The `onboarding` entry is INERT on `hero`/`search`/`filter` because\n * `/onboarding-guides` is owned by `OnboardingGuidesCatalogView` (a\n * hub-side full-page view), not the shared `DevSectionView` chrome.\n * This entry exists ONLY to drive the homepage navigator card. Any\n * embedder iterating the registry must SKIP `onboarding` if they\n * don't host the `/onboarding-guides` route — e.g.\n * `Object.values(OPENFRAME_DEV_SECTIONS).filter(s => s.href !== '/onboarding-guides')`.\n *\n * SERVER-BUNDLE SAFETY:\n * This module imports lucide-react icon components as JSX values but\n * never RENDERS them at module load. Lib's tsup config places `utils/`\n * in the server bundle (no `\"use client\"` banner), which is safe\n * because component-function references don't execute on import.\n * Precedent: `src/utils/platform-config.tsx` (also lucide imports,\n * also server-bundle, also imported by route-page `metadata` exports).\n */\n\nimport { Map as MapIcon, Wrench, Rocket, GraduationCap, LifeBuoy, type LucideIcon } from 'lucide-react'\nimport { releaseStatusOptions } from '../../types'\n\n// Roadmap status options — `as const` preserves readonly tuple typing\n// across the registry boundary.\nexport const ROADMAP_STATUS_OPTIONS = [\n { value: 'all', label: 'All' },\n { value: 'completed', label: 'Completed' },\n { value: 'in_progress', label: 'In Progress' },\n] as const\n\n// Delivery (ClickUp custom item type) filter options. `Bug` and `Request`\n// are the ClickUp `custom_item_id` labels — 1008 / 1009.\nexport const DELIVERY_TASK_TYPE_OPTIONS = [\n { value: 'all', label: 'All' },\n { value: 'Bug', label: 'Bug-fix' },\n { value: 'Request', label: 'Enhancement' },\n] as const\n\n// Ticket status filter for the Help Center. Lowercase wire values\n// match what `/api/chat/agent/find-ticket` accepts in `body.status`\n// (the route normalizes to lowercase + allowlists 'open' | 'closed'\n// before threading into `findTicketExecutor`'s `selfStatus` scope).\nexport const TICKET_STATUS_OPTIONS = [\n { value: 'all', label: 'All' },\n { value: 'open', label: 'Open' },\n { value: 'closed', label: 'Closed' },\n] as const\n\nexport interface OpenframeDevSection {\n /** Route href the navigator card and any internal cross-link composes. */\n href: string\n icon: LucideIcon\n /** Brief copy for the homepage navigator card (≈50 char teaser). */\n navigator: {\n title: string\n description: string\n }\n /** Longer copy for the destination page hero (≈120-150 char marketing paragraph). */\n hero: {\n title: string\n description: string\n }\n /** Inline search bar configuration. */\n search: {\n /** Placeholder text shown in the search input. */\n placeholder: string\n /** URL search param the input writes on submit and the list reads on fetch. */\n paramKey: string\n } | null\n /** Filter pill row configuration. `null` when the section has no filter (e.g. onboarding-guides). */\n filter: {\n label: string\n /** URL search param the pills write and the list reads. */\n paramKey: string\n /** The option value that maps to \"no filter applied\". When selected,\n * the URL param is removed instead of being set. Defaults to the\n * first option's value if omitted — explicit field guards against\n * brittleness if `options` is later reordered. */\n defaultValue: string\n options: readonly { value: string; label: string }[]\n } | null\n}\n\nexport const OPENFRAME_DEV_SECTIONS = {\n roadmap: {\n href: '/roadmap',\n icon: MapIcon,\n navigator: {\n title: 'Development Roadmap',\n description: \"What we're building next — vote on upcoming features.\",\n },\n hero: {\n title: 'Development Roadmap',\n description:\n \"See what's in flight, what's planned, and what's up for community vote. The entire OpenFrame roadmap is public.\",\n },\n search: { placeholder: 'Search roadmap items...', paramKey: 'search' },\n filter: { label: 'Status', paramKey: 'status', defaultValue: 'all', options: ROADMAP_STATUS_OPTIONS },\n },\n delivery: {\n href: '/bug-fixes-and-enhancements',\n icon: Wrench,\n navigator: {\n title: 'Bug-fixes & Enhancements',\n description: 'Recently shipped fixes and improvements.',\n },\n hero: {\n title: 'Bug-fixes & Enhancements',\n description:\n 'A running log of fixes and improvements shipping into OpenFrame — recently completed and actively in progress.',\n },\n search: { placeholder: 'Search tasks...', paramKey: 'search' },\n filter: { label: 'Type', paramKey: 'task_type', defaultValue: 'all', options: DELIVERY_TASK_TYPE_OPTIONS },\n },\n releases: {\n href: '/releases',\n icon: Rocket,\n navigator: {\n title: 'Product Releases',\n description: 'Version history and release notes.',\n },\n hero: {\n title: 'Product Releases',\n description:\n 'Version notes, change summaries, and stability tier (alpha / beta / stable) for every OpenFrame release.',\n },\n search: { placeholder: 'Search releases...', paramKey: 'search' },\n filter: { label: 'Status', paramKey: 'release_status', defaultValue: 'all', options: releaseStatusOptions },\n },\n onboarding: {\n href: '/onboarding-guides',\n icon: GraduationCap,\n navigator: {\n title: 'Onboarding Guides',\n description: 'Step-by-step product walkthroughs.',\n },\n // `hero` / `search` / `filter` are intentionally inert here —\n // /onboarding-guides is owned by OnboardingGuidesCatalogView, not\n // DevSectionView. This entry exists ONLY to drive the homepage\n // navigator card so all 4 cards stay in one registry.\n hero: { title: '', description: '' },\n search: null,\n filter: null,\n },\n tickets: {\n href: '/tickets',\n icon: LifeBuoy,\n navigator: {\n title: 'Help Center',\n description: 'Open and manage your support tickets.',\n },\n hero: {\n title: 'Help Center',\n description:\n 'Open new tickets, follow up on existing ones, and track responses from the team — all in one place.',\n },\n search: { placeholder: 'Search your tickets...', paramKey: 'search' },\n filter: {\n label: 'Status',\n paramKey: 'status',\n defaultValue: 'all',\n options: TICKET_STATUS_OPTIONS,\n },\n },\n} as const satisfies Record<string, OpenframeDevSection>\n\nexport type OpenframeDevSectionKey = keyof typeof OPENFRAME_DEV_SECTIONS\n"]}