octocms 0.4.13 → 0.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin/AdminApp.d.ts +1 -1
- package/dist/admin/AdminApp.js +2 -2
- package/dist/admin/AdminApp.js.map +1 -1
- package/dist/admin/actions/agent.d.ts +3 -3
- package/dist/admin/actions/agent.js.map +1 -1
- package/dist/admin/actions/media.d.ts.map +1 -1
- package/dist/admin/actions/media.js +3 -1
- package/dist/admin/actions/media.js.map +1 -1
- package/dist/admin/pages/AdminErrorView.d.ts.map +1 -1
- package/dist/admin/pages/AdminErrorView.js +9 -9
- package/dist/admin/pages/AdminErrorView.js.map +1 -1
- package/dist/admin/pages/AdminLayout.d.ts +1 -1
- package/dist/admin/pages/AdminLayout.d.ts.map +1 -1
- package/dist/admin/pages/AdminLayout.js +2 -2
- package/dist/admin/pages/AdminLayout.js.map +1 -1
- package/dist/admin/pages/ChatPage.d.ts +3 -3
- package/dist/admin/pages/ChatPage.d.ts.map +1 -1
- package/dist/admin/pages/ChatPage.js +8 -5
- package/dist/admin/pages/ChatPage.js.map +1 -1
- package/dist/admin/pages/CollectionPage.d.ts.map +1 -1
- package/dist/admin/pages/CollectionPage.js +5 -1
- package/dist/admin/pages/CollectionPage.js.map +1 -1
- package/dist/admin/pages/ContentModelPage.d.ts.map +1 -1
- package/dist/admin/pages/ContentModelPage.js +5 -1
- package/dist/admin/pages/ContentModelPage.js.map +1 -1
- package/dist/admin/pages/ContentPage.d.ts.map +1 -1
- package/dist/admin/pages/ContentPage.js +5 -1
- package/dist/admin/pages/ContentPage.js.map +1 -1
- package/dist/admin/pages/ContentTypePage.d.ts.map +1 -1
- package/dist/admin/pages/ContentTypePage.js +6 -2
- package/dist/admin/pages/ContentTypePage.js.map +1 -1
- package/dist/admin/pages/EntryPage.d.ts.map +1 -1
- package/dist/admin/pages/EntryPage.js +5 -1
- package/dist/admin/pages/EntryPage.js.map +1 -1
- package/dist/admin/pages/MediaAssetPage.d.ts.map +1 -1
- package/dist/admin/pages/MediaAssetPage.js +6 -2
- package/dist/admin/pages/MediaAssetPage.js.map +1 -1
- package/dist/admin/pages/MediaPage.d.ts.map +1 -1
- package/dist/admin/pages/MediaPage.js +6 -2
- package/dist/admin/pages/MediaPage.js.map +1 -1
- package/dist/admin/theme/toggle.d.ts.map +1 -1
- package/dist/admin/theme/toggle.js +27 -27
- package/dist/admin/theme/toggle.js.map +1 -1
- package/dist/agent/chatSetup.d.ts +19 -0
- package/dist/agent/chatSetup.d.ts.map +1 -0
- package/dist/agent/chatSetup.js +119 -0
- package/dist/agent/chatSetup.js.map +1 -0
- package/dist/agent/featureFlag.d.ts +3 -3
- package/dist/agent/featureFlag.js.map +1 -1
- package/dist/agent/index.cjs +75 -5309
- package/dist/agent/index.cjs.map +1 -1
- package/dist/{agentDocs-M3R2CPUQ.js → agentDocs-QZ4NOQVH.js} +2 -2
- package/dist/{chunk-DCDFWNC6.js → chunk-I7VNI2IG.js} +4 -7
- package/dist/{chunk-DCDFWNC6.js.map → chunk-I7VNI2IG.js.map} +1 -1
- package/dist/chunk-TOUAHFDW.js +7 -0
- package/dist/{chunk-NAHOP7TG.js.map → chunk-TOUAHFDW.js.map} +1 -1
- package/dist/cli/index.js +4 -4
- package/dist/cli/lib/templates.js +3 -6
- package/dist/cli/lib/templates.js.map +1 -1
- package/dist/components/Chat/ChatAgentSetup.d.ts +7 -0
- package/dist/components/Chat/ChatAgentSetup.d.ts.map +1 -0
- package/dist/components/Chat/ChatAgentSetup.js +37 -0
- package/dist/components/Chat/ChatAgentSetup.js.map +1 -0
- package/dist/components/Chat/ChatPage.d.ts +6 -1
- package/dist/components/Chat/ChatPage.d.ts.map +1 -1
- package/dist/components/Chat/ChatPage.js +123 -128
- package/dist/components/Chat/ChatPage.js.map +1 -1
- package/dist/components/Chat/ChatSidebar.d.ts +10 -0
- package/dist/components/Chat/ChatSidebar.d.ts.map +1 -0
- package/dist/components/Chat/ChatSidebar.js +45 -0
- package/dist/components/Chat/ChatSidebar.js.map +1 -0
- package/dist/components/Chat/Composer.d.ts.map +1 -1
- package/dist/components/Chat/Composer.js +28 -45
- package/dist/components/Chat/Composer.js.map +1 -1
- package/dist/components/Chat/Message.d.ts.map +1 -1
- package/dist/components/Chat/Message.js +40 -39
- package/dist/components/Chat/Message.js.map +1 -1
- package/dist/components/Chat/ProposalCard.d.ts.map +1 -1
- package/dist/components/Chat/ProposalCard.js +56 -67
- package/dist/components/Chat/ProposalCard.js.map +1 -1
- package/dist/components/Chat/ToolCallCard.d.ts.map +1 -1
- package/dist/components/Chat/ToolCallCard.js +29 -38
- package/dist/components/Chat/ToolCallCard.js.map +1 -1
- package/dist/components/Chat/chatStorage.d.ts +64 -0
- package/dist/components/Chat/chatStorage.d.ts.map +1 -0
- package/dist/components/Chat/chatStorage.js +154 -0
- package/dist/components/Chat/chatStorage.js.map +1 -0
- package/dist/components/Chat/useChatHistory.d.ts +12 -0
- package/dist/components/Chat/useChatHistory.d.ts.map +1 -0
- package/dist/components/Chat/useChatHistory.js +196 -0
- package/dist/components/Chat/useChatHistory.js.map +1 -0
- package/dist/components/Chat/useChatStream.d.ts +6 -0
- package/dist/components/Chat/useChatStream.d.ts.map +1 -1
- package/dist/components/Chat/useChatStream.js +31 -2
- package/dist/components/Chat/useChatStream.js.map +1 -1
- package/dist/components/CommandK/CommandK.d.ts +1 -1
- package/dist/components/CommandK/CommandK.d.ts.map +1 -1
- package/dist/components/CommandK/CommandK.js +100 -116
- package/dist/components/CommandK/CommandK.js.map +1 -1
- package/dist/components/CommandK/parts.d.ts.map +1 -1
- package/dist/components/CommandK/parts.js +9 -11
- package/dist/components/CommandK/parts.js.map +1 -1
- package/dist/components/ContentModel/ConditionalBranchesEditor.d.ts.map +1 -1
- package/dist/components/ContentModel/ConditionalBranchesEditor.js +40 -45
- package/dist/components/ContentModel/ConditionalBranchesEditor.js.map +1 -1
- package/dist/components/ContentModel/ContentModelList.d.ts.map +1 -1
- package/dist/components/ContentModel/ContentModelList.js +65 -80
- package/dist/components/ContentModel/ContentModelList.js.map +1 -1
- package/dist/components/ContentModel/ContentTypeDetail.d.ts.map +1 -1
- package/dist/components/ContentModel/ContentTypeDetail.js +253 -280
- package/dist/components/ContentModel/ContentTypeDetail.js.map +1 -1
- package/dist/components/ContentModel/CreateContentTypeDialog.d.ts.map +1 -1
- package/dist/components/ContentModel/CreateContentTypeDialog.js +42 -30
- package/dist/components/ContentModel/CreateContentTypeDialog.js.map +1 -1
- package/dist/components/ContentModel/DeleteContentTypeDialog.d.ts.map +1 -1
- package/dist/components/ContentModel/DeleteContentTypeDialog.js +14 -15
- package/dist/components/ContentModel/DeleteContentTypeDialog.js.map +1 -1
- package/dist/components/ContentModel/DeleteFieldDialog.d.ts.map +1 -1
- package/dist/components/ContentModel/DeleteFieldDialog.js +27 -20
- package/dist/components/ContentModel/DeleteFieldDialog.js.map +1 -1
- package/dist/components/ContentModel/EditContentTypeDialog.d.ts.map +1 -1
- package/dist/components/ContentModel/EditContentTypeDialog.js +46 -34
- package/dist/components/ContentModel/EditContentTypeDialog.js.map +1 -1
- package/dist/components/ContentModel/FieldDialog.d.ts.map +1 -1
- package/dist/components/ContentModel/FieldDialog.js +95 -84
- package/dist/components/ContentModel/FieldDialog.js.map +1 -1
- package/dist/components/ContentModel/RichTextOptionsEditor.d.ts.map +1 -1
- package/dist/components/ContentModel/RichTextOptionsEditor.js +90 -81
- package/dist/components/ContentModel/RichTextOptionsEditor.js.map +1 -1
- package/dist/components/ContentModel/SchemaImpactList.d.ts.map +1 -1
- package/dist/components/ContentModel/SchemaImpactList.js +19 -36
- package/dist/components/ContentModel/SchemaImpactList.js.map +1 -1
- package/dist/components/ContentModel/SchemaOptionFieldInput.d.ts.map +1 -1
- package/dist/components/ContentModel/SchemaOptionFieldInput.js +63 -84
- package/dist/components/ContentModel/SchemaOptionFieldInput.js.map +1 -1
- package/dist/components/ContentModel/skeletons/ContentModelListPageSkeleton.d.ts +3 -0
- package/dist/components/ContentModel/skeletons/ContentModelListPageSkeleton.d.ts.map +1 -0
- package/dist/components/ContentModel/skeletons/ContentModelListPageSkeleton.js +15 -0
- package/dist/components/ContentModel/skeletons/ContentModelListPageSkeleton.js.map +1 -0
- package/dist/components/ContentModel/skeletons/ContentTypeDetailPageSkeleton.d.ts +3 -0
- package/dist/components/ContentModel/skeletons/ContentTypeDetailPageSkeleton.d.ts.map +1 -0
- package/dist/components/ContentModel/skeletons/ContentTypeDetailPageSkeleton.js +11 -0
- package/dist/components/ContentModel/skeletons/ContentTypeDetailPageSkeleton.js.map +1 -0
- package/dist/components/ContentModel/skeletons/FieldTableSkeleton.js +3 -3
- package/dist/components/ContentModel/skeletons/FieldTableSkeleton.js.map +1 -1
- package/dist/components/ContentModel/skeletons/SchemaTableSkeleton.d.ts.map +1 -1
- package/dist/components/ContentModel/skeletons/SchemaTableSkeleton.js +4 -12
- package/dist/components/ContentModel/skeletons/SchemaTableSkeleton.js.map +1 -1
- package/dist/components/Dashboard/DashboardContent.d.ts.map +1 -1
- package/dist/components/Dashboard/DashboardContent.js +87 -114
- package/dist/components/Dashboard/DashboardContent.js.map +1 -1
- package/dist/components/Dashboard/RecentPullRequests.d.ts.map +1 -1
- package/dist/components/Dashboard/RecentPullRequests.js +33 -45
- package/dist/components/Dashboard/RecentPullRequests.js.map +1 -1
- package/dist/components/Dashboard/skeletons/ContentPageChromeSkeleton.d.ts +2 -7
- package/dist/components/Dashboard/skeletons/ContentPageChromeSkeleton.d.ts.map +1 -1
- package/dist/components/Dashboard/skeletons/ContentPageChromeSkeleton.js +5 -20
- package/dist/components/Dashboard/skeletons/ContentPageChromeSkeleton.js.map +1 -1
- package/dist/components/Dashboard/skeletons/ContentTableSkeleton.js +9 -9
- package/dist/components/Dashboard/skeletons/ContentTableSkeleton.js.map +1 -1
- package/dist/components/Dashboard/skeletons/DashboardCollectionPageSkeleton.d.ts +3 -0
- package/dist/components/Dashboard/skeletons/DashboardCollectionPageSkeleton.d.ts.map +1 -0
- package/dist/components/Dashboard/skeletons/DashboardCollectionPageSkeleton.js +10 -0
- package/dist/components/Dashboard/skeletons/DashboardCollectionPageSkeleton.js.map +1 -0
- package/dist/components/Dashboard/skeletons/DashboardPageSkeleton.d.ts +9 -0
- package/dist/components/Dashboard/skeletons/DashboardPageSkeleton.d.ts.map +1 -0
- package/dist/components/Dashboard/skeletons/DashboardPageSkeleton.js +16 -0
- package/dist/components/Dashboard/skeletons/DashboardPageSkeleton.js.map +1 -0
- package/dist/components/Dashboard/skeletons/LeftPanelSkeleton.d.ts.map +1 -1
- package/dist/components/Dashboard/skeletons/LeftPanelSkeleton.js +7 -18
- package/dist/components/Dashboard/skeletons/LeftPanelSkeleton.js.map +1 -1
- package/dist/components/DiffView/DiffHunk.d.ts.map +1 -1
- package/dist/components/DiffView/DiffHunk.js +12 -40
- package/dist/components/DiffView/DiffHunk.js.map +1 -1
- package/dist/components/DiffView/DiffView.d.ts.map +1 -1
- package/dist/components/DiffView/DiffView.js +33 -52
- package/dist/components/DiffView/DiffView.js.map +1 -1
- package/dist/components/EditPost/EditPost.d.ts.map +1 -1
- package/dist/components/EditPost/EditPost.js +139 -200
- package/dist/components/EditPost/EditPost.js.map +1 -1
- package/dist/components/EditPost/skeletons/EditPostPageSkeleton.d.ts +3 -0
- package/dist/components/EditPost/skeletons/EditPostPageSkeleton.d.ts.map +1 -0
- package/dist/components/EditPost/skeletons/EditPostPageSkeleton.js +21 -0
- package/dist/components/EditPost/skeletons/EditPostPageSkeleton.js.map +1 -0
- package/dist/components/EditPost/skeletons/EntryFormSkeleton.d.ts.map +1 -1
- package/dist/components/EditPost/skeletons/EntryFormSkeleton.js +1 -9
- package/dist/components/EditPost/skeletons/EntryFormSkeleton.js.map +1 -1
- package/dist/components/EditPost/skeletons/EntrySidebarSkeleton.d.ts.map +1 -1
- package/dist/components/EditPost/skeletons/EntrySidebarSkeleton.js +12 -20
- package/dist/components/EditPost/skeletons/EntrySidebarSkeleton.js.map +1 -1
- package/dist/components/ErrorBoundary/ErrorBoundary.d.ts.map +1 -0
- package/dist/components/{ErrorBoundary.js → ErrorBoundary/ErrorBoundary.js} +15 -21
- package/dist/components/ErrorBoundary/ErrorBoundary.js.map +1 -0
- package/dist/components/HistorySection/HistorySection.d.ts.map +1 -1
- package/dist/components/HistorySection/HistorySection.js +23 -42
- package/dist/components/HistorySection/HistorySection.js.map +1 -1
- package/dist/components/InlineEntryEditor/InlineEntryEditor.d.ts.map +1 -1
- package/dist/components/InlineEntryEditor/InlineEntryEditor.js +120 -123
- package/dist/components/InlineEntryEditor/InlineEntryEditor.js.map +1 -1
- package/dist/components/Layout/BranchSelectorDialog.d.ts +9 -0
- package/dist/components/Layout/BranchSelectorDialog.d.ts.map +1 -0
- package/dist/components/Layout/BranchSelectorDialog.js +130 -0
- package/dist/components/Layout/BranchSelectorDialog.js.map +1 -0
- package/dist/components/Layout/CreateBranchDialog.d.ts.map +1 -0
- package/dist/components/{CreateBranchDialog.js → Layout/CreateBranchDialog.js} +16 -16
- package/dist/components/Layout/CreateBranchDialog.js.map +1 -0
- package/dist/components/Layout/Layout.d.ts.map +1 -1
- package/dist/components/Layout/Layout.js +18 -26
- package/dist/components/Layout/Layout.js.map +1 -1
- package/dist/components/Layout/LeftNavItem.d.ts.map +1 -1
- package/dist/components/Layout/LeftNavItem.js +7 -7
- package/dist/components/Layout/LeftNavItem.js.map +1 -1
- package/dist/components/Layout/Page.d.ts +16 -0
- package/dist/components/Layout/Page.d.ts.map +1 -0
- package/dist/components/Layout/Page.js +47 -0
- package/dist/components/Layout/Page.js.map +1 -0
- package/dist/components/Layout/TopHeader.d.ts +1 -1
- package/dist/components/Layout/TopHeader.d.ts.map +1 -1
- package/dist/components/Layout/TopHeader.js +70 -165
- package/dist/components/Layout/TopHeader.js.map +1 -1
- package/dist/components/Layout/UserAccountDialog.d.ts +12 -0
- package/dist/components/Layout/UserAccountDialog.d.ts.map +1 -0
- package/dist/components/Layout/UserAccountDialog.js +48 -0
- package/dist/components/Layout/UserAccountDialog.js.map +1 -0
- package/dist/components/Layout/skeletons/AgentNavSkeleton.js +1 -1
- package/dist/components/Layout/skeletons/AgentNavSkeleton.js.map +1 -1
- package/dist/components/Layout/skeletons/BranchChipSkeleton.d.ts.map +1 -1
- package/dist/components/Layout/skeletons/BranchChipSkeleton.js +1 -8
- package/dist/components/Layout/skeletons/BranchChipSkeleton.js.map +1 -1
- package/dist/components/Layout/skeletons/NeutralPageSkeleton.d.ts +3 -0
- package/dist/components/Layout/skeletons/NeutralPageSkeleton.d.ts.map +1 -0
- package/dist/components/Layout/skeletons/NeutralPageSkeleton.js +11 -0
- package/dist/components/Layout/skeletons/NeutralPageSkeleton.js.map +1 -0
- package/dist/components/Layout/skeletons/PageChromeSkeleton.d.ts +19 -0
- package/dist/components/Layout/skeletons/PageChromeSkeleton.d.ts.map +1 -0
- package/dist/components/Layout/skeletons/PageChromeSkeleton.js +31 -0
- package/dist/components/Layout/skeletons/PageChromeSkeleton.js.map +1 -0
- package/dist/components/Layout/skeletons/RouteMainSlotSkeleton.d.ts +9 -0
- package/dist/components/Layout/skeletons/RouteMainSlotSkeleton.d.ts.map +1 -0
- package/dist/components/Layout/skeletons/RouteMainSlotSkeleton.js +15 -0
- package/dist/components/Layout/skeletons/RouteMainSlotSkeleton.js.map +1 -0
- package/dist/components/Layout/skeletons/TopHeaderSkeleton.d.ts.map +1 -1
- package/dist/components/Layout/skeletons/TopHeaderSkeleton.js +10 -17
- package/dist/components/Layout/skeletons/TopHeaderSkeleton.js.map +1 -1
- package/dist/components/Layout/skeletons/routeSkeletons.d.ts +16 -0
- package/dist/components/Layout/skeletons/routeSkeletons.d.ts.map +1 -0
- package/dist/components/Layout/skeletons/routeSkeletons.js +48 -0
- package/dist/components/Layout/skeletons/routeSkeletons.js.map +1 -0
- package/dist/components/LinkedBySection/LinkedBySection.js +13 -13
- package/dist/components/LinkedBySection/LinkedBySection.js.map +1 -1
- package/dist/components/MediaAsset/MediaAsset.d.ts +1 -1
- package/dist/components/MediaAsset/MediaAsset.d.ts.map +1 -1
- package/dist/components/MediaAsset/MediaAsset.js +126 -136
- package/dist/components/MediaAsset/MediaAsset.js.map +1 -1
- package/dist/components/MediaAsset/skeletons/MediaAssetPageSkeleton.d.ts +3 -0
- package/dist/components/MediaAsset/skeletons/MediaAssetPageSkeleton.d.ts.map +1 -0
- package/dist/components/MediaAsset/skeletons/MediaAssetPageSkeleton.js +21 -0
- package/dist/components/MediaAsset/skeletons/MediaAssetPageSkeleton.js.map +1 -0
- package/dist/components/MediaAsset/skeletons/MediaMetadataFormSkeleton.d.ts.map +1 -1
- package/dist/components/MediaAsset/skeletons/MediaMetadataFormSkeleton.js +26 -22
- package/dist/components/MediaAsset/skeletons/MediaMetadataFormSkeleton.js.map +1 -1
- package/dist/components/MediaAsset/skeletons/MediaPreviewSkeleton.d.ts.map +1 -1
- package/dist/components/MediaAsset/skeletons/MediaPreviewSkeleton.js +1 -9
- package/dist/components/MediaAsset/skeletons/MediaPreviewSkeleton.js.map +1 -1
- package/dist/components/MediaManager/CreateFolderDialog.d.ts.map +1 -1
- package/dist/components/MediaManager/CreateFolderDialog.js +15 -8
- package/dist/components/MediaManager/CreateFolderDialog.js.map +1 -1
- package/dist/components/MediaManager/DeleteFolderDialog.d.ts.map +1 -1
- package/dist/components/MediaManager/DeleteFolderDialog.js +1 -2
- package/dist/components/MediaManager/DeleteFolderDialog.js.map +1 -1
- package/dist/components/MediaManager/MarkdownImageEditToolbar.d.ts.map +1 -1
- package/dist/components/MediaManager/MarkdownImageEditToolbar.js +7 -9
- package/dist/components/MediaManager/MarkdownImageEditToolbar.js.map +1 -1
- package/dist/components/MediaManager/MarkdownInsertImageDialog.d.ts.map +1 -1
- package/dist/components/MediaManager/MarkdownInsertImageDialog.js +6 -9
- package/dist/components/MediaManager/MarkdownInsertImageDialog.js.map +1 -1
- package/dist/components/MediaManager/MediaLeftPanel.d.ts.map +1 -1
- package/dist/components/MediaManager/MediaLeftPanel.js +21 -23
- package/dist/components/MediaManager/MediaLeftPanel.js.map +1 -1
- package/dist/components/MediaManager/MediaListTable.d.ts.map +1 -1
- package/dist/components/MediaManager/MediaListTable.js +15 -21
- package/dist/components/MediaManager/MediaListTable.js.map +1 -1
- package/dist/components/MediaManager/MediaManager.d.ts.map +1 -1
- package/dist/components/MediaManager/MediaManager.js +101 -151
- package/dist/components/MediaManager/MediaManager.js.map +1 -1
- package/dist/components/MediaManager/MediaSelectDialog.js +22 -64
- package/dist/components/MediaManager/MediaSelectDialog.js.map +1 -1
- package/dist/components/MediaManager/MediaUploadBar.d.ts.map +1 -1
- package/dist/components/MediaManager/MediaUploadBar.js +9 -10
- package/dist/components/MediaManager/MediaUploadBar.js.map +1 -1
- package/dist/components/MediaManager/MediaUploadDialog.d.ts.map +1 -1
- package/dist/components/MediaManager/MediaUploadDialog.js +18 -11
- package/dist/components/MediaManager/MediaUploadDialog.js.map +1 -1
- package/dist/components/MediaManager/MediaViewModeSwitcher.d.ts +8 -0
- package/dist/components/MediaManager/MediaViewModeSwitcher.d.ts.map +1 -0
- package/dist/components/MediaManager/MediaViewModeSwitcher.js +14 -0
- package/dist/components/MediaManager/MediaViewModeSwitcher.js.map +1 -0
- package/dist/components/MediaManager/skeletons/MediaGridSkeleton.d.ts.map +1 -1
- package/dist/components/MediaManager/skeletons/MediaGridSkeleton.js +4 -12
- package/dist/components/MediaManager/skeletons/MediaGridSkeleton.js.map +1 -1
- package/dist/components/MediaManager/skeletons/MediaLeftPanelSkeleton.d.ts.map +1 -1
- package/dist/components/MediaManager/skeletons/MediaLeftPanelSkeleton.js +5 -13
- package/dist/components/MediaManager/skeletons/MediaLeftPanelSkeleton.js.map +1 -1
- package/dist/components/MediaManager/skeletons/MediaListTableSkeleton.d.ts.map +1 -1
- package/dist/components/MediaManager/skeletons/MediaListTableSkeleton.js +7 -15
- package/dist/components/MediaManager/skeletons/MediaListTableSkeleton.js.map +1 -1
- package/dist/components/MediaManager/skeletons/MediaManagerMainSkeleton.d.ts +3 -0
- package/dist/components/MediaManager/skeletons/MediaManagerMainSkeleton.d.ts.map +1 -0
- package/dist/components/MediaManager/skeletons/MediaManagerMainSkeleton.js +15 -0
- package/dist/components/MediaManager/skeletons/MediaManagerMainSkeleton.js.map +1 -0
- package/dist/components/MediaManager/skeletons/MediaManagerPageSkeleton.d.ts +3 -0
- package/dist/components/MediaManager/skeletons/MediaManagerPageSkeleton.d.ts.map +1 -0
- package/dist/components/MediaManager/skeletons/MediaManagerPageSkeleton.js +21 -0
- package/dist/components/MediaManager/skeletons/MediaManagerPageSkeleton.js.map +1 -0
- package/dist/components/public/MarkdownContent.d.ts.map +1 -1
- package/dist/components/public/MarkdownContent.js +1 -2
- package/dist/components/public/MarkdownContent.js.map +1 -1
- package/dist/components/public/RichTextContent.d.ts.map +1 -1
- package/dist/components/public/RichTextContent.js +19 -8
- package/dist/components/public/RichTextContent.js.map +1 -1
- package/dist/components/public/SearchBox.d.ts.map +1 -1
- package/dist/components/public/SearchBox.js +32 -60
- package/dist/components/public/SearchBox.js.map +1 -1
- package/dist/components/public/index.cjs +6 -413
- package/dist/components/public/index.cjs.map +1 -1
- package/dist/components/skeletons/MainSlotSkeleton.d.ts +0 -7
- package/dist/components/skeletons/MainSlotSkeleton.d.ts.map +1 -1
- package/dist/components/skeletons/MainSlotSkeleton.js +4 -17
- package/dist/components/skeletons/MainSlotSkeleton.js.map +1 -1
- package/dist/components/skeletons/blocks.d.ts.map +1 -1
- package/dist/components/skeletons/blocks.js +15 -7
- package/dist/components/skeletons/blocks.js.map +1 -1
- package/dist/components/skeletons/index.d.ts +4 -4
- package/dist/components/skeletons/index.d.ts.map +1 -1
- package/dist/components/skeletons/index.js +1 -2
- package/dist/components/skeletons/index.js.map +1 -1
- package/dist/components/skeletons/primitives.d.ts +2 -2
- package/dist/components/skeletons/primitives.d.ts.map +1 -1
- package/dist/components/skeletons/primitives.js +3 -3
- package/dist/components/skeletons/primitives.js.map +1 -1
- package/dist/components/test/dndTestUtils.d.ts +7 -0
- package/dist/components/test/dndTestUtils.d.ts.map +1 -0
- package/dist/components/test/dndTestUtils.js +15 -0
- package/dist/components/test/dndTestUtils.js.map +1 -0
- package/dist/components/ui/Avatar/Avatar.d.ts +5 -0
- package/dist/components/ui/Avatar/Avatar.d.ts.map +1 -0
- package/dist/components/ui/Avatar/Avatar.js +63 -0
- package/dist/components/ui/Avatar/Avatar.js.map +1 -0
- package/dist/components/ui/{branch-chip.d.ts → BranchChip/BranchChip.d.ts} +2 -5
- package/dist/components/ui/BranchChip/BranchChip.d.ts.map +1 -0
- package/dist/components/ui/BranchChip/BranchChip.js +47 -0
- package/dist/components/ui/BranchChip/BranchChip.js.map +1 -0
- package/dist/components/ui/Button/Button.d.ts +15 -0
- package/dist/components/ui/Button/Button.d.ts.map +1 -0
- package/dist/components/ui/Button/Button.js +49 -0
- package/dist/components/ui/Button/Button.js.map +1 -0
- package/dist/components/ui/Card/Card.d.ts +6 -0
- package/dist/components/ui/Card/Card.d.ts.map +1 -0
- package/dist/components/ui/{card.js → Card/Card.js} +12 -22
- package/dist/components/ui/Card/Card.js.map +1 -0
- package/dist/components/ui/{chip.d.ts → Chip/Chip.d.ts} +1 -1
- package/dist/components/ui/Chip/Chip.d.ts.map +1 -0
- package/dist/components/ui/Chip/Chip.js +24 -0
- package/dist/components/ui/Chip/Chip.js.map +1 -0
- package/dist/components/ui/Dialog/Dialog.d.ts +32 -0
- package/dist/components/ui/Dialog/Dialog.d.ts.map +1 -0
- package/dist/components/ui/Dialog/Dialog.js +194 -0
- package/dist/components/ui/Dialog/Dialog.js.map +1 -0
- package/dist/components/ui/DropdownMenu/DropdownMenu.d.ts +66 -0
- package/dist/components/ui/DropdownMenu/DropdownMenu.d.ts.map +1 -0
- package/dist/components/ui/DropdownMenu/DropdownMenu.js +308 -0
- package/dist/components/ui/DropdownMenu/DropdownMenu.js.map +1 -0
- package/dist/components/ui/{field.d.ts → FormField/Field.d.ts} +1 -1
- package/dist/components/ui/FormField/Field.d.ts.map +1 -0
- package/dist/components/ui/FormField/Field.js +41 -0
- package/dist/components/ui/FormField/Field.js.map +1 -0
- package/dist/components/{FieldShell.d.ts → ui/FormField/FieldShell.d.ts} +2 -2
- package/dist/components/ui/FormField/FieldShell.d.ts.map +1 -0
- package/dist/components/ui/FormField/FieldShell.js +29 -0
- package/dist/components/ui/FormField/FieldShell.js.map +1 -0
- package/dist/components/ui/FormField/FormBooleanField.d.ts.map +1 -0
- package/dist/components/ui/FormField/FormBooleanField.js +56 -0
- package/dist/components/ui/FormField/FormBooleanField.js.map +1 -0
- package/dist/components/ui/FormField/FormColorField.d.ts.map +1 -0
- package/dist/components/{FormColorField.js → ui/FormField/FormColorField.js} +10 -13
- package/dist/components/ui/FormField/FormColorField.js.map +1 -0
- package/dist/components/{FormConditionalField.d.ts → ui/FormField/FormConditionalField.d.ts} +1 -1
- package/dist/components/ui/FormField/FormConditionalField.d.ts.map +1 -0
- package/dist/components/{FormConditionalField.js → ui/FormField/FormConditionalField.js} +61 -58
- package/dist/components/ui/FormField/FormConditionalField.js.map +1 -0
- package/dist/components/ui/FormField/FormDatetimeField.d.ts.map +1 -0
- package/dist/components/ui/FormField/FormDatetimeField.js +48 -0
- package/dist/components/ui/FormField/FormDatetimeField.js.map +1 -0
- package/dist/components/{FormFields.d.ts → ui/FormField/FormFields.d.ts} +1 -1
- package/dist/components/ui/FormField/FormFields.d.ts.map +1 -0
- package/dist/components/{FormFields.js → ui/FormField/FormFields.js} +6 -6
- package/dist/components/ui/FormField/FormFields.js.map +1 -0
- package/dist/components/{FormImageField.d.ts → ui/FormField/FormImageField.d.ts} +1 -1
- package/dist/components/ui/FormField/FormImageField.d.ts.map +1 -0
- package/dist/components/{FormImageField.js → ui/FormField/FormImageField.js} +25 -30
- package/dist/components/ui/FormField/FormImageField.js.map +1 -0
- package/dist/components/ui/FormField/FormJsonField.d.ts.map +1 -0
- package/dist/components/{FormJsonField.js → ui/FormField/FormJsonField.js} +7 -10
- package/dist/components/ui/FormField/FormJsonField.js.map +1 -0
- package/dist/components/ui/FormField/FormMarkdownField.d.ts.map +1 -0
- package/dist/components/{FormMarkdownField.js → ui/FormField/FormMarkdownField.js} +11 -20
- package/dist/components/ui/FormField/FormMarkdownField.js.map +1 -0
- package/dist/components/ui/FormField/FormNumberField.d.ts.map +1 -0
- package/dist/components/ui/FormField/FormNumberField.js +38 -0
- package/dist/components/ui/FormField/FormNumberField.js.map +1 -0
- package/dist/components/{FormReferenceField.d.ts → ui/FormField/FormReferenceField.d.ts} +1 -1
- package/dist/components/ui/FormField/FormReferenceField.d.ts.map +1 -0
- package/dist/components/{FormReferenceField.js → ui/FormField/FormReferenceField.js} +109 -118
- package/dist/components/ui/FormField/FormReferenceField.js.map +1 -0
- package/dist/components/{FormRichTextField.d.ts → ui/FormField/FormRichTextField.d.ts} +1 -1
- package/dist/components/ui/FormField/FormRichTextField.d.ts.map +1 -0
- package/dist/components/{FormRichTextField.js → ui/FormField/FormRichTextField.js} +28 -33
- package/dist/components/ui/FormField/FormRichTextField.js.map +1 -0
- package/dist/components/{FormSelectField.d.ts → ui/FormField/FormSelectField.d.ts} +1 -1
- package/dist/components/ui/FormField/FormSelectField.d.ts.map +1 -0
- package/dist/components/{FormSelectField.js → ui/FormField/FormSelectField.js} +11 -23
- package/dist/components/ui/FormField/FormSelectField.js.map +1 -0
- package/dist/components/ui/FormField/FormSlugField.d.ts.map +1 -0
- package/dist/components/{FormSlugField.js → ui/FormField/FormSlugField.js} +21 -26
- package/dist/components/ui/FormField/FormSlugField.js.map +1 -0
- package/dist/components/ui/FormField/FormStringField.d.ts.map +1 -0
- package/dist/components/ui/FormField/FormStringField.js +23 -0
- package/dist/components/ui/FormField/FormStringField.js.map +1 -0
- package/dist/components/ui/FormField/FormStringListField.d.ts.map +1 -0
- package/dist/components/{FormStringListField.js → ui/FormField/FormStringListField.js} +14 -25
- package/dist/components/ui/FormField/FormStringListField.js.map +1 -0
- package/dist/components/ui/FormField/FormTextField.d.ts.map +1 -0
- package/dist/components/ui/FormField/FormTextField.js +35 -0
- package/dist/components/ui/FormField/FormTextField.js.map +1 -0
- package/dist/components/ui/FormField/FormUrlField.d.ts.map +1 -0
- package/dist/components/ui/FormField/FormUrlField.js +26 -0
- package/dist/components/ui/FormField/FormUrlField.js.map +1 -0
- package/dist/components/{richtext → ui/FormField/richtext}/ComponentEmbedEditor.d.ts +1 -1
- package/dist/components/ui/FormField/richtext/ComponentEmbedEditor.d.ts.map +1 -0
- package/dist/components/ui/FormField/richtext/ComponentEmbedEditor.js +165 -0
- package/dist/components/ui/FormField/richtext/ComponentEmbedEditor.js.map +1 -0
- package/dist/components/ui/FormField/richtext/ConditionEmbedEditor.d.ts.map +1 -0
- package/dist/components/{richtext → ui/FormField/richtext}/ConditionEmbedEditor.js +25 -39
- package/dist/components/ui/FormField/richtext/ConditionEmbedEditor.js.map +1 -0
- package/dist/components/ui/FormField/richtext/ImageEmbedEditor.d.ts.map +1 -0
- package/dist/components/{richtext → ui/FormField/richtext}/ImageEmbedEditor.js +77 -56
- package/dist/components/ui/FormField/richtext/ImageEmbedEditor.js.map +1 -0
- package/dist/components/ui/FormField/richtext/ReferenceEmbedEditor.d.ts.map +1 -0
- package/dist/components/{richtext → ui/FormField/richtext}/ReferenceEmbedEditor.js +55 -43
- package/dist/components/ui/FormField/richtext/ReferenceEmbedEditor.js.map +1 -0
- package/dist/components/ui/FormField/richtext/SlashCommandMenu.d.ts.map +1 -0
- package/dist/components/{richtext → ui/FormField/richtext}/SlashCommandMenu.js +21 -33
- package/dist/components/ui/FormField/richtext/SlashCommandMenu.js.map +1 -0
- package/dist/components/ui/FormField/richtext/VariableEmbedEditor.d.ts.map +1 -0
- package/dist/components/ui/FormField/richtext/VariableEmbedEditor.js +61 -0
- package/dist/components/ui/FormField/richtext/VariableEmbedEditor.js.map +1 -0
- package/dist/components/ui/Icon/Icon.d.ts +77 -0
- package/dist/components/ui/Icon/Icon.d.ts.map +1 -0
- package/dist/components/ui/Icon/Icon.js +618 -0
- package/dist/components/ui/Icon/Icon.js.map +1 -0
- package/dist/components/ui/{input.d.ts → Input/Input.d.ts} +1 -1
- package/dist/components/ui/Input/Input.d.ts.map +1 -0
- package/dist/components/ui/Input/Input.js +25 -0
- package/dist/components/ui/Input/Input.js.map +1 -0
- package/dist/components/ui/{kbd.d.ts → Kbd/Kbd.d.ts} +1 -1
- package/dist/components/ui/Kbd/Kbd.d.ts.map +1 -0
- package/dist/components/ui/Kbd/Kbd.js +19 -0
- package/dist/components/ui/Kbd/Kbd.js.map +1 -0
- package/dist/components/ui/Label/Label.d.ts +3 -0
- package/dist/components/ui/Label/Label.d.ts.map +1 -0
- package/dist/components/ui/Label/Label.js +20 -0
- package/dist/components/ui/Label/Label.js.map +1 -0
- package/dist/components/ui/Portal/Portal.d.ts +8 -0
- package/dist/components/ui/Portal/Portal.d.ts.map +1 -0
- package/dist/components/ui/Portal/Portal.js +14 -0
- package/dist/components/ui/Portal/Portal.js.map +1 -0
- package/dist/components/ui/Select/Select.d.ts +33 -0
- package/dist/components/ui/Select/Select.d.ts.map +1 -0
- package/dist/components/ui/Select/Select.js +280 -0
- package/dist/components/ui/Select/Select.js.map +1 -0
- package/dist/components/ui/Slot/Slot.d.ts +6 -0
- package/dist/components/ui/Slot/Slot.d.ts.map +1 -0
- package/dist/components/ui/Slot/Slot.js +39 -0
- package/dist/components/ui/Slot/Slot.js.map +1 -0
- package/dist/components/ui/{status-badge.d.ts → StatusBadge/StatusBadge.d.ts} +2 -2
- package/dist/components/ui/StatusBadge/StatusBadge.d.ts.map +1 -0
- package/dist/components/ui/{status-badge.js → StatusBadge/StatusBadge.js} +8 -9
- package/dist/components/ui/StatusBadge/StatusBadge.js.map +1 -0
- package/dist/components/ui/Switcher/Switcher.d.ts +9 -0
- package/dist/components/ui/Switcher/Switcher.d.ts.map +1 -0
- package/dist/components/ui/Switcher/Switcher.js +75 -0
- package/dist/components/ui/Switcher/Switcher.js.map +1 -0
- package/dist/components/ui/{table.d.ts → Table/Table.d.ts} +1 -1
- package/dist/components/ui/Table/Table.d.ts.map +1 -0
- package/dist/components/ui/{table.js → Table/Table.js} +11 -29
- package/dist/components/ui/Table/Table.js.map +1 -0
- package/dist/components/ui/Tabs/Tabs.d.ts +16 -0
- package/dist/components/ui/Tabs/Tabs.d.ts.map +1 -0
- package/dist/components/ui/Tabs/Tabs.js +96 -0
- package/dist/components/ui/Tabs/Tabs.js.map +1 -0
- package/dist/components/ui/{textarea.d.ts → Textarea/Textarea.d.ts} +1 -1
- package/dist/components/ui/Textarea/Textarea.d.ts.map +1 -0
- package/dist/components/ui/Textarea/Textarea.js +16 -0
- package/dist/components/ui/Textarea/Textarea.js.map +1 -0
- package/dist/components/ui/Toast/Toast.d.ts +21 -0
- package/dist/components/ui/Toast/Toast.d.ts.map +1 -0
- package/dist/components/ui/Toast/Toast.js +98 -0
- package/dist/components/ui/Toast/Toast.js.map +1 -0
- package/dist/components/ui/{toaster.d.ts → Toaster/Toaster.d.ts} +1 -1
- package/dist/components/ui/Toaster/Toaster.d.ts.map +1 -0
- package/dist/components/ui/Toaster/Toaster.js +27 -0
- package/dist/components/ui/Toaster/Toaster.js.map +1 -0
- package/dist/components/ui/index.d.ts +45 -31
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +76 -36
- package/dist/components/ui/index.js.map +1 -1
- package/dist/config.cjs +4 -99
- package/dist/config.cjs.map +1 -1
- package/dist/defineConfig.cjs +0 -2
- package/dist/defineConfig.cjs.map +1 -1
- package/dist/globals.css +9648 -430
- package/dist/hooks/useComposedRefs.d.ts +5 -0
- package/dist/hooks/useComposedRefs.d.ts.map +1 -0
- package/dist/hooks/useComposedRefs.js +23 -0
- package/dist/hooks/useComposedRefs.js.map +1 -0
- package/dist/hooks/useControllableState.d.ts +8 -0
- package/dist/hooks/useControllableState.d.ts.map +1 -0
- package/dist/hooks/useControllableState.js +28 -0
- package/dist/hooks/useControllableState.js.map +1 -0
- package/dist/hooks/usePopoverContent.d.ts +26 -0
- package/dist/hooks/usePopoverContent.d.ts.map +1 -0
- package/dist/hooks/usePopoverContent.js +44 -0
- package/dist/hooks/usePopoverContent.js.map +1 -0
- package/dist/hooks/useToast.d.ts +4 -4
- package/dist/hooks/useToast.d.ts.map +1 -1
- package/dist/hooks/useToast.js +1 -3
- package/dist/hooks/useToast.js.map +1 -1
- package/dist/index.cjs +11 -9506
- package/dist/index.cjs.map +1 -1
- package/dist/{init-KWH66PKY.js → init-KNIWQGJL.js} +3 -18
- package/dist/init-KNIWQGJL.js.map +1 -0
- package/dist/lib/configStore.cjs +1 -3
- package/dist/lib/configStore.cjs.map +1 -1
- package/dist/lib/slugField.d.ts.map +1 -1
- package/dist/lib/slugField.js +3 -3
- package/dist/lib/slugField.js.map +1 -1
- package/dist/lib/slugify.d.ts +13 -0
- package/dist/lib/slugify.d.ts.map +1 -0
- package/dist/lib/slugify.js +8 -0
- package/dist/lib/slugify.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +29 -3
- package/dist/lib/utils.js.map +1 -1
- package/dist/query.cjs +58 -9011
- package/dist/query.cjs.map +1 -1
- package/dist/types.cjs +0 -2
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.ts +3 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/{update-QNJRYPMC.js → update-QALIQG76.js} +2 -2
- package/dist/withOctoCMS.cjs +2 -36
- package/dist/withOctoCMS.cjs.map +1 -1
- package/globals.css +9648 -430
- package/package.json +1 -16
- package/dist/chunk-NAHOP7TG.js +0 -7
- package/dist/components/ContentModel/ContentModelList.skeleton.d.ts +0 -5
- package/dist/components/ContentModel/ContentModelList.skeleton.d.ts.map +0 -1
- package/dist/components/ContentModel/ContentModelList.skeleton.js +0 -16
- package/dist/components/ContentModel/ContentModelList.skeleton.js.map +0 -1
- package/dist/components/ContentModel/ContentTypeDetail.skeleton.d.ts +0 -5
- package/dist/components/ContentModel/ContentTypeDetail.skeleton.d.ts.map +0 -1
- package/dist/components/ContentModel/ContentTypeDetail.skeleton.js +0 -22
- package/dist/components/ContentModel/ContentTypeDetail.skeleton.js.map +0 -1
- package/dist/components/ContentTypes.d.ts +0 -7
- package/dist/components/ContentTypes.d.ts.map +0 -1
- package/dist/components/ContentTypes.js +0 -132
- package/dist/components/ContentTypes.js.map +0 -1
- package/dist/components/CreateBranchDialog.d.ts.map +0 -1
- package/dist/components/CreateBranchDialog.js.map +0 -1
- package/dist/components/Dashboard/DashboardContent.collection.skeleton.d.ts +0 -3
- package/dist/components/Dashboard/DashboardContent.collection.skeleton.d.ts.map +0 -1
- package/dist/components/Dashboard/DashboardContent.collection.skeleton.js +0 -10
- package/dist/components/Dashboard/DashboardContent.collection.skeleton.js.map +0 -1
- package/dist/components/Dashboard/DashboardContent.list.skeleton.d.ts +0 -7
- package/dist/components/Dashboard/DashboardContent.list.skeleton.d.ts.map +0 -1
- package/dist/components/Dashboard/DashboardContent.list.skeleton.js +0 -22
- package/dist/components/Dashboard/DashboardContent.list.skeleton.js.map +0 -1
- package/dist/components/Dashboard/DashboardContent.skeleton.d.ts +0 -2
- package/dist/components/Dashboard/DashboardContent.skeleton.d.ts.map +0 -1
- package/dist/components/Dashboard/DashboardContent.skeleton.js +0 -13
- package/dist/components/Dashboard/DashboardContent.skeleton.js.map +0 -1
- package/dist/components/EditPost/EditPost.skeleton.d.ts +0 -5
- package/dist/components/EditPost/EditPost.skeleton.d.ts.map +0 -1
- package/dist/components/EditPost/EditPost.skeleton.js +0 -34
- package/dist/components/EditPost/EditPost.skeleton.js.map +0 -1
- package/dist/components/ErrorBoundary.d.ts.map +0 -1
- package/dist/components/ErrorBoundary.js.map +0 -1
- package/dist/components/FieldHintAndError.d.ts +0 -8
- package/dist/components/FieldHintAndError.d.ts.map +0 -1
- package/dist/components/FieldHintAndError.js +0 -14
- package/dist/components/FieldHintAndError.js.map +0 -1
- package/dist/components/FieldLabel.d.ts +0 -11
- package/dist/components/FieldLabel.d.ts.map +0 -1
- package/dist/components/FieldLabel.js +0 -17
- package/dist/components/FieldLabel.js.map +0 -1
- package/dist/components/FieldShell.d.ts.map +0 -1
- package/dist/components/FieldShell.js +0 -29
- package/dist/components/FieldShell.js.map +0 -1
- package/dist/components/FileExplorer/FileExplorer.d.ts +0 -8
- package/dist/components/FileExplorer/FileExplorer.d.ts.map +0 -1
- package/dist/components/FileExplorer/FileExplorer.js +0 -68
- package/dist/components/FileExplorer/FileExplorer.js.map +0 -1
- package/dist/components/FormBooleanField.d.ts.map +0 -1
- package/dist/components/FormBooleanField.js +0 -52
- package/dist/components/FormBooleanField.js.map +0 -1
- package/dist/components/FormColorField.d.ts.map +0 -1
- package/dist/components/FormColorField.js.map +0 -1
- package/dist/components/FormConditionalField.d.ts.map +0 -1
- package/dist/components/FormConditionalField.js.map +0 -1
- package/dist/components/FormDatetimeField.d.ts.map +0 -1
- package/dist/components/FormDatetimeField.js +0 -42
- package/dist/components/FormDatetimeField.js.map +0 -1
- package/dist/components/FormFields.d.ts.map +0 -1
- package/dist/components/FormFields.js.map +0 -1
- package/dist/components/FormImageField.d.ts.map +0 -1
- package/dist/components/FormImageField.js.map +0 -1
- package/dist/components/FormJsonField.d.ts.map +0 -1
- package/dist/components/FormJsonField.js.map +0 -1
- package/dist/components/FormMarkdownField.d.ts.map +0 -1
- package/dist/components/FormMarkdownField.js.map +0 -1
- package/dist/components/FormNumberField.d.ts.map +0 -1
- package/dist/components/FormNumberField.js +0 -43
- package/dist/components/FormNumberField.js.map +0 -1
- package/dist/components/FormReferenceField.d.ts.map +0 -1
- package/dist/components/FormReferenceField.js.map +0 -1
- package/dist/components/FormRichTextField.d.ts.map +0 -1
- package/dist/components/FormRichTextField.js.map +0 -1
- package/dist/components/FormSelectField.d.ts.map +0 -1
- package/dist/components/FormSelectField.js.map +0 -1
- package/dist/components/FormSlugField.d.ts.map +0 -1
- package/dist/components/FormSlugField.js.map +0 -1
- package/dist/components/FormStringField.d.ts.map +0 -1
- package/dist/components/FormStringField.js +0 -28
- package/dist/components/FormStringField.js.map +0 -1
- package/dist/components/FormStringListField.d.ts.map +0 -1
- package/dist/components/FormStringListField.js.map +0 -1
- package/dist/components/FormTextField.d.ts.map +0 -1
- package/dist/components/FormTextField.js +0 -40
- package/dist/components/FormTextField.js.map +0 -1
- package/dist/components/FormUrlField.d.ts.map +0 -1
- package/dist/components/FormUrlField.js +0 -31
- package/dist/components/FormUrlField.js.map +0 -1
- package/dist/components/Layout/PageBar.d.ts +0 -10
- package/dist/components/Layout/PageBar.d.ts.map +0 -1
- package/dist/components/Layout/PageBar.js +0 -43
- package/dist/components/Layout/PageBar.js.map +0 -1
- package/dist/components/Layout/PageShell.d.ts +0 -30
- package/dist/components/Layout/PageShell.d.ts.map +0 -1
- package/dist/components/Layout/PageShell.js +0 -33
- package/dist/components/Layout/PageShell.js.map +0 -1
- package/dist/components/MediaAsset/MediaAsset.skeleton.d.ts +0 -3
- package/dist/components/MediaAsset/MediaAsset.skeleton.d.ts.map +0 -1
- package/dist/components/MediaAsset/MediaAsset.skeleton.js +0 -42
- package/dist/components/MediaAsset/MediaAsset.skeleton.js.map +0 -1
- package/dist/components/MediaManager/MediaManager.skeleton.d.ts +0 -3
- package/dist/components/MediaManager/MediaManager.skeleton.d.ts.map +0 -1
- package/dist/components/MediaManager/MediaManager.skeleton.js +0 -30
- package/dist/components/MediaManager/MediaManager.skeleton.js.map +0 -1
- package/dist/components/StatusBadge.d.ts +0 -2
- package/dist/components/StatusBadge.d.ts.map +0 -1
- package/dist/components/StatusBadge.js +0 -7
- package/dist/components/StatusBadge.js.map +0 -1
- package/dist/components/richtext/ComponentEmbedEditor.d.ts.map +0 -1
- package/dist/components/richtext/ComponentEmbedEditor.js +0 -153
- package/dist/components/richtext/ComponentEmbedEditor.js.map +0 -1
- package/dist/components/richtext/ConditionEmbedEditor.d.ts.map +0 -1
- package/dist/components/richtext/ConditionEmbedEditor.js.map +0 -1
- package/dist/components/richtext/ImageEmbedEditor.d.ts.map +0 -1
- package/dist/components/richtext/ImageEmbedEditor.js.map +0 -1
- package/dist/components/richtext/ReferenceEmbedEditor.d.ts.map +0 -1
- package/dist/components/richtext/ReferenceEmbedEditor.js.map +0 -1
- package/dist/components/richtext/SlashCommandMenu.d.ts.map +0 -1
- package/dist/components/richtext/SlashCommandMenu.js.map +0 -1
- package/dist/components/richtext/VariableEmbedEditor.d.ts.map +0 -1
- package/dist/components/richtext/VariableEmbedEditor.js +0 -58
- package/dist/components/richtext/VariableEmbedEditor.js.map +0 -1
- package/dist/components/ui/avatar-stack.d.ts +0 -13
- package/dist/components/ui/avatar-stack.d.ts.map +0 -1
- package/dist/components/ui/avatar-stack.js +0 -27
- package/dist/components/ui/avatar-stack.js.map +0 -1
- package/dist/components/ui/avatar.d.ts +0 -7
- package/dist/components/ui/avatar.d.ts.map +0 -1
- package/dist/components/ui/avatar.js +0 -45
- package/dist/components/ui/avatar.js.map +0 -1
- package/dist/components/ui/banner.d.ts +0 -13
- package/dist/components/ui/banner.d.ts.map +0 -1
- package/dist/components/ui/banner.js +0 -24
- package/dist/components/ui/banner.js.map +0 -1
- package/dist/components/ui/branch-chip.d.ts.map +0 -1
- package/dist/components/ui/branch-chip.js +0 -58
- package/dist/components/ui/branch-chip.js.map +0 -1
- package/dist/components/ui/button.d.ts +0 -14
- package/dist/components/ui/button.d.ts.map +0 -1
- package/dist/components/ui/button.js +0 -65
- package/dist/components/ui/button.js.map +0 -1
- package/dist/components/ui/card.d.ts +0 -7
- package/dist/components/ui/card.d.ts.map +0 -1
- package/dist/components/ui/card.js.map +0 -1
- package/dist/components/ui/chip.d.ts.map +0 -1
- package/dist/components/ui/chip.js +0 -44
- package/dist/components/ui/chip.js.map +0 -1
- package/dist/components/ui/dialog.d.ts +0 -20
- package/dist/components/ui/dialog.d.ts.map +0 -1
- package/dist/components/ui/dialog.js +0 -93
- package/dist/components/ui/dialog.js.map +0 -1
- package/dist/components/ui/dropdown-menu.d.ts +0 -28
- package/dist/components/ui/dropdown-menu.d.ts.map +0 -1
- package/dist/components/ui/dropdown-menu.js +0 -165
- package/dist/components/ui/dropdown-menu.js.map +0 -1
- package/dist/components/ui/empty.d.ts +0 -11
- package/dist/components/ui/empty.d.ts.map +0 -1
- package/dist/components/ui/empty.js +0 -24
- package/dist/components/ui/empty.js.map +0 -1
- package/dist/components/ui/field.d.ts.map +0 -1
- package/dist/components/ui/field.js +0 -52
- package/dist/components/ui/field.js.map +0 -1
- package/dist/components/ui/input.d.ts.map +0 -1
- package/dist/components/ui/input.js +0 -51
- package/dist/components/ui/input.js.map +0 -1
- package/dist/components/ui/kbd.d.ts.map +0 -1
- package/dist/components/ui/kbd.js +0 -30
- package/dist/components/ui/kbd.js.map +0 -1
- package/dist/components/ui/label.d.ts +0 -6
- package/dist/components/ui/label.d.ts.map +0 -1
- package/dist/components/ui/label.js +0 -20
- package/dist/components/ui/label.js.map +0 -1
- package/dist/components/ui/publish-button.d.ts +0 -7
- package/dist/components/ui/publish-button.d.ts.map +0 -1
- package/dist/components/ui/publish-button.js +0 -50
- package/dist/components/ui/publish-button.js.map +0 -1
- package/dist/components/ui/select.d.ts +0 -14
- package/dist/components/ui/select.d.ts.map +0 -1
- package/dist/components/ui/select.js +0 -132
- package/dist/components/ui/select.js.map +0 -1
- package/dist/components/ui/sonner.d.ts +0 -6
- package/dist/components/ui/sonner.d.ts.map +0 -1
- package/dist/components/ui/sonner.js +0 -37
- package/dist/components/ui/sonner.js.map +0 -1
- package/dist/components/ui/status-badge.d.ts.map +0 -1
- package/dist/components/ui/status-badge.js.map +0 -1
- package/dist/components/ui/table.d.ts.map +0 -1
- package/dist/components/ui/table.js.map +0 -1
- package/dist/components/ui/tabs-pill.d.ts +0 -17
- package/dist/components/ui/tabs-pill.d.ts.map +0 -1
- package/dist/components/ui/tabs-pill.js +0 -67
- package/dist/components/ui/tabs-pill.js.map +0 -1
- package/dist/components/ui/tabs.d.ts +0 -8
- package/dist/components/ui/tabs.d.ts.map +0 -1
- package/dist/components/ui/tabs.js +0 -59
- package/dist/components/ui/tabs.js.map +0 -1
- package/dist/components/ui/textarea.d.ts.map +0 -1
- package/dist/components/ui/textarea.js +0 -25
- package/dist/components/ui/textarea.js.map +0 -1
- package/dist/components/ui/toast-card.d.ts +0 -15
- package/dist/components/ui/toast-card.d.ts.map +0 -1
- package/dist/components/ui/toast-card.js +0 -90
- package/dist/components/ui/toast-card.js.map +0 -1
- package/dist/components/ui/toast.d.ts +0 -16
- package/dist/components/ui/toast.d.ts.map +0 -1
- package/dist/components/ui/toast.js +0 -95
- package/dist/components/ui/toast.js.map +0 -1
- package/dist/components/ui/toaster.d.ts.map +0 -1
- package/dist/components/ui/toaster.js +0 -30
- package/dist/components/ui/toaster.js.map +0 -1
- package/dist/init-KWH66PKY.js.map +0 -1
- /package/dist/{agentDocs-M3R2CPUQ.js.map → agentDocs-QZ4NOQVH.js.map} +0 -0
- /package/dist/components/{ErrorBoundary.d.ts → ErrorBoundary/ErrorBoundary.d.ts} +0 -0
- /package/dist/components/{CreateBranchDialog.d.ts → Layout/CreateBranchDialog.d.ts} +0 -0
- /package/dist/components/{FormBooleanField.d.ts → ui/FormField/FormBooleanField.d.ts} +0 -0
- /package/dist/components/{FormColorField.d.ts → ui/FormField/FormColorField.d.ts} +0 -0
- /package/dist/components/{FormDatetimeField.d.ts → ui/FormField/FormDatetimeField.d.ts} +0 -0
- /package/dist/components/{FormJsonField.d.ts → ui/FormField/FormJsonField.d.ts} +0 -0
- /package/dist/components/{FormMarkdownField.d.ts → ui/FormField/FormMarkdownField.d.ts} +0 -0
- /package/dist/components/{FormNumberField.d.ts → ui/FormField/FormNumberField.d.ts} +0 -0
- /package/dist/components/{FormSlugField.d.ts → ui/FormField/FormSlugField.d.ts} +0 -0
- /package/dist/components/{FormStringField.d.ts → ui/FormField/FormStringField.d.ts} +0 -0
- /package/dist/components/{FormStringListField.d.ts → ui/FormField/FormStringListField.d.ts} +0 -0
- /package/dist/components/{FormTextField.d.ts → ui/FormField/FormTextField.d.ts} +0 -0
- /package/dist/components/{FormUrlField.d.ts → ui/FormField/FormUrlField.d.ts} +0 -0
- /package/dist/components/{richtext → ui/FormField/richtext}/ConditionEmbedEditor.d.ts +0 -0
- /package/dist/components/{richtext → ui/FormField/richtext}/ImageEmbedEditor.d.ts +0 -0
- /package/dist/components/{richtext → ui/FormField/richtext}/ReferenceEmbedEditor.d.ts +0 -0
- /package/dist/components/{richtext → ui/FormField/richtext}/SlashCommandMenu.d.ts +0 -0
- /package/dist/components/{richtext → ui/FormField/richtext}/VariableEmbedEditor.d.ts +0 -0
- /package/dist/{update-QNJRYPMC.js.map → update-QALIQG76.js.map} +0 -0
package/dist/agent/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../agent/pricing.ts","../../agent/usage.ts","../../agent/featureFlag.ts","../../agent/configStore.ts","../../agent/embedText.ts","../../agent/embedder.ts","../../lib/companionMarkdown.ts","../../agent/storeFormat.ts","../../lib/cmsServerLog.ts","../../lib/contentSourceError.ts","../../admin/auth.ts","../../lib/contentBranch.ts","../../lib/configStore.ts","../../lib/githubContentMode.ts","../../github-public.ts","../../admin/github.ts","../../agent/embeddings.ts","../../agent/embeddingsHook.ts","../../lib/resolveEntryTitle.ts","../../admin/actions/registerConfig.ts","../../lib/localReader.ts","../../lib/branchHistory.ts","../../lib/initialEntryFields.ts","../../lib/colorField.ts","../../lib/datetimeField.ts","../../lib/jsonField.ts","../../lib/numberField.ts","../../lib/selectField.ts","../../lib/slugField.ts","../../lib/stringListField.ts","../../lib/urlField.ts","../../lib/persistedFormFields.ts","../../lib/validateEntryFields.ts","../../lib/mediaPath.ts","../../lib/searchIndex.ts","../../admin/store/contentStoreFetch.ts","../../admin/store/contentStore.ts","../../lib/publicContentCacheTag.ts","../../admin/actions/utils.ts","../../admin/actions/build.ts","../../admin/actions/files.ts","../../agent/providers/anthropic.ts","../../agent/providers/openai.ts","../../agent/index.ts","../../agent/defaults.ts","../../agent/search.ts","../../agent/systemPrompt.ts","../../agent/tools/index.ts","../../agent/proposals.ts","../../agent/chat.ts","../../agent/attachments.ts","../../agent/chatApi.ts","../../agent/providers/index.ts"],"sourcesContent":["import type { AgentConfig, AgentProvider } from './types';\n\n/** Returns provider pricing if defined, otherwise `null` (treated as $0). */\nexport function getProviderPricing(provider: AgentProvider) {\n return provider.pricing ?? null;\n}\n\n/**\n * Estimated USD cost of a turn against `config.provider.pricing`.\n * `cachedInput` is the subset of `input` tokens served from the prompt cache\n * (billed at the cached rate). Returns `0` for providers without pricing\n * (typically local models).\n */\nexport function estimateCostUSD(config: AgentConfig, input: number, output: number, cachedInput = 0): number {\n const pricing = getProviderPricing(config.provider);\n if (!pricing) return 0;\n const fresh = Math.max(0, input - cachedInput);\n return (\n (fresh * pricing.inputPerM) / 1_000_000 +\n (cachedInput * pricing.cachedInputPerM) / 1_000_000 +\n (output * pricing.outputPerM) / 1_000_000\n );\n}\n","/**\n * Cumulative spend tracker for the chat agent.\n *\n * In-memory and per-process: every Vercel function instance owns its own\n * counter, and it resets on cold start. This is intentionally lightweight —\n * the goal is \"best-effort cutoff so a runaway loop doesn't burn the dev\n * credit\", not a hard accounting guarantee. For a hard cap, set a workspace\n * budget alert in your provider's console alongside `config.totalBudgetUSD`.\n *\n * Phase 3 (chat route) calls {@link recordTurn} after each provider response.\n */\n\nimport { estimateCostUSD } from './pricing';\nimport type { AgentConfig } from './types';\n\nexport type AgentUsage = {\n inputTokens: number;\n cachedInputTokens: number;\n outputTokens: number;\n costUSD: number;\n lastUpdated: string | null;\n};\n\nconst ZERO: AgentUsage = {\n inputTokens: 0,\n cachedInputTokens: 0,\n outputTokens: 0,\n costUSD: 0,\n lastUpdated: null,\n};\n\nlet state: AgentUsage = { ...ZERO };\n\nexport function getUsage(): AgentUsage {\n return { ...state };\n}\n\nexport function recordTurn(\n config: AgentConfig,\n turn: { input: number; output: number; cachedInput?: number },\n): AgentUsage {\n const cachedInput = turn.cachedInput ?? 0;\n state = {\n inputTokens: state.inputTokens + turn.input,\n cachedInputTokens: state.cachedInputTokens + cachedInput,\n outputTokens: state.outputTokens + turn.output,\n costUSD: state.costUSD + estimateCostUSD(config, turn.input, turn.output, cachedInput),\n lastUpdated: new Date().toISOString(),\n };\n return getUsage();\n}\n\nexport function resetUsage(): AgentUsage {\n state = { ...ZERO };\n return getUsage();\n}\n\n/**\n * Whether cumulative spend has crossed `config.totalBudgetUSD`.\n * `totalBudgetUSD <= 0` disables the cap entirely (useful for local providers).\n */\nexport function isBudgetExceeded(config: AgentConfig, usage: AgentUsage = state): boolean {\n if (config.totalBudgetUSD <= 0) return false;\n return usage.costUSD >= config.totalBudgetUSD;\n}\n","/**\n * Server-side check for whether the RAG chat agent feature is enabled.\n *\n * The agent is enabled when:\n * 1. The provider's API key env var is set (Anthropic / OpenAI), OR the\n * provider is `'local'` and a `baseURL` is configured (no key required), AND\n * 2. cumulative spend on this deploy is under `config.totalBudgetUSD`\n * (cap is bypassed when `totalBudgetUSD <= 0`).\n *\n * When either check fails, the `/cms/chat` route returns 404 and the Header\n * nav link is hidden. Do not call from client components — the result must be\n * passed down as a boolean prop to avoid leaking the key.\n *\n * Note: this does NOT check whether the SDK packages are installed. They are\n * optional peer deps; their absence surfaces at chat-route invocation time\n * with a clear error rather than silently disabling the feature.\n */\n\nimport type { AgentConfig, AgentProvider } from './types';\nimport { getUsage, isBudgetExceeded } from './usage';\n\nexport type AgentStatus =\n | { enabled: true }\n | { enabled: false; reason: 'no-key' }\n | { enabled: false; reason: 'budget-exceeded'; spentUSD: number; budgetUSD: number };\n\nconst DEFAULT_API_KEY_ENVS: Record<AgentProvider['type'], string | null> = {\n anthropic: 'ANTHROPIC_API_KEY',\n openai: 'OPENAI_API_KEY',\n local: null,\n};\n\n/** Resolves the env var name a provider reads its API key from. */\nexport function providerApiKeyEnv(provider: AgentProvider): string | null {\n if (provider.apiKeyEnv) return provider.apiKeyEnv;\n return DEFAULT_API_KEY_ENVS[provider.type];\n}\n\n/** True iff the provider has the credentials it needs to talk to its model. */\nexport function hasProviderKey(provider: AgentProvider): boolean {\n if (provider.type === 'local') {\n if (provider.apiKeyEnv) {\n const key = process.env[provider.apiKeyEnv];\n return typeof key === 'string' && key.length > 0;\n }\n return Boolean(provider.baseURL);\n }\n const envName = providerApiKeyEnv(provider);\n if (!envName) return false;\n const key = process.env[envName];\n return typeof key === 'string' && key.length > 0;\n}\n\nexport function getAgentStatus(config: AgentConfig): AgentStatus {\n if (!hasProviderKey(config.provider)) return { enabled: false, reason: 'no-key' };\n const usage = getUsage();\n if (isBudgetExceeded(config, usage)) {\n return {\n enabled: false,\n reason: 'budget-exceeded',\n spentUSD: usage.costUSD,\n budgetUSD: config.totalBudgetUSD,\n };\n }\n return { enabled: true };\n}\n\nexport function isAgentEnabled(config: AgentConfig): boolean {\n return getAgentStatus(config).enabled;\n}\n","/**\n * Singleton holder for the chat agent's `AgentConfig`.\n *\n * Mirrors `octocms/lib/configStore` for the regular `Config`. Populated by\n * the auto-generated `cms/__generated__/configInit.ts` so server actions can\n * read the agent config without importing the user's `cms/octocms.config.ts`\n * directly (architecture rule: no `octocms/` file imports user-app files).\n *\n * Returns `null` from `getAgentConfig()` when the user hasn't exported an\n * `agentConfig` — the chat feature stays cleanly opt-in.\n */\n\nimport type { AgentConfig } from './types';\n\nlet _agentConfig: AgentConfig | null = null;\n\nexport function setAgentConfig(config: AgentConfig): void {\n _agentConfig = config;\n}\n\nexport function getAgentConfig(): AgentConfig | null {\n return _agentConfig;\n}\n","/**\n * Pure helper that turns a content entry into the plain-text payload we feed\n * to the embedding model. One vector per entry — every leaf field plus\n * companion `.md` / `.mdx` content is flattened into a single string.\n *\n * Reference fields keep the raw key strings (e.g. `\"author-abc.json\"`) — we\n * don't resolve them. The model still gets a useful signal (the key encodes\n * the collection) and we avoid recursive lookups during indexing.\n *\n * Field-name labels are included to give the model coarse semantic anchors\n * (`title:`, `body:`, …) without overwhelming the actual content.\n */\n\ntype EntryLike = {\n fields?: Record<string, unknown>;\n};\n\nfunction valueToText(value: unknown): string {\n if (value == null) return '';\n if (typeof value === 'string') return value;\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n if (Array.isArray(value)) {\n return value.map(valueToText).filter(Boolean).join(', ');\n }\n if (typeof value === 'object') {\n // For objects (image fields, JSON blobs, etc.) — flatten leaf string/number values.\n const parts: string[] = [];\n for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n const text = valueToText(v);\n if (text) parts.push(`${k}: ${text}`);\n }\n return parts.join(', ');\n }\n return '';\n}\n\n/**\n * Flatten an entry's fields plus companion-file contents into a single\n * embedding-ready string. Companion contents take precedence when a field\n * name appears in both (matches `getFile`'s merge order — companion wins).\n */\nexport function entryToEmbeddingText(entry: EntryLike, companions: Record<string, string> = {}): string {\n const lines: string[] = [];\n const fields = entry.fields ?? {};\n\n for (const [key, value] of Object.entries(fields)) {\n if (key in companions) continue; // handled below — companion content wins\n const text = valueToText(value).trim();\n if (text) lines.push(`${key}: ${text}`);\n }\n\n for (const [key, content] of Object.entries(companions)) {\n const trimmed = (content ?? '').trim();\n if (trimmed) lines.push(`${key}: ${trimmed}`);\n }\n\n return lines.join('\\n');\n}\n","/**\n * Embedding adapter — turns text into 384-dim float vectors.\n *\n * The default implementation, `LocalTransformersEmbedder`, runs\n * `Xenova/bge-small-en-v1.5` in-process via `@huggingface/transformers`. No\n * network calls after the model is cached, no LM Studio dependency, no key.\n *\n * The adapter is intentionally tiny so we can swap in a hosted provider\n * (Voyage / OpenAI) later without touching the rest of the agent.\n */\n\nexport interface Embedder {\n /** Embed a batch of texts. The returned array matches `texts` 1:1. */\n embed(texts: string[]): Promise<Float32Array[]>;\n /** Vector dimensionality — 384 for bge-small, etc. */\n readonly dim: number;\n /** Identifier written into the store header so we can detect model swaps. */\n readonly modelId: string;\n}\n\nconst DEFAULT_MODEL_ID = 'Xenova/bge-small-en-v1.5';\nconst DEFAULT_DIM = 384;\n\ntype FeatureExtractionPipeline = (\n texts: string[],\n options: { pooling: 'mean'; normalize: boolean },\n) => Promise<{ data: Float32Array; dims: number[] }>;\n\n/**\n * `onnxruntime-node` (a transitive dep of `@huggingface/transformers`) loads\n * `libonnxruntime.so.1` via a synchronous `require` at module top-level. On\n * Vercel the .so isn't bundled by default, so the require throws and — worse\n * — the package's internal init also fires an *unhandled* rejection that\n * crashes the lambda with exit 128 even though our own `try`/`catch` handles\n * the import.\n *\n * Install a one-time process-level filter that swallows just those native-\n * load rejections. Other unhandled rejections still crash with the default\n * Node behaviour.\n */\nlet nativeRejectionFilterInstalled = false;\nfunction installNativeRejectionFilter(): void {\n if (nativeRejectionFilterInstalled) return;\n if (typeof process === 'undefined' || typeof process.on !== 'function') return;\n nativeRejectionFilterInstalled = true;\n process.on('unhandledRejection', (reason: unknown) => {\n const msg = reason instanceof Error ? reason.message : String(reason);\n if (/libonnxruntime|onnxruntime-node|ERR_DLOPEN_FAILED/i.test(msg)) {\n // Already surfaced via the embedder's caller catch path. Swallow so\n // the lambda doesn't exit 128 on a content write.\n return;\n }\n // Preserve Node's default crash behaviour for unrelated rejections.\n setImmediate(() => {\n throw reason;\n });\n });\n}\n\nclass LocalTransformersEmbedder implements Embedder {\n readonly modelId: string;\n readonly dim: number;\n private pipelinePromise: Promise<FeatureExtractionPipeline> | null = null;\n private permanentFailure: Error | null = null;\n\n constructor(modelId: string = DEFAULT_MODEL_ID, dim: number = DEFAULT_DIM) {\n this.modelId = modelId;\n this.dim = dim;\n }\n\n private async getPipeline(): Promise<FeatureExtractionPipeline> {\n if (this.permanentFailure) throw this.permanentFailure;\n if (this.pipelinePromise) return this.pipelinePromise;\n installNativeRejectionFilter();\n const p = (async (): Promise<FeatureExtractionPipeline> => {\n let mod: typeof import('@huggingface/transformers');\n try {\n mod = await import('@huggingface/transformers');\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n if (/libonnxruntime|onnxruntime-node|ERR_DLOPEN_FAILED/i.test(msg)) {\n throw new Error(\n `Embeddings unavailable: '@huggingface/transformers' loaded but its native ` +\n `dependency 'onnxruntime-node' could not load (${msg}). On Vercel, add ` +\n `'./node_modules/onnxruntime-node/**' to 'outputFileTracingIncludes' ` +\n `for the relevant routes, or rely on offline 'npx octocms embeddings:gen'.`,\n );\n }\n throw new Error(\n `Embeddings require the optional peer dep '@huggingface/transformers'. Install it with: npm install @huggingface/transformers`,\n );\n }\n const pipe = (await mod.pipeline('feature-extraction', this.modelId)) as unknown as FeatureExtractionPipeline;\n return pipe;\n })();\n // Mark as handled at promise-creation time so a rejection that beats the\n // first await (e.g. native-lib load) doesn't fire unhandledRejection.\n p.catch((e: unknown) => {\n this.permanentFailure = e instanceof Error ? e : new Error(String(e));\n this.pipelinePromise = null;\n });\n this.pipelinePromise = p;\n return p;\n }\n\n async embed(texts: string[]): Promise<Float32Array[]> {\n if (texts.length === 0) return [];\n const pipe = await this.getPipeline();\n // bge-small expects mean-pooled, L2-normalised embeddings — the model card\n // and Xenova's transformers.js examples both prescribe these defaults.\n const output = await pipe(texts, { pooling: 'mean', normalize: true });\n const flat = output.data;\n const out: Float32Array[] = [];\n for (let i = 0; i < texts.length; i++) {\n const start = i * this.dim;\n const slice = new Float32Array(this.dim);\n slice.set(flat.subarray(start, start + this.dim));\n out.push(slice);\n }\n return out;\n }\n}\n\nlet defaultEmbedder: Embedder | null = null;\n\n/** Lazy singleton — first call kicks off the model load (~3–10s cold). */\nexport function getDefaultEmbedder(): Embedder {\n if (!defaultEmbedder) defaultEmbedder = new LocalTransformersEmbedder();\n return defaultEmbedder;\n}\n\n/** Test seam: replace or reset the singleton. */\nexport function setDefaultEmbedder(embedder: Embedder | null): void {\n defaultEmbedder = embedder;\n}\n\nexport { LocalTransformersEmbedder, DEFAULT_MODEL_ID, DEFAULT_DIM };\n","import type { Config } from '../types';\n\n/** Derive the companion `.md` file path for a markdown field from the entry JSON path. */\nexport function companionMarkdownPath(entryJsonPath: string, fieldName: string): string {\n const base = entryJsonPath.replace(/\\.json$/, '');\n return `${base}.${fieldName}.md`;\n}\n\n/** Derive the companion `.mdx` file path for a richtext field from the entry JSON path. */\nexport function companionRichTextPath(entryJsonPath: string, fieldName: string): string {\n const base = entryJsonPath.replace(/\\.json$/, '');\n return `${base}.${fieldName}.mdx`;\n}\n\n/** Return field names that have `format: 'markdown'` for the given collection type. */\nexport function getMarkdownFieldNames(collectionType: string, collections: Config['collections']): string[] {\n const col = (collections as Record<string, any>)[collectionType];\n if (!col) return [];\n return Object.entries(col.fields)\n .filter(([, def]: [string, any]) => def.format === 'markdown')\n .map(([key]) => key);\n}\n\n/** Return field names that have `format: 'richtext'` for the given collection type. */\nexport function getRichTextFieldNames(collectionType: string, collections: Config['collections']): string[] {\n const col = (collections as Record<string, any>)[collectionType];\n if (!col) return [];\n return Object.entries(col.fields)\n .filter(([, def]: [string, any]) => def.format === 'richtext')\n .map(([key]) => key);\n}\n\n/** Return a map of `{ fieldName: companionPath }` for all markdown fields in the collection. */\nexport function companionMarkdownPathsForEntry(\n entryJsonPath: string,\n collectionType: string,\n collections: Config['collections'],\n): Record<string, string> {\n const names = getMarkdownFieldNames(collectionType, collections);\n const result: Record<string, string> = {};\n for (const name of names) {\n result[name] = companionMarkdownPath(entryJsonPath, name);\n }\n return result;\n}\n\n/** Return a map of `{ fieldName: companionPath }` for all richtext fields in the collection. */\nexport function companionRichTextPathsForEntry(\n entryJsonPath: string,\n collectionType: string,\n collections: Config['collections'],\n): Record<string, string> {\n const names = getRichTextFieldNames(collectionType, collections);\n const result: Record<string, string> = {};\n for (const name of names) {\n result[name] = companionRichTextPath(entryJsonPath, name);\n }\n return result;\n}\n\n/**\n * Return a map of `{ fieldName: companionPath }` for ALL companion-file fields\n * (both markdown `.md` and richtext `.mdx`) in the collection.\n */\nexport function companionFilePathsForEntry(\n entryJsonPath: string,\n collectionType: string,\n collections: Config['collections'],\n): Record<string, string> {\n return {\n ...companionMarkdownPathsForEntry(entryJsonPath, collectionType, collections),\n ...companionRichTextPathsForEntry(entryJsonPath, collectionType, collections),\n };\n}\n","/**\n * On-disk format helpers for the embeddings store.\n *\n * Embedding vectors are stored as base64-encoded `Float32Array` payloads in\n * `cms/__generated__/embeddings.json`. Base64 keeps them ASCII-safe for JSON\n * (no NaN escaping, no array-of-numbers bloat) while still round-tripping\n * losslessly to `Float32Array` for in-process cosine similarity.\n */\n\n/** Encode a `Float32Array` to a base64 string. */\nexport function encodeFloat32(vec: Float32Array): string {\n // Wrap the underlying buffer in a Uint8Array view, then base64-encode it.\n const bytes = new Uint8Array(vec.buffer, vec.byteOffset, vec.byteLength);\n return Buffer.from(bytes).toString('base64');\n}\n\n/** Decode a base64 string back into a `Float32Array`. */\nexport function decodeFloat32(b64: string): Float32Array {\n const buf = Buffer.from(b64, 'base64');\n // Copy into a fresh ArrayBuffer so the returned view is not tied to Buffer's\n // pooled allocator (Buffer instances may share memory with other Buffers).\n const ab = new ArrayBuffer(buf.byteLength);\n new Uint8Array(ab).set(buf);\n return new Float32Array(ab);\n}\n\n/**\n * Cosine similarity in `[-1, 1]`. Returns `0` for zero-length inputs or when\n * either vector has zero magnitude. Both vectors must have the same length —\n * mismatched lengths throw to surface programmer error early.\n */\nexport function cosineSimilarity(a: Float32Array, b: Float32Array): number {\n if (a.length !== b.length) {\n throw new Error(`cosineSimilarity: length mismatch (${a.length} vs ${b.length})`);\n }\n if (a.length === 0) return 0;\n\n let dot = 0;\n let normA = 0;\n let normB = 0;\n for (let i = 0; i < a.length; i++) {\n const x = a[i];\n const y = b[i];\n dot += x * y;\n normA += x * x;\n normB += y * y;\n }\n\n if (normA === 0 || normB === 0) return 0;\n return dot / (Math.sqrt(normA) * Math.sqrt(normB));\n}\n","/* oxlint-disable no-console -- intentional server-side observability for CMS/GitHub actions */\n\ntype CmsServerLogFields = {\n operation: string;\n message: string;\n branch?: string;\n status?: number;\n};\n\n/**\n * Structured stderr logging for CMS server actions (GitHub API failures, etc.).\n * Kept in one module so `no-console` stays enabled elsewhere.\n */\nexport const logCmsServerError = (fields: CmsServerLogFields): void => {\n const parts = [\n '[cms]',\n fields.operation,\n fields.branch ? `branch=${fields.branch}` : null,\n fields.status != null ? `status=${fields.status}` : null,\n fields.message,\n ].filter(Boolean);\n console.error(parts.join(' '));\n};\n","export type ContentSourceCode = 'github_config' | 'github_auth' | 'github_unavailable' | 'github_rate_limit';\n\nconst PUBLIC_PREFIX = 'CMS_PUBLIC:';\n\n/**\n * Thrown when the public site cannot load CMS content from GitHub (or config is invalid).\n * `message` uses a stable prefix so the client error boundary can recover details if `code` is lost in serialization.\n */\nexport class ContentSourceError extends Error {\n readonly code: ContentSourceCode;\n readonly userMessage: string;\n\n constructor(code: ContentSourceCode, userMessage: string, options?: { cause?: unknown }) {\n super(`${PUBLIC_PREFIX}${code}:${userMessage}`, options);\n this.name = 'ContentSourceError';\n this.code = code;\n this.userMessage = userMessage;\n }\n}\n\nexport function isContentSourceError(error: unknown): error is ContentSourceError {\n return error instanceof ContentSourceError;\n}\n\n/** Recover code + user text from a serialized error `message` (e.g. in the client error boundary). */\nexport function parseContentSourceFromMessage(message: string): {\n code: ContentSourceCode;\n userMessage: string;\n} | null {\n if (!message.startsWith(PUBLIC_PREFIX)) return null;\n const rest = message.slice(PUBLIC_PREFIX.length);\n const colon = rest.indexOf(':');\n if (colon === -1) return null;\n const code = rest.slice(0, colon) as ContentSourceCode;\n const userMessage = rest.slice(colon + 1);\n if (\n code !== 'github_config' &&\n code !== 'github_auth' &&\n code !== 'github_unavailable' &&\n code !== 'github_rate_limit'\n ) {\n return null;\n }\n if (!userMessage) return null;\n return { code, userMessage };\n}\n\ntype MapContext = { owner: string; repo: string; ref?: string };\n\n/**\n * Map a GitHub REST / Octokit error from `repos.getContent` (and similar) to a public-facing error.\n */\nexport function mapGitHubApiErrorToContentSource(error: unknown, ctx: MapContext): ContentSourceError {\n const err = error as { status?: number; message?: string; response?: { data?: { message?: string } } };\n const status = err?.status;\n const detail =\n (typeof err?.response?.data?.message === 'string' && err.response.data.message) ||\n (typeof err?.message === 'string' && err.message) ||\n 'Unknown error';\n\n if (status === 429) {\n return new ContentSourceError(\n 'github_rate_limit',\n 'GitHub rate limit exceeded. Please wait a few minutes and try again.',\n { cause: error },\n );\n }\n\n if (status === 401 || status === 403) {\n return new ContentSourceError(\n 'github_auth',\n `This site could not read content from GitHub (${ctx.owner}/${ctx.repo}). For private repositories, set CMS_GITHUB_TOKEN with Contents: Read access. If you use a token, ensure it is valid and has access to this repository.`,\n { cause: error },\n );\n }\n\n if (typeof status === 'number' && status >= 500) {\n return new ContentSourceError('github_unavailable', 'GitHub is temporarily unavailable. Please try again later.', {\n cause: error,\n });\n }\n\n if (status === 404) {\n const refHint = ctx.ref ? ` (ref: ${ctx.ref})` : '';\n return new ContentSourceError(\n 'github_auth',\n `Content was not found in GitHub at ${ctx.owner}/${ctx.repo}${refHint}. The branch or file may be missing, or the server may not have permission to read it.`,\n { cause: error },\n );\n }\n\n const lower = String(detail).toLowerCase();\n if (\n lower.includes('fetch failed') ||\n lower.includes('econnreset') ||\n lower.includes('enotfound') ||\n lower.includes('etimedout') ||\n lower.includes('network') ||\n lower.includes('socket')\n ) {\n return new ContentSourceError(\n 'github_unavailable',\n 'Could not reach GitHub to load content. Check your network connection and try again later.',\n { cause: error },\n );\n }\n\n return new ContentSourceError('github_unavailable', `Could not load content from GitHub (${detail}).`, {\n cause: error,\n });\n}\n","import type { AuthOptions } from 'next-auth';\nimport GithubProvider from 'next-auth/providers/github';\n\nexport const authOptions: AuthOptions = {\n providers: [\n GithubProvider({\n clientId: process.env.GITHUB_ID || '',\n clientSecret: process.env.GITHUB_SECRET || '',\n authorization: { params: { scope: 'repo' } },\n }),\n ],\n secret: process.env.NEXTAUTH_SECRET || '',\n callbacks: {\n async jwt({ token, account }) {\n if (account?.access_token) {\n token.accessToken = account.access_token;\n }\n return token;\n },\n async session({ session, token }) {\n (session as any).accessToken = token.accessToken;\n return session;\n },\n },\n};\n","const trim = (value: string | undefined): string => (typeof value === 'string' ? value.trim() : '');\n\n/**\n * Optional default branch from env (per deploy). If set but the branch does not exist on GitHub,\n * callers fall back to `config.git.baseBranch`.\n */\nexport function getCmsBranchEnv(): string | undefined {\n const v = trim(process.env.CMS_BRANCH);\n return v || undefined;\n}\n\n/**\n * Build / deployment id for the per-build pointer filename under `cms/pointers/`.\n *\n * Typical sources: `VERCEL_DEPLOYMENT_ID`, `VERCEL_BUILD_ID`, `GITHUB_RUN_ID`, or `BUILD_ID`.\n * Falls back to `local` when unset (local dev and non-Vercel hosts should set `BUILD_ID` if multiple\n * deploys share one repo and need separate pointers).\n */\nexport function getBuildId(): string {\n const raw =\n trim(process.env.VERCEL_DEPLOYMENT_ID) ||\n trim(process.env.VERCEL_BUILD_ID) ||\n trim(process.env.GITHUB_RUN_ID) ||\n trim(process.env.BUILD_ID) ||\n '';\n const id = raw.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^\\.+/, '');\n return id || 'local';\n}\n\n/** True when the editor-selected branch matches public default (`baseBranch` or `CMS_BRANCH`). */\nexport function isDefaultPublicEditorBranch(branch: string, baseBranch: string): boolean {\n const b = trim(branch);\n if (!b) return true;\n if (b === trim(baseBranch)) return true;\n const envDefault = getCmsBranchEnv();\n if (envDefault && b === trim(envDefault)) return true;\n return false;\n}\n\n/** Serialized pointer JSON written to Git (includes `buildId` for traceability). */\nexport function serializePointerPayload(branch: string): string {\n return `${JSON.stringify({ branch, buildId: getBuildId() }, null, 2)}\\n`;\n}\n\n/** Repo-relative path to the per-build pointer JSON on the pointer ref (or base branch). */\nexport function getPointerFilePath(): string {\n const id =\n getBuildId()\n .replace(/[^a-zA-Z0-9._-]+/g, '-')\n .replace(/^\\.+/, '') || 'local';\n return `cms/pointers/${id}.json`;\n}\n","import type { Config } from '../types';\n\nlet _config: Config | null = null;\n\n/**\n * Register the app config. Called once by `withOctoCMS()` in `next.config.ts`\n * and by the generated `cms/__generated__/configInit.ts` side-effect module\n * (ensures the singleton is populated even in serverless cold starts).\n */\nexport function setConfig(config: Config): void {\n _config = config;\n}\n\n/**\n * Read the registered app config. Throws if `setConfig()` has not been called.\n *\n * All `octocms/` code that needs the runtime config should call this function\n * instead of importing directly from the consumer's `cms/octocms.config.ts`.\n */\nexport function getConfig(): Config {\n if (!_config) {\n throw new Error(\n 'OctoCMS config not initialized. Import `cms/__generated__/configInit` in your root `app/layout.tsx`, ' +\n 'in `src/instrumentation.ts`, and on the admin catch-all `cms/[[...path]]/page.tsx` (server actions may skip layout). ' +\n 'Also ensure `tsconfig.json` maps `cms/__generated__/*` to `./cms/__generated__/*` so admin server actions can load `configInit`. ' +\n 'See docs/deployment-errors.md.',\n );\n }\n return _config;\n}\n","/**\n * Runtime check: true when content reads use the GitHub API. True in\n * production builds; in dev, true only when `CMS_FORCE_GITHUB_API=true`.\n *\n * NOTE on bundler dead-code elimination: this is a function call, so the\n * bundler can't see through it. To gate dev-only filesystem code so it's\n * eliminated from production bundles, prefix the runtime check with an\n * inline `process.env.NODE_ENV` test in the SAME file:\n *\n * if (process.env.NODE_ENV === 'production' || isProductionMode()) {\n * // GitHub path — taken in prod, taken in dev when CMS_FORCE_GITHUB_API=true\n * } else {\n * // local FS path — DCE'd in prod, kept in dev\n * fsPromises.readFile(path.join(process.cwd(), filePath), 'utf8');\n * }\n *\n * Next.js statically replaces `process.env.NODE_ENV` with a string literal\n * at build time, so in production `'production' === 'production'` folds to\n * `true`, the `||` short-circuits, the `else` becomes unreachable, and the\n * bundler removes its `path.join(process.cwd(), …)` calls (which would\n * otherwise trip the NFT tracer into pulling in unrelated files like\n * `next.config.ts`). The replacement only happens for `process.env.NODE_ENV`\n * literals in the calling file — propagating a `const` exported from this\n * module across module boundaries is unreliable, so inline the check.\n */\nexport function isProductionMode(): boolean {\n if (process.env.NODE_ENV === 'production') return true;\n return process.env.CMS_FORCE_GITHUB_API === 'true';\n}\n","import { Octokit } from 'octokit';\n\nimport { getCmsBranchEnv, getPointerFilePath } from './lib/contentBranch';\nimport { getConfig } from './lib/configStore';\nimport { ContentSourceError, isContentSourceError, mapGitHubApiErrorToContentSource } from './lib/contentSourceError';\n\nexport { isProductionMode } from './lib/githubContentMode';\n\nconst getGitHubConfig = () => ({\n owner: process.env.GITHUB_REPO_OWNER || '',\n repo: process.env.GITHUB_REPO_NAME || '',\n branch: getConfig().git.baseBranch,\n});\n\nexport const assertGitHubConfig = () => {\n const { owner, repo, branch } = getGitHubConfig();\n\n if (!owner || !repo) {\n throw new ContentSourceError(\n 'github_config',\n 'GitHub repository is not configured. Set environment variables GITHUB_REPO_OWNER and GITHUB_REPO_NAME.',\n );\n }\n\n return { owner, repo, branch };\n};\n\n/**\n * Create public-read Octokit clients.\n *\n * 1) Use CMS_GITHUB_TOKEN when available (private repos / higher rate limits).\n * NOTE: Do NOT use GITHUB_TOKEN — Vercel overrides it with its own system token.\n * 2) Also try unauthenticated reads (public repos) to avoid hard dependency.\n */\nexport const getPublicOctokits = (): Octokit[] => {\n const token = process.env.CMS_GITHUB_TOKEN?.trim();\n const clients: Octokit[] = [];\n\n if (token) {\n clients.push(new Octokit({ auth: token }));\n }\n\n clients.push(new Octokit());\n\n return clients;\n};\n\n/**\n * When `config.git.publishedPointerBranch` is set, per-build pointer files under `cms/pointers/`\n * are read and written on that branch — use an unprotected branch so Publish avoids a protected base branch.\n */\nexport const getPublishedPointerRef = (): string | undefined => {\n const v = getConfig().git.publishedPointerBranch?.trim();\n return v || undefined;\n};\n\n/**\n * Read a file from GitHub using a static server token (no user session required).\n * Used by public pages to fetch content in production.\n */\nexport const readGitHubFilePublic = async (filePath: string, branch?: string): Promise<string | null> => {\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const ref = branch ?? configBranch;\n const clients = getPublicOctokits();\n\n let sawAuthError = false;\n for (const octokit of clients) {\n try {\n const { data } = await octokit.rest.repos.getContent({\n owner,\n repo,\n path: filePath,\n ref,\n });\n\n if ('content' in data && data.type === 'file') {\n return Buffer.from(data.content, 'base64').toString('utf-8');\n }\n\n return null;\n } catch (error: any) {\n if (error.status === 429) {\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref });\n }\n\n if (error.status === 401 || error.status === 403) {\n sawAuthError = true;\n continue;\n }\n\n if (error.status === 404) {\n // 404 from a client that authenticated successfully = file genuinely missing.\n // 404 only after auth failures = \"no access\" — keep trying / fall through.\n if (sawAuthError) continue;\n return null;\n }\n\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref });\n }\n }\n\n // All clients failed and at least one rejected auth — typical for private repos with bad token.\n const tokenPresent = !!process.env.CMS_GITHUB_TOKEN?.trim();\n throw new ContentSourceError(\n 'github_auth',\n tokenPresent\n ? `Cannot read ${owner}/${repo} (ref: ${ref}) from GitHub. CMS_GITHUB_TOKEN is set but was rejected — verify it has Contents: Read access on this repository.`\n : `Cannot read ${owner}/${repo} (ref: ${ref}) from GitHub. Set CMS_GITHUB_TOKEN with Contents: Read access on this repository.`,\n );\n};\n\n/**\n * List files in a directory from the GitHub repo.\n * Returns an array of file paths.\n *\n * Tries all available Octokit clients in order (authenticated first, then\n * unauthenticated) so that a bad/expired CMS_GITHUB_TOKEN automatically\n * falls back to unauthenticated reads on public repos.\n */\nexport const listGitHubFiles = async (dirPath: string, extension?: string, branch?: string): Promise<string[]> => {\n const clients = getPublicOctokits();\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const ref = branch ?? configBranch;\n\n let sawAuthError = false;\n for (const octokit of clients) {\n try {\n const { data } = await octokit.rest.repos.getContent({\n owner,\n repo,\n path: dirPath,\n ref,\n });\n\n if (!Array.isArray(data)) {\n return [];\n }\n\n let files = data.filter((item) => item.type === 'file').map((item) => item.path);\n\n if (extension) {\n files = files.filter((f) => f.endsWith(extension));\n }\n\n return files;\n } catch (error: any) {\n if (error.status === 429) {\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref });\n }\n if (error.status === 401 || error.status === 403) {\n sawAuthError = true;\n continue;\n }\n if (error.status === 404) {\n // 404 from a client that authenticated = directory genuinely missing.\n // 404 after auth failures = \"no access\" — keep trying / fall through.\n if (sawAuthError) continue;\n return [];\n }\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref });\n }\n }\n\n const tokenPresent = !!process.env.CMS_GITHUB_TOKEN?.trim();\n throw new ContentSourceError(\n 'github_auth',\n tokenPresent\n ? `Cannot list ${owner}/${repo}/${dirPath} (ref: ${ref}) from GitHub. CMS_GITHUB_TOKEN is set but was rejected — verify it has Contents: Read access on this repository.`\n : `Cannot list ${owner}/${repo}/${dirPath} (ref: ${ref}) from GitHub. Set CMS_GITHUB_TOKEN with Contents: Read access on this repository.`,\n );\n};\n\n/**\n * List files recursively across subdirectories (public read — same token/session\n * strategy as {@link listGitHubFiles}).\n */\nexport const listGitHubFilesRecursive = async (\n dirPath: string,\n extension?: string,\n branch?: string,\n): Promise<string[]> => {\n const [octokit] = getPublicOctokits();\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const ref = branch ?? configBranch;\n\n try {\n const { data } = await octokit.rest.repos.getContent({\n owner,\n repo,\n path: dirPath,\n ref,\n });\n\n if (!Array.isArray(data)) {\n return [];\n }\n\n const results: string[] = [];\n\n for (const item of data) {\n if (item.type === 'file') {\n if (!extension || item.path.endsWith(extension)) {\n results.push(item.path);\n }\n } else if (item.type === 'dir') {\n const subFiles = await listGitHubFilesRecursive(item.path, extension, branch);\n results.push(...subFiles);\n }\n }\n\n return results;\n } catch (error: any) {\n if (error.status === 404) {\n return [];\n }\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref });\n }\n};\n\n/**\n * Returns true when `heads/<branchName>` exists on the remote.\n */\nexport const branchExistsOnGitHub = async (branchName: string): Promise<boolean> => {\n const { owner, repo } = assertGitHubConfig();\n const clients = getPublicOctokits();\n\n let sawAuthError = false;\n for (const octokit of clients) {\n try {\n await octokit.rest.git.getRef({\n owner,\n repo,\n ref: `heads/${branchName}`,\n });\n return true;\n } catch (error: any) {\n if (error.status === 404) {\n if (sawAuthError) continue;\n return false;\n }\n if (error.status === 401 || error.status === 403) {\n sawAuthError = true;\n continue;\n }\n if (error.status === 429) {\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref: branchName });\n }\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref: branchName });\n }\n }\n\n const tokenPresent = !!process.env.CMS_GITHUB_TOKEN?.trim();\n throw new ContentSourceError(\n 'github_auth',\n tokenPresent\n ? `Cannot verify branch ${branchName} on ${owner}/${repo}. CMS_GITHUB_TOKEN is set but was rejected — verify it has Contents: Read access on this repository.`\n : `Cannot verify branch ${branchName} on ${owner}/${repo}. Set CMS_GITHUB_TOKEN with Contents: Read access on this repository.`,\n );\n};\n\n/**\n * List remote branch names whose ref starts with `refs/heads/<prefix>` (prefix should look like `cms/`).\n */\nexport const listGitHubBranchRefsByPrefix = async (prefix: string): Promise<string[]> => {\n const { owner, repo } = assertGitHubConfig();\n const normalized = prefix.replace(/^\\/+/, '');\n const refParam = normalized.endsWith('/') ? `heads/${normalized}` : `heads/${normalized}/`;\n const clients = getPublicOctokits();\n\n let sawAuthError = false;\n for (const octokit of clients) {\n try {\n const { data } = await octokit.rest.git.listMatchingRefs({\n owner,\n repo,\n ref: refParam,\n });\n return data.map((r) => r.ref.replace(/^refs\\/heads\\//, '')).filter((name): name is string => Boolean(name));\n } catch (error: any) {\n if (error.status === 429) {\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref: refParam });\n }\n if (error.status === 401 || error.status === 403) {\n sawAuthError = true;\n continue;\n }\n if (error.status === 404) {\n if (sawAuthError) continue;\n return [];\n }\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref: refParam });\n }\n }\n\n const tokenPresent = !!process.env.CMS_GITHUB_TOKEN?.trim();\n throw new ContentSourceError(\n 'github_auth',\n tokenPresent\n ? `Cannot list branch refs ${owner}/${repo} (${refParam}). CMS_GITHUB_TOKEN is set but was rejected — verify it has Contents: Read access on this repository.`\n : `Cannot list branch refs ${owner}/${repo} (${refParam}). Set CMS_GITHUB_TOKEN with Contents: Read access on this repository.`,\n );\n};\n\n/**\n * Resolve which Git branch public reads use.\n *\n * Precedence:\n * 1. `{ \"branch\": \"<name>\", \"buildId\": \"<id>\" }` from {@link getPointerFilePath} on the pointer ref (or base branch); only `branch` is used for resolution\n * 2. `CMS_BRANCH` env var when the branch exists\n * 3. `config.git.baseBranch`\n *\n * If the pointer file or `CMS_BRANCH` names a branch that does not exist, falls back to the next step.\n */\nexport const resolveContentBranch = async (): Promise<string> => {\n const { branch: configBranch } = assertGitHubConfig();\n const pointerRef = getPublishedPointerRef() ?? configBranch;\n const pointerPath = getPointerFilePath();\n\n /** Dedupe `git.getRef` within this resolution (pointer branch vs `CMS_BRANCH` may repeat). */\n const existsCache = new Map<string, Promise<boolean>>();\n const pickIfExists = async (name: string | undefined | null): Promise<string | null> => {\n if (!name || typeof name !== 'string') return null;\n const b = name.trim();\n if (!b) return null;\n if (b === configBranch) return configBranch;\n let pending = existsCache.get(b);\n if (!pending) {\n pending = branchExistsOnGitHub(b);\n existsCache.set(b, pending);\n }\n if (await pending) return b;\n return null;\n };\n\n let content: string | null;\n try {\n content = await readGitHubFilePublic(pointerPath, pointerRef);\n } catch (e) {\n if (isContentSourceError(e)) throw e;\n content = null;\n }\n\n if (content) {\n try {\n const parsed = JSON.parse(content) as { branch?: unknown };\n if (typeof parsed.branch === 'string') {\n const picked = await pickIfExists(parsed.branch);\n if (picked) return picked;\n }\n } catch {\n /* fall through */\n }\n }\n\n const envBranch = getCmsBranchEnv();\n if (envBranch) {\n const picked = await pickIfExists(envBranch);\n if (picked) return picked;\n }\n\n return configBranch;\n};\n","import { Octokit } from 'octokit';\nimport { getServerSession } from 'next-auth';\n\nimport { logCmsServerError } from '../lib/cmsServerLog';\nimport { mapGitHubApiErrorToContentSource } from '../lib/contentSourceError';\n\nimport { authOptions } from './auth';\n\nimport {\n assertGitHubConfig,\n getPublicOctokits,\n getPublishedPointerRef,\n readGitHubFilePublic,\n listGitHubFiles,\n listGitHubFilesRecursive,\n listGitHubBranchRefsByPrefix,\n resolveContentBranch,\n isProductionMode,\n} from '../github-public';\n\nexport {\n assertGitHubConfig,\n getPublicOctokits,\n getPublishedPointerRef,\n readGitHubFilePublic,\n listGitHubFiles,\n listGitHubFilesRecursive,\n listGitHubBranchRefsByPrefix,\n resolveContentBranch,\n isProductionMode,\n};\n\nconst getErrorMessage = (error: unknown): string => {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n};\n\nconst formatGitHubApiError = (error: any): string => {\n const status = error?.status;\n const message = error?.response?.data?.message || error?.message || getErrorMessage(error);\n\n if (status) {\n return `${status} ${message}`;\n }\n\n return message;\n};\n\nconst getDefaultBranchRef = async (octokit: Octokit, owner: string, repo: string): Promise<string> => {\n const { data: repoData } = await octokit.rest.repos.get({ owner, repo });\n const defaultBranch = repoData.default_branch || 'main';\n const { data: defaultRef } = await octokit.rest.git.getRef({\n owner,\n repo,\n ref: `heads/${defaultBranch}`,\n });\n\n return defaultRef.object.sha;\n};\n\nconst ensureBranchExists = async (octokit: Octokit, owner: string, repo: string, branch: string) => {\n try {\n await octokit.rest.git.getRef({\n owner,\n repo,\n ref: `heads/${branch}`,\n });\n } catch (error: any) {\n if (error.status !== 404) {\n throw error;\n }\n\n const baseSha = await getDefaultBranchRef(octokit, owner, repo);\n\n await octokit.rest.git.createRef({\n owner,\n repo,\n ref: `refs/heads/${branch}`,\n sha: baseSha,\n });\n }\n};\n\nconst getOctokit = async () => {\n const session = await getServerSession(authOptions);\n const accessToken = (session as any)?.accessToken;\n\n if (!accessToken) {\n throw new Error('No GitHub access token found. Please sign in again.');\n }\n\n return new Octokit({ auth: accessToken });\n};\n\n/**\n * Get an Octokit client suitable for write operations (save, delete, create PR).\n * Prefers CMS_GITHUB_TOKEN so it works even when the GitHub App is not installed\n * on the target repo. Falls back to the user session token.\n */\nconst getWriteOctokit = async (): Promise<Octokit> => {\n const token = process.env.CMS_GITHUB_TOKEN?.trim();\n\n if (token) {\n return new Octokit({ auth: token });\n }\n\n return getOctokit();\n};\n\n/**\n * Read a binary file from GitHub using a static server token (no user session required).\n * If `branch` is provided, reads from that branch directly (used by the media route\n * so editors see uploads on their active feature branch before publishing).\n * Otherwise uses {@link resolveContentBranch} so assets match the same ref as\n * `query()` / public JSON (not only `git.baseBranch`).\n * Returns a Buffer, or null if the file does not exist.\n */\nexport const readGitHubBinaryFilePublic = async (filePath: string, branch?: string): Promise<Buffer | null> => {\n const { owner, repo } = assertGitHubConfig();\n const ref = branch ?? (await resolveContentBranch());\n const clients = getPublicOctokits();\n\n for (const octokit of clients) {\n try {\n const { data } = await octokit.rest.repos.getContent({\n owner,\n repo,\n path: filePath,\n ref,\n });\n\n if ('content' in data && data.type === 'file') {\n return Buffer.from(data.content.replace(/\\n/g, ''), 'base64');\n }\n\n return null;\n } catch (error: any) {\n if (error.status === 429) {\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref });\n }\n\n if (error.status === 401 || error.status === 403 || error.status === 404) {\n continue;\n }\n\n throw mapGitHubApiErrorToContentSource(error, { owner, repo, ref });\n }\n }\n\n return null;\n};\n\n/**\n * Get a file's content and SHA from the GitHub repo.\n * Returns { content, sha } or null if the file doesn't exist.\n */\nexport const getGitHubFile = async (\n filePath: string,\n branch?: string,\n): Promise<{ content: string; sha: string } | null> => {\n const [octokit] = getPublicOctokits();\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const ref = branch || configBranch;\n\n try {\n const { data } = await octokit.rest.repos.getContent({\n owner,\n repo,\n path: filePath,\n ref,\n });\n\n if ('content' in data && data.type === 'file') {\n const content = Buffer.from(data.content, 'base64').toString('utf-8');\n return { content, sha: data.sha };\n }\n\n return null;\n } catch (error: any) {\n if (error.status === 404) {\n return null;\n }\n throw error;\n }\n};\n\n/**\n * Create or update a file in the GitHub repo via a commit.\n *\n * @param existingSha Optional SHA of the existing file blob. When provided from\n * the content store, skips the pre-read API call (saves 1 request per write).\n */\nexport const saveGitHubFile = async (\n filePath: string,\n content: string,\n message: string,\n branch?: string,\n existingSha?: string,\n) => {\n const octokit = await getWriteOctokit();\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const targetBranch = branch || configBranch;\n\n await ensureBranchExists(octokit, owner, repo, targetBranch);\n\n // Get existing file SHA if it exists (required for updates) — skip when caller provides it\n const existing = existingSha ? { sha: existingSha } : await getGitHubFile(filePath, targetBranch);\n\n try {\n await octokit.rest.repos.createOrUpdateFileContents({\n owner,\n repo,\n path: filePath,\n message,\n content: Buffer.from(content).toString('base64'),\n branch: targetBranch,\n ...(existing ? { sha: existing.sha } : {}),\n });\n } catch (error: any) {\n if (error.status === 403) {\n throw new Error(\n 'GitHub token is missing repository write permissions. Ensure the app is installed on the repo and has Contents: Read and write permission.',\n );\n }\n\n if (error.status === 409) {\n throw new Error(\n 'GitHub rejected the commit due to branch protection or write conflicts. Use a writable branch (for example cms/edits) or relax direct-push protection on main.',\n );\n }\n\n if (error.status === 422) {\n throw new Error(`GitHub validation failed while saving content: ${formatGitHubApiError(error)}`);\n }\n\n throw new Error(`GitHub save failed: ${formatGitHubApiError(error)}`);\n }\n};\n\n/**\n * Create or update a binary file in the GitHub repo via a commit.\n * Unlike saveGitHubFile, this accepts a Buffer directly to avoid encoding corruption.\n */\nexport const saveGitHubBinaryFile = async (filePath: string, buffer: Buffer, message: string, branch?: string) => {\n const octokit = await getWriteOctokit();\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const targetBranch = branch || configBranch;\n\n await ensureBranchExists(octokit, owner, repo, targetBranch);\n\n const existing = await getGitHubFile(filePath, targetBranch);\n\n try {\n await octokit.rest.repos.createOrUpdateFileContents({\n owner,\n repo,\n path: filePath,\n message,\n content: buffer.toString('base64'),\n branch: targetBranch,\n ...(existing ? { sha: existing.sha } : {}),\n });\n } catch (error: any) {\n if (error.status === 403) {\n throw new Error(\n 'GitHub token is missing repository write permissions. Ensure the app is installed on the repo and has Contents: Read and write permission.',\n );\n }\n\n if (error.status === 409) {\n throw new Error(\n 'GitHub rejected the commit due to branch protection or write conflicts. Use a writable branch (for example cms/edits) or relax direct-push protection on main.',\n );\n }\n\n if (error.status === 422) {\n throw new Error(`GitHub validation failed while saving content: ${formatGitHubApiError(error)}`);\n }\n\n throw new Error(`GitHub save failed: ${formatGitHubApiError(error)}`);\n }\n};\n\n/**\n * A single file change in a multi-file commit. `delete` removes the path\n * from the tree; `upsert-text` and `upsert-binary` create or update it.\n */\nexport type GitHubBatchChange =\n | { kind: 'upsert-text'; path: string; content: string }\n | { kind: 'upsert-binary'; path: string; content: Buffer }\n | { kind: 'delete'; path: string };\n\n/**\n * Commit multiple file changes atomically as a single GitHub commit on\n * `branch`. Used by the visual schema editor to write `cms/schema.json`\n * plus regenerated artifacts plus migrated entry files in one commit.\n *\n * Implementation: builds a git tree off the branch's current HEAD, creates a\n * single commit, then fast-forwards the branch. If `branch` does not exist,\n * it is created from `git.baseBranch` first (mirrors `ensureBranchExists`).\n *\n * Throws if all `changes` are no-ops (e.g. all deletes target missing paths)\n * — GitHub rejects empty trees.\n */\nexport const commitMultipleFilesToGitHub = async (\n changes: readonly GitHubBatchChange[],\n message: string,\n branch?: string,\n): Promise<{ sha: string }> => {\n if (changes.length === 0) {\n throw new Error('commitMultipleFilesToGitHub: no changes provided');\n }\n\n const octokit = await getWriteOctokit();\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const targetBranch = branch || configBranch;\n\n await ensureBranchExists(octokit, owner, repo, targetBranch);\n\n const { data: ref } = await octokit.rest.git.getRef({\n owner,\n repo,\n ref: `heads/${targetBranch}`,\n });\n const headSha = ref.object.sha;\n\n const { data: headCommit } = await octokit.rest.git.getCommit({\n owner,\n repo,\n commit_sha: headSha,\n });\n const baseTreeSha = headCommit.tree.sha;\n\n const tree: {\n path: string;\n mode: '100644';\n type: 'blob';\n sha?: string | null;\n content?: string;\n }[] = [];\n\n for (const change of changes) {\n if (change.kind === 'delete') {\n tree.push({ path: change.path, mode: '100644', type: 'blob', sha: null });\n continue;\n }\n if (change.kind === 'upsert-text') {\n // Push content directly. GitHub will create a blob server-side.\n tree.push({ path: change.path, mode: '100644', type: 'blob', content: change.content });\n continue;\n }\n // Binary: must upload as a blob first, then reference its SHA.\n const { data: blob } = await octokit.rest.git.createBlob({\n owner,\n repo,\n content: change.content.toString('base64'),\n encoding: 'base64',\n });\n tree.push({ path: change.path, mode: '100644', type: 'blob', sha: blob.sha });\n }\n\n let newTreeSha: string;\n try {\n const { data: newTree } = await octokit.rest.git.createTree({\n owner,\n repo,\n base_tree: baseTreeSha,\n tree,\n });\n newTreeSha = newTree.sha;\n } catch (error: any) {\n throw new Error(`GitHub createTree failed: ${formatGitHubApiError(error)}`);\n }\n\n if (newTreeSha === baseTreeSha) {\n throw new Error('commitMultipleFilesToGitHub: changes produced no diff (every file was already up to date)');\n }\n\n const { data: newCommit } = await octokit.rest.git.createCommit({\n owner,\n repo,\n message,\n tree: newTreeSha,\n parents: [headSha],\n });\n\n try {\n await octokit.rest.git.updateRef({\n owner,\n repo,\n ref: `heads/${targetBranch}`,\n sha: newCommit.sha,\n });\n } catch (error: any) {\n if (error.status === 422) {\n throw new Error(\n `Branch \"${targetBranch}\" moved while committing. Retry the schema save: ${formatGitHubApiError(error)}`,\n );\n }\n throw new Error(`GitHub updateRef failed: ${formatGitHubApiError(error)}`);\n }\n\n return { sha: newCommit.sha };\n};\n\n/**\n * Delete a file from the GitHub repo via a commit.\n */\nexport const deleteGitHubFile = async (filePath: string, message: string, branch?: string) => {\n const octokit = await getWriteOctokit();\n const { owner, repo, branch: configBranch } = assertGitHubConfig();\n const targetBranch = branch || configBranch;\n\n const existing = await getGitHubFile(filePath, targetBranch);\n\n if (!existing) {\n return; // File doesn't exist, nothing to delete\n }\n\n await octokit.rest.repos.deleteFile({\n owner,\n repo,\n path: filePath,\n message,\n sha: existing.sha,\n branch: targetBranch,\n });\n};\n\n/**\n * Create a new branch in the GitHub repo from `config.git.baseBranch`.\n */\nexport const createGitHubBranch = async (branchName: string): Promise<void> => {\n const octokit = await getWriteOctokit();\n const { owner, repo, branch: baseBranch } = assertGitHubConfig();\n\n const { data: baseRef } = await octokit.rest.git.getRef({\n owner,\n repo,\n ref: `heads/${baseBranch}`,\n });\n\n await octokit.rest.git.createRef({\n owner,\n repo,\n ref: `refs/heads/${branchName}`,\n sha: baseRef.object.sha,\n });\n};\n\nconst ensureLabelExists = async (octokit: Octokit, owner: string, repo: string, name: string, color: string) => {\n try {\n await octokit.rest.issues.getLabel({ owner, repo, name });\n } catch (error: any) {\n if (error.status === 404) {\n await octokit.rest.issues.createLabel({\n owner,\n repo,\n name,\n color,\n description: 'Content updates from the CMS editor',\n });\n } else {\n throw error;\n }\n }\n};\n\n/**\n * Create a draft pull request for a CMS branch, adding the 'cms-update' label.\n */\nexport const createGitHubCMSPullRequest = async (\n headBranch: string,\n title: string,\n body: string,\n targetBranch: string,\n): Promise<{ url: string; number: number }> => {\n const octokit = await getWriteOctokit();\n const { owner, repo } = assertGitHubConfig();\n\n let data: { html_url: string; number: number };\n\n try {\n const res = await octokit.rest.pulls.create({\n owner,\n repo,\n title,\n body,\n head: headBranch,\n base: targetBranch,\n draft: true,\n });\n data = res.data;\n } catch (error: any) {\n const detail = formatGitHubApiError(error);\n logCmsServerError({\n operation: 'pulls.create',\n branch: headBranch,\n status: error?.status,\n message: detail,\n });\n\n if (error?.status === 422) {\n const lower = detail.toLowerCase();\n if (lower.includes('no commits between')) {\n throw new Error(\n 'Could not open draft pull request: GitHub reports no new commits on this branch versus the base branch. Save branch metadata should have created a commit — please try again or open a pull request manually on GitHub.',\n );\n }\n\n throw new Error(`Could not open draft pull request: ${detail}`);\n }\n\n throw new Error(`Could not open draft pull request: ${detail}`);\n }\n\n try {\n await ensureLabelExists(octokit, owner, repo, 'cms-update', '0075ca');\n await octokit.rest.issues.addLabels({\n owner,\n repo,\n issue_number: data.number,\n labels: ['cms-update'],\n });\n } catch (_e) {\n // Label is cosmetic — don't fail branch creation if labelling errors\n }\n\n return { url: data.html_url, number: data.number };\n};\n\n/**\n * List all open PRs tagged with the 'cms-update' label.\n */\nexport const listGitHubCMSPullRequests = async (): Promise<\n { branch: string; prUrl: string; prNumber: number; title: string }[]\n> => {\n const octokit = await getWriteOctokit();\n const { owner, repo } = assertGitHubConfig();\n\n const { data: prs } = await octokit.rest.pulls.list({\n owner,\n repo,\n state: 'open',\n per_page: 100,\n });\n\n return prs\n .filter((pr) => pr.labels.some((l) => l.name === 'cms-update'))\n .map((pr) => ({\n branch: pr.head.ref,\n prUrl: pr.html_url,\n prNumber: pr.number,\n title: pr.title,\n }));\n};\n\nexport type RecentCMSPullRequestState = 'open' | 'merged' | 'closed';\n\n/**\n * List the most-recently-updated PRs tagged with the `cms-update` label,\n * across all states (open / merged / closed). Used by the dashboard\n * \"Recent pull requests\" card.\n */\nexport const listGitHubRecentCMSPullRequests = async (\n limit = 5,\n): Promise<\n {\n branch: string;\n prUrl: string;\n prNumber: number;\n title: string;\n state: RecentCMSPullRequestState;\n updatedAt: string;\n authorLogin: string | null;\n authorAvatarUrl: string | null;\n }[]\n> => {\n const octokit = await getWriteOctokit();\n const { owner, repo } = assertGitHubConfig();\n\n const { data: prs } = await octokit.rest.pulls.list({\n owner,\n repo,\n state: 'all',\n sort: 'updated',\n direction: 'desc',\n per_page: 50,\n });\n\n return prs\n .filter((pr) => pr.labels.some((l) => l.name === 'cms-update'))\n .slice(0, Math.max(1, limit))\n .map((pr) => {\n const state: RecentCMSPullRequestState = pr.merged_at ? 'merged' : pr.state === 'open' ? 'open' : 'closed';\n return {\n branch: pr.head.ref,\n prUrl: pr.html_url,\n prNumber: pr.number,\n title: pr.title,\n state,\n updatedAt: pr.updated_at,\n authorLogin: pr.user?.login ?? null,\n authorAvatarUrl: pr.user?.avatar_url ?? null,\n };\n });\n};\n\n/**\n * Create a pull request from the configured branch to the target branch.\n */\nexport const createGitHubPullRequest = async (\n title: string,\n body: string,\n targetBranch: string = 'main',\n): Promise<{ url: string; number: number }> => {\n const octokit = await getWriteOctokit();\n const { owner, repo, branch } = assertGitHubConfig();\n\n if (branch === targetBranch) {\n throw new Error(`Cannot create PR: source branch \"${branch}\" is the same as target branch \"${targetBranch}\"`);\n }\n\n const { data } = await octokit.rest.pulls.create({\n owner,\n repo,\n title,\n body,\n head: branch,\n base: targetBranch,\n });\n\n return { url: data.html_url, number: data.number };\n};\n\n/**\n * Merge a pull request via squash.\n */\nexport const mergePullRequest = async (prNumber: number): Promise<void> => {\n const octokit = await getWriteOctokit();\n const { owner, repo } = assertGitHubConfig();\n\n await octokit.rest.pulls.merge({\n owner,\n repo,\n pull_number: prNumber,\n merge_method: 'squash',\n });\n};\n\n/**\n * Convert a draft pull request for a CMS branch to \"Ready for Review\".\n * No-op if no open PR exists for the branch or if it is already non-draft.\n */\nexport const markPRReadyForReview = async (branchName: string): Promise<void> => {\n const octokit = await getWriteOctokit();\n const { owner, repo } = assertGitHubConfig();\n\n const { data: prs } = await octokit.rest.pulls.list({\n owner,\n repo,\n head: `${owner}:${branchName}`,\n state: 'open',\n per_page: 1,\n });\n\n const pr = prs[0];\n if (!pr || !pr.draft) return;\n\n await octokit.graphql(\n `mutation MarkReadyForReview($pullRequestId: ID!) {\n markPullRequestReadyForReview(input: { pullRequestId: $pullRequestId }) {\n pullRequest { isDraft }\n }\n }`,\n { pullRequestId: pr.node_id },\n );\n};\n","/**\n * Store I/O for the embeddings index.\n *\n * The store is a single committed JSON file (`cms/__generated__/embeddings.json`)\n * holding one row per content entry: `{ hash, vec }`. `hash` is a sha256 of the\n * embedding text — when an entry's text hasn't changed we skip re-embedding,\n * which keeps `embeddings:gen` fast and idempotent.\n *\n * Used by:\n * - The CLI command `embeddings:gen` for full / incremental rebuilds.\n * - The save/new/remove server actions to keep the store in sync with content.\n * - Phase 2's `searchContent` for cosine retrieval (read-only).\n */\n\nimport { createHash } from 'crypto';\nimport { promises as fsPromises } from 'fs';\nimport path from 'path';\n\nimport type { Config } from '../types';\nimport { companionFilePathsForEntry } from '../lib/companionMarkdown';\nimport { entryToEmbeddingText } from './embedText';\nimport { getDefaultEmbedder, type Embedder, DEFAULT_DIM, DEFAULT_MODEL_ID } from './embedder';\nimport { decodeFloat32, encodeFloat32 } from './storeFormat';\n\nexport const EMBEDDINGS_STORE_PATH = 'cms/__generated__/embeddings.json';\n\nexport type EmbeddingsRecord = {\n /** sha256 of the embedding text — used to skip re-embed when content is unchanged. */\n hash: string;\n /** Base64-encoded `Float32Array`. */\n vec: string;\n};\n\nexport type EmbeddingsStore = {\n model: string;\n dim: number;\n /** Map from content path (e.g. `\"cms/content/post/post-abc.json\"`) to record. */\n entries: Record<string, EmbeddingsRecord>;\n};\n\n/** Hash an embedding text into a stable cache key. */\nexport function hashEmbeddingText(text: string): string {\n return createHash('sha256').update(text).digest('hex');\n}\n\n/** Construct an empty store with the given embedder's metadata. */\nexport function emptyStore(embedder?: Embedder): EmbeddingsStore {\n const e = embedder ?? null;\n return {\n model: e?.modelId ?? DEFAULT_MODEL_ID,\n dim: e?.dim ?? DEFAULT_DIM,\n entries: {},\n };\n}\n\nfunction normalizeContentPath(p: string): string {\n return p.replace(/\\\\/g, '/');\n}\n\n/**\n * Read the embeddings store from disk. Returns an empty store when the file\n * doesn't exist yet — first run after enabling the agent.\n *\n * Production reads from the active branch via the GitHub admin helpers;\n * `branch` is forwarded to `getGitHubFile` when provided. Dev / CLI reads\n * straight from the local FS.\n */\nexport async function loadEmbeddings(branch?: string): Promise<EmbeddingsStore> {\n const raw = await readStoreRaw(branch);\n if (!raw) return emptyStore();\n try {\n const parsed = JSON.parse(raw) as Partial<EmbeddingsStore>;\n if (!parsed || typeof parsed !== 'object' || !parsed.entries || typeof parsed.entries !== 'object') {\n return emptyStore();\n }\n return {\n model: typeof parsed.model === 'string' ? parsed.model : DEFAULT_MODEL_ID,\n dim: typeof parsed.dim === 'number' ? parsed.dim : DEFAULT_DIM,\n entries: parsed.entries as Record<string, EmbeddingsRecord>,\n };\n } catch {\n return emptyStore();\n }\n}\n\nasync function readStoreRaw(branch?: string): Promise<string | null> {\n // Try GitHub first when running in production / a Next.js server context;\n // fall back silently to local FS so the CLI works offline.\n try {\n const isProd = process.env.NODE_ENV === 'production';\n if (isProd) {\n const { getGitHubFile } = await import('../admin/github');\n const file = await getGitHubFile(EMBEDDINGS_STORE_PATH, branch);\n if (file) return file.content;\n }\n } catch {\n /* fall through to local FS */\n }\n try {\n const abs = path.join(process.cwd(), 'cms', '__generated__', 'embeddings.json');\n return await fsPromises.readFile(abs, { encoding: 'utf8' });\n } catch {\n return null;\n }\n}\n\n/** Serialise a store to the canonical on-disk format (JSON, sorted keys, trailing newline). */\nexport function serializeStore(store: EmbeddingsStore): string {\n const sortedEntries: Record<string, EmbeddingsRecord> = {};\n for (const key of Object.keys(store.entries).sort()) {\n sortedEntries[key] = store.entries[key];\n }\n const ordered: EmbeddingsStore = {\n model: store.model,\n dim: store.dim,\n entries: sortedEntries,\n };\n return JSON.stringify(ordered, null, 2) + '\\n';\n}\n\n/** Pure helper — return a new store with `path` removed. */\nexport function removeEntryFromStore(store: EmbeddingsStore, entryPath: string): EmbeddingsStore {\n const norm = normalizeContentPath(entryPath);\n if (!(norm in store.entries)) return store;\n const next: Record<string, EmbeddingsRecord> = { ...store.entries };\n delete next[norm];\n return { ...store, entries: next };\n}\n\n/** Pure helper — return a new store with `path` upserted. */\nexport function upsertEntryInStore(\n store: EmbeddingsStore,\n entryPath: string,\n record: EmbeddingsRecord,\n): EmbeddingsStore {\n const norm = normalizeContentPath(entryPath);\n return {\n ...store,\n entries: { ...store.entries, [norm]: record },\n };\n}\n\nasync function readEntryAndCompanionsLocal(\n filePath: string,\n collections: Config['collections'],\n): Promise<{\n entry: { sys?: { type?: string }; fields?: Record<string, unknown> };\n companions: Record<string, string>;\n} | null> {\n const abs = path.join(process.cwd(), 'cms', filePath.replace(/^cms[\\\\/]/, ''));\n let raw: string;\n try {\n raw = await fsPromises.readFile(abs, { encoding: 'utf8' });\n } catch {\n return null;\n }\n let entry: any;\n try {\n entry = JSON.parse(raw);\n } catch {\n return null;\n }\n const collectionType = entry?.sys?.type;\n const companions: Record<string, string> = {};\n if (typeof collectionType === 'string') {\n const paths = companionFilePathsForEntry(filePath, collectionType, collections);\n for (const [field, p] of Object.entries(paths)) {\n try {\n companions[field] = await fsPromises.readFile(path.join(process.cwd(), 'cms', p.replace(/^cms[\\\\/]/, '')), {\n encoding: 'utf8',\n });\n } catch {\n companions[field] = '';\n }\n }\n }\n return { entry, companions };\n}\n\n/**\n * Compute (or look up) the embedding for a single entry on disk.\n *\n * - `store` provides the previous record (if any) so we can skip re-embedding\n * when the text hash hasn't changed.\n * - `embedder` defaults to the local transformers singleton.\n *\n * Returns `null` when the entry can't be read (deleted between listing and\n * embedding, or unreadable JSON).\n */\nexport async function embedEntry(\n filePath: string,\n options: {\n collections: Config['collections'];\n store?: EmbeddingsStore;\n embedder?: Embedder;\n },\n): Promise<{ path: string; hash: string; vec: Float32Array; skipped: boolean } | null> {\n const { collections, store, embedder = getDefaultEmbedder() } = options;\n const norm = normalizeContentPath(filePath);\n const loaded = await readEntryAndCompanionsLocal(filePath, collections);\n if (!loaded) return null;\n\n const text = entryToEmbeddingText(loaded.entry, loaded.companions);\n const hash = hashEmbeddingText(text);\n\n const existing = store?.entries[norm];\n if (existing && existing.hash === hash && store?.dim === embedder.dim) {\n return { path: norm, hash, vec: decodeFloat32(existing.vec), skipped: true };\n }\n\n const [vec] = await embedder.embed([text]);\n return { path: norm, hash, vec, skipped: false };\n}\n\n/**\n * Embed an entry from already-in-memory content. Used by the save/new server\n * actions to avoid an extra disk roundtrip — the entry payload and companion\n * map are right there in `saveFile`'s scope.\n */\nexport async function embedEntryFromMemory(\n entry: { fields?: Record<string, unknown> },\n companions: Record<string, string>,\n options: {\n store?: EmbeddingsStore;\n embedder?: Embedder;\n } = {},\n): Promise<{ hash: string; vec: Float32Array; skipped: boolean; record: EmbeddingsRecord }> {\n const { embedder = getDefaultEmbedder() } = options;\n const text = entryToEmbeddingText(entry, companions);\n const hash = hashEmbeddingText(text);\n const [vec] = await embedder.embed([text]);\n return {\n hash,\n vec,\n skipped: false,\n record: { hash, vec: encodeFloat32(vec) },\n };\n}\n\n/**\n * Rebuild the store for `paths` in a single batched embedder call. Reuses\n * existing records when their content hash matches — full rebuilds against\n * unchanged content are no-ops.\n */\nexport async function embedAll(\n paths: readonly string[],\n options: {\n collections: Config['collections'];\n previous?: EmbeddingsStore;\n embedder?: Embedder;\n /** Optional progress callback — `(done, total)` per entry processed. */\n onProgress?: (done: number, total: number) => void;\n },\n): Promise<EmbeddingsStore> {\n const { collections, previous, embedder = getDefaultEmbedder(), onProgress } = options;\n const next = emptyStore(embedder);\n\n // First pass: compute texts + hashes; mark which need re-embedding.\n type PendingEntry = { path: string; text: string; hash: string };\n const toEmbed: PendingEntry[] = [];\n let processed = 0;\n\n for (const filePath of paths) {\n const norm = normalizeContentPath(filePath);\n const loaded = await readEntryAndCompanionsLocal(filePath, collections);\n if (!loaded) continue;\n const text = entryToEmbeddingText(loaded.entry, loaded.companions);\n const hash = hashEmbeddingText(text);\n const existing = previous?.entries[norm];\n if (existing && existing.hash === hash && previous?.dim === embedder.dim) {\n next.entries[norm] = existing;\n processed++;\n onProgress?.(processed, paths.length);\n continue;\n }\n toEmbed.push({ path: norm, text, hash });\n }\n\n // Second pass: batched embedding. Chunk to avoid OOM on giant collections.\n const BATCH = 32;\n for (let i = 0; i < toEmbed.length; i += BATCH) {\n const chunk = toEmbed.slice(i, i + BATCH);\n const vecs = await embedder.embed(chunk.map((c) => c.text));\n for (let j = 0; j < chunk.length; j++) {\n const { path: p, hash } = chunk[j];\n next.entries[p] = { hash, vec: encodeFloat32(vecs[j]) };\n processed++;\n onProgress?.(processed, paths.length);\n }\n }\n\n return next;\n}\n","/**\n * Side-effect hook used by save/new/remove server actions to keep\n * `cms/__generated__/embeddings.json` in sync with content writes.\n *\n * Best-effort by design — when the agent is disabled, the optional peer dep\n * is missing, or the embedder fails for any reason, the helper logs a warning\n * and returns silently. The primary content commit still succeeds; running\n * `embeddings:gen` in CI is the safety net that repairs drift.\n *\n * The hook itself is responsible for *persisting* the updated store. In\n * production this is a separate single-file commit (kept simple to avoid\n * refactoring the multi-step save flow); in dev it's a local FS write. When\n * we later move to atomic batched commits this module is the single seam to\n * change.\n */\n\n/* eslint-disable no-console */\n\nimport { promises as fsPromises } from 'fs';\nimport path from 'path';\n\nimport type { Config } from '../types';\nimport type { AgentConfig } from './types';\nimport { isAgentEnabled } from './featureFlag';\nimport {\n EMBEDDINGS_STORE_PATH,\n embedEntryFromMemory,\n emptyStore,\n loadEmbeddings,\n removeEntryFromStore,\n serializeStore,\n upsertEntryInStore,\n type EmbeddingsStore,\n} from './embeddings';\n\nfunction normalizeContentPath(p: string): string {\n return p.replace(/\\\\/g, '/');\n}\n\nasync function persistStore(\n serialized: string,\n branch: string | undefined,\n message: string,\n isProduction: boolean,\n): Promise<void> {\n if (isProduction) {\n const { saveGitHubFile } = await import('../admin/github');\n await saveGitHubFile(EMBEDDINGS_STORE_PATH, serialized, message, branch);\n return;\n }\n const abs = path.join(process.cwd(), 'cms', '__generated__', 'embeddings.json');\n await fsPromises.mkdir(path.dirname(abs), { recursive: true });\n await fsPromises.writeFile(abs, serialized, 'utf8');\n}\n\n/**\n * Re-embed the given entry and persist the updated store. No-op when the\n * agent is disabled. Failures are logged and swallowed — content writes must\n * not fail because of an embedding issue.\n */\nexport async function syncEmbeddingsAfterUpsert(args: {\n agentConfig: AgentConfig;\n config: Config;\n entryPath: string;\n payload: { sys?: { type?: string }; fields?: Record<string, unknown> };\n companions: Record<string, string>;\n branch: string | undefined;\n isProduction: boolean;\n}): Promise<void> {\n const { agentConfig, entryPath, payload, companions, branch, isProduction } = args;\n if (!isAgentEnabled(agentConfig)) return;\n\n try {\n const previous: EmbeddingsStore = await loadEmbeddings(branch).catch(() => emptyStore());\n const { record } = await embedEntryFromMemory(payload, companions, { store: previous });\n const next = upsertEntryInStore(previous, normalizeContentPath(entryPath), record);\n await persistStore(serializeStore(next), branch, `CMS: update embeddings for ${entryPath}`, isProduction);\n } catch (e) {\n console.warn(`[octocms/agent] embeddings sync failed for ${entryPath}: ${(e as Error).message}`);\n }\n}\n\n/**\n * Drop the entry from the store and persist. No-op when the entry isn't in\n * the store. Same best-effort semantics as `syncEmbeddingsAfterUpsert`.\n */\nexport async function syncEmbeddingsAfterRemove(args: {\n agentConfig: AgentConfig;\n entryPath: string;\n branch: string | undefined;\n isProduction: boolean;\n}): Promise<void> {\n const { agentConfig, entryPath, branch, isProduction } = args;\n if (!isAgentEnabled(agentConfig)) return;\n\n try {\n const previous: EmbeddingsStore = await loadEmbeddings(branch).catch(() => emptyStore());\n const norm = normalizeContentPath(entryPath);\n if (!(norm in previous.entries)) return;\n const next = removeEntryFromStore(previous, norm);\n await persistStore(serializeStore(next), branch, `CMS: remove embeddings for ${entryPath}`, isProduction);\n } catch (e) {\n console.warn(`[octocms/agent] embeddings remove failed for ${entryPath}: ${(e as Error).message}`);\n }\n}\n","/**\n * Pure helpers for deriving an entry's display title and identity from the\n * config + the parsed entry JSON.\n *\n * Extracted from `octocms/admin/actions/entries.ts` so non-admin code paths\n * (e.g. the chat agent's `searchContent`) can resolve titles without pulling\n * in `'use server'` modules. The admin `getEntryList` is a thin wrapper that\n * adds disk I/O on top of these helpers.\n */\n\nimport type { Config } from '../admin/types';\n\n/** Locate the field marked `entryTitle: true` on the given collection, if any. */\nexport function getEntryTitleField(config: Config, collectionName: string): string | undefined {\n const collection = config.collections[collectionName as keyof Config['collections']];\n if (!collection) return undefined;\n return Object.keys(collection.fields).find((key) => collection.fields[key].entryTitle);\n}\n\n/** Default fallback: filename stem without folder prefix or `.json` extension. */\nexport function defaultEntryId(config: Config, filePath: string): string {\n const stripped = filePath.replace(`${config.contentFolder}/`, '').replace('.json', '');\n const parts = stripped.split('/');\n return parts[parts.length - 1] ?? stripped;\n}\n\n/** Return the collection name (= `sys.type` segment) for a given content file path.\n * Recognises media-entry paths under `mediaContentFolder` and returns `'media'`. */\nexport function collectionFromPath(config: Config, filePath: string): string {\n const mediaFolder = (config as Config & { mediaContentFolder?: string }).mediaContentFolder ?? 'cms/media';\n if (filePath.startsWith(`${mediaFolder}/`)) return 'media';\n const stripped = filePath.replace(`${config.contentFolder}/`, '').replace('.json', '');\n const parts = stripped.split('/');\n return parts[0] ?? '';\n}\n\ntype EntryPayload = {\n sys?: { id?: unknown; type?: unknown };\n fields?: Record<string, unknown>;\n};\n\n/**\n * Resolve a human-readable title from the entry payload, falling back to the\n * filename stem when no title field is configured or populated. Mirrors\n * `getEntryList` exactly so search hits and the entry list agree.\n */\nexport function resolveEntryTitle(config: Config, filePath: string, entry: EntryPayload | null | undefined): string {\n const fallback = defaultEntryId(config, filePath);\n if (!entry) return fallback;\n\n const collectionType = typeof entry.sys?.type === 'string' ? entry.sys.type : collectionFromPath(config, filePath);\n\n // Media entries store their display name on `fields.title` regardless of schema.\n if (collectionType === 'media') {\n const mediaTitle = entry.fields?.title;\n if (typeof mediaTitle === 'string' && mediaTitle.trim() !== '') return mediaTitle.trim();\n return fallback;\n }\n\n const titleField = getEntryTitleField(config, collectionType);\n if (titleField) {\n const value = entry.fields?.[titleField];\n if (typeof value === 'string' && value.trim() !== '') return value.trim();\n if (typeof value === 'number' || typeof value === 'boolean') return String(value);\n }\n\n return fallback;\n}\n\n/**\n * Resolve the entry id — `sys.id` for media (kept for parity with `getEntryList`),\n * filename stem for everything else.\n */\nexport function resolveEntryId(config: Config, filePath: string, entry: EntryPayload | null | undefined): string {\n const fallback = defaultEntryId(config, filePath);\n if (!entry) return fallback;\n const collectionType = typeof entry.sys?.type === 'string' ? entry.sys.type : collectionFromPath(config, filePath);\n if (collectionType === 'media') {\n const sysId = entry.sys?.id;\n if (typeof sysId === 'string' && sysId !== '') return sysId;\n }\n return fallback;\n}\n\n/**\n * Build a short text excerpt for search hits — picks the first non-title\n * text-like field, trims and ellipsizes to `maxLen`. Works without companion\n * markdown content, so callers don't need to do another disk read.\n */\nexport function buildEntryExcerpt(\n config: Config,\n filePath: string,\n entry: EntryPayload | null | undefined,\n maxLen = 200,\n): string {\n if (!entry?.fields) return '';\n const collectionType = typeof entry.sys?.type === 'string' ? entry.sys.type : collectionFromPath(config, filePath);\n const titleField = getEntryTitleField(config, collectionType);\n const collection = config.collections[collectionType as keyof Config['collections']];\n if (!collection) return '';\n\n const candidateFormats = new Set(['text', 'markdown', 'richtext', 'string']);\n for (const [fieldKey, fieldDef] of Object.entries(collection.fields)) {\n if (fieldKey === titleField) continue;\n if (!candidateFormats.has(fieldDef.format)) continue;\n const value = entry.fields[fieldKey];\n const text = stringifyForExcerpt(value);\n if (text) return truncate(text, maxLen);\n }\n return '';\n}\n\nfunction stringifyForExcerpt(value: unknown): string {\n if (typeof value === 'string') return value.trim();\n if (Array.isArray(value))\n return value\n .filter((v) => typeof v === 'string')\n .join(', ')\n .trim();\n return '';\n}\n\nfunction truncate(text: string, maxLen: number): string {\n const collapsed = text.replace(/\\s+/g, ' ').trim();\n if (collapsed.length <= maxLen) return collapsed;\n return collapsed.slice(0, maxLen - 1).trimEnd() + '…';\n}\n","/**\n * Side-effect module: runs `setConfig()` / `setAgentConfig()` via the generated\n * `cms/__generated__/configInit.ts`. Imported at the top of every admin server\n * action file so Next.js server-action bundles (which may omit layout and\n * catch-all `page.tsx`) still initialise the config singleton before `getConfig()`.\n *\n * Requires `tsconfig` path `cms/__generated__/*` → `./cms/__generated__/*`\n * (`octocms init` / `octocms update` add this).\n */\nimport 'cms/__generated__/configInit';\n","import fsPromises from 'fs/promises';\nimport path from 'path';\n\n/** Read a JSON content file from local disk. Returns null on ENOENT or parse error. */\nexport async function readLocalContentFile(filePath: string): Promise<unknown | null> {\n const fullPath = path.join(process.cwd(), filePath);\n try {\n const data = await fsPromises.readFile(fullPath, { encoding: 'utf8' });\n return JSON.parse(data);\n } catch (error: any) {\n if (error?.code === 'ENOENT' || error instanceof SyntaxError) return null;\n throw error;\n }\n}\n\n/** Read a raw text file (e.g. companion .md) from local disk. Returns '' on ENOENT. */\nexport async function readLocalRawFile(filePath: string): Promise<string> {\n const fullPath = path.join(process.cwd(), filePath);\n try {\n return await fsPromises.readFile(fullPath, { encoding: 'utf8' });\n } catch (error: any) {\n if (error?.code === 'ENOENT') return '';\n throw error;\n }\n}\n\n/**\n * List all files under `dirPath` whose name ends with `ext`, recursively.\n * Returns paths like `dirPath/sub/file.ext` with forward slashes, sorted.\n * Returns [] if the directory does not exist.\n */\nexport async function listLocalFilesRecursive(dirPath: string, ext: string): Promise<string[]> {\n return listLocalFilesWithExtensions(dirPath, [ext], true);\n}\n\n/**\n * List files in `dirPath` whose name ends with any of the given extensions.\n * Pass `recursive: true` to descend into subdirectories.\n * Extensions may include or omit the leading dot.\n * Returns [] if the directory does not exist.\n */\nexport async function listLocalFilesWithExtensions(\n dirPath: string,\n extensions: string[],\n recursive = false,\n): Promise<string[]> {\n const fullDir = path.join(process.cwd(), dirPath);\n const normalizedExts = extensions.map((e) => (e.startsWith('.') ? e : `.${e}`));\n\n try {\n if (recursive) {\n const names = (await fsPromises.readdir(fullDir, { recursive: true })) as unknown as string[];\n return names\n .filter((n) => normalizedExts.some((e) => n.endsWith(e)))\n .map((n) => `${dirPath}/${n}`.replace(/\\\\/g, '/'))\n .sort();\n }\n\n const entries = await fsPromises.readdir(fullDir, { withFileTypes: true });\n return (entries as import('fs').Dirent[])\n .filter((e) => e.isFile() && normalizedExts.some((ext) => e.name.endsWith(ext)))\n .map((e) => `${dirPath}/${e.name}`)\n .sort();\n } catch (error: any) {\n if (error?.code === 'ENOENT') return [];\n throw error;\n }\n}\n\n/** List .json files in a collection directory on local disk. Returns [] if directory does not exist. */\nexport async function listLocalCollectionFiles(dirPath: string): Promise<string[]> {\n const fullDir = path.join(process.cwd(), dirPath);\n try {\n const entries = await fsPromises.readdir(fullDir, { withFileTypes: true });\n return entries.filter((e) => e.isFile() && e.name.endsWith('.json')).map((e) => `${dirPath}/${e.name}`);\n } catch (error: any) {\n if (error?.code === 'ENOENT') return [];\n throw error;\n }\n}\n","import { z } from 'zod';\n\n/** Repo path for CMS branch workspace metadata (committed on feature branches). */\nexport const BRANCH_HISTORY_FILE_PATH = 'cms/branch-history.json';\n\nconst branchWorkspaceSchema = z.object({\n title: z.string(),\n description: z.string().optional(),\n createdAt: z.string(),\n entries: z.array(z.string()),\n});\n\nexport type BranchWorkspaceRecord = z.infer<typeof branchWorkspaceSchema>;\n\n/** Maps Git branch name → workspace metadata. */\nexport type BranchHistoryFile = Record<string, BranchWorkspaceRecord>;\n\nconst rootSchema = z.record(z.string(), branchWorkspaceSchema);\n\nexport const parseBranchHistoryFile = (content: string): BranchHistoryFile => {\n const trimmed = content.trim();\n if (!trimmed) {\n return {};\n }\n\n try {\n const parsed: unknown = JSON.parse(trimmed);\n const result = rootSchema.safeParse(parsed);\n return result.success ? result.data : {};\n } catch {\n return {};\n }\n};\n\nexport const serializeBranchHistoryFile = (data: BranchHistoryFile): string => `${JSON.stringify(data, null, 2)}\\n`;\n\nexport type UpsertBranchWorkspaceInput = {\n title: string;\n description?: string;\n createdAt: string;\n};\n\n/**\n * Add or update a branch workspace. If the branch key already exists, preserves `entries`\n * and the original `createdAt`; updates `title` and optional `description`.\n */\nexport const upsertBranchWorkspace = (\n data: BranchHistoryFile,\n branchName: string,\n input: UpsertBranchWorkspaceInput,\n): BranchHistoryFile => {\n const existing = data[branchName];\n\n if (existing) {\n return {\n ...data,\n [branchName]: {\n title: input.title,\n ...(input.description !== undefined && input.description !== ''\n ? { description: input.description }\n : existing.description !== undefined\n ? { description: existing.description }\n : {}),\n createdAt: existing.createdAt,\n entries: existing.entries,\n },\n };\n }\n\n return {\n ...data,\n [branchName]: {\n title: input.title,\n ...(input.description !== undefined && input.description !== '' ? { description: input.description } : {}),\n createdAt: input.createdAt,\n entries: [],\n },\n };\n};\n\n/** Append a content file path to the branch's `entries` if not already present. No-op if branch missing. */\nexport const appendEntryPathToBranch = (\n data: BranchHistoryFile,\n branchName: string,\n entryPath: string,\n): BranchHistoryFile => {\n const existing = data[branchName];\n if (!existing) {\n return data;\n }\n\n if (existing.entries.includes(entryPath)) {\n return data;\n }\n\n return {\n ...data,\n [branchName]: {\n ...existing,\n entries: [...existing.entries, entryPath],\n },\n };\n};\n\n/** Returns serialized JSON or `null` if there is nothing to write (unknown branch or no new entry). */\nexport const mergeHistoryContentWithAppendedEntry = (\n content: string,\n branchName: string,\n entryPath: string,\n): string | null => {\n const data = parseBranchHistoryFile(content);\n if (!data[branchName]) {\n return null;\n }\n\n const next = appendEntryPathToBranch(data, branchName, entryPath);\n if (next === data) {\n return null;\n }\n\n return serializeBranchHistoryFile(next);\n};\n","import type { Config } from '../admin/types';\nimport { getConfig } from './configStore';\n\n/**\n * Default `fields` object for a newly created entry (from schema `defaultBoolean`, `defaultOption`, etc.).\n */\nexport function initialFieldsForNewEntry(collectionType: string): Record<string, unknown> {\n const config = getConfig();\n const col = config.collections[collectionType as keyof Config['collections']];\n if (!col) {\n return {};\n }\n\n const out: Record<string, unknown> = {};\n\n for (const [key, def] of Object.entries(col.fields)) {\n if (def.format === 'boolean' && def.defaultBoolean !== undefined) {\n out[key] = def.defaultBoolean ? 'true' : 'false';\n continue;\n }\n\n if (def.format === 'select') {\n const allowed = new Set(def.options.map((o) => o.value));\n if (def.multiple === true) {\n const raw = def.defaultOptions;\n if (raw?.length) {\n const vals = raw.filter((v) => allowed.has(v));\n if (vals.length > 0) {\n out[key] = vals;\n }\n }\n } else if (def.defaultOption != null && allowed.has(def.defaultOption)) {\n out[key] = def.defaultOption;\n }\n }\n }\n\n return out;\n}\n","import type { CollectionField } from '../admin/types';\n\nconst HEX6 = /^#([0-9a-f]{6})$/i;\nconst HEX3 = /^#([0-9a-f]{3})$/i;\n\n/**\n * Expands #rgb to #rrggbb. Returns null if the string is not a valid hex color token.\n */\nexport function normalizeHexColor(raw: string): string | null {\n const s = raw.trim();\n if (!s) {\n return null;\n }\n const m6 = HEX6.exec(s);\n if (m6) {\n return `#${m6[1]!.toLowerCase()}`;\n }\n const m3 = HEX3.exec(s);\n if (m3) {\n const [r, g, b] = m3[1]!.split('');\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\n }\n return null;\n}\n\nexport function parseColorFieldInput(\n def: Pick<CollectionField, 'label' | 'required'>,\n raw: string,\n): { ok: true; value: string } | { ok: false; message: string } {\n const trimmed = raw.trim();\n if (!trimmed) {\n if (def.required) {\n return { ok: false, message: `${def.label} is required` };\n }\n return { ok: true, value: '' };\n }\n const normalized = normalizeHexColor(trimmed);\n if (!normalized) {\n return {\n ok: false,\n message: `${def.label} must be a hex color such as #aabbcc or #abc`,\n };\n }\n return { ok: true, value: normalized };\n}\n","import type { CollectionField } from '../admin/types';\n\nfunction pad2(n: number): string {\n return String(n).padStart(2, '0');\n}\n\n/** Local `datetime-local` value (no timezone suffix). */\nexport function toDatetimeLocalValue(d: Date): string {\n return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}T${pad2(d.getHours())}:${pad2(d.getMinutes())}`;\n}\n\n/** Local `date` input value (YYYY-MM-DD). */\nexport function toDateInputValue(d: Date): string {\n return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;\n}\n\n/**\n * Convert stored ISO (full or date-only) to the value expected by `<input type=\"datetime-local\">` or `<input type=\"date\">`.\n */\nexport function storedDatetimeToFormInput(stored: string | null | undefined, dateOnly: boolean): string {\n const t = stored == null ? '' : String(stored).trim();\n if (!t) {\n return '';\n }\n if (dateOnly) {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(t)) {\n return t;\n }\n const d = new Date(t);\n if (Number.isNaN(d.getTime())) {\n return '';\n }\n return toDateInputValue(d);\n }\n const d = new Date(t);\n if (Number.isNaN(d.getTime())) {\n return '';\n }\n return toDatetimeLocalValue(d);\n}\n\n/**\n * Convert a browser date/datetime-local string to persisted ISO 8601 (UTC for date-time, calendar date for date-only).\n */\nexport function formInputToStoredIso(trimmed: string, dateOnly: boolean): string {\n if (dateOnly) {\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(trimmed)) {\n throw new Error('Invalid date');\n }\n const [y, m, day] = trimmed.split('-').map(Number);\n const d = new Date(y, m - 1, day);\n if (d.getFullYear() !== y || d.getMonth() !== m - 1 || d.getDate() !== day) {\n throw new Error('Invalid date');\n }\n return trimmed;\n }\n const d = new Date(trimmed);\n if (Number.isNaN(d.getTime())) {\n throw new Error('Invalid datetime');\n }\n return d.toISOString();\n}\n\nexport type DatetimeFieldParseResult = { ok: true; value: string | null } | { ok: false; message: string };\n\n/**\n * Parse a datetime field value from form text. Empty optional fields become `null`.\n */\nexport function parseDatetimeFieldInput(field: CollectionField, raw: string): DatetimeFieldParseResult {\n if (field.format !== 'datetime') {\n throw new Error('parseDatetimeFieldInput: field is not format \"datetime\"');\n }\n\n const dateOnly = field.dateOnly === true;\n const trimmed = raw.trim();\n if (trimmed === '') {\n if (field.required) {\n return { ok: false, message: `${field.label} is required` };\n }\n return { ok: true, value: null };\n }\n\n try {\n return { ok: true, value: formInputToStoredIso(trimmed, dateOnly) };\n } catch {\n return {\n ok: false,\n message: `${field.label} must be a valid ${dateOnly ? 'date' : 'date and time'}`,\n };\n }\n}\n","import type { CollectionField } from '../admin/types';\n\n/** Max textarea length for JSON fields (raw string before parse). */\nexport const JSON_FIELD_MAX_RAW_CHARS = 100_000;\n\nexport type JsonFieldParseResult = { ok: true; value: unknown | null } | { ok: false; message: string };\n\n/**\n * Serialize a stored JSON field value for the editor textarea.\n * Native objects/arrays from disk become pretty-printed JSON; legacy string values pass through.\n */\nexport function jsonFieldValueToFormString(raw: unknown): string {\n if (raw === undefined || raw === null) {\n return '';\n }\n if (typeof raw === 'string') {\n return raw;\n }\n try {\n return JSON.stringify(raw, null, 2);\n } catch {\n return '';\n }\n}\n\n/**\n * Parse and validate a JSON field from form text. Empty optional fields become `null`.\n */\nexport function parseJsonFieldInput(field: CollectionField, raw: string): JsonFieldParseResult {\n if (field.format !== 'json') {\n throw new Error('parseJsonFieldInput: field is not format \"json\"');\n }\n\n const trimmed = raw.trim();\n if (trimmed === '') {\n if (field.required) {\n return { ok: false, message: `${field.label} is required` };\n }\n return { ok: true, value: null };\n }\n\n if (raw.length > JSON_FIELD_MAX_RAW_CHARS) {\n return {\n ok: false,\n message: `${field.label} must be at most ${JSON_FIELD_MAX_RAW_CHARS.toLocaleString()} characters`,\n };\n }\n\n try {\n return { ok: true, value: JSON.parse(trimmed) };\n } catch {\n return { ok: false, message: `${field.label} must be valid JSON` };\n }\n}\n","import type { CollectionField } from '../admin/types';\n\nexport type NumberFieldParseResult = { ok: true; value: number | null } | { ok: false; message: string };\n\n/**\n * Parse a number field value from form text. Empty optional fields become `null`.\n */\nexport function parseNumberFieldInput(field: CollectionField, raw: string): NumberFieldParseResult {\n if (field.format !== 'number') {\n throw new Error('parseNumberFieldInput: field is not format \"number\"');\n }\n\n const trimmed = raw.trim();\n if (trimmed === '') {\n if (field.required) {\n return { ok: false, message: `${field.label} is required` };\n }\n return { ok: true, value: null };\n }\n\n const num = Number(trimmed);\n if (!Number.isFinite(num)) {\n return { ok: false, message: `${field.label} must be a valid number` };\n }\n\n if (field.valueType === 'int' && !Number.isInteger(num)) {\n return { ok: false, message: `${field.label} must be a whole number` };\n }\n\n if (field.min != null && num < field.min) {\n return { ok: false, message: `${field.label} must be at least ${field.min}` };\n }\n if (field.max != null && num > field.max) {\n return { ok: false, message: `${field.label} must be at most ${field.max}` };\n }\n\n const stored = field.valueType === 'int' ? Math.trunc(num) : num;\n return { ok: true, value: stored };\n}\n","import type { SelectCollectionField } from '../admin/types';\n\nexport type SelectFieldParseResult = { ok: true; value: string | string[] } | { ok: false; message: string };\n\nfunction allowedValues(field: SelectCollectionField): Set<string> {\n return new Set(field.options.map((o) => o.value));\n}\n\n/**\n * Parse select / multiselect form submission (single: plain string; multiple: JSON array string).\n */\nexport function parseSelectFieldInput(field: SelectCollectionField, raw: string): SelectFieldParseResult {\n const allowed = allowedValues(field);\n const multiple = field.multiple === true;\n\n if (multiple) {\n const trimmed = raw.trim();\n if (trimmed === '') {\n if (field.required) {\n return { ok: false, message: `${field.label} is required` };\n }\n return { ok: true, value: [] };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return { ok: false, message: `${field.label} has invalid data` };\n }\n if (!Array.isArray(parsed)) {\n return { ok: false, message: `${field.label} must be a JSON array` };\n }\n const strings = parsed.map((p) => String(p));\n for (const s of strings) {\n if (!allowed.has(s)) {\n return { ok: false, message: `${field.label} contains an invalid choice` };\n }\n }\n if (field.required && strings.length === 0) {\n return { ok: false, message: `${field.label} is required` };\n }\n return { ok: true, value: strings };\n }\n\n const t = raw.trim();\n if (t === '') {\n if (field.required) {\n return { ok: false, message: `${field.label} is required` };\n }\n return { ok: true, value: '' };\n }\n if (!allowed.has(t)) {\n return { ok: false, message: `${field.label} has an invalid choice` };\n }\n return { ok: true, value: t };\n}\n","import slugify from 'slugify';\n\nimport type { CollectionField } from '../admin/types';\n\n/** Stored slugs and URL segments must match this pattern (after normalization). */\nexport const SLUG_MAX_LENGTH = 200;\n\nconst SLUG_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\nexport function isValidSlugPattern(s: string): boolean {\n return s.length > 0 && s.length <= SLUG_MAX_LENGTH && SLUG_REGEX.test(s);\n}\n\n/**\n * Normalizes text as the user types in the slug field: lowercase, spaces and\n * underscores become hyphens, other invalid characters are removed, hyphens\n * collapsed. Leading hyphens are stripped; a trailing hyphen is kept while typing.\n */\nexport function sanitizeSlugFieldInputValue(raw: string): string {\n let s = raw.toLowerCase();\n s = s.replace(/[\\s_]+/g, '-');\n s = s.replace(/[^a-z0-9-]+/g, '');\n s = s.replace(/-+/g, '-');\n s = s.replace(/^-+/, '');\n if (s.length > SLUG_MAX_LENGTH) {\n s = s.slice(0, SLUG_MAX_LENGTH);\n }\n return s;\n}\n\n/**\n * Turn arbitrary text (e.g. entry title) into a URL slug segment.\n * Lowercase, hyphen-separated, ASCII alphanumerics only (`strict` mode).\n * Underscores are treated like spaces so words stay separated.\n */\nexport function slugifyForUrl(input: string): string {\n const trimmed = String(input).trim();\n const preprocessed = trimmed.replace(/_+/g, ' ').replace(/\\s+/g, ' ').trim();\n if (!preprocessed) {\n return '';\n }\n const raw = slugify(preprocessed, { lower: true, strict: true, trim: true });\n let collapsed = raw.replace(/-+/g, '-').replace(/^-|-$/g, '');\n if (collapsed.length > SLUG_MAX_LENGTH) {\n collapsed = collapsed.slice(0, SLUG_MAX_LENGTH).replace(/-+$/g, '');\n }\n return collapsed;\n}\n\n/**\n * Normalize a slug already stored in JSON for comparison (idempotent for valid slugs).\n */\nexport function normalizeStoredSlug(raw: string): string {\n return slugifyForUrl(raw);\n}\n\nexport function parseSlugFieldInput(\n def: Pick<CollectionField, 'label' | 'required'>,\n raw: string,\n): { ok: true; value: string } | { ok: false; message: string } {\n const trimmed = raw.trim();\n if (!trimmed) {\n if (def.required) {\n return { ok: false, message: `${def.label} is required` };\n }\n return { ok: true, value: '' };\n }\n const candidate = slugifyForUrl(trimmed);\n if (!isValidSlugPattern(candidate)) {\n return {\n ok: false,\n message: `${def.label} must be a URL-safe slug (lowercase letters, numbers, hyphens only)`,\n };\n }\n return { ok: true, value: candidate };\n}\n","/**\n * Parse and normalize string list values for `format: 'string'` fields with `list: true`.\n * Form submission uses a hidden input with JSON.stringify(string[]).\n */\nexport function normalizeStringListFromStorage(raw: unknown): string[] {\n if (Array.isArray(raw)) {\n return raw.map((x) => String(x));\n }\n if (raw == null || raw === '') {\n return [];\n }\n return [String(raw)];\n}\n\nexport type ParseStringListFormResult = { ok: true; items: string[] } | { ok: false; message: string };\n\n/**\n * Parses the hidden input value: must be JSON array of strings (non-string elements coerced).\n * Empty strings after trim are dropped.\n */\nexport function parseStringListFormRaw(raw: string): ParseStringListFormResult {\n const trimmed = raw.trim();\n if (trimmed === '') {\n return { ok: true, items: [] };\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return { ok: false, message: 'Invalid list data' };\n }\n if (!Array.isArray(parsed)) {\n return { ok: false, message: 'List field must be a JSON array' };\n }\n const items: string[] = [];\n for (const el of parsed) {\n const s = String(el).trim();\n if (s.length > 0) {\n items.push(s);\n }\n }\n return { ok: true, items };\n}\n","import type { CollectionField } from '../admin/types';\n\nfunction isAllowedCmsUrl(s: string): boolean {\n if (s.startsWith('https://') || s.startsWith('http://')) {\n return true;\n }\n if (s.startsWith('/')) {\n return !s.startsWith('//');\n }\n return false;\n}\n\nexport function parseUrlFieldInput(\n def: Pick<CollectionField, 'label' | 'required'>,\n raw: string,\n): { ok: true; value: string } | { ok: false; message: string } {\n const trimmed = raw.trim();\n if (!trimmed) {\n if (def.required) {\n return { ok: false, message: `${def.label} is required` };\n }\n return { ok: true, value: '' };\n }\n if (!isAllowedCmsUrl(trimmed)) {\n return {\n ok: false,\n message: `${def.label} must start with http://, https://, or / (root-relative path)`,\n };\n }\n return { ok: true, value: trimmed };\n}\n","import type { CollectionField, Config } from '../admin/types';\nimport { getConfig } from './configStore';\nimport { parseColorFieldInput } from './colorField';\nimport { parseDatetimeFieldInput } from './datetimeField';\nimport { parseJsonFieldInput } from './jsonField';\nimport { parseNumberFieldInput } from './numberField';\nimport { parseSelectFieldInput } from './selectField';\nimport { parseSlugFieldInput } from './slugField';\nimport { parseStringListFormRaw } from './stringListField';\nimport { parseUrlFieldInput } from './urlField';\n\n/**\n * Merge form string values into persisted field shapes (e.g. numbers as JSON numbers, datetimes as ISO strings or null).\n */\nexport function persistedFieldsFromFormStrings(\n collectionType: string,\n strFields: Record<string, string>,\n): Record<string, unknown> {\n const config = getConfig();\n const col = config.collections[collectionType as keyof Config['collections']];\n if (!col) {\n return { ...strFields };\n }\n\n const out: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(strFields)) {\n const def = col.fields[k];\n if (def?.format === 'number') {\n const r = parseNumberFieldInput(def, v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.value;\n } else if (def?.format === 'datetime') {\n const r = parseDatetimeFieldInput(def, v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.value;\n } else if (def?.format === 'json') {\n const r = parseJsonFieldInput(def, v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.value;\n } else if (def?.format === 'string' && def.list) {\n const r = parseStringListFormRaw(v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.items;\n } else if (def?.format === 'slug') {\n const r = parseSlugFieldInput(def, v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.value;\n } else if (def?.format === 'select') {\n const r = parseSelectFieldInput(def, v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.value;\n } else if (def?.format === 'text') {\n const trimmed = v.trim();\n if (def.required && !trimmed) {\n throw new Error(`${def.label} is required`);\n }\n out[k] = trimmed;\n } else if (def?.format === 'url') {\n const r = parseUrlFieldInput(def, v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.value;\n } else if (def?.format === 'color') {\n const r = parseColorFieldInput(def, v);\n if (!r.ok) {\n throw new Error(r.message);\n }\n out[k] = r.value;\n } else if (def?.format === 'markdown' || def?.format === 'richtext') {\n out[k] = v;\n } else if (def?.format === 'conditional') {\n // Conditional fields are stored as a keyed object — parse from JSON string.\n let parsed: unknown;\n try {\n parsed = v ? JSON.parse(v) : {};\n } catch {\n parsed = {};\n }\n\n if (typeof parsed === 'object' && parsed && !Array.isArray(parsed)) {\n const obj = parsed as Record<string, unknown>;\n const result: Record<string, unknown> = {};\n\n for (const branch of def.conditional.branches) {\n const branchValue = obj[branch.key];\n if (branch.collection) {\n // Reference branch — store as string ref key\n result[branch.key] = typeof branchValue === 'string' ? branchValue : '';\n } else if (branch.fields) {\n // Inline branch — recursively persist each sub-field\n const branchObj = (\n typeof branchValue === 'object' && branchValue && !Array.isArray(branchValue) ? branchValue : {}\n ) as Record<string, string>;\n\n const subOut: Record<string, unknown> = {};\n for (const [subK, subDef] of Object.entries(branch.fields)) {\n const subV = branchObj[subK] ?? '';\n const subStr = subV === null || subV === undefined ? '' : String(subV);\n subOut[subK] = persistSingleField(subDef, subStr);\n }\n result[branch.key] = subOut;\n }\n }\n out[k] = result;\n } else {\n out[k] = {};\n }\n } else {\n out[k] = v;\n }\n }\n return out;\n}\n\n/**\n * Persist a single field value from its form string. Returns the typed value for JSON storage.\n */\nfunction persistSingleField(def: CollectionField, raw: string): unknown {\n switch (def.format) {\n case 'number': {\n const r = parseNumberFieldInput(def, raw);\n return r.ok ? r.value : raw;\n }\n case 'datetime': {\n const r = parseDatetimeFieldInput(def, raw);\n return r.ok ? r.value : raw;\n }\n case 'json': {\n const r = parseJsonFieldInput(def, raw);\n return r.ok ? r.value : raw;\n }\n case 'string':\n if (def.list) {\n const r = parseStringListFormRaw(raw);\n return r.ok ? r.items : raw;\n }\n return raw;\n case 'slug': {\n const r = parseSlugFieldInput(def, raw);\n return r.ok ? r.value : raw;\n }\n case 'select': {\n const r = parseSelectFieldInput(def, raw);\n return r.ok ? r.value : raw;\n }\n case 'text':\n return raw.trim();\n case 'url': {\n const r = parseUrlFieldInput(def, raw);\n return r.ok ? r.value : raw;\n }\n case 'color': {\n const r = parseColorFieldInput(def, raw);\n return r.ok ? r.value : raw;\n }\n default:\n return raw;\n }\n}\n","import { z } from 'zod';\n\nimport type { CollectionField, Config, ConditionalCollectionField, ReferenceFieldConfig } from '../admin/types';\nimport { getConfig } from './configStore';\nimport { parseDatetimeFieldInput } from './datetimeField';\nimport { parseJsonFieldInput } from './jsonField';\nimport { parseNumberFieldInput } from './numberField';\nimport { parseSelectFieldInput } from './selectField';\nimport { parseColorFieldInput } from './colorField';\nimport { parseSlugFieldInput } from './slugField';\nimport { parseStringListFormRaw } from './stringListField';\nimport { parseUrlFieldInput } from './urlField';\n\nfunction parseReferencePaths(raw: string, cardinality: 'one' | 'many'): string[] {\n if (cardinality === 'one') {\n const t = raw.trim();\n return t ? [t] : [];\n }\n try {\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return parsed.map((p) => String(p));\n } catch {\n return [];\n }\n}\n\nfunction validateReferenceField(\n field: { label: string; required?: boolean; reference?: ReferenceFieldConfig },\n raw: string,\n): string | null {\n const cardinality = field.reference?.cardinality ?? 'many';\n const paths = parseReferencePaths(raw, cardinality);\n const max = cardinality === 'one' ? 1 : field.reference?.max;\n\n const minFromRef = field.reference?.min ?? 0;\n const minFromRequired = field.required ? 1 : 0;\n const effectiveMin = Math.max(minFromRef, minFromRequired);\n\n if (cardinality === 'one') {\n const count = paths.length > 0 && paths[0] ? 1 : 0;\n if (effectiveMin > 0 && count < 1) {\n return `${field.label} is required`;\n }\n if (max === 1 && paths.length > 1) {\n return `${field.label} allows only one item`;\n }\n return null;\n }\n\n if (paths.length < effectiveMin) {\n return effectiveMin === 1\n ? `${field.label} is required`\n : `At least ${effectiveMin} items required for ${field.label}`;\n }\n if (max != null && paths.length > max) {\n return `At most ${max} items allowed for ${field.label}`;\n }\n return null;\n}\n\n/**\n * Validates CMS entry field values from the editor form against collection config (Zod + reference rules).\n */\nexport function validateEntryFields(\n collectionType: string,\n fields: Record<string, string>,\n): { ok: true } | { ok: false; fieldErrors: Record<string, string> } {\n const config = getConfig();\n const col = config.collections[collectionType as keyof Config['collections']];\n if (!col) {\n return { ok: true };\n }\n\n const fieldErrors: Record<string, string> = {};\n\n for (const [key, def] of Object.entries(col.fields)) {\n const raw = fields[key] ?? '';\n let message: string | null = null;\n\n switch (def.format) {\n case 'string': {\n if (def.list) {\n const parsed = parseStringListFormRaw(raw);\n if (!parsed.ok) {\n message = parsed.message;\n } else if (def.required && parsed.items.length === 0) {\n message = `${def.label} is required`;\n }\n } else {\n const schema = def.required ? z.string().trim().min(1, `${def.label} is required`) : z.string();\n const parsed = schema.safeParse(raw);\n if (!parsed.success) {\n message = parsed.error.issues[0]?.message ?? 'Invalid value';\n }\n }\n break;\n }\n case 'text': {\n const schema = def.required ? z.string().trim().min(1, `${def.label} is required`) : z.string();\n const parsed = schema.safeParse(raw);\n if (!parsed.success) {\n message = parsed.error.issues[0]?.message ?? 'Invalid value';\n }\n break;\n }\n case 'markdown':\n case 'richtext': {\n const schema = def.required ? z.string().trim().min(1, `${def.label} is required`) : z.string();\n const parsed = schema.safeParse(raw);\n if (!parsed.success) {\n message = parsed.error.issues[0]?.message ?? 'Invalid value';\n }\n break;\n }\n case 'image': {\n const schema = def.required ? z.string().trim().min(1, `${def.label} is required`) : z.string();\n const parsed = schema.safeParse(raw);\n if (!parsed.success) {\n message = parsed.error.issues[0]?.message ?? 'Invalid value';\n }\n break;\n }\n case 'boolean': {\n const parsed = z.enum(['true', 'false']).safeParse(raw);\n if (!parsed.success) {\n message = `${def.label} is invalid`;\n }\n break;\n }\n case 'number': {\n const parsed = parseNumberFieldInput(def, raw);\n if (!parsed.ok) {\n message = parsed.message;\n }\n break;\n }\n case 'datetime': {\n const parsed = parseDatetimeFieldInput(def, raw);\n if (!parsed.ok) {\n message = parsed.message;\n }\n break;\n }\n case 'reference': {\n message = validateReferenceField(def, raw);\n break;\n }\n case 'json': {\n const parsed = parseJsonFieldInput(def, raw);\n if (!parsed.ok) {\n message = parsed.message;\n }\n break;\n }\n case 'slug': {\n const parsed = parseSlugFieldInput(def, raw);\n if (!parsed.ok) {\n message = parsed.message;\n }\n break;\n }\n case 'select': {\n const parsed = parseSelectFieldInput(def, raw);\n if (!parsed.ok) {\n message = parsed.message;\n }\n break;\n }\n case 'url': {\n const parsed = parseUrlFieldInput(def, raw);\n if (!parsed.ok) {\n message = parsed.message;\n }\n break;\n }\n case 'color': {\n const parsed = parseColorFieldInput(def, raw);\n if (!parsed.ok) {\n message = parsed.message;\n }\n break;\n }\n case 'conditional': {\n message = validateConditionalField(def, raw, key, fieldErrors);\n break;\n }\n default:\n break;\n }\n\n if (message) {\n fieldErrors[key] = message;\n }\n }\n\n return Object.keys(fieldErrors).length === 0 ? { ok: true } : { ok: false, fieldErrors };\n}\n\n/**\n * Validate all branches of a conditional field. Populates `fieldErrors` with dot-path keys\n * (e.g. `hero.image.src`) for nested branch field errors. Returns a top-level message or null.\n */\nfunction validateConditionalField(\n def: ConditionalCollectionField,\n raw: string,\n parentKey: string,\n fieldErrors: Record<string, string>,\n): string | null {\n let obj: Record<string, unknown>;\n try {\n obj = raw ? JSON.parse(raw) : {};\n } catch {\n return `${def.label} has invalid data`;\n }\n\n if (typeof obj !== 'object' || obj === null || Array.isArray(obj)) {\n return `${def.label} must be an object`;\n }\n\n for (const branch of def.conditional.branches) {\n const branchValue = obj[branch.key];\n\n if (branch.collection) {\n // Reference branch — validate the ref key is a non-empty string when required\n if (def.required && (!branchValue || typeof branchValue !== 'string' || !String(branchValue).trim())) {\n fieldErrors[`${parentKey}.${branch.key}`] = `${branch.label} reference is required`;\n }\n } else if (branch.fields) {\n // Inline branch — validate each sub-field\n const branchObj = (\n typeof branchValue === 'object' && branchValue && !Array.isArray(branchValue) ? branchValue : {}\n ) as Record<string, unknown>;\n\n for (const [subKey, subDef] of Object.entries(branch.fields)) {\n const subRaw = branchObj[subKey] ?? '';\n const subStr = subRaw === null || subRaw === undefined ? '' : String(subRaw);\n const subMessage = validateSingleField(subDef, subStr);\n if (subMessage) {\n fieldErrors[`${parentKey}.${branch.key}.${subKey}`] = subMessage;\n }\n }\n }\n }\n\n return null;\n}\n\n/**\n * Validate a single field value against its definition. Returns an error message or null.\n * Reuses the same logic as the main switch but for a single field.\n */\nfunction validateSingleField(def: CollectionField, raw: string): string | null {\n switch (def.format) {\n case 'string': {\n if (def.list) {\n const parsed = parseStringListFormRaw(raw);\n if (!parsed.ok) return parsed.message;\n if (def.required && parsed.items.length === 0) return `${def.label} is required`;\n } else {\n const schema = def.required ? z.string().trim().min(1, `${def.label} is required`) : z.string();\n const parsed = schema.safeParse(raw);\n if (!parsed.success) return parsed.error.issues[0]?.message ?? 'Invalid value';\n }\n return null;\n }\n case 'text':\n case 'markdown':\n case 'richtext':\n case 'image': {\n const schema = def.required ? z.string().trim().min(1, `${def.label} is required`) : z.string();\n const parsed = schema.safeParse(raw);\n if (!parsed.success) return parsed.error.issues[0]?.message ?? 'Invalid value';\n return null;\n }\n case 'boolean': {\n const parsed = z.enum(['true', 'false']).safeParse(raw);\n if (!parsed.success) return `${def.label} is invalid`;\n return null;\n }\n case 'number': {\n const parsed = parseNumberFieldInput(def, raw);\n return parsed.ok ? null : parsed.message;\n }\n case 'datetime': {\n const parsed = parseDatetimeFieldInput(def, raw);\n return parsed.ok ? null : parsed.message;\n }\n case 'reference': {\n return validateReferenceField(def, raw);\n }\n case 'json': {\n const parsed = parseJsonFieldInput(def, raw);\n return parsed.ok ? null : parsed.message;\n }\n case 'slug': {\n const parsed = parseSlugFieldInput(def, raw);\n return parsed.ok ? null : parsed.message;\n }\n case 'select': {\n const parsed = parseSelectFieldInput(def, raw);\n return parsed.ok ? null : parsed.message;\n }\n case 'url': {\n const parsed = parseUrlFieldInput(def, raw);\n return parsed.ok ? null : parsed.message;\n }\n case 'color': {\n const parsed = parseColorFieldInput(def, raw);\n return parsed.ok ? null : parsed.message;\n }\n case 'conditional': {\n // Nested conditional — recursive validation\n const nestedErrors: Record<string, string> = {};\n const msg = validateConditionalField(def, raw, '', nestedErrors);\n if (msg) return msg;\n // If there are nested errors, return the first one\n const firstErr = Object.values(nestedErrors)[0];\n return firstErr ?? null;\n }\n default:\n return null;\n }\n}\n","/**\n * Shared media-path helpers.\n *\n * Media entries live in their own top-level folder (`cms/media/` by default),\n * separate from editorial content under `cms/content/`. This module is the\n * single source of truth for that path so callers do not have to recompute it.\n */\n\nimport { getConfig } from './configStore';\n\nconst DEFAULT_MEDIA_CONTENT_FOLDER = 'cms/media';\n\n/** Folder where media entry JSONs are stored. */\nexport function mediaContentFolder(): string {\n const cfg = getConfig() as { mediaContentFolder?: unknown };\n const v = cfg.mediaContentFolder;\n return typeof v === 'string' && v.trim() !== '' ? v : DEFAULT_MEDIA_CONTENT_FOLDER;\n}\n\n/** Repo-relative path to the media entry JSON for a given media UUID. */\nexport function mediaEntryPath(id: string): string {\n return `${mediaContentFolder()}/media-${id}.json`;\n}\n\n/** True if a file path is a media entry JSON (under the media-content folder). */\nexport function isMediaEntryPath(p: string): boolean {\n return p.startsWith(`${mediaContentFolder()}/`);\n}\n","import MiniSearch, { type Options } from 'minisearch';\n\nimport type { CollectionField, Config, PublicCollectionSearchConfig } from '../types';\n\n// --- Types ---\n\nexport type SearchDocument = {\n id: string;\n type: string;\n typeLabel: string;\n title: string;\n content: string;\n snippet: string;\n url: string;\n};\n\nexport type SearchResult = {\n type: string;\n typeLabel: string;\n id: string;\n title: string;\n score: number;\n match: Record<string, string[]>;\n url: string;\n snippet: string;\n};\n\nexport type EntryForSearch = {\n /** Relative path, e.g. \"post/post-abc123.json\" */\n path: string;\n content: Record<string, unknown>;\n companionContent: Record<string, string>;\n};\n\n// --- Constants ---\n\nconst SEARCHABLE_BY_DEFAULT = new Set<string>(['string', 'text', 'markdown', 'richtext', 'slug', 'select']);\n\nconst MINISEARCH_OPTIONS: Options<SearchDocument> = {\n fields: ['title', 'content'],\n storeFields: ['type', 'typeLabel', 'title', 'url', 'snippet'],\n searchOptions: {\n boost: { title: 2 },\n prefix: true,\n fuzzy: 0.2,\n },\n};\n\n// --- Public functions ---\n\n/**\n * Build the admin entry-editor href for a search hit. The hit's `id` is the\n * MiniSearch document id, encoded as `<type>/<filename-stem>` by\n * `entryToDocument`. The admin route at `/cms/content/<type>/<filename-stem>`\n * matches the per-segment route file at\n * `src/app/cms/content/[type]/[id]/page.tsx`.\n *\n * Use this for click navigation in admin search surfaces (full-page,\n * `CommandK` palette). For public-collection links, use `result.url`.\n */\nexport function entryAdminHref(result: { id: string }): string {\n const [type, ...rest] = result.id.split('/');\n const id = rest.join('/');\n return `/cms/content/${type}/${id}`;\n}\n\n/** Return searchable field names for a collection based on format + searchable flag. */\nexport function getSearchableFields(collectionName: string, config: Config): string[] {\n const col = config.collections[collectionName as keyof typeof config.collections];\n if (!col) return [];\n\n return Object.entries(col.fields)\n .filter(([, field]) => isFieldSearchable(field))\n .map(([key]) => key);\n}\n\n/** Strip MDX/HTML tags from richtext/markdown content, leaving only searchable plain text. */\nexport function stripMarkup(content: string): string {\n return (\n content\n // Remove import/export statements (MDX)\n .replace(/^(import|export)\\s.+$/gm, '')\n // Remove HTML/JSX tags\n .replace(/<[^>]+>/g, '')\n // Remove markdown images \n .replace(/!\\[[^\\]]*\\]\\([^)]*\\)/g, '')\n // Convert markdown links [text](url) → text\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n // Remove heading markers\n .replace(/^#{1,6}\\s+/gm, '')\n // Remove bold/italic markers\n .replace(/(\\*{1,3}|_{1,3})(.+?)\\1/g, '$2')\n // Remove fenced code block markers (but keep content)\n .replace(/^```\\w*$/gm, '')\n // Remove inline code backticks\n .replace(/`([^`]+)`/g, '$1')\n // Remove horizontal rules\n .replace(/^[-*_]{3,}$/gm, '')\n // Remove blockquote markers\n .replace(/^>\\s?/gm, '')\n // Collapse multiple newlines / whitespace\n .replace(/\\n{2,}/g, '\\n')\n .replace(/\\s+/g, ' ')\n .trim()\n );\n}\n\n/**\n * Resolve a URL pattern by substituting `:fieldName` placeholders with entry field values.\n * `:id` is special — uses `entry.content.sys.id`.\n * Returns null if a referenced field is empty/missing.\n */\nexport function resolveUrlPattern(pattern: string, entry: EntryForSearch, entryId: string): string | null {\n const placeholders = pattern.match(/:(\\w+)/g);\n if (!placeholders) return pattern;\n\n let resolved = pattern;\n const fields = (entry.content as { fields?: Record<string, unknown> }).fields ?? {};\n\n for (const placeholder of placeholders) {\n const fieldName = placeholder.slice(1); // strip leading ':'\n let value: string | undefined;\n\n if (fieldName === 'id') {\n value = entryId;\n } else {\n const raw = fields[fieldName];\n value = typeof raw === 'string' && raw.length > 0 ? raw : undefined;\n }\n\n if (!value) return null;\n resolved = resolved.replace(placeholder, value);\n }\n\n return resolved;\n}\n\n/** Build a MiniSearch index from entries and serialize to JSON string. */\nexport function buildSearchIndex(\n entries: EntryForSearch[],\n config: Config,\n /** Only index entries from these collections. undefined = all. */\n collections?: string[],\n): string {\n const miniSearch = new MiniSearch<SearchDocument>(MINISEARCH_OPTIONS);\n\n const publicCollections = config.search?.publicCollections;\n\n for (const entry of entries) {\n const doc = entryToDocument(entry, config, collections, publicCollections);\n if (doc) miniSearch.add(doc);\n }\n\n return JSON.stringify(miniSearch);\n}\n\n/** Load a serialized index and run a query. */\nexport function querySearchIndex(serializedIndex: string, query: string, limit = 50): SearchResult[] {\n if (!query.trim()) return [];\n\n const miniSearch = MiniSearch.loadJSON<SearchDocument>(serializedIndex, MINISEARCH_OPTIONS);\n const results = miniSearch.search(query, MINISEARCH_OPTIONS.searchOptions);\n\n return results.slice(0, limit).map((r) => ({\n type: r.type,\n typeLabel: r.typeLabel,\n id: r.id,\n title: r.title,\n score: r.score,\n match: r.match,\n url: r.url,\n snippet: (r.snippet as string | undefined) ?? '',\n }));\n}\n\n// --- Internal helpers ---\n\nfunction isFieldSearchable(field: CollectionField): boolean {\n if (field.searchable === false) return false;\n if (field.searchable === true) return true;\n return SEARCHABLE_BY_DEFAULT.has(field.format);\n}\n\nfunction parseEntryPath(path: string): { type: string; id: string } | null {\n // path like \"post/post-abc123.json\"\n const parts = path.split('/');\n if (parts.length < 2) return null;\n const type = parts[parts.length - 2];\n const fileName = parts[parts.length - 1];\n const id = fileName.replace(/\\.json$/, '');\n return { type, id };\n}\n\n/** Extract a snippet from content, truncating to maxLength and word boundary. */\nfunction extractSnippet(text: string, maxLength = 200): string {\n if (text.length <= maxLength) return text;\n const truncated = text.slice(0, maxLength);\n const lastSpace = truncated.lastIndexOf(' ');\n return (lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated) + '\\u2026';\n}\n\nfunction entryToDocument(\n entry: EntryForSearch,\n config: Config,\n allowedCollections: string[] | undefined,\n publicCollections: Record<string, PublicCollectionSearchConfig> | undefined,\n): SearchDocument | null {\n const parsed = parseEntryPath(entry.path);\n if (!parsed) return null;\n\n const { type, id } = parsed;\n\n if (allowedCollections && !allowedCollections.includes(type)) return null;\n\n const col = config.collections[type as keyof typeof config.collections];\n if (!col) return null;\n\n const searchableFields = getSearchableFields(type, config);\n const fields = (entry.content as { fields?: Record<string, unknown> }).fields ?? {};\n\n // Build title from the entryTitle field\n const titleFieldKey = Object.entries(col.fields).find(([, f]) => f.entryTitle)?.[0];\n const title = titleFieldKey && typeof fields[titleFieldKey] === 'string' ? (fields[titleFieldKey] as string) : id;\n\n // Build content from all searchable fields (excluding the title field to avoid double-indexing)\n const contentParts: string[] = [];\n for (const fieldName of searchableFields) {\n if (fieldName === titleFieldKey) continue;\n\n const fieldDef = col.fields[fieldName];\n if (!fieldDef) continue;\n\n if (fieldDef.format === 'markdown' || fieldDef.format === 'richtext') {\n const companion = entry.companionContent[fieldName];\n if (companion) contentParts.push(stripMarkup(companion));\n } else if (fieldDef.format === 'select') {\n const raw = fields[fieldName];\n if (typeof raw === 'string') {\n const selectField = fieldDef as Extract<CollectionField, { format: 'select' }>;\n const option = selectField.options.find((o) => o.value === raw);\n contentParts.push(option?.label ?? raw);\n } else if (Array.isArray(raw)) {\n const selectField = fieldDef as Extract<CollectionField, { format: 'select' }>;\n for (const v of raw) {\n if (typeof v === 'string') {\n const option = selectField.options.find((o) => o.value === v);\n contentParts.push(option?.label ?? v);\n }\n }\n }\n } else {\n const raw = fields[fieldName];\n if (typeof raw === 'string') contentParts.push(raw);\n else if (Array.isArray(raw)) contentParts.push(raw.filter((v) => typeof v === 'string').join(' '));\n }\n }\n\n // Resolve URL for public search. Admin search must include every entry, so\n // a missing pattern field leaves `url` empty rather than dropping the entry.\n // Public consumers filter on `url !== ''` to skip unresolvable entries.\n let url = '';\n if (publicCollections && type in publicCollections) {\n const urlConfig = publicCollections[type];\n const resolved = resolveUrlPattern(urlConfig.urlPattern, entry, id);\n if (resolved !== null) url = resolved;\n }\n\n const contentText = contentParts.join(' ');\n return {\n id: `${type}/${id}`,\n type,\n typeLabel: col.label,\n title,\n content: contentText,\n snippet: extractSnippet(contentText),\n url,\n };\n}\n","/**\n * Bulk-fetch all CMS content for a branch using the Git Trees API.\n *\n * Replaces N+1 sequential `repos.getContent` calls with:\n * 1 × `git.getTree({ recursive: 1 })` → all paths + blob SHAs\n * N × `git.getBlob(sha)` → parallel, chunked (PARALLEL_BLOB_LIMIT)\n *\n * Falls back to the existing per-file REST approach on failure.\n */\n\nimport { Octokit } from 'octokit';\n\nimport { getConfig } from '../../lib/configStore';\nimport { companionMarkdownPathsForEntry, companionRichTextPathsForEntry } from '../../lib/companionMarkdown';\nimport { logCmsServerError } from '../../lib/cmsServerLog';\nimport { isMediaEntryPath, mediaContentFolder } from '../../lib/mediaPath';\n\nimport type { BranchStoreData, StoredEntry } from './contentStoreTypes';\n\n/** Maximum concurrent blob fetches. GitHub allows bursts but we stay conservative. */\nconst PARALLEL_BLOB_LIMIT = 20;\n\ntype TreeItem = {\n path?: string;\n mode?: string;\n type?: string;\n sha?: string;\n size?: number;\n};\n\n/** Returns true for CMS-managed files: editorial content under `contentFolder` (`.json`/`.md`/`.mdx`)\n * or media-entry JSONs under `mediaContentFolder`. */\nfunction isCmsContentFile(filePath: string): boolean {\n const config = getConfig();\n if (\n filePath.startsWith(`${config.contentFolder}/`) &&\n (filePath.endsWith('.json') || filePath.endsWith('.md') || filePath.endsWith('.mdx'))\n ) {\n return true;\n }\n return filePath.startsWith(`${mediaContentFolder()}/`) && filePath.endsWith('.json');\n}\n\n/** Extract collection name from a content path like \"cms/content/post/post-123.json\".\n * Returns null for media-entry paths (they have no collection). */\nfunction collectionFromPath(filePath: string): string | null {\n const config = getConfig();\n if (!filePath.startsWith(`${config.contentFolder}/`)) return null;\n const relative = filePath.slice(config.contentFolder.length + 1); // \"post/post-123.json\"\n const slashIdx = relative.indexOf('/');\n return slashIdx > 0 ? relative.slice(0, slashIdx) : null;\n}\n\n/** Fetch blob content from GitHub, returning the decoded UTF-8 string. */\nasync function fetchBlobContent(octokit: Octokit, owner: string, repo: string, sha: string): Promise<string> {\n const { data } = await octokit.rest.git.getBlob({ owner, repo, file_sha: sha });\n return Buffer.from(data.content, 'base64').toString('utf-8');\n}\n\n/** Process fetched items in parallel with a concurrency limit. */\nasync function parallelMap<T, R>(items: T[], limit: number, fn: (item: T) => Promise<R>): Promise<R[]> {\n const results: R[] = [];\n let index = 0;\n\n async function next(): Promise<void> {\n while (index < items.length) {\n const current = index++;\n results[current] = await fn(items[current]);\n }\n }\n\n const workers = Array.from({ length: Math.min(limit, items.length) }, () => next());\n await Promise.all(workers);\n return results;\n}\n\n/**\n * Fetch all CMS content for a branch using the Git Trees API.\n *\n * @param octokit Authenticated Octokit client (session or CMS_GITHUB_TOKEN)\n * @param owner Repository owner\n * @param repo Repository name\n * @param branch Git ref (branch name)\n * @returns Fully populated BranchStoreData or null if the tree fetch fails\n */\nexport async function fetchBranchContent(\n octokit: Octokit,\n owner: string,\n repo: string,\n branch: string,\n): Promise<BranchStoreData | null> {\n const config = getConfig();\n // Step 1: Get the full recursive tree in one API call\n let treeSha: string;\n let treeItems: TreeItem[];\n\n try {\n const { data } = await octokit.rest.git.getTree({\n owner,\n repo,\n tree_sha: branch,\n recursive: '1',\n });\n treeSha = data.sha;\n treeItems = data.tree;\n\n if (data.truncated) {\n logCmsServerError({\n operation: 'contentStore.fetchTree',\n branch,\n message: 'Git tree was truncated — repo may have too many files. Store may be incomplete.',\n });\n }\n } catch (error) {\n logCmsServerError({\n operation: 'contentStore.fetchTree',\n branch,\n message: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n\n // Step 2: Filter to CMS content files (json + md under contentFolder)\n const cmsItems = treeItems.filter(\n (item): item is TreeItem & { path: string; sha: string } =>\n item.type === 'blob' &&\n typeof item.path === 'string' &&\n typeof item.sha === 'string' &&\n isCmsContentFile(item.path),\n );\n\n if (cmsItems.length === 0) {\n return {\n branch,\n treeSha,\n entries: new Map(),\n byCollection: new Map(),\n mediaEntries: new Map(),\n populatedAt: Date.now(),\n version: 0,\n searchIndex: null,\n searchIndexVersion: -1,\n };\n }\n\n // Build a SHA→path index for deduplication (same blob content shared across files is rare but possible)\n const jsonItems = cmsItems.filter((item) => item.path.endsWith('.json'));\n const mdItems = cmsItems.filter((item) => item.path.endsWith('.md') || item.path.endsWith('.mdx'));\n\n // Step 3: Fetch all blob contents in parallel chunks\n const jsonContents = await parallelMap(jsonItems, PARALLEL_BLOB_LIMIT, async (item) => {\n try {\n const content = await fetchBlobContent(octokit, owner, repo, item.sha);\n return { path: item.path, sha: item.sha, content };\n } catch {\n return { path: item.path, sha: item.sha, content: null };\n }\n });\n\n const mdContents = await parallelMap(mdItems, PARALLEL_BLOB_LIMIT, async (item) => {\n try {\n const content = await fetchBlobContent(octokit, owner, repo, item.sha);\n return { path: item.path, content };\n } catch {\n return { path: item.path, content: null };\n }\n });\n\n // Index markdown contents by path for fast lookup\n const mdByPath = new Map<string, string>();\n for (const md of mdContents) {\n if (md.content !== null) {\n mdByPath.set(md.path, md.content);\n }\n }\n\n // Step 4: Parse JSON, pair companion markdown, build indexed Maps\n const entries = new Map<string, StoredEntry>();\n const byCollection = new Map<string, string[]>();\n const mediaEntries = new Map<string, StoredEntry>();\n\n for (const item of jsonContents) {\n if (item.content === null) continue;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(item.content) as Record<string, unknown>;\n } catch {\n continue; // Skip malformed JSON\n }\n\n const collectionType =\n typeof (parsed as { sys?: { type?: unknown } }).sys?.type === 'string'\n ? (parsed as { sys: { type: string } }).sys.type\n : null;\n\n // Merge companion markdown and richtext files\n const companions: Record<string, string> = {};\n if (collectionType) {\n const mdPaths = companionMarkdownPathsForEntry(item.path, collectionType, config.collections);\n for (const [fieldName, mdPath] of Object.entries(mdPaths)) {\n companions[fieldName] = mdByPath.get(mdPath) ?? '';\n }\n const rtPaths = companionRichTextPathsForEntry(item.path, collectionType, config.collections);\n for (const [fieldName, rtPath] of Object.entries(rtPaths)) {\n companions[fieldName] = mdByPath.get(rtPath) ?? '';\n }\n }\n\n const stored: StoredEntry = {\n path: item.path,\n content: parsed,\n sha: item.sha,\n companionMarkdown: companions,\n };\n\n if (isMediaEntryPath(item.path)) {\n mediaEntries.set(item.path, stored);\n continue;\n }\n\n entries.set(item.path, stored);\n\n // Index by collection\n const collection = collectionFromPath(item.path);\n if (collection) {\n const list = byCollection.get(collection);\n if (list) {\n list.push(item.path);\n } else {\n byCollection.set(collection, [item.path]);\n }\n }\n }\n\n return {\n branch,\n treeSha,\n entries,\n byCollection,\n mediaEntries,\n populatedAt: Date.now(),\n version: 0,\n searchIndex: null,\n searchIndexVersion: -1,\n };\n}\n","/**\n * In-memory content store for the CMS admin UI.\n *\n * Module-level state persists across requests within the same warm serverless\n * instance (Vercel, Cloudflare, Node.js). A CMS admin session involves many\n * rapid clicks, so a warm store covers the entire interactive session.\n *\n * Read operations return cached data instantly; writes go to GitHub first\n * (source of truth) then update the store via applyMutation().\n */\n\nimport { getConfig } from '../../lib/configStore';\nimport { logCmsServerError } from '../../lib/cmsServerLog';\nimport { isMediaEntryPath } from '../../lib/mediaPath';\nimport { buildSearchIndex, type EntryForSearch } from '../../lib/searchIndex';\n\nimport { assertGitHubConfig, getPublicOctokits } from '../github';\nimport { fetchBranchContent } from './contentStoreFetch';\nimport type { BranchStoreData, StoredEntry, StoreMutation } from './contentStoreTypes';\n\n// ---------------------------------------------------------------------------\n// TTL configuration\n// ---------------------------------------------------------------------------\n\n/** Serve directly from cache without any background refresh. */\nconst FRESH_TTL_MS = 30_000; // 30 seconds\n\n/** Serve stale data while triggering a background refresh. */\nconst STALE_TTL_MS = 300_000; // 5 minutes\n\n// ---------------------------------------------------------------------------\n// Module-level state (persists across requests in a warm serverless instance)\n// ---------------------------------------------------------------------------\n\n/** Branch name → cached store data. */\nconst stores = new Map<string, BranchStoreData>();\n\n/** Branch name → in-flight fetch promise (deduplication). */\nconst inflight = new Map<string, Promise<BranchStoreData | null>>();\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction age(store: BranchStoreData): number {\n return Date.now() - store.populatedAt;\n}\n\nfunction isFresh(store: BranchStoreData): boolean {\n return age(store) < FRESH_TTL_MS;\n}\n\nfunction isStale(store: BranchStoreData): boolean {\n return age(store) < STALE_TTL_MS;\n}\n\n/** Default branch from cookie or config. */\nfunction resolveBranch(branch: string | undefined): string {\n return branch || getConfig().git.baseBranch;\n}\n\n/**\n * Deduplicated fetch: if another call for the same branch is already in flight,\n * reuse that promise instead of firing a second GitHub request.\n */\nfunction deduplicatedFetch(branch: string): Promise<BranchStoreData | null> {\n const existing = inflight.get(branch);\n if (existing) return existing;\n\n const promise = doFetch(branch).finally(() => {\n inflight.delete(branch);\n });\n\n inflight.set(branch, promise);\n return promise;\n}\n\nasync function doFetch(branch: string): Promise<BranchStoreData | null> {\n const { owner, repo } = assertGitHubConfig();\n const [octokit] = getPublicOctokits();\n\n if (!octokit) {\n logCmsServerError({\n operation: 'contentStore.fetch',\n branch,\n message: 'No Octokit client available for store fetch',\n });\n return null;\n }\n\n const result = await fetchBranchContent(octokit, owner, repo, branch);\n\n if (result) {\n stores.set(branch, result);\n }\n\n return result;\n}\n\n/**\n * Get or populate the store for a branch. Implements the three-tier strategy:\n * - Cache hit + fresh → return immediately\n * - Cache hit + stale → return stale, trigger background refresh\n * - Cache miss / expired → block on fetch\n */\nasync function ensureStore(branch: string): Promise<BranchStoreData | null> {\n const cached = stores.get(branch);\n\n if (cached && isFresh(cached)) {\n return cached;\n }\n\n if (cached && isStale(cached)) {\n // Return stale data immediately, refresh in background\n deduplicatedFetch(branch).catch(() => {\n /* background refresh — errors logged inside doFetch */\n });\n return cached;\n }\n\n // Cold start or expired — block on fetch\n return deduplicatedFetch(branch);\n}\n\n// ---------------------------------------------------------------------------\n// Collection path helpers\n// ---------------------------------------------------------------------------\n\nfunction collectionFromPath(filePath: string): string | null {\n const config = getConfig();\n const prefix = `${config.contentFolder}/`;\n if (!filePath.startsWith(prefix)) return null;\n const relative = filePath.slice(prefix.length);\n const slashIdx = relative.indexOf('/');\n return slashIdx > 0 ? relative.slice(0, slashIdx) : null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API — Read operations\n// ---------------------------------------------------------------------------\n\n/**\n * Get a single file from the store. Returns the StoredEntry with pre-parsed\n * content and companion markdown already merged, or null if not found.\n *\n * Looks in both editorial entries and media entries (the store keeps them in\n * separate maps; consumers shouldn't have to know which).\n */\nexport async function getStoredFile(filePath: string, branch?: string): Promise<StoredEntry | null> {\n const resolved = resolveBranch(branch);\n const store = await ensureStore(resolved);\n if (!store) return null;\n return store.entries.get(filePath) ?? store.mediaEntries.get(filePath) ?? null;\n}\n\n/**\n * Get all content file paths for a collection (or all collections if '**').\n * Returns an array of normalized file paths.\n */\nexport async function getStoredContentFiles(collection: string, branch?: string): Promise<string[] | null> {\n const resolved = resolveBranch(branch);\n const store = await ensureStore(resolved);\n if (!store) return null;\n\n if (collection === '**') {\n // Return all editorial entry paths. Media lives in `mediaEntries` and is\n // not included by `getContentFiles('**')` callers.\n const all: string[] = [];\n for (const [path] of store.entries) {\n if (path.endsWith('.json')) {\n all.push(path);\n }\n }\n return all;\n }\n\n return store.byCollection.get(collection)?.slice() ?? [];\n}\n\n/**\n * Get all media entries from the store.\n */\nexport async function getStoredMediaEntries(branch?: string): Promise<Map<string, StoredEntry> | null> {\n const resolved = resolveBranch(branch);\n const store = await ensureStore(resolved);\n if (!store) return null;\n return store.mediaEntries;\n}\n\n/**\n * Get the cached SHA for a file path (used to skip the pre-read on save).\n * Returns null if the file is not in the store.\n */\nexport async function getStoredFileSha(filePath: string, branch?: string): Promise<string | null> {\n const resolved = resolveBranch(branch);\n const store = await ensureStore(resolved);\n if (!store) return null;\n return (store.entries.get(filePath) ?? store.mediaEntries.get(filePath))?.sha ?? null;\n}\n\n// ---------------------------------------------------------------------------\n// Public API — Search index\n// ---------------------------------------------------------------------------\n\n/**\n * Get or lazily build the serialized MiniSearch index for admin search.\n * Rebuilds only when the store version has changed since the last build.\n */\nexport async function getOrBuildSearchIndex(branch?: string): Promise<string | null> {\n const config = getConfig();\n const resolved = resolveBranch(branch);\n const store = await ensureStore(resolved);\n if (!store) return null;\n\n if (store.searchIndex !== null && store.searchIndexVersion === store.version) {\n return store.searchIndex;\n }\n\n // Build from current entries — `store.entries` is editorial-only (media\n // lives in `store.mediaEntries`), so no per-path filter is needed.\n const entries: EntryForSearch[] = [];\n for (const [path, stored] of store.entries) {\n entries.push({\n path: path.replace(`${config.contentFolder}/`, ''),\n content: stored.content,\n companionContent: stored.companionMarkdown as Record<string, string>,\n });\n }\n\n const serialized = buildSearchIndex(entries, config);\n store.searchIndex = serialized;\n store.searchIndexVersion = store.version;\n return serialized;\n}\n\n// ---------------------------------------------------------------------------\n// Public API — Write-through mutations\n// ---------------------------------------------------------------------------\n\n/**\n * Apply a write-through mutation to the in-memory store after a successful\n * GitHub write. This keeps the store consistent without a full re-fetch.\n */\nexport function applyMutation(branch: string, mutation: StoreMutation): void {\n const store = stores.get(branch);\n if (!store) return; // Store not populated yet — next read will fetch fresh data\n\n if (mutation.type === 'upsert') {\n const isMedia = isMediaEntryPath(mutation.path);\n const existing = isMedia ? store.mediaEntries.get(mutation.path) : store.entries.get(mutation.path);\n const entry: StoredEntry = {\n path: mutation.path,\n content: mutation.content,\n sha: mutation.sha,\n companionMarkdown: mutation.companions ? { ...mutation.companions } : (existing?.companionMarkdown ?? {}),\n };\n\n if (isMedia) {\n store.mediaEntries.set(mutation.path, entry);\n } else {\n store.entries.set(mutation.path, entry);\n\n // Update collection index\n const collection = collectionFromPath(mutation.path);\n if (collection) {\n const list = store.byCollection.get(collection);\n if (list) {\n if (!list.includes(mutation.path)) {\n list.push(mutation.path);\n }\n } else {\n store.byCollection.set(collection, [mutation.path]);\n }\n }\n }\n } else {\n // delete\n if (isMediaEntryPath(mutation.path)) {\n store.mediaEntries.delete(mutation.path);\n } else {\n store.entries.delete(mutation.path);\n\n const collection = collectionFromPath(mutation.path);\n if (collection) {\n const list = store.byCollection.get(collection);\n if (list) {\n const idx = list.indexOf(mutation.path);\n if (idx >= 0) list.splice(idx, 1);\n }\n }\n }\n }\n\n store.version++;\n}\n\n// ---------------------------------------------------------------------------\n// Public API — Lifecycle\n// ---------------------------------------------------------------------------\n\n/**\n * Invalidate the store for a branch, forcing a fresh fetch on the next read.\n */\nexport function invalidateBranch(branch: string): void {\n stores.delete(branch);\n inflight.delete(branch);\n}\n\n/**\n * Pre-populate the store for a branch (e.g. after switching branches).\n * Non-blocking — returns a promise that resolves when the store is warm.\n */\nexport async function warmBranch(branch: string): Promise<void> {\n await deduplicatedFetch(branch);\n}\n\n/**\n * Check whether the store has data for a branch (for testing / diagnostics).\n */\nexport function hasStore(branch: string): boolean {\n return stores.has(branch);\n}\n\n/**\n * Get the current store data for a branch (for testing / diagnostics).\n * Returns undefined if no data is cached.\n */\nexport function getStoreSnapshot(branch: string): BranchStoreData | undefined {\n return stores.get(branch);\n}\n\n/**\n * Clear all stores (for testing).\n */\nexport function clearAllStores(): void {\n stores.clear();\n inflight.clear();\n}\n","/**\n * Canonical Next.js cache tag for public readers that load OctoCMS content under\n * `\"use cache\"`. After saves, `buildJsons()` calls `updateTag` with this value.\n *\n * Use `cacheTag(OCTOCMS_PUBLIC_CONTENT_CACHE_TAG)` in your cached loaders so they\n * all refresh together. Webhooks may call `GET /api/revalidate/<this-string>`.\n */\nexport const OCTOCMS_PUBLIC_CONTENT_CACHE_TAG = 'octocms:content';\n","import { getConfig } from '../../lib/configStore';\nimport type { Config } from '../types';\n\nexport const getErrorMessage = (error: unknown): string => {\n if (error instanceof Error) {\n return error.message;\n }\n\n return String(error);\n};\n\n/** Standard result for CMS server actions — use for user-facing feedback (toast). */\nexport type ActionResult = { success: true } | { success: false; error: string };\n\n/** `saveFile` may attach per-field errors (e.g. duplicate slug). */\nexport type SaveFileResult =\n | { success: true }\n | { success: false; error: string; fieldErrors?: Record<string, string> };\n\nexport const actionOk = (): { success: true } => ({ success: true });\n\nexport const actionErr = (error: unknown): { success: false; error: string } => ({\n success: false,\n error: getErrorMessage(error),\n});\n\nexport type NewFileResult = { success: true; path: string } | { success: false; error: string };\n\nexport type UploadMediaResult = { success: true; id: string } | { success: false; error: string };\n\nexport type CreatePRResult = { success: true; url: string; number: number } | { success: false; error: string };\n\nexport type CreateBranchInput = {\n branchName: string;\n title: string;\n description?: string;\n};\n\n/** After a successful branch + metadata commit; `prUrl` may be empty if opening the draft PR failed. */\nexport type CreateBranchResult =\n | { success: true; prUrl: string; prWarning?: string }\n | { success: false; error: string };\n\nexport const getEntryTitleField = (collectionName: string): string | undefined => {\n const config = getConfig();\n const collection = config.collections[collectionName as keyof Config['collections']];\n\n if (!collection) return undefined;\n\n return Object.keys(collection.fields).find((key) => collection.fields[key].entryTitle);\n};\n","'use server';\n\nimport './registerConfig';\n\nimport { revalidatePath, revalidateTag, updateTag } from 'next/cache';\n\nimport { OCTOCMS_PUBLIC_CONTENT_CACHE_TAG } from '../../lib/publicContentCacheTag';\n\nimport { actionErr, actionOk, type ActionResult } from './utils';\n\n/**\n * Invalidate public caches after content writes: one shared `\"use cache\"` tag for\n * all OctoCMS-driven public reads, plus root layout revalidation so App Router pages\n * under `/` pick up fresh RSC payloads without per-route config.\n *\n * Public site search (`GET /api/search`) is separate — built on demand from Git.\n */\nexport const buildJsons = async (_editedFileName?: string): Promise<ActionResult> => {\n try {\n try {\n updateTag(OCTOCMS_PUBLIC_CONTENT_CACHE_TAG);\n } catch {\n revalidateTag(OCTOCMS_PUBLIC_CONTENT_CACHE_TAG, { expire: 0 });\n }\n\n revalidatePath('/', 'layout');\n\n return actionOk();\n } catch (e) {\n return actionErr(e);\n }\n};\n","'use server';\n\nimport './registerConfig';\n\nimport fsPromises from 'fs/promises';\nimport path from 'path';\n\nimport { cookies } from 'next/headers';\n\nimport { getConfig } from '../../lib/configStore';\nimport { listLocalCollectionFiles, listLocalFilesRecursive, listLocalFilesWithExtensions } from '../../lib/localReader';\nimport { getAgentConfig } from '../../agent/configStore';\nimport { syncEmbeddingsAfterRemove, syncEmbeddingsAfterUpsert } from '../../agent/embeddingsHook';\nimport { BRANCH_HISTORY_FILE_PATH, mergeHistoryContentWithAppendedEntry } from '../../lib/branchHistory';\nimport { companionMarkdownPathsForEntry, companionRichTextPathsForEntry } from '../../lib/companionMarkdown';\nimport { initialFieldsForNewEntry } from '../../lib/initialEntryFields';\nimport { persistedFieldsFromFormStrings } from '../../lib/persistedFormFields';\nimport { normalizeStoredSlug } from '../../lib/slugField';\nimport { validateEntryFields } from '../../lib/validateEntryFields';\nimport type { Config } from '../types';\n\nimport {\n deleteGitHubFile,\n getGitHubFile,\n isProductionMode,\n listGitHubFiles,\n listGitHubFilesRecursive,\n readGitHubFilePublic,\n saveGitHubFile,\n} from '../github';\nimport { applyMutation, getStoredContentFiles, getStoredFile, getStoredFileSha } from '../store/contentStore';\nimport { mediaContentFolder, mediaEntryPath } from '../../lib/mediaPath';\nimport { buildJsons } from './build';\nimport {\n actionErr,\n actionOk,\n getErrorMessage,\n type ActionResult,\n type NewFileResult,\n type SaveFileResult,\n} from './utils';\n\nexport type { SaveFileResult } from './utils';\n\nconst CMS_ACTIVE_BRANCH_COOKIE = 'cms-active-branch';\n\nfunction normalizeContentPath(p: string): string {\n return p.replace(/\\\\/g, '/');\n}\n\n/** Best-effort embedding store sync after content writes. No-op when the agent isn't configured. */\nasync function syncEmbeddingsForUpsertIfEnabled(\n entryPath: string,\n payload: { sys?: { type?: string }; fields?: Record<string, unknown> },\n companions: Record<string, string>,\n branch: string | undefined,\n isProduction: boolean,\n): Promise<void> {\n const agentConfig = getAgentConfig();\n if (!agentConfig) return;\n const config = getConfig();\n await syncEmbeddingsAfterUpsert({ agentConfig, config, entryPath, payload, companions, branch, isProduction });\n}\n\nasync function syncEmbeddingsForRemoveIfEnabled(\n entryPath: string,\n branch: string | undefined,\n isProduction: boolean,\n): Promise<void> {\n const agentConfig = getAgentConfig();\n if (!agentConfig) return;\n await syncEmbeddingsAfterRemove({ agentConfig, entryPath, branch, isProduction });\n}\n\n/** Records the entry path under the active branch in `cms/branch-history.json` (GitHub or local). Best-effort. */\nasync function persistBranchHistoryEntryIfNeeded(activeBranch: string | undefined, entryPath: string): Promise<void> {\n if (!activeBranch) {\n return;\n }\n\n const normalized = normalizeContentPath(entryPath);\n\n if (isProductionMode()) {\n try {\n const historyFile = await getGitHubFile(BRANCH_HISTORY_FILE_PATH, activeBranch);\n const next = mergeHistoryContentWithAppendedEntry(historyFile?.content ?? '', activeBranch, normalized);\n if (next == null) {\n return;\n }\n\n await saveGitHubFile(BRANCH_HISTORY_FILE_PATH, next, 'CMS: track entry in branch history', activeBranch);\n } catch {\n /* best-effort sidecar — primary save must still succeed */\n }\n\n return;\n }\n\n try {\n const abs = path.join(/*turbopackIgnore: true*/ process.cwd(), BRANCH_HISTORY_FILE_PATH);\n let raw = '';\n try {\n raw = await fsPromises.readFile(abs, { encoding: 'utf8' });\n } catch {\n raw = '';\n }\n\n const next = mergeHistoryContentWithAppendedEntry(raw, activeBranch, normalized);\n if (next == null) {\n return;\n }\n\n await fsPromises.mkdir(path.dirname(abs), { recursive: true });\n await fsPromises.writeFile(abs, next, 'utf8');\n } catch {\n /* best-effort sidecar */\n }\n}\n\nasync function assertSlugFieldsUnique(\n entryType: string,\n fileName: string,\n persistedFields: Record<string, unknown>,\n): Promise<{ ok: true } | { ok: false; fieldKey: string; message: string }> {\n const config = getConfig();\n const col = config.collections[entryType as keyof Config['collections']];\n if (!col) {\n return { ok: true };\n }\n\n const slugFieldEntries = Object.entries(col.fields).filter(([, def]) => def.format === 'slug');\n if (slugFieldEntries.length === 0) {\n return { ok: true };\n }\n\n const selfPath = normalizeContentPath(fileName);\n const siblings = await getContentFiles(entryType);\n if (!Array.isArray(siblings)) {\n return { ok: true };\n }\n\n for (const [slugKey] of slugFieldEntries) {\n const candidate = persistedFields[slugKey];\n if (typeof candidate !== 'string' || !candidate.trim()) {\n continue;\n }\n const normCandidate = normalizeStoredSlug(candidate);\n if (!normCandidate) {\n continue;\n }\n\n for (const siblingPath of siblings) {\n if (normalizeContentPath(siblingPath) === selfPath) {\n continue;\n }\n let data: unknown;\n try {\n data = await getFile(siblingPath);\n } catch {\n continue;\n }\n if (!data || typeof data !== 'object') {\n continue;\n }\n const fields = (data as { fields?: Record<string, unknown> }).fields;\n if (!fields) {\n continue;\n }\n const other = fields[slugKey];\n if (typeof other !== 'string' || !other.trim()) {\n continue;\n }\n if (normalizeStoredSlug(other) === normCandidate) {\n return {\n ok: false,\n fieldKey: slugKey,\n message: `Another ${col.label} already uses this slug. Choose a different value.`,\n };\n }\n }\n }\n\n return { ok: true };\n}\n\nconst MEDIA_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\nasync function assertImageFieldsReferenceMediaWithTitle(\n entryType: string,\n strFields: Record<string, string>,\n): Promise<{ ok: true } | { ok: false; fieldKey: string; message: string }> {\n const config = getConfig();\n const col = config.collections[entryType as keyof Config['collections']];\n if (!col) {\n return { ok: true };\n }\n\n for (const [key, def] of Object.entries(col.fields)) {\n if (def.format !== 'image') {\n continue;\n }\n const raw = (strFields[key] ?? '').trim();\n if (!raw || raw.startsWith('/')) {\n continue;\n }\n if (!MEDIA_UUID_RE.test(raw)) {\n continue;\n }\n\n const mediaPath = mediaEntryPath(raw);\n let media: unknown;\n try {\n media = await getFile(mediaPath);\n } catch {\n return {\n ok: false,\n fieldKey: key,\n message: `Media not found for ${def.label}. Choose a valid image in the Media library.`,\n };\n }\n\n const title = (media as { fields?: { title?: unknown } })?.fields?.title;\n if (typeof title !== 'string' || !title.trim()) {\n return {\n ok: false,\n fieldKey: key,\n message: `Selected image is missing a required Title; fix it in the Media library.`,\n };\n }\n }\n\n return { ok: true };\n}\n\n/**\n * In production, reject writes that would target `config.git.baseBranch` (no feature branch cookie).\n */\nexport const assertFeatureBranchForWritesIfRequired = async (): Promise<void> => {\n if (!isProductionMode()) {\n return;\n }\n\n if (!(await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value) {\n throw new Error('Create or select a branch before editing.');\n }\n};\n\nexport const waitForPublicReadConsistency = async (fileName: string, expectedContent: string, readRef?: string) => {\n if (!isProductionMode()) {\n return;\n }\n\n const parsedAttempts = Number.parseInt(process.env.CMS_GITHUB_CONSISTENCY_ATTEMPTS || '8', 10);\n const parsedDelayMs = Number.parseInt(process.env.CMS_GITHUB_CONSISTENCY_DELAY_MS || '250', 10);\n const maxAttempts = Number.isFinite(parsedAttempts) && parsedAttempts > 0 ? parsedAttempts : 1;\n const delayMs = Number.isFinite(parsedDelayMs) && parsedDelayMs >= 0 ? parsedDelayMs : 250;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const visibleContent = await readGitHubFilePublic(fileName, readRef);\n\n if (visibleContent === expectedContent) {\n return;\n }\n } catch (_e) {\n // Ignore transient read failures and retry within the same save request.\n }\n\n if (attempt < maxAttempts && delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n};\n\nexport const getContentFiles = async (collection: string = '**') => {\n const config = getConfig();\n try {\n if (isProductionMode()) {\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n\n // Try in-memory store first (instant)\n try {\n const stored = await getStoredContentFiles(collection, activeBranch);\n if (stored) return stored;\n } catch {\n // Store unavailable — fall through to direct GitHub API\n }\n\n try {\n if (collection === '**') {\n const listed = await listGitHubFilesRecursive(config.contentFolder, '.json', activeBranch);\n return Array.isArray(listed) ? listed : [];\n }\n\n const listed = await listGitHubFiles(`${config.contentFolder}/${collection}`, '.json', activeBranch);\n return Array.isArray(listed) ? listed : [];\n } catch (e) {\n // Fall back to local files if GitHub API access is not available.\n }\n }\n\n if (collection === '**') {\n return await listLocalFilesRecursive(config.contentFolder, '.json');\n }\n return await listLocalCollectionFiles(`${config.contentFolder}/${collection}`);\n } catch (e) {\n return [];\n }\n};\n\n/**\n * List media-entry JSON files (e.g. `cms/media/media-<uuid>.json`).\n *\n * Distinct from `getContentFiles`, which lists editorial content under\n * `config.contentFolder`, and from `getMediaFiles`, which lists physical image\n * binaries under `config.mediaFolder`. This is the JSON-entry layer.\n */\nexport const getMediaContentFiles = async (): Promise<string[]> => {\n const folder = mediaContentFolder();\n try {\n if (isProductionMode()) {\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n\n try {\n return await listGitHubFiles(folder, '.json', activeBranch);\n } catch (_e) {\n // Fall back to local files if GitHub API access is not available.\n }\n }\n\n return await listLocalCollectionFiles(folder);\n } catch (_e) {\n return [];\n }\n};\n\nexport const getMediaFiles = async (folder: string = '**') => {\n const config = getConfig();\n try {\n if (isProductionMode()) {\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n\n try {\n const dir = folder === '**' ? config.mediaFolder : `${config.mediaFolder}/${folder}`;\n const allFiles = await listGitHubFilesRecursive(dir, undefined, activeBranch);\n const extensions = config.mediaAllowedFormats;\n return allFiles.filter((f) => extensions.some((ext) => f.endsWith(`.${ext}`)));\n } catch (e) {\n // Fall back to local files if GitHub API access is not available.\n }\n }\n\n const dir = folder === '**' ? config.mediaFolder : `${config.mediaFolder}/${folder}`;\n return await listLocalFilesWithExtensions(dir, config.mediaAllowedFormats, folder === '**');\n } catch (e) {\n return [];\n }\n};\n\n/**\n * Read only the raw entry JSON — no companion markdown/richtext merging.\n * Use for list views where companion content is never needed.\n */\nexport const getFileJson = async (fileName: string): Promise<Record<string, unknown> | null> => {\n if (isProductionMode()) {\n let activeBranch: string | undefined;\n try {\n activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n } catch {}\n\n try {\n const stored = await getStoredFile(fileName, activeBranch);\n if (stored) return structuredClone(stored.content);\n } catch {}\n\n try {\n const result = await getGitHubFile(fileName, activeBranch);\n if (result) return JSON.parse(result.content) as Record<string, unknown>;\n } catch {}\n\n try {\n const raw = await readGitHubFilePublic(fileName, activeBranch);\n if (raw) return JSON.parse(raw) as Record<string, unknown>;\n } catch {}\n\n return null;\n }\n\n try {\n const filePath = path.join(/*turbopackIgnore: true*/ process.cwd(), fileName);\n const data = await fsPromises.readFile(filePath, { encoding: 'utf8' });\n return JSON.parse(data) as Record<string, unknown>;\n } catch {\n return null;\n }\n};\n\nexport const getFile = async (fileName: string) => {\n const config = getConfig();\n try {\n let entry: any;\n\n if (isProductionMode()) {\n // Try in-memory store first (instant, includes pre-merged companions)\n try {\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n const stored = await getStoredFile(fileName, activeBranch);\n\n if (stored) {\n entry = structuredClone(stored.content);\n // Merge pre-cached companion markdown into fields\n if (entry.fields) {\n for (const [fieldName, mdContent] of Object.entries(stored.companionMarkdown)) {\n entry.fields[fieldName] = mdContent;\n }\n }\n return entry;\n }\n } catch {\n // Store unavailable — fall through to direct GitHub API\n }\n\n try {\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n const result = await getGitHubFile(fileName, activeBranch);\n\n if (result) {\n entry = JSON.parse(result.content);\n }\n } catch (e) {\n // Fall back to local file if GitHub API access is not available.\n }\n\n // Cold serverless instance: content store is empty. `getGitHubFile` may return null\n // (404 race) or throw before `readGitHubFilePublic`'s multi-client retry path runs.\n // Never fall through to `fs.readFile` on deploy — the repo is not on disk (ENOENT → 500).\n if (!entry) {\n try {\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n const raw = await readGitHubFilePublic(fileName, activeBranch);\n if (raw) {\n entry = JSON.parse(raw);\n }\n } catch {\n /* best-effort */\n }\n }\n }\n\n if (!entry) {\n if (isProductionMode()) {\n return {};\n }\n const filePath = path.join(/*turbopackIgnore: true*/ process.cwd(), fileName);\n const data = await fsPromises.readFile(filePath, { encoding: 'utf8' });\n entry = JSON.parse(data);\n }\n\n if (!entry) {\n return {};\n }\n\n // Merge companion markdown and richtext files into fields\n const collectionType = entry?.sys?.type;\n if (typeof collectionType === 'string' && entry.fields) {\n const companionPaths = companionMarkdownPathsForEntry(fileName, collectionType, config.collections);\n for (const [fieldName, mdPath] of Object.entries(companionPaths)) {\n entry.fields[fieldName] = await readCompanionMarkdownContent(mdPath);\n }\n const richTextPaths = companionRichTextPathsForEntry(fileName, collectionType, config.collections);\n for (const [fieldName, mdxPath] of Object.entries(richTextPaths)) {\n entry.fields[fieldName] = await readCompanionMarkdownContent(mdxPath);\n }\n }\n\n return entry;\n } catch (e) {\n throw new Error('Failed to get file');\n }\n};\n\n/** Read a companion markdown file as a string. Returns `\"\"` if the file does not exist. */\nasync function readCompanionMarkdownContent(filePath: string): Promise<string> {\n if (isProductionMode()) {\n try {\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n const result = await getGitHubFile(filePath, activeBranch);\n return result?.content ?? '';\n } catch {\n return '';\n }\n }\n\n try {\n return await fsPromises.readFile(path.join(/*turbopackIgnore: true*/ process.cwd(), filePath), {\n encoding: 'utf8',\n });\n } catch {\n return '';\n }\n}\n\nexport const saveFile = async (\n formData: any,\n fileName: string,\n options?: { skipStatusTransition?: boolean },\n): Promise<SaveFileResult> => {\n const config = getConfig();\n try {\n let payload = formData;\n const entryType = payload?.sys?.type;\n const rawFields = payload?.fields;\n if (typeof entryType === 'string' && rawFields && typeof rawFields === 'object' && !Array.isArray(rawFields)) {\n const strFields: Record<string, string> = {};\n for (const [k, v] of Object.entries(rawFields)) {\n if (v == null) {\n strFields[k] = '';\n } else if (typeof v === 'object') {\n strFields[k] = JSON.stringify(v);\n } else {\n strFields[k] = String(v);\n }\n }\n const validated = validateEntryFields(entryType, strFields);\n if (!validated.ok) {\n const first = Object.values(validated.fieldErrors)[0];\n return {\n success: false,\n error: first || 'Validation failed',\n fieldErrors: validated.fieldErrors,\n };\n }\n\n const mediaTitles = await assertImageFieldsReferenceMediaWithTitle(entryType, strFields);\n if (!mediaTitles.ok) {\n return {\n success: false,\n error: mediaTitles.message,\n fieldErrors: { [mediaTitles.fieldKey]: mediaTitles.message },\n };\n }\n\n payload = {\n ...payload,\n fields: persistedFieldsFromFormStrings(entryType, strFields),\n };\n\n const slugUnique = await assertSlugFieldsUnique(entryType, fileName, payload.fields);\n if (!slugUnique.ok) {\n return {\n success: false,\n error: slugUnique.message,\n fieldErrors: { [slugUnique.fieldKey]: slugUnique.message },\n };\n }\n }\n\n // New entries start as draft (hidden from `query()`). First successful save promotes to `changed`\n // so they become eligible for public pages once the workspace branch is published from the header.\n if (!options?.skipStatusTransition && payload?.sys?.status === 'draft') {\n payload = { ...payload, sys: { ...payload.sys, status: 'changed' } };\n }\n\n // Auto-transition published/merged → changed on regular save (not on explicit publish)\n if (!options?.skipStatusTransition && (payload?.sys?.status === 'published' || payload?.sys?.status === 'merged')) {\n payload = { ...payload, sys: { ...payload.sys, status: 'changed' } };\n }\n\n // Extract markdown and richtext fields into companion files, remove from JSON payload\n const markdownContents: Record<string, string> = {};\n if (typeof entryType === 'string' && payload.fields) {\n const companionPaths = companionMarkdownPathsForEntry(fileName, entryType, config.collections);\n for (const [fieldName] of Object.entries(companionPaths)) {\n markdownContents[fieldName] = payload.fields[fieldName] ?? '';\n delete payload.fields[fieldName];\n }\n const richTextPaths = companionRichTextPathsForEntry(fileName, entryType, config.collections);\n for (const [fieldName] of Object.entries(richTextPaths)) {\n markdownContents[fieldName] = payload.fields[fieldName] ?? '';\n delete payload.fields[fieldName];\n }\n }\n\n const data = JSON.stringify(payload, null, 2);\n const normalizedData = `${data}\\n`;\n\n if (isProductionMode()) {\n await assertFeatureBranchForWritesIfRequired();\n const entryTypeLabel = payload?.sys?.type || 'content';\n const entryId = payload?.sys?.id || '';\n const message = `Update ${entryTypeLabel} ${entryId}`;\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n\n // Use cached SHA from the store to skip the pre-read API call\n const cachedSha = (await getStoredFileSha(fileName, activeBranch)) || undefined;\n await saveGitHubFile(fileName, normalizedData, message, activeBranch, cachedSha);\n // Write companion markdown and richtext files\n const mdPaths =\n typeof entryType === 'string' ? companionMarkdownPathsForEntry(fileName, entryType, config.collections) : {};\n for (const [fieldName, mdPath] of Object.entries(mdPaths)) {\n const mdContent = markdownContents[fieldName] ?? '';\n await saveGitHubFile(mdPath, mdContent, `Update ${fieldName} for ${entryType} ${entryId}`, activeBranch);\n }\n const rtPaths =\n typeof entryType === 'string' ? companionRichTextPathsForEntry(fileName, entryType, config.collections) : {};\n for (const [fieldName, rtPath] of Object.entries(rtPaths)) {\n const rtContent = markdownContents[fieldName] ?? '';\n await saveGitHubFile(rtPath, rtContent, `Update ${fieldName} for ${entryType} ${entryId}`, activeBranch);\n }\n await waitForPublicReadConsistency(fileName, normalizedData);\n\n // Write-through: update in-memory store so subsequent reads are instant\n if (activeBranch) {\n applyMutation(activeBranch, {\n type: 'upsert',\n path: fileName,\n content: payload,\n sha: '', // SHA unknown after single-file commit; next tree fetch will correct it\n companions: markdownContents,\n });\n }\n\n await persistBranchHistoryEntryIfNeeded(activeBranch, fileName);\n await syncEmbeddingsForUpsertIfEnabled(fileName, payload, markdownContents, activeBranch, true);\n const built = await buildJsons(fileName);\n\n return built.success ? actionOk() : built;\n }\n\n const cookieStore = await cookies();\n const activeBranchDev = cookieStore.get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n const filePath = path.join(/*turbopackIgnore: true*/ process.cwd(), fileName);\n await fsPromises.writeFile(filePath, normalizedData, 'utf8');\n // Write companion markdown and richtext files\n const mdPaths =\n typeof entryType === 'string' ? companionMarkdownPathsForEntry(fileName, entryType, config.collections) : {};\n for (const [fieldName, mdPath] of Object.entries(mdPaths)) {\n const mdContent = markdownContents[fieldName] ?? '';\n await fsPromises.writeFile(path.join(/*turbopackIgnore: true*/ process.cwd(), mdPath), mdContent, 'utf8');\n }\n const rtPathsDev =\n typeof entryType === 'string' ? companionRichTextPathsForEntry(fileName, entryType, config.collections) : {};\n for (const [fieldName, rtPath] of Object.entries(rtPathsDev)) {\n const rtContent = markdownContents[fieldName] ?? '';\n await fsPromises.writeFile(path.join(/*turbopackIgnore: true*/ process.cwd(), rtPath), rtContent, 'utf8');\n }\n await persistBranchHistoryEntryIfNeeded(activeBranchDev, fileName);\n await syncEmbeddingsForUpsertIfEnabled(fileName, payload, markdownContents, activeBranchDev, false);\n const built = await buildJsons(fileName);\n\n return built.success ? actionOk() : built;\n } catch (e) {\n return actionErr(new Error(`Failed to save file: ${getErrorMessage(e)}`));\n }\n};\n\nexport const newFile = async (type: string): Promise<NewFileResult> => {\n const config = getConfig();\n try {\n const id = crypto.randomUUID();\n const values = {\n sys: {\n id,\n type,\n status: 'draft' as const,\n },\n fields: initialFieldsForNewEntry(type),\n };\n const data = JSON.stringify(values, null, 2);\n const file = `${config.contentFolder}/${type}/${type}-${id}.json`;\n const normalizedData = `${data}\\n`;\n\n if (isProductionMode()) {\n await assertFeatureBranchForWritesIfRequired();\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n await saveGitHubFile(file, normalizedData, `Create new ${type} ${id}`, activeBranch);\n await waitForPublicReadConsistency(file, normalizedData);\n\n // Write-through: add new entry to in-memory store\n if (activeBranch) {\n applyMutation(activeBranch, {\n type: 'upsert',\n path: file,\n content: values,\n sha: '',\n });\n }\n\n await persistBranchHistoryEntryIfNeeded(activeBranch, file);\n await syncEmbeddingsForUpsertIfEnabled(file, values, {}, activeBranch, true);\n const built = await buildJsons(file);\n\n return built.success ? { success: true, path: file } : { success: false, error: built.error };\n }\n\n const cookieStore = await cookies();\n const activeBranchDev = cookieStore.get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n const filePath = path.join(/*turbopackIgnore: true*/ process.cwd(), file);\n await fsPromises.mkdir(path.dirname(filePath), { recursive: true });\n await fsPromises.writeFile(filePath, normalizedData, 'utf8');\n await persistBranchHistoryEntryIfNeeded(activeBranchDev, file);\n await syncEmbeddingsForUpsertIfEnabled(file, values, {}, activeBranchDev, false);\n const built = await buildJsons(file);\n\n return built.success ? { success: true, path: file } : { success: false, error: built.error };\n } catch (e) {\n return { success: false, error: getErrorMessage(e) } satisfies NewFileResult;\n }\n};\n\nexport const removeFile = async (fileName: string): Promise<ActionResult> => {\n const config = getConfig();\n try {\n let collectionType: string | undefined;\n try {\n const existing = await getFile(fileName);\n collectionType = existing?.sys?.type;\n } catch {\n /* best-effort */\n }\n\n // Determine companion markdown and richtext files to delete\n const companionPaths =\n typeof collectionType === 'string'\n ? [\n ...Object.values(companionMarkdownPathsForEntry(fileName, collectionType, config.collections)),\n ...Object.values(companionRichTextPathsForEntry(fileName, collectionType, config.collections)),\n ]\n : [];\n\n if (isProductionMode()) {\n await assertFeatureBranchForWritesIfRequired();\n const activeBranch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value;\n await deleteGitHubFile(fileName, `Remove ${fileName}`, activeBranch);\n for (const mdPath of companionPaths) {\n try {\n await deleteGitHubFile(mdPath, `Remove companion ${mdPath}`, activeBranch);\n } catch {\n /* best-effort — companion may not exist */\n }\n }\n\n // Write-through: remove entry from in-memory store\n if (activeBranch) {\n applyMutation(activeBranch, { type: 'delete', path: fileName });\n }\n\n await syncEmbeddingsForRemoveIfEnabled(fileName, activeBranch, true);\n const built = await buildJsons(fileName);\n\n return built.success ? actionOk() : built;\n }\n\n const filePath = path.join(/*turbopackIgnore: true*/ process.cwd(), fileName);\n await fsPromises.unlink(filePath);\n for (const mdPath of companionPaths) {\n try {\n await fsPromises.unlink(path.join(/*turbopackIgnore: true*/ process.cwd(), mdPath));\n } catch {\n /* best-effort — companion may not exist */\n }\n }\n await syncEmbeddingsForRemoveIfEnabled(fileName, undefined, false);\n const built = await buildJsons(fileName);\n\n return built.success ? actionOk() : built;\n } catch (e) {\n return actionErr(e);\n }\n};\n","/**\n * Anthropic adapter — wraps `@anthropic-ai/sdk` `messages.stream()`.\n *\n * Maps Anthropic's content-block streaming events into our normalised\n * {@link ProviderEvent} stream. The SDK is loaded lazily so a missing peer\n * dep surfaces here instead of at module-import time.\n */\nimport type { AnthropicProvider } from '../types';\nimport { providerApiKeyEnv } from '../featureFlag';\n\nimport type { ChatProvider, ChatStreamInput, NormalizedMessage, NormalizedTool, ProviderEvent } from './types';\n\ntype AnthropicSdk = typeof import('@anthropic-ai/sdk');\n\nasync function loadSdk(): Promise<AnthropicSdk> {\n try {\n return (await import('@anthropic-ai/sdk')) as unknown as AnthropicSdk;\n } catch {\n throw new Error(\n 'The chat agent is configured for Anthropic but the optional peer dependency `@anthropic-ai/sdk` is not installed. Run: npm install @anthropic-ai/sdk',\n );\n }\n}\n\nfunction toAnthropicMessages(messages: NormalizedMessage[]): unknown[] {\n // Anthropic alternates user/assistant, with `tool_result` blocks living\n // inside a user message. We coalesce consecutive `tool` messages into a\n // single user message of `tool_result` blocks.\n const out: { role: 'user' | 'assistant'; content: unknown }[] = [];\n for (const m of messages) {\n if (m.role === 'tool') {\n const last = out[out.length - 1];\n const block = {\n type: 'tool_result' as const,\n tool_use_id: m.toolUseId,\n content: m.content,\n ...(m.isError ? { is_error: true } : {}),\n };\n if (last && last.role === 'user' && Array.isArray(last.content)) {\n (last.content as unknown[]).push(block);\n } else {\n out.push({ role: 'user', content: [block] });\n }\n continue;\n }\n if (m.role === 'user') {\n if (typeof m.content === 'string') {\n out.push({ role: 'user', content: m.content });\n } else {\n const blocks = m.content.map((b) => mapUserBlockToAnthropic(b));\n out.push({ role: 'user', content: blocks });\n }\n continue;\n }\n // assistant — text + tool_use only\n const blocks = m.content.map((b) => {\n if (b.type === 'text') return { type: 'text', text: b.text };\n if (b.type === 'tool_use') return { type: 'tool_use', id: b.id, name: b.name, input: b.input };\n // Defensive — assistant turns shouldn't include document blocks. Drop to text.\n return { type: 'text', text: `[unexpected ${b.type} block]` };\n });\n out.push({ role: 'assistant', content: blocks });\n }\n return out;\n}\n\n/**\n * Map a normalised user content block to Anthropic's wire format. PDF\n * attachments become native `document` blocks (Claude reads them directly,\n * including images and layout); text blocks pass through unchanged.\n */\nfunction mapUserBlockToAnthropic(block: { type: string; [k: string]: unknown }): unknown {\n if (block.type === 'text') {\n return { type: 'text', text: block.text };\n }\n if (block.type === 'document_pdf') {\n return {\n type: 'document',\n source: {\n type: 'base64',\n media_type: block.mediaType,\n data: block.base64,\n },\n title: block.filename,\n };\n }\n // Unsupported block type — drop to a placeholder so the request isn't malformed.\n return { type: 'text', text: `[unsupported block: ${block.type}]` };\n}\n\nfunction toAnthropicTools(tools: NormalizedTool[]): unknown[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.inputSchema,\n }));\n}\n\nexport class AnthropicChatProvider implements ChatProvider {\n readonly providerType = 'anthropic' as const;\n readonly supportsNativePdf = true;\n\n constructor(private readonly provider: AnthropicProvider) {}\n\n get modelId(): string {\n return this.provider.model;\n }\n\n async *streamChat(input: ChatStreamInput): AsyncIterable<ProviderEvent> {\n let sdk: AnthropicSdk;\n try {\n sdk = await loadSdk();\n } catch (err) {\n yield { type: 'error', message: err instanceof Error ? err.message : 'Failed to load Anthropic SDK' };\n return;\n }\n\n const envName = providerApiKeyEnv(this.provider) ?? 'ANTHROPIC_API_KEY';\n const apiKey = process.env[envName];\n if (!apiKey) {\n yield { type: 'error', message: `Missing API key — set ${envName} in the environment.` };\n return;\n }\n\n const Anthropic = (sdk as unknown as { default: new (opts: { apiKey: string }) => unknown }).default ?? sdk;\n const client = new (\n Anthropic as new (opts: { apiKey: string }) => {\n messages: { stream: (req: unknown) => AsyncIterable<unknown> & { finalMessage(): Promise<unknown> } };\n }\n )({ apiKey });\n\n const stream = client.messages.stream({\n model: this.provider.model,\n max_tokens: input.maxOutputTokens,\n system: input.systemPrompt,\n messages: toAnthropicMessages(input.messages),\n ...(input.tools.length > 0 ? { tools: toAnthropicTools(input.tools) } : {}),\n });\n\n const inputJsonByIndex = new Map<number, string>();\n const idByIndex = new Map<number, string>();\n const nameByIndex = new Map<number, string>();\n\n try {\n for await (const ev of stream as AsyncIterable<{ type: string } & Record<string, unknown>>) {\n switch (ev.type) {\n case 'content_block_start': {\n const idx = ev.index as number;\n const block = ev.content_block as { type: string; id?: string; name?: string };\n if (block.type === 'tool_use') {\n const id = block.id ?? `tool_${idx}`;\n const name = block.name ?? '';\n idByIndex.set(idx, id);\n nameByIndex.set(idx, name);\n inputJsonByIndex.set(idx, '');\n yield { type: 'tool_use_start', id, name };\n }\n break;\n }\n case 'content_block_delta': {\n const idx = ev.index as number;\n const delta = ev.delta as { type: string; text?: string; partial_json?: string };\n if (delta.type === 'text_delta' && typeof delta.text === 'string') {\n yield { type: 'text_delta', text: delta.text };\n } else if (delta.type === 'input_json_delta' && typeof delta.partial_json === 'string') {\n const id = idByIndex.get(idx);\n if (id) {\n inputJsonByIndex.set(idx, (inputJsonByIndex.get(idx) ?? '') + delta.partial_json);\n yield { type: 'tool_use_input_delta', id, partialJson: delta.partial_json };\n }\n }\n break;\n }\n case 'content_block_stop': {\n const idx = ev.index as number;\n const id = idByIndex.get(idx);\n const name = nameByIndex.get(idx);\n if (id && name !== undefined) {\n const raw = inputJsonByIndex.get(idx) ?? '';\n let parsed: unknown = {};\n try {\n parsed = raw ? JSON.parse(raw) : {};\n } catch {\n parsed = { _rawInput: raw };\n }\n yield { type: 'tool_use_complete', id, name, input: parsed };\n }\n break;\n }\n default:\n break;\n }\n }\n const final = (await stream.finalMessage()) as {\n stop_reason?: string;\n usage?: { input_tokens?: number; output_tokens?: number; cache_read_input_tokens?: number };\n };\n const usage = final.usage ?? {};\n yield {\n type: 'message_stop',\n stopReason: mapAnthropicStopReason(final.stop_reason),\n usage: {\n inputTokens: usage.input_tokens ?? 0,\n outputTokens: usage.output_tokens ?? 0,\n cachedInputTokens: usage.cache_read_input_tokens ?? 0,\n },\n };\n } catch (err) {\n yield { type: 'error', message: err instanceof Error ? err.message : 'Anthropic stream failed' };\n }\n }\n}\n\nfunction mapAnthropicStopReason(r: unknown): 'end_turn' | 'tool_use' | 'max_tokens' | 'stop_sequence' | 'other' {\n if (r === 'end_turn' || r === 'tool_use' || r === 'max_tokens' || r === 'stop_sequence') return r;\n return 'other';\n}\n","/**\n * OpenAI adapter — wraps `openai` SDK `chat.completions.create({ stream: true })`.\n *\n * Powers both `'openai'` and `'local'` providers. The `'local'` variant just\n * sets `baseURL` to a local OpenAI-compatible endpoint (Ollama, LM Studio,\n * vLLM, llama.cpp server) and treats a missing API key as \"no auth needed\".\n *\n * The Chat Completions API streams tool calls as JSON-string `arguments`\n * deltas; we accumulate them and parse once the call ends.\n */\nimport type { LocalProvider, OpenAIProvider } from '../types';\nimport { providerApiKeyEnv } from '../featureFlag';\n\nimport type { ChatProvider, ChatStreamInput, NormalizedMessage, NormalizedTool, ProviderEvent } from './types';\n\ntype OpenAISdk = typeof import('openai');\n\nasync function loadSdk(): Promise<OpenAISdk> {\n try {\n return (await import('openai')) as unknown as OpenAISdk;\n } catch {\n throw new Error(\n 'The chat agent is configured for OpenAI / local but the optional peer dependency `openai` is not installed. Run: npm install openai',\n );\n }\n}\n\ntype OpenAIMessage =\n | { role: 'system'; content: string }\n | { role: 'user'; content: string }\n | {\n role: 'assistant';\n content: string | null;\n tool_calls?: { id: string; type: 'function'; function: { name: string; arguments: string } }[];\n }\n | { role: 'tool'; tool_call_id: string; content: string };\n\nfunction toOpenAIMessages(systemPrompt: string, messages: NormalizedMessage[]): OpenAIMessage[] {\n const out: OpenAIMessage[] = [];\n if (systemPrompt) out.push({ role: 'system', content: systemPrompt });\n\n for (const m of messages) {\n if (m.role === 'tool') {\n out.push({ role: 'tool', tool_call_id: m.toolUseId, content: m.content });\n continue;\n }\n if (m.role === 'user') {\n const text = typeof m.content === 'string' ? m.content : extractText(m.content);\n out.push({ role: 'user', content: text });\n continue;\n }\n // assistant\n let text = '';\n const toolCalls: { id: string; type: 'function'; function: { name: string; arguments: string } }[] = [];\n for (const block of m.content) {\n if (block.type === 'text') text += block.text;\n else if (block.type === 'tool_use') {\n toolCalls.push({\n id: block.id,\n type: 'function',\n function: { name: block.name, arguments: JSON.stringify(block.input ?? {}) },\n });\n }\n }\n out.push({\n role: 'assistant',\n content: text || null,\n ...(toolCalls.length > 0 ? { tool_calls: toolCalls } : {}),\n });\n }\n return out;\n}\n\nfunction extractText(blocks: { type: string; text?: string; filename?: string }[]): string {\n // Defensive: this provider doesn't support native PDFs. The route handler\n // converts PDFs to text BEFORE the message reaches us. If we still see a\n // `document_pdf` block (e.g. a hand-built request), surface a clear marker\n // so the model knows the binary was dropped.\n const parts: string[] = [];\n for (const b of blocks) {\n if (b.type === 'text') {\n parts.push(b.text ?? '');\n } else if (b.type === 'document_pdf') {\n parts.push(`[Attached PDF \"${b.filename ?? 'document.pdf'}\" — binary content not available to this provider]`);\n }\n }\n return parts.join('\\n');\n}\n\nfunction toOpenAITools(tools: NormalizedTool[]): unknown[] {\n return tools.map((t) => ({\n type: 'function',\n function: {\n name: t.name,\n description: t.description,\n parameters: t.inputSchema,\n },\n }));\n}\n\nexport class OpenAIChatProvider implements ChatProvider {\n readonly supportsNativePdf = false;\n\n constructor(private readonly provider: OpenAIProvider | LocalProvider) {}\n\n get providerType(): 'openai' | 'local' {\n return this.provider.type;\n }\n\n get modelId(): string {\n return this.provider.model;\n }\n\n async *streamChat(input: ChatStreamInput): AsyncIterable<ProviderEvent> {\n let sdk: OpenAISdk;\n try {\n sdk = await loadSdk();\n } catch (err) {\n yield { type: 'error', message: err instanceof Error ? err.message : 'Failed to load OpenAI SDK' };\n return;\n }\n\n const envName = providerApiKeyEnv(this.provider);\n const apiKey = envName ? process.env[envName] : undefined;\n const baseURL =\n this.provider.type === 'local' ? this.provider.baseURL : ((this.provider as OpenAIProvider).baseURL ?? undefined);\n\n if (this.provider.type === 'openai' && !apiKey) {\n yield {\n type: 'error',\n message: `Missing API key — set ${envName ?? 'OPENAI_API_KEY'} in the environment.`,\n };\n return;\n }\n\n const OpenAI = (sdk as unknown as { default: new (opts: unknown) => unknown }).default ?? sdk;\n const client = new (\n OpenAI as new (opts: { apiKey?: string; baseURL?: string }) => {\n chat: {\n completions: {\n create: (req: unknown) => Promise<AsyncIterable<unknown>>;\n };\n };\n }\n )({\n // Local servers usually don't need a key; pass a dummy if none provided to satisfy the SDK guard.\n apiKey: apiKey ?? (this.provider.type === 'local' ? 'lm-studio' : ''),\n ...(baseURL ? { baseURL } : {}),\n });\n\n const messages = toOpenAIMessages(input.systemPrompt, input.messages);\n const tools = input.tools.length > 0 ? toOpenAITools(input.tools) : undefined;\n\n let stream: AsyncIterable<unknown>;\n try {\n stream = await client.chat.completions.create({\n model: this.provider.model,\n max_tokens: input.maxOutputTokens,\n stream: true,\n stream_options: { include_usage: true },\n messages,\n ...(tools ? { tools } : {}),\n });\n } catch (err) {\n yield { type: 'error', message: err instanceof Error ? err.message : 'OpenAI stream failed to open' };\n return;\n }\n\n type ToolCallAccum = { id: string; name: string; argsJson: string; emittedStart: boolean };\n const toolCalls = new Map<number, ToolCallAccum>();\n let finishReason: string | null = null;\n let usage: { input?: number; output?: number; cached?: number } = {};\n\n try {\n for await (const chunk of stream as AsyncIterable<{\n choices?: { delta?: { content?: string; tool_calls?: unknown[] }; finish_reason?: string }[];\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n prompt_tokens_details?: { cached_tokens?: number };\n };\n }>) {\n const choice = chunk.choices?.[0];\n const delta = choice?.delta;\n if (delta?.content) {\n yield { type: 'text_delta', text: delta.content };\n }\n if (delta?.tool_calls) {\n for (const tc of delta.tool_calls as {\n index: number;\n id?: string;\n function?: { name?: string; arguments?: string };\n }[]) {\n const idx = tc.index;\n let acc = toolCalls.get(idx);\n if (!acc) {\n acc = { id: tc.id ?? `tool_${idx}`, name: '', argsJson: '', emittedStart: false };\n toolCalls.set(idx, acc);\n }\n if (tc.id) acc.id = tc.id;\n if (tc.function?.name) acc.name = tc.function.name;\n if (!acc.emittedStart && acc.name) {\n acc.emittedStart = true;\n yield { type: 'tool_use_start', id: acc.id, name: acc.name };\n }\n if (tc.function?.arguments) {\n acc.argsJson += tc.function.arguments;\n if (acc.emittedStart) {\n yield { type: 'tool_use_input_delta', id: acc.id, partialJson: tc.function.arguments };\n }\n }\n }\n }\n if (choice?.finish_reason) {\n finishReason = choice.finish_reason;\n }\n if (chunk.usage) {\n usage = {\n input: chunk.usage.prompt_tokens,\n output: chunk.usage.completion_tokens,\n cached: chunk.usage.prompt_tokens_details?.cached_tokens,\n };\n }\n }\n } catch (err) {\n yield { type: 'error', message: err instanceof Error ? err.message : 'OpenAI stream failed' };\n return;\n }\n\n // Emit final tool_use_complete events for any tool calls collected.\n for (const acc of toolCalls.values()) {\n if (!acc.emittedStart) {\n yield { type: 'tool_use_start', id: acc.id, name: acc.name };\n }\n let parsed: unknown = {};\n try {\n parsed = acc.argsJson ? JSON.parse(acc.argsJson) : {};\n } catch {\n parsed = { _rawInput: acc.argsJson };\n }\n yield { type: 'tool_use_complete', id: acc.id, name: acc.name, input: parsed };\n }\n\n yield {\n type: 'message_stop',\n stopReason: mapFinishReason(finishReason, toolCalls.size > 0),\n usage: {\n inputTokens: usage.input ?? 0,\n outputTokens: usage.output ?? 0,\n cachedInputTokens: usage.cached ?? 0,\n },\n };\n }\n}\n\nfunction mapFinishReason(\n r: string | null,\n hadToolCalls: boolean,\n): 'end_turn' | 'tool_use' | 'max_tokens' | 'stop_sequence' | 'other' {\n if (r === 'tool_calls' || (hadToolCalls && r !== 'length')) return 'tool_use';\n if (r === 'stop') return 'end_turn';\n if (r === 'length') return 'max_tokens';\n return 'other';\n}\n","export type {\n AgentConfig,\n AgentPricing,\n AgentProvider,\n AnthropicProvider,\n OpenAIProvider,\n LocalProvider,\n} from './types';\nexport { DEFAULT_AGENT_CONFIG, defineAgentConfig } from './defaults';\nexport { estimateCostUSD, getProviderPricing } from './pricing';\nexport { getAgentStatus, hasProviderKey, isAgentEnabled, providerApiKeyEnv, type AgentStatus } from './featureFlag';\nexport { getUsage, recordTurn, resetUsage, isBudgetExceeded, type AgentUsage } from './usage';\nexport { setAgentConfig, getAgentConfig } from './configStore';\nexport { entryToEmbeddingText } from './embedText';\nexport {\n type Embedder,\n LocalTransformersEmbedder,\n getDefaultEmbedder,\n setDefaultEmbedder,\n DEFAULT_MODEL_ID,\n DEFAULT_DIM,\n} from './embedder';\nexport {\n type EmbeddingsRecord,\n type EmbeddingsStore,\n EMBEDDINGS_STORE_PATH,\n emptyStore,\n hashEmbeddingText,\n loadEmbeddings,\n serializeStore,\n removeEntryFromStore,\n upsertEntryInStore,\n embedEntry,\n embedEntryFromMemory,\n embedAll,\n} from './embeddings';\nexport { encodeFloat32, decodeFloat32, cosineSimilarity } from './storeFormat';\nexport { syncEmbeddingsAfterUpsert, syncEmbeddingsAfterRemove } from './embeddingsHook';\nexport { searchContent, clearSearchCache, type SearchHit, type SearchOptions } from './search';\nexport { buildSystemPrompt, type SystemPromptInput, type StyleExemplar } from './systemPrompt';\nexport {\n READ_ONLY_TOOLS,\n PROPOSAL_TOOLS,\n ALL_TOOLS,\n getToolHandler,\n getToolDefinitions,\n acceptProposal,\n type ToolHandler,\n type ToolContext,\n type ToolRunResult,\n} from './tools';\nexport {\n type Proposal,\n type EditProposal,\n type CreateProposal,\n type AcceptResult,\n describeEditSummary,\n describeCreateSummary,\n fieldsToFormStrings,\n resolveEntryPath,\n} from './proposals';\nexport { runChat, type ChatEvent, type RunChatInput } from './chat';\nexport {\n classifyAttachment,\n checkAttachmentSize,\n checkAttachmentCount,\n normalizeAttachments,\n wrapAttachmentText,\n type AttachmentKind,\n type RawAttachment,\n type NormalizedAttachmentsResult,\n type AttachmentDiagnostic,\n} from './attachments';\nexport { chatRoute, chatStatusRoute } from './chatApi';\nexport { getChatProvider } from './providers';\nexport type {\n ChatProvider,\n ChatStreamInput,\n NormalizedMessage,\n NormalizedContentBlock,\n NormalizedTool,\n ProviderEvent,\n} from './providers/types';\n","import type { AgentConfig } from './types';\n\n/**\n * Defaults for {@link AgentConfig}. Targets Claude Haiku 4.5 — cheapest\n * current Claude tier with full tool-use support — and a $5 spend cap that\n * comfortably covers evaluation and developer testing.\n */\nexport const DEFAULT_AGENT_CONFIG: AgentConfig = {\n provider: {\n type: 'anthropic',\n model: 'claude-haiku-4-5-20251001',\n pricing: { inputPerM: 1, outputPerM: 5, cachedInputPerM: 0.1 },\n },\n maxInputTokens: 100_000,\n maxOutputTokens: 10_000,\n maxProposalsPerTurn: 20,\n maxAttachmentBytes: 25 * 1024 * 1024,\n maxAttachmentsPerTurn: 3,\n totalBudgetUSD: 5,\n};\n\n/**\n * Helper for the user's `cms/octocms.config.ts`. Merges shallow overrides\n * into {@link DEFAULT_AGENT_CONFIG} so users only specify what they want to\n * change. The `provider` field is replaced wholesale (it's a discriminated\n * union — shallow-merging across `'anthropic'` / `'openai'` / `'local'`\n * variants would produce invalid combinations).\n */\nexport function defineAgentConfig(overrides: Partial<AgentConfig> = {}): AgentConfig {\n return {\n ...DEFAULT_AGENT_CONFIG,\n ...overrides,\n provider: overrides.provider ?? DEFAULT_AGENT_CONFIG.provider,\n };\n}\n","/**\n * Phase 2 — Retrieval.\n *\n * `searchContent(query, options)` runs cosine similarity over the committed\n * embeddings store and returns ranked content hits. The agent calls this from\n * its `searchContent` tool; the same function is also handy for one-off\n * scripts or other admin UI that needs retrieval.\n *\n * Reads only — never mutates content. Loads the same on-disk store the\n * embedding pipeline writes (`cms/__generated__/embeddings.json`), so search\n * results follow whichever branch the caller targets.\n *\n * The store is cached in module scope for ~30 seconds. That's plenty for the\n * back-and-forth of a single chat turn (multiple tool calls share one load)\n * while still picking up freshly committed embeddings without a process\n * restart.\n */\n\nimport { promises as fsPromises } from 'fs';\nimport path from 'path';\n\nimport type { Config } from '../admin/types';\nimport { getConfig } from '../lib/configStore';\nimport { buildEntryExcerpt, collectionFromPath, resolveEntryId, resolveEntryTitle } from '../lib/resolveEntryTitle';\n\nimport { getDefaultEmbedder, type Embedder } from './embedder';\nimport { loadEmbeddings, type EmbeddingsStore } from './embeddings';\nimport { cosineSimilarity, decodeFloat32 } from './storeFormat';\n\nexport type SearchHit = {\n /** Entry id — filename stem for non-media, `sys.id` for media. */\n id: string;\n /** Repo-relative path, e.g. `cms/content/post/post-abc.json`. */\n path: string;\n /** Collection name (= `sys.type`). */\n collection: string;\n /** Cosine similarity in `[-1, 1]`. Higher = better match. */\n score: number;\n /** Human-readable title resolved from the schema's `entryTitle` field. */\n title: string;\n /** Short text excerpt (≤ 200 chars by default) — empty when nothing useful is available. */\n excerpt: string;\n};\n\nexport type SearchOptions = {\n /** Top-K hits to return. Defaults to 10. */\n k?: number;\n /** Restrict results to a single collection (`sys.type`). */\n collection?: string;\n /** Branch override forwarded to `loadEmbeddings` and the entry reader. */\n branch?: string;\n /** Override the embedder (test seam). Defaults to the local transformers singleton. */\n embedder?: Embedder;\n /** Bypass the in-process store cache. Defaults to false. */\n noCache?: boolean;\n /** Excerpt max length. Defaults to 200. */\n excerptLength?: number;\n};\n\ntype CacheEntry = { store: EmbeddingsStore; expiresAt: number; key: string };\n\nconst STORE_CACHE_TTL_MS = 30_000;\nlet cached: CacheEntry | null = null;\n\nasync function getStore(branch: string | undefined, noCache: boolean): Promise<EmbeddingsStore> {\n const key = branch ?? '';\n const now = Date.now();\n if (!noCache && cached && cached.key === key && cached.expiresAt > now) {\n return cached.store;\n }\n const store = await loadEmbeddings(branch);\n cached = { store, expiresAt: now + STORE_CACHE_TTL_MS, key };\n return store;\n}\n\n/** Test seam — drop the cached store so the next call reloads from disk. */\nexport function clearSearchCache(): void {\n cached = null;\n}\n\nasync function readEntryPayload(filePath: string, branch: string | undefined): Promise<unknown | null> {\n // Match `loadEmbeddings`'s strategy: try GitHub in production, fall back to\n // the local filesystem. We deliberately don't merge companion `.md` content —\n // titles and excerpts come from `entry.fields` only, which keeps each search\n // hit cheap (no extra companion fetch per result).\n try {\n if (process.env.NODE_ENV === 'production') {\n const { getGitHubFile } = await import('../admin/github');\n const file = await getGitHubFile(filePath, branch);\n if (file) {\n try {\n return JSON.parse(file.content);\n } catch {\n return null;\n }\n }\n }\n } catch {\n /* fall through to FS */\n }\n try {\n const abs = path.join(process.cwd(), 'cms', filePath.replace(/^cms[\\\\/]/, ''));\n const raw = await fsPromises.readFile(abs, { encoding: 'utf8' });\n return JSON.parse(raw);\n } catch {\n return null;\n }\n}\n\n/**\n * Run cosine retrieval over the embeddings store.\n *\n * Scoring is brute-force (one dot product per stored vector). At the design\n * scale of ~5,000 entries × 384 dims this finishes in ~10 ms on a warm process —\n * the dominant cost is embedding the query, which is ~3–10 s on cold start\n * and < 100 ms warm.\n */\nexport async function searchContent(query: string, options: SearchOptions = {}): Promise<SearchHit[]> {\n const trimmed = query?.trim() ?? '';\n if (!trimmed) return [];\n\n const k = Math.max(1, options.k ?? 10);\n const embedder = options.embedder ?? getDefaultEmbedder();\n const config: Config = getConfig();\n\n const store = await getStore(options.branch, options.noCache ?? false);\n const paths = Object.keys(store.entries);\n if (paths.length === 0) return [];\n\n const [queryVec] = await embedder.embed([trimmed]);\n\n // Score every entry, optionally pre-filtered by collection. We score before\n // resolving titles/excerpts so the per-hit disk reads only run for the top K.\n type Scored = { path: string; score: number };\n const scored: Scored[] = [];\n for (const p of paths) {\n if (options.collection) {\n const c = collectionFromPath(config, p);\n if (c !== options.collection) continue;\n }\n const record = store.entries[p];\n let vec: Float32Array;\n try {\n vec = decodeFloat32(record.vec);\n } catch {\n continue;\n }\n if (vec.length !== queryVec.length) continue;\n const score = cosineSimilarity(queryVec, vec);\n scored.push({ path: p, score });\n }\n\n scored.sort((a, b) => b.score - a.score);\n const top = scored.slice(0, k);\n\n const excerptLength = options.excerptLength ?? 200;\n const hits: SearchHit[] = [];\n for (const { path: p, score } of top) {\n const payload = (await readEntryPayload(p, options.branch)) as {\n sys?: { id?: unknown; type?: unknown };\n fields?: Record<string, unknown>;\n } | null;\n const collection = collectionFromPath(config, p);\n hits.push({\n id: resolveEntryId(config, p, payload ?? undefined),\n path: p,\n collection,\n score,\n title: resolveEntryTitle(config, p, payload ?? undefined),\n excerpt: buildEntryExcerpt(config, p, payload ?? undefined, excerptLength),\n });\n }\n\n return hits;\n}\n","/**\n * System prompt builder for the chat agent.\n *\n * Pure function — collects schema overview + (optionally) recent post bodies\n * and assembles the prompt at request time. The agent's behavioural rules\n * live here too: search before answering, never claim to have edited\n * anything, mutations require approval (Phase 4).\n */\nimport type { Config } from '../types';\n\nexport type StyleExemplar = {\n /** Collection name. */\n type: string;\n /** Resolved entry title. */\n title: string;\n /** Truncated body — caller is responsible for keeping size reasonable. */\n body: string;\n};\n\nexport type SystemPromptInput = {\n config: Config;\n /** Optional 2–3 recent posts whose body text is included as style guidance. */\n styleExemplars?: StyleExemplar[];\n /** Override \"today's date\" — defaults to `new Date()`. Useful for tests. */\n now?: Date;\n};\n\nexport function buildSystemPrompt({ config, styleExemplars, now }: SystemPromptInput): string {\n const today = (now ?? new Date()).toISOString().slice(0, 10);\n\n const collectionLines: string[] = [];\n for (const [name, col] of Object.entries(config.collections)) {\n const fieldSummary = Object.entries(col.fields)\n .map(([key, def]) => `${key}:${def.format}${def.required ? '*' : ''}`)\n .join(', ');\n const cardinality = col.hasMany ? 'many' : 'singleton';\n collectionLines.push(` - ${name} (${cardinality}, label=\"${col.label}\"): ${fieldSummary}`);\n }\n\n const exemplarsBlock =\n styleExemplars && styleExemplars.length > 0\n ? '\\n\\n## Recent posts (style reference)\\n' +\n styleExemplars.map((e, i) => `### Example ${i + 1} — ${e.type}: \"${e.title}\"\\n${e.body.trim()}`).join('\\n\\n')\n : '';\n\n return `You are the editorial assistant for the OctoCMS CMS. You help editors find, summarize, and improve their content.\n\nToday's date is ${today}.\n\n## Your tools\n\nRead-only — use these to discover content:\n- searchContent(query, k?, collection?) — semantic search over all entries; returns hits with title, score, excerpt\n- listCollections() — returns the schema's collection definitions\n- getEntry(id, collection?) — fetch a single entry's fields by its filename stem (id), e.g. \"post-abc\"\n- findEntryForDocument(documentText, hintUrl?, k?) — when the user uploaded a PDF / DOCX, identify which existing CMS entry it most likely corresponds to; returns ranked candidates with a \\`matchedBy\\` reason\n\nMutating — these emit *proposals* that the user must accept in the UI before any write happens. You CANNOT save anything yourself; this is the only mechanism:\n- proposeEdit({ entryId, collection, fieldChanges, reasoning }) — propose changes to one existing entry. \\`fieldChanges\\` is an object of fieldName → new value; only include fields you want to change.\n- proposeNewEntry({ collection, fields, reasoning }) — propose a new entry. \\`fields\\` must include every required field for that collection.\n\n## Behavioural rules\n\n1. **Always search before answering** content questions. Do not rely on training data — your only source of truth about this project is the tools.\n2. **Cite the entry path** for every claim, e.g. \"(post/post-abc.json)\". The user can click through.\n3. **Mutations require approval.** Use \\`proposeEdit\\` / \\`proposeNewEntry\\` — never claim to have saved anything before the user accepts. Each proposal becomes a card with a diff or preview; the user clicks **Accept** or **Reject**. After you emit a proposal, stop and wait — do NOT re-emit the same proposal, and do NOT propose the same change in a follow-up turn unless the user asks again.\n4. **Always confirm the entry exists first.** Before \\`proposeEdit\\`, run \\`searchContent\\` and/or \\`getEntry\\` to get the exact \\`entryId\\` (filename stem) and to inspect the current values you are changing. Quoting the existing value back to the user before proposing is a good habit.\n5. **Validate inputs to your proposals carefully.** The server re-runs schema validation; if it fails, the tool returns \\`fieldErrors\\` and you should self-correct and propose again.\n6. **Be concise.** Two short paragraphs beat eight verbose ones. Use bullet lists when comparing multiple entries.\n7. **If a tool returns nothing**, say so plainly and suggest a different query. Do not invent results.\n8. **Stay on-task.** This is an editorial assistant — politely refuse off-topic questions.\n\n## Schema overview\n\nThe CMS has these collections:\n${collectionLines.join('\\n')}\n\nReference fields store filename stems (e.g. \"author-abc.json\"). Use \\`getEntry\\` to expand them.${exemplarsBlock}`;\n}\n","/**\n * Tool registry for the chat agent. Two flavours:\n *\n * - **Read-only tools** — `searchContent`, `listCollections`, `getEntry`. Run\n * directly on the server and return their result string to the model.\n * - **Proposal tools** — `proposeEdit`, `proposeNewEntry`. Validate the\n * payload, then return BOTH a string for the model and a `proposal`\n * object the chat loop emits as a `proposal` SSE event. The user must\n * explicitly approve in the UI before any write happens — see\n * `octocms/agent/proposals.ts`.\n *\n * Each tool exposes:\n * - `definition` — the JSON schema sent to the model.\n * - `run(input, ctx)` — server-side handler returning either a plain string\n * (the model sees it as the tool result) or `{ message, proposal? }`.\n * Errors are caught and stringified by the chat loop; we never throw out\n * of `run`.\n */\nimport { randomUUID } from 'node:crypto';\n\nimport type { NormalizedTool } from '../providers/types';\nimport type { Config } from '../../types';\nimport {\n acceptProposal as _acceptProposal,\n describeCreateSummary,\n describeEditSummary,\n fieldsToFormStrings,\n resolveEntryPath,\n type CreateProposal,\n type EditProposal,\n type Proposal,\n} from '../proposals';\nimport { searchContent } from '../search';\n\nexport type ToolRunResult =\n | string\n | {\n /** What the model sees as the tool result (must already be JSON-stringified). */\n message: string;\n /** Optional proposal — the chat loop emits it as an SSE event before the tool_result. */\n proposal?: Proposal;\n };\n\nexport type ToolHandler = {\n definition: NormalizedTool;\n run(input: unknown, ctx: ToolContext): Promise<ToolRunResult>;\n};\n\nexport type ToolContext = {\n config: Config;\n branch?: string;\n /**\n * Wire-level `tool_use_id` for the current invocation. Proposal tools embed\n * this in the proposal so the UI can correlate accept/reject with the\n * originating tool call.\n */\n toolUseId?: string;\n};\n\nconst searchContentTool: ToolHandler = {\n definition: {\n name: 'searchContent',\n description:\n 'Semantic search over all CMS entries. Use this BEFORE answering any question about content. Returns ranked hits with title, score, and a short excerpt.',\n inputSchema: {\n type: 'object',\n properties: {\n query: { type: 'string', description: 'Natural-language search query.' },\n k: {\n type: 'integer',\n description: 'Number of results to return (1–25). Defaults to 8.',\n minimum: 1,\n maximum: 25,\n },\n collection: {\n type: 'string',\n description: 'Optional collection name to restrict the search (e.g. \"post\").',\n },\n },\n required: ['query'],\n },\n },\n async run(input, ctx) {\n const { query, k, collection } = (input ?? {}) as { query?: unknown; k?: unknown; collection?: unknown };\n if (typeof query !== 'string' || !query.trim()) {\n return JSON.stringify({ error: 'query is required and must be a non-empty string' });\n }\n const hits = await searchContent(query, {\n k: typeof k === 'number' ? Math.max(1, Math.min(25, Math.floor(k))) : 8,\n collection: typeof collection === 'string' && collection.trim() ? collection.trim() : undefined,\n branch: ctx.branch,\n });\n if (hits.length === 0) {\n return JSON.stringify({\n results: [],\n note: 'No results — verify the query, or try a broader phrasing. If embeddings.json is missing, run `npx octocms embeddings:gen` on your dev machine.',\n });\n }\n return JSON.stringify({\n results: hits.map((h) => ({\n id: h.id,\n path: h.path,\n collection: h.collection,\n score: Number(h.score.toFixed(4)),\n title: h.title,\n excerpt: h.excerpt,\n })),\n });\n },\n};\n\nconst listCollectionsTool: ToolHandler = {\n definition: {\n name: 'listCollections',\n description:\n 'List all collections in the schema with their fields and types. Useful when the user asks about content shape.',\n inputSchema: { type: 'object', properties: {}, additionalProperties: false },\n },\n async run(_input, ctx) {\n const collections = Object.entries(ctx.config.collections).map(([name, col]) => ({\n name,\n label: col.label,\n hasMany: Boolean(col.hasMany),\n fields: Object.entries(col.fields).map(([key, def]) => ({\n key,\n label: def.label,\n format: def.format,\n required: Boolean(def.required),\n })),\n }));\n return JSON.stringify({ collections });\n },\n};\n\nconst getEntryTool: ToolHandler = {\n definition: {\n name: 'getEntry',\n description:\n 'Fetch a single entry by its filename stem (the value returned in `id` from searchContent). Returns the raw `sys` + `fields` payload. Reference fields stay as their key strings — call getEntry again to expand them.',\n inputSchema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Filename stem, e.g. \"post-abc\".' },\n collection: {\n type: 'string',\n description: 'Optional collection name. If omitted, the tool searches all collections by id (slower).',\n },\n },\n required: ['id'],\n },\n },\n async run(input, ctx) {\n const { id, collection } = (input ?? {}) as { id?: unknown; collection?: unknown };\n if (typeof id !== 'string' || !id.trim()) {\n return JSON.stringify({ error: 'id is required and must be a non-empty string' });\n }\n const cleanId = id.trim().replace(/\\.json$/, '');\n const { getFile, getContentFiles } =\n (await import('../../admin/actions/files')) as typeof import('../../admin/actions/files');\n\n const colName = typeof collection === 'string' && collection.trim() ? collection.trim() : undefined;\n if (colName && !ctx.config.collections[colName as keyof typeof ctx.config.collections]) {\n return JSON.stringify({ error: `Unknown collection: ${colName}` });\n }\n\n const candidates = colName ? [colName] : Object.keys(ctx.config.collections);\n\n for (const c of candidates) {\n const entries = await getContentFiles(c).catch(() => [] as string[]);\n const match = entries.find((p) => {\n const stem = p\n .split('/')\n .pop()\n ?.replace(/\\.json$/, '');\n return stem === cleanId;\n });\n if (!match) continue;\n try {\n const payload = await getFile(match);\n return JSON.stringify({ path: match, entry: payload });\n } catch (err) {\n return JSON.stringify({\n error: `Failed to read entry: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n return JSON.stringify({ error: `No entry found with id \"${cleanId}\"` });\n },\n};\n\nconst proposeEditTool: ToolHandler = {\n definition: {\n name: 'proposeEdit',\n description:\n 'Propose changes to an existing entry. The user must explicitly accept the proposal in the UI before any write happens — you cannot save anything yourself. Always run `searchContent` and/or `getEntry` first to confirm the exact entry id and the existing field values you intend to change.',\n inputSchema: {\n type: 'object',\n properties: {\n entryId: {\n type: 'string',\n description: 'Filename stem of the entry to edit, e.g. \"post-abc\". Must match an existing entry.',\n },\n collection: {\n type: 'string',\n description: 'The collection the entry belongs to (e.g. \"post\"). Must match the entry.',\n },\n fieldChanges: {\n type: 'object',\n description:\n 'Object of fieldName → new value. Only include fields you want to change. For markdown fields pass the full new body as a string. For reference (cardinality:many) fields pass an array of filename stems. Existing fields you omit stay as-is.',\n additionalProperties: true,\n },\n reasoning: {\n type: 'string',\n description: 'One sentence explaining why this change. Shown to the user verbatim on the approval card.',\n },\n },\n required: ['entryId', 'collection', 'fieldChanges', 'reasoning'],\n },\n },\n async run(input, ctx) {\n const { entryId, collection, fieldChanges, reasoning } = (input ?? {}) as {\n entryId?: unknown;\n collection?: unknown;\n fieldChanges?: unknown;\n reasoning?: unknown;\n };\n if (typeof entryId !== 'string' || !entryId.trim()) {\n return JSON.stringify({ ok: false, error: 'entryId is required (filename stem like \"post-abc\")' });\n }\n if (typeof collection !== 'string' || !collection.trim()) {\n return JSON.stringify({ ok: false, error: 'collection is required' });\n }\n if (!fieldChanges || typeof fieldChanges !== 'object' || Array.isArray(fieldChanges)) {\n return JSON.stringify({ ok: false, error: 'fieldChanges must be an object of fieldName → new value' });\n }\n const reasoningStr = typeof reasoning === 'string' ? reasoning.trim() : '';\n if (!reasoningStr) {\n return JSON.stringify({ ok: false, error: 'reasoning is required (one sentence)' });\n }\n\n const cleanCollection = collection.trim();\n if (!(cleanCollection in ctx.config.collections)) {\n return JSON.stringify({ ok: false, error: `Unknown collection: ${cleanCollection}` });\n }\n\n const cleanId = entryId.trim().replace(/\\.json$/, '');\n const entryPath = await resolveEntryPath(cleanCollection, cleanId, ctx.config);\n if (!entryPath) {\n return JSON.stringify({ ok: false, error: `Entry \"${cleanId}\" not found in collection \"${cleanCollection}\".` });\n }\n\n // Re-validate the merged result against the schema. We need the existing\n // entry to merge against so we don't trip required-field checks on fields\n // the model isn't touching.\n const { getFile } = (await import('../../admin/actions/files')) as typeof import('../../admin/actions/files');\n let existing: { fields?: Record<string, unknown> };\n try {\n existing = await getFile(entryPath);\n } catch (err) {\n return JSON.stringify({\n ok: false,\n error: `Failed to read entry: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n const merged = { ...existing.fields, ...(fieldChanges as Record<string, unknown>) };\n const stringFields = fieldsToFormStrings(merged);\n\n const { validateEntryFields } =\n (await import('../../lib/validateEntryFields')) as typeof import('../../lib/validateEntryFields');\n const validation = validateEntryFields(cleanCollection, stringFields);\n if (!validation.ok) {\n return JSON.stringify({\n ok: false,\n error: 'Validation failed — fix the field values and try again.',\n fieldErrors: validation.fieldErrors,\n });\n }\n\n const summary = describeEditSummary(cleanCollection, cleanId, fieldChanges as Record<string, unknown>);\n const proposal: EditProposal = {\n id: `prop_${randomUUID()}`,\n kind: 'edit',\n toolUseId: ctx.toolUseId ?? '',\n collection: cleanCollection,\n entryPath,\n entryId: cleanId,\n fieldChanges: fieldChanges as Record<string, unknown>,\n reasoning: reasoningStr,\n summary,\n };\n return {\n message: JSON.stringify({\n ok: true,\n proposalId: proposal.id,\n summary,\n awaitingApproval: true,\n note: 'Proposal emitted. The user will accept or reject it in the UI — do NOT propose the same change again.',\n }),\n proposal,\n };\n },\n};\n\nconst proposeNewEntryTool: ToolHandler = {\n definition: {\n name: 'proposeNewEntry',\n description:\n 'Propose a brand-new entry in a collection. The user must explicitly accept the proposal in the UI before any write happens. Use `listCollections` first if you are not sure of the available fields.',\n inputSchema: {\n type: 'object',\n properties: {\n collection: { type: 'string', description: 'Collection name to create the entry in.' },\n fields: {\n type: 'object',\n description:\n 'Full proposed `fields` object. Required fields must be present. For markdown fields pass the full body as a string. For reference (cardinality:many) fields pass an array of filename stems.',\n additionalProperties: true,\n },\n reasoning: {\n type: 'string',\n description: 'One sentence explaining why this entry. Shown verbatim on the card.',\n },\n },\n required: ['collection', 'fields', 'reasoning'],\n },\n },\n async run(input, ctx) {\n const { collection, fields, reasoning } = (input ?? {}) as {\n collection?: unknown;\n fields?: unknown;\n reasoning?: unknown;\n };\n if (typeof collection !== 'string' || !collection.trim()) {\n return JSON.stringify({ ok: false, error: 'collection is required' });\n }\n if (!fields || typeof fields !== 'object' || Array.isArray(fields)) {\n return JSON.stringify({ ok: false, error: 'fields must be an object' });\n }\n const reasoningStr = typeof reasoning === 'string' ? reasoning.trim() : '';\n if (!reasoningStr) {\n return JSON.stringify({ ok: false, error: 'reasoning is required (one sentence)' });\n }\n\n const cleanCollection = collection.trim();\n if (!(cleanCollection in ctx.config.collections)) {\n return JSON.stringify({ ok: false, error: `Unknown collection: ${cleanCollection}` });\n }\n\n const stringFields = fieldsToFormStrings(fields as Record<string, unknown>);\n const { validateEntryFields } =\n (await import('../../lib/validateEntryFields')) as typeof import('../../lib/validateEntryFields');\n const validation = validateEntryFields(cleanCollection, stringFields);\n if (!validation.ok) {\n return JSON.stringify({\n ok: false,\n error: 'Validation failed — fix the field values and try again.',\n fieldErrors: validation.fieldErrors,\n });\n }\n\n const summary = describeCreateSummary(cleanCollection, fields as Record<string, unknown>);\n const proposal: CreateProposal = {\n id: `prop_${randomUUID()}`,\n kind: 'create',\n toolUseId: ctx.toolUseId ?? '',\n collection: cleanCollection,\n fields: fields as Record<string, unknown>,\n reasoning: reasoningStr,\n summary,\n };\n return {\n message: JSON.stringify({\n ok: true,\n proposalId: proposal.id,\n summary,\n awaitingApproval: true,\n note: 'Proposal emitted. The user will accept or reject it in the UI — do NOT propose the same entry again.',\n }),\n proposal,\n };\n },\n};\n\n/**\n * Phase 5 — match an uploaded document to a CMS entry.\n *\n * Two-tier strategy:\n * 1. URL hint match — if the user provides a URL or path, walk every\n * collection's `routeTemplate` (e.g. `'/blog/[slug]'`) and try to extract\n * field values. If the matched fields point at a real entry, return that\n * entry as the highest-confidence candidate.\n * 2. Search fallback — embed the document text and run `searchContent` over\n * the existing embeddings index. Returns the top hits.\n *\n * The model gets a ranked list with a `matchedBy` reason on each candidate\n * so it can surface them to the user and ask which one to update.\n */\nconst findEntryForDocumentTool: ToolHandler = {\n definition: {\n name: 'findEntryForDocument',\n description:\n 'Given the text of an uploaded document (and optionally a URL hint), suggest CMS entries that the document is most likely about. Returns ranked candidates with a reason for the match. Use this BEFORE proposing edits when the user uploads a PDF / DOCX without naming a specific entry.',\n inputSchema: {\n type: 'object',\n properties: {\n documentText: {\n type: 'string',\n description:\n 'The extracted text from the uploaded document — typically the first 1–2 paragraphs are enough to disambiguate.',\n },\n hintUrl: {\n type: 'string',\n description:\n \"Optional URL or path the user mentioned, e.g. '/blog/my-post'. When set, exact matches against any collection's `routeTemplate` rank highest.\",\n },\n k: {\n type: 'integer',\n description: 'Number of search-fallback candidates to return (1–10). Defaults to 5.',\n minimum: 1,\n maximum: 10,\n },\n },\n required: ['documentText'],\n },\n },\n async run(input, ctx) {\n const { documentText, hintUrl, k } = (input ?? {}) as {\n documentText?: unknown;\n hintUrl?: unknown;\n k?: unknown;\n };\n if (typeof documentText !== 'string' || !documentText.trim()) {\n return JSON.stringify({ error: 'documentText is required and must be a non-empty string' });\n }\n const limit = typeof k === 'number' ? Math.max(1, Math.min(10, Math.floor(k))) : 5;\n\n const candidates: Array<{\n id: string;\n path: string;\n collection: string;\n score: number;\n title: string;\n excerpt: string;\n matchedBy: 'routeTemplate' | 'search';\n }> = [];\n\n // 1) URL-hint matching against any collection's routeTemplate.\n if (typeof hintUrl === 'string' && hintUrl.trim()) {\n const cleanHint = hintUrl.trim();\n for (const [collectionName, collection] of Object.entries(ctx.config.collections)) {\n const template = (collection as { routeTemplate?: string }).routeTemplate;\n if (!template) continue;\n const fieldValues = matchRouteTemplate(template, cleanHint);\n if (!fieldValues) continue;\n const match = await findEntryByFieldValues(collectionName, fieldValues, ctx);\n if (match) {\n candidates.push({ ...match, matchedBy: 'routeTemplate' });\n }\n }\n }\n\n // 2) Search fallback — embed the document text and rank entries.\n const queryText = documentText.trim().slice(0, 2000);\n try {\n const hits = await searchContent(queryText, {\n k: limit,\n branch: ctx.branch,\n });\n for (const h of hits) {\n if (candidates.some((c) => c.path === h.path)) continue;\n candidates.push({ ...h, matchedBy: 'search' });\n }\n } catch (err) {\n return JSON.stringify({\n error: `Search fallback failed: ${err instanceof Error ? err.message : String(err)}`,\n candidates,\n });\n }\n\n if (candidates.length === 0) {\n return JSON.stringify({\n candidates: [],\n note: 'No candidates found — verify the document has searchable text, or ask the user which entry to update.',\n });\n }\n\n return JSON.stringify({\n candidates: candidates.map((c) => ({\n id: c.id,\n path: c.path,\n collection: c.collection,\n title: c.title,\n score: Number(c.score.toFixed(4)),\n excerpt: c.excerpt,\n matchedBy: c.matchedBy,\n })),\n });\n },\n};\n\n/**\n * Match a route template like `/blog/[slug]` (or `/items/[id]/[lang]`) against\n * a literal URL/path. Returns an object mapping each placeholder to the\n * captured value, or `null` if the template doesn't match. Query strings and\n * trailing slashes are ignored. Exposed for unit tests.\n */\nexport function matchRouteTemplate(template: string, url: string): Record<string, string> | null {\n // Drop scheme + host: '/blog/foo?x=1' → '/blog/foo'\n let path = url;\n const protoIdx = path.indexOf('://');\n if (protoIdx !== -1) {\n const slash = path.indexOf('/', protoIdx + 3);\n path = slash === -1 ? '/' : path.slice(slash);\n }\n const queryIdx = path.indexOf('?');\n if (queryIdx !== -1) path = path.slice(0, queryIdx);\n\n const norm = (s: string) => s.replace(/\\/+$/, '') || '/';\n const tplParts = norm(template).split('/');\n const urlParts = norm(path).split('/');\n if (tplParts.length !== urlParts.length) return null;\n\n const out: Record<string, string> = {};\n for (let i = 0; i < tplParts.length; i++) {\n const tp = tplParts[i];\n const up = urlParts[i];\n const m = tp.match(/^\\[(.+)\\]$/);\n if (m) {\n if (!up) return null;\n out[m[1]] = decodeURIComponent(up);\n } else if (tp !== up) {\n return null;\n }\n }\n return out;\n}\n\nasync function findEntryByFieldValues(\n collectionName: string,\n fieldValues: Record<string, string>,\n ctx: ToolContext,\n): Promise<{ id: string; path: string; collection: string; score: number; title: string; excerpt: string } | null> {\n const { getFile, getContentFiles } =\n (await import('../../admin/actions/files')) as typeof import('../../admin/actions/files');\n const { resolveEntryTitle, resolveEntryId, buildEntryExcerpt } =\n (await import('../../lib/resolveEntryTitle')) as typeof import('../../lib/resolveEntryTitle');\n\n const entries = await getContentFiles(collectionName).catch(() => [] as string[]);\n for (const p of entries) {\n let payload: { sys?: { id?: unknown; type?: unknown }; fields?: Record<string, unknown> };\n try {\n payload = (await getFile(p)) as typeof payload;\n } catch {\n continue;\n }\n let allMatch = true;\n for (const [key, expected] of Object.entries(fieldValues)) {\n const actual = payload.fields?.[key];\n if (typeof actual !== 'string' || actual !== expected) {\n // Also accept matching against the filename stem when the placeholder is `id`.\n if (key === 'id') {\n const stem = p\n .split('/')\n .pop()\n ?.replace(/\\.json$/, '');\n if (stem === expected) continue;\n }\n allMatch = false;\n break;\n }\n }\n if (!allMatch) continue;\n return {\n id: resolveEntryId(ctx.config, p, payload),\n path: p,\n collection: collectionName,\n score: 1,\n title: resolveEntryTitle(ctx.config, p, payload),\n excerpt: buildEntryExcerpt(ctx.config, p, payload),\n };\n }\n return null;\n}\n\nexport const READ_ONLY_TOOLS: ToolHandler[] = [\n searchContentTool,\n listCollectionsTool,\n getEntryTool,\n findEntryForDocumentTool,\n];\n\nexport const PROPOSAL_TOOLS: ToolHandler[] = [proposeEditTool, proposeNewEntryTool];\n\nexport const ALL_TOOLS: ToolHandler[] = [...READ_ONLY_TOOLS, ...PROPOSAL_TOOLS];\n\nexport function getToolHandler(name: string): ToolHandler | undefined {\n return ALL_TOOLS.find((t) => t.definition.name === name);\n}\n\nexport function getToolDefinitions(): NormalizedTool[] {\n return ALL_TOOLS.map((t) => t.definition);\n}\n\n// Re-exported so callers don't need to reach into `proposals.ts` for the\n// server-side accept handler.\nexport { _acceptProposal as acceptProposal };\n","/**\n * Proposal types + the server-side accept handler shared by the\n * `/api/agent/proposals/accept` route and (in tests) direct callers.\n *\n * Phase 4 of the chat agent. Mutating tool calls (`proposeEdit`,\n * `proposeNewEntry`) never touch content directly — they emit proposal\n * objects that the user accepts or rejects in the UI. The actual write\n * happens here, on the stateless accept endpoint, which re-validates the\n * payload before calling `saveFile` / `newFile`.\n *\n * The proposal payload travels:\n * tool handler → SSE `proposal` event → client React state → POST /accept\n *\n * Server state is intentionally NOT kept between the SSE stream and the\n * accept endpoint — Vercel-safe, see RAG_PLAN.md Phase 4.\n */\nimport type { Config } from '../types';\n\n/** Common fields on every proposal. */\ntype ProposalBase = {\n /** Stable id for UI keying — generated server-side, not used by the accept endpoint. */\n id: string;\n /** Tool-use id that emitted the proposal. Lets the UI correlate cards with their tool call. */\n toolUseId: string;\n /** One-sentence rationale from the model — surfaced verbatim on the card. */\n reasoning: string;\n /** Short human-readable label, e.g. \"Edit post 'My title' (title, body)\". */\n summary: string;\n};\n\nexport type EditProposal = ProposalBase & {\n kind: 'edit';\n collection: string;\n /** Full content path to the entry, e.g. `cms/content/post/post-abc.json`. */\n entryPath: string;\n /** Filename stem, e.g. `post-abc`. Surfaced for UI/citation only. */\n entryId: string;\n /** Object of fieldName → new raw value. Only the fields being changed. */\n fieldChanges: Record<string, unknown>;\n};\n\nexport type CreateProposal = ProposalBase & {\n kind: 'create';\n collection: string;\n /** Full proposed `fields` block for the new entry. */\n fields: Record<string, unknown>;\n};\n\nexport type Proposal = EditProposal | CreateProposal;\n\nexport type AcceptResult =\n | { ok: true; entryPath: string }\n | { ok: false; error: string; fieldErrors?: Record<string, string> };\n\n/**\n * Validate that an arbitrary deserialised body is a well-formed `Proposal`.\n * Used at the accept boundary to reject malformed client payloads before\n * `acceptProposal` runs schema validation.\n */\nexport function isProposal(p: unknown): p is Proposal {\n if (!p || typeof p !== 'object') return false;\n const obj = p as Record<string, unknown>;\n if (obj.kind !== 'edit' && obj.kind !== 'create') return false;\n if (typeof obj.collection !== 'string' || !obj.collection) return false;\n if (obj.kind === 'edit') {\n return (\n typeof obj.entryPath === 'string' &&\n !!obj.entryPath &&\n typeof obj.fieldChanges === 'object' &&\n obj.fieldChanges !== null\n );\n }\n return typeof obj.fields === 'object' && obj.fields !== null;\n}\n\n/**\n * Coerce arbitrary field values to strings so that `validateEntryFields` and\n * `saveFile` (which both expect form-style strings) can consume them.\n *\n * Mirrors the same coercion `saveFile` does internally on the form payload.\n */\nexport function fieldsToFormStrings(fields: Record<string, unknown>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(fields)) {\n if (v == null) {\n out[k] = '';\n } else if (typeof v === 'object') {\n out[k] = JSON.stringify(v);\n } else {\n out[k] = String(v);\n }\n }\n return out;\n}\n\n/**\n * Locate the on-disk path for an entry given its filename stem and collection.\n * Returns `null` if no match. Used by `proposeEdit` to validate that the model\n * referenced a real entry before emitting a proposal.\n */\nexport async function resolveEntryPath(collection: string, entryId: string, config: Config): Promise<string | null> {\n if (!(collection in config.collections)) return null;\n const cleanId = entryId.trim().replace(/\\.json$/, '');\n const { getContentFiles } = (await import('../admin/actions/files')) as typeof import('../admin/actions/files');\n const entries = await getContentFiles(collection).catch(() => [] as string[]);\n const match = entries.find((p) => {\n const stem = p\n .split('/')\n .pop()\n ?.replace(/\\.json$/, '');\n return stem === cleanId;\n });\n return match ?? null;\n}\n\n/**\n * Server-side execution of an accepted proposal. Re-validates the payload,\n * then runs the corresponding write action. Stateless — does not trust any\n * server-side memory of the proposal; everything is re-checked from the\n * payload + current entry state on disk.\n */\nexport async function acceptProposal(proposal: Proposal): Promise<AcceptResult> {\n const { saveFile, newFile, getFile } =\n (await import('../admin/actions/files')) as typeof import('../admin/actions/files');\n\n if (proposal.kind === 'edit') {\n let existing: { sys?: Record<string, unknown>; fields?: Record<string, unknown> };\n try {\n existing = await getFile(proposal.entryPath);\n } catch (err) {\n return {\n ok: false,\n error: `Could not read entry at ${proposal.entryPath}: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n if (!existing || !existing.sys) {\n return { ok: false, error: `Entry ${proposal.entryPath} not found.` };\n }\n const mergedFields = { ...existing.fields, ...proposal.fieldChanges };\n const payload = { sys: existing.sys, fields: mergedFields };\n const result = await saveFile(payload as Parameters<typeof saveFile>[0], proposal.entryPath);\n if (!result.success) {\n return {\n ok: false,\n error: result.error,\n ...(result.fieldErrors ? { fieldErrors: result.fieldErrors } : {}),\n };\n }\n return { ok: true, entryPath: proposal.entryPath };\n }\n\n // kind === 'create'\n const created = await newFile(proposal.collection);\n if (!created.success) {\n return { ok: false, error: created.error };\n }\n let existing: { sys?: Record<string, unknown>; fields?: Record<string, unknown> };\n try {\n existing = await getFile(created.path);\n } catch (err) {\n return {\n ok: false,\n error: `Created entry but could not re-read it at ${created.path}: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n const mergedFields = { ...existing.fields, ...proposal.fields };\n const payload = { sys: existing.sys, fields: mergedFields };\n const saved = await saveFile(payload as Parameters<typeof saveFile>[0], created.path);\n if (!saved.success) {\n return {\n ok: false,\n error: saved.error,\n ...(saved.fieldErrors ? { fieldErrors: saved.fieldErrors } : {}),\n };\n }\n return { ok: true, entryPath: created.path };\n}\n\n/**\n * Build a short human label for an edit proposal. Used for the chat card and\n * the model-facing tool result.\n */\nexport function describeEditSummary(\n collection: string,\n entryId: string,\n fieldChanges: Record<string, unknown>,\n): string {\n const fields = Object.keys(fieldChanges);\n const list = fields.length > 3 ? `${fields.slice(0, 3).join(', ')}, +${fields.length - 3} more` : fields.join(', ');\n return `Edit ${collection} ${entryId}${list ? ` (${list})` : ''}`;\n}\n\n/** Build a short human label for a create proposal. */\nexport function describeCreateSummary(collection: string, fields: Record<string, unknown>): string {\n const fieldCount = Object.keys(fields).length;\n return `Create new ${collection} (${fieldCount} field${fieldCount === 1 ? '' : 's'} set)`;\n}\n","/**\n * Agent loop — drives one or more provider turns until the model says\n * `end_turn` or a budget cap is hit.\n *\n * The function is a single async generator. Callers (the SSE route handler)\n * await each event and forward it to the client. After every turn the loop\n * decides whether to run tools and feed results back as a new user message\n * (the `tool` role on our normalised wire — see provider adapters).\n */\nimport type { Config } from '../types';\nimport type { ChatProvider, NormalizedContentBlock, NormalizedMessage, NormalizedTool } from './providers/types';\nimport type { AgentConfig } from './types';\nimport type { Proposal } from './proposals';\nimport { estimateCostUSD } from './pricing';\nimport { recordTurn } from './usage';\nimport { getToolDefinitions, getToolHandler } from './tools';\n\nexport type ChatEvent =\n | { type: 'text_delta'; text: string }\n | { type: 'tool_use_start'; id: string; name: string }\n | { type: 'tool_use_input_delta'; id: string; partialJson: string }\n | { type: 'tool_use_complete'; id: string; name: string; input: unknown }\n | { type: 'tool_result'; toolUseId: string; name: string; result: string; isError?: boolean }\n | { type: 'proposal'; proposal: Proposal }\n | { type: 'turn_stop'; stopReason: 'end_turn' | 'tool_use' | 'max_tokens' | 'stop_sequence' | 'other' }\n | {\n type: 'usage';\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens?: number;\n costUSDDelta: number;\n totalCostUSD: number;\n }\n | { type: 'budget_exceeded'; reason: 'input_tokens' | 'output_tokens' | 'spend' | 'max_turns' | 'proposal_cap' }\n | { type: 'done' }\n | { type: 'error'; message: string };\n\nexport type RunChatInput = {\n agentConfig: AgentConfig;\n config: Config;\n systemPrompt: string;\n messages: NormalizedMessage[];\n provider: ChatProvider;\n tools?: NormalizedTool[];\n branch?: string;\n /** Hard ceiling on agent loop iterations. Defaults to 10. */\n maxTurns?: number;\n};\n\nexport async function* runChat(input: RunChatInput): AsyncGenerator<ChatEvent> {\n const tools = input.tools ?? getToolDefinitions();\n const maxTurns = input.maxTurns ?? 10;\n\n // Conversation state mutated across turns. We keep a copy so the caller's\n // array isn't mutated.\n const messages: NormalizedMessage[] = [...input.messages];\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n\n for (let turn = 0; turn < maxTurns; turn++) {\n const stream = input.provider.streamChat({\n messages,\n tools,\n systemPrompt: input.systemPrompt,\n maxOutputTokens: input.agentConfig.maxOutputTokens,\n });\n\n const assistantBlocks: NormalizedContentBlock[] = [];\n let currentText = '';\n const pendingToolCalls: { id: string; name: string; input: unknown }[] = [];\n let stopReason: 'end_turn' | 'tool_use' | 'max_tokens' | 'stop_sequence' | 'other' = 'other';\n let usage = { inputTokens: 0, outputTokens: 0, cachedInputTokens: 0 };\n let errored = false;\n\n for await (const ev of stream) {\n if (ev.type === 'error') {\n yield { type: 'error', message: ev.message };\n errored = true;\n break;\n }\n if (ev.type === 'text_delta') {\n currentText += ev.text;\n yield ev;\n continue;\n }\n if (ev.type === 'tool_use_start') {\n if (currentText) {\n assistantBlocks.push({ type: 'text', text: currentText });\n currentText = '';\n }\n yield ev;\n continue;\n }\n if (ev.type === 'tool_use_input_delta') {\n yield ev;\n continue;\n }\n if (ev.type === 'tool_use_complete') {\n assistantBlocks.push({ type: 'tool_use', id: ev.id, name: ev.name, input: ev.input });\n pendingToolCalls.push({ id: ev.id, name: ev.name, input: ev.input });\n yield ev;\n continue;\n }\n if (ev.type === 'message_stop') {\n if (currentText) {\n assistantBlocks.push({ type: 'text', text: currentText });\n currentText = '';\n }\n stopReason = ev.stopReason;\n usage = {\n inputTokens: ev.usage.inputTokens,\n outputTokens: ev.usage.outputTokens,\n cachedInputTokens: ev.usage.cachedInputTokens ?? 0,\n };\n }\n }\n\n if (errored) return;\n\n // Persist assistant turn into conversation history for any follow-up turn.\n messages.push({ role: 'assistant', content: assistantBlocks });\n\n // Bookkeeping — budget + usage event\n totalInputTokens += usage.inputTokens;\n totalOutputTokens += usage.outputTokens;\n const costDelta = estimateCostUSD(\n input.agentConfig,\n usage.inputTokens,\n usage.outputTokens,\n usage.cachedInputTokens,\n );\n const cumulative = recordTurn(input.agentConfig, {\n input: usage.inputTokens,\n output: usage.outputTokens,\n cachedInput: usage.cachedInputTokens,\n });\n yield {\n type: 'usage',\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n cachedInputTokens: usage.cachedInputTokens,\n costUSDDelta: costDelta,\n totalCostUSD: cumulative.costUSD,\n };\n\n yield { type: 'turn_stop', stopReason };\n\n if (totalInputTokens > input.agentConfig.maxInputTokens) {\n yield { type: 'budget_exceeded', reason: 'input_tokens' };\n return;\n }\n if (totalOutputTokens > input.agentConfig.maxOutputTokens) {\n yield { type: 'budget_exceeded', reason: 'output_tokens' };\n return;\n }\n\n // No tools requested — we're done.\n if (pendingToolCalls.length === 0) {\n yield { type: 'done' };\n return;\n }\n\n // Run each tool sequentially so the model sees a consistent ordering for\n // tools that depend on a previous tool's effect (e.g. `proposeEdit` after\n // `getEntry`).\n let proposalsThisTurn = 0;\n const proposalCap = input.agentConfig.maxProposalsPerTurn;\n for (const call of pendingToolCalls) {\n const handler = getToolHandler(call.name);\n let result: string;\n let isError = false;\n let proposal: Proposal | undefined;\n if (!handler) {\n result = JSON.stringify({ error: `Unknown tool: ${call.name}` });\n isError = true;\n } else {\n try {\n const ret = await handler.run(call.input, {\n config: input.config,\n branch: input.branch,\n toolUseId: call.id,\n });\n if (typeof ret === 'string') {\n result = ret;\n } else {\n result = ret.message;\n proposal = ret.proposal;\n }\n } catch (err) {\n result = JSON.stringify({ error: err instanceof Error ? err.message : String(err) });\n isError = true;\n }\n }\n\n if (proposal) {\n if (proposalsThisTurn >= proposalCap) {\n // Cap reached — drop the proposal and tell the model so it can stop\n // emitting more. The user already has `proposalCap` cards to deal with.\n result = JSON.stringify({\n ok: false,\n error: `Per-turn proposal cap reached (${proposalCap}). Stop emitting more — the user must accept or reject the existing cards before you propose anything else.`,\n });\n isError = true;\n } else {\n proposalsThisTurn += 1;\n // Stamp the wire-level toolUseId in case the handler used a placeholder.\n const stamped: Proposal = { ...proposal, toolUseId: call.id };\n yield { type: 'proposal', proposal: stamped };\n }\n }\n\n yield { type: 'tool_result', toolUseId: call.id, name: call.name, result, isError };\n messages.push({ role: 'tool', toolUseId: call.id, content: result, isError });\n }\n\n // Continue loop — feed tool results back to the model.\n }\n\n yield { type: 'budget_exceeded', reason: 'max_turns' };\n}\n","/**\n * Phase 5 — chat-agent file attachment processing.\n *\n * Pure server-side functions that turn raw uploaded files into normalised\n * content blocks suitable for any chat provider:\n *\n * - **DOCX (any provider)** → text via `mammoth`, prefixed with the filename.\n * - **PDF on Anthropic** → `document_pdf` block (native pass-through).\n * - **PDF on OpenAI / local** → text via `pdfjs-dist`, prefixed with filename.\n * - **Plain text / Markdown** → text block, prefixed with filename.\n *\n * Both extractor libraries (`mammoth`, `pdfjs-dist`) are optional peer\n * dependencies — they're loaded lazily so projects that don't use file\n * uploads don't pay for them.\n */\nimport type { NormalizedContentBlock } from './providers/types';\nimport type { AgentConfig } from './types';\n\n/**\n * Categorisation we apply to an uploaded file based on its filename + MIME\n * type. Drives the dispatch in {@link normalizeAttachments}.\n */\nexport type AttachmentKind = 'pdf' | 'docx' | 'text' | 'unsupported';\n\n/** Raw input — what the route handler hands to {@link normalizeAttachments}. */\nexport type RawAttachment = {\n filename: string;\n mediaType: string;\n /** Binary content. Should already be size-checked by the caller. */\n bytes: Uint8Array;\n};\n\n/** Result of attachment normalisation, including any skipped files. */\nexport type NormalizedAttachmentsResult = {\n blocks: NormalizedContentBlock[];\n /** Per-file outcome — useful for the route handler to relay back to the client. */\n diagnostics: AttachmentDiagnostic[];\n};\n\nexport type AttachmentDiagnostic =\n | { filename: string; status: 'ok'; kind: AttachmentKind; bytes: number }\n | { filename: string; status: 'skipped'; reason: string };\n\n/** Decide what kind of file we're dealing with from filename + MIME. */\nexport function classifyAttachment(filename: string, mediaType: string): AttachmentKind {\n const lowered = filename.toLowerCase();\n const mt = (mediaType || '').toLowerCase();\n if (mt === 'application/pdf' || lowered.endsWith('.pdf')) return 'pdf';\n if (mt === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || lowered.endsWith('.docx')) {\n return 'docx';\n }\n if (mt.startsWith('text/') || lowered.endsWith('.txt') || lowered.endsWith('.md') || lowered.endsWith('.markdown')) {\n return 'text';\n }\n return 'unsupported';\n}\n\n/** Validate a file against the per-attachment limit. Returns null if ok. */\nexport function checkAttachmentSize(bytes: number, config: Pick<AgentConfig, 'maxAttachmentBytes'>): string | null {\n if (bytes > config.maxAttachmentBytes) {\n return `File exceeds the ${formatBytes(config.maxAttachmentBytes)} per-file limit (got ${formatBytes(bytes)}).`;\n }\n return null;\n}\n\n/** Validate the count of attachments against the per-turn cap. */\nexport function checkAttachmentCount(count: number, config: Pick<AgentConfig, 'maxAttachmentsPerTurn'>): string | null {\n if (count > config.maxAttachmentsPerTurn) {\n return `Too many attachments — limit is ${config.maxAttachmentsPerTurn} per turn (got ${count}).`;\n }\n return null;\n}\n\nfunction formatBytes(n: number): string {\n if (n >= 1024 * 1024) return `${(n / (1024 * 1024)).toFixed(1)} MB`;\n if (n >= 1024) return `${(n / 1024).toFixed(1)} KB`;\n return `${n} B`;\n}\n\n/** Tag a text snippet so the model knows it came from an attachment. */\nexport function wrapAttachmentText(filename: string, text: string): string {\n return `[Attached document: ${filename}]\\n\\n${text}`;\n}\n\n/**\n * Convert a list of raw attachments into normalised content blocks for the\n * given provider's PDF capability. PDF behaviour depends on\n * `supportsNativePdf`; everything else is text either way.\n *\n * Errors during extraction (corrupt files, missing peer deps) are reported\n * as `skipped` diagnostics — the chat continues without that attachment so a\n * single bad file doesn't break the whole turn.\n */\nexport async function normalizeAttachments(\n attachments: RawAttachment[],\n options: {\n supportsNativePdf: boolean;\n /** Test seam — inject extractors directly. */\n extractDocxText?: (bytes: Uint8Array) => Promise<string>;\n extractPdfText?: (bytes: Uint8Array) => Promise<string>;\n },\n): Promise<NormalizedAttachmentsResult> {\n const blocks: NormalizedContentBlock[] = [];\n const diagnostics: AttachmentDiagnostic[] = [];\n\n const extractDocx = options.extractDocxText ?? extractDocxTextDefault;\n const extractPdf = options.extractPdfText ?? extractPdfTextDefault;\n\n for (const att of attachments) {\n const kind = classifyAttachment(att.filename, att.mediaType);\n\n if (kind === 'unsupported') {\n diagnostics.push({\n filename: att.filename,\n status: 'skipped',\n reason: `Unsupported file type \"${att.mediaType || 'unknown'}\". Allowed: PDF, DOCX, .txt, .md.`,\n });\n continue;\n }\n\n if (kind === 'text') {\n const text = bytesToString(att.bytes);\n blocks.push({ type: 'text', text: wrapAttachmentText(att.filename, text) });\n diagnostics.push({ filename: att.filename, status: 'ok', kind, bytes: att.bytes.length });\n continue;\n }\n\n if (kind === 'docx') {\n try {\n const text = await extractDocx(att.bytes);\n blocks.push({ type: 'text', text: wrapAttachmentText(att.filename, text) });\n diagnostics.push({ filename: att.filename, status: 'ok', kind, bytes: att.bytes.length });\n } catch (err) {\n diagnostics.push({\n filename: att.filename,\n status: 'skipped',\n reason: `DOCX extraction failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n continue;\n }\n\n // kind === 'pdf'\n if (options.supportsNativePdf) {\n blocks.push({\n type: 'document_pdf',\n base64: bytesToBase64(att.bytes),\n mediaType: 'application/pdf',\n filename: att.filename,\n });\n diagnostics.push({ filename: att.filename, status: 'ok', kind, bytes: att.bytes.length });\n continue;\n }\n\n try {\n const text = await extractPdf(att.bytes);\n blocks.push({ type: 'text', text: wrapAttachmentText(att.filename, text) });\n diagnostics.push({ filename: att.filename, status: 'ok', kind, bytes: att.bytes.length });\n } catch (err) {\n diagnostics.push({\n filename: att.filename,\n status: 'skipped',\n reason: `PDF text extraction failed: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n }\n\n return { blocks, diagnostics };\n}\n\nfunction bytesToString(bytes: Uint8Array): string {\n return new TextDecoder('utf-8', { fatal: false }).decode(bytes);\n}\n\nfunction bytesToBase64(bytes: Uint8Array): string {\n // Buffer is the most reliable way to get base64 in Node — avoids\n // String.fromCharCode chunk-size limits.\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(bytes).toString('base64');\n }\n // Browser fallback (the chat agent runs server-side, so this is mostly\n // for shared utilities — kept simple to stay dependency-free).\n let binary = '';\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return btoa(binary);\n}\n\nasync function extractDocxTextDefault(bytes: Uint8Array): Promise<string> {\n let mammoth: typeof import('mammoth');\n try {\n mammoth = (await import('mammoth')) as unknown as typeof import('mammoth');\n } catch {\n throw new Error(\"Optional peer dependency 'mammoth' is not installed. Run: npm install mammoth\");\n }\n // mammoth's `extractRawText` is happy with a `{ buffer }` input — Buffer is\n // a Uint8Array subclass in Node, so this works without a copy.\n const buffer = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes);\n const result = await mammoth.extractRawText({ buffer });\n return result.value || '';\n}\n\nasync function extractPdfTextDefault(bytes: Uint8Array): Promise<string> {\n type PdfJsModule = {\n getDocument: (params: { data: Uint8Array }) => { promise: Promise<PdfDocument> };\n GlobalWorkerOptions?: { workerSrc?: string };\n };\n type PdfDocument = {\n numPages: number;\n getPage(pageNumber: number): Promise<PdfPage>;\n destroy?(): Promise<void>;\n };\n type PdfPage = {\n getTextContent(): Promise<{ items: Array<{ str?: string }> }>;\n };\n\n let pdfjs: PdfJsModule;\n try {\n // Use the legacy build — the modern build assumes a browser environment\n // (DOMMatrix / OffscreenCanvas) that Node does not provide. The legacy\n // build is the one Mozilla ships specifically for Node.\n pdfjs = (await import('pdfjs-dist/legacy/build/pdf.mjs')) as unknown as PdfJsModule;\n } catch {\n try {\n pdfjs = (await import('pdfjs-dist')) as unknown as PdfJsModule;\n } catch {\n throw new Error(\"Optional peer dependency 'pdfjs-dist' is not installed. Run: npm install pdfjs-dist\");\n }\n }\n\n // Disable worker — server-side we run in the main thread.\n if (pdfjs.GlobalWorkerOptions) pdfjs.GlobalWorkerOptions.workerSrc = '';\n\n // Pass a copy because pdf.js mutates the buffer it receives.\n const data = new Uint8Array(bytes.length);\n data.set(bytes);\n const doc = await pdfjs.getDocument({ data }).promise;\n\n const lines: string[] = [];\n for (let i = 1; i <= doc.numPages; i++) {\n const page = await doc.getPage(i);\n const content = await page.getTextContent();\n const pageText = content.items.map((it) => it.str ?? '').join(' ');\n lines.push(pageText.trim());\n }\n if (typeof doc.destroy === 'function') {\n try {\n await doc.destroy();\n } catch {\n /* best-effort */\n }\n }\n return lines.join('\\n\\n');\n}\n","/**\n * Packaged Route Handler for the chat-agent SSE endpoint.\n *\n * Lives inside `octocms/agent` so the user app keeps a thin re-export at\n * `app/api/agent/route.ts` (scaffolded by `octocms init` and `octocms update`,\n * see `octocms/cli/lib/templates.ts` → `agentChatRouteTemplate`). The user\n * file's only job is to side-effect-import `cms/__generated__/configInit` (so\n * `getAgentConfig()` resolves on cold start) and re-export {@link chatRoute}\n * as `POST`.\n *\n * **Stateless**: each request carries the full message history and any\n * uploaded attachments. Vercel-safe — no temp files, no cross-request memory.\n *\n * **Abort handling**: the request's `signal` is forwarded into a per-request\n * `AbortController`. The agent loop checks it between turns; the SSE stream\n * also cancels naturally when the client disconnects.\n */\nimport { getServerSession } from 'next-auth/next';\nimport { cookies } from 'next/headers';\n\nimport { authOptions } from '../admin/auth';\nimport { getConfig } from '../lib/configStore';\n\nimport {\n checkAttachmentCount,\n checkAttachmentSize,\n normalizeAttachments,\n type AttachmentDiagnostic,\n type RawAttachment,\n} from './attachments';\nimport { runChat, type ChatEvent } from './chat';\nimport { getAgentConfig } from './configStore';\nimport { isAgentEnabled } from './featureFlag';\nimport { getChatProvider } from './providers';\nimport type { NormalizedContentBlock, NormalizedMessage } from './providers/types';\nimport { buildSystemPrompt, type StyleExemplar } from './systemPrompt';\n\nconst CMS_ACTIVE_BRANCH_COOKIE = 'cms-active-branch';\n\ntype ChatRequestBody = {\n messages?: NormalizedMessage[];\n styleExemplars?: StyleExemplar[];\n};\n\nfunction notFound(): Response {\n return new Response(null, { status: 404 });\n}\n\nfunction unauthorized(): Response {\n return new Response(JSON.stringify({ error: 'Unauthorized' }), {\n status: 401,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nfunction badRequest(message: string): Response {\n return new Response(JSON.stringify({ error: message }), {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\n/**\n * `POST /api/agent` — streams the chat response as SSE. Accepts both JSON\n * (no attachments — Phase 3/4 behaviour) and `multipart/form-data` (Phase 5,\n * with files). Auth-gated; 404 when the agent feature is disabled for this\n * deploy.\n */\nexport async function chatRoute(request: Request): Promise<Response> {\n const agentConfig = getAgentConfig();\n if (!agentConfig || !isAgentEnabled(agentConfig)) return notFound();\n\n const session = await getServerSession(authOptions);\n if (!session) return unauthorized();\n\n // Two body formats: JSON (no attachments — Phase 3/4 behaviour) and\n // multipart/form-data (Phase 5, with files). Detect via Content-Type.\n const contentType = request.headers.get('content-type') ?? '';\n let body: ChatRequestBody;\n let rawAttachments: RawAttachment[] = [];\n if (contentType.includes('multipart/form-data')) {\n let form: FormData;\n try {\n form = await request.formData();\n } catch {\n return badRequest('Multipart body could not be parsed.');\n }\n const messagesField = form.get('messages');\n const exemplarsField = form.get('styleExemplars');\n try {\n body = {\n messages: typeof messagesField === 'string' ? (JSON.parse(messagesField) as NormalizedMessage[]) : [],\n styleExemplars:\n typeof exemplarsField === 'string' ? (JSON.parse(exemplarsField) as StyleExemplar[]) : undefined,\n };\n } catch {\n return badRequest('`messages` (and `styleExemplars`) must be JSON-encoded form fields.');\n }\n rawAttachments = await collectFormAttachments(form);\n } else {\n try {\n body = (await request.json()) as ChatRequestBody;\n } catch {\n return badRequest('Body must be JSON.');\n }\n }\n const messages = Array.isArray(body.messages) ? body.messages : [];\n if (messages.length === 0) return badRequest('`messages` must be a non-empty array.');\n\n const countError = checkAttachmentCount(rawAttachments.length, agentConfig);\n if (countError) return badRequest(countError);\n for (const a of rawAttachments) {\n const sizeError = checkAttachmentSize(a.bytes.length, agentConfig);\n if (sizeError) return badRequest(`${a.filename}: ${sizeError}`);\n }\n\n const config = getConfig();\n const branch = (await cookies()).get(CMS_ACTIVE_BRANCH_COOKIE)?.value || undefined;\n\n let provider;\n try {\n provider = getChatProvider(agentConfig.provider);\n } catch (err) {\n return badRequest(err instanceof Error ? err.message : 'Failed to initialise chat provider.');\n }\n\n // Phase 5: turn raw uploads into normalised content blocks (PDF passes\n // through natively to Anthropic; everything else is text). Append them to\n // the LAST user message so the model sees them in the right turn.\n let attachmentDiagnostics: AttachmentDiagnostic[] = [];\n if (rawAttachments.length > 0) {\n const normalized = await normalizeAttachments(rawAttachments, {\n supportsNativePdf: provider.supportsNativePdf,\n });\n attachmentDiagnostics = normalized.diagnostics;\n if (normalized.blocks.length > 0) {\n attachLastUserMessage(messages, normalized.blocks);\n }\n }\n\n const systemPrompt = buildSystemPrompt({\n config,\n styleExemplars: body.styleExemplars,\n });\n\n const encoder = new TextEncoder();\n const stream = new ReadableStream<Uint8Array>({\n async start(controller) {\n let closed = false;\n const safeEnqueue = (chunk: Uint8Array) => {\n if (closed) return;\n try {\n controller.enqueue(chunk);\n } catch {\n // Controller already closed (client disconnected mid-write).\n closed = true;\n }\n };\n const send = (event: ChatEvent) => {\n safeEnqueue(encoder.encode(`data: ${JSON.stringify(event)}\\n\\n`));\n };\n\n // Forward the request abort signal so client-side aborts (the Stop\n // button, page navigation) cleanly stop the agent loop.\n const onAbort = () => {\n closed = true;\n try {\n controller.close();\n } catch {\n /* already closed */\n }\n };\n request.signal.addEventListener('abort', onAbort);\n\n // Initial provider info — UI shows \"Local · qwen/qwen2.5-coder-14b\" etc.\n safeEnqueue(\n encoder.encode(\n `event: meta\\ndata: ${JSON.stringify({\n provider: provider.providerType,\n model: provider.modelId,\n })}\\n\\n`,\n ),\n );\n\n // Surface any attachment diagnostics (skipped files, etc.) to the client\n // BEFORE the agent loop runs, so the UI can render warnings inline.\n if (attachmentDiagnostics.length > 0) {\n safeEnqueue(\n encoder.encode(`event: attachments\\ndata: ${JSON.stringify({ diagnostics: attachmentDiagnostics })}\\n\\n`),\n );\n }\n\n try {\n for await (const ev of runChat({\n agentConfig,\n config,\n systemPrompt,\n messages,\n provider,\n branch,\n })) {\n if (request.signal.aborted) break;\n send(ev);\n if (ev.type === 'done' || ev.type === 'error' || ev.type === 'budget_exceeded') break;\n }\n } catch (err) {\n send({ type: 'error', message: err instanceof Error ? err.message : 'Agent loop crashed.' });\n } finally {\n request.signal.removeEventListener('abort', onAbort);\n if (!closed) {\n try {\n controller.close();\n } catch {\n /* already closed */\n }\n }\n }\n },\n });\n\n return new Response(stream, {\n status: 200,\n headers: {\n 'Content-Type': 'text/event-stream; charset=utf-8',\n 'Cache-Control': 'no-cache, no-transform',\n Connection: 'keep-alive',\n },\n });\n}\n\n/**\n * `GET /api/agent` — small health endpoint so the client can verify the\n * agent is enabled and read the active provider/model without opening a\n * stream. Auth-gated; 404 when disabled.\n */\nexport async function chatStatusRoute(): Promise<Response> {\n const agentConfig = getAgentConfig();\n if (!agentConfig || !isAgentEnabled(agentConfig)) return notFound();\n\n const session = await getServerSession(authOptions);\n if (!session) return unauthorized();\n\n const provider = agentConfig.provider;\n return new Response(\n JSON.stringify({\n enabled: true,\n provider: provider.type,\n model: provider.model,\n }),\n { status: 200, headers: { 'Content-Type': 'application/json' } },\n );\n}\n\n/**\n * Pull every `file` form field out of the multipart body. We don't validate\n * them here — `normalizeAttachments` does that — we just collect them.\n */\nasync function collectFormAttachments(form: FormData): Promise<RawAttachment[]> {\n const out: RawAttachment[] = [];\n // FormData.getAll('files') accepts an array uploaded under one field name.\n // We also accept indexed names ('files[0]', etc.) for robustness.\n const candidates: FormDataEntryValue[] = [];\n for (const v of form.getAll('files')) candidates.push(v);\n for (const [key, value] of form.entries()) {\n if (key === 'files' || key === 'messages' || key === 'styleExemplars') continue;\n if (key.startsWith('files[')) candidates.push(value);\n }\n for (const v of candidates) {\n if (typeof v === 'string') continue;\n const file = v as File;\n const ab = await file.arrayBuffer();\n out.push({\n filename: file.name || 'upload',\n mediaType: file.type || '',\n bytes: new Uint8Array(ab),\n });\n }\n return out;\n}\n\n/**\n * Append the given content blocks to the last user message in the history.\n * If the last message isn't a user turn (defensive — should never happen for\n * the request just sent), append a fresh user message instead.\n */\nfunction attachLastUserMessage(messages: NormalizedMessage[], blocks: NormalizedContentBlock[]): void {\n const lastIdx = messages.length - 1;\n const last = messages[lastIdx];\n if (last && last.role === 'user') {\n const existing: NormalizedContentBlock[] =\n typeof last.content === 'string' ? [{ type: 'text', text: last.content }] : [...last.content];\n messages[lastIdx] = { role: 'user', content: [...existing, ...blocks] };\n return;\n }\n messages.push({ role: 'user', content: blocks });\n}\n","/**\n * Picks the right {@link ChatProvider} for an `AgentProvider` config.\n *\n * Lazy-imports the SDK adapter so a project that only uses Anthropic doesn't\n * need `openai` installed (and vice versa).\n */\nimport type { AgentProvider } from '../types';\nimport type { ChatProvider } from './types';\n\nexport function getChatProvider(provider: AgentProvider): ChatProvider {\n if (provider.type === 'anthropic') {\n // Synchronous import is fine — the file itself only loads `@anthropic-ai/sdk`\n // lazily inside `streamChat`, so import-cost stays cheap even when the SDK\n // isn't installed.\n const { AnthropicChatProvider } = require('./anthropic') as typeof import('./anthropic');\n return new AnthropicChatProvider(provider);\n }\n if (provider.type === 'openai' || provider.type === 'local') {\n const { OpenAIChatProvider } = require('./openai') as typeof import('./openai');\n return new OpenAIChatProvider(provider);\n }\n throw new Error(`Unknown agent provider: ${(provider as { type?: string }).type ?? 'undefined'}`);\n}\n\nexport type {\n ChatProvider,\n ChatStreamInput,\n NormalizedContentBlock,\n NormalizedMessage,\n NormalizedTool,\n ProviderEvent,\n} from './types';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGO,SAAS,mBAAmB,UAAyB;AAH5D;AAIE,UAAO,cAAS,YAAT,YAAoB;AAC7B;AAQO,SAAS,gBAAgB,QAAqB,OAAe,QAAgB,cAAc,GAAW;AAC3G,QAAM,UAAU,mBAAmB,OAAO,QAAQ;AAClD,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,WAAW;AAC7C,SACG,QAAQ,QAAQ,YAAa,MAC7B,cAAc,QAAQ,kBAAmB,MACzC,SAAS,QAAQ,aAAc;AAEpC;AAtBA;AAAA;AAAA;AAAA;AAAA;;;ACiCO,SAAS,WAAuB;AACrC,SAAO,mBAAK;AACd;AAEO,SAAS,WACd,QACA,MACY;AAxCd;AAyCE,QAAM,eAAc,UAAK,gBAAL,YAAoB;AACxC,UAAQ;AAAA,IACN,aAAa,MAAM,cAAc,KAAK;AAAA,IACtC,mBAAmB,MAAM,oBAAoB;AAAA,IAC7C,cAAc,MAAM,eAAe,KAAK;AAAA,IACxC,SAAS,MAAM,UAAU,gBAAgB,QAAQ,KAAK,OAAO,KAAK,QAAQ,WAAW;AAAA,IACrF,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,EACtC;AACA,SAAO,SAAS;AAClB;AAEO,SAAS,aAAyB;AACvC,UAAQ,mBAAK;AACb,SAAO,SAAS;AAClB;AAMO,SAAS,iBAAiB,QAAqB,QAAoB,OAAgB;AACxF,MAAI,OAAO,kBAAkB,EAAG,QAAO;AACvC,SAAO,MAAM,WAAW,OAAO;AACjC;AAhEA,IAuBM,MAQF;AA/BJ;AAAA;AAAA;AAYA;AAWA,IAAM,OAAmB;AAAA,MACvB,aAAa;AAAA,MACb,mBAAmB;AAAA,MACnB,cAAc;AAAA,MACd,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAEA,IAAI,QAAoB,mBAAK;AAAA;AAAA;;;ACEtB,SAAS,kBAAkB,UAAwC;AACxE,MAAI,SAAS,UAAW,QAAO,SAAS;AACxC,SAAO,qBAAqB,SAAS,IAAI;AAC3C;AAGO,SAAS,eAAe,UAAkC;AAC/D,MAAI,SAAS,SAAS,SAAS;AAC7B,QAAI,SAAS,WAAW;AACtB,YAAMA,OAAM,QAAQ,IAAI,SAAS,SAAS;AAC1C,aAAO,OAAOA,SAAQ,YAAYA,KAAI,SAAS;AAAA,IACjD;AACA,WAAO,QAAQ,SAAS,OAAO;AAAA,EACjC;AACA,QAAM,UAAU,kBAAkB,QAAQ;AAC1C,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,MAAM,QAAQ,IAAI,OAAO;AAC/B,SAAO,OAAO,QAAQ,YAAY,IAAI,SAAS;AACjD;AAEO,SAAS,eAAe,QAAkC;AAC/D,MAAI,CAAC,eAAe,OAAO,QAAQ,EAAG,QAAO,EAAE,SAAS,OAAO,QAAQ,SAAS;AAChF,QAAM,QAAQ,SAAS;AACvB,MAAI,iBAAiB,QAAQ,KAAK,GAAG;AACnC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,UAAU,MAAM;AAAA,MAChB,WAAW,OAAO;AAAA,IACpB;AAAA,EACF;AACA,SAAO,EAAE,SAAS,KAAK;AACzB;AAEO,SAAS,eAAe,QAA8B;AAC3D,SAAO,eAAe,MAAM,EAAE;AAChC;AArEA,IA0BM;AA1BN;AAAA;AAAA;AAmBA;AAOA,IAAM,uBAAqE;AAAA,MACzE,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,OAAO;AAAA,IACT;AAAA;AAAA;;;ACdO,SAAS,eAAe,QAA2B;AACxD,iBAAe;AACjB;AAEO,SAAS,iBAAqC;AACnD,SAAO;AACT;AAtBA,IAcI;AAdJ;AAAA;AAAA;AAcA,IAAI,eAAmC;AAAA;AAAA;;;ACGvC,SAAS,YAAY,OAAwB;AAC3C,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AAChF,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,WAAW,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,EACzD;AACA,MAAI,OAAO,UAAU,UAAU;AAE7B,UAAM,QAAkB,CAAC;AACzB,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACrE,YAAM,OAAO,YAAY,CAAC;AAC1B,UAAI,KAAM,OAAM,KAAK,GAAG,CAAC,KAAK,IAAI,EAAE;AAAA,IACtC;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AACA,SAAO;AACT;AAOO,SAAS,qBAAqB,OAAkB,aAAqC,CAAC,GAAW;AAzCxG;AA0CE,QAAM,QAAkB,CAAC;AACzB,QAAM,UAAS,WAAM,WAAN,YAAgB,CAAC;AAEhC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,OAAO,WAAY;AACvB,UAAM,OAAO,YAAY,KAAK,EAAE,KAAK;AACrC,QAAI,KAAM,OAAM,KAAK,GAAG,GAAG,KAAK,IAAI,EAAE;AAAA,EACxC;AAEA,aAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,UAAU,GAAG;AACvD,UAAM,WAAW,4BAAW,IAAI,KAAK;AACrC,QAAI,QAAS,OAAM,KAAK,GAAG,GAAG,KAAK,OAAO,EAAE;AAAA,EAC9C;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAzDA;AAAA;AAAA;AAAA;AAAA;;;ACyCA,SAAS,+BAAqC;AAC5C,MAAI,+BAAgC;AACpC,MAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,OAAO,WAAY;AACxE,mCAAiC;AACjC,UAAQ,GAAG,sBAAsB,CAAC,WAAoB;AACpD,UAAM,MAAM,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM;AACpE,QAAI,qDAAqD,KAAK,GAAG,GAAG;AAGlE;AAAA,IACF;AAEA,iBAAa,MAAM;AACjB,YAAM;AAAA,IACR,CAAC;AAAA,EACH,CAAC;AACH;AAqEO,SAAS,qBAA+B;AAC7C,MAAI,CAAC,gBAAiB,mBAAkB,IAAI,0BAA0B;AACtE,SAAO;AACT;AAGO,SAAS,mBAAmB,UAAiC;AAClE,oBAAkB;AACpB;AAtIA,IAoBM,kBACA,aAmBF,gCAmBE,2BAgEF;AA3HJ;AAAA;AAAA;AAoBA,IAAM,mBAAmB;AACzB,IAAM,cAAc;AAmBpB,IAAI,iCAAiC;AAmBrC,IAAM,4BAAN,MAAoD;AAAA,MAMlD,YAAY,UAAkB,kBAAkB,MAAc,aAAa;AAH3E,aAAQ,kBAA6D;AACrE,aAAQ,mBAAiC;AAGvC,aAAK,UAAU;AACf,aAAK,MAAM;AAAA,MACb;AAAA,MAEA,MAAc,cAAkD;AAC9D,YAAI,KAAK,iBAAkB,OAAM,KAAK;AACtC,YAAI,KAAK,gBAAiB,QAAO,KAAK;AACtC,qCAA6B;AAC7B,cAAM,KAAK,YAAgD;AACzD,cAAI;AACJ,cAAI;AACF,kBAAM,MAAM,OAAO,2BAA2B;AAAA,UAChD,SAAS,GAAG;AACV,kBAAM,MAAM,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AACrD,gBAAI,qDAAqD,KAAK,GAAG,GAAG;AAClE,oBAAM,IAAI;AAAA,gBACR,2HACmD,GAAG;AAAA,cAGxD;AAAA,YACF;AACA,kBAAM,IAAI;AAAA,cACR;AAAA,YACF;AAAA,UACF;AACA,gBAAM,OAAQ,MAAM,IAAI,SAAS,sBAAsB,KAAK,OAAO;AACnE,iBAAO;AAAA,QACT,GAAG;AAGH,UAAE,MAAM,CAAC,MAAe;AACtB,eAAK,mBAAmB,aAAa,QAAQ,IAAI,IAAI,MAAM,OAAO,CAAC,CAAC;AACpE,eAAK,kBAAkB;AAAA,QACzB,CAAC;AACD,aAAK,kBAAkB;AACvB,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,MAAM,OAA0C;AACpD,YAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAChC,cAAM,OAAO,MAAM,KAAK,YAAY;AAGpC,cAAM,SAAS,MAAM,KAAK,OAAO,EAAE,SAAS,QAAQ,WAAW,KAAK,CAAC;AACrE,cAAM,OAAO,OAAO;AACpB,cAAM,MAAsB,CAAC;AAC7B,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,gBAAM,QAAQ,IAAI,KAAK;AACvB,gBAAM,QAAQ,IAAI,aAAa,KAAK,GAAG;AACvC,gBAAM,IAAI,KAAK,SAAS,OAAO,QAAQ,KAAK,GAAG,CAAC;AAChD,cAAI,KAAK,KAAK;AAAA,QAChB;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,IAAI,kBAAmC;AAAA;AAAA;;;ACxHhC,SAAS,sBAAsB,eAAuB,WAA2B;AACtF,QAAM,OAAO,cAAc,QAAQ,WAAW,EAAE;AAChD,SAAO,GAAG,IAAI,IAAI,SAAS;AAC7B;AAGO,SAAS,sBAAsB,eAAuB,WAA2B;AACtF,QAAM,OAAO,cAAc,QAAQ,WAAW,EAAE;AAChD,SAAO,GAAG,IAAI,IAAI,SAAS;AAC7B;AAGO,SAAS,sBAAsB,gBAAwB,aAA8C;AAC1G,QAAM,MAAO,YAAoC,cAAc;AAC/D,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,SAAO,OAAO,QAAQ,IAAI,MAAM,EAC7B,OAAO,CAAC,CAAC,EAAE,GAAG,MAAqB,IAAI,WAAW,UAAU,EAC5D,IAAI,CAAC,CAAC,GAAG,MAAM,GAAG;AACvB;AAGO,SAAS,sBAAsB,gBAAwB,aAA8C;AAC1G,QAAM,MAAO,YAAoC,cAAc;AAC/D,MAAI,CAAC,IAAK,QAAO,CAAC;AAClB,SAAO,OAAO,QAAQ,IAAI,MAAM,EAC7B,OAAO,CAAC,CAAC,EAAE,GAAG,MAAqB,IAAI,WAAW,UAAU,EAC5D,IAAI,CAAC,CAAC,GAAG,MAAM,GAAG;AACvB;AAGO,SAAS,+BACd,eACA,gBACA,aACwB;AACxB,QAAM,QAAQ,sBAAsB,gBAAgB,WAAW;AAC/D,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,OAAO;AACxB,WAAO,IAAI,IAAI,sBAAsB,eAAe,IAAI;AAAA,EAC1D;AACA,SAAO;AACT;AAGO,SAAS,+BACd,eACA,gBACA,aACwB;AACxB,QAAM,QAAQ,sBAAsB,gBAAgB,WAAW;AAC/D,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,OAAO;AACxB,WAAO,IAAI,IAAI,sBAAsB,eAAe,IAAI;AAAA,EAC1D;AACA,SAAO;AACT;AAMO,SAAS,2BACd,eACA,gBACA,aACwB;AACxB,SAAO,kCACF,+BAA+B,eAAe,gBAAgB,WAAW,IACzE,+BAA+B,eAAe,gBAAgB,WAAW;AAEhF;AAzEA;AAAA;AAAA;AAAA;AAAA;;;ACUO,SAAS,cAAc,KAA2B;AAEvD,QAAM,QAAQ,IAAI,WAAW,IAAI,QAAQ,IAAI,YAAY,IAAI,UAAU;AACvE,SAAO,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ;AAC7C;AAGO,SAAS,cAAc,KAA2B;AACvD,QAAM,MAAM,OAAO,KAAK,KAAK,QAAQ;AAGrC,QAAM,KAAK,IAAI,YAAY,IAAI,UAAU;AACzC,MAAI,WAAW,EAAE,EAAE,IAAI,GAAG;AAC1B,SAAO,IAAI,aAAa,EAAE;AAC5B;AAOO,SAAS,iBAAiB,GAAiB,GAAyB;AACzE,MAAI,EAAE,WAAW,EAAE,QAAQ;AACzB,UAAM,IAAI,MAAM,sCAAsC,EAAE,MAAM,OAAO,EAAE,MAAM,GAAG;AAAA,EAClF;AACA,MAAI,EAAE,WAAW,EAAG,QAAO;AAE3B,MAAI,MAAM;AACV,MAAI,QAAQ;AACZ,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,UAAM,IAAI,EAAE,CAAC;AACb,UAAM,IAAI,EAAE,CAAC;AACb,WAAO,IAAI;AACX,aAAS,IAAI;AACb,aAAS,IAAI;AAAA,EACf;AAEA,MAAI,UAAU,KAAK,UAAU,EAAG,QAAO;AACvC,SAAO,OAAO,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK;AAClD;AAlDA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAaa;AAbb;AAAA;AAAA;AAaO,IAAM,oBAAoB,CAAC,WAAqC;AACrE,YAAM,QAAQ;AAAA,QACZ;AAAA,QACA,OAAO;AAAA,QACP,OAAO,SAAS,UAAU,OAAO,MAAM,KAAK;AAAA,QAC5C,OAAO,UAAU,OAAO,UAAU,OAAO,MAAM,KAAK;AAAA,QACpD,OAAO;AAAA,MACT,EAAE,OAAO,OAAO;AAChB,cAAQ,MAAM,MAAM,KAAK,GAAG,CAAC;AAAA,IAC/B;AAAA;AAAA;;;ACFO,SAAS,qBAAqB,OAA6C;AAChF,SAAO,iBAAiB;AAC1B;AA8BO,SAAS,iCAAiC,OAAgB,KAAqC;AApDtG;AAqDE,QAAM,MAAM;AACZ,QAAM,SAAS,2BAAK;AACpB,QAAM,SACH,SAAO,sCAAK,aAAL,mBAAe,SAAf,mBAAqB,aAAY,YAAY,IAAI,SAAS,KAAK,WACtE,QAAO,2BAAK,aAAY,YAAY,IAAI,WACzC;AAEF,MAAI,WAAW,KAAK;AAClB,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA,EAAE,OAAO,MAAM;AAAA,IACjB;AAAA,EACF;AAEA,MAAI,WAAW,OAAO,WAAW,KAAK;AACpC,WAAO,IAAI;AAAA,MACT;AAAA,MACA,iDAAiD,IAAI,KAAK,IAAI,IAAI,IAAI;AAAA,MACtE,EAAE,OAAO,MAAM;AAAA,IACjB;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,YAAY,UAAU,KAAK;AAC/C,WAAO,IAAI,mBAAmB,sBAAsB,8DAA8D;AAAA,MAChH,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,MAAI,WAAW,KAAK;AAClB,UAAM,UAAU,IAAI,MAAM,UAAU,IAAI,GAAG,MAAM;AACjD,WAAO,IAAI;AAAA,MACT;AAAA,MACA,sCAAsC,IAAI,KAAK,IAAI,IAAI,IAAI,GAAG,OAAO;AAAA,MACrE,EAAE,OAAO,MAAM;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,QAAQ,OAAO,MAAM,EAAE,YAAY;AACzC,MACE,MAAM,SAAS,cAAc,KAC7B,MAAM,SAAS,YAAY,KAC3B,MAAM,SAAS,WAAW,KAC1B,MAAM,SAAS,WAAW,KAC1B,MAAM,SAAS,SAAS,KACxB,MAAM,SAAS,QAAQ,GACvB;AACA,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA,EAAE,OAAO,MAAM;AAAA,IACjB;AAAA,EACF;AAEA,SAAO,IAAI,mBAAmB,sBAAsB,uCAAuC,MAAM,MAAM;AAAA,IACrG,OAAO;AAAA,EACT,CAAC;AACH;AA9GA,IAEM,eAMO;AARb;AAAA;AAAA;AAEA,IAAM,gBAAgB;AAMf,IAAM,qBAAN,cAAiC,MAAM;AAAA,MAI5C,YAAY,MAAyB,aAAqB,SAA+B;AACvF,cAAM,GAAG,aAAa,GAAG,IAAI,IAAI,WAAW,IAAI,OAAO;AACvD,aAAK,OAAO;AACZ,aAAK,OAAO;AACZ,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AAAA;AAAA;;;AClBA,IACA,eAEa;AAHb;AAAA;AAAA;AACA,oBAA2B;AAEpB,IAAM,cAA2B;AAAA,MACtC,WAAW;AAAA,YACT,cAAAC,SAAe;AAAA,UACb,UAAU,QAAQ,IAAI,aAAa;AAAA,UACnC,cAAc,QAAQ,IAAI,iBAAiB;AAAA,UAC3C,eAAe,EAAE,QAAQ,EAAE,OAAO,OAAO,EAAE;AAAA,QAC7C,CAAC;AAAA,MACH;AAAA,MACA,QAAQ,QAAQ,IAAI,mBAAmB;AAAA,MACvC,WAAW;AAAA,QACT,MAAM,IAAI,EAAE,OAAO,QAAQ,GAAG;AAC5B,cAAI,mCAAS,cAAc;AACzB,kBAAM,cAAc,QAAQ;AAAA,UAC9B;AACA,iBAAO;AAAA,QACT;AAAA,QACA,MAAM,QAAQ,EAAE,SAAS,MAAM,GAAG;AAChC,UAAC,QAAgB,cAAc,MAAM;AACrC,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AClBO,SAAS,kBAAsC;AACpD,QAAM,IAAI,KAAK,QAAQ,IAAI,UAAU;AACrC,SAAO,KAAK;AACd;AASO,SAAS,aAAqB;AACnC,QAAM,MACJ,KAAK,QAAQ,IAAI,oBAAoB,KACrC,KAAK,QAAQ,IAAI,eAAe,KAChC,KAAK,QAAQ,IAAI,aAAa,KAC9B,KAAK,QAAQ,IAAI,QAAQ,KACzB;AACF,QAAM,KAAK,IAAI,QAAQ,qBAAqB,GAAG,EAAE,QAAQ,QAAQ,EAAE;AACnE,SAAO,MAAM;AACf;AAkBO,SAAS,qBAA6B;AAC3C,QAAM,KACJ,WAAW,EACR,QAAQ,qBAAqB,GAAG,EAChC,QAAQ,QAAQ,EAAE,KAAK;AAC5B,SAAO,gBAAgB,EAAE;AAC3B;AAnDA,IAAM;AAAN;AAAA;AAAA;AAAA,IAAM,OAAO,CAAC,UAAuC,OAAO,UAAU,WAAW,MAAM,KAAK,IAAI;AAAA;AAAA;;;ACmBzF,SAAS,YAAoB;AAClC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IAIF;AAAA,EACF;AACA,SAAO;AACT;AA7BA,IAEI;AAFJ,IAAAC,oBAAA;AAAA;AAAA;AAEA,IAAI,UAAyB;AAAA;AAAA;;;ACuBtB,SAAS,mBAA4B;AAC1C,MAAI,QAAQ,IAAI,aAAa,aAAc,QAAO;AAClD,SAAO,QAAQ,IAAI,yBAAyB;AAC9C;AA5BA;AAAA;AAAA;AAAA;AAAA;;;ACAA,oBAQM,iBAMO,oBAoBA,mBAiBA,wBASA,sBA2DA,iBAyDA,0BA8CA,sBAyCA,8BAkDA;AAzTb;AAAA;AAAA;AAAA,qBAAwB;AAExB;AACA,IAAAC;AACA;AAEA;AAEA,IAAM,kBAAkB,OAAO;AAAA,MAC7B,OAAO,QAAQ,IAAI,qBAAqB;AAAA,MACxC,MAAM,QAAQ,IAAI,oBAAoB;AAAA,MACtC,QAAQ,UAAU,EAAE,IAAI;AAAA,IAC1B;AAEO,IAAM,qBAAqB,MAAM;AACtC,YAAM,EAAE,OAAO,MAAM,OAAO,IAAI,gBAAgB;AAEhD,UAAI,CAAC,SAAS,CAAC,MAAM;AACnB,cAAM,IAAI;AAAA,UACR;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,aAAO,EAAE,OAAO,MAAM,OAAO;AAAA,IAC/B;AASO,IAAM,oBAAoB,MAAiB;AAlClD;AAmCE,YAAM,SAAQ,aAAQ,IAAI,qBAAZ,mBAA8B;AAC5C,YAAM,UAAqB,CAAC;AAE5B,UAAI,OAAO;AACT,gBAAQ,KAAK,IAAI,uBAAQ,EAAE,MAAM,MAAM,CAAC,CAAC;AAAA,MAC3C;AAEA,cAAQ,KAAK,IAAI,uBAAQ,CAAC;AAE1B,aAAO;AAAA,IACT;AAMO,IAAM,yBAAyB,MAA0B;AAnDhE;AAoDE,YAAM,KAAI,eAAU,EAAE,IAAI,2BAAhB,mBAAwC;AAClD,aAAO,KAAK;AAAA,IACd;AAMO,IAAM,uBAAuB,OAAO,UAAkB,WAA4C;AA5DzG;AA6DE,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,MAAM,0BAAU;AACtB,YAAM,UAAU,kBAAkB;AAElC,UAAI,eAAe;AACnB,iBAAW,WAAW,SAAS;AAC7B,YAAI;AACF,gBAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,MAAM,WAAW;AAAA,YACnD;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACF,CAAC;AAED,cAAI,aAAa,QAAQ,KAAK,SAAS,QAAQ;AAC7C,mBAAO,OAAO,KAAK,KAAK,SAAS,QAAQ,EAAE,SAAS,OAAO;AAAA,UAC7D;AAEA,iBAAO;AAAA,QACT,SAAS,OAAY;AACnB,cAAI,MAAM,WAAW,KAAK;AACxB,kBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,UACpE;AAEA,cAAI,MAAM,WAAW,OAAO,MAAM,WAAW,KAAK;AAChD,2BAAe;AACf;AAAA,UACF;AAEA,cAAI,MAAM,WAAW,KAAK;AAGxB,gBAAI,aAAc;AAClB,mBAAO;AAAA,UACT;AAEA,gBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,QACpE;AAAA,MACF;AAGA,YAAM,eAAe,CAAC,GAAC,aAAQ,IAAI,qBAAZ,mBAA8B;AACrD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,eACI,eAAe,KAAK,IAAI,IAAI,UAAU,GAAG,2HACzC,eAAe,KAAK,IAAI,IAAI,UAAU,GAAG;AAAA,MAC/C;AAAA,IACF;AAUO,IAAM,kBAAkB,OAAO,SAAiB,WAAoB,WAAuC;AAvHlH;AAwHE,YAAM,UAAU,kBAAkB;AAClC,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,MAAM,0BAAU;AAEtB,UAAI,eAAe;AACnB,iBAAW,WAAW,SAAS;AAC7B,YAAI;AACF,gBAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,MAAM,WAAW;AAAA,YACnD;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACF,CAAC;AAED,cAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACxB,mBAAO,CAAC;AAAA,UACV;AAEA,cAAI,QAAQ,KAAK,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI;AAE/E,cAAI,WAAW;AACb,oBAAQ,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,SAAS,CAAC;AAAA,UACnD;AAEA,iBAAO;AAAA,QACT,SAAS,OAAY;AACnB,cAAI,MAAM,WAAW,KAAK;AACxB,kBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,UACpE;AACA,cAAI,MAAM,WAAW,OAAO,MAAM,WAAW,KAAK;AAChD,2BAAe;AACf;AAAA,UACF;AACA,cAAI,MAAM,WAAW,KAAK;AAGxB,gBAAI,aAAc;AAClB,mBAAO,CAAC;AAAA,UACV;AACA,gBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,QACpE;AAAA,MACF;AAEA,YAAM,eAAe,CAAC,GAAC,aAAQ,IAAI,qBAAZ,mBAA8B;AACrD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,eACI,eAAe,KAAK,IAAI,IAAI,IAAI,OAAO,UAAU,GAAG,2HACpD,eAAe,KAAK,IAAI,IAAI,IAAI,OAAO,UAAU,GAAG;AAAA,MAC1D;AAAA,IACF;AAMO,IAAM,2BAA2B,OACtC,SACA,WACA,WACsB;AACtB,YAAM,CAAC,OAAO,IAAI,kBAAkB;AACpC,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,MAAM,0BAAU;AAEtB,UAAI;AACF,cAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,MAAM,WAAW;AAAA,UACnD;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN;AAAA,QACF,CAAC;AAED,YAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACxB,iBAAO,CAAC;AAAA,QACV;AAEA,cAAM,UAAoB,CAAC;AAE3B,mBAAW,QAAQ,MAAM;AACvB,cAAI,KAAK,SAAS,QAAQ;AACxB,gBAAI,CAAC,aAAa,KAAK,KAAK,SAAS,SAAS,GAAG;AAC/C,sBAAQ,KAAK,KAAK,IAAI;AAAA,YACxB;AAAA,UACF,WAAW,KAAK,SAAS,OAAO;AAC9B,kBAAM,WAAW,MAAM,yBAAyB,KAAK,MAAM,WAAW,MAAM;AAC5E,oBAAQ,KAAK,GAAG,QAAQ;AAAA,UAC1B;AAAA,QACF;AAEA,eAAO;AAAA,MACT,SAAS,OAAY;AACnB,YAAI,MAAM,WAAW,KAAK;AACxB,iBAAO,CAAC;AAAA,QACV;AACA,cAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,MACpE;AAAA,IACF;AAKO,IAAM,uBAAuB,OAAO,eAAyC;AA9NpF;AA+NE,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAC3C,YAAM,UAAU,kBAAkB;AAElC,UAAI,eAAe;AACnB,iBAAW,WAAW,SAAS;AAC7B,YAAI;AACF,gBAAM,QAAQ,KAAK,IAAI,OAAO;AAAA,YAC5B;AAAA,YACA;AAAA,YACA,KAAK,SAAS,UAAU;AAAA,UAC1B,CAAC;AACD,iBAAO;AAAA,QACT,SAAS,OAAY;AACnB,cAAI,MAAM,WAAW,KAAK;AACxB,gBAAI,aAAc;AAClB,mBAAO;AAAA,UACT;AACA,cAAI,MAAM,WAAW,OAAO,MAAM,WAAW,KAAK;AAChD,2BAAe;AACf;AAAA,UACF;AACA,cAAI,MAAM,WAAW,KAAK;AACxB,kBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC;AAAA,UAChF;AACA,gBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,KAAK,WAAW,CAAC;AAAA,QAChF;AAAA,MACF;AAEA,YAAM,eAAe,CAAC,GAAC,aAAQ,IAAI,qBAAZ,mBAA8B;AACrD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,eACI,wBAAwB,UAAU,OAAO,KAAK,IAAI,IAAI,8GACtD,wBAAwB,UAAU,OAAO,KAAK,IAAI,IAAI;AAAA,MAC5D;AAAA,IACF;AAKO,IAAM,+BAA+B,OAAO,WAAsC;AAvQzF;AAwQE,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAC3C,YAAM,aAAa,OAAO,QAAQ,QAAQ,EAAE;AAC5C,YAAM,WAAW,WAAW,SAAS,GAAG,IAAI,SAAS,UAAU,KAAK,SAAS,UAAU;AACvF,YAAM,UAAU,kBAAkB;AAElC,UAAI,eAAe;AACnB,iBAAW,WAAW,SAAS;AAC7B,YAAI;AACF,gBAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,IAAI,iBAAiB;AAAA,YACvD;AAAA,YACA;AAAA,YACA,KAAK;AAAA,UACP,CAAC;AACD,iBAAO,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI,QAAQ,kBAAkB,EAAE,CAAC,EAAE,OAAO,CAAC,SAAyB,QAAQ,IAAI,CAAC;AAAA,QAC5G,SAAS,OAAY;AACnB,cAAI,MAAM,WAAW,KAAK;AACxB,kBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,KAAK,SAAS,CAAC;AAAA,UAC9E;AACA,cAAI,MAAM,WAAW,OAAO,MAAM,WAAW,KAAK;AAChD,2BAAe;AACf;AAAA,UACF;AACA,cAAI,MAAM,WAAW,KAAK;AACxB,gBAAI,aAAc;AAClB,mBAAO,CAAC;AAAA,UACV;AACA,gBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,KAAK,SAAS,CAAC;AAAA,QAC9E;AAAA,MACF;AAEA,YAAM,eAAe,CAAC,GAAC,aAAQ,IAAI,qBAAZ,mBAA8B;AACrD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,eACI,2BAA2B,KAAK,IAAI,IAAI,KAAK,QAAQ,+GACrD,2BAA2B,KAAK,IAAI,IAAI,KAAK,QAAQ;AAAA,MAC3D;AAAA,IACF;AAYO,IAAM,uBAAuB,YAA6B;AAzTjE;AA0TE,YAAM,EAAE,QAAQ,aAAa,IAAI,mBAAmB;AACpD,YAAM,cAAa,4BAAuB,MAAvB,YAA4B;AAC/C,YAAM,cAAc,mBAAmB;AAGvC,YAAM,cAAc,oBAAI,IAA8B;AACtD,YAAM,eAAe,OAAO,SAA4D;AACtF,YAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,cAAM,IAAI,KAAK,KAAK;AACpB,YAAI,CAAC,EAAG,QAAO;AACf,YAAI,MAAM,aAAc,QAAO;AAC/B,YAAI,UAAU,YAAY,IAAI,CAAC;AAC/B,YAAI,CAAC,SAAS;AACZ,oBAAU,qBAAqB,CAAC;AAChC,sBAAY,IAAI,GAAG,OAAO;AAAA,QAC5B;AACA,YAAI,MAAM,QAAS,QAAO;AAC1B,eAAO;AAAA,MACT;AAEA,UAAI;AACJ,UAAI;AACF,kBAAU,MAAM,qBAAqB,aAAa,UAAU;AAAA,MAC9D,SAAS,GAAG;AACV,YAAI,qBAAqB,CAAC,EAAG,OAAM;AACnC,kBAAU;AAAA,MACZ;AAEA,UAAI,SAAS;AACX,YAAI;AACF,gBAAM,SAAS,KAAK,MAAM,OAAO;AACjC,cAAI,OAAO,OAAO,WAAW,UAAU;AACrC,kBAAM,SAAS,MAAM,aAAa,OAAO,MAAM;AAC/C,gBAAI,OAAQ,QAAO;AAAA,UACrB;AAAA,QACF,SAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,YAAY,gBAAgB;AAClC,UAAI,WAAW;AACb,cAAM,SAAS,MAAM,aAAa,SAAS;AAC3C,YAAI,OAAQ,QAAO;AAAA,MACrB;AAEA,aAAO;AAAA,IACT;AAAA;AAAA;;;ACzWA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAC,iBACA,kBA+BM,iBAQA,sBAWA,qBAYA,oBAuBA,YAgBA,iBAkBO,4BAuCA,eAoCA,gBAmDA,sBA6DA,6BAwGA,kBAwBA,oBAkBP,mBAqBO,4BA+DA,2BA8BA,iCA+CA,yBA2BA,kBAgBA;AAjpBb;AAAA;AAAA;AAAA,IAAAA,kBAAwB;AACxB,uBAAiC;AAEjC;AACA;AAEA;AAEA;AAwBA,IAAM,kBAAkB,CAAC,UAA2B;AAClD,UAAI,iBAAiB,OAAO;AAC1B,eAAO,MAAM;AAAA,MACf;AAEA,aAAO,OAAO,KAAK;AAAA,IACrB;AAEA,IAAM,uBAAuB,CAAC,UAAuB;AAxCrD;AAyCE,YAAM,SAAS,+BAAO;AACtB,YAAM,YAAU,0CAAO,aAAP,mBAAiB,SAAjB,mBAAuB,aAAW,+BAAO,YAAW,gBAAgB,KAAK;AAEzF,UAAI,QAAQ;AACV,eAAO,GAAG,MAAM,IAAI,OAAO;AAAA,MAC7B;AAEA,aAAO;AAAA,IACT;AAEA,IAAM,sBAAsB,OAAO,SAAkB,OAAe,SAAkC;AACpG,YAAM,EAAE,MAAM,SAAS,IAAI,MAAM,QAAQ,KAAK,MAAM,IAAI,EAAE,OAAO,KAAK,CAAC;AACvE,YAAM,gBAAgB,SAAS,kBAAkB;AACjD,YAAM,EAAE,MAAM,WAAW,IAAI,MAAM,QAAQ,KAAK,IAAI,OAAO;AAAA,QACzD;AAAA,QACA;AAAA,QACA,KAAK,SAAS,aAAa;AAAA,MAC7B,CAAC;AAED,aAAO,WAAW,OAAO;AAAA,IAC3B;AAEA,IAAM,qBAAqB,OAAO,SAAkB,OAAe,MAAc,WAAmB;AAClG,UAAI;AACF,cAAM,QAAQ,KAAK,IAAI,OAAO;AAAA,UAC5B;AAAA,UACA;AAAA,UACA,KAAK,SAAS,MAAM;AAAA,QACtB,CAAC;AAAA,MACH,SAAS,OAAY;AACnB,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM;AAAA,QACR;AAEA,cAAM,UAAU,MAAM,oBAAoB,SAAS,OAAO,IAAI;AAE9D,cAAM,QAAQ,KAAK,IAAI,UAAU;AAAA,UAC/B;AAAA,UACA;AAAA,UACA,KAAK,cAAc,MAAM;AAAA,UACzB,KAAK;AAAA,QACP,CAAC;AAAA,MACH;AAAA,IACF;AAEA,IAAM,aAAa,YAAY;AAC7B,YAAM,UAAU,UAAM,mCAAiB,WAAW;AAClD,YAAM,cAAe,mCAAiB;AAEtC,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,qDAAqD;AAAA,MACvE;AAEA,aAAO,IAAI,wBAAQ,EAAE,MAAM,YAAY,CAAC;AAAA,IAC1C;AAOA,IAAM,kBAAkB,YAA8B;AAtGtD;AAuGE,YAAM,SAAQ,aAAQ,IAAI,qBAAZ,mBAA8B;AAE5C,UAAI,OAAO;AACT,eAAO,IAAI,wBAAQ,EAAE,MAAM,MAAM,CAAC;AAAA,MACpC;AAEA,aAAO,WAAW;AAAA,IACpB;AAUO,IAAM,6BAA6B,OAAO,UAAkB,WAA4C;AAC7G,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAC3C,YAAM,MAAM,0BAAW,MAAM,qBAAqB;AAClD,YAAM,UAAU,kBAAkB;AAElC,iBAAW,WAAW,SAAS;AAC7B,YAAI;AACF,gBAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,MAAM,WAAW;AAAA,YACnD;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,UACF,CAAC;AAED,cAAI,aAAa,QAAQ,KAAK,SAAS,QAAQ;AAC7C,mBAAO,OAAO,KAAK,KAAK,QAAQ,QAAQ,OAAO,EAAE,GAAG,QAAQ;AAAA,UAC9D;AAEA,iBAAO;AAAA,QACT,SAAS,OAAY;AACnB,cAAI,MAAM,WAAW,KAAK;AACxB,kBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,UACpE;AAEA,cAAI,MAAM,WAAW,OAAO,MAAM,WAAW,OAAO,MAAM,WAAW,KAAK;AACxE;AAAA,UACF;AAEA,gBAAM,iCAAiC,OAAO,EAAE,OAAO,MAAM,IAAI,CAAC;AAAA,QACpE;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAMO,IAAM,gBAAgB,OAC3B,UACA,WACqD;AACrD,YAAM,CAAC,OAAO,IAAI,kBAAkB;AACpC,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,MAAM,UAAU;AAEtB,UAAI;AACF,cAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,MAAM,WAAW;AAAA,UACnD;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN;AAAA,QACF,CAAC;AAED,YAAI,aAAa,QAAQ,KAAK,SAAS,QAAQ;AAC7C,gBAAM,UAAU,OAAO,KAAK,KAAK,SAAS,QAAQ,EAAE,SAAS,OAAO;AACpE,iBAAO,EAAE,SAAS,KAAK,KAAK,IAAI;AAAA,QAClC;AAEA,eAAO;AAAA,MACT,SAAS,OAAY;AACnB,YAAI,MAAM,WAAW,KAAK;AACxB,iBAAO;AAAA,QACT;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAQO,IAAM,iBAAiB,OAC5B,UACA,SACA,SACA,QACA,gBACG;AACH,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,eAAe,UAAU;AAE/B,YAAM,mBAAmB,SAAS,OAAO,MAAM,YAAY;AAG3D,YAAM,WAAW,cAAc,EAAE,KAAK,YAAY,IAAI,MAAM,cAAc,UAAU,YAAY;AAEhG,UAAI;AACF,cAAM,QAAQ,KAAK,MAAM,2BAA2B;AAAA,UAClD;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA,SAAS,OAAO,KAAK,OAAO,EAAE,SAAS,QAAQ;AAAA,UAC/C,QAAQ;AAAA,WACJ,WAAW,EAAE,KAAK,SAAS,IAAI,IAAI,CAAC,EACzC;AAAA,MACH,SAAS,OAAY;AACnB,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,IAAI,MAAM,kDAAkD,qBAAqB,KAAK,CAAC,EAAE;AAAA,QACjG;AAEA,cAAM,IAAI,MAAM,uBAAuB,qBAAqB,KAAK,CAAC,EAAE;AAAA,MACtE;AAAA,IACF;AAMO,IAAM,uBAAuB,OAAO,UAAkB,QAAgB,SAAiB,WAAoB;AAChH,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,eAAe,UAAU;AAE/B,YAAM,mBAAmB,SAAS,OAAO,MAAM,YAAY;AAE3D,YAAM,WAAW,MAAM,cAAc,UAAU,YAAY;AAE3D,UAAI;AACF,cAAM,QAAQ,KAAK,MAAM,2BAA2B;AAAA,UAClD;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA,SAAS,OAAO,SAAS,QAAQ;AAAA,UACjC,QAAQ;AAAA,WACJ,WAAW,EAAE,KAAK,SAAS,IAAI,IAAI,CAAC,EACzC;AAAA,MACH,SAAS,OAAY;AACnB,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,IAAI,MAAM,kDAAkD,qBAAqB,KAAK,CAAC,EAAE;AAAA,QACjG;AAEA,cAAM,IAAI,MAAM,uBAAuB,qBAAqB,KAAK,CAAC,EAAE;AAAA,MACtE;AAAA,IACF;AAuBO,IAAM,8BAA8B,OACzC,SACA,SACA,WAC6B;AAC7B,UAAI,QAAQ,WAAW,GAAG;AACxB,cAAM,IAAI,MAAM,kDAAkD;AAAA,MACpE;AAEA,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,eAAe,UAAU;AAE/B,YAAM,mBAAmB,SAAS,OAAO,MAAM,YAAY;AAE3D,YAAM,EAAE,MAAM,IAAI,IAAI,MAAM,QAAQ,KAAK,IAAI,OAAO;AAAA,QAClD;AAAA,QACA;AAAA,QACA,KAAK,SAAS,YAAY;AAAA,MAC5B,CAAC;AACD,YAAM,UAAU,IAAI,OAAO;AAE3B,YAAM,EAAE,MAAM,WAAW,IAAI,MAAM,QAAQ,KAAK,IAAI,UAAU;AAAA,QAC5D;AAAA,QACA;AAAA,QACA,YAAY;AAAA,MACd,CAAC;AACD,YAAM,cAAc,WAAW,KAAK;AAEpC,YAAM,OAMA,CAAC;AAEP,iBAAW,UAAU,SAAS;AAC5B,YAAI,OAAO,SAAS,UAAU;AAC5B,eAAK,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK,CAAC;AACxE;AAAA,QACF;AACA,YAAI,OAAO,SAAS,eAAe;AAEjC,eAAK,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,UAAU,MAAM,QAAQ,SAAS,OAAO,QAAQ,CAAC;AACtF;AAAA,QACF;AAEA,cAAM,EAAE,MAAM,KAAK,IAAI,MAAM,QAAQ,KAAK,IAAI,WAAW;AAAA,UACvD;AAAA,UACA;AAAA,UACA,SAAS,OAAO,QAAQ,SAAS,QAAQ;AAAA,UACzC,UAAU;AAAA,QACZ,CAAC;AACD,aAAK,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,UAAU,MAAM,QAAQ,KAAK,KAAK,IAAI,CAAC;AAAA,MAC9E;AAEA,UAAI;AACJ,UAAI;AACF,cAAM,EAAE,MAAM,QAAQ,IAAI,MAAM,QAAQ,KAAK,IAAI,WAAW;AAAA,UAC1D;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX;AAAA,QACF,CAAC;AACD,qBAAa,QAAQ;AAAA,MACvB,SAAS,OAAY;AACnB,cAAM,IAAI,MAAM,6BAA6B,qBAAqB,KAAK,CAAC,EAAE;AAAA,MAC5E;AAEA,UAAI,eAAe,aAAa;AAC9B,cAAM,IAAI,MAAM,2FAA2F;AAAA,MAC7G;AAEA,YAAM,EAAE,MAAM,UAAU,IAAI,MAAM,QAAQ,KAAK,IAAI,aAAa;AAAA,QAC9D;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,SAAS,CAAC,OAAO;AAAA,MACnB,CAAC;AAED,UAAI;AACF,cAAM,QAAQ,KAAK,IAAI,UAAU;AAAA,UAC/B;AAAA,UACA;AAAA,UACA,KAAK,SAAS,YAAY;AAAA,UAC1B,KAAK,UAAU;AAAA,QACjB,CAAC;AAAA,MACH,SAAS,OAAY;AACnB,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,IAAI;AAAA,YACR,WAAW,YAAY,oDAAoD,qBAAqB,KAAK,CAAC;AAAA,UACxG;AAAA,QACF;AACA,cAAM,IAAI,MAAM,4BAA4B,qBAAqB,KAAK,CAAC,EAAE;AAAA,MAC3E;AAEA,aAAO,EAAE,KAAK,UAAU,IAAI;AAAA,IAC9B;AAKO,IAAM,mBAAmB,OAAO,UAAkB,SAAiB,WAAoB;AAC5F,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,MAAM,QAAQ,aAAa,IAAI,mBAAmB;AACjE,YAAM,eAAe,UAAU;AAE/B,YAAM,WAAW,MAAM,cAAc,UAAU,YAAY;AAE3D,UAAI,CAAC,UAAU;AACb;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK,MAAM,WAAW;AAAA,QAClC;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA,KAAK,SAAS;AAAA,QACd,QAAQ;AAAA,MACV,CAAC;AAAA,IACH;AAKO,IAAM,qBAAqB,OAAO,eAAsC;AAC7E,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,MAAM,QAAQ,WAAW,IAAI,mBAAmB;AAE/D,YAAM,EAAE,MAAM,QAAQ,IAAI,MAAM,QAAQ,KAAK,IAAI,OAAO;AAAA,QACtD;AAAA,QACA;AAAA,QACA,KAAK,SAAS,UAAU;AAAA,MAC1B,CAAC;AAED,YAAM,QAAQ,KAAK,IAAI,UAAU;AAAA,QAC/B;AAAA,QACA;AAAA,QACA,KAAK,cAAc,UAAU;AAAA,QAC7B,KAAK,QAAQ,OAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,IAAM,oBAAoB,OAAO,SAAkB,OAAe,MAAc,MAAc,UAAkB;AAC9G,UAAI;AACF,cAAM,QAAQ,KAAK,OAAO,SAAS,EAAE,OAAO,MAAM,KAAK,CAAC;AAAA,MAC1D,SAAS,OAAY;AACnB,YAAI,MAAM,WAAW,KAAK;AACxB,gBAAM,QAAQ,KAAK,OAAO,YAAY;AAAA,YACpC;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,aAAa;AAAA,UACf,CAAC;AAAA,QACH,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAKO,IAAM,6BAA6B,OACxC,YACA,OACA,MACA,iBAC6C;AAC7C,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAE3C,UAAI;AAEJ,UAAI;AACF,cAAM,MAAM,MAAM,QAAQ,KAAK,MAAM,OAAO;AAAA,UAC1C;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO;AAAA,QACT,CAAC;AACD,eAAO,IAAI;AAAA,MACb,SAAS,OAAY;AACnB,cAAM,SAAS,qBAAqB,KAAK;AACzC,0BAAkB;AAAA,UAChB,WAAW;AAAA,UACX,QAAQ;AAAA,UACR,QAAQ,+BAAO;AAAA,UACf,SAAS;AAAA,QACX,CAAC;AAED,aAAI,+BAAO,YAAW,KAAK;AACzB,gBAAM,QAAQ,OAAO,YAAY;AACjC,cAAI,MAAM,SAAS,oBAAoB,GAAG;AACxC,kBAAM,IAAI;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,IAAI,MAAM,sCAAsC,MAAM,EAAE;AAAA,QAChE;AAEA,cAAM,IAAI,MAAM,sCAAsC,MAAM,EAAE;AAAA,MAChE;AAEA,UAAI;AACF,cAAM,kBAAkB,SAAS,OAAO,MAAM,cAAc,QAAQ;AACpE,cAAM,QAAQ,KAAK,OAAO,UAAU;AAAA,UAClC;AAAA,UACA;AAAA,UACA,cAAc,KAAK;AAAA,UACnB,QAAQ,CAAC,YAAY;AAAA,QACvB,CAAC;AAAA,MACH,SAAS,IAAI;AAAA,MAEb;AAEA,aAAO,EAAE,KAAK,KAAK,UAAU,QAAQ,KAAK,OAAO;AAAA,IACnD;AAKO,IAAM,4BAA4B,YAEpC;AACH,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAE3C,YAAM,EAAE,MAAM,IAAI,IAAI,MAAM,QAAQ,KAAK,MAAM,KAAK;AAAA,QAClD;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAED,aAAO,IACJ,OAAO,CAAC,OAAO,GAAG,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,CAAC,EAC7D,IAAI,CAAC,QAAQ;AAAA,QACZ,QAAQ,GAAG,KAAK;AAAA,QAChB,OAAO,GAAG;AAAA,QACV,UAAU,GAAG;AAAA,QACb,OAAO,GAAG;AAAA,MACZ,EAAE;AAAA,IACN;AASO,IAAM,kCAAkC,OAC7C,QAAQ,MAYL;AACH,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAE3C,YAAM,EAAE,MAAM,IAAI,IAAI,MAAM,QAAQ,KAAK,MAAM,KAAK;AAAA,QAClD;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,MAAM;AAAA,QACN,WAAW;AAAA,QACX,UAAU;AAAA,MACZ,CAAC;AAED,aAAO,IACJ,OAAO,CAAC,OAAO,GAAG,OAAO,KAAK,CAAC,MAAM,EAAE,SAAS,YAAY,CAAC,EAC7D,MAAM,GAAG,KAAK,IAAI,GAAG,KAAK,CAAC,EAC3B,IAAI,CAAC,OAAO;AAplBjB;AAqlBM,cAAMC,SAAmC,GAAG,YAAY,WAAW,GAAG,UAAU,SAAS,SAAS;AAClG,eAAO;AAAA,UACL,QAAQ,GAAG,KAAK;AAAA,UAChB,OAAO,GAAG;AAAA,UACV,UAAU,GAAG;AAAA,UACb,OAAO,GAAG;AAAA,UACV,OAAAA;AAAA,UACA,WAAW,GAAG;AAAA,UACd,cAAa,cAAG,SAAH,mBAAS,UAAT,YAAkB;AAAA,UAC/B,kBAAiB,cAAG,SAAH,mBAAS,eAAT,YAAuB;AAAA,QAC1C;AAAA,MACF,CAAC;AAAA,IACL;AAKO,IAAM,0BAA0B,OACrC,OACA,MACA,eAAuB,WACsB;AAC7C,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,MAAM,OAAO,IAAI,mBAAmB;AAEnD,UAAI,WAAW,cAAc;AAC3B,cAAM,IAAI,MAAM,oCAAoC,MAAM,mCAAmC,YAAY,GAAG;AAAA,MAC9G;AAEA,YAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,MAAM,OAAO;AAAA,QAC/C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,MACR,CAAC;AAED,aAAO,EAAE,KAAK,KAAK,UAAU,QAAQ,KAAK,OAAO;AAAA,IACnD;AAKO,IAAM,mBAAmB,OAAO,aAAoC;AACzE,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAE3C,YAAM,QAAQ,KAAK,MAAM,MAAM;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,aAAa;AAAA,QACb,cAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAMO,IAAM,uBAAuB,OAAO,eAAsC;AAC/E,YAAM,UAAU,MAAM,gBAAgB;AACtC,YAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAE3C,YAAM,EAAE,MAAM,IAAI,IAAI,MAAM,QAAQ,KAAK,MAAM,KAAK;AAAA,QAClD;AAAA,QACA;AAAA,QACA,MAAM,GAAG,KAAK,IAAI,UAAU;AAAA,QAC5B,OAAO;AAAA,QACP,UAAU;AAAA,MACZ,CAAC;AAED,YAAM,KAAK,IAAI,CAAC;AAChB,UAAI,CAAC,MAAM,CAAC,GAAG,MAAO;AAEtB,YAAM,QAAQ;AAAA,QACZ;AAAA;AAAA;AAAA;AAAA;AAAA,QAKA,EAAE,eAAe,GAAG,QAAQ;AAAA,MAC9B;AAAA,IACF;AAAA;AAAA;;;AC/nBO,SAAS,kBAAkB,MAAsB;AACtD,aAAO,0BAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACvD;AAGO,SAAS,WAAW,UAAsC;AA9CjE;AA+CE,QAAM,IAAI,8BAAY;AACtB,SAAO;AAAA,IACL,QAAO,4BAAG,YAAH,YAAc;AAAA,IACrB,MAAK,4BAAG,QAAH,YAAU;AAAA,IACf,SAAS,CAAC;AAAA,EACZ;AACF;AAEA,SAAS,qBAAqB,GAAmB;AAC/C,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAUA,eAAsB,eAAe,QAA2C;AAC9E,QAAM,MAAM,MAAM,aAAa,MAAM;AACrC,MAAI,CAAC,IAAK,QAAO,WAAW;AAC5B,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAI,CAAC,UAAU,OAAO,WAAW,YAAY,CAAC,OAAO,WAAW,OAAO,OAAO,YAAY,UAAU;AAClG,aAAO,WAAW;AAAA,IACpB;AACA,WAAO;AAAA,MACL,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAAA,MACzD,KAAK,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM;AAAA,MACnD,SAAS,OAAO;AAAA,IAClB;AAAA,EACF,SAAQ;AACN,WAAO,WAAW;AAAA,EACpB;AACF;AAEA,eAAe,aAAa,QAAyC;AAGnE,MAAI;AACF,UAAM,SAAS,QAAQ,IAAI,aAAa;AACxC,QAAI,QAAQ;AACV,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM;AAChC,YAAM,OAAO,MAAMA,eAAc,uBAAuB,MAAM;AAC9D,UAAI,KAAM,QAAO,KAAK;AAAA,IACxB;AAAA,EACF,SAAQ;AAAA,EAER;AACA,MAAI;AACF,UAAM,MAAM,YAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,iBAAiB,iBAAiB;AAC9E,WAAO,MAAM,UAAAC,SAAW,SAAS,KAAK,EAAE,UAAU,OAAO,CAAC;AAAA,EAC5D,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,eAAe,OAAgC;AAC7D,QAAM,gBAAkD,CAAC;AACzD,aAAW,OAAO,OAAO,KAAK,MAAM,OAAO,EAAE,KAAK,GAAG;AACnD,kBAAc,GAAG,IAAI,MAAM,QAAQ,GAAG;AAAA,EACxC;AACA,QAAM,UAA2B;AAAA,IAC/B,OAAO,MAAM;AAAA,IACb,KAAK,MAAM;AAAA,IACX,SAAS;AAAA,EACX;AACA,SAAO,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI;AAC5C;AAGO,SAAS,qBAAqB,OAAwB,WAAoC;AAC/F,QAAM,OAAO,qBAAqB,SAAS;AAC3C,MAAI,EAAE,QAAQ,MAAM,SAAU,QAAO;AACrC,QAAM,OAAyC,mBAAK,MAAM;AAC1D,SAAO,KAAK,IAAI;AAChB,SAAO,iCAAK,QAAL,EAAY,SAAS,KAAK;AACnC;AAGO,SAAS,mBACd,OACA,WACA,QACiB;AACjB,QAAM,OAAO,qBAAqB,SAAS;AAC3C,SAAO,iCACF,QADE;AAAA,IAEL,SAAS,iCAAK,MAAM,UAAX,EAAoB,CAAC,IAAI,GAAG,OAAO;AAAA,EAC9C;AACF;AAEA,eAAe,4BACb,UACA,aAIQ;AApJV;AAqJE,QAAM,MAAM,YAAAD,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,SAAS,QAAQ,aAAa,EAAE,CAAC;AAC7E,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,UAAAC,SAAW,SAAS,KAAK,EAAE,UAAU,OAAO,CAAC;AAAA,EAC3D,SAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,GAAG;AAAA,EACxB,SAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,kBAAiB,oCAAO,QAAP,mBAAY;AACnC,QAAM,aAAqC,CAAC;AAC5C,MAAI,OAAO,mBAAmB,UAAU;AACtC,UAAM,QAAQ,2BAA2B,UAAU,gBAAgB,WAAW;AAC9E,eAAW,CAAC,OAAO,CAAC,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,UAAI;AACF,mBAAW,KAAK,IAAI,MAAM,UAAAA,SAAW,SAAS,YAAAD,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,EAAE,QAAQ,aAAa,EAAE,CAAC,GAAG;AAAA,UACzG,UAAU;AAAA,QACZ,CAAC;AAAA,MACH,SAAQ;AACN,mBAAW,KAAK,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACA,SAAO,EAAE,OAAO,WAAW;AAC7B;AAYA,eAAsB,WACpB,UACA,SAKqF;AACrF,QAAM,EAAE,aAAa,OAAO,WAAW,mBAAmB,EAAE,IAAI;AAChE,QAAM,OAAO,qBAAqB,QAAQ;AAC1C,QAAM,SAAS,MAAM,4BAA4B,UAAU,WAAW;AACtE,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,OAAO,qBAAqB,OAAO,OAAO,OAAO,UAAU;AACjE,QAAM,OAAO,kBAAkB,IAAI;AAEnC,QAAM,WAAW,+BAAO,QAAQ;AAChC,MAAI,YAAY,SAAS,SAAS,SAAQ,+BAAO,SAAQ,SAAS,KAAK;AACrE,WAAO,EAAE,MAAM,MAAM,MAAM,KAAK,cAAc,SAAS,GAAG,GAAG,SAAS,KAAK;AAAA,EAC7E;AAEA,QAAM,CAAC,GAAG,IAAI,MAAM,SAAS,MAAM,CAAC,IAAI,CAAC;AACzC,SAAO,EAAE,MAAM,MAAM,MAAM,KAAK,SAAS,MAAM;AACjD;AAOA,eAAsB,qBACpB,OACA,YACA,UAGI,CAAC,GACqF;AAC1F,QAAM,EAAE,WAAW,mBAAmB,EAAE,IAAI;AAC5C,QAAM,OAAO,qBAAqB,OAAO,UAAU;AACnD,QAAM,OAAO,kBAAkB,IAAI;AACnC,QAAM,CAAC,GAAG,IAAI,MAAM,SAAS,MAAM,CAAC,IAAI,CAAC;AACzC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,QAAQ,EAAE,MAAM,KAAK,cAAc,GAAG,EAAE;AAAA,EAC1C;AACF;AAOA,eAAsB,SACpB,OACA,SAO0B;AAC1B,QAAM,EAAE,aAAa,UAAU,WAAW,mBAAmB,GAAG,WAAW,IAAI;AAC/E,QAAM,OAAO,WAAW,QAAQ;AAIhC,QAAM,UAA0B,CAAC;AACjC,MAAI,YAAY;AAEhB,aAAW,YAAY,OAAO;AAC5B,UAAM,OAAO,qBAAqB,QAAQ;AAC1C,UAAM,SAAS,MAAM,4BAA4B,UAAU,WAAW;AACtE,QAAI,CAAC,OAAQ;AACb,UAAM,OAAO,qBAAqB,OAAO,OAAO,OAAO,UAAU;AACjE,UAAM,OAAO,kBAAkB,IAAI;AACnC,UAAM,WAAW,qCAAU,QAAQ;AACnC,QAAI,YAAY,SAAS,SAAS,SAAQ,qCAAU,SAAQ,SAAS,KAAK;AACxE,WAAK,QAAQ,IAAI,IAAI;AACrB;AACA,+CAAa,WAAW,MAAM;AAC9B;AAAA,IACF;AACA,YAAQ,KAAK,EAAE,MAAM,MAAM,MAAM,KAAK,CAAC;AAAA,EACzC;AAGA,QAAM,QAAQ;AACd,WAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,OAAO;AAC9C,UAAM,QAAQ,QAAQ,MAAM,GAAG,IAAI,KAAK;AACxC,UAAM,OAAO,MAAM,SAAS,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAC1D,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,EAAE,MAAM,GAAG,KAAK,IAAI,MAAM,CAAC;AACjC,WAAK,QAAQ,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,KAAK,CAAC,CAAC,EAAE;AACtD;AACA,+CAAa,WAAW,MAAM;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;AApSA,IAcA,eACA,WACA,aAQa;AAxBb;AAAA;AAAA;AAcA,oBAA2B;AAC3B,gBAAuC;AACvC,kBAAiB;AAGjB;AACA;AACA;AACA;AAEO,IAAM,wBAAwB;AAAA;AAAA;;;ACWrC,SAASE,sBAAqB,GAAmB;AAC/C,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAEA,eAAe,aACb,YACA,QACA,SACA,cACe;AACf,MAAI,cAAc;AAChB,UAAM,EAAE,gBAAAC,gBAAe,IAAI,MAAM;AACjC,UAAMA,gBAAe,uBAAuB,YAAY,SAAS,MAAM;AACvE;AAAA,EACF;AACA,QAAM,MAAM,aAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,iBAAiB,iBAAiB;AAC9E,QAAM,WAAAC,SAAW,MAAM,aAAAD,QAAK,QAAQ,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AAC7D,QAAM,WAAAC,SAAW,UAAU,KAAK,YAAY,MAAM;AACpD;AAOA,eAAsB,0BAA0B,MAQ9B;AAChB,QAAM,EAAE,aAAa,WAAW,SAAS,YAAY,QAAQ,aAAa,IAAI;AAC9E,MAAI,CAAC,eAAe,WAAW,EAAG;AAElC,MAAI;AACF,UAAM,WAA4B,MAAM,eAAe,MAAM,EAAE,MAAM,MAAM,WAAW,CAAC;AACvF,UAAM,EAAE,OAAO,IAAI,MAAM,qBAAqB,SAAS,YAAY,EAAE,OAAO,SAAS,CAAC;AACtF,UAAM,OAAO,mBAAmB,UAAUH,sBAAqB,SAAS,GAAG,MAAM;AACjF,UAAM,aAAa,eAAe,IAAI,GAAG,QAAQ,8BAA8B,SAAS,IAAI,YAAY;AAAA,EAC1G,SAAS,GAAG;AACV,YAAQ,KAAK,8CAA8C,SAAS,KAAM,EAAY,OAAO,EAAE;AAAA,EACjG;AACF;AAMA,eAAsB,0BAA0B,MAK9B;AAChB,QAAM,EAAE,aAAa,WAAW,QAAQ,aAAa,IAAI;AACzD,MAAI,CAAC,eAAe,WAAW,EAAG;AAElC,MAAI;AACF,UAAM,WAA4B,MAAM,eAAe,MAAM,EAAE,MAAM,MAAM,WAAW,CAAC;AACvF,UAAM,OAAOA,sBAAqB,SAAS;AAC3C,QAAI,EAAE,QAAQ,SAAS,SAAU;AACjC,UAAM,OAAO,qBAAqB,UAAU,IAAI;AAChD,UAAM,aAAa,eAAe,IAAI,GAAG,QAAQ,8BAA8B,SAAS,IAAI,YAAY;AAAA,EAC1G,SAAS,GAAG;AACV,YAAQ,KAAK,gDAAgD,SAAS,KAAM,EAAY,OAAO,EAAE;AAAA,EACnG;AACF;AAxGA,IAkBAI,YACAC;AAnBA;AAAA;AAAA;AAkBA,IAAAD,aAAuC;AACvC,IAAAC,eAAiB;AAIjB;AACA;AAAA;AAAA;;;ACxBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAaO,SAAS,mBAAmB,QAAgB,gBAA4C;AAC7F,QAAM,aAAa,OAAO,YAAY,cAA6C;AACnF,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,OAAO,KAAK,WAAW,MAAM,EAAE,KAAK,CAAC,QAAQ,WAAW,OAAO,GAAG,EAAE,UAAU;AACvF;AAGO,SAAS,eAAe,QAAgB,UAA0B;AApBzE;AAqBE,QAAM,WAAW,SAAS,QAAQ,GAAG,OAAO,aAAa,KAAK,EAAE,EAAE,QAAQ,SAAS,EAAE;AACrF,QAAM,QAAQ,SAAS,MAAM,GAAG;AAChC,UAAO,WAAM,MAAM,SAAS,CAAC,MAAtB,YAA2B;AACpC;AAIO,SAAS,mBAAmB,QAAgB,UAA0B;AA5B7E;AA6BE,QAAM,eAAe,YAAoD,uBAApD,YAA0E;AAC/F,MAAI,SAAS,WAAW,GAAG,WAAW,GAAG,EAAG,QAAO;AACnD,QAAM,WAAW,SAAS,QAAQ,GAAG,OAAO,aAAa,KAAK,EAAE,EAAE,QAAQ,SAAS,EAAE;AACrF,QAAM,QAAQ,SAAS,MAAM,GAAG;AAChC,UAAO,WAAM,CAAC,MAAP,YAAY;AACrB;AAYO,SAAS,kBAAkB,QAAgB,UAAkB,OAAgD;AA9CpH;AA+CE,QAAM,WAAW,eAAe,QAAQ,QAAQ;AAChD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,iBAAiB,SAAO,WAAM,QAAN,mBAAW,UAAS,WAAW,MAAM,IAAI,OAAO,mBAAmB,QAAQ,QAAQ;AAGjH,MAAI,mBAAmB,SAAS;AAC9B,UAAM,cAAa,WAAM,WAAN,mBAAc;AACjC,QAAI,OAAO,eAAe,YAAY,WAAW,KAAK,MAAM,GAAI,QAAO,WAAW,KAAK;AACvF,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,mBAAmB,QAAQ,cAAc;AAC5D,MAAI,YAAY;AACd,UAAM,SAAQ,WAAM,WAAN,mBAAe;AAC7B,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,MAAM,GAAI,QAAO,MAAM,KAAK;AACxE,QAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AAAA,EAClF;AAEA,SAAO;AACT;AAMO,SAAS,eAAe,QAAgB,UAAkB,OAAgD;AAzEjH;AA0EE,QAAM,WAAW,eAAe,QAAQ,QAAQ;AAChD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,iBAAiB,SAAO,WAAM,QAAN,mBAAW,UAAS,WAAW,MAAM,IAAI,OAAO,mBAAmB,QAAQ,QAAQ;AACjH,MAAI,mBAAmB,SAAS;AAC9B,UAAM,SAAQ,WAAM,QAAN,mBAAW;AACzB,QAAI,OAAO,UAAU,YAAY,UAAU,GAAI,QAAO;AAAA,EACxD;AACA,SAAO;AACT;AAOO,SAAS,kBACd,QACA,UACA,OACA,SAAS,KACD;AA9FV;AA+FE,MAAI,EAAC,+BAAO,QAAQ,QAAO;AAC3B,QAAM,iBAAiB,SAAO,WAAM,QAAN,mBAAW,UAAS,WAAW,MAAM,IAAI,OAAO,mBAAmB,QAAQ,QAAQ;AACjH,QAAM,aAAa,mBAAmB,QAAQ,cAAc;AAC5D,QAAM,aAAa,OAAO,YAAY,cAA6C;AACnF,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,mBAAmB,oBAAI,IAAI,CAAC,QAAQ,YAAY,YAAY,QAAQ,CAAC;AAC3E,aAAW,CAAC,UAAU,QAAQ,KAAK,OAAO,QAAQ,WAAW,MAAM,GAAG;AACpE,QAAI,aAAa,WAAY;AAC7B,QAAI,CAAC,iBAAiB,IAAI,SAAS,MAAM,EAAG;AAC5C,UAAM,QAAQ,MAAM,OAAO,QAAQ;AACnC,UAAM,OAAO,oBAAoB,KAAK;AACtC,QAAI,KAAM,QAAO,SAAS,MAAM,MAAM;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAAwB;AACnD,MAAI,OAAO,UAAU,SAAU,QAAO,MAAM,KAAK;AACjD,MAAI,MAAM,QAAQ,KAAK;AACrB,WAAO,MACJ,OAAO,CAAC,MAAM,OAAO,MAAM,QAAQ,EACnC,KAAK,IAAI,EACT,KAAK;AACV,SAAO;AACT;AAEA,SAAS,SAAS,MAAc,QAAwB;AACtD,QAAM,YAAY,KAAK,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACjD,MAAI,UAAU,UAAU,OAAQ,QAAO;AACvC,SAAO,UAAU,MAAM,GAAG,SAAS,CAAC,EAAE,QAAQ,IAAI;AACpD;AA9HA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IASA;AATA;AAAA;AAAA;AASA,wBAAO;AAAA;AAAA;;;ACsBP,eAAsB,wBAAwB,SAAiB,KAAgC;AAC7F,SAAO,6BAA6B,SAAS,CAAC,GAAG,GAAG,IAAI;AAC1D;AAQA,eAAsB,6BACpB,SACA,YACA,YAAY,OACO;AACnB,QAAM,UAAU,aAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO;AAChD,QAAM,iBAAiB,WAAW,IAAI,CAAC,MAAO,EAAE,WAAW,GAAG,IAAI,IAAI,IAAI,CAAC,EAAG;AAE9E,MAAI;AACF,QAAI,WAAW;AACb,YAAM,QAAS,MAAM,gBAAAC,QAAW,QAAQ,SAAS,EAAE,WAAW,KAAK,CAAC;AACpE,aAAO,MACJ,OAAO,CAAC,MAAM,eAAe,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EACvD,IAAI,CAAC,MAAM,GAAG,OAAO,IAAI,CAAC,GAAG,QAAQ,OAAO,GAAG,CAAC,EAChD,KAAK;AAAA,IACV;AAEA,UAAM,UAAU,MAAM,gBAAAA,QAAW,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;AACzE,WAAQ,QACL,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,eAAe,KAAK,CAAC,QAAQ,EAAE,KAAK,SAAS,GAAG,CAAC,CAAC,EAC9E,IAAI,CAAC,MAAM,GAAG,OAAO,IAAI,EAAE,IAAI,EAAE,EACjC,KAAK;AAAA,EACV,SAAS,OAAY;AACnB,SAAI,+BAAO,UAAS,SAAU,QAAO,CAAC;AACtC,UAAM;AAAA,EACR;AACF;AAGA,eAAsB,yBAAyB,SAAoC;AACjF,QAAM,UAAU,aAAAD,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO;AAChD,MAAI;AACF,UAAM,UAAU,MAAM,gBAAAC,QAAW,QAAQ,SAAS,EAAE,eAAe,KAAK,CAAC;AACzE,WAAO,QAAQ,OAAO,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,KAAK,SAAS,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,IAAI,EAAE,IAAI,EAAE;AAAA,EACxG,SAAS,OAAY;AACnB,SAAI,+BAAO,UAAS,SAAU,QAAO,CAAC;AACtC,UAAM;AAAA,EACR;AACF;AA/EA,qBACAC;AADA;AAAA;AAAA;AAAA,sBAAuB;AACvB,IAAAA,eAAiB;AAAA;AAAA;;;ACDjB,gBAGa,0BAEP,uBAYA,YAEO,wBAeA,4BA+CA,yBAwBA;AAzGb;AAAA;AAAA;AAAA,iBAAkB;AAGX,IAAM,2BAA2B;AAExC,IAAM,wBAAwB,aAAE,OAAO;AAAA,MACrC,OAAO,aAAE,OAAO;AAAA,MAChB,aAAa,aAAE,OAAO,EAAE,SAAS;AAAA,MACjC,WAAW,aAAE,OAAO;AAAA,MACpB,SAAS,aAAE,MAAM,aAAE,OAAO,CAAC;AAAA,IAC7B,CAAC;AAOD,IAAM,aAAa,aAAE,OAAO,aAAE,OAAO,GAAG,qBAAqB;AAEtD,IAAM,yBAAyB,CAAC,YAAuC;AAC5E,YAAM,UAAU,QAAQ,KAAK;AAC7B,UAAI,CAAC,SAAS;AACZ,eAAO,CAAC;AAAA,MACV;AAEA,UAAI;AACF,cAAM,SAAkB,KAAK,MAAM,OAAO;AAC1C,cAAM,SAAS,WAAW,UAAU,MAAM;AAC1C,eAAO,OAAO,UAAU,OAAO,OAAO,CAAC;AAAA,MACzC,SAAQ;AACN,eAAO,CAAC;AAAA,MACV;AAAA,IACF;AAEO,IAAM,6BAA6B,CAAC,SAAoC,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA;AA+CxG,IAAM,0BAA0B,CACrC,MACA,YACA,cACsB;AACtB,YAAM,WAAW,KAAK,UAAU;AAChC,UAAI,CAAC,UAAU;AACb,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,QAAQ,SAAS,SAAS,GAAG;AACxC,eAAO;AAAA,MACT;AAEA,aAAO,iCACF,OADE;AAAA,QAEL,CAAC,UAAU,GAAG,iCACT,WADS;AAAA,UAEZ,SAAS,CAAC,GAAG,SAAS,SAAS,SAAS;AAAA,QAC1C;AAAA,MACF;AAAA,IACF;AAGO,IAAM,uCAAuC,CAClD,SACA,YACA,cACkB;AAClB,YAAM,OAAO,uBAAuB,OAAO;AAC3C,UAAI,CAAC,KAAK,UAAU,GAAG;AACrB,eAAO;AAAA,MACT;AAEA,YAAM,OAAO,wBAAwB,MAAM,YAAY,SAAS;AAChE,UAAI,SAAS,MAAM;AACjB,eAAO;AAAA,MACT;AAEA,aAAO,2BAA2B,IAAI;AAAA,IACxC;AAAA;AAAA;;;ACnHO,SAAS,yBAAyB,gBAAiD;AACxF,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,OAAO,YAAY,cAA6C;AAC5E,MAAI,CAAC,KAAK;AACR,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,MAA+B,CAAC;AAEtC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,IAAI,MAAM,GAAG;AACnD,QAAI,IAAI,WAAW,aAAa,IAAI,mBAAmB,QAAW;AAChE,UAAI,GAAG,IAAI,IAAI,iBAAiB,SAAS;AACzC;AAAA,IACF;AAEA,QAAI,IAAI,WAAW,UAAU;AAC3B,YAAM,UAAU,IAAI,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACvD,UAAI,IAAI,aAAa,MAAM;AACzB,cAAM,MAAM,IAAI;AAChB,YAAI,2BAAK,QAAQ;AACf,gBAAM,OAAO,IAAI,OAAO,CAAC,MAAM,QAAQ,IAAI,CAAC,CAAC;AAC7C,cAAI,KAAK,SAAS,GAAG;AACnB,gBAAI,GAAG,IAAI;AAAA,UACb;AAAA,QACF;AAAA,MACF,WAAW,IAAI,iBAAiB,QAAQ,QAAQ,IAAI,IAAI,aAAa,GAAG;AACtE,YAAI,GAAG,IAAI,IAAI;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAtCA;AAAA;AAAA;AACA,IAAAC;AAAA;AAAA;;;ACOO,SAAS,kBAAkB,KAA4B;AAC5D,QAAM,IAAI,IAAI,KAAK;AACnB,MAAI,CAAC,GAAG;AACN,WAAO;AAAA,EACT;AACA,QAAM,KAAK,KAAK,KAAK,CAAC;AACtB,MAAI,IAAI;AACN,WAAO,IAAI,GAAG,CAAC,EAAG,YAAY,CAAC;AAAA,EACjC;AACA,QAAM,KAAK,KAAK,KAAK,CAAC;AACtB,MAAI,IAAI;AACN,UAAM,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,EAAG,MAAM,EAAE;AACjC,WAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,YAAY;AAAA,EACjD;AACA,SAAO;AACT;AAEO,SAAS,qBACd,KACA,KAC8D;AAC9D,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,SAAS;AACZ,QAAI,IAAI,UAAU;AAChB,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,IAAI,KAAK,eAAe;AAAA,IAC1D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,GAAG;AAAA,EAC/B;AACA,QAAM,aAAa,kBAAkB,OAAO;AAC5C,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,GAAG,IAAI,KAAK;AAAA,IACvB;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,WAAW;AACvC;AA5CA,IAEM,MACA;AAHN;AAAA;AAAA;AAEA,IAAM,OAAO;AACb,IAAM,OAAO;AAAA;AAAA;;;ACyCN,SAAS,qBAAqB,SAAiB,UAA2B;AAC/E,MAAI,UAAU;AACZ,QAAI,CAAC,sBAAsB,KAAK,OAAO,GAAG;AACxC,YAAM,IAAI,MAAM,cAAc;AAAA,IAChC;AACA,UAAM,CAAC,GAAG,GAAG,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,IAAI,MAAM;AACjD,UAAMC,KAAI,IAAI,KAAK,GAAG,IAAI,GAAG,GAAG;AAChC,QAAIA,GAAE,YAAY,MAAM,KAAKA,GAAE,SAAS,MAAM,IAAI,KAAKA,GAAE,QAAQ,MAAM,KAAK;AAC1E,YAAM,IAAI,MAAM,cAAc;AAAA,IAChC;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI,IAAI,KAAK,OAAO;AAC1B,MAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,GAAG;AAC7B,UAAM,IAAI,MAAM,kBAAkB;AAAA,EACpC;AACA,SAAO,EAAE,YAAY;AACvB;AAOO,SAAS,wBAAwB,OAAwB,KAAuC;AACrG,MAAI,MAAM,WAAW,YAAY;AAC/B,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AAEA,QAAM,WAAW,MAAM,aAAa;AACpC,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,YAAY,IAAI;AAClB,QAAI,MAAM,UAAU;AAClB,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,eAAe;AAAA,IAC5D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,EACjC;AAEA,MAAI;AACF,WAAO,EAAE,IAAI,MAAM,OAAO,qBAAqB,SAAS,QAAQ,EAAE;AAAA,EACpE,SAAQ;AACN,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,GAAG,MAAM,KAAK,oBAAoB,WAAW,SAAS,eAAe;AAAA,IAChF;AAAA,EACF;AACF;AA1FA;AAAA;AAAA;AAAA;AAAA;;;AC4BO,SAAS,oBAAoB,OAAwB,KAAmC;AAC7F,MAAI,MAAM,WAAW,QAAQ;AAC3B,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AAEA,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,YAAY,IAAI;AAClB,QAAI,MAAM,UAAU;AAClB,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,eAAe;AAAA,IAC5D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,EACjC;AAEA,MAAI,IAAI,SAAS,0BAA0B;AACzC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,GAAG,MAAM,KAAK,oBAAoB,yBAAyB,eAAe,CAAC;AAAA,IACtF;AAAA,EACF;AAEA,MAAI;AACF,WAAO,EAAE,IAAI,MAAM,OAAO,KAAK,MAAM,OAAO,EAAE;AAAA,EAChD,SAAQ;AACN,WAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,sBAAsB;AAAA,EACnE;AACF;AArDA,IAGa;AAHb;AAAA;AAAA;AAGO,IAAM,2BAA2B;AAAA;AAAA;;;ACIjC,SAAS,sBAAsB,OAAwB,KAAqC;AACjG,MAAI,MAAM,WAAW,UAAU;AAC7B,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAEA,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,YAAY,IAAI;AAClB,QAAI,MAAM,UAAU;AAClB,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,eAAe;AAAA,IAC5D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,KAAK;AAAA,EACjC;AAEA,QAAM,MAAM,OAAO,OAAO;AAC1B,MAAI,CAAC,OAAO,SAAS,GAAG,GAAG;AACzB,WAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,0BAA0B;AAAA,EACvE;AAEA,MAAI,MAAM,cAAc,SAAS,CAAC,OAAO,UAAU,GAAG,GAAG;AACvD,WAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,0BAA0B;AAAA,EACvE;AAEA,MAAI,MAAM,OAAO,QAAQ,MAAM,MAAM,KAAK;AACxC,WAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,qBAAqB,MAAM,GAAG,GAAG;AAAA,EAC9E;AACA,MAAI,MAAM,OAAO,QAAQ,MAAM,MAAM,KAAK;AACxC,WAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,oBAAoB,MAAM,GAAG,GAAG;AAAA,EAC7E;AAEA,QAAM,SAAS,MAAM,cAAc,QAAQ,KAAK,MAAM,GAAG,IAAI;AAC7D,SAAO,EAAE,IAAI,MAAM,OAAO,OAAO;AACnC;AAtCA;AAAA;AAAA;AAAA;AAAA;;;ACIA,SAAS,cAAc,OAA2C;AAChE,SAAO,IAAI,IAAI,MAAM,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAClD;AAKO,SAAS,sBAAsB,OAA8B,KAAqC;AACvG,QAAM,UAAU,cAAc,KAAK;AACnC,QAAM,WAAW,MAAM,aAAa;AAEpC,MAAI,UAAU;AACZ,UAAM,UAAU,IAAI,KAAK;AACzB,QAAI,YAAY,IAAI;AAClB,UAAI,MAAM,UAAU;AAClB,eAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,eAAe;AAAA,MAC5D;AACA,aAAO,EAAE,IAAI,MAAM,OAAO,CAAC,EAAE;AAAA,IAC/B;AACA,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,OAAO;AAAA,IAC7B,SAAQ;AACN,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,oBAAoB;AAAA,IACjE;AACA,QAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,wBAAwB;AAAA,IACrE;AACA,UAAM,UAAU,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAC3C,eAAW,KAAK,SAAS;AACvB,UAAI,CAAC,QAAQ,IAAI,CAAC,GAAG;AACnB,eAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,8BAA8B;AAAA,MAC3E;AAAA,IACF;AACA,QAAI,MAAM,YAAY,QAAQ,WAAW,GAAG;AAC1C,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,eAAe;AAAA,IAC5D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,QAAQ;AAAA,EACpC;AAEA,QAAM,IAAI,IAAI,KAAK;AACnB,MAAI,MAAM,IAAI;AACZ,QAAI,MAAM,UAAU;AAClB,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,eAAe;AAAA,IAC5D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,GAAG;AAAA,EAC/B;AACA,MAAI,CAAC,QAAQ,IAAI,CAAC,GAAG;AACnB,WAAO,EAAE,IAAI,OAAO,SAAS,GAAG,MAAM,KAAK,yBAAyB;AAAA,EACtE;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,EAAE;AAC9B;AAvDA;AAAA;AAAA;AAAA;AAAA;;;ACSO,SAAS,mBAAmB,GAAoB;AACrD,SAAO,EAAE,SAAS,KAAK,EAAE,UAAU,mBAAmB,WAAW,KAAK,CAAC;AACzE;AAwBO,SAAS,cAAc,OAAuB;AACnD,QAAM,UAAU,OAAO,KAAK,EAAE,KAAK;AACnC,QAAM,eAAe,QAAQ,QAAQ,OAAO,GAAG,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAC3E,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AACA,QAAM,UAAM,eAAAC,SAAQ,cAAc,EAAE,OAAO,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC;AAC3E,MAAI,YAAY,IAAI,QAAQ,OAAO,GAAG,EAAE,QAAQ,UAAU,EAAE;AAC5D,MAAI,UAAU,SAAS,iBAAiB;AACtC,gBAAY,UAAU,MAAM,GAAG,eAAe,EAAE,QAAQ,QAAQ,EAAE;AAAA,EACpE;AACA,SAAO;AACT;AAKO,SAAS,oBAAoB,KAAqB;AACvD,SAAO,cAAc,GAAG;AAC1B;AAEO,SAAS,oBACd,KACA,KAC8D;AAC9D,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,SAAS;AACZ,QAAI,IAAI,UAAU;AAChB,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,IAAI,KAAK,eAAe;AAAA,IAC1D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,GAAG;AAAA,EAC/B;AACA,QAAM,YAAY,cAAc,OAAO;AACvC,MAAI,CAAC,mBAAmB,SAAS,GAAG;AAClC,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,GAAG,IAAI,KAAK;AAAA,IACvB;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,UAAU;AACtC;AA3EA,oBAKa,iBAEP;AAPN;AAAA;AAAA;AAAA,qBAAoB;AAKb,IAAM,kBAAkB;AAE/B,IAAM,aAAa;AAAA;AAAA;;;ACaZ,SAAS,uBAAuB,KAAwC;AAC7E,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,YAAY,IAAI;AAClB,WAAO,EAAE,IAAI,MAAM,OAAO,CAAC,EAAE;AAAA,EAC/B;AACA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,OAAO;AAAA,EAC7B,SAAQ;AACN,WAAO,EAAE,IAAI,OAAO,SAAS,oBAAoB;AAAA,EACnD;AACA,MAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,WAAO,EAAE,IAAI,OAAO,SAAS,kCAAkC;AAAA,EACjE;AACA,QAAM,QAAkB,CAAC;AACzB,aAAW,MAAM,QAAQ;AACvB,UAAM,IAAI,OAAO,EAAE,EAAE,KAAK;AAC1B,QAAI,EAAE,SAAS,GAAG;AAChB,YAAM,KAAK,CAAC;AAAA,IACd;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,MAAM;AAC3B;AA1CA;AAAA;AAAA;AAAA;AAAA;;;ACEA,SAAS,gBAAgB,GAAoB;AAC3C,MAAI,EAAE,WAAW,UAAU,KAAK,EAAE,WAAW,SAAS,GAAG;AACvD,WAAO;AAAA,EACT;AACA,MAAI,EAAE,WAAW,GAAG,GAAG;AACrB,WAAO,CAAC,EAAE,WAAW,IAAI;AAAA,EAC3B;AACA,SAAO;AACT;AAEO,SAAS,mBACd,KACA,KAC8D;AAC9D,QAAM,UAAU,IAAI,KAAK;AACzB,MAAI,CAAC,SAAS;AACZ,QAAI,IAAI,UAAU;AAChB,aAAO,EAAE,IAAI,OAAO,SAAS,GAAG,IAAI,KAAK,eAAe;AAAA,IAC1D;AACA,WAAO,EAAE,IAAI,MAAM,OAAO,GAAG;AAAA,EAC/B;AACA,MAAI,CAAC,gBAAgB,OAAO,GAAG;AAC7B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS,GAAG,IAAI,KAAK;AAAA,IACvB;AAAA,EACF;AACA,SAAO,EAAE,IAAI,MAAM,OAAO,QAAQ;AACpC;AA9BA;AAAA;AAAA;AAAA;AAAA;;;ACcO,SAAS,+BACd,gBACA,WACyB;AAjB3B;AAkBE,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,OAAO,YAAY,cAA6C;AAC5E,MAAI,CAAC,KAAK;AACR,WAAO,mBAAK;AAAA,EACd;AAEA,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC9C,UAAM,MAAM,IAAI,OAAO,CAAC;AACxB,SAAI,2BAAK,YAAW,UAAU;AAC5B,YAAM,IAAI,sBAAsB,KAAK,CAAC;AACtC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,YAAY;AACrC,YAAM,IAAI,wBAAwB,KAAK,CAAC;AACxC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,QAAQ;AACjC,YAAM,IAAI,oBAAoB,KAAK,CAAC;AACpC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,YAAY,IAAI,MAAM;AAC/C,YAAM,IAAI,uBAAuB,CAAC;AAClC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,QAAQ;AACjC,YAAM,IAAI,oBAAoB,KAAK,CAAC;AACpC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,UAAU;AACnC,YAAM,IAAI,sBAAsB,KAAK,CAAC;AACtC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,QAAQ;AACjC,YAAM,UAAU,EAAE,KAAK;AACvB,UAAI,IAAI,YAAY,CAAC,SAAS;AAC5B,cAAM,IAAI,MAAM,GAAG,IAAI,KAAK,cAAc;AAAA,MAC5C;AACA,UAAI,CAAC,IAAI;AAAA,IACX,YAAW,2BAAK,YAAW,OAAO;AAChC,YAAM,IAAI,mBAAmB,KAAK,CAAC;AACnC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,SAAS;AAClC,YAAM,IAAI,qBAAqB,KAAK,CAAC;AACrC,UAAI,CAAC,EAAE,IAAI;AACT,cAAM,IAAI,MAAM,EAAE,OAAO;AAAA,MAC3B;AACA,UAAI,CAAC,IAAI,EAAE;AAAA,IACb,YAAW,2BAAK,YAAW,eAAc,2BAAK,YAAW,YAAY;AACnE,UAAI,CAAC,IAAI;AAAA,IACX,YAAW,2BAAK,YAAW,eAAe;AAExC,UAAI;AACJ,UAAI;AACF,iBAAS,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC;AAAA,MAChC,SAAQ;AACN,iBAAS,CAAC;AAAA,MACZ;AAEA,UAAI,OAAO,WAAW,YAAY,UAAU,CAAC,MAAM,QAAQ,MAAM,GAAG;AAClE,cAAM,MAAM;AACZ,cAAM,SAAkC,CAAC;AAEzC,mBAAW,UAAU,IAAI,YAAY,UAAU;AAC7C,gBAAM,cAAc,IAAI,OAAO,GAAG;AAClC,cAAI,OAAO,YAAY;AAErB,mBAAO,OAAO,GAAG,IAAI,OAAO,gBAAgB,WAAW,cAAc;AAAA,UACvE,WAAW,OAAO,QAAQ;AAExB,kBAAM,YACJ,OAAO,gBAAgB,YAAY,eAAe,CAAC,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC;AAGjG,kBAAM,SAAkC,CAAC;AACzC,uBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AAC1D,oBAAM,QAAO,eAAU,IAAI,MAAd,YAAmB;AAChC,oBAAM,SAAS,SAAS,QAAQ,SAAS,SAAY,KAAK,OAAO,IAAI;AACrE,qBAAO,IAAI,IAAI,mBAAmB,QAAQ,MAAM;AAAA,YAClD;AACA,mBAAO,OAAO,GAAG,IAAI;AAAA,UACvB;AAAA,QACF;AACA,YAAI,CAAC,IAAI;AAAA,MACX,OAAO;AACL,YAAI,CAAC,IAAI,CAAC;AAAA,MACZ;AAAA,IACF,OAAO;AACL,UAAI,CAAC,IAAI;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,mBAAmB,KAAsB,KAAsB;AACtE,UAAQ,IAAI,QAAQ;AAAA,IAClB,KAAK,UAAU;AACb,YAAM,IAAI,sBAAsB,KAAK,GAAG;AACxC,aAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,IAC1B;AAAA,IACA,KAAK,YAAY;AACf,YAAM,IAAI,wBAAwB,KAAK,GAAG;AAC1C,aAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,IAC1B;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,IAAI,oBAAoB,KAAK,GAAG;AACtC,aAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,IAC1B;AAAA,IACA,KAAK;AACH,UAAI,IAAI,MAAM;AACZ,cAAM,IAAI,uBAAuB,GAAG;AACpC,eAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,MAC1B;AACA,aAAO;AAAA,IACT,KAAK,QAAQ;AACX,YAAM,IAAI,oBAAoB,KAAK,GAAG;AACtC,aAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,IAC1B;AAAA,IACA,KAAK,UAAU;AACb,YAAM,IAAI,sBAAsB,KAAK,GAAG;AACxC,aAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,IAC1B;AAAA,IACA,KAAK;AACH,aAAO,IAAI,KAAK;AAAA,IAClB,KAAK,OAAO;AACV,YAAM,IAAI,mBAAmB,KAAK,GAAG;AACrC,aAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,IAC1B;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,IAAI,qBAAqB,KAAK,GAAG;AACvC,aAAO,EAAE,KAAK,EAAE,QAAQ;AAAA,IAC1B;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AA3KA;AAAA;AAAA;AACA,IAAAC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;;;ACTA;AAAA;AAAA;AAAA;AAaA,SAAS,oBAAoB,KAAa,aAAuC;AAC/E,MAAI,gBAAgB,OAAO;AACzB,UAAM,IAAI,IAAI,KAAK;AACnB,WAAO,IAAI,CAAC,CAAC,IAAI,CAAC;AAAA,EACpB;AACA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO,CAAC;AACpC,WAAO,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,CAAC;AAAA,EACpC,SAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,uBACP,OACA,KACe;AA9BjB;AA+BE,QAAM,eAAc,iBAAM,cAAN,mBAAiB,gBAAjB,YAAgC;AACpD,QAAM,QAAQ,oBAAoB,KAAK,WAAW;AAClD,QAAM,MAAM,gBAAgB,QAAQ,KAAI,WAAM,cAAN,mBAAiB;AAEzD,QAAM,cAAa,iBAAM,cAAN,mBAAiB,QAAjB,YAAwB;AAC3C,QAAM,kBAAkB,MAAM,WAAW,IAAI;AAC7C,QAAM,eAAe,KAAK,IAAI,YAAY,eAAe;AAEzD,MAAI,gBAAgB,OAAO;AACzB,UAAM,QAAQ,MAAM,SAAS,KAAK,MAAM,CAAC,IAAI,IAAI;AACjD,QAAI,eAAe,KAAK,QAAQ,GAAG;AACjC,aAAO,GAAG,MAAM,KAAK;AAAA,IACvB;AACA,QAAI,QAAQ,KAAK,MAAM,SAAS,GAAG;AACjC,aAAO,GAAG,MAAM,KAAK;AAAA,IACvB;AACA,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,SAAS,cAAc;AAC/B,WAAO,iBAAiB,IACpB,GAAG,MAAM,KAAK,iBACd,YAAY,YAAY,uBAAuB,MAAM,KAAK;AAAA,EAChE;AACA,MAAI,OAAO,QAAQ,MAAM,SAAS,KAAK;AACrC,WAAO,WAAW,GAAG,sBAAsB,MAAM,KAAK;AAAA,EACxD;AACA,SAAO;AACT;AAKO,SAAS,oBACd,gBACA,QACmE;AAnErE;AAoEE,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,OAAO,YAAY,cAA6C;AAC5E,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAEA,QAAM,cAAsC,CAAC;AAE7C,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,IAAI,MAAM,GAAG;AACnD,UAAM,OAAM,YAAO,GAAG,MAAV,YAAe;AAC3B,QAAI,UAAyB;AAE7B,YAAQ,IAAI,QAAQ;AAAA,MAClB,KAAK,UAAU;AACb,YAAI,IAAI,MAAM;AACZ,gBAAM,SAAS,uBAAuB,GAAG;AACzC,cAAI,CAAC,OAAO,IAAI;AACd,sBAAU,OAAO;AAAA,UACnB,WAAW,IAAI,YAAY,OAAO,MAAM,WAAW,GAAG;AACpD,sBAAU,GAAG,IAAI,KAAK;AAAA,UACxB;AAAA,QACF,OAAO;AACL,gBAAM,SAAS,IAAI,WAAW,cAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,GAAG,IAAI,KAAK,cAAc,IAAI,cAAE,OAAO;AAC9F,gBAAM,SAAS,OAAO,UAAU,GAAG;AACnC,cAAI,CAAC,OAAO,SAAS;AACnB,uBAAU,kBAAO,MAAM,OAAO,CAAC,MAArB,mBAAwB,YAAxB,YAAmC;AAAA,UAC/C;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AACX,cAAM,SAAS,IAAI,WAAW,cAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,GAAG,IAAI,KAAK,cAAc,IAAI,cAAE,OAAO;AAC9F,cAAM,SAAS,OAAO,UAAU,GAAG;AACnC,YAAI,CAAC,OAAO,SAAS;AACnB,qBAAU,kBAAO,MAAM,OAAO,CAAC,MAArB,mBAAwB,YAAxB,YAAmC;AAAA,QAC/C;AACA;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK,YAAY;AACf,cAAM,SAAS,IAAI,WAAW,cAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,GAAG,IAAI,KAAK,cAAc,IAAI,cAAE,OAAO;AAC9F,cAAM,SAAS,OAAO,UAAU,GAAG;AACnC,YAAI,CAAC,OAAO,SAAS;AACnB,qBAAU,kBAAO,MAAM,OAAO,CAAC,MAArB,mBAAwB,YAAxB,YAAmC;AAAA,QAC/C;AACA;AAAA,MACF;AAAA,MACA,KAAK,SAAS;AACZ,cAAM,SAAS,IAAI,WAAW,cAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,GAAG,IAAI,KAAK,cAAc,IAAI,cAAE,OAAO;AAC9F,cAAM,SAAS,OAAO,UAAU,GAAG;AACnC,YAAI,CAAC,OAAO,SAAS;AACnB,qBAAU,kBAAO,MAAM,OAAO,CAAC,MAArB,mBAAwB,YAAxB,YAAmC;AAAA,QAC/C;AACA;AAAA,MACF;AAAA,MACA,KAAK,WAAW;AACd,cAAM,SAAS,cAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,UAAU,GAAG;AACtD,YAAI,CAAC,OAAO,SAAS;AACnB,oBAAU,GAAG,IAAI,KAAK;AAAA,QACxB;AACA;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,cAAM,SAAS,sBAAsB,KAAK,GAAG;AAC7C,YAAI,CAAC,OAAO,IAAI;AACd,oBAAU,OAAO;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA,KAAK,YAAY;AACf,cAAM,SAAS,wBAAwB,KAAK,GAAG;AAC/C,YAAI,CAAC,OAAO,IAAI;AACd,oBAAU,OAAO;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA,KAAK,aAAa;AAChB,kBAAU,uBAAuB,KAAK,GAAG;AACzC;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AACX,cAAM,SAAS,oBAAoB,KAAK,GAAG;AAC3C,YAAI,CAAC,OAAO,IAAI;AACd,oBAAU,OAAO;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AACX,cAAM,SAAS,oBAAoB,KAAK,GAAG;AAC3C,YAAI,CAAC,OAAO,IAAI;AACd,oBAAU,OAAO;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,cAAM,SAAS,sBAAsB,KAAK,GAAG;AAC7C,YAAI,CAAC,OAAO,IAAI;AACd,oBAAU,OAAO;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA,KAAK,OAAO;AACV,cAAM,SAAS,mBAAmB,KAAK,GAAG;AAC1C,YAAI,CAAC,OAAO,IAAI;AACd,oBAAU,OAAO;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA,KAAK,SAAS;AACZ,cAAM,SAAS,qBAAqB,KAAK,GAAG;AAC5C,YAAI,CAAC,OAAO,IAAI;AACd,oBAAU,OAAO;AAAA,QACnB;AACA;AAAA,MACF;AAAA,MACA,KAAK,eAAe;AAClB,kBAAU,yBAAyB,KAAK,KAAK,KAAK,WAAW;AAC7D;AAAA,MACF;AAAA,MACA;AACE;AAAA,IACJ;AAEA,QAAI,SAAS;AACX,kBAAY,GAAG,IAAI;AAAA,IACrB;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,WAAW,EAAE,WAAW,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,OAAO,YAAY;AACzF;AAMA,SAAS,yBACP,KACA,KACA,WACA,aACe;AAhNjB;AAiNE,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAAA,EACjC,SAAQ;AACN,WAAO,GAAG,IAAI,KAAK;AAAA,EACrB;AAEA,MAAI,OAAO,QAAQ,YAAY,QAAQ,QAAQ,MAAM,QAAQ,GAAG,GAAG;AACjE,WAAO,GAAG,IAAI,KAAK;AAAA,EACrB;AAEA,aAAW,UAAU,IAAI,YAAY,UAAU;AAC7C,UAAM,cAAc,IAAI,OAAO,GAAG;AAElC,QAAI,OAAO,YAAY;AAErB,UAAI,IAAI,aAAa,CAAC,eAAe,OAAO,gBAAgB,YAAY,CAAC,OAAO,WAAW,EAAE,KAAK,IAAI;AACpG,oBAAY,GAAG,SAAS,IAAI,OAAO,GAAG,EAAE,IAAI,GAAG,OAAO,KAAK;AAAA,MAC7D;AAAA,IACF,WAAW,OAAO,QAAQ;AAExB,YAAM,YACJ,OAAO,gBAAgB,YAAY,eAAe,CAAC,MAAM,QAAQ,WAAW,IAAI,cAAc,CAAC;AAGjG,iBAAW,CAAC,QAAQ,MAAM,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AAC5D,cAAM,UAAS,eAAU,MAAM,MAAhB,YAAqB;AACpC,cAAM,SAAS,WAAW,QAAQ,WAAW,SAAY,KAAK,OAAO,MAAM;AAC3E,cAAM,aAAa,oBAAoB,QAAQ,MAAM;AACrD,YAAI,YAAY;AACd,sBAAY,GAAG,SAAS,IAAI,OAAO,GAAG,IAAI,MAAM,EAAE,IAAI;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,oBAAoB,KAAsB,KAA4B;AA5P/E;AA6PE,UAAQ,IAAI,QAAQ;AAAA,IAClB,KAAK,UAAU;AACb,UAAI,IAAI,MAAM;AACZ,cAAM,SAAS,uBAAuB,GAAG;AACzC,YAAI,CAAC,OAAO,GAAI,QAAO,OAAO;AAC9B,YAAI,IAAI,YAAY,OAAO,MAAM,WAAW,EAAG,QAAO,GAAG,IAAI,KAAK;AAAA,MACpE,OAAO;AACL,cAAM,SAAS,IAAI,WAAW,cAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,GAAG,IAAI,KAAK,cAAc,IAAI,cAAE,OAAO;AAC9F,cAAM,SAAS,OAAO,UAAU,GAAG;AACnC,YAAI,CAAC,OAAO,QAAS,SAAO,kBAAO,MAAM,OAAO,CAAC,MAArB,mBAAwB,YAAxB,YAAmC;AAAA,MACjE;AACA,aAAO;AAAA,IACT;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK,SAAS;AACZ,YAAM,SAAS,IAAI,WAAW,cAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,GAAG,IAAI,KAAK,cAAc,IAAI,cAAE,OAAO;AAC9F,YAAM,SAAS,OAAO,UAAU,GAAG;AACnC,UAAI,CAAC,OAAO,QAAS,SAAO,kBAAO,MAAM,OAAO,CAAC,MAArB,mBAAwB,YAAxB,YAAmC;AAC/D,aAAO;AAAA,IACT;AAAA,IACA,KAAK,WAAW;AACd,YAAM,SAAS,cAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,UAAU,GAAG;AACtD,UAAI,CAAC,OAAO,QAAS,QAAO,GAAG,IAAI,KAAK;AACxC,aAAO;AAAA,IACT;AAAA,IACA,KAAK,UAAU;AACb,YAAM,SAAS,sBAAsB,KAAK,GAAG;AAC7C,aAAO,OAAO,KAAK,OAAO,OAAO;AAAA,IACnC;AAAA,IACA,KAAK,YAAY;AACf,YAAM,SAAS,wBAAwB,KAAK,GAAG;AAC/C,aAAO,OAAO,KAAK,OAAO,OAAO;AAAA,IACnC;AAAA,IACA,KAAK,aAAa;AAChB,aAAO,uBAAuB,KAAK,GAAG;AAAA,IACxC;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,SAAS,oBAAoB,KAAK,GAAG;AAC3C,aAAO,OAAO,KAAK,OAAO,OAAO;AAAA,IACnC;AAAA,IACA,KAAK,QAAQ;AACX,YAAM,SAAS,oBAAoB,KAAK,GAAG;AAC3C,aAAO,OAAO,KAAK,OAAO,OAAO;AAAA,IACnC;AAAA,IACA,KAAK,UAAU;AACb,YAAM,SAAS,sBAAsB,KAAK,GAAG;AAC7C,aAAO,OAAO,KAAK,OAAO,OAAO;AAAA,IACnC;AAAA,IACA,KAAK,OAAO;AACV,YAAM,SAAS,mBAAmB,KAAK,GAAG;AAC1C,aAAO,OAAO,KAAK,OAAO,OAAO;AAAA,IACnC;AAAA,IACA,KAAK,SAAS;AACZ,YAAM,SAAS,qBAAqB,KAAK,GAAG;AAC5C,aAAO,OAAO,KAAK,OAAO,OAAO;AAAA,IACnC;AAAA,IACA,KAAK,eAAe;AAElB,YAAM,eAAuC,CAAC;AAC9C,YAAM,MAAM,yBAAyB,KAAK,KAAK,IAAI,YAAY;AAC/D,UAAI,IAAK,QAAO;AAEhB,YAAM,WAAW,OAAO,OAAO,YAAY,EAAE,CAAC;AAC9C,aAAO,8BAAY;AAAA,IACrB;AAAA,IACA;AACE,aAAO;AAAA,EACX;AACF;AAnUA,IAAAC;AAAA;AAAA;AAAA;AAAA,IAAAA,cAAkB;AAGlB,IAAAC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAAA;AAAA;;;ACEO,SAAS,qBAA6B;AAC3C,QAAM,MAAM,UAAU;AACtB,QAAM,IAAI,IAAI;AACd,SAAO,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,KAAK,IAAI;AACxD;AAGO,SAAS,eAAe,IAAoB;AACjD,SAAO,GAAG,mBAAmB,CAAC,UAAU,EAAE;AAC5C;AAGO,SAAS,iBAAiB,GAAoB;AACnD,SAAO,EAAE,WAAW,GAAG,mBAAmB,CAAC,GAAG;AAChD;AA3BA,IAUM;AAVN;AAAA;AAAA;AAQA,IAAAC;AAEA,IAAM,+BAA+B;AAAA;AAAA;;;ACVrC;AAAA;AAAA;AAAA;AAAA,wBAAyC;AAAA;AAAA;;;ACgCzC,SAAS,iBAAiB,UAA2B;AACnD,QAAM,SAAS,UAAU;AACzB,MACE,SAAS,WAAW,GAAG,OAAO,aAAa,GAAG,MAC7C,SAAS,SAAS,OAAO,KAAK,SAAS,SAAS,KAAK,KAAK,SAAS,SAAS,MAAM,IACnF;AACA,WAAO;AAAA,EACT;AACA,SAAO,SAAS,WAAW,GAAG,mBAAmB,CAAC,GAAG,KAAK,SAAS,SAAS,OAAO;AACrF;AAIA,SAASC,oBAAmB,UAAiC;AAC3D,QAAM,SAAS,UAAU;AACzB,MAAI,CAAC,SAAS,WAAW,GAAG,OAAO,aAAa,GAAG,EAAG,QAAO;AAC7D,QAAM,WAAW,SAAS,MAAM,OAAO,cAAc,SAAS,CAAC;AAC/D,QAAM,WAAW,SAAS,QAAQ,GAAG;AACrC,SAAO,WAAW,IAAI,SAAS,MAAM,GAAG,QAAQ,IAAI;AACtD;AAGA,eAAe,iBAAiB,SAAkB,OAAe,MAAc,KAA8B;AAC3G,QAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,IAAI,QAAQ,EAAE,OAAO,MAAM,UAAU,IAAI,CAAC;AAC9E,SAAO,OAAO,KAAK,KAAK,SAAS,QAAQ,EAAE,SAAS,OAAO;AAC7D;AAGA,eAAe,YAAkB,OAAY,OAAe,IAA2C;AACrG,QAAM,UAAe,CAAC;AACtB,MAAI,QAAQ;AAEZ,iBAAe,OAAsB;AACnC,WAAO,QAAQ,MAAM,QAAQ;AAC3B,YAAM,UAAU;AAChB,cAAQ,OAAO,IAAI,MAAM,GAAG,MAAM,OAAO,CAAC;AAAA,IAC5C;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC;AAClF,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;AAWA,eAAsB,mBACpB,SACA,OACA,MACA,QACiC;AA1FnC;AA2FE,QAAM,SAAS,UAAU;AAEzB,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,UAAM,EAAE,KAAK,IAAI,MAAM,QAAQ,KAAK,IAAI,QAAQ;AAAA,MAC9C;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV,WAAW;AAAA,IACb,CAAC;AACD,cAAU,KAAK;AACf,gBAAY,KAAK;AAEjB,QAAI,KAAK,WAAW;AAClB,wBAAkB;AAAA,QAChB,WAAW;AAAA,QACX;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF,SAAS,OAAO;AACd,sBAAkB;AAAA,MAChB,WAAW;AAAA,MACX;AAAA,MACA,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAChE,CAAC;AACD,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,UAAU;AAAA,IACzB,CAAC,SACC,KAAK,SAAS,UACd,OAAO,KAAK,SAAS,YACrB,OAAO,KAAK,QAAQ,YACpB,iBAAiB,KAAK,IAAI;AAAA,EAC9B;AAEA,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS,oBAAI,IAAI;AAAA,MACjB,cAAc,oBAAI,IAAI;AAAA,MACtB,cAAc,oBAAI,IAAI;AAAA,MACtB,aAAa,KAAK,IAAI;AAAA,MACtB,SAAS;AAAA,MACT,aAAa;AAAA,MACb,oBAAoB;AAAA,IACtB;AAAA,EACF;AAGA,QAAM,YAAY,SAAS,OAAO,CAAC,SAAS,KAAK,KAAK,SAAS,OAAO,CAAC;AACvE,QAAM,UAAU,SAAS,OAAO,CAAC,SAAS,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,KAAK,SAAS,MAAM,CAAC;AAGjG,QAAM,eAAe,MAAM,YAAY,WAAW,qBAAqB,OAAO,SAAS;AACrF,QAAI;AACF,YAAM,UAAU,MAAM,iBAAiB,SAAS,OAAO,MAAM,KAAK,GAAG;AACrE,aAAO,EAAE,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,QAAQ;AAAA,IACnD,SAAQ;AACN,aAAO,EAAE,MAAM,KAAK,MAAM,KAAK,KAAK,KAAK,SAAS,KAAK;AAAA,IACzD;AAAA,EACF,CAAC;AAED,QAAM,aAAa,MAAM,YAAY,SAAS,qBAAqB,OAAO,SAAS;AACjF,QAAI;AACF,YAAM,UAAU,MAAM,iBAAiB,SAAS,OAAO,MAAM,KAAK,GAAG;AACrE,aAAO,EAAE,MAAM,KAAK,MAAM,QAAQ;AAAA,IACpC,SAAQ;AACN,aAAO,EAAE,MAAM,KAAK,MAAM,SAAS,KAAK;AAAA,IAC1C;AAAA,EACF,CAAC;AAGD,QAAM,WAAW,oBAAI,IAAoB;AACzC,aAAW,MAAM,YAAY;AAC3B,QAAI,GAAG,YAAY,MAAM;AACvB,eAAS,IAAI,GAAG,MAAM,GAAG,OAAO;AAAA,IAClC;AAAA,EACF;AAGA,QAAM,UAAU,oBAAI,IAAyB;AAC7C,QAAM,eAAe,oBAAI,IAAsB;AAC/C,QAAM,eAAe,oBAAI,IAAyB;AAElD,aAAW,QAAQ,cAAc;AAC/B,QAAI,KAAK,YAAY,KAAM;AAE3B,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,KAAK,OAAO;AAAA,IAClC,SAAQ;AACN;AAAA,IACF;AAEA,UAAM,iBACJ,SAAQ,YAAwC,QAAxC,mBAA6C,UAAS,WACzD,OAAqC,IAAI,OAC1C;AAGN,UAAM,aAAqC,CAAC;AAC5C,QAAI,gBAAgB;AAClB,YAAM,UAAU,+BAA+B,KAAK,MAAM,gBAAgB,OAAO,WAAW;AAC5F,iBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,mBAAW,SAAS,KAAI,cAAS,IAAI,MAAM,MAAnB,YAAwB;AAAA,MAClD;AACA,YAAM,UAAU,+BAA+B,KAAK,MAAM,gBAAgB,OAAO,WAAW;AAC5F,iBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,mBAAW,SAAS,KAAI,cAAS,IAAI,MAAM,MAAnB,YAAwB;AAAA,MAClD;AAAA,IACF;AAEA,UAAM,SAAsB;AAAA,MAC1B,MAAM,KAAK;AAAA,MACX,SAAS;AAAA,MACT,KAAK,KAAK;AAAA,MACV,mBAAmB;AAAA,IACrB;AAEA,QAAI,iBAAiB,KAAK,IAAI,GAAG;AAC/B,mBAAa,IAAI,KAAK,MAAM,MAAM;AAClC;AAAA,IACF;AAEA,YAAQ,IAAI,KAAK,MAAM,MAAM;AAG7B,UAAM,aAAaA,oBAAmB,KAAK,IAAI;AAC/C,QAAI,YAAY;AACd,YAAM,OAAO,aAAa,IAAI,UAAU;AACxC,UAAI,MAAM;AACR,aAAK,KAAK,KAAK,IAAI;AAAA,MACrB,OAAO;AACL,qBAAa,IAAI,YAAY,CAAC,KAAK,IAAI,CAAC;AAAA,MAC1C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,KAAK,IAAI;AAAA,IACtB,SAAS;AAAA,IACT,aAAa;AAAA,IACb,oBAAoB;AAAA,EACtB;AACF;AAtPA,IAoBM;AApBN;AAAA;AAAA;AAYA,IAAAC;AACA;AACA;AACA;AAKA,IAAM,sBAAsB;AAAA;AAAA;;;ACwB5B,SAAS,IAAI,OAAgC;AAC3C,SAAO,KAAK,IAAI,IAAI,MAAM;AAC5B;AAEA,SAAS,QAAQ,OAAiC;AAChD,SAAO,IAAI,KAAK,IAAI;AACtB;AAEA,SAAS,QAAQ,OAAiC;AAChD,SAAO,IAAI,KAAK,IAAI;AACtB;AAGA,SAAS,cAAc,QAAoC;AACzD,SAAO,UAAU,UAAU,EAAE,IAAI;AACnC;AAMA,SAAS,kBAAkB,QAAiD;AAC1E,QAAM,WAAW,SAAS,IAAI,MAAM;AACpC,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,QAAQ,MAAM,EAAE,QAAQ,MAAM;AAC5C,aAAS,OAAO,MAAM;AAAA,EACxB,CAAC;AAED,WAAS,IAAI,QAAQ,OAAO;AAC5B,SAAO;AACT;AAEA,eAAe,QAAQ,QAAiD;AACtE,QAAM,EAAE,OAAO,KAAK,IAAI,mBAAmB;AAC3C,QAAM,CAAC,OAAO,IAAI,kBAAkB;AAEpC,MAAI,CAAC,SAAS;AACZ,sBAAkB;AAAA,MAChB,WAAW;AAAA,MACX;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,MAAM,mBAAmB,SAAS,OAAO,MAAM,MAAM;AAEpE,MAAI,QAAQ;AACV,WAAO,IAAI,QAAQ,MAAM;AAAA,EAC3B;AAEA,SAAO;AACT;AAQA,eAAe,YAAY,QAAiD;AAC1E,QAAMC,UAAS,OAAO,IAAI,MAAM;AAEhC,MAAIA,WAAU,QAAQA,OAAM,GAAG;AAC7B,WAAOA;AAAA,EACT;AAEA,MAAIA,WAAU,QAAQA,OAAM,GAAG;AAE7B,sBAAkB,MAAM,EAAE,MAAM,MAAM;AAAA,IAEtC,CAAC;AACD,WAAOA;AAAA,EACT;AAGA,SAAO,kBAAkB,MAAM;AACjC;AAMA,SAASC,oBAAmB,UAAiC;AAC3D,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,GAAG,OAAO,aAAa;AACtC,MAAI,CAAC,SAAS,WAAW,MAAM,EAAG,QAAO;AACzC,QAAM,WAAW,SAAS,MAAM,OAAO,MAAM;AAC7C,QAAM,WAAW,SAAS,QAAQ,GAAG;AACrC,SAAO,WAAW,IAAI,SAAS,MAAM,GAAG,QAAQ,IAAI;AACtD;AAaA,eAAsB,cAAc,UAAkB,QAA8C;AApJpG;AAqJE,QAAM,WAAW,cAAc,MAAM;AACrC,QAAM,QAAQ,MAAM,YAAY,QAAQ;AACxC,MAAI,CAAC,MAAO,QAAO;AACnB,UAAO,iBAAM,QAAQ,IAAI,QAAQ,MAA1B,YAA+B,MAAM,aAAa,IAAI,QAAQ,MAA9D,YAAmE;AAC5E;AAMA,eAAsB,sBAAsB,YAAoB,QAA2C;AA/J3G;AAgKE,QAAM,WAAW,cAAc,MAAM;AACrC,QAAM,QAAQ,MAAM,YAAY,QAAQ;AACxC,MAAI,CAAC,MAAO,QAAO;AAEnB,MAAI,eAAe,MAAM;AAGvB,UAAM,MAAgB,CAAC;AACvB,eAAW,CAACC,KAAI,KAAK,MAAM,SAAS;AAClC,UAAIA,MAAK,SAAS,OAAO,GAAG;AAC1B,YAAI,KAAKA,KAAI;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,UAAO,iBAAM,aAAa,IAAI,UAAU,MAAjC,mBAAoC,YAApC,YAA+C,CAAC;AACzD;AAgBA,eAAsB,iBAAiB,UAAkB,QAAyC;AAjMlG;AAkME,QAAM,WAAW,cAAc,MAAM;AACrC,QAAM,QAAQ,MAAM,YAAY,QAAQ;AACxC,MAAI,CAAC,MAAO,QAAO;AACnB,UAAQ,uBAAM,QAAQ,IAAI,QAAQ,MAA1B,YAA+B,MAAM,aAAa,IAAI,QAAQ,MAA9D,mBAAkE,QAAlE,YAAyE;AACnF;AA6CO,SAAS,cAAc,QAAgB,UAA+B;AAnP7E;AAoPE,QAAM,QAAQ,OAAO,IAAI,MAAM;AAC/B,MAAI,CAAC,MAAO;AAEZ,MAAI,SAAS,SAAS,UAAU;AAC9B,UAAM,UAAU,iBAAiB,SAAS,IAAI;AAC9C,UAAM,WAAW,UAAU,MAAM,aAAa,IAAI,SAAS,IAAI,IAAI,MAAM,QAAQ,IAAI,SAAS,IAAI;AAClG,UAAM,QAAqB;AAAA,MACzB,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,KAAK,SAAS;AAAA,MACd,mBAAmB,SAAS,aAAa,mBAAK,SAAS,eAAgB,0CAAU,sBAAV,YAA+B,CAAC;AAAA,IACzG;AAEA,QAAI,SAAS;AACX,YAAM,aAAa,IAAI,SAAS,MAAM,KAAK;AAAA,IAC7C,OAAO;AACL,YAAM,QAAQ,IAAI,SAAS,MAAM,KAAK;AAGtC,YAAM,aAAaD,oBAAmB,SAAS,IAAI;AACnD,UAAI,YAAY;AACd,cAAM,OAAO,MAAM,aAAa,IAAI,UAAU;AAC9C,YAAI,MAAM;AACR,cAAI,CAAC,KAAK,SAAS,SAAS,IAAI,GAAG;AACjC,iBAAK,KAAK,SAAS,IAAI;AAAA,UACzB;AAAA,QACF,OAAO;AACL,gBAAM,aAAa,IAAI,YAAY,CAAC,SAAS,IAAI,CAAC;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAAA,EACF,OAAO;AAEL,QAAI,iBAAiB,SAAS,IAAI,GAAG;AACnC,YAAM,aAAa,OAAO,SAAS,IAAI;AAAA,IACzC,OAAO;AACL,YAAM,QAAQ,OAAO,SAAS,IAAI;AAElC,YAAM,aAAaA,oBAAmB,SAAS,IAAI;AACnD,UAAI,YAAY;AACd,cAAM,OAAO,MAAM,aAAa,IAAI,UAAU;AAC9C,YAAI,MAAM;AACR,gBAAM,MAAM,KAAK,QAAQ,SAAS,IAAI;AACtC,cAAI,OAAO,EAAG,MAAK,OAAO,KAAK,CAAC;AAAA,QAClC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM;AACR;AAtSA,IAyBM,cAGA,cAOA,QAGA;AAtCN;AAAA;AAAA;AAWA,IAAAE;AACA;AACA;AACA;AAEA;AACA;AAQA,IAAM,eAAe;AAGrB,IAAM,eAAe;AAOrB,IAAM,SAAS,oBAAI,IAA6B;AAGhD,IAAM,WAAW,oBAAI,IAA6C;AAAA;AAAA;;;ACtClE,IAOa;AAPb;AAAA;AAAA;AAOO,IAAM,mCAAmC;AAAA;AAAA;;;ACPhD,IAGaC,kBAgBA,UAEA;AArBb;AAAA;AAAA;AAAA,IAAAC;AAGO,IAAMD,mBAAkB,CAAC,UAA2B;AACzD,UAAI,iBAAiB,OAAO;AAC1B,eAAO,MAAM;AAAA,MACf;AAEA,aAAO,OAAO,KAAK;AAAA,IACrB;AAUO,IAAM,WAAW,OAA0B,EAAE,SAAS,KAAK;AAE3D,IAAM,YAAY,CAAC,WAAuD;AAAA,MAC/E,SAAS;AAAA,MACT,OAAOA,iBAAgB,KAAK;AAAA,IAC9B;AAAA;AAAA;;;ACxBA,IAIA,cAaa;AAjBb;AAAA;AAAA;AAAA;AAEA;AAEA,mBAAyD;AAEzD;AAEA;AASO,IAAM,aAAa,OAAO,oBAAoD;AACnF,UAAI;AACF,YAAI;AACF,sCAAU,gCAAgC;AAAA,QAC5C,SAAQ;AACN,0CAAc,kCAAkC,EAAE,QAAQ,EAAE,CAAC;AAAA,QAC/D;AAEA,yCAAe,KAAK,QAAQ;AAE5B,eAAO,SAAS;AAAA,MAClB,SAAS,GAAG;AACV,eAAO,UAAU,CAAC;AAAA,MACpB;AAAA,IACF;AAAA;AAAA;;;AC/BA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8CA,SAASE,sBAAqB,GAAmB;AAC/C,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAGA,eAAe,iCACb,WACA,SACA,YACA,QACA,cACe;AACf,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,YAAa;AAClB,QAAM,SAAS,UAAU;AACzB,QAAM,0BAA0B,EAAE,aAAa,QAAQ,WAAW,SAAS,YAAY,QAAQ,aAAa,CAAC;AAC/G;AAEA,eAAe,iCACb,WACA,QACA,cACe;AACf,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,YAAa;AAClB,QAAM,0BAA0B,EAAE,aAAa,WAAW,QAAQ,aAAa,CAAC;AAClF;AAGA,eAAe,kCAAkC,cAAkC,WAAkC;AA3ErH;AA4EE,MAAI,CAAC,cAAc;AACjB;AAAA,EACF;AAEA,QAAM,aAAaA,sBAAqB,SAAS;AAEjD,MAAI,iBAAiB,GAAG;AACtB,QAAI;AACF,YAAM,cAAc,MAAM,cAAc,0BAA0B,YAAY;AAC9E,YAAM,OAAO,sCAAqC,gDAAa,YAAb,YAAwB,IAAI,cAAc,UAAU;AACtG,UAAI,QAAQ,MAAM;AAChB;AAAA,MACF;AAEA,YAAM,eAAe,0BAA0B,MAAM,sCAAsC,YAAY;AAAA,IACzG,SAAQ;AAAA,IAER;AAEA;AAAA,EACF;AAEA,MAAI;AACF,UAAM,MAAM,aAAAC,QAAK;AAAA;AAAA,MAA+B,QAAQ,IAAI;AAAA,MAAG;AAAA,IAAwB;AACvF,QAAI,MAAM;AACV,QAAI;AACF,YAAM,MAAM,iBAAAC,QAAW,SAAS,KAAK,EAAE,UAAU,OAAO,CAAC;AAAA,IAC3D,SAAQ;AACN,YAAM;AAAA,IACR;AAEA,UAAM,OAAO,qCAAqC,KAAK,cAAc,UAAU;AAC/E,QAAI,QAAQ,MAAM;AAChB;AAAA,IACF;AAEA,UAAM,iBAAAA,QAAW,MAAM,aAAAD,QAAK,QAAQ,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AAC7D,UAAM,iBAAAC,QAAW,UAAU,KAAK,MAAM,MAAM;AAAA,EAC9C,SAAQ;AAAA,EAER;AACF;AAEA,eAAe,uBACb,WACA,UACA,iBAC0E;AAC1E,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,OAAO,YAAY,SAAwC;AACvE,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAEA,QAAM,mBAAmB,OAAO,QAAQ,IAAI,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,GAAG,MAAM,IAAI,WAAW,MAAM;AAC7F,MAAI,iBAAiB,WAAW,GAAG;AACjC,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAEA,QAAM,WAAWF,sBAAqB,QAAQ;AAC9C,QAAM,WAAW,MAAM,gBAAgB,SAAS;AAChD,MAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAEA,aAAW,CAAC,OAAO,KAAK,kBAAkB;AACxC,UAAM,YAAY,gBAAgB,OAAO;AACzC,QAAI,OAAO,cAAc,YAAY,CAAC,UAAU,KAAK,GAAG;AACtD;AAAA,IACF;AACA,UAAM,gBAAgB,oBAAoB,SAAS;AACnD,QAAI,CAAC,eAAe;AAClB;AAAA,IACF;AAEA,eAAW,eAAe,UAAU;AAClC,UAAIA,sBAAqB,WAAW,MAAM,UAAU;AAClD;AAAA,MACF;AACA,UAAI;AACJ,UAAI;AACF,eAAO,MAAM,QAAQ,WAAW;AAAA,MAClC,SAAQ;AACN;AAAA,MACF;AACA,UAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC;AAAA,MACF;AACA,YAAM,SAAU,KAA8C;AAC9D,UAAI,CAAC,QAAQ;AACX;AAAA,MACF;AACA,YAAM,QAAQ,OAAO,OAAO;AAC5B,UAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,GAAG;AAC9C;AAAA,MACF;AACA,UAAI,oBAAoB,KAAK,MAAM,eAAe;AAChD,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,UAAU;AAAA,UACV,SAAS,WAAW,IAAI,KAAK;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,KAAK;AACpB;AAIA,eAAe,yCACb,WACA,WAC0E;AA9L5E;AA+LE,QAAM,SAAS,UAAU;AACzB,QAAM,MAAM,OAAO,YAAY,SAAwC;AACvE,MAAI,CAAC,KAAK;AACR,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB;AAEA,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,IAAI,MAAM,GAAG;AACnD,QAAI,IAAI,WAAW,SAAS;AAC1B;AAAA,IACF;AACA,UAAM,QAAO,eAAU,GAAG,MAAb,YAAkB,IAAI,KAAK;AACxC,QAAI,CAAC,OAAO,IAAI,WAAW,GAAG,GAAG;AAC/B;AAAA,IACF;AACA,QAAI,CAAC,cAAc,KAAK,GAAG,GAAG;AAC5B;AAAA,IACF;AAEA,UAAM,YAAY,eAAe,GAAG;AACpC,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,QAAQ,SAAS;AAAA,IACjC,SAAQ;AACN,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS,uBAAuB,IAAI,KAAK;AAAA,MAC3C;AAAA,IACF;AAEA,UAAM,SAAS,oCAA4C,WAA5C,mBAAoD;AACnE,QAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,GAAG;AAC9C,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,UAAU;AAAA,QACV,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,KAAK;AACpB;AA0PA,eAAe,6BAA6B,UAAmC;AAle/E;AAmeE,MAAI,iBAAiB,GAAG;AACtB,QAAI;AACF,YAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AACtE,YAAM,SAAS,MAAM,cAAc,UAAU,YAAY;AACzD,cAAO,sCAAQ,YAAR,YAAmB;AAAA,IAC5B,SAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI;AACF,WAAO,MAAM,iBAAAE,QAAW,SAAS,aAAAD,QAAK;AAAA;AAAA,MAA+B,QAAQ,IAAI;AAAA,MAAG;AAAA,IAAQ,GAAG;AAAA,MAC7F,UAAU;AAAA,IACZ,CAAC;AAAA,EACH,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AApfA,IAIAE,kBACAC,cAEA,gBAqCM,0BA6IA,eAoDO,wCAUA,8BA2BA,iBA2CA,sBAmBA,eA2BA,aAkCA,SAyGA,UA0JA,SAsDA;AAtsBb;AAAA;AAAA;AAAA;AAEA;AAEA,IAAAD,mBAAuB;AACvB,IAAAC,eAAiB;AAEjB,qBAAwB;AAExB,IAAAC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AASA;AACA;AACA;AACA;AAWA,IAAM,2BAA2B;AA6IjC,IAAM,gBAAgB;AAoDf,IAAM,yCAAyC,YAA2B;AA7OjF;AA8OE,UAAI,CAAC,iBAAiB,GAAG;AACvB;AAAA,MACF;AAEA,UAAI,GAAE,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD,QAAO;AAC3D,cAAM,IAAI,MAAM,2CAA2C;AAAA,MAC7D;AAAA,IACF;AAEO,IAAM,+BAA+B,OAAO,UAAkB,iBAAyB,YAAqB;AACjH,UAAI,CAAC,iBAAiB,GAAG;AACvB;AAAA,MACF;AAEA,YAAM,iBAAiB,OAAO,SAAS,QAAQ,IAAI,mCAAmC,KAAK,EAAE;AAC7F,YAAM,gBAAgB,OAAO,SAAS,QAAQ,IAAI,mCAAmC,OAAO,EAAE;AAC9F,YAAM,cAAc,OAAO,SAAS,cAAc,KAAK,iBAAiB,IAAI,iBAAiB;AAC7F,YAAM,UAAU,OAAO,SAAS,aAAa,KAAK,iBAAiB,IAAI,gBAAgB;AAEvF,eAAS,UAAU,GAAG,WAAW,aAAa,WAAW;AACvD,YAAI;AACF,gBAAM,iBAAiB,MAAM,qBAAqB,UAAU,OAAO;AAEnE,cAAI,mBAAmB,iBAAiB;AACtC;AAAA,UACF;AAAA,QACF,SAAS,IAAI;AAAA,QAEb;AAEA,YAAI,UAAU,eAAe,UAAU,GAAG;AACxC,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,OAAO,CAAC;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AAEO,IAAM,kBAAkB,OAAO,aAAqB,SAAS;AAlRpE;AAmRE,YAAM,SAAS,UAAU;AACzB,UAAI;AACF,YAAI,iBAAiB,GAAG;AACtB,gBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AAGtE,cAAI;AACF,kBAAM,SAAS,MAAM,sBAAsB,YAAY,YAAY;AACnE,gBAAI,OAAQ,QAAO;AAAA,UACrB,SAAQ;AAAA,UAER;AAEA,cAAI;AACF,gBAAI,eAAe,MAAM;AACvB,oBAAMC,UAAS,MAAM,yBAAyB,OAAO,eAAe,SAAS,YAAY;AACzF,qBAAO,MAAM,QAAQA,OAAM,IAAIA,UAAS,CAAC;AAAA,YAC3C;AAEA,kBAAM,SAAS,MAAM,gBAAgB,GAAG,OAAO,aAAa,IAAI,UAAU,IAAI,SAAS,YAAY;AACnG,mBAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC;AAAA,UAC3C,SAAS,GAAG;AAAA,UAEZ;AAAA,QACF;AAEA,YAAI,eAAe,MAAM;AACvB,iBAAO,MAAM,wBAAwB,OAAO,eAAe,OAAO;AAAA,QACpE;AACA,eAAO,MAAM,yBAAyB,GAAG,OAAO,aAAa,IAAI,UAAU,EAAE;AAAA,MAC/E,SAAS,GAAG;AACV,eAAO,CAAC;AAAA,MACV;AAAA,IACF;AASO,IAAM,uBAAuB,YAA+B;AA7TnE;AA8TE,YAAM,SAAS,mBAAmB;AAClC,UAAI;AACF,YAAI,iBAAiB,GAAG;AACtB,gBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AAEtE,cAAI;AACF,mBAAO,MAAM,gBAAgB,QAAQ,SAAS,YAAY;AAAA,UAC5D,SAAS,IAAI;AAAA,UAEb;AAAA,QACF;AAEA,eAAO,MAAM,yBAAyB,MAAM;AAAA,MAC9C,SAAS,IAAI;AACX,eAAO,CAAC;AAAA,MACV;AAAA,IACF;AAEO,IAAM,gBAAgB,OAAO,SAAiB,SAAS;AAhV9D;AAiVE,YAAM,SAAS,UAAU;AACzB,UAAI;AACF,YAAI,iBAAiB,GAAG;AACtB,gBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AAEtE,cAAI;AACF,kBAAMC,OAAM,WAAW,OAAO,OAAO,cAAc,GAAG,OAAO,WAAW,IAAI,MAAM;AAClF,kBAAM,WAAW,MAAM,yBAAyBA,MAAK,QAAW,YAAY;AAC5E,kBAAM,aAAa,OAAO;AAC1B,mBAAO,SAAS,OAAO,CAAC,MAAM,WAAW,KAAK,CAAC,QAAQ,EAAE,SAAS,IAAI,GAAG,EAAE,CAAC,CAAC;AAAA,UAC/E,SAAS,GAAG;AAAA,UAEZ;AAAA,QACF;AAEA,cAAM,MAAM,WAAW,OAAO,OAAO,cAAc,GAAG,OAAO,WAAW,IAAI,MAAM;AAClF,eAAO,MAAM,6BAA6B,KAAK,OAAO,qBAAqB,WAAW,IAAI;AAAA,MAC5F,SAAS,GAAG;AACV,eAAO,CAAC;AAAA,MACV;AAAA,IACF;AAMO,IAAM,cAAc,OAAO,aAA8D;AA3WhG;AA4WE,UAAI,iBAAiB,GAAG;AACtB,YAAI;AACJ,YAAI;AACF,0BAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AAAA,QAClE,SAAQ;AAAA,QAAC;AAET,YAAI;AACF,gBAAM,SAAS,MAAM,cAAc,UAAU,YAAY;AACzD,cAAI,OAAQ,QAAO,gBAAgB,OAAO,OAAO;AAAA,QACnD,SAAQ;AAAA,QAAC;AAET,YAAI;AACF,gBAAM,SAAS,MAAM,cAAc,UAAU,YAAY;AACzD,cAAI,OAAQ,QAAO,KAAK,MAAM,OAAO,OAAO;AAAA,QAC9C,SAAQ;AAAA,QAAC;AAET,YAAI;AACF,gBAAM,MAAM,MAAM,qBAAqB,UAAU,YAAY;AAC7D,cAAI,IAAK,QAAO,KAAK,MAAM,GAAG;AAAA,QAChC,SAAQ;AAAA,QAAC;AAET,eAAO;AAAA,MACT;AAEA,UAAI;AACF,cAAM,WAAW,aAAAN,QAAK;AAAA;AAAA,UAA+B,QAAQ,IAAI;AAAA,UAAG;AAAA,QAAQ;AAC5E,cAAM,OAAO,MAAM,iBAAAC,QAAW,SAAS,UAAU,EAAE,UAAU,OAAO,CAAC;AACrE,eAAO,KAAK,MAAM,IAAI;AAAA,MACxB,SAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAEO,IAAM,UAAU,OAAO,aAAqB;AA7YnD;AA8YE,YAAM,SAAS,UAAU;AACzB,UAAI;AACF,YAAI;AAEJ,YAAI,iBAAiB,GAAG;AAEtB,cAAI;AACF,kBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AACtE,kBAAM,SAAS,MAAM,cAAc,UAAU,YAAY;AAEzD,gBAAI,QAAQ;AACV,sBAAQ,gBAAgB,OAAO,OAAO;AAEtC,kBAAI,MAAM,QAAQ;AAChB,2BAAW,CAAC,WAAW,SAAS,KAAK,OAAO,QAAQ,OAAO,iBAAiB,GAAG;AAC7E,wBAAM,OAAO,SAAS,IAAI;AAAA,gBAC5B;AAAA,cACF;AACA,qBAAO;AAAA,YACT;AAAA,UACF,SAAQ;AAAA,UAER;AAEA,cAAI;AACF,kBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AACtE,kBAAM,SAAS,MAAM,cAAc,UAAU,YAAY;AAEzD,gBAAI,QAAQ;AACV,sBAAQ,KAAK,MAAM,OAAO,OAAO;AAAA,YACnC;AAAA,UACF,SAAS,GAAG;AAAA,UAEZ;AAKA,cAAI,CAAC,OAAO;AACV,gBAAI;AACF,oBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AACtE,oBAAM,MAAM,MAAM,qBAAqB,UAAU,YAAY;AAC7D,kBAAI,KAAK;AACP,wBAAQ,KAAK,MAAM,GAAG;AAAA,cACxB;AAAA,YACF,SAAQ;AAAA,YAER;AAAA,UACF;AAAA,QACF;AAEA,YAAI,CAAC,OAAO;AACV,cAAI,iBAAiB,GAAG;AACtB,mBAAO,CAAC;AAAA,UACV;AACA,gBAAM,WAAW,aAAAD,QAAK;AAAA;AAAA,YAA+B,QAAQ,IAAI;AAAA,YAAG;AAAA,UAAQ;AAC5E,gBAAM,OAAO,MAAM,iBAAAC,QAAW,SAAS,UAAU,EAAE,UAAU,OAAO,CAAC;AACrE,kBAAQ,KAAK,MAAM,IAAI;AAAA,QACzB;AAEA,YAAI,CAAC,OAAO;AACV,iBAAO,CAAC;AAAA,QACV;AAGA,cAAM,kBAAiB,oCAAO,QAAP,mBAAY;AACnC,YAAI,OAAO,mBAAmB,YAAY,MAAM,QAAQ;AACtD,gBAAM,iBAAiB,+BAA+B,UAAU,gBAAgB,OAAO,WAAW;AAClG,qBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,cAAc,GAAG;AAChE,kBAAM,OAAO,SAAS,IAAI,MAAM,6BAA6B,MAAM;AAAA,UACrE;AACA,gBAAM,gBAAgB,+BAA+B,UAAU,gBAAgB,OAAO,WAAW;AACjG,qBAAW,CAAC,WAAW,OAAO,KAAK,OAAO,QAAQ,aAAa,GAAG;AAChE,kBAAM,OAAO,SAAS,IAAI,MAAM,6BAA6B,OAAO;AAAA,UACtE;AAAA,QACF;AAEA,eAAO;AAAA,MACT,SAAS,GAAG;AACV,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AAAA,IACF;AAuBO,IAAM,WAAW,OACtB,UACA,UACA,YAC4B;AA1f9B;AA2fE,YAAM,SAAS,UAAU;AACzB,UAAI;AACF,YAAI,UAAU;AACd,cAAM,aAAY,wCAAS,QAAT,mBAAc;AAChC,cAAM,YAAY,mCAAS;AAC3B,YAAI,OAAO,cAAc,YAAY,aAAa,OAAO,cAAc,YAAY,CAAC,MAAM,QAAQ,SAAS,GAAG;AAC5G,gBAAM,YAAoC,CAAC;AAC3C,qBAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,SAAS,GAAG;AAC9C,gBAAI,KAAK,MAAM;AACb,wBAAU,CAAC,IAAI;AAAA,YACjB,WAAW,OAAO,MAAM,UAAU;AAChC,wBAAU,CAAC,IAAI,KAAK,UAAU,CAAC;AAAA,YACjC,OAAO;AACL,wBAAU,CAAC,IAAI,OAAO,CAAC;AAAA,YACzB;AAAA,UACF;AACA,gBAAM,YAAY,oBAAoB,WAAW,SAAS;AAC1D,cAAI,CAAC,UAAU,IAAI;AACjB,kBAAM,QAAQ,OAAO,OAAO,UAAU,WAAW,EAAE,CAAC;AACpD,mBAAO;AAAA,cACL,SAAS;AAAA,cACT,OAAO,SAAS;AAAA,cAChB,aAAa,UAAU;AAAA,YACzB;AAAA,UACF;AAEA,gBAAM,cAAc,MAAM,yCAAyC,WAAW,SAAS;AACvF,cAAI,CAAC,YAAY,IAAI;AACnB,mBAAO;AAAA,cACL,SAAS;AAAA,cACT,OAAO,YAAY;AAAA,cACnB,aAAa,EAAE,CAAC,YAAY,QAAQ,GAAG,YAAY,QAAQ;AAAA,YAC7D;AAAA,UACF;AAEA,oBAAU,iCACL,UADK;AAAA,YAER,QAAQ,+BAA+B,WAAW,SAAS;AAAA,UAC7D;AAEA,gBAAM,aAAa,MAAM,uBAAuB,WAAW,UAAU,QAAQ,MAAM;AACnF,cAAI,CAAC,WAAW,IAAI;AAClB,mBAAO;AAAA,cACL,SAAS;AAAA,cACT,OAAO,WAAW;AAAA,cAClB,aAAa,EAAE,CAAC,WAAW,QAAQ,GAAG,WAAW,QAAQ;AAAA,YAC3D;AAAA,UACF;AAAA,QACF;AAIA,YAAI,EAAC,mCAAS,2BAAwB,wCAAS,QAAT,mBAAc,YAAW,SAAS;AACtE,oBAAU,iCAAK,UAAL,EAAc,KAAK,iCAAK,QAAQ,MAAb,EAAkB,QAAQ,UAAU,GAAE;AAAA,QACrE;AAGA,YAAI,EAAC,mCAAS,4BAAyB,wCAAS,QAAT,mBAAc,YAAW,iBAAe,wCAAS,QAAT,mBAAc,YAAW,WAAW;AACjH,oBAAU,iCAAK,UAAL,EAAc,KAAK,iCAAK,QAAQ,MAAb,EAAkB,QAAQ,UAAU,GAAE;AAAA,QACrE;AAGA,cAAM,mBAA2C,CAAC;AAClD,YAAI,OAAO,cAAc,YAAY,QAAQ,QAAQ;AACnD,gBAAM,iBAAiB,+BAA+B,UAAU,WAAW,OAAO,WAAW;AAC7F,qBAAW,CAAC,SAAS,KAAK,OAAO,QAAQ,cAAc,GAAG;AACxD,6BAAiB,SAAS,KAAI,aAAQ,OAAO,SAAS,MAAxB,YAA6B;AAC3D,mBAAO,QAAQ,OAAO,SAAS;AAAA,UACjC;AACA,gBAAM,gBAAgB,+BAA+B,UAAU,WAAW,OAAO,WAAW;AAC5F,qBAAW,CAAC,SAAS,KAAK,OAAO,QAAQ,aAAa,GAAG;AACvD,6BAAiB,SAAS,KAAI,aAAQ,OAAO,SAAS,MAAxB,YAA6B;AAC3D,mBAAO,QAAQ,OAAO,SAAS;AAAA,UACjC;AAAA,QACF;AAEA,cAAM,OAAO,KAAK,UAAU,SAAS,MAAM,CAAC;AAC5C,cAAM,iBAAiB,GAAG,IAAI;AAAA;AAE9B,YAAI,iBAAiB,GAAG;AACtB,gBAAM,uCAAuC;AAC7C,gBAAM,mBAAiB,wCAAS,QAAT,mBAAc,SAAQ;AAC7C,gBAAM,YAAU,wCAAS,QAAT,mBAAc,OAAM;AACpC,gBAAM,UAAU,UAAU,cAAc,IAAI,OAAO;AACnD,gBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AAGtE,gBAAM,YAAa,MAAM,iBAAiB,UAAU,YAAY,KAAM;AACtE,gBAAM,eAAe,UAAU,gBAAgB,SAAS,cAAc,SAAS;AAE/E,gBAAMM,WACJ,OAAO,cAAc,WAAW,+BAA+B,UAAU,WAAW,OAAO,WAAW,IAAI,CAAC;AAC7G,qBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQA,QAAO,GAAG;AACzD,kBAAM,aAAY,sBAAiB,SAAS,MAA1B,YAA+B;AACjD,kBAAM,eAAe,QAAQ,WAAW,UAAU,SAAS,QAAQ,SAAS,IAAI,OAAO,IAAI,YAAY;AAAA,UACzG;AACA,gBAAM,UACJ,OAAO,cAAc,WAAW,+BAA+B,UAAU,WAAW,OAAO,WAAW,IAAI,CAAC;AAC7G,qBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,kBAAM,aAAY,sBAAiB,SAAS,MAA1B,YAA+B;AACjD,kBAAM,eAAe,QAAQ,WAAW,UAAU,SAAS,QAAQ,SAAS,IAAI,OAAO,IAAI,YAAY;AAAA,UACzG;AACA,gBAAM,6BAA6B,UAAU,cAAc;AAG3D,cAAI,cAAc;AAChB,0BAAc,cAAc;AAAA,cAC1B,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,cACT,KAAK;AAAA;AAAA,cACL,YAAY;AAAA,YACd,CAAC;AAAA,UACH;AAEA,gBAAM,kCAAkC,cAAc,QAAQ;AAC9D,gBAAM,iCAAiC,UAAU,SAAS,kBAAkB,cAAc,IAAI;AAC9F,gBAAMC,SAAQ,MAAM,WAAW,QAAQ;AAEvC,iBAAOA,OAAM,UAAU,SAAS,IAAIA;AAAA,QACtC;AAEA,cAAM,cAAc,UAAM,wBAAQ;AAClC,cAAM,mBAAkB,iBAAY,IAAI,wBAAwB,MAAxC,mBAA2C;AACnE,cAAM,WAAW,aAAAR,QAAK;AAAA;AAAA,UAA+B,QAAQ,IAAI;AAAA,UAAG;AAAA,QAAQ;AAC5E,cAAM,iBAAAC,QAAW,UAAU,UAAU,gBAAgB,MAAM;AAE3D,cAAM,UACJ,OAAO,cAAc,WAAW,+BAA+B,UAAU,WAAW,OAAO,WAAW,IAAI,CAAC;AAC7G,mBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACzD,gBAAM,aAAY,sBAAiB,SAAS,MAA1B,YAA+B;AACjD,gBAAM,iBAAAA,QAAW,UAAU,aAAAD,QAAK;AAAA;AAAA,YAA+B,QAAQ,IAAI;AAAA,YAAG;AAAA,UAAM,GAAG,WAAW,MAAM;AAAA,QAC1G;AACA,cAAM,aACJ,OAAO,cAAc,WAAW,+BAA+B,UAAU,WAAW,OAAO,WAAW,IAAI,CAAC;AAC7G,mBAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC5D,gBAAM,aAAY,sBAAiB,SAAS,MAA1B,YAA+B;AACjD,gBAAM,iBAAAC,QAAW,UAAU,aAAAD,QAAK;AAAA;AAAA,YAA+B,QAAQ,IAAI;AAAA,YAAG;AAAA,UAAM,GAAG,WAAW,MAAM;AAAA,QAC1G;AACA,cAAM,kCAAkC,iBAAiB,QAAQ;AACjE,cAAM,iCAAiC,UAAU,SAAS,kBAAkB,iBAAiB,KAAK;AAClG,cAAM,QAAQ,MAAM,WAAW,QAAQ;AAEvC,eAAO,MAAM,UAAU,SAAS,IAAI;AAAA,MACtC,SAAS,GAAG;AACV,eAAO,UAAU,IAAI,MAAM,wBAAwBS,iBAAgB,CAAC,CAAC,EAAE,CAAC;AAAA,MAC1E;AAAA,IACF;AAEO,IAAM,UAAU,OAAO,SAAyC;AAhpBvE;AAipBE,YAAM,SAAS,UAAU;AACzB,UAAI;AACF,cAAM,KAAK,OAAO,WAAW;AAC7B,cAAM,SAAS;AAAA,UACb,KAAK;AAAA,YACH;AAAA,YACA;AAAA,YACA,QAAQ;AAAA,UACV;AAAA,UACA,QAAQ,yBAAyB,IAAI;AAAA,QACvC;AACA,cAAM,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC;AAC3C,cAAM,OAAO,GAAG,OAAO,aAAa,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAC1D,cAAM,iBAAiB,GAAG,IAAI;AAAA;AAE9B,YAAI,iBAAiB,GAAG;AACtB,gBAAM,uCAAuC;AAC7C,gBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AACtE,gBAAM,eAAe,MAAM,gBAAgB,cAAc,IAAI,IAAI,EAAE,IAAI,YAAY;AACnF,gBAAM,6BAA6B,MAAM,cAAc;AAGvD,cAAI,cAAc;AAChB,0BAAc,cAAc;AAAA,cAC1B,MAAM;AAAA,cACN,MAAM;AAAA,cACN,SAAS;AAAA,cACT,KAAK;AAAA,YACP,CAAC;AAAA,UACH;AAEA,gBAAM,kCAAkC,cAAc,IAAI;AAC1D,gBAAM,iCAAiC,MAAM,QAAQ,CAAC,GAAG,cAAc,IAAI;AAC3E,gBAAMD,SAAQ,MAAM,WAAW,IAAI;AAEnC,iBAAOA,OAAM,UAAU,EAAE,SAAS,MAAM,MAAM,KAAK,IAAI,EAAE,SAAS,OAAO,OAAOA,OAAM,MAAM;AAAA,QAC9F;AAEA,cAAM,cAAc,UAAM,wBAAQ;AAClC,cAAM,mBAAkB,iBAAY,IAAI,wBAAwB,MAAxC,mBAA2C;AACnE,cAAM,WAAW,aAAAR,QAAK;AAAA;AAAA,UAA+B,QAAQ,IAAI;AAAA,UAAG;AAAA,QAAI;AACxE,cAAM,iBAAAC,QAAW,MAAM,aAAAD,QAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClE,cAAM,iBAAAC,QAAW,UAAU,UAAU,gBAAgB,MAAM;AAC3D,cAAM,kCAAkC,iBAAiB,IAAI;AAC7D,cAAM,iCAAiC,MAAM,QAAQ,CAAC,GAAG,iBAAiB,KAAK;AAC/E,cAAM,QAAQ,MAAM,WAAW,IAAI;AAEnC,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,MAAM,KAAK,IAAI,EAAE,SAAS,OAAO,OAAO,MAAM,MAAM;AAAA,MAC9F,SAAS,GAAG;AACV,eAAO,EAAE,SAAS,OAAO,OAAOQ,iBAAgB,CAAC,EAAE;AAAA,MACrD;AAAA,IACF;AAEO,IAAM,aAAa,OAAO,aAA4C;AAtsB7E;AAusBE,YAAM,SAAS,UAAU;AACzB,UAAI;AACF,YAAI;AACJ,YAAI;AACF,gBAAM,WAAW,MAAM,QAAQ,QAAQ;AACvC,4BAAiB,0CAAU,QAAV,mBAAe;AAAA,QAClC,SAAQ;AAAA,QAER;AAGA,cAAM,iBACJ,OAAO,mBAAmB,WACtB;AAAA,UACE,GAAG,OAAO,OAAO,+BAA+B,UAAU,gBAAgB,OAAO,WAAW,CAAC;AAAA,UAC7F,GAAG,OAAO,OAAO,+BAA+B,UAAU,gBAAgB,OAAO,WAAW,CAAC;AAAA,QAC/F,IACA,CAAC;AAEP,YAAI,iBAAiB,GAAG;AACtB,gBAAM,uCAAuC;AAC7C,gBAAM,gBAAgB,gBAAM,wBAAQ,GAAG,IAAI,wBAAwB,MAA7C,mBAAgD;AACtE,gBAAM,iBAAiB,UAAU,UAAU,QAAQ,IAAI,YAAY;AACnE,qBAAW,UAAU,gBAAgB;AACnC,gBAAI;AACF,oBAAM,iBAAiB,QAAQ,oBAAoB,MAAM,IAAI,YAAY;AAAA,YAC3E,SAAQ;AAAA,YAER;AAAA,UACF;AAGA,cAAI,cAAc;AAChB,0BAAc,cAAc,EAAE,MAAM,UAAU,MAAM,SAAS,CAAC;AAAA,UAChE;AAEA,gBAAM,iCAAiC,UAAU,cAAc,IAAI;AACnE,gBAAMD,SAAQ,MAAM,WAAW,QAAQ;AAEvC,iBAAOA,OAAM,UAAU,SAAS,IAAIA;AAAA,QACtC;AAEA,cAAM,WAAW,aAAAR,QAAK;AAAA;AAAA,UAA+B,QAAQ,IAAI;AAAA,UAAG;AAAA,QAAQ;AAC5E,cAAM,iBAAAC,QAAW,OAAO,QAAQ;AAChC,mBAAW,UAAU,gBAAgB;AACnC,cAAI;AACF,kBAAM,iBAAAA,QAAW,OAAO,aAAAD,QAAK;AAAA;AAAA,cAA+B,QAAQ,IAAI;AAAA,cAAG;AAAA,YAAM,CAAC;AAAA,UACpF,SAAQ;AAAA,UAER;AAAA,QACF;AACA,cAAM,iCAAiC,UAAU,QAAW,KAAK;AACjE,cAAM,QAAQ,MAAM,WAAW,QAAQ;AAEvC,eAAO,MAAM,UAAU,SAAS,IAAI;AAAA,MACtC,SAAS,GAAG;AACV,eAAO,UAAU,CAAC;AAAA,MACpB;AAAA,IACF;AAAA;AAAA;;;ACjwBA;AAAA;AAAA;AAAA;AAcA,eAAe,UAAiC;AAC9C,MAAI;AACF,WAAQ,MAAM,OAAO,mBAAmB;AAAA,EAC1C,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,oBAAoB,UAA0C;AAIrE,QAAM,MAA0D,CAAC;AACjE,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,SAAS,QAAQ;AACrB,YAAM,OAAO,IAAI,IAAI,SAAS,CAAC;AAC/B,YAAM,QAAQ;AAAA,QACZ,MAAM;AAAA,QACN,aAAa,EAAE;AAAA,QACf,SAAS,EAAE;AAAA,SACP,EAAE,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;AAExC,UAAI,QAAQ,KAAK,SAAS,UAAU,MAAM,QAAQ,KAAK,OAAO,GAAG;AAC/D,QAAC,KAAK,QAAsB,KAAK,KAAK;AAAA,MACxC,OAAO;AACL,YAAI,KAAK,EAAE,MAAM,QAAQ,SAAS,CAAC,KAAK,EAAE,CAAC;AAAA,MAC7C;AACA;AAAA,IACF;AACA,QAAI,EAAE,SAAS,QAAQ;AACrB,UAAI,OAAO,EAAE,YAAY,UAAU;AACjC,YAAI,KAAK,EAAE,MAAM,QAAQ,SAAS,EAAE,QAAQ,CAAC;AAAA,MAC/C,OAAO;AACL,cAAMU,UAAS,EAAE,QAAQ,IAAI,CAAC,MAAM,wBAAwB,CAAC,CAAC;AAC9D,YAAI,KAAK,EAAE,MAAM,QAAQ,SAASA,QAAO,CAAC;AAAA,MAC5C;AACA;AAAA,IACF;AAEA,UAAM,SAAS,EAAE,QAAQ,IAAI,CAAC,MAAM;AAClC,UAAI,EAAE,SAAS,OAAQ,QAAO,EAAE,MAAM,QAAQ,MAAM,EAAE,KAAK;AAC3D,UAAI,EAAE,SAAS,WAAY,QAAO,EAAE,MAAM,YAAY,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,OAAO,EAAE,MAAM;AAE7F,aAAO,EAAE,MAAM,QAAQ,MAAM,eAAe,EAAE,IAAI,UAAU;AAAA,IAC9D,CAAC;AACD,QAAI,KAAK,EAAE,MAAM,aAAa,SAAS,OAAO,CAAC;AAAA,EACjD;AACA,SAAO;AACT;AAOA,SAAS,wBAAwB,OAAwD;AACvF,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO,EAAE,MAAM,QAAQ,MAAM,MAAM,KAAK;AAAA,EAC1C;AACA,MAAI,MAAM,SAAS,gBAAgB;AACjC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,YAAY,MAAM;AAAA,QAClB,MAAM,MAAM;AAAA,MACd;AAAA,MACA,OAAO,MAAM;AAAA,IACf;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,QAAQ,MAAM,uBAAuB,MAAM,IAAI,IAAI;AACpE;AAEA,SAAS,iBAAiB,OAAoC;AAC5D,SAAO,MAAM,IAAI,CAAC,OAAO;AAAA,IACvB,MAAM,EAAE;AAAA,IACR,aAAa,EAAE;AAAA,IACf,cAAc,EAAE;AAAA,EAClB,EAAE;AACJ;AAqHA,SAAS,uBAAuB,GAAgF;AAC9G,MAAI,MAAM,cAAc,MAAM,cAAc,MAAM,gBAAgB,MAAM,gBAAiB,QAAO;AAChG,SAAO;AACT;AAxNA,IAkGa;AAlGb;AAAA;AAAA;AAQA;AA0FO,IAAM,wBAAN,MAAoD;AAAA,MAIzD,YAA6B,UAA6B;AAA7B;AAH7B,aAAS,eAAe;AACxB,aAAS,oBAAoB;AAAA,MAE8B;AAAA,MAE3D,IAAI,UAAkB;AACpB,eAAO,KAAK,SAAS;AAAA,MACvB;AAAA,MAEO,WAAW,OAAsD;AAAA;AA5G1E;AA6GI,cAAI;AACJ,cAAI;AACF,kBAAM,kBAAM,QAAQ;AAAA,UACtB,SAAS,KAAK;AACZ,kBAAM,EAAE,MAAM,SAAS,SAAS,eAAe,QAAQ,IAAI,UAAU,+BAA+B;AACpG;AAAA,UACF;AAEA,gBAAM,WAAU,uBAAkB,KAAK,QAAQ,MAA/B,YAAoC;AACpD,gBAAM,SAAS,QAAQ,IAAI,OAAO;AAClC,cAAI,CAAC,QAAQ;AACX,kBAAM,EAAE,MAAM,SAAS,SAAS,8BAAyB,OAAO,uBAAuB;AACvF;AAAA,UACF;AAEA,gBAAM,aAAa,SAA0E,YAA1E,YAAqF;AACxG,gBAAM,SAAS,IACb,UAGA,EAAE,OAAO,CAAC;AAEZ,gBAAM,SAAS,OAAO,SAAS,OAAO;AAAA,YACpC,OAAO,KAAK,SAAS;AAAA,YACrB,YAAY,MAAM;AAAA,YAClB,QAAQ,MAAM;AAAA,YACd,UAAU,oBAAoB,MAAM,QAAQ;AAAA,aACxC,MAAM,MAAM,SAAS,IAAI,EAAE,OAAO,iBAAiB,MAAM,KAAK,EAAE,IAAI,CAAC,EAC1E;AAED,gBAAM,mBAAmB,oBAAI,IAAoB;AACjD,gBAAM,YAAY,oBAAI,IAAoB;AAC1C,gBAAM,cAAc,oBAAI,IAAoB;AAE5C,cAAI;AACF;AAAA,yCAAuB,SAAvB,uFAA4F;AAAjF,sBAAM,KAAjB;AACE,wBAAQ,GAAG,MAAM;AAAA,kBACf,KAAK,uBAAuB;AAC1B,0BAAM,MAAM,GAAG;AACf,0BAAM,QAAQ,GAAG;AACjB,wBAAI,MAAM,SAAS,YAAY;AAC7B,4BAAM,MAAK,WAAM,OAAN,YAAY,QAAQ,GAAG;AAClC,4BAAM,QAAO,WAAM,SAAN,YAAc;AAC3B,gCAAU,IAAI,KAAK,EAAE;AACrB,kCAAY,IAAI,KAAK,IAAI;AACzB,uCAAiB,IAAI,KAAK,EAAE;AAC5B,4BAAM,EAAE,MAAM,kBAAkB,IAAI,KAAK;AAAA,oBAC3C;AACA;AAAA,kBACF;AAAA,kBACA,KAAK,uBAAuB;AAC1B,0BAAM,MAAM,GAAG;AACf,0BAAM,QAAQ,GAAG;AACjB,wBAAI,MAAM,SAAS,gBAAgB,OAAO,MAAM,SAAS,UAAU;AACjE,4BAAM,EAAE,MAAM,cAAc,MAAM,MAAM,KAAK;AAAA,oBAC/C,WAAW,MAAM,SAAS,sBAAsB,OAAO,MAAM,iBAAiB,UAAU;AACtF,4BAAM,KAAK,UAAU,IAAI,GAAG;AAC5B,0BAAI,IAAI;AACN,yCAAiB,IAAI,OAAM,sBAAiB,IAAI,GAAG,MAAxB,YAA6B,MAAM,MAAM,YAAY;AAChF,8BAAM,EAAE,MAAM,wBAAwB,IAAI,aAAa,MAAM,aAAa;AAAA,sBAC5E;AAAA,oBACF;AACA;AAAA,kBACF;AAAA,kBACA,KAAK,sBAAsB;AACzB,0BAAM,MAAM,GAAG;AACf,0BAAM,KAAK,UAAU,IAAI,GAAG;AAC5B,0BAAM,OAAO,YAAY,IAAI,GAAG;AAChC,wBAAI,MAAM,SAAS,QAAW;AAC5B,4BAAM,OAAM,sBAAiB,IAAI,GAAG,MAAxB,YAA6B;AACzC,0BAAI,SAAkB,CAAC;AACvB,0BAAI;AACF,iCAAS,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAAA,sBACpC,SAAQ;AACN,iCAAS,EAAE,WAAW,IAAI;AAAA,sBAC5B;AACA,4BAAM,EAAE,MAAM,qBAAqB,IAAI,MAAM,OAAO,OAAO;AAAA,oBAC7D;AACA;AAAA,kBACF;AAAA,kBACA;AACE;AAAA,gBACJ;AAAA,cACF;AAAA,qBAhDA,MAhJN;AAgJM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiDA,kBAAM,QAAS,kBAAM,OAAO,aAAa;AAIzC,kBAAM,SAAQ,WAAM,UAAN,YAAe,CAAC;AAC9B,kBAAM;AAAA,cACJ,MAAM;AAAA,cACN,YAAY,uBAAuB,MAAM,WAAW;AAAA,cACpD,OAAO;AAAA,gBACL,cAAa,WAAM,iBAAN,YAAsB;AAAA,gBACnC,eAAc,WAAM,kBAAN,YAAuB;AAAA,gBACrC,oBAAmB,WAAM,4BAAN,YAAiC;AAAA,cACtD;AAAA,YACF;AAAA,UACF,SAAS,KAAK;AACZ,kBAAM,EAAE,MAAM,SAAS,SAAS,eAAe,QAAQ,IAAI,UAAU,0BAA0B;AAAA,UACjG;AAAA,QACF;AAAA;AAAA,IACF;AAAA;AAAA;;;ACnNA;AAAA;AAAA;AAAA;AAiBA,eAAeC,WAA8B;AAC3C,MAAI;AACF,WAAQ,MAAM,OAAO,QAAQ;AAAA,EAC/B,SAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAYA,SAAS,iBAAiB,cAAsB,UAAgD;AArChG;AAsCE,QAAM,MAAuB,CAAC;AAC9B,MAAI,aAAc,KAAI,KAAK,EAAE,MAAM,UAAU,SAAS,aAAa,CAAC;AAEpE,aAAW,KAAK,UAAU;AACxB,QAAI,EAAE,SAAS,QAAQ;AACrB,UAAI,KAAK,EAAE,MAAM,QAAQ,cAAc,EAAE,WAAW,SAAS,EAAE,QAAQ,CAAC;AACxE;AAAA,IACF;AACA,QAAI,EAAE,SAAS,QAAQ;AACrB,YAAMC,QAAO,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,YAAY,EAAE,OAAO;AAC9E,UAAI,KAAK,EAAE,MAAM,QAAQ,SAASA,MAAK,CAAC;AACxC;AAAA,IACF;AAEA,QAAI,OAAO;AACX,UAAM,YAA+F,CAAC;AACtG,eAAW,SAAS,EAAE,SAAS;AAC7B,UAAI,MAAM,SAAS,OAAQ,SAAQ,MAAM;AAAA,eAChC,MAAM,SAAS,YAAY;AAClC,kBAAU,KAAK;AAAA,UACb,IAAI,MAAM;AAAA,UACV,MAAM;AAAA,UACN,UAAU,EAAE,MAAM,MAAM,MAAM,WAAW,KAAK,WAAU,WAAM,UAAN,YAAe,CAAC,CAAC,EAAE;AAAA,QAC7E,CAAC;AAAA,MACH;AAAA,IACF;AACA,QAAI,KAAK;AAAA,MACP,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,OACb,UAAU,SAAS,IAAI,EAAE,YAAY,UAAU,IAAI,CAAC,EACzD;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,YAAY,QAAsE;AAzE3F;AA8EE,QAAM,QAAkB,CAAC;AACzB,aAAW,KAAK,QAAQ;AACtB,QAAI,EAAE,SAAS,QAAQ;AACrB,YAAM,MAAK,OAAE,SAAF,YAAU,EAAE;AAAA,IACzB,WAAW,EAAE,SAAS,gBAAgB;AACpC,YAAM,KAAK,mBAAkB,OAAE,aAAF,YAAc,cAAc,yDAAoD;AAAA,IAC/G;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,cAAc,OAAoC;AACzD,SAAO,MAAM,IAAI,CAAC,OAAO;AAAA,IACvB,MAAM;AAAA,IACN,UAAU;AAAA,MACR,MAAM,EAAE;AAAA,MACR,aAAa,EAAE;AAAA,MACf,YAAY,EAAE;AAAA,IAChB;AAAA,EACF,EAAE;AACJ;AA6JA,SAAS,gBACP,GACA,cACoE;AACpE,MAAI,MAAM,gBAAiB,gBAAgB,MAAM,SAAW,QAAO;AACnE,MAAI,MAAM,OAAQ,QAAO;AACzB,MAAI,MAAM,SAAU,QAAO;AAC3B,SAAO;AACT;AAvQA,IAoGa;AApGb;AAAA;AAAA;AAWA;AAyFO,IAAM,qBAAN,MAAiD;AAAA,MAGtD,YAA6B,UAA0C;AAA1C;AAF7B,aAAS,oBAAoB;AAAA,MAE2C;AAAA,MAExE,IAAI,eAAmC;AACrC,eAAO,KAAK,SAAS;AAAA,MACvB;AAAA,MAEA,IAAI,UAAkB;AACpB,eAAO,KAAK,SAAS;AAAA,MACvB;AAAA,MAEO,WAAW,OAAsD;AAAA;AAjH1E;AAkHI,cAAI;AACJ,cAAI;AACF,kBAAM,kBAAMD,SAAQ;AAAA,UACtB,SAAS,KAAK;AACZ,kBAAM,EAAE,MAAM,SAAS,SAAS,eAAe,QAAQ,IAAI,UAAU,4BAA4B;AACjG;AAAA,UACF;AAEA,gBAAM,UAAU,kBAAkB,KAAK,QAAQ;AAC/C,gBAAM,SAAS,UAAU,QAAQ,IAAI,OAAO,IAAI;AAChD,gBAAM,UACJ,KAAK,SAAS,SAAS,UAAU,KAAK,SAAS,WAAY,UAAK,SAA4B,YAAjC,YAA4C;AAEzG,cAAI,KAAK,SAAS,SAAS,YAAY,CAAC,QAAQ;AAC9C,kBAAM;AAAA,cACJ,MAAM;AAAA,cACN,SAAS,8BAAyB,4BAAW,gBAAgB;AAAA,YAC/D;AACA;AAAA,UACF;AAEA,gBAAM,UAAU,SAA+D,YAA/D,YAA0E;AAC1F,gBAAM,SAAS,IACb,OAOA;AAAA;AAAA,YAEA,QAAQ,0BAAW,KAAK,SAAS,SAAS,UAAU,cAAc;AAAA,aAC9D,UAAU,EAAE,QAAQ,IAAI,CAAC,EAC9B;AAED,gBAAM,WAAW,iBAAiB,MAAM,cAAc,MAAM,QAAQ;AACpE,gBAAM,QAAQ,MAAM,MAAM,SAAS,IAAI,cAAc,MAAM,KAAK,IAAI;AAEpE,cAAI;AACJ,cAAI;AACF,qBAAS,kBAAM,OAAO,KAAK,YAAY,OAAO;AAAA,cAC5C,OAAO,KAAK,SAAS;AAAA,cACrB,YAAY,MAAM;AAAA,cAClB,QAAQ;AAAA,cACR,gBAAgB,EAAE,eAAe,KAAK;AAAA,cACtC;AAAA,eACI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAC1B;AAAA,UACH,SAAS,KAAK;AACZ,kBAAM,EAAE,MAAM,SAAS,SAAS,eAAe,QAAQ,IAAI,UAAU,+BAA+B;AACpG;AAAA,UACF;AAGA,gBAAM,YAAY,oBAAI,IAA2B;AACjD,cAAI,eAA8B;AAClC,cAAI,QAA8D,CAAC;AAEnE,cAAI;AACF;AAAA,yCAA0B,SAA1B,uFAOI;AAPO,sBAAM,QAAjB;AAQE,sBAAM,UAAS,WAAM,YAAN,mBAAgB;AAC/B,sBAAM,QAAQ,iCAAQ;AACtB,oBAAI,+BAAO,SAAS;AAClB,wBAAM,EAAE,MAAM,cAAc,MAAM,MAAM,QAAQ;AAAA,gBAClD;AACA,oBAAI,+BAAO,YAAY;AACrB,6BAAW,MAAM,MAAM,YAIlB;AACH,0BAAM,MAAM,GAAG;AACf,wBAAI,MAAM,UAAU,IAAI,GAAG;AAC3B,wBAAI,CAAC,KAAK;AACR,4BAAM,EAAE,KAAI,QAAG,OAAH,YAAS,QAAQ,GAAG,IAAI,MAAM,IAAI,UAAU,IAAI,cAAc,MAAM;AAChF,gCAAU,IAAI,KAAK,GAAG;AAAA,oBACxB;AACA,wBAAI,GAAG,GAAI,KAAI,KAAK,GAAG;AACvB,yBAAI,QAAG,aAAH,mBAAa,KAAM,KAAI,OAAO,GAAG,SAAS;AAC9C,wBAAI,CAAC,IAAI,gBAAgB,IAAI,MAAM;AACjC,0BAAI,eAAe;AACnB,4BAAM,EAAE,MAAM,kBAAkB,IAAI,IAAI,IAAI,MAAM,IAAI,KAAK;AAAA,oBAC7D;AACA,yBAAI,QAAG,aAAH,mBAAa,WAAW;AAC1B,0BAAI,YAAY,GAAG,SAAS;AAC5B,0BAAI,IAAI,cAAc;AACpB,8BAAM,EAAE,MAAM,wBAAwB,IAAI,IAAI,IAAI,aAAa,GAAG,SAAS,UAAU;AAAA,sBACvF;AAAA,oBACF;AAAA,kBACF;AAAA,gBACF;AACA,oBAAI,iCAAQ,eAAe;AACzB,iCAAe,OAAO;AAAA,gBACxB;AACA,oBAAI,MAAM,OAAO;AACf,0BAAQ;AAAA,oBACN,OAAO,MAAM,MAAM;AAAA,oBACnB,QAAQ,MAAM,MAAM;AAAA,oBACpB,SAAQ,WAAM,MAAM,0BAAZ,mBAAmC;AAAA,kBAC7C;AAAA,gBACF;AAAA,cACF;AAAA,qBAjDA,MA9KN;AA8KM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAkDF,SAAS,KAAK;AACZ,kBAAM,EAAE,MAAM,SAAS,SAAS,eAAe,QAAQ,IAAI,UAAU,uBAAuB;AAC5F;AAAA,UACF;AAGA,qBAAW,OAAO,UAAU,OAAO,GAAG;AACpC,gBAAI,CAAC,IAAI,cAAc;AACrB,oBAAM,EAAE,MAAM,kBAAkB,IAAI,IAAI,IAAI,MAAM,IAAI,KAAK;AAAA,YAC7D;AACA,gBAAI,SAAkB,CAAC;AACvB,gBAAI;AACF,uBAAS,IAAI,WAAW,KAAK,MAAM,IAAI,QAAQ,IAAI,CAAC;AAAA,YACtD,SAAQ;AACN,uBAAS,EAAE,WAAW,IAAI,SAAS;AAAA,YACrC;AACA,kBAAM,EAAE,MAAM,qBAAqB,IAAI,IAAI,IAAI,MAAM,IAAI,MAAM,OAAO,OAAO;AAAA,UAC/E;AAEA,gBAAM;AAAA,YACJ,MAAM;AAAA,YACN,YAAY,gBAAgB,cAAc,UAAU,OAAO,CAAC;AAAA,YAC5D,OAAO;AAAA,cACL,cAAa,WAAM,UAAN,YAAe;AAAA,cAC5B,eAAc,WAAM,WAAN,YAAgB;AAAA,cAC9B,oBAAmB,WAAM,WAAN,YAAgB;AAAA,YACrC;AAAA,UACF;AAAA,QACF;AAAA;AAAA,IACF;AAAA;AAAA;;;AC7PA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOO,IAAM,uBAAoC;AAAA,EAC/C,UAAU;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS,EAAE,WAAW,GAAG,YAAY,GAAG,iBAAiB,IAAI;AAAA,EAC/D;AAAA,EACA,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,qBAAqB;AAAA,EACrB,oBAAoB,KAAK,OAAO;AAAA,EAChC,uBAAuB;AAAA,EACvB,gBAAgB;AAClB;AASO,SAAS,kBAAkB,YAAkC,CAAC,GAAgB;AA5BrF;AA6BE,SAAO,gDACF,uBACA,YAFE;AAAA,IAGL,WAAU,eAAU,aAAV,YAAsB,qBAAqB;AAAA,EACvD;AACF;;;ADzBA;AACA;AACA;AACA;AACA;AACA;AAQA;AAcA;AACA;;;AEnBA,IAAAE,aAAuC;AACvC,IAAAC,eAAiB;AAGjBC;AACA;AAEA;AACA;AACA;AAkCA,IAAM,qBAAqB;AAC3B,IAAI,SAA4B;AAEhC,eAAe,SAAS,QAA4B,SAA4C;AAC9F,QAAM,MAAM,0BAAU;AACtB,QAAM,MAAM,KAAK,IAAI;AACrB,MAAI,CAAC,WAAW,UAAU,OAAO,QAAQ,OAAO,OAAO,YAAY,KAAK;AACtE,WAAO,OAAO;AAAA,EAChB;AACA,QAAM,QAAQ,MAAM,eAAe,MAAM;AACzC,WAAS,EAAE,OAAO,WAAW,MAAM,oBAAoB,IAAI;AAC3D,SAAO;AACT;AAGO,SAAS,mBAAyB;AACvC,WAAS;AACX;AAEA,eAAe,iBAAiB,UAAkB,QAAqD;AAKrG,MAAI;AACF,QAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM;AAChC,YAAM,OAAO,MAAMA,eAAc,UAAU,MAAM;AACjD,UAAI,MAAM;AACR,YAAI;AACF,iBAAO,KAAK,MAAM,KAAK,OAAO;AAAA,QAChC,SAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAQ;AAAA,EAER;AACA,MAAI;AACF,UAAM,MAAM,aAAAC,QAAK,KAAK,QAAQ,IAAI,GAAG,OAAO,SAAS,QAAQ,aAAa,EAAE,CAAC;AAC7E,UAAM,MAAM,MAAM,WAAAC,SAAW,SAAS,KAAK,EAAE,UAAU,OAAO,CAAC;AAC/D,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUA,eAAsB,cAAc,OAAe,UAAyB,CAAC,GAAyB;AArHtG;AAsHE,QAAM,WAAU,oCAAO,WAAP,YAAiB;AACjC,MAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,QAAM,IAAI,KAAK,IAAI,IAAG,aAAQ,MAAR,YAAa,EAAE;AACrC,QAAM,YAAW,aAAQ,aAAR,YAAoB,mBAAmB;AACxD,QAAM,SAAiB,UAAU;AAEjC,QAAM,QAAQ,MAAM,SAAS,QAAQ,SAAQ,aAAQ,YAAR,YAAmB,KAAK;AACrE,QAAM,QAAQ,OAAO,KAAK,MAAM,OAAO;AACvC,MAAI,MAAM,WAAW,EAAG,QAAO,CAAC;AAEhC,QAAM,CAAC,QAAQ,IAAI,MAAM,SAAS,MAAM,CAAC,OAAO,CAAC;AAKjD,QAAM,SAAmB,CAAC;AAC1B,aAAW,KAAK,OAAO;AACrB,QAAI,QAAQ,YAAY;AACtB,YAAM,IAAI,mBAAmB,QAAQ,CAAC;AACtC,UAAI,MAAM,QAAQ,WAAY;AAAA,IAChC;AACA,UAAM,SAAS,MAAM,QAAQ,CAAC;AAC9B,QAAI;AACJ,QAAI;AACF,YAAM,cAAc,OAAO,GAAG;AAAA,IAChC,SAAQ;AACN;AAAA,IACF;AACA,QAAI,IAAI,WAAW,SAAS,OAAQ;AACpC,UAAM,QAAQ,iBAAiB,UAAU,GAAG;AAC5C,WAAO,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;AAAA,EAChC;AAEA,SAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACvC,QAAM,MAAM,OAAO,MAAM,GAAG,CAAC;AAE7B,QAAM,iBAAgB,aAAQ,kBAAR,YAAyB;AAC/C,QAAM,OAAoB,CAAC;AAC3B,aAAW,EAAE,MAAM,GAAG,MAAM,KAAK,KAAK;AACpC,UAAM,UAAW,MAAM,iBAAiB,GAAG,QAAQ,MAAM;AAIzD,UAAM,aAAa,mBAAmB,QAAQ,CAAC;AAC/C,SAAK,KAAK;AAAA,MACR,IAAI,eAAe,QAAQ,GAAG,4BAAW,MAAS;AAAA,MAClD,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,OAAO,kBAAkB,QAAQ,GAAG,4BAAW,MAAS;AAAA,MACxD,SAAS,kBAAkB,QAAQ,GAAG,4BAAW,QAAW,aAAa;AAAA,IAC3E,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;ACnJO,SAAS,kBAAkB,EAAE,QAAQ,gBAAgB,IAAI,GAA8B;AAC5F,QAAM,SAAS,oBAAO,oBAAI,KAAK,GAAG,YAAY,EAAE,MAAM,GAAG,EAAE;AAE3D,QAAM,kBAA4B,CAAC;AACnC,aAAW,CAAC,MAAM,GAAG,KAAK,OAAO,QAAQ,OAAO,WAAW,GAAG;AAC5D,UAAM,eAAe,OAAO,QAAQ,IAAI,MAAM,EAC3C,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,GAAG,GAAG,IAAI,IAAI,MAAM,GAAG,IAAI,WAAW,MAAM,EAAE,EAAE,EACpE,KAAK,IAAI;AACZ,UAAM,cAAc,IAAI,UAAU,SAAS;AAC3C,oBAAgB,KAAK,OAAO,IAAI,KAAK,WAAW,YAAY,IAAI,KAAK,OAAO,YAAY,EAAE;AAAA,EAC5F;AAEA,QAAM,iBACJ,kBAAkB,eAAe,SAAS,IACtC,4CACA,eAAe,IAAI,CAAC,GAAG,MAAM,eAAe,IAAI,CAAC,WAAM,EAAE,IAAI,MAAM,EAAE,KAAK;AAAA,EAAM,EAAE,KAAK,KAAK,CAAC,EAAE,EAAE,KAAK,MAAM,IAC5G;AAEN,SAAO;AAAA;AAAA,kBAES,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4BrB,gBAAgB,KAAK,IAAI,CAAC;AAAA;AAAA,kGAEsE,cAAc;AAChH;;;AC5DA,yBAA2B;;;AC+DpB,SAAS,oBAAoB,QAAyD;AAC3F,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,QAAI,KAAK,MAAM;AACb,UAAI,CAAC,IAAI;AAAA,IACX,WAAW,OAAO,MAAM,UAAU;AAChC,UAAI,CAAC,IAAI,KAAK,UAAU,CAAC;AAAA,IAC3B,OAAO;AACL,UAAI,CAAC,IAAI,OAAO,CAAC;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAOA,eAAsB,iBAAiB,YAAoB,SAAiB,QAAwC;AAClH,MAAI,EAAE,cAAc,OAAO,aAAc,QAAO;AAChD,QAAM,UAAU,QAAQ,KAAK,EAAE,QAAQ,WAAW,EAAE;AACpD,QAAM,EAAE,iBAAAC,iBAAgB,IAAK,MAAM;AACnC,QAAM,UAAU,MAAMA,iBAAgB,UAAU,EAAE,MAAM,MAAM,CAAC,CAAa;AAC5E,QAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM;AAzGpC;AA0GI,UAAM,QAAO,OACV,MAAM,GAAG,EACT,IAAI,MAFM,mBAGT,QAAQ,WAAW;AACvB,WAAO,SAAS;AAAA,EAClB,CAAC;AACD,SAAO,wBAAS;AAClB;AAQA,eAAsB,eAAe,UAA2C;AAC9E,QAAM,EAAE,UAAAC,WAAU,SAAAC,UAAS,SAAAC,SAAQ,IAChC,MAAM;AAET,MAAI,SAAS,SAAS,QAAQ;AAC5B,QAAIC;AACJ,QAAI;AACF,MAAAA,YAAW,MAAMD,SAAQ,SAAS,SAAS;AAAA,IAC7C,SAAS,KAAK;AACZ,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,2BAA2B,SAAS,SAAS,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAC3G;AAAA,IACF;AACA,QAAI,CAACC,aAAY,CAACA,UAAS,KAAK;AAC9B,aAAO,EAAE,IAAI,OAAO,OAAO,SAAS,SAAS,SAAS,cAAc;AAAA,IACtE;AACA,UAAMC,gBAAe,kCAAKD,UAAS,SAAW,SAAS;AACvD,UAAME,WAAU,EAAE,KAAKF,UAAS,KAAK,QAAQC,cAAa;AAC1D,UAAM,SAAS,MAAMJ,UAASK,UAA2C,SAAS,SAAS;AAC3F,QAAI,CAAC,OAAO,SAAS;AACnB,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,OAAO,OAAO;AAAA,SACV,OAAO,cAAc,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;AAAA,IAEpE;AACA,WAAO,EAAE,IAAI,MAAM,WAAW,SAAS,UAAU;AAAA,EACnD;AAGA,QAAM,UAAU,MAAMJ,SAAQ,SAAS,UAAU;AACjD,MAAI,CAAC,QAAQ,SAAS;AACpB,WAAO,EAAE,IAAI,OAAO,OAAO,QAAQ,MAAM;AAAA,EAC3C;AACA,MAAI;AACJ,MAAI;AACF,eAAW,MAAMC,SAAQ,QAAQ,IAAI;AAAA,EACvC,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,6CAA6C,QAAQ,IAAI,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACvH;AAAA,EACF;AACA,QAAM,eAAe,kCAAK,SAAS,SAAW,SAAS;AACvD,QAAM,UAAU,EAAE,KAAK,SAAS,KAAK,QAAQ,aAAa;AAC1D,QAAM,QAAQ,MAAMF,UAAS,SAA2C,QAAQ,IAAI;AACpF,MAAI,CAAC,MAAM,SAAS;AAClB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,MAAM;AAAA,OACT,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,EAElE;AACA,SAAO,EAAE,IAAI,MAAM,WAAW,QAAQ,KAAK;AAC7C;AAMO,SAAS,oBACd,YACA,SACA,cACQ;AACR,QAAM,SAAS,OAAO,KAAK,YAAY;AACvC,QAAM,OAAO,OAAO,SAAS,IAAI,GAAG,OAAO,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,MAAM,OAAO,SAAS,CAAC,UAAU,OAAO,KAAK,IAAI;AAClH,SAAO,QAAQ,UAAU,IAAI,OAAO,GAAG,OAAO,KAAK,IAAI,MAAM,EAAE;AACjE;AAGO,SAAS,sBAAsB,YAAoB,QAAyC;AACjG,QAAM,aAAa,OAAO,KAAK,MAAM,EAAE;AACvC,SAAO,cAAc,UAAU,KAAK,UAAU,SAAS,eAAe,IAAI,KAAK,GAAG;AACpF;;;ADzIA,IAAM,oBAAiC;AAAA,EACrC,YAAY;AAAA,IACV,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,OAAO,EAAE,MAAM,UAAU,aAAa,iCAAiC;AAAA,QACvE,GAAG;AAAA,UACD,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,QACA,YAAY;AAAA,UACV,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,OAAO;AAAA,IACpB;AAAA,EACF;AAAA,EACA,MAAM,IAAI,OAAO,KAAK;AACpB,UAAM,EAAE,OAAO,GAAG,WAAW,IAAK,wBAAS,CAAC;AAC5C,QAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,GAAG;AAC9C,aAAO,KAAK,UAAU,EAAE,OAAO,mDAAmD,CAAC;AAAA,IACrF;AACA,UAAM,OAAO,MAAM,cAAc,OAAO;AAAA,MACtC,GAAG,OAAO,MAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI;AAAA,MACtE,YAAY,OAAO,eAAe,YAAY,WAAW,KAAK,IAAI,WAAW,KAAK,IAAI;AAAA,MACtF,QAAQ,IAAI;AAAA,IACd,CAAC;AACD,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO,KAAK,UAAU;AAAA,QACpB,SAAS,CAAC;AAAA,QACV,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,WAAO,KAAK,UAAU;AAAA,MACpB,SAAS,KAAK,IAAI,CAAC,OAAO;AAAA,QACxB,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,YAAY,EAAE;AAAA,QACd,OAAO,OAAO,EAAE,MAAM,QAAQ,CAAC,CAAC;AAAA,QAChC,OAAO,EAAE;AAAA,QACT,SAAS,EAAE;AAAA,MACb,EAAE;AAAA,IACJ,CAAC;AAAA,EACH;AACF;AAEA,IAAM,sBAAmC;AAAA,EACvC,YAAY;AAAA,IACV,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa,EAAE,MAAM,UAAU,YAAY,CAAC,GAAG,sBAAsB,MAAM;AAAA,EAC7E;AAAA,EACA,MAAM,IAAI,QAAQ,KAAK;AACrB,UAAM,cAAc,OAAO,QAAQ,IAAI,OAAO,WAAW,EAAE,IAAI,CAAC,CAAC,MAAM,GAAG,OAAO;AAAA,MAC/E;AAAA,MACA,OAAO,IAAI;AAAA,MACX,SAAS,QAAQ,IAAI,OAAO;AAAA,MAC5B,QAAQ,OAAO,QAAQ,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,GAAG,OAAO;AAAA,QACtD;AAAA,QACA,OAAO,IAAI;AAAA,QACX,QAAQ,IAAI;AAAA,QACZ,UAAU,QAAQ,IAAI,QAAQ;AAAA,MAChC,EAAE;AAAA,IACJ,EAAE;AACF,WAAO,KAAK,UAAU,EAAE,YAAY,CAAC;AAAA,EACvC;AACF;AAEA,IAAM,eAA4B;AAAA,EAChC,YAAY;AAAA,IACV,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,IAAI,EAAE,MAAM,UAAU,aAAa,kCAAkC;AAAA,QACrE,YAAY;AAAA,UACV,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EACA,MAAM,IAAI,OAAO,KAAK;AACpB,UAAM,EAAE,IAAI,WAAW,IAAK,wBAAS,CAAC;AACtC,QAAI,OAAO,OAAO,YAAY,CAAC,GAAG,KAAK,GAAG;AACxC,aAAO,KAAK,UAAU,EAAE,OAAO,gDAAgD,CAAC;AAAA,IAClF;AACA,UAAM,UAAU,GAAG,KAAK,EAAE,QAAQ,WAAW,EAAE;AAC/C,UAAM,EAAE,SAAAM,UAAS,iBAAAC,iBAAgB,IAC9B,MAAM;AAET,UAAM,UAAU,OAAO,eAAe,YAAY,WAAW,KAAK,IAAI,WAAW,KAAK,IAAI;AAC1F,QAAI,WAAW,CAAC,IAAI,OAAO,YAAY,OAA8C,GAAG;AACtF,aAAO,KAAK,UAAU,EAAE,OAAO,uBAAuB,OAAO,GAAG,CAAC;AAAA,IACnE;AAEA,UAAM,aAAa,UAAU,CAAC,OAAO,IAAI,OAAO,KAAK,IAAI,OAAO,WAAW;AAE3E,eAAW,KAAK,YAAY;AAC1B,YAAM,UAAU,MAAMA,iBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC,CAAa;AACnE,YAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM;AAzKxC;AA0KQ,cAAM,QAAO,OACV,MAAM,GAAG,EACT,IAAI,MAFM,mBAGT,QAAQ,WAAW;AACvB,eAAO,SAAS;AAAA,MAClB,CAAC;AACD,UAAI,CAAC,MAAO;AACZ,UAAI;AACF,cAAM,UAAU,MAAMD,SAAQ,KAAK;AACnC,eAAO,KAAK,UAAU,EAAE,MAAM,OAAO,OAAO,QAAQ,CAAC;AAAA,MACvD,SAAS,KAAK;AACZ,eAAO,KAAK,UAAU;AAAA,UACpB,OAAO,yBAAyB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAClF,CAAC;AAAA,MACH;AAAA,IACF;AACA,WAAO,KAAK,UAAU,EAAE,OAAO,2BAA2B,OAAO,IAAI,CAAC;AAAA,EACxE;AACF;AAEA,IAAM,kBAA+B;AAAA,EACnC,YAAY;AAAA,IACV,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,YAAY;AAAA,UACV,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,QACA,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,aACE;AAAA,UACF,sBAAsB;AAAA,QACxB;AAAA,QACA,WAAW;AAAA,UACT,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,WAAW,cAAc,gBAAgB,WAAW;AAAA,IACjE;AAAA,EACF;AAAA,EACA,MAAM,IAAI,OAAO,KAAK;AA5NxB;AA6NI,UAAM,EAAE,SAAS,YAAY,cAAc,UAAU,IAAK,wBAAS,CAAC;AAMpE,QAAI,OAAO,YAAY,YAAY,CAAC,QAAQ,KAAK,GAAG;AAClD,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,sDAAsD,CAAC;AAAA,IACnG;AACA,QAAI,OAAO,eAAe,YAAY,CAAC,WAAW,KAAK,GAAG;AACxD,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,yBAAyB,CAAC;AAAA,IACtE;AACA,QAAI,CAAC,gBAAgB,OAAO,iBAAiB,YAAY,MAAM,QAAQ,YAAY,GAAG;AACpF,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,+DAA0D,CAAC;AAAA,IACvG;AACA,UAAM,eAAe,OAAO,cAAc,WAAW,UAAU,KAAK,IAAI;AACxE,QAAI,CAAC,cAAc;AACjB,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,uCAAuC,CAAC;AAAA,IACpF;AAEA,UAAM,kBAAkB,WAAW,KAAK;AACxC,QAAI,EAAE,mBAAmB,IAAI,OAAO,cAAc;AAChD,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,uBAAuB,eAAe,GAAG,CAAC;AAAA,IACtF;AAEA,UAAM,UAAU,QAAQ,KAAK,EAAE,QAAQ,WAAW,EAAE;AACpD,UAAM,YAAY,MAAM,iBAAiB,iBAAiB,SAAS,IAAI,MAAM;AAC7E,QAAI,CAAC,WAAW;AACd,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,UAAU,OAAO,8BAA8B,eAAe,KAAK,CAAC;AAAA,IAChH;AAKA,UAAM,EAAE,SAAAA,SAAQ,IAAK,MAAM;AAC3B,QAAI;AACJ,QAAI;AACF,iBAAW,MAAMA,SAAQ,SAAS;AAAA,IACpC,SAAS,KAAK;AACZ,aAAO,KAAK,UAAU;AAAA,QACpB,IAAI;AAAA,QACJ,OAAO,yBAAyB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MAClF,CAAC;AAAA,IACH;AACA,UAAM,SAAS,kCAAK,SAAS,SAAY;AACzC,UAAM,eAAe,oBAAoB,MAAM;AAE/C,UAAM,EAAE,qBAAAE,qBAAoB,IACzB,MAAM;AACT,UAAM,aAAaA,qBAAoB,iBAAiB,YAAY;AACpE,QAAI,CAAC,WAAW,IAAI;AAClB,aAAO,KAAK,UAAU;AAAA,QACpB,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,aAAa,WAAW;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,UAAM,UAAU,oBAAoB,iBAAiB,SAAS,YAAuC;AACrG,UAAM,WAAyB;AAAA,MAC7B,IAAI,YAAQ,+BAAW,CAAC;AAAA,MACxB,MAAM;AAAA,MACN,YAAW,SAAI,cAAJ,YAAiB;AAAA,MAC5B,YAAY;AAAA,MACZ;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA,WAAW;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS,KAAK,UAAU;AAAA,QACtB,IAAI;AAAA,QACJ,YAAY,SAAS;AAAA,QACrB;AAAA,QACA,kBAAkB;AAAA,QAClB,MAAM;AAAA,MACR,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,sBAAmC;AAAA,EACvC,YAAY;AAAA,IACV,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,YAAY,EAAE,MAAM,UAAU,aAAa,0CAA0C;AAAA,QACrF,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,aACE;AAAA,UACF,sBAAsB;AAAA,QACxB;AAAA,QACA,WAAW;AAAA,UACT,MAAM;AAAA,UACN,aAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,UAAU,CAAC,cAAc,UAAU,WAAW;AAAA,IAChD;AAAA,EACF;AAAA,EACA,MAAM,IAAI,OAAO,KAAK;AAvUxB;AAwUI,UAAM,EAAE,YAAY,QAAQ,UAAU,IAAK,wBAAS,CAAC;AAKrD,QAAI,OAAO,eAAe,YAAY,CAAC,WAAW,KAAK,GAAG;AACxD,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,yBAAyB,CAAC;AAAA,IACtE;AACA,QAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,GAAG;AAClE,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,2BAA2B,CAAC;AAAA,IACxE;AACA,UAAM,eAAe,OAAO,cAAc,WAAW,UAAU,KAAK,IAAI;AACxE,QAAI,CAAC,cAAc;AACjB,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,uCAAuC,CAAC;AAAA,IACpF;AAEA,UAAM,kBAAkB,WAAW,KAAK;AACxC,QAAI,EAAE,mBAAmB,IAAI,OAAO,cAAc;AAChD,aAAO,KAAK,UAAU,EAAE,IAAI,OAAO,OAAO,uBAAuB,eAAe,GAAG,CAAC;AAAA,IACtF;AAEA,UAAM,eAAe,oBAAoB,MAAiC;AAC1E,UAAM,EAAE,qBAAAA,qBAAoB,IACzB,MAAM;AACT,UAAM,aAAaA,qBAAoB,iBAAiB,YAAY;AACpE,QAAI,CAAC,WAAW,IAAI;AAClB,aAAO,KAAK,UAAU;AAAA,QACpB,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,aAAa,WAAW;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,UAAM,UAAU,sBAAsB,iBAAiB,MAAiC;AACxF,UAAM,WAA2B;AAAA,MAC/B,IAAI,YAAQ,+BAAW,CAAC;AAAA,MACxB,MAAM;AAAA,MACN,YAAW,SAAI,cAAJ,YAAiB;AAAA,MAC5B,YAAY;AAAA,MACZ;AAAA,MACA,WAAW;AAAA,MACX;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS,KAAK,UAAU;AAAA,QACtB,IAAI;AAAA,QACJ,YAAY,SAAS;AAAA,QACrB;AAAA,QACA,kBAAkB;AAAA,QAClB,MAAM;AAAA,MACR,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF;AACF;AAgBA,IAAM,2BAAwC;AAAA,EAC5C,YAAY;AAAA,IACV,MAAM;AAAA,IACN,aACE;AAAA,IACF,aAAa;AAAA,MACX,MAAM;AAAA,MACN,YAAY;AAAA,QACV,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,QACA,SAAS;AAAA,UACP,MAAM;AAAA,UACN,aACE;AAAA,QACJ;AAAA,QACA,GAAG;AAAA,UACD,MAAM;AAAA,UACN,aAAa;AAAA,UACb,SAAS;AAAA,UACT,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,UAAU,CAAC,cAAc;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,MAAM,IAAI,OAAO,KAAK;AACpB,UAAM,EAAE,cAAc,SAAS,EAAE,IAAK,wBAAS,CAAC;AAKhD,QAAI,OAAO,iBAAiB,YAAY,CAAC,aAAa,KAAK,GAAG;AAC5D,aAAO,KAAK,UAAU,EAAE,OAAO,0DAA0D,CAAC;AAAA,IAC5F;AACA,UAAM,QAAQ,OAAO,MAAM,WAAW,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI;AAEjF,UAAM,aAQD,CAAC;AAGN,QAAI,OAAO,YAAY,YAAY,QAAQ,KAAK,GAAG;AACjD,YAAM,YAAY,QAAQ,KAAK;AAC/B,iBAAW,CAAC,gBAAgB,UAAU,KAAK,OAAO,QAAQ,IAAI,OAAO,WAAW,GAAG;AACjF,cAAM,WAAY,WAA0C;AAC5D,YAAI,CAAC,SAAU;AACf,cAAM,cAAc,mBAAmB,UAAU,SAAS;AAC1D,YAAI,CAAC,YAAa;AAClB,cAAM,QAAQ,MAAM,uBAAuB,gBAAgB,aAAa,GAAG;AAC3E,YAAI,OAAO;AACT,qBAAW,KAAK,iCAAK,QAAL,EAAY,WAAW,gBAAgB,EAAC;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAGA,UAAM,YAAY,aAAa,KAAK,EAAE,MAAM,GAAG,GAAI;AACnD,QAAI;AACF,YAAM,OAAO,MAAM,cAAc,WAAW;AAAA,QAC1C,GAAG;AAAA,QACH,QAAQ,IAAI;AAAA,MACd,CAAC;AACD,iBAAW,KAAK,MAAM;AACpB,YAAI,WAAW,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAG;AAC/C,mBAAW,KAAK,iCAAK,IAAL,EAAQ,WAAW,SAAS,EAAC;AAAA,MAC/C;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,KAAK,UAAU;AAAA,QACpB,OAAO,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAClF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,KAAK,UAAU;AAAA,QACpB,YAAY,CAAC;AAAA,QACb,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,UAAU;AAAA,MACpB,YAAY,WAAW,IAAI,CAAC,OAAO;AAAA,QACjC,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,YAAY,EAAE;AAAA,QACd,OAAO,EAAE;AAAA,QACT,OAAO,OAAO,EAAE,MAAM,QAAQ,CAAC,CAAC;AAAA,QAChC,SAAS,EAAE;AAAA,QACX,WAAW,EAAE;AAAA,MACf,EAAE;AAAA,IACJ,CAAC;AAAA,EACH;AACF;AAQO,SAAS,mBAAmB,UAAkB,KAA4C;AAE/F,MAAIC,QAAO;AACX,QAAM,WAAWA,MAAK,QAAQ,KAAK;AACnC,MAAI,aAAa,IAAI;AACnB,UAAM,QAAQA,MAAK,QAAQ,KAAK,WAAW,CAAC;AAC5C,IAAAA,QAAO,UAAU,KAAK,MAAMA,MAAK,MAAM,KAAK;AAAA,EAC9C;AACA,QAAM,WAAWA,MAAK,QAAQ,GAAG;AACjC,MAAI,aAAa,GAAI,CAAAA,QAAOA,MAAK,MAAM,GAAG,QAAQ;AAElD,QAAM,OAAO,CAAC,MAAc,EAAE,QAAQ,QAAQ,EAAE,KAAK;AACrD,QAAM,WAAW,KAAK,QAAQ,EAAE,MAAM,GAAG;AACzC,QAAM,WAAW,KAAKA,KAAI,EAAE,MAAM,GAAG;AACrC,MAAI,SAAS,WAAW,SAAS,OAAQ,QAAO;AAEhD,QAAM,MAA8B,CAAC;AACrC,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,KAAK,SAAS,CAAC;AACrB,UAAM,KAAK,SAAS,CAAC;AACrB,UAAM,IAAI,GAAG,MAAM,YAAY;AAC/B,QAAI,GAAG;AACL,UAAI,CAAC,GAAI,QAAO;AAChB,UAAI,EAAE,CAAC,CAAC,IAAI,mBAAmB,EAAE;AAAA,IACnC,WAAW,OAAO,IAAI;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,uBACb,gBACA,aACA,KACiH;AA9hBnH;AA+hBE,QAAM,EAAE,SAAAH,UAAS,iBAAAC,iBAAgB,IAC9B,MAAM;AACT,QAAM,EAAE,mBAAAG,oBAAmB,gBAAAC,iBAAgB,mBAAAC,mBAAkB,IAC1D,MAAM;AAET,QAAM,UAAU,MAAML,iBAAgB,cAAc,EAAE,MAAM,MAAM,CAAC,CAAa;AAChF,aAAW,KAAK,SAAS;AACvB,QAAI;AACJ,QAAI;AACF,gBAAW,MAAMD,SAAQ,CAAC;AAAA,IAC5B,SAAQ;AACN;AAAA,IACF;AACA,QAAI,WAAW;AACf,eAAW,CAAC,KAAK,QAAQ,KAAK,OAAO,QAAQ,WAAW,GAAG;AACzD,YAAM,UAAS,aAAQ,WAAR,mBAAiB;AAChC,UAAI,OAAO,WAAW,YAAY,WAAW,UAAU;AAErD,YAAI,QAAQ,MAAM;AAChB,gBAAM,QAAO,OACV,MAAM,GAAG,EACT,IAAI,MAFM,mBAGT,QAAQ,WAAW;AACvB,cAAI,SAAS,SAAU;AAAA,QACzB;AACA,mBAAW;AACX;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,SAAU;AACf,WAAO;AAAA,MACL,IAAIK,gBAAe,IAAI,QAAQ,GAAG,OAAO;AAAA,MACzC,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,OAAOD,mBAAkB,IAAI,QAAQ,GAAG,OAAO;AAAA,MAC/C,SAASE,mBAAkB,IAAI,QAAQ,GAAG,OAAO;AAAA,IACnD;AAAA,EACF;AACA,SAAO;AACT;AAEO,IAAM,kBAAiC;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,iBAAgC,CAAC,iBAAiB,mBAAmB;AAE3E,IAAM,YAA2B,CAAC,GAAG,iBAAiB,GAAG,cAAc;AAEvE,SAAS,eAAe,MAAuC;AACpE,SAAO,UAAU,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,IAAI;AACzD;AAEO,SAAS,qBAAuC;AACrD,SAAO,UAAU,IAAI,CAAC,MAAM,EAAE,UAAU;AAC1C;;;AE7kBA;AACA;AAmCA,SAAuB,QAAQ,OAAgD;AAAA;AAjD/E;AAkDE,UAAM,SAAQ,WAAM,UAAN,YAAe,mBAAmB;AAChD,UAAM,YAAW,WAAM,aAAN,YAAkB;AAInC,UAAM,WAAgC,CAAC,GAAG,MAAM,QAAQ;AACxD,QAAI,mBAAmB;AACvB,QAAI,oBAAoB;AAExB,aAAS,OAAO,GAAG,OAAO,UAAU,QAAQ;AAC1C,YAAM,SAAS,MAAM,SAAS,WAAW;AAAA,QACvC;AAAA,QACA;AAAA,QACA,cAAc,MAAM;AAAA,QACpB,iBAAiB,MAAM,YAAY;AAAA,MACrC,CAAC;AAED,YAAM,kBAA4C,CAAC;AACnD,UAAI,cAAc;AAClB,YAAM,mBAAmE,CAAC;AAC1E,UAAI,aAAiF;AACrF,UAAI,QAAQ,EAAE,aAAa,GAAG,cAAc,GAAG,mBAAmB,EAAE;AACpE,UAAI,UAAU;AAEd;AAAA,mCAAuB,SAAvB,uFAA+B;AAApB,gBAAM,KAAjB;AACE,cAAI,GAAG,SAAS,SAAS;AACvB,kBAAM,EAAE,MAAM,SAAS,SAAS,GAAG,QAAQ;AAC3C,sBAAU;AACV;AAAA,UACF;AACA,cAAI,GAAG,SAAS,cAAc;AAC5B,2BAAe,GAAG;AAClB,kBAAM;AACN;AAAA,UACF;AACA,cAAI,GAAG,SAAS,kBAAkB;AAChC,gBAAI,aAAa;AACf,8BAAgB,KAAK,EAAE,MAAM,QAAQ,MAAM,YAAY,CAAC;AACxD,4BAAc;AAAA,YAChB;AACA,kBAAM;AACN;AAAA,UACF;AACA,cAAI,GAAG,SAAS,wBAAwB;AACtC,kBAAM;AACN;AAAA,UACF;AACA,cAAI,GAAG,SAAS,qBAAqB;AACnC,4BAAgB,KAAK,EAAE,MAAM,YAAY,IAAI,GAAG,IAAI,MAAM,GAAG,MAAM,OAAO,GAAG,MAAM,CAAC;AACpF,6BAAiB,KAAK,EAAE,IAAI,GAAG,IAAI,MAAM,GAAG,MAAM,OAAO,GAAG,MAAM,CAAC;AACnE,kBAAM;AACN;AAAA,UACF;AACA,cAAI,GAAG,SAAS,gBAAgB;AAC9B,gBAAI,aAAa;AACf,8BAAgB,KAAK,EAAE,MAAM,QAAQ,MAAM,YAAY,CAAC;AACxD,4BAAc;AAAA,YAChB;AACA,yBAAa,GAAG;AAChB,oBAAQ;AAAA,cACN,aAAa,GAAG,MAAM;AAAA,cACtB,cAAc,GAAG,MAAM;AAAA,cACvB,oBAAmB,QAAG,MAAM,sBAAT,YAA8B;AAAA,YACnD;AAAA,UACF;AAAA,QACF;AAAA,eAzCA,MA1EJ;AA0EI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2CA,UAAI,QAAS;AAGb,eAAS,KAAK,EAAE,MAAM,aAAa,SAAS,gBAAgB,CAAC;AAG7D,0BAAoB,MAAM;AAC1B,2BAAqB,MAAM;AAC3B,YAAM,YAAY;AAAA,QAChB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AACA,YAAM,aAAa,WAAW,MAAM,aAAa;AAAA,QAC/C,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA,QACd,aAAa,MAAM;AAAA,MACrB,CAAC;AACD,YAAM;AAAA,QACJ,MAAM;AAAA,QACN,aAAa,MAAM;AAAA,QACnB,cAAc,MAAM;AAAA,QACpB,mBAAmB,MAAM;AAAA,QACzB,cAAc;AAAA,QACd,cAAc,WAAW;AAAA,MAC3B;AAEA,YAAM,EAAE,MAAM,aAAa,WAAW;AAEtC,UAAI,mBAAmB,MAAM,YAAY,gBAAgB;AACvD,cAAM,EAAE,MAAM,mBAAmB,QAAQ,eAAe;AACxD;AAAA,MACF;AACA,UAAI,oBAAoB,MAAM,YAAY,iBAAiB;AACzD,cAAM,EAAE,MAAM,mBAAmB,QAAQ,gBAAgB;AACzD;AAAA,MACF;AAGA,UAAI,iBAAiB,WAAW,GAAG;AACjC,cAAM,EAAE,MAAM,OAAO;AACrB;AAAA,MACF;AAKA,UAAI,oBAAoB;AACxB,YAAM,cAAc,MAAM,YAAY;AACtC,iBAAW,QAAQ,kBAAkB;AACnC,cAAM,UAAU,eAAe,KAAK,IAAI;AACxC,YAAI;AACJ,YAAI,UAAU;AACd,YAAI;AACJ,YAAI,CAAC,SAAS;AACZ,mBAAS,KAAK,UAAU,EAAE,OAAO,iBAAiB,KAAK,IAAI,GAAG,CAAC;AAC/D,oBAAU;AAAA,QACZ,OAAO;AACL,cAAI;AACF,kBAAM,MAAM,kBAAM,QAAQ,IAAI,KAAK,OAAO;AAAA,cACxC,QAAQ,MAAM;AAAA,cACd,QAAQ,MAAM;AAAA,cACd,WAAW,KAAK;AAAA,YAClB,CAAC;AACD,gBAAI,OAAO,QAAQ,UAAU;AAC3B,uBAAS;AAAA,YACX,OAAO;AACL,uBAAS,IAAI;AACb,yBAAW,IAAI;AAAA,YACjB;AAAA,UACF,SAAS,KAAK;AACZ,qBAAS,KAAK,UAAU,EAAE,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AACnF,sBAAU;AAAA,UACZ;AAAA,QACF;AAEA,YAAI,UAAU;AACZ,cAAI,qBAAqB,aAAa;AAGpC,qBAAS,KAAK,UAAU;AAAA,cACtB,IAAI;AAAA,cACJ,OAAO,kCAAkC,WAAW;AAAA,YACtD,CAAC;AACD,sBAAU;AAAA,UACZ,OAAO;AACL,iCAAqB;AAErB,kBAAM,UAAoB,iCAAK,WAAL,EAAe,WAAW,KAAK,GAAG;AAC5D,kBAAM,EAAE,MAAM,YAAY,UAAU,QAAQ;AAAA,UAC9C;AAAA,QACF;AAEA,cAAM,EAAE,MAAM,eAAe,WAAW,KAAK,IAAI,MAAM,KAAK,MAAM,QAAQ,QAAQ;AAClF,iBAAS,KAAK,EAAE,MAAM,QAAQ,WAAW,KAAK,IAAI,SAAS,QAAQ,QAAQ,CAAC;AAAA,MAC9E;AAAA,IAGF;AAEA,UAAM,EAAE,MAAM,mBAAmB,QAAQ,YAAY;AAAA,EACvD;AAAA;;;AC/KO,SAAS,mBAAmB,UAAkB,WAAmC;AACtF,QAAM,UAAU,SAAS,YAAY;AACrC,QAAM,MAAM,aAAa,IAAI,YAAY;AACzC,MAAI,OAAO,qBAAqB,QAAQ,SAAS,MAAM,EAAG,QAAO;AACjE,MAAI,OAAO,6EAA6E,QAAQ,SAAS,OAAO,GAAG;AACjH,WAAO;AAAA,EACT;AACA,MAAI,GAAG,WAAW,OAAO,KAAK,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,KAAK,KAAK,QAAQ,SAAS,WAAW,GAAG;AAClH,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAGO,SAAS,oBAAoB,OAAe,QAAgE;AACjH,MAAI,QAAQ,OAAO,oBAAoB;AACrC,WAAO,oBAAoB,YAAY,OAAO,kBAAkB,CAAC,wBAAwB,YAAY,KAAK,CAAC;AAAA,EAC7G;AACA,SAAO;AACT;AAGO,SAAS,qBAAqB,OAAe,QAAmE;AACrH,MAAI,QAAQ,OAAO,uBAAuB;AACxC,WAAO,wCAAmC,OAAO,qBAAqB,kBAAkB,KAAK;AAAA,EAC/F;AACA,SAAO;AACT;AAEA,SAAS,YAAY,GAAmB;AACtC,MAAI,KAAK,OAAO,KAAM,QAAO,IAAI,KAAK,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC9D,MAAI,KAAK,KAAM,QAAO,IAAI,IAAI,MAAM,QAAQ,CAAC,CAAC;AAC9C,SAAO,GAAG,CAAC;AACb;AAGO,SAAS,mBAAmB,UAAkB,MAAsB;AACzE,SAAO,uBAAuB,QAAQ;AAAA;AAAA,EAAQ,IAAI;AACpD;AAWA,eAAsB,qBACpB,aACA,SAMsC;AArGxC;AAsGE,QAAM,SAAmC,CAAC;AAC1C,QAAM,cAAsC,CAAC;AAE7C,QAAM,eAAc,aAAQ,oBAAR,YAA2B;AAC/C,QAAM,cAAa,aAAQ,mBAAR,YAA0B;AAE7C,aAAW,OAAO,aAAa;AAC7B,UAAM,OAAO,mBAAmB,IAAI,UAAU,IAAI,SAAS;AAE3D,QAAI,SAAS,eAAe;AAC1B,kBAAY,KAAK;AAAA,QACf,UAAU,IAAI;AAAA,QACd,QAAQ;AAAA,QACR,QAAQ,0BAA0B,IAAI,aAAa,SAAS;AAAA,MAC9D,CAAC;AACD;AAAA,IACF;AAEA,QAAI,SAAS,QAAQ;AACnB,YAAM,OAAO,cAAc,IAAI,KAAK;AACpC,aAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,mBAAmB,IAAI,UAAU,IAAI,EAAE,CAAC;AAC1E,kBAAY,KAAK,EAAE,UAAU,IAAI,UAAU,QAAQ,MAAM,MAAM,OAAO,IAAI,MAAM,OAAO,CAAC;AACxF;AAAA,IACF;AAEA,QAAI,SAAS,QAAQ;AACnB,UAAI;AACF,cAAM,OAAO,MAAM,YAAY,IAAI,KAAK;AACxC,eAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,mBAAmB,IAAI,UAAU,IAAI,EAAE,CAAC;AAC1E,oBAAY,KAAK,EAAE,UAAU,IAAI,UAAU,QAAQ,MAAM,MAAM,OAAO,IAAI,MAAM,OAAO,CAAC;AAAA,MAC1F,SAAS,KAAK;AACZ,oBAAY,KAAK;AAAA,UACf,UAAU,IAAI;AAAA,UACd,QAAQ;AAAA,UACR,QAAQ,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACrF,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAGA,QAAI,QAAQ,mBAAmB;AAC7B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,QAAQ,cAAc,IAAI,KAAK;AAAA,QAC/B,WAAW;AAAA,QACX,UAAU,IAAI;AAAA,MAChB,CAAC;AACD,kBAAY,KAAK,EAAE,UAAU,IAAI,UAAU,QAAQ,MAAM,MAAM,OAAO,IAAI,MAAM,OAAO,CAAC;AACxF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,OAAO,MAAM,WAAW,IAAI,KAAK;AACvC,aAAO,KAAK,EAAE,MAAM,QAAQ,MAAM,mBAAmB,IAAI,UAAU,IAAI,EAAE,CAAC;AAC1E,kBAAY,KAAK,EAAE,UAAU,IAAI,UAAU,QAAQ,MAAM,MAAM,OAAO,IAAI,MAAM,OAAO,CAAC;AAAA,IAC1F,SAAS,KAAK;AACZ,kBAAY,KAAK;AAAA,QACf,UAAU,IAAI;AAAA,QACd,QAAQ;AAAA,QACR,QAAQ,+BAA+B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACzF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ,YAAY;AAC/B;AAEA,SAAS,cAAc,OAA2B;AAChD,SAAO,IAAI,YAAY,SAAS,EAAE,OAAO,MAAM,CAAC,EAAE,OAAO,KAAK;AAChE;AAEA,SAAS,cAAc,OAA2B;AAGhD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,OAAO,KAAK,KAAK,EAAE,SAAS,QAAQ;AAAA,EAC7C;AAGA,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,IAAK,WAAU,OAAO,aAAa,MAAM,CAAC,CAAC;AAC7E,SAAO,KAAK,MAAM;AACpB;AAEA,eAAe,uBAAuB,OAAoC;AACxE,MAAI;AACJ,MAAI;AACF,cAAW,MAAM,OAAO,SAAS;AAAA,EACnC,SAAQ;AACN,UAAM,IAAI,MAAM,+EAA+E;AAAA,EACjG;AAGA,QAAM,SAAS,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AACjE,QAAM,SAAS,MAAM,QAAQ,eAAe,EAAE,OAAO,CAAC;AACtD,SAAO,OAAO,SAAS;AACzB;AAEA,eAAe,sBAAsB,OAAoC;AAcvE,MAAI;AACJ,MAAI;AAIF,YAAS,MAAM,OAAO,iCAAiC;AAAA,EACzD,SAAQ;AACN,QAAI;AACF,cAAS,MAAM,OAAO,YAAY;AAAA,IACpC,SAAQC,IAAA;AACN,YAAM,IAAI,MAAM,qFAAqF;AAAA,IACvG;AAAA,EACF;AAGA,MAAI,MAAM,oBAAqB,OAAM,oBAAoB,YAAY;AAGrE,QAAM,OAAO,IAAI,WAAW,MAAM,MAAM;AACxC,OAAK,IAAI,KAAK;AACd,QAAM,MAAM,MAAM,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE;AAE9C,QAAM,QAAkB,CAAC;AACzB,WAAS,IAAI,GAAG,KAAK,IAAI,UAAU,KAAK;AACtC,UAAM,OAAO,MAAM,IAAI,QAAQ,CAAC;AAChC,UAAM,UAAU,MAAM,KAAK,eAAe;AAC1C,UAAM,WAAW,QAAQ,MAAM,IAAI,CAAC,OAAI;AAjP5C;AAiP+C,sBAAG,QAAH,YAAU;AAAA,KAAE,EAAE,KAAK,GAAG;AACjE,UAAM,KAAK,SAAS,KAAK,CAAC;AAAA,EAC5B;AACA,MAAI,OAAO,IAAI,YAAY,YAAY;AACrC,QAAI;AACF,YAAM,IAAI,QAAQ;AAAA,IACpB,SAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO,MAAM,KAAK,MAAM;AAC1B;;;AC3OA,kBAAiC;AACjC,IAAAC,kBAAwB;AAExB;AACAC;AAUA;AACA;;;ACvBO,SAAS,gBAAgB,UAAuC;AATvE;AAUE,MAAI,SAAS,SAAS,aAAa;AAIjC,UAAM,EAAE,uBAAAC,uBAAsB,IAAI;AAClC,WAAO,IAAIA,uBAAsB,QAAQ;AAAA,EAC3C;AACA,MAAI,SAAS,SAAS,YAAY,SAAS,SAAS,SAAS;AAC3D,UAAM,EAAE,oBAAAC,oBAAmB,IAAI;AAC/B,WAAO,IAAIA,oBAAmB,QAAQ;AAAA,EACxC;AACA,QAAM,IAAI,MAAM,4BAA4B,cAA+B,SAA/B,YAAuC,WAAW,EAAE;AAClG;;;ADeA,IAAMC,4BAA2B;AAOjC,SAAS,WAAqB;AAC5B,SAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAC3C;AAEA,SAAS,eAAyB;AAChC,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,eAAe,CAAC,GAAG;AAAA,IAC7D,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,EAChD,CAAC;AACH;AAEA,SAAS,WAAW,SAA2B;AAC7C,SAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,QAAQ,CAAC,GAAG;AAAA,IACtD,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,EAChD,CAAC;AACH;AAQA,eAAsB,UAAU,SAAqC;AApErE;AAqEE,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,eAAe,CAAC,eAAe,WAAW,EAAG,QAAO,SAAS;AAElE,QAAM,UAAU,UAAM,8BAAiB,WAAW;AAClD,MAAI,CAAC,QAAS,QAAO,aAAa;AAIlC,QAAM,eAAc,aAAQ,QAAQ,IAAI,cAAc,MAAlC,YAAuC;AAC3D,MAAI;AACJ,MAAI,iBAAkC,CAAC;AACvC,MAAI,YAAY,SAAS,qBAAqB,GAAG;AAC/C,QAAI;AACJ,QAAI;AACF,aAAO,MAAM,QAAQ,SAAS;AAAA,IAChC,SAAQ;AACN,aAAO,WAAW,qCAAqC;AAAA,IACzD;AACA,UAAM,gBAAgB,KAAK,IAAI,UAAU;AACzC,UAAM,iBAAiB,KAAK,IAAI,gBAAgB;AAChD,QAAI;AACF,aAAO;AAAA,QACL,UAAU,OAAO,kBAAkB,WAAY,KAAK,MAAM,aAAa,IAA4B,CAAC;AAAA,QACpG,gBACE,OAAO,mBAAmB,WAAY,KAAK,MAAM,cAAc,IAAwB;AAAA,MAC3F;AAAA,IACF,SAAQ;AACN,aAAO,WAAW,qEAAqE;AAAA,IACzF;AACA,qBAAiB,MAAM,uBAAuB,IAAI;AAAA,EACpD,OAAO;AACL,QAAI;AACF,aAAQ,MAAM,QAAQ,KAAK;AAAA,IAC7B,SAAQ;AACN,aAAO,WAAW,oBAAoB;AAAA,IACxC;AAAA,EACF;AACA,QAAM,WAAW,MAAM,QAAQ,KAAK,QAAQ,IAAI,KAAK,WAAW,CAAC;AACjE,MAAI,SAAS,WAAW,EAAG,QAAO,WAAW,uCAAuC;AAEpF,QAAM,aAAa,qBAAqB,eAAe,QAAQ,WAAW;AAC1E,MAAI,WAAY,QAAO,WAAW,UAAU;AAC5C,aAAW,KAAK,gBAAgB;AAC9B,UAAM,YAAY,oBAAoB,EAAE,MAAM,QAAQ,WAAW;AACjE,QAAI,UAAW,QAAO,WAAW,GAAG,EAAE,QAAQ,KAAK,SAAS,EAAE;AAAA,EAChE;AAEA,QAAM,SAAS,UAAU;AACzB,QAAM,WAAU,gBAAM,yBAAQ,GAAG,IAAIA,yBAAwB,MAA7C,mBAAgD,UAAS;AAEzE,MAAI;AACJ,MAAI;AACF,eAAW,gBAAgB,YAAY,QAAQ;AAAA,EACjD,SAAS,KAAK;AACZ,WAAO,WAAW,eAAe,QAAQ,IAAI,UAAU,qCAAqC;AAAA,EAC9F;AAKA,MAAI,wBAAgD,CAAC;AACrD,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,aAAa,MAAM,qBAAqB,gBAAgB;AAAA,MAC5D,mBAAmB,SAAS;AAAA,IAC9B,CAAC;AACD,4BAAwB,WAAW;AACnC,QAAI,WAAW,OAAO,SAAS,GAAG;AAChC,4BAAsB,UAAU,WAAW,MAAM;AAAA,IACnD;AAAA,EACF;AAEA,QAAM,eAAe,kBAAkB;AAAA,IACrC;AAAA,IACA,gBAAgB,KAAK;AAAA,EACvB,CAAC;AAED,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,SAAS,IAAI,eAA2B;AAAA,IAC5C,MAAM,MAAM,YAAY;AACtB,UAAI,SAAS;AACb,YAAM,cAAc,CAAC,UAAsB;AACzC,YAAI,OAAQ;AACZ,YAAI;AACF,qBAAW,QAAQ,KAAK;AAAA,QAC1B,SAAQ;AAEN,mBAAS;AAAA,QACX;AAAA,MACF;AACA,YAAM,OAAO,CAAC,UAAqB;AACjC,oBAAY,QAAQ,OAAO,SAAS,KAAK,UAAU,KAAK,CAAC;AAAA;AAAA,CAAM,CAAC;AAAA,MAClE;AAIA,YAAM,UAAU,MAAM;AACpB,iBAAS;AACT,YAAI;AACF,qBAAW,MAAM;AAAA,QACnB,SAAQ;AAAA,QAER;AAAA,MACF;AACA,cAAQ,OAAO,iBAAiB,SAAS,OAAO;AAGhD;AAAA,QACE,QAAQ;AAAA,UACN;AAAA,QAAsB,KAAK,UAAU;AAAA,YACnC,UAAU,SAAS;AAAA,YACnB,OAAO,SAAS;AAAA,UAClB,CAAC,CAAC;AAAA;AAAA;AAAA,QACJ;AAAA,MACF;AAIA,UAAI,sBAAsB,SAAS,GAAG;AACpC;AAAA,UACE,QAAQ,OAAO;AAAA,QAA6B,KAAK,UAAU,EAAE,aAAa,sBAAsB,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,QAC1G;AAAA,MACF;AAEA,UAAI;AACF;AAAA,qCAAuB,QAAQ;AAAA,YAC7B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF,CAAC,IAPD,0EAOI;AAPO,kBAAM,KAAjB;AAQE,gBAAI,QAAQ,OAAO,QAAS;AAC5B,iBAAK,EAAE;AACP,gBAAI,GAAG,SAAS,UAAU,GAAG,SAAS,WAAW,GAAG,SAAS,kBAAmB;AAAA,UAClF;AAAA,iBAXA,MAjMR;AAiMQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYF,SAAS,KAAK;AACZ,aAAK,EAAE,MAAM,SAAS,SAAS,eAAe,QAAQ,IAAI,UAAU,sBAAsB,CAAC;AAAA,MAC7F,UAAE;AACA,gBAAQ,OAAO,oBAAoB,SAAS,OAAO;AACnD,YAAI,CAAC,QAAQ;AACX,cAAI;AACF,uBAAW,MAAM;AAAA,UACnB,SAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,IAAI,SAAS,QAAQ;AAAA,IAC1B,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;AAOA,eAAsB,kBAAqC;AACzD,QAAM,cAAc,eAAe;AACnC,MAAI,CAAC,eAAe,CAAC,eAAe,WAAW,EAAG,QAAO,SAAS;AAElE,QAAM,UAAU,UAAM,8BAAiB,WAAW;AAClD,MAAI,CAAC,QAAS,QAAO,aAAa;AAElC,QAAM,WAAW,YAAY;AAC7B,SAAO,IAAI;AAAA,IACT,KAAK,UAAU;AAAA,MACb,SAAS;AAAA,MACT,UAAU,SAAS;AAAA,MACnB,OAAO,SAAS;AAAA,IAClB,CAAC;AAAA,IACD,EAAE,QAAQ,KAAK,SAAS,EAAE,gBAAgB,mBAAmB,EAAE;AAAA,EACjE;AACF;AAMA,eAAe,uBAAuB,MAA0C;AAC9E,QAAM,MAAuB,CAAC;AAG9B,QAAM,aAAmC,CAAC;AAC1C,aAAW,KAAK,KAAK,OAAO,OAAO,EAAG,YAAW,KAAK,CAAC;AACvD,aAAW,CAAC,KAAK,KAAK,KAAK,KAAK,QAAQ,GAAG;AACzC,QAAI,QAAQ,WAAW,QAAQ,cAAc,QAAQ,iBAAkB;AACvE,QAAI,IAAI,WAAW,QAAQ,EAAG,YAAW,KAAK,KAAK;AAAA,EACrD;AACA,aAAW,KAAK,YAAY;AAC1B,QAAI,OAAO,MAAM,SAAU;AAC3B,UAAM,OAAO;AACb,UAAM,KAAK,MAAM,KAAK,YAAY;AAClC,QAAI,KAAK;AAAA,MACP,UAAU,KAAK,QAAQ;AAAA,MACvB,WAAW,KAAK,QAAQ;AAAA,MACxB,OAAO,IAAI,WAAW,EAAE;AAAA,IAC1B,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAOA,SAAS,sBAAsB,UAA+B,QAAwC;AACpG,QAAM,UAAU,SAAS,SAAS;AAClC,QAAM,OAAO,SAAS,OAAO;AAC7B,MAAI,QAAQ,KAAK,SAAS,QAAQ;AAChC,UAAM,WACJ,OAAO,KAAK,YAAY,WAAW,CAAC,EAAE,MAAM,QAAQ,MAAM,KAAK,QAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,OAAO;AAC9F,aAAS,OAAO,IAAI,EAAE,MAAM,QAAQ,SAAS,CAAC,GAAG,UAAU,GAAG,MAAM,EAAE;AACtE;AAAA,EACF;AACA,WAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,OAAO,CAAC;AACjD;","names":["key","GithubProvider","init_configStore","init_configStore","import_octokit","state","getGitHubFile","path","fsPromises","normalizeContentPath","saveGitHubFile","path","fsPromises","import_fs","import_path","path","fsPromises","import_path","init_configStore","d","slugify","init_configStore","import_zod","init_configStore","init_configStore","collectionFromPath","init_configStore","cached","collectionFromPath","path","init_configStore","getErrorMessage","init_configStore","normalizeContentPath","path","fsPromises","import_promises","import_path","init_configStore","listed","dir","mdPaths","built","getErrorMessage","blocks","loadSdk","text","import_fs","import_path","init_configStore","getGitHubFile","path","fsPromises","getContentFiles","saveFile","newFile","getFile","existing","mergedFields","payload","getFile","getContentFiles","validateEntryFields","path","resolveEntryTitle","resolveEntryId","buildEntryExcerpt","e","import_headers","init_configStore","AnthropicChatProvider","OpenAIChatProvider","CMS_ACTIVE_BRANCH_COOKIE"]}
|
|
1
|
+
{"version":3,"sources":["../../agent/index.ts"],"sourcesContent":["export type {\n AgentConfig,\n AgentPricing,\n AgentProvider,\n AnthropicProvider,\n OpenAIProvider,\n LocalProvider,\n} from './types';\nexport { DEFAULT_AGENT_CONFIG, defineAgentConfig } from './defaults';\nexport { estimateCostUSD, getProviderPricing } from './pricing';\nexport { getAgentStatus, hasProviderKey, isAgentEnabled, providerApiKeyEnv, type AgentStatus } from './featureFlag';\nexport { getUsage, recordTurn, resetUsage, isBudgetExceeded, type AgentUsage } from './usage';\nexport { setAgentConfig, getAgentConfig } from './configStore';\nexport { entryToEmbeddingText } from './embedText';\nexport {\n type Embedder,\n LocalTransformersEmbedder,\n getDefaultEmbedder,\n setDefaultEmbedder,\n DEFAULT_MODEL_ID,\n DEFAULT_DIM,\n} from './embedder';\nexport {\n type EmbeddingsRecord,\n type EmbeddingsStore,\n EMBEDDINGS_STORE_PATH,\n emptyStore,\n hashEmbeddingText,\n loadEmbeddings,\n serializeStore,\n removeEntryFromStore,\n upsertEntryInStore,\n embedEntry,\n embedEntryFromMemory,\n embedAll,\n} from './embeddings';\nexport { encodeFloat32, decodeFloat32, cosineSimilarity } from './storeFormat';\nexport { syncEmbeddingsAfterUpsert, syncEmbeddingsAfterRemove } from './embeddingsHook';\nexport { searchContent, clearSearchCache, type SearchHit, type SearchOptions } from './search';\nexport { buildSystemPrompt, type SystemPromptInput, type StyleExemplar } from './systemPrompt';\nexport {\n READ_ONLY_TOOLS,\n PROPOSAL_TOOLS,\n ALL_TOOLS,\n getToolHandler,\n getToolDefinitions,\n acceptProposal,\n type ToolHandler,\n type ToolContext,\n type ToolRunResult,\n} from './tools';\nexport {\n type Proposal,\n type EditProposal,\n type CreateProposal,\n type AcceptResult,\n describeEditSummary,\n describeCreateSummary,\n fieldsToFormStrings,\n resolveEntryPath,\n} from './proposals';\nexport { runChat, type ChatEvent, type RunChatInput } from './chat';\nexport {\n classifyAttachment,\n checkAttachmentSize,\n checkAttachmentCount,\n normalizeAttachments,\n wrapAttachmentText,\n type AttachmentKind,\n type RawAttachment,\n type NormalizedAttachmentsResult,\n type AttachmentDiagnostic,\n} from './attachments';\nexport { chatRoute, chatStatusRoute } from './chatApi';\nexport { getChatProvider } from './providers';\nexport type {\n ChatProvider,\n ChatStreamInput,\n NormalizedMessage,\n NormalizedContentBlock,\n NormalizedTool,\n ProviderEvent,\n} from './providers/types';\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,sBAAwD;AACxD,qBAAoD;AACpD,yBAAoG;AACpG,mBAAoF;AACpF,yBAA+C;AAC/C,uBAAqC;AACrC,sBAOO;AACP,wBAaO;AACP,yBAA+D;AAC/D,4BAAqE;AACrE,oBAAoF;AACpF,0BAA8E;AAC9E,mBAUO;AACP,uBASO;AACP,kBAA2D;AAC3D,yBAUO;AACP,qBAA2C;AAC3C,uBAAgC;","names":[]}
|