@burdenoff/fluidgrids-fe-sdk 2026.1102.1 → 2026.1102.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/{ExecutionDetailPage-DSLBVHNF.js → ExecutionDetailPage-XHII23QR.js} +11 -11
  2. package/dist/{ExecutionsListPage-4JAHYMBY.js → ExecutionsListPage-GTCSYSC6.js} +7 -7
  3. package/dist/{WorkflowBuilder-KY7WPG6S.js → WorkflowBuilder-ZIXEU7DQ.js} +12 -11
  4. package/dist/{WorkflowsList-R54WQMBJ.js → WorkflowsList-NYSQEZWU.js} +7 -7
  5. package/dist/{agentTools-4WNGUHVC.js → agentTools-PA62A53S.js} +4 -4
  6. package/dist/{chunk-UFT457ZJ.js → chunk-23LYGZ27.js} +1 -1
  7. package/dist/{chunk-MOMFAIGR.js → chunk-37BKVPO7.js} +12 -40
  8. package/dist/{chunk-WNZKFW7A.js → chunk-3Y4266JL.js} +3 -3
  9. package/dist/{chunk-K4UJ27ED.js → chunk-4FDMLKLL.js} +2 -2
  10. package/dist/{chunk-KD4O5ODO.js → chunk-6VODFT2Q.js} +5 -5
  11. package/dist/{chunk-VZ3KQIQE.js → chunk-7JLLH4YE.js} +4 -4
  12. package/dist/{chunk-IG5BMZXN.js → chunk-7SY2SL5Y.js} +6 -6
  13. package/dist/{chunk-WEE4WVMB.js → chunk-A4XNCGWT.js} +2 -2
  14. package/dist/{chunk-BTQBEF4H.js → chunk-A7QPQ6MO.js} +1 -1
  15. package/dist/{chunk-6OCQ3M5C.js → chunk-B2DNUVKW.js} +4 -4
  16. package/dist/{chunk-SRQ2RPRL.js → chunk-BDBSRN2O.js} +4 -4
  17. package/dist/{chunk-FQ4IYSLN.js → chunk-CXNJKM4D.js} +1 -1
  18. package/dist/{chunk-OOVWMJBF.js → chunk-DLKGWGRN.js} +1 -1
  19. package/dist/{chunk-KQ3SBSDS.js → chunk-EFOJEQDS.js} +2 -2
  20. package/dist/{chunk-QMDG54ST.js → chunk-JCHE4V55.js} +1 -1
  21. package/dist/{chunk-ZC7XPBZN.js → chunk-JTQFBZTV.js} +2 -1
  22. package/dist/{chunk-5YNWH64U.js → chunk-MY752OLT.js} +67 -195
  23. package/dist/{chunk-Z6UUJWJ6.js → chunk-OR7KZZ2D.js} +1 -1
  24. package/dist/{chunk-ZLOASEDO.js → chunk-OUYEMZT6.js} +1 -1
  25. package/dist/{chunk-M3XHFK3Y.js → chunk-OZCJHPMH.js} +3 -3
  26. package/dist/{chunk-LENZTZNB.js → chunk-P6IRD5SA.js} +10 -10
  27. package/dist/chunk-PBCBDSVA.js +1480 -0
  28. package/dist/{chunk-YBL4H324.js → chunk-PC3CICOW.js} +1 -1
  29. package/dist/{chunk-KI37QYJ7.js → chunk-QAXP5HON.js} +2 -2
  30. package/dist/{chunk-LN5LXMNA.js → chunk-TJ2PFY7I.js} +2 -2
  31. package/dist/{chunk-ENULBWW2.js → chunk-UETHT3KG.js} +2 -2
  32. package/dist/{chunk-DUE25AIG.js → chunk-VFLHURFM.js} +1 -1
  33. package/dist/{chunk-WOSFZWOQ.js → chunk-W74MXVFX.js} +1 -1
  34. package/dist/{chunk-QK76M4E5.js → chunk-XNVYPEBO.js} +129 -21
  35. package/dist/{chunk-3VEJGG5F.js → chunk-YVOHCC7J.js} +4 -4
  36. package/dist/{chunk-GAVK2EWX.js → chunk-ZTJX5ONT.js} +4 -4
  37. package/dist/executions.js +12 -12
  38. package/dist/history.js +5 -4
  39. package/dist/index.d.ts +226 -1
  40. package/dist/index.js +2625 -48
  41. package/dist/{node-detail-view-6TN4ZLIC.js → node-detail-view-KET5DNEH.js} +8 -8
  42. package/dist/nodes.js +2 -2
  43. package/dist/observability.js +5 -5
  44. package/dist/{quick-config-panel-GNAQCCFQ.js → quick-config-panel-L6CTZQUG.js} +5 -5
  45. package/dist/settings.js +6 -6
  46. package/dist/templates.js +11 -10
  47. package/dist/workflow-builder.js +13 -12
  48. package/dist/workflows-list.js +7 -7
  49. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,56 +1,57 @@
1
1
  export { Label } from './chunk-VTQVPNUQ.js';
2
- import { useRunners, useRunnerActions, RunnerStatusPill, runnerInstallCommand } from './chunk-Z6UUJWJ6.js';
3
- export { RUNNER_INSTALL_SCRIPT_URL, RunOnSection, RunnerStatusPill, runnerInstallCommand, useRunnerActions, useRunners } from './chunk-Z6UUJWJ6.js';
2
+ import { useRunners, useRunnerActions, RunnerStatusPill, runnerInstallCommand } from './chunk-OR7KZZ2D.js';
3
+ export { RUNNER_INSTALL_SCRIPT_URL, RunOnSection, RunnerStatusPill, runnerInstallCommand, useRunnerActions, useRunners } from './chunk-OR7KZZ2D.js';
4
4
  export { Popover, PopoverContent, PopoverTrigger } from './chunk-GTEBQQ7J.js';
5
- export { WorkflowBuilder, WorkflowBuilderCore, WorkflowSearchRedirect } from './chunk-M3XHFK3Y.js';
6
- export { GuidedTourStarter, WorkflowBuilder as WorkflowBuilderPage } from './chunk-MOMFAIGR.js';
7
- export { FirstWorkflowChecklist, FirstWorkflowChecklistView, WorkflowsList, useCreateWorkflowFirst } from './chunk-IG5BMZXN.js';
8
- import { CreateWorkflowRefusalDialog } from './chunk-QMDG54ST.js';
9
- export { CreateWorkflowRefusalDialog, GUIDED_FIRST_WORKFLOW_NAV, GUIDED_FIRST_WORKFLOW_STATE, GUIDED_TOUR_STATE, firstWorkflowProgress, isGuidedTourIntent, pickGuidedTour } from './chunk-QMDG54ST.js';
5
+ export { WorkflowBuilder, WorkflowBuilderCore, WorkflowSearchRedirect } from './chunk-OZCJHPMH.js';
6
+ export { GuidedTourStarter, WorkflowBuilder as WorkflowBuilderPage } from './chunk-37BKVPO7.js';
7
+ export { FirstWorkflowChecklist, FirstWorkflowChecklistView, WorkflowsList, useCreateWorkflowFirst } from './chunk-7SY2SL5Y.js';
8
+ import { CreateWorkflowRefusalDialog } from './chunk-JCHE4V55.js';
9
+ export { CreateWorkflowRefusalDialog, GUIDED_FIRST_WORKFLOW_NAV, GUIDED_FIRST_WORKFLOW_STATE, GUIDED_TOUR_STATE, firstWorkflowProgress, isGuidedTourIntent, pickGuidedTour } from './chunk-JCHE4V55.js';
10
10
  import './chunk-PIKYQE7P.js';
11
11
  import './chunk-AD3BXTJS.js';
12
- export { ExecutionsListPage } from './chunk-6OCQ3M5C.js';
13
- import { usePendingHumanRequests, HumanRequestCard } from './chunk-LENZTZNB.js';
14
- export { ExecutionDetailPage, HumanRequestCard, RunHumanRequests, usePendingHumanRequests, useRespondToHumanRequest, useRunHumanRequests } from './chunk-LENZTZNB.js';
15
- import './chunk-ENULBWW2.js';
16
- import { TagFilterSelect } from './chunk-GAVK2EWX.js';
17
- import './chunk-KI37QYJ7.js';
18
- export { HistoryPage } from './chunk-QK76M4E5.js';
19
- export { NodesPage, fetchAllNodesWithManifests, useLazyNodeManifest, useNodeEndpoint, useNodeEndpoints, useNodeManifest } from './chunk-DUE25AIG.js';
20
- export { DataSinkDashboardPage, ErrorAnalyticsPage, InsightsPage } from './chunk-VZ3KQIQE.js';
21
- import './chunk-WEE4WVMB.js';
22
- export { SettingsPage } from './chunk-KD4O5ODO.js';
23
- import './chunk-BTQBEF4H.js';
24
- import './chunk-OOVWMJBF.js';
25
- export { useDataSinkData, useDataSinks, useInsightsData, useLogStreamDestinationActions, useLogStreamDestinations, useRunReplayActions } from './chunk-FQ4IYSLN.js';
12
+ export { ExecutionsListPage } from './chunk-B2DNUVKW.js';
13
+ import { usePendingHumanRequests, HumanRequestCard } from './chunk-P6IRD5SA.js';
14
+ export { ExecutionDetailPage, HumanRequestCard, RunHumanRequests, usePendingHumanRequests, useRespondToHumanRequest, useRunHumanRequests } from './chunk-P6IRD5SA.js';
15
+ import './chunk-UETHT3KG.js';
16
+ import { TagFilterSelect } from './chunk-ZTJX5ONT.js';
17
+ import './chunk-QAXP5HON.js';
18
+ export { HistoryPage } from './chunk-XNVYPEBO.js';
19
+ export { NodesPage, fetchAllNodesWithManifests, useLazyNodeManifest, useNodeEndpoint, useNodeEndpoints, useNodeManifest } from './chunk-VFLHURFM.js';
20
+ export { DataSinkDashboardPage, ErrorAnalyticsPage, InsightsPage } from './chunk-7JLLH4YE.js';
21
+ import './chunk-A4XNCGWT.js';
22
+ export { SettingsPage } from './chunk-6VODFT2Q.js';
23
+ import './chunk-A7QPQ6MO.js';
24
+ import './chunk-DLKGWGRN.js';
25
+ export { useDataSinkData, useDataSinks, useInsightsData, useLogStreamDestinationActions, useLogStreamDestinations, useRunReplayActions } from './chunk-CXNJKM4D.js';
26
26
  import './chunk-5ERAJC2I.js';
27
- import { ThemeProvider, extractTemplateGraph } from './chunk-3VEJGG5F.js';
28
- export { TemplatePreview, TemplatesPage } from './chunk-3VEJGG5F.js';
29
- import { useAiWorkflowTemplates, AI_DRAFT_MAX_PROMPT_LENGTH, FlowBuilderPage, FluidGridsMark, draftToCanvas, enrichDraftNodes } from './chunk-5YNWH64U.js';
30
- export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, RunsUsageMeter, RunsUsageMeterView, readRunsQuota, runsQuotaLevel, summarizeRunsQuota, useRunsQuota } from './chunk-5YNWH64U.js';
27
+ import { ThemeProvider, extractTemplateGraph } from './chunk-YVOHCC7J.js';
28
+ export { TemplatePreview, TemplatesPage } from './chunk-YVOHCC7J.js';
29
+ import { useAiWorkflowTemplates, AI_DRAFT_MAX_PROMPT_LENGTH, FlowBuilderPage, FluidGridsMark, draftToCanvas, enrichDraftNodes } from './chunk-MY752OLT.js';
30
+ export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, RunsUsageMeter, RunsUsageMeterView, readRunsQuota, runsQuotaLevel, summarizeRunsQuota, useRunsQuota } from './chunk-MY752OLT.js';
31
31
  import './chunk-GEMNVFPK.js';
32
32
  import './chunk-B6CCE2RW.js';
33
33
  export { Input } from './chunk-IEVSFCFS.js';
34
34
  export { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './chunk-YXMFRQYV.js';
35
35
  export { Badge, Button, badgeVariants, buttonVariants } from './chunk-BQXVT32O.js';
36
- import './chunk-WOSFZWOQ.js';
37
- import './chunk-ZLOASEDO.js';
38
- import './chunk-K4UJ27ED.js';
39
- import { EntityTagPicker } from './chunk-WNZKFW7A.js';
40
- export { EntityTagPicker } from './chunk-WNZKFW7A.js';
36
+ import './chunk-W74MXVFX.js';
37
+ import './chunk-OUYEMZT6.js';
38
+ import './chunk-4FDMLKLL.js';
39
+ import { EntityTagPicker } from './chunk-3Y4266JL.js';
40
+ export { EntityTagPicker } from './chunk-3Y4266JL.js';
41
41
  import './chunk-JDLQ6QIB.js';
42
- import { useDataTableTagOverlay, tagLabel } from './chunk-YBL4H324.js';
43
- export { FLUIDGRIDS_ENTITY_TYPES, tagLabel, useAvailableTags, useCreateTag, useDraftEntityTags, useEntityTags, useReplaceEntityTags, useSearchTags, useTagEntity, useUntagEntity } from './chunk-YBL4H324.js';
42
+ import { useDataTableTagOverlay, tagLabel } from './chunk-PC3CICOW.js';
43
+ export { FLUIDGRIDS_ENTITY_TYPES, tagLabel, useAvailableTags, useCreateTag, useDraftEntityTags, useEntityTags, useReplaceEntityTags, useSearchTags, useTagEntity, useUntagEntity } from './chunk-PC3CICOW.js';
44
44
  import { AiCreditBalanceSlot, notifyFluidGridsAiCreditsUpdated } from './chunk-Y53CVZVV.js';
45
+ import './chunk-PBCBDSVA.js';
45
46
  import './chunk-FNZZ5JJL.js';
46
- import { useCreateWorkflow } from './chunk-KQ3SBSDS.js';
47
- export { useActivateWorkflow, useCreateWorkflow, useCreateWorkflowVersion, useDashboardSummary, useDeactivateWorkflow, useDeleteWorkflow, useDuplicateWorkflow, useImportWorkflow, useLazyWorkflowDefinition, useRestoreWorkflowVersion, useTriggerWorkflow, useUpdateWorkflow, useWorkflowDefinition, useWorkflowDefinitions, useWorkflowRun, useWorkflowRuns, useWorkflowVersions } from './chunk-KQ3SBSDS.js';
47
+ import { useCreateWorkflow } from './chunk-EFOJEQDS.js';
48
+ export { useActivateWorkflow, useCreateWorkflow, useCreateWorkflowVersion, useDashboardSummary, useDeactivateWorkflow, useDeleteWorkflow, useDuplicateWorkflow, useImportWorkflow, useLazyWorkflowDefinition, useRestoreWorkflowVersion, useTriggerWorkflow, useUpdateWorkflow, useWorkflowDefinition, useWorkflowDefinitions, useWorkflowRun, useWorkflowRuns, useWorkflowVersions } from './chunk-EFOJEQDS.js';
48
49
  export { FluidGridsAssistantBridge, useFluidGridsPageControls } from './chunk-PJAWNFJV.js';
49
50
  import './chunk-GLYINMOR.js';
50
51
  export { A2AMessagePriority, A2AMessageStatus, A2ATrustLevel, ActionExecutionStatus, ActionPolicyEffect, ActionSourceType, ActionStatus, ActionTriggerType, ActivityCategory, ActivityType, ActorType, AdaAdapterKind, AdaAdapterStatus, AdaAuthMethod, AdaChargebackMode, AdaConnectionStatus, AdaDataSubjectRequestStatus, AdaDataSubjectRequestType, AdaDataSubjectRetentionRule, AdaDriftStatus, AdaEdgeKind, AdaInvitationStatus, AdaLegalCheckpointType, AdaPartnerCapability, AdaPartnerCapabilityState, AdaPartnerRelationship, AdaPolicyEnforcement, AdaPolicyKind, AdaResourceState, AdaSeverity, AdaSyncKind, AdaSyncStatus, AdaViolationStatus, AgentCapabilityScope, AgentDefinitionStatus, AgentVisibility, AiContextStatus, AiContextType, AiPredictionStatus, AiPromptCategory, AiPromptStatus, AlertSeverity, AnalyticsEntityType, AnalyticsEventSeverity, AnalyticsGranularity, AnalyticsInsightSeverity, AppCategory, AppInstallationState, AppPermission, AppStatus, AppType, AppVisibility, ApprovalStatus, ArtAdobeSyncDirection, ArtAdobeSyncStatus, ArtAnchorType, ArtApprovalDecision, ArtAssetKind, ArtCustomDomainStatus, ArtDiscoverSort, ArtDistributionStatus, ArtDsp, ArtDspDeliveryStatus, ArtEarningStatus, ArtEngagementKind, ArtEngagementSource, ArtFeedbackStatus, ArtLicenseModel, ArtLicenseStatus, ArtListingStatus, ArtMedium, ArtOrderRole, ArtOrderStatus, ArtProductionRole, ArtProductionStatus, ArtReleaseStatus, ArtReportFormat, ArtReviewGuestStatus, ArtReviewStatus, ArtStageRule, ArtStageStatus, ArtTagSuggestionSource, ArtVisibility, ArtWebhookDeliveryStatus, ArtWebhookKind, ArtWorkStatus, ArtifactType, AssetAssignmentStatus, AssetBudgetStatus, AssetCondition, AssetDeadlineAlertKind, AssetDeadlineAlertStatus, AssetDepreciationMethod, AssetMeterUnit, AssetStatus, AssetTransactionStatus, AssetTransactionType, AssignmentSource, AssistantHistoryArchivedFilter, AssistantHistoryChannel, AssistantHistoryChannelFilter, AssistantHistoryDeleteOutcome, AssistantHistoryEntryKind, AssistantHistoryRole, AssistantHistorySaveOutcome, AssistantHistoryUpdateOutcome, AssistantMessageRole, AssistantRelayGateway, AthAgentRunStatus, AthAgentRunTrigger, AthAiAssessment, AthAvailabilityResponse, AthFixtureStatus, AthFixtureType, AthMemberRole, AthMemberStatus, AthMetricType, AthProgramLevel, AthProgramStatus, AthSessionStatus, AthSessionType, AthSport, AthTeamStatus, AthWorkoutStatus, AttendeeRole, AuthMethodFlow, AuthType, AuthorType, BackoffStrategy, BatchDownloadStatus, BigConsoleAnomalyDetectionMethod, BigConsoleAnomalyDirection, BigConsoleConflictResolution, BigConsoleDashboardCategory, BigConsoleDashboardEmbedAccessMode, BigConsoleDashboardEmbedContentReviewState, BigConsoleDashboardEmbedPolicyStatus, BigConsoleDashboardEmbedTheme, BigConsoleDashboardLayout, BigConsoleDashboardPageLayout, BigConsoleDashboardSharePermission, BigConsoleDashboardShareRecipientType, BigConsoleDashboardSortField, BigConsoleDashboardStatus, BigConsoleDashboardStyleType, BigConsoleDashboardTemplateAuthorType, BigConsoleDashboardTemplateComplexity, BigConsoleDashboardTemplateStatus, BigConsoleDashboardVisibility, BigConsoleDataSourceTestStatus, BigConsoleDataSourceType, BigConsoleDrilldownNavigationMode, BigConsoleFilterType, BigConsoleGeneratedLayoutType, BigConsoleTimeBucket, BigConsoleTimeRange, BigConsoleWidgetActionStyle, BigConsoleWidgetActionType, BigConsoleWidgetConfidence, BigConsoleWidgetEventStatus, BigConsoleWidgetHttpMethod, BigConsoleWidgetRenderer, BigConsoleWidgetType, BillingPlan, BillingType, BoardColumnType, BoardType, BookingFormFieldType, BookingPageType, BookingStatus, BotAppStatus, BotAppType, BotAppVisibility, BotlitAgentCapability, BotlitAgentStatus, BotlitAgentType, BotlitHealthStatus, BotlitLlmProviderType, BotmanorAgentApprovalStatus, BotmanorAgentCapability, BotmanorAgentStatus, BotmanorAgentType, BotmanorHealthStatus, BotmanorLlmProviderType, BraAccountStatus, BraAccountType, BraAdvisorRole, BraAdvisorStatus, BraAggregationLinkStatus, BraAggregationProvider, BraAssetClass, BraGoalProjection, BraGoalStatus, BraGoalType, BraHouseholdStatus, BraInsightSeverity, BraInsightStatus, BraInsightType, BraPortfolioStatus, BraRebalanceAuditEvent, BraRebalanceStatus, BraRecurringCategory, BraRecurringFrequency, BraReportFrequency, BraReportRunStatus, BraRiskProfile, BraRiskSignalKind, BraScheduledReportStatus, BraTradeInstructionAction, BraTradeInstructionSource, BraTradeInstructionStatus, BraTransactionType, BudgetStatus, BuiAccessibilityContentKind, BuiAccessibilityRule, BuiAccessibilitySeverity, BuiAccessibilityTargetType, BuiAdminCopilotActionKind, BuiAdminCopilotActionStatus, BuiAdminCopilotRole, BuiAiSuggestionOutcome, BuiAssessmentStatus, BuiAssessmentType, BuiAutomationRunStatus, BuiAutomationTemplate, BuiAutomationTriggerKind, BuiAutomationTriggerSource, BuiBadgeAwardMethod, BuiBadgeAwardStatus, BuiBadgeKind, BuiBadgeStatus, BuiCertificateStatus, BuiCertificationBody, BuiCohortStatus, BuiCourseExportFormat, BuiCourseLevel, BuiCourseStatus, BuiEnrollmentStatus, BuiExternalSource, BuiExternalSyncKind, BuiLessonType, BuiLtiGradeSyncStatus, BuiLtiMessageType, BuiLtiRosterMemberStatus, BuiMigrationFormat, BuiMigrationIssueSeverity, BuiMigrationJobKind, BuiMigrationJobStatus, BuiOnboardingStepKey, BuiPacingHint, BuiPathRecommendationReason, BuiProctoringDecision, BuiProctoringSignalType, BuiProctoringStatus, BuiProgressStatus, BuiQuestionType, BuiSkillCategory, BuiSkillStandardSource, BuiSubmissionStatus, BuiTutorAdaptiveLevel, BuiTutorMessageRole, BuiTutorReviewAction, BuiTutorReviewStatus, BulkConversationAction, CalendarEventStatus, CalendarExecutionStatus, CalendarExportFormat, CalendarPromptStatus, CalendarResourceType, CalendarType, CallParticipantChangeType, CallState, CallType, CatalogVisibility, ChangeRisk, ChangeStatus, ChannelMessageStatus, ChannelPlatform, ChannelType, ChatRole, CheckInStatus, ChunkingMethod, CircuitState, CodeReplaceKind, CodeReplaceStatus, CohortType, ColAssistantSuggestionKind, ColAssistantSuggestionStatus, ColCertainty, ColEventType, ColGender, ColGuardianRequestDecision, ColGuardianRequestStatus, ColGuardianRequestTargetKind, ColGuardianRequestType, ColKeepsakeBookStatus, ColLifeStatus, ColMemberRole, ColMembershipStatus, ColMemoryKind, ColPromptCategory, ColPromptRelationshipType, ColRelationshipType, ColStoryFormat, ColTreeStatus, ColVisibility, CollaboratorRole, CollectionActivityType, CollectionItemSortField, CollectionSortField, CollectionType, CollectionVisibility, ComAnalyticsPeriod, ComBadgeCriteria, ComBillingInterval, ComChallengePhase, ComChallengeStatus, ComChannelType, ComChannelVisibility, ComCircleStatus, ComCircleVisibility, ComCommunityHealthStatus, ComDevicePlatform, ComDigitalProductType, ComEventMode, ComEventStatus, ComExportFormat, ComFollowTargetType, ComGamificationAction, ComInsightCode, ComInsightSeverity, ComLeaderboardPeriod, ComLiveStreamRecordingCaptureMode, ComLiveStreamRecordingStatus, ComLiveStreamStatus, ComMediaMode, ComMemberRole, ComMembershipStatus, ComModerationCategory, ComModerationReviewDecision, ComModerationTargetType, ComModerationVerdictType, ComMonetizationStatus, ComPaidEventStatus, ComPollStatus, ComPostStatus, ComPresence, ComReactionTargetType, ComReactionType, ComReportStatus, ComReportTargetType, ComRsvpStatus, ComTipIntentStatus, ComVoiceSessionStatus, ComVoiceSignalType, CommentExportFormat, CommentScheduleType, CommentStatus, CommentVisibility, ComparisonOperator, ComponentLifecycle, ComponentType, ConfigScope, ConflictResolution, ConnectionAccess, ConnectionAccessFilter, ConnectionCredentialSource, ConnectionExpiryReason, ConnectionQuality, ConnectionSharePrincipalType, ConnectionShareRole, ConnectionStatus, ConnectionVisibility, ConnectorApiKeyPlacement, ConnectorSubmissionStatus, ConsultationConsultantType, ConsultationStatus, ContentSearchEngine, ContentSearchStatus, ContentType, ConversationPermission, ConversationSortField, ConversationState, ConversationType, ConversationVisibility, ConversationsExportFormat, CooAdminDecision, CooBrandStatus, CooCatalogProvider, CooCollaborationPayoutStatus, CooCollaborationStatus, CooCollaboratorRole, CooCollectionStatus, CooCommissionReversalStatus, CooEarningSyncStatus, CooFulfilmentStatus, CooLegalCheckpointType, CooLookOccasion, CooOrderStatus, CooOutfitSlot, CooPublishBlockerCode, CooRefundStatus, CooRestockStatus, CooReturnRequestStatus, CooSeason, CooStoreListingStatus, CooStoreSyncStatus, CooStyleCategory, CooStyleItemStatus, CooVisibility, CooWardrobeFindingKind, CooWardrobeSource, CooWeatherHint, CosAccessLevel, CosAnalysisStatus, CosDatasetStatus, CosDoiState, CosExternalRegistryMode, CosFieldType, CosGrantStatus, CosNotebookStatus, CosPipelineStatus, CosPipelineTrigger, CosReleaseStatus, CosRunStatus, CosSchemaSampleOrigin, CosSearchEntityType, CosSearchEvidenceKind, CosSearchLineageKind, CosSourceStatus, CosSourceType, CosStepKind, CosTriageAction, CosTriageEvidenceKind, CosTriageSignalSeverity, CosZenodoMirrorStatus, CrewAiDecisionKind, CrewPayrollCountry, CrewPayrollRunStatus, CrewfoundryExportFormat, CustomFieldType, CustomNodeLanguage, DataClassification, DataSinkAlertChannel, DataSinkAlertConditionType, DataSinkAlertExecutionStatus, DataSinkRefreshType, DataSinkSetupState, DataSinkSourceType, DataSinkStatus, DataSinkUpdateEventType, DataTableColumnType, DataTableFilterOp, DayOfWeek, DeliveryChannelType, DeliveryJobStatus, DeliveryPriority, DemandForecastScope, DependencyStatus, DependencyType, DeploymentEnvironment, DeploymentStatus, DiscoveryJobStatus, DlqStatus, DocStatus, DocumentStatus, DrainageStatus, DriverStatus, EcoAiActivitySource, EcoAiAnalysisStatus, EcoAiProposedActionKind, EcoAlertTriageClassification, EcoAlertTriageRecommendation, EcoAnomalyKind, EcoCarbonEntryStatus, EcoConservationStatus, EcoDataSourceType, EcoEmissionScope, EcoHabitatProjectStatus, EcoIngestionJobStatus, EcoIngestionRecordType, EcoMeasurementSource, EcoObservationMethod, EcoReductionTargetStatus, EcoReportFramework, EcoReportStatus, EcoRestorationActivityType, EcoSensorKind, EcoSensorStatus, EcoSiteStatus, EcoSiteType, EcoTaxonGroup, EcoThresholdDirection, EcoThresholdSeverity, EcoTriageSignalDirection, EncryptionAlgorithm, EnergyLevel, EntityStatus, ErrorType, EventStatus, EventType, EventValidationStatus, EventVisibility, EventfullyManagedAiDecisionKind, EventfullyManagedForecastBasis, EventfullyManagedForecastConfidence, EventfullyManagedIntegrationConnectorStatus, EventfullyManagedIntegrationProvider, EventfullyManagedIntegrationSyncRunStatus, EventfullyManagedSessionRecommendationEmptyReason, EventfullyManagedVirtualParticipantRole, EventfullyManagedVirtualSessionMode, EventfullyManagedVirtualSessionStatus, EventfullyManagedVirtualSignalType, ExecutionKind, ExecutionStatus, ExecutionType, ExecutorType, ExpenseOrderByField, ExpenseStatus, ExportArchiveFormat, ExportFormat, ExportJobStatus, ExportScope, ExportSortField, ExternalCalendarSyncDirection, ExternalCalendarSyncStatus, ExternalProviderType, FeatureRequestStatus, FidelityLevel, FieldMaskStrategy, FileEventType, FileMetadataSortField, FileSha256Provenance, FileShareAccessLevel, FileShareType, FileSortField, FileStatus, FileVisibility, FilterDataType, FilterOperator, FluidGridsEventType, FluidGridsWorkflowStatus, FolderSortField, FolderStatus, FuelType, FunnelStepOrder, GeofenceEventType, GeofenceTrigger, GgnomadAccessibilityFeature, GgnomadAffiliateCommissionStatus, GgnomadAffiliatePartnerStatus, GgnomadAffiliateReferralSource, GgnomadApprovalStatus, GgnomadAvailabilityStatus, GgnomadBookingOperation, GgnomadBookingQuantityBasis, GgnomadBookingStatus, GgnomadBookingType, GgnomadCalendarDayStatus, GgnomadCartStatus, GgnomadChannelSyncDirection, GgnomadChannelSyncStatus, GgnomadClaimStatus, GgnomadExportFormat, GgnomadGroupTripSplitMethod, GgnomadGroupTripVoteChoice, GgnomadListingStatus, GgnomadListingType, GgnomadLoyaltyTransactionType, GgnomadNightlyRateSource, GgnomadPaymentMethod, GgnomadPricingRuleType, GgnomadPrivateRequestAction, GgnomadPrivateRequestStatus, GgnomadProviderType, GgnomadPushPlatform, GgnomadSearchEntityType, GgnomadSearchSort, GgnomadSurchargeSource, GgnomadSustainabilityPractice, GgnomadTicketStatus, GgnomadTripPlanItemType, GovAgentRunStatus, GovAgentRunTrigger, GovApplicationStatus, GovAssetCategory, GovAssetOperator, GovAssetStatus, GovBenchmarkScope, GovBudgetCategory, GovBudgetLineKind, GovBudgetStatus, GovCaseEscalationKind, GovCaseEscalationStatus, GovCaseNoteType, GovCasePriority, GovCommitmentStatus, GovConsultationStatus, GovConsultationType, GovDataLicense, GovDatasetFormat, GovDatasetStatus, GovDocumentStatus, GovElectionStatus, GovElectionType, GovEventCategory, GovEventImpact, GovFeeType, GovFundingSource, GovGrievanceStatus, GovIndicatorDirection, GovIndicatorDomain, GovIndicatorPeriodicity, GovIndicatorValueType, GovInsightKind, GovInsightSeverity, GovIntelEntityType, GovJurisdictionStatus, GovMilestoneStatus, GovOfficeType, GovPaymentStatus, GovPermitStatus, GovProjectStatus, GovProposalStatus, GovSentiment, GovServiceCategory, GovServiceStatus, GovTrendDirection, GovVerificationStatus, GraphMetadataOperator, GraphSearchMode, GraphSearchSortBy, GroupCompositionMode, GroupExportFormat, GroupScope, GroupSortField, GroupStatus, GroupType, GroupVisibility, GroupsExportFormat, GrowLocationType, HeadshotmarketingAdCampaignStatus, HeadshotmarketingAdConnectionMode, HeadshotmarketingAdConnectionStatus, HeadshotmarketingAdCreativeStatus, HeadshotmarketingAdCreativeTestMetric, HeadshotmarketingAdCreativeTestOutcome, HeadshotmarketingAdCreativeTestStatus, HeadshotmarketingAdCreativeType, HeadshotmarketingAdPlatform, HeadshotmarketingAdSyncAttemptStatus, HeadshotmarketingAdSyncDirection, HeadshotmarketingAdSyncStatus, HeadshotmarketingAdSyncTrigger, HeadshotmarketingAgentActionStatus, HeadshotmarketingAgentMessageRole, HeadshotmarketingAiDecisionSource, HeadshotmarketingAiToolCategory, HeadshotmarketingAiToolExecutionStatus, HeadshotmarketingAssetType, HeadshotmarketingAttributionConversionType, HeadshotmarketingAttributionModel, HeadshotmarketingAudienceSuggestionStatus, HeadshotmarketingAutomationRunStatus, HeadshotmarketingAutomationStepLogStatus, HeadshotmarketingAutomationSubjectType, HeadshotmarketingAutomationTriggerType, HeadshotmarketingAutomationWorkflowStatus, HeadshotmarketingCampaignStatus, HeadshotmarketingCampaignType, HeadshotmarketingContactStatus, HeadshotmarketingContentItemStatus, HeadshotmarketingContentItemType, HeadshotmarketingCulturalCategory, HeadshotmarketingCulturalRegion, HeadshotmarketingDataDrivenStatus, HeadshotmarketingDealStatus, HeadshotmarketingEventRegistrationStatus, HeadshotmarketingEventStatus, HeadshotmarketingEventType, HeadshotmarketingExportFormat, HeadshotmarketingInfluencerCampaignStatus, HeadshotmarketingInfluencerRelationshipStatus, HeadshotmarketingInfluencerTier, HeadshotmarketingIntegrationCategory, HeadshotmarketingIntegrationConnectionType, HeadshotmarketingIntegrationListingStatus, HeadshotmarketingLandingPageSectionType, HeadshotmarketingLandingPageStatus, HeadshotmarketingLeadScoreTier, HeadshotmarketingLeadSource, HeadshotmarketingLeadStatus, HeadshotmarketingNextActionType, HeadshotmarketingSeoAuditSeverity, HeadshotmarketingSeoAuditStatus, HeadshotmarketingSeoKeywordDataStatus, HeadshotmarketingSeoKeywordStatus, HeadshotmarketingSeoRankCheckStatus, HeadshotmarketingSocialAccountDeliveryMode, HeadshotmarketingSocialAccountStatus, HeadshotmarketingSocialMentionSentiment, HeadshotmarketingSocialMentionStatus, HeadshotmarketingSocialMentionType, HeadshotmarketingSocialPlatform, HeadshotmarketingSocialPostStatus, HeadshotmarketingTouchpointType, HeadshotmarketingTrackedClickResolution, HeadshotmarketingTrackedLinkKind, HeadshotmarketingTrackedLinkSource, HeadshotmarketingTranslationStatus, HeadshotmarketingWorkspaceIntegrationStatus, HealthyBowlAdvisoryTaskStatus, HealthyBowlConsultantAssignmentScope, HealthyBowlFarmRecommendationPriority, HealthyBowlFarmRecommendationStatus, HealthyBowlFinancierGrantScope, HealthyBowlGeneratableReportType, HealthyBowlGrowthGranularity, HealthyBowlPaddockState, HealthyBowlTaggableType, HokActivationAudience, HokAdCampaignStatus, HokAdCreativeType, HokAdDemandSource, HokAdPlacement, HokApplicationStatus, HokAssistantBasis, HokAuditionStatus, HokBreakdownCategory, HokBudgetForecastStatus, HokCallbackFormat, HokCallbackStatus, HokCastingSide, HokChannelStatus, HokClipStatus, HokConflictSeverity, HokCostCategory, HokCreditRole, HokCrewRole, HokDisputeCategory, HokDisputeOutcome, HokDisputeStatus, HokEmbedKind, HokEmbedStatus, HokEntitlementSource, HokEntitlementStatus, HokFitSignal, HokGuardianLinkStatus, HokLegalCheckpointType, HokListKind, HokListVisibility, HokLocalizationKind, HokLocalizationStatus, HokModerationSeverity, HokModerationStatus, HokMonetizationMode, HokNameMatchType, HokOfferPaymentStatus, HokOfferSignerRole, HokOfferStatus, HokOnboardingStepKey, HokPlanPhaseKey, HokPlaybackEventType, HokProductionFormat, HokProductionMemberKind, HokProductionStatus, HokRatingSubjectType, HokRecommendationAction, HokRecommendationReasonKind, HokRecommendationSurface, HokRecommendationVariant, HokReviewStatus, HokRightsWindowStatus, HokRoyaltyComputationMethod, HokRoyaltyLedgerStatus, HokRoyaltyPayeeType, HokSceneSetting, HokSceneTimeOfDay, HokScheduleConflictType, HokShootDayStatus, HokShotMovement, HokShotStatus, HokShotType, HokTalentInvitationStatus, HokTitleStatus, HokTitleType, HokVerificationStatus, HokVerificationSubjectType, HokWatchFeedHealth, HokWatchOfferQuality, HokWatchOptionSource, HokWatchPartyStatus, HokWatchProviderStatus, HousingVistaAnalyticsPeriod, HousingVistaMaintenancePriority, HousingVistaMaintenanceStatus, HousingVistaNlSearchMethod, HousingVistaOfferResponseAction, HousingVistaOfferStatus, HousingVistaPropertyStatus, HousingVistaPropertyType, HousingVistaRentalApplicationStatus, HousingVistaReraVerificationStatus, HousingVistaViewingStatus, HousingVistaViewingType, HttpMethod, IncidentStatus, IndexStatus, InstallMode, InstructionFilename, InstructionScope, IntAlertSeverity, IntAlertStatus, IntCaseStatus, IntClassification, IntConfidence, IntEntityType, IntFeedStatus, IntIndicatorType, IntMissionStatus, IntPriority, IntRelationshipType, IntReportStatus, IntReportType, IntRequirementStatus, IntSourceDiscipline, IntSourceStatus, IntTaskStatus, IntegrationEventStatus, IntegrationStatus, InventoryTransactionType, InvitationEmailStatus, InvitationStatus, InviteStatus, InvoiceStatus, IssueTokenErrorCode, JobStatus, JoinGroupStatus, KadaikodiAddressType, KadaikodiClockAction, KadaikodiInvestmentStatus, KadaikodiLoyaltyTxnType, KadaikodiMembershipInterval, KadaikodiOfferingKind, KadaikodiOrderStatus, KadaikodiPaymentMethodType, KadaikodiPaymentStatus, KadaikodiProviderStatus, KadaikodiRiskLevel, KadaikodiServiceCategory, KadaikodiSubscriptionStatus, KadaikodiWorkerTaskStatus, KadaikodiWorkerTaskType, KeyResultMetricType, KeyResultProgressSource, KeyResultStatus, KeyStatus, KeyType, KnowledgeArticleStatus, KnowledgeCleanupKind, LabAgentRunStatus, LabAgentRunTrigger, LabBookingStatus, LabDatasetKind, LabDatasetStatus, LabExperimentStatus, LabInstrumentStatus, LabInventoryCategory, LabInventoryStatus, LabNotebookEntryStatus, LabPipelineRunStatus, LabProjectStatus, LabProjectVisibility, LabProtocolStatus, LabProvenanceEntityType, LabRunRecommendation, LabRunStatus, LabStepKind, LegalHoldStatus, LicenseMetricType, LicensePositionType, LocationType, LockType, LogAction, LogLevel, LogStreamEventType, LogStreamProvider, MailboxFolder, MailboxKind, ManAssetStatus, ManCapaVerificationResult, ManChecklistItemResult, ManControlChartType, ManDowntimeReason, ManErpEntityType, ManErpProvider, ManErpSyncDirection, ManErpSyncStatus, ManInspectionResult, ManInspectionStage, ManItemType, ManLegalCheckpointType, ManMaintenanceStatus, ManMaintenanceType, ManMaintenanceWorkOrderEventType, ManMaterialLinkRole, ManMaterialLotEventType, ManMaterialLotReleaseDecision, ManMaterialLotStatus, ManMaterialSerialEventType, ManNonConformanceDisposition, ManNonConformanceEventType, ManNonConformanceLinkType, ManNonConformanceStatus, ManOperationStatus, ManPmState, ManProductionOrderStatus, ManProductionPriority, ManRoutingEventType, ManSeverity, ManTagSource, ManTrackingMode, ManWorkCenterType, McpConnectionStatus, McpResourceType, McpToolRiskLevel, McpToolStatus, MeetingActionItemStatus, MeetingOrderByField, MeetingParticipantRole, MeetingParticipantStatus, MeetingProvider, MeetingType, MemberPresenceStatus, MembershipRole, MembershipSource, MembershipStatus, MembershipType, MentionType, MeshSessionKind, MessageContentType, MessageReportResolutionAction, MessageReportStatus, MessageStatus, MessageType, MetadataValueType, MetricAggregationField, MetricType, MilestoneStatus, MisfirePolicy, Mood, MtwCarrierProvider, MtwCarrierServiceMode, MtwConsolidationQuantityBasis, MtwConsolidationReportKind, MtwConsumedFuelBasis, MtwConsumedFuelQualification, MtwConsumedFuelReason, MtwContainerCargoCategory, MtwContainerCycleStatus, MtwContainerDefectSeverity, MtwContainerEventKind, MtwContainerEventType, MtwContainerExaminationScheme, MtwContainerHoldStatus, MtwContainerQualificationScope, MtwContainerQualificationStatus, MtwContainerSuitability, MtwDistanceUnit, MtwDriverStopState, MtwEquipmentType, MtwExportFormat, MtwFleetAlertSeverity, MtwFleetAlertSubjectType, MtwFleetAlertType, MtwFreeTimeApplicability, MtwFreeTimeCalculationPolicy, MtwFreeTimeChargeKind, MtwFreeTimeDecisionKind, MtwFreeTimePartialDayPolicy, MtwFreeTimeTierBasis, MtwFreightAmountBasis, MtwFreightCategory, MtwFreightCommercialStatus, MtwFreightDisposition, MtwFreightInvoiceAcceptance, MtwFreightInvoiceBlocker, MtwFreightInvoiceFlag, MtwFreightInvoiceReason, MtwFreightKind, MtwFreightLocationKind, MtwFreightRequirementStatus, MtwFreightRounding, MtwFreightVolumeUnit, MtwFreightWeightUnit, MtwImportColumnType, MtwImportEntityType, MtwImportFormat, MtwImportStatus, MtwIntegrationProvider, MtwPalletBoundStatus, MtwPalletClassification, MtwPalletLayoutStatus, MtwPalletMethod, MtwPalletMode, MtwPalletUnits, MtwPalletUnsupportedStatus, MtwPickReviewAction, MtwPickReviewKind, MtwPickReviewState, MtwPickTaskStatus, MtwPickTaskWorkflow, MtwProcedureApplicabilityStatus, MtwProcedureDeviationAuthority, MtwProcedureDeviationKind, MtwProcedureDeviationReviewKind, MtwProcedureRecordingBoundary, MtwProcedureStep, MtwProcedureStepKind, MtwProcedureVersionKind, MtwReuseApprovalKind, MtwReuseBlockerCertainty, MtwReuseReadinessStatus, MtwReuseReservationStatus, MtwReuseReservationTerminalStatus, MtwReuseSourcePurpose, MtwRiskLevel, MtwRiskNarrationStatus, MtwRiskRecommendedAction, MtwRiskSignalCode, MtwServiceAvailability, MtwServiceOfferingCategory, MtwServiceProviderType, MtwStockBindingCompletenessStatus, MtwStockBindingCountUnitKind, MtwStockBindingExpiryPolicy, MtwStockBindingIncompleteReason, MtwStockBindingLotDisposition, MtwStockBindingLotPolicy, MtwStockBindingProvenance, MtwStockBindingScope, MtwStockObservationCountScope, MtwStockObservationEvidenceStatus, MtwStockObservationKind, MtwStockObservationStatus, MtwTrackingAlertType, MtwTripUtilizationBasis, MtwTripUtilizationCoverage, MtwUtilizationCapacityBasis, MtwUtilizationDistanceBasis, MtwUtilizationLoadBasis, MtwUtilizationLoadedState, MtwUtilizationMetricReason, MtwUtilizationMetricStatus, MtwUtilizationWarning, MtwWeightUnit, MybAiOperationStatus, MybAiOperationType, MybAiProvider, MybBodyMetricType, MybCoachingStatus, MybDeviceConnectionStatus, MybDeviceProvider, MybExportFormat, MybFitnessLevel, MybGoalStatus, MybGoalType, MybGuidanceAction, MybGuidanceSignal, MybLegalCheckpointType, MybLogSource, MybMealType, MybMuscleGroup, MybProgramPhase, MybProgramStatus, MybRecoveryMetric, MybSessionStatus, MybWearableMetricType, MybWorkoutType, NatsFilterType, NodeConfigStatus, NodeStatus, NoteVisibility, NotificationLevel, ObjectiveStatus, OceanContainerType, OptimisationDismissReason, OptimisationKind, OptimisationSuggestionStatus, OrderDirection, OverrideType, PackageKind, ParentClosePolicy, ParserStatus, ParserType, ParticipantChangeType, ParticipantRole, PhysicalAuditItemOutcome, PhysicalAuditStatus, PipelineExecutionStatus, PipelineStatus, PlanmagnetActivityEventType, PlanmagnetAgentRunStatus, PlanmagnetAgentRunTrigger, PlanmagnetAnalyticsWindowPreset, PlanmagnetAutomationExecutionStatus, PlanmagnetAutomationStatus, PlanmagnetAutomationTriggerType, PlanmagnetBoardCardField, PlanmagnetBoardCardSortField, PlanmagnetBoardGroupBy, PlanmagnetBoardViewVisibility, PlanmagnetBusinessIntelligenceReason, PlanmagnetCommentStatus, PlanmagnetCommentTargetType, PlanmagnetDocDiffHunkKind, PlanmagnetDocEventKind, PlanmagnetDocSuggestionStatus, PlanmagnetDueGroup, PlanmagnetFeatureOrder, PlanmagnetForecastMethod, PlanmagnetImportFormat, PlanmagnetImportOutcome, PlanmagnetKano, PlanmagnetMeetingKind, PlanmagnetMilestoneOrder, PlanmagnetMoscow, PlanmagnetOutlookMethod, PlanmagnetPresenceEventKind, PlanmagnetPresenceTargetType, PlanmagnetPrioritizationMethod, PlanmagnetPrioritizationSource, PlanmagnetProductFeatureStatus, PlanmagnetProductLaunchChecklistCategory, PlanmagnetProductLaunchStatus, PlanmagnetProductLaunchTemplateKey, PlanmagnetProductLifecycleStage, PlanmagnetProductMarketSizingMethod, PlanmagnetProductPersonaStatus, PlanmagnetProjectEventKind, PlanmagnetProjectStatus, PlanmagnetQualityTrendDirection, PlanmagnetReleaseScope, PlanmagnetReportDeliveryStatus, PlanmagnetReportExportFormat, PlanmagnetReportRunTrigger, PlanmagnetReportScheduleCadence, PlanmagnetReportSource, PlanmagnetReportVisibility, PlanmagnetResourceForecastScopeType, PlanmagnetRiskFlagKind, PlanmagnetRiskFlagSeverity, PlanmagnetRoadmapEventKind, PlanmagnetRoadmapHorizon, PlanmagnetRoadmapReviewDecisionKind, PlanmagnetRoadmapReviewStatus, PlanmagnetRoadmapRiskLevel, PlanmagnetSatisfactionMetricType, PlanmagnetSatisfactionResponseSource, PlanmagnetSatisfactionWindowPreset, PlanmagnetSkillCoverageStatus, PlanmagnetSortDirection, PlanmagnetSprintEventKind, PlanmagnetSprintOpenItemsAction, PlanmagnetSprintScope, PlanmagnetStatusCategory, PlanmagnetStatusTransitionSource, PlanmagnetSuccessLikelihood, PlanmagnetSyncConflictResolution, PlanmagnetSyncConflictStatus, PlanmagnetSyncDirection, PlanmagnetSyncProvider, PlanmagnetSyncRunStatus, PlanmagnetSyncStatus, PlanmagnetThroughputBucket, PlanmagnetValueEffortQuadrant, PlanmagnetWebhookDeliveryStatus, PlanmagnetWebhookSubscriptionDeliveryStatus, PlanmagnetWebhookSubscriptionStatus, PlanmagnetWidgetRunStatus, PlanmagnetWidgetType, PlanmagnetWorkItemCodeLinkKind, PlanmagnetWorkItemCodeLinkState, PlanmagnetWorkItemEventKind, PluginStatus, PolicyType, PomodoroGoalPeriod, PomodoroGoalType, PomodoroSessionOrderByField, PomodoroSessionType, PortfolioStatus, PresenceStatus, Priority, ProblemStatus, ProductType, ProjectMethodology, ProjectOrderField, ProjectStatus, PromptAiCredentialSource, PromptGenerationStatus, PromptPriority, PromptStatus, PromptUsageDimensionV2, ProviderCategory, PswClientPortalUserStatus, PswClientStatus, PswClientType, PswComplianceStatus, PswComplianceType, PswConflictCheckStatus, PswCredentialRequestStatus, PswCredentialWriteOperation, PswDataSubjectRequestStatus, PswDataSubjectRequestType, PswDeliverableStatus, PswDocumentClassification, PswDocumentStatus, PswEducationUnit, PswEngagementStatus, PswErasureRequestStatus, PswExportFormat, PswFeeArrangement, PswInvoiceStatus, PswLegalCheckpointType, PswMatterPriority, PswMatterStatus, PswMilestoneStatus, PswObligationKind, PswRecordedValidity, PswRetainerCadence, PswSignatureAuditEventType, PswSignatureRequestStatus, PswSignatureSignerStatus, PswSignatureType, PswSourceObservation, PswTeamRole, PswTimeEntryStatus, PswTrustAccountStatus, PswTrustTransactionType, PswTrustTransferStatus, PublishType, QualityGateStatus, RbacChangeType, ReactionChangeType, RecordingMode, ReleaseStatus, ReminderChannel, ReminderType, ReportFormat, ReportScheduleStatus, ResourceBookingStatus, RetrievalMode, RiskSeverity, RiskStatus, RoadmapItemStatus, RoadmapPlanningFocus, RoadmapType, RoleAssignmentRequesterActorType, RoleLevel, RouteStatus, RoutingStrategy, RsvpStatus, RuleActionType, RuleConditionOperator, RuleMaterializationStrategy, RuleRunMode, RunFailureBucket, RunFailureClusterStatus, RunGroupBy, RunLogLevel, RunLogStream, RunMode, RunStatus, RunTriggerType, SandboxAgentJobStatus, SandboxAgentKind, SandboxAssistantMode, SandboxAssistantWriteApproval, SandboxChangeType, SandboxKind, SandboxMode, SandboxRunnerStatus, SandboxSource, SandboxStatus, SandboxTemplate, SchedulePriority, ScheduleType, ScorecardMetricDirection, ScorecardMetricStatus, ScorecardMetricType, ScorecardOwnerType, ScorecardTier, SecretProviderType, SecretShareKind, SecretShareScope, SecretShareStatus, SecretStatus, SecretType, SecurityComplianceStatus, SecurityEvidenceStatus, SecurityEvidenceType, SecurityEvidenceUploadType, SecurityExportFormat, SecurityFindingCategory, SecurityFindingStatus, SecurityGovernancePolicyStatus, SecurityMemberEventAction, SecurityPolicyLevel, SecurityScanConclusion, SecurityScanStatus, SecuritySecretEventAction, SecuritySeverity, SecurityStage, SecuritySubscriptionEvent, SecurityVaultEventAction, SegmentVisibility, SemAggregation, SemConnectionHealth, SemConnectorKind, SemDataSourceStatus, SemDataType, SemEntityKind, SemLineageDirection, SemLineageEdgeKind, SemLineageNodeKind, SemLineageRootKind, SemModelStatus, SemNlAssistStatus, SemNlClarificationReason, SemNlStatus, SemNlStepKind, SemOnboardingStepKey, SemPolicyEffect, SemPolicyScope, SemQueryRunStatus, SemQueryStatus, SemRelationshipKind, SemSqlColumnKind, SemSqlDataType, SessionExportFormat, SessionRecordingStatus, SessionRecordingStreamType, SessionSharePermission, SetActorRolesMode, SettingsCategory, ShareGrantStatus, ShareGrantVisibility, ShareRole, ShareSortField, ShareStatus, ShareTokenType, ShipmentLegStatus, ShipmentStatus, ShipmentStatusAuthority, ShipmentStatusDecisionOrigin, ShipmentStatusDecisionOutcome, ShipmentStatusHeldReason, SiemExportFormat, SignatureType, SmartCollectionConditionField, SmartCollectionConditionOperator, SmartCollectionOperator, SortDirection, SortOrder, SprintStatus, StageErrorHandling, StageExecutionStatus, StaticDataScope, StorageMode, StrategicAlignment, StressLevel, SubAgentKind, SubAgentScheduleStatus, SubAgentStatus, SubAgentSweepStatus, SubAgentSweepTrigger, SubAssetType, SubBenchmarkSourceKind, SubBillingInterval, SubChannelStatus, SubChannelType, SubDecisionKind, SubDecisionRecommendation, SubDecisionStatus, SubDiscoverySource, SubEntitlementType, SubInvoiceStatus, SubMessageCategory, SubModerationAction, SubOverlapType, SubPaymentInstrumentStatus, SubPaymentInstrumentType, SubPolicyAction, SubProviderCategory, SubProviderStatus, SubRelationshipKind, SubRelationshipStatus, SubReportStatus, SubRetentionDataClass, SubShadowItReason, SubSpendRiskKind, SubSpendRiskSeverity, SubSubmissionStatus, SubWorkflowStatus, SuggestedDataSourceType, SyncDirection, SyncFromGlobalOperation, SyncProvider, SystemEventType, TagCardinality, TagDataType, TagFilterOperator, TagRelationType, TagScope, TagsExportFormat, TargetType, TaskOrderField, TaskPriority, TaskStatus, TcpAccessLevel, TcpAgentRunStatus, TcpAgentRunTrigger, TcpAiGroundingKind, TcpAiReviewStatus, TcpAiUncertainty, TcpAiUseCase, TcpArchiveItemKind, TcpModerationStatus, TcpSourceType, TcpStoryFormat, TcpStoryStatus, TcpTopicCategory, TcpVerificationStatus, TecCertificateStatus, TecCertificateVerificationStatus, TecCourseLevel, TecCourseStatus, TecEnrollmentStatus, TecHackathonStatus, TecInterviewFrequency, TecLegalAcceptanceType, TecLessonCompletionMethod, TecLessonKind, TecLessonRunStatus, TecMentorStatus, TecPayoutStatus, TecPortfolioItemKind, TecProblemDifficulty, TecProblemStatus, TecReviewSource, TecSessionStatus, TecSolutionRunStatus, TecStudyPlanStatus, TecStudyPlanStepKind, TecStudyPlanStepStatus, TecSubmissionVerdict, TecTeamSubmissionStatus, TecTestCaseStatus, TecTestCaseVisibility, TemplateCategory, TemplateVisibility, TheAssetKind, TheAssetStatus, TheCommodityType, TheComplianceCategory, TheComplianceStatus, TheContractSide, TheContractStatus, TheCorrectiveActionStatus, TheEmissionScope, TheEsgDisclosureStatus, TheEsgFramework, TheInventoryStatus, TheLegalCheckpointType, ThePricingBasis, TheReserveCategory, TheSafetyIncidentCategory, TheSafetyIncidentSeverity, TheSafetyIncidentStatus, TheShipmentStatus, TheTransportMode, TheUnit, TimeCampusActivationMilestoneKey, TimeCampusAppletCategory, TimeCampusAppletInstallSource, TimeCampusCaptureChannelPrivacyMode, TimeCampusCaptureChannelStatus, TimeCampusCaptureChannelSyncStatus, TimeCampusCaptureChannelType, TimeCampusDataErasureStatus, TimeCampusExportFormat, TimeCampusFocusBlockReason, TimeCampusFocusBlockResponse, TimeCampusFocusBlockSource, TimeCampusFocusBlockStatus, TimeCampusFocusCalendarHoldStatus, TimeCampusFocusInterruptionSource, TimeCampusFocusProtectionLevel, TimeCampusFocusSessionStatus, TimeCampusInvoiceStatus, TimeCampusLifeDomain, TimeCampusLoadEvidenceKind, TimeCampusLoadEvidenceRefType, TimeCampusLoadFallbackReason, TimeCampusLoadLevel, TimeCampusLoadSignalMethod, TimeCampusOwnershipContext, TimeCampusProjectStatus, TimeCampusRecommendationSource, TimeCampusSortDirection, TimeCampusTemplateCategory, TimeCampusTimelineCategory, TimeCampusTimelineSource, TimeEntryOrderField, TimeEntryStatus, TimeGrain, TlsMode, ToolApprovalDecisionValue, ToolApprovalStatus, ToolApprovalTimeoutAction, ToolRiskLevel, TrackingEventType, TrackingSourceTimeProvenance, TransportMode, TraversalDirection, TunnelDomainType, TunnelDomainVerificationStatus, TunnelEnvironment, TunnelProtocol, TunnelProviderKey, TunnelSessionStatus, TunnelShardStatus, TunnelStatus, UpdateScope, UploadStatus, UploadType, UsageStatus, ValidationMethod, VariableScope, VaultIncidentSeverity, VaultIncidentStatus, VaultMemberRole, VaultRotationStatus, VaultScope, VaultSecurityEventSeverity, VaultSecurityEventType, VaultStatus, VaultSyncStatus, VehicleStatus, VehicleType, VersionStatus, VersioningBehavior, VibeAuditAction, VibeAuditExportFormat, VibeAuditResourceType, VibeAuditStatus, VibeCalendarExecutionStatus, VibeCalendarTaskStatus, VibeDeckButtonActionType, VibeDeckSharePermission, VibeDeckShareStatus, VibeDeckShareVisibility, VibeEntityType, VibeLlmContextTokenStatus, VibeStatus, VibeType, VibeVisibility, VibecontrolsActionType, VibecontrolsAgentVisibility, VibecontrolsDocsBuildImagePullPolicy, VibecontrolsDocsBuildImageScanStatus, VibecontrolsDocsBuildImageStatus, VibecontrolsDocsBuildRuntime, VibecontrolsDocsPageStatus, VibecontrolsDocsProvider, VibecontrolsDocsRevisionStatus, VibecontrolsDocsSiteOwnerType, VibecontrolsDocsSiteVisibility, VibecontrolsGitHubRepoScope, VibecontrolsGitHubRepoVisibility, VibecontrolsSessionStatus, VibecontrolsSessionType, VibecontrolsTemplateCategory, VibecontrolsTemplateStatus, Visibility, VisibilityType, VocabularyKind, VocabularyScope, WarehouseType, WebhookAuthType, WebhookTestListenerStatus, WidgetType, WorkItemLinkRelation, WorkItemPriority, WorkItemStatus, WorkItemType, WorkOrderStatus, WorkOrderType, WorkPatternInsightType, WorkflowAuthoringChannel, WorkflowDiffKind, WorkflowEnvironment, WorkflowExportFormat, WorkflowGenerationStatus, WorkflowGitProvider, WorkflowGitPushStatus, WorkflowGitPushTrigger, WorkflowHumanRequestStatus, WorkflowHumanResponseType, WorkflowIdConflictPolicy, WorkflowIdReusePolicy, WorkflowPromotionStatus, WorkflowProposalKind, WorkflowProposalStatus, WorkflowQueryRejectCondition, WorkflowResetType, WorkflowRunEventType, WorkflowRunUpdateStatus, WorkflowStatus, WorkflowTaskFailureCause, WorkflowTestAssertionOperator, WorkflowTestExpectedStatus, WorkflowTestRunSource, WorkflowTestRunStatus, WorkflowUpdateWaitFor, WorkspaceCompositionPricingMode, WorkspaceCompositionSource, WorkspaceInviteStatus, WorkspaceLegalCheckpointType, WorkspaceModuleKind, WorkspaceModuleOpenMode, WorkspaceQuotaMode, WorkspaceResourceStatus, WorkspaceResourceType, WorkspaceStatus, WorkspaceType, WorkspacesExportFormat } from './chunk-AOLY5INN.js';
51
52
  import { FluidGridsDocsLink } from './chunk-4VJ3MDOV.js';
52
- import { FluidGridsProvider, classifyCreateRefusal, builderPathOf, BILLING_PLANS_PATH, throwIfResultError, isForbiddenError, describeOperationError, nodesOf, ensureNodeConfigsLoaded, buildOperationSeed } from './chunk-UFT457ZJ.js';
53
- export { BILLING_PLANS_PATH, ConnectionFormDialog, ConnectionSelector, DURABLE_FUNCTION_NODE_TYPES, FLUIDGRIDS_FLAGS, FLUIDGRIDS_FLAG_DEFAULTS, FluidGridsProvider, PHASE_C_FLAGS_OFF, RUNS_QUOTA_NAME, RUN_CONTROL_NODE_TYPES, WORKFLOWS_QUOTA_NAME, WORKFLOW_TEST_NODE_TYPES, blankWorkflowCreateInput, classifyCreateRefusal, createThenOpen, describeOperationError, emitNodeInstalled, emitRunFailed, emitRunLimitHit, emitRunStarted, emitTemplateUsed, emitUpgradeClicked, emitWorkflowCreated, emitWorkflowLimitHit, emitWorkflowPublished, filterPaletteNodes, findQuotaRefusal, isDurableFunctionNodeType, isForbiddenError, isNodeTypeHiddenFromPalette, isQuotaExhaustedFailure, isRunControlNodeType, listCustomBlocks, openRunQuotaUpgradePrompt, refetchStoreNodes, registerCustomBlock, resolvePhaseCFlags, resolveUiSpec, stripSubmitActions, throwIfResultError, useConnection, useConnections, useConnectionsByProvider, useContinuousOptimisationEnabled, useCreateConnection, useDurableFunctionNodesEnabled, useDurableParityEnabled, useFlowStore, useFluidGridsAnalytics, useFluidGridsContext, useFluidGridsFlag, useInitiateOAuth, useNodeExecution, usePaletteGates, usePhaseCFlags, useProviders, useSelfHostedWorkersEnabled, useWorkflowTestsEnabled } from './chunk-UFT457ZJ.js';
53
+ import { FluidGridsProvider, classifyCreateRefusal, builderPathOf, BILLING_PLANS_PATH, throwIfResultError, isForbiddenError, describeOperationError, nodesOf, ensureNodeConfigsLoaded, buildOperationSeed } from './chunk-23LYGZ27.js';
54
+ export { BILLING_PLANS_PATH, ConnectionFormDialog, ConnectionSelector, DURABLE_FUNCTION_NODE_TYPES, FLUIDGRIDS_FLAGS, FLUIDGRIDS_FLAG_DEFAULTS, FluidGridsProvider, PHASE_C_FLAGS_OFF, RUNS_QUOTA_NAME, RUN_CONTROL_NODE_TYPES, WORKFLOWS_QUOTA_NAME, WORKFLOW_TEST_NODE_TYPES, blankWorkflowCreateInput, classifyCreateRefusal, createThenOpen, describeOperationError, emitNodeInstalled, emitRunFailed, emitRunLimitHit, emitRunStarted, emitTemplateUsed, emitUpgradeClicked, emitWorkflowCreated, emitWorkflowLimitHit, emitWorkflowPublished, filterPaletteNodes, findQuotaRefusal, isDurableFunctionNodeType, isForbiddenError, isNodeTypeHiddenFromPalette, isQuotaExhaustedFailure, isRunControlNodeType, listCustomBlocks, openRunQuotaUpgradePrompt, refetchStoreNodes, registerCustomBlock, resolvePhaseCFlags, resolveUiSpec, stripSubmitActions, throwIfResultError, useConnection, useConnections, useConnectionsByProvider, useContinuousOptimisationEnabled, useCreateConnection, useDurableFunctionNodesEnabled, useDurableParityEnabled, useFlowStore, useFluidGridsAnalytics, useFluidGridsContext, useFluidGridsFlag, useInitiateOAuth, useNodeExecution, usePaletteGates, usePhaseCFlags, useProviders, useSelfHostedWorkersEnabled, useWorkflowTestsEnabled } from './chunk-23LYGZ27.js';
54
55
  import { useFluidGridsPermission, FLUIDGRIDS_PERMISSIONS, SdkPermissionButton } from './chunk-ZUVFD5KV.js';
55
56
  export { ALLOW_ALL_PERMISSIONS, FLUIDGRIDS_PERMISSIONS, FluidGridsPermissionsProvider, SdkPermissionButton, SdkPermissionGate, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, evaluatePermissionCheck, useFluidGridsPermission } from './chunk-ZUVFD5KV.js';
56
57
  import { cn } from './chunk-JL7CASN5.js';
@@ -60,19 +61,19 @@ import { createGlobalStoreClient } from './chunk-PXIFUMLA.js';
60
61
  export { createGlobalStoreClient, getGlobalStoreClient, resetGlobalStoreClient, setGlobalStoreClient } from './chunk-PXIFUMLA.js';
61
62
  export { config, getFluidGridsConfig, getGraphQLEndpoint, resetFluidGridsConfig, resetFluidGridsExecutionState, setFluidGridsConfig } from './chunk-6AMNEX2Y.js';
62
63
  import './chunk-G77IGC3Y.js';
63
- import { WorkflowGenerationDocument, GenerateWorkflowFromPromptDocument, CancelWorkflowGenerationDocument } from './chunk-ZC7XPBZN.js';
64
- export { AcquireWorkflowEditLeaseDocument, ActivateWorkflowDefinitionDocument, ActivateWorkflowVersionCheckedDocument, ActiveExecutionsDocument, ApplyWorkflowProposalDocument, ApproveWorkflowPromotionDocument, AvailableFluidgridsTagsDocument, BuildWorkflowCodeDocument, BulkAssignWorkflowsToProjectDocument, BulkDeleteWorkflowsDocument, BulkMoveWorkflowsToFolderDocument, CancelExecutionDocument, CancelWorkflowGenerationDocument, CancelWorkflowPromotionDocument, CancelWorkflowProposalDocument, ContinuousOptimisationSettingsDocument, ContinuousOptimisationSettingsFieldsFragmentDoc, CreateFluidgridsTagDocument, CreateWorkflowDefinitionDocument, CreateWorkflowFolderDocument, CreateWorkflowProjectDocument, CreateWorkflowTestCaseDocument, CreateWorkflowTestCaseFromRunDocument, CreateWorkflowVersionDocument, DashboardSummaryDocument, DataTablesTagsDocument, DeactivateWorkflowDefinitionDocument, DeleteWorkflowDefinitionDocument, DeleteWorkflowFolderDocument, DeleteWorkflowProjectDocument, DeleteWorkflowRolloutDocument, DeleteWorkflowTestCaseDocument, DeployWorkflowVersionToDevDocument, DismissOptimisationSuggestionDocument, DismissRunFailureClusterDocument, DuplicateWorkflowDocument, DurableHistoryCapsDocument, DurableParityRunFieldsDocument, DurableRunFieldsDocument, EventRegistrationsDocument, ExecuteStepDocument, ExecutionDetailDocument, ExecutionLogsDocument, ExecutionStatsDocument, ExecutionsListDocument, ExplainRunDocument, ExportWorkflowCodeDocument, FgRunOptimisationScanDocument, FgTriageFailedRunsDocument, FileDownloadUrlDocument, FluidgridsAvailableTagFieldsFragmentDoc, FluidgridsEntityTagsDocument, FluidgridsTagAssignmentFieldsFragmentDoc, GenerateWorkflowFromPromptDocument, ImportWorkflowDocument, ImportWorkflowTemplateDocument, LinkWorkflowGitRepositoryDocument, ListenForWebhookTestEventDocument, MoveWorkflowFolderDocument, NodeEndpointConfigDocument, NodeEndpointConfigsDocument, NodeManifestDocument, NodeSchemaIntrospectionDocument, NodeStatesDocument, NodeUsageStatusDocument, OptimisationSuggestionFieldsFragmentDoc, OptimisationSuggestionsDocument, PauseExecutionDocument, PinNodeDataDocument, PreviewScheduleDocument, ProposeOptimisationDocument, ProposeRunFixDocument, ProposeWorkflowChangeDocument, PushWorkflowToGitDocument, RegisterNodeDocument, RejectWorkflowPromotionDocument, RejectWorkflowProposalDocument, ReleaseWorkflowEditLeaseDocument, RemoveNodeFromWorkflowsDocument, RenameWorkflowFolderDocument, RenameWorkflowProjectDocument, ReplaceFluidgridsEntityTagsDocument, RequestWorkflowPromotionDocument, RestoreWorkflowFromGitDocument, RestoreWorkflowVersionDocument, ResumeExecutionDocument, RetryNodeDocument, RunCodeReplaceFieldsFragmentDoc, RunEventAppendedDocument, RunFailureClustersDocument, RunFailureTriageSettingsDocument, RunFromNodeDocument, RunFromNodeEligibilityDocument, RunLogAppendedDocument, RunLogLineFieldsFragmentDoc, RunLogsDocument, RunWorkflowTestsDocument, SearchFluidgridsTagsDocument, SetContinuousOptimisationEnabledDocument, SetRunFailureTriageEnabledDocument, SetWorkflowRolloutDocument, SetWorkflowRunVersioningOverrideDocument, SignalWorkflowRunDocument, SnoozeOptimisationSuggestionDocument, StopWebhookTestListenerDocument, TagFluidgridsEntityDocument, TakeOverWorkflowEditLeaseDocument, TerminateExecutionDocument, TerminateWorkflowRunDocument, TriggerWorkflowDocument, UnlinkWorkflowGitRepositoryDocument, UnpinNodeDataDocument, UntagFluidgridsEntityDocument, UpdateDurableHistoryCapsDocument, UpdateWorkflowDefinitionDocument, UpdateWorkflowEnvironmentPolicyDocument, UpdateWorkflowTestCaseDocument, UsageTimeSeriesDocument, WebhookTestListenerDocument, WorkflowAuthoringDocument, WorkflowCodeSourceDocument, WorkflowDefinitionDocument, WorkflowDefinitionsDocument, WorkflowDefinitionsTagsDocument, WorkflowEditLeaseDocument, WorkflowEditLeaseStatusDocument, WorkflowEnvironmentsDocument, WorkflowFoldersDocument, WorkflowGenerationDocument, WorkflowGenerationTemplatesDocument, WorkflowGitCommitsDocument, WorkflowGitDiffDocument, WorkflowGitPushesDocument, WorkflowGitRepositoryDocument, WorkflowPinnedDataDocument, WorkflowProjectsDocument, WorkflowPromotionRequestsDocument, WorkflowProposalDocument, WorkflowRolloutFieldsFragmentDoc, WorkflowRunDeterminismStatusDocument, WorkflowRunDocument, WorkflowRunEventFieldsFragmentDoc, WorkflowRunHistoryDocument, WorkflowRunMetadataDocument, WorkflowRunPendingDocument, WorkflowRunStackTraceDocument, WorkflowRunsCountDocument, WorkflowRunsDocument, WorkflowTestCaseFieldsFragmentDoc, WorkflowTestCaseResultFieldsFragmentDoc, WorkflowTestCasesDocument, WorkflowTestRunDocument, WorkflowTestRunFieldsFragmentDoc, WorkflowTestRunsDocument, WorkflowVersionDrainageDocument, WorkflowVersioningDocument, WorkflowVersionsDocument, WorkspaceRunsQuotaDocument, useActivateWorkflowDefinitionMutation, useActiveExecutionsLazyQuery, useActiveExecutionsQuery, useActiveExecutionsSuspenseQuery, useAvailableFluidgridsTagsLazyQuery, useAvailableFluidgridsTagsQuery, useAvailableFluidgridsTagsSuspenseQuery, useCancelExecutionMutation, useCreateFluidgridsTagMutation, useCreateWorkflowDefinitionMutation, useCreateWorkflowVersionMutation, useDashboardSummaryLazyQuery, useDashboardSummaryQuery, useDashboardSummarySuspenseQuery, useDeactivateWorkflowDefinitionMutation, useDeleteWorkflowDefinitionMutation, useDuplicateWorkflowMutation, useEventRegistrationsLazyQuery, useEventRegistrationsQuery, useEventRegistrationsSuspenseQuery, useExecuteStepMutation, useExecutionDetailLazyQuery, useExecutionDetailQuery, useExecutionDetailSuspenseQuery, useExecutionLogsLazyQuery, useExecutionLogsQuery, useExecutionLogsSuspenseQuery, useExecutionStatsLazyQuery, useExecutionStatsQuery, useExecutionStatsSuspenseQuery, useExecutionsListLazyQuery, useExecutionsListQuery, useExecutionsListSuspenseQuery, useFluidgridsEntityTagsLazyQuery, useFluidgridsEntityTagsQuery, useFluidgridsEntityTagsSuspenseQuery, useImportWorkflowMutation, useImportWorkflowTemplateMutation, useNodeEndpointConfigLazyQuery, useNodeEndpointConfigQuery, useNodeEndpointConfigSuspenseQuery, useNodeEndpointConfigsLazyQuery, useNodeEndpointConfigsQuery, useNodeEndpointConfigsSuspenseQuery, useNodeManifestLazyQuery, useNodeManifestQuery, useNodeManifestSuspenseQuery, useNodeSchemaIntrospectionLazyQuery, useNodeSchemaIntrospectionQuery, useNodeSchemaIntrospectionSuspenseQuery, useNodeStatesLazyQuery, useNodeStatesQuery, useNodeStatesSuspenseQuery, useNodeUsageStatusLazyQuery, useNodeUsageStatusQuery, useNodeUsageStatusSuspenseQuery, usePauseExecutionMutation, usePinNodeDataMutation, usePreviewScheduleLazyQuery, usePreviewScheduleQuery, usePreviewScheduleSuspenseQuery, useRegisterNodeMutation, useRemoveNodeFromWorkflowsMutation, useReplaceFluidgridsEntityTagsMutation, useRestoreWorkflowVersionMutation, useResumeExecutionMutation, useRetryNodeMutation, useRunFromNodeEligibilityLazyQuery, useRunFromNodeEligibilityQuery, useRunFromNodeEligibilitySuspenseQuery, useRunFromNodeMutation, useRunLogAppendedSubscription, useRunLogsLazyQuery, useRunLogsQuery, useRunLogsSuspenseQuery, useSearchFluidgridsTagsLazyQuery, useSearchFluidgridsTagsQuery, useSearchFluidgridsTagsSuspenseQuery, useTagFluidgridsEntityMutation, useTerminateExecutionMutation, useTriggerWorkflowMutation, useUnpinNodeDataMutation, useUntagFluidgridsEntityMutation, useUpdateWorkflowDefinitionMutation, useUsageTimeSeriesLazyQuery, useUsageTimeSeriesQuery, useUsageTimeSeriesSuspenseQuery, useWorkflowDefinitionLazyQuery, useWorkflowDefinitionQuery, useWorkflowDefinitionSuspenseQuery, useWorkflowDefinitionsLazyQuery, useWorkflowDefinitionsQuery, useWorkflowDefinitionsSuspenseQuery, useWorkflowDefinitionsTagsLazyQuery, useWorkflowDefinitionsTagsQuery, useWorkflowDefinitionsTagsSuspenseQuery, useWorkflowPinnedDataLazyQuery, useWorkflowPinnedDataQuery, useWorkflowPinnedDataSuspenseQuery, useWorkflowRunLazyQuery, useWorkflowRunQuery, useWorkflowRunSuspenseQuery, useWorkflowRunsLazyQuery, useWorkflowRunsQuery, useWorkflowRunsSuspenseQuery, useWorkflowVersionsLazyQuery, useWorkflowVersionsQuery, useWorkflowVersionsSuspenseQuery } from './chunk-ZC7XPBZN.js';
64
+ import { WorkflowGenerationDocument, GenerateWorkflowFromPromptDocument, CancelWorkflowGenerationDocument } from './chunk-JTQFBZTV.js';
65
+ export { AcquireWorkflowEditLeaseDocument, ActivateWorkflowDefinitionDocument, ActivateWorkflowVersionCheckedDocument, ActiveExecutionsDocument, ApplyWorkflowProposalDocument, ApproveWorkflowPromotionDocument, AvailableFluidgridsTagsDocument, BuildWorkflowCodeDocument, BulkAssignWorkflowsToProjectDocument, BulkDeleteWorkflowsDocument, BulkMoveWorkflowsToFolderDocument, CancelExecutionDocument, CancelWorkflowGenerationDocument, CancelWorkflowPromotionDocument, CancelWorkflowProposalDocument, ContinuousOptimisationSettingsDocument, ContinuousOptimisationSettingsFieldsFragmentDoc, CreateFluidgridsTagDocument, CreateWorkflowDefinitionDocument, CreateWorkflowFolderDocument, CreateWorkflowProjectDocument, CreateWorkflowTestCaseDocument, CreateWorkflowTestCaseFromRunDocument, CreateWorkflowVersionDocument, DashboardSummaryDocument, DataTablesTagsDocument, DeactivateWorkflowDefinitionDocument, DeleteWorkflowDefinitionDocument, DeleteWorkflowFolderDocument, DeleteWorkflowProjectDocument, DeleteWorkflowRolloutDocument, DeleteWorkflowTestCaseDocument, DeployWorkflowVersionToDevDocument, DismissOptimisationSuggestionDocument, DismissRunFailureClusterDocument, DuplicateWorkflowDocument, DurableHistoryCapsDocument, DurableParityRunFieldsDocument, DurableRunFieldsDocument, EventRegistrationsDocument, ExecuteStepDocument, ExecutionDetailDocument, ExecutionLogsDocument, ExecutionStatsDocument, ExecutionsListDocument, ExplainRunDocument, ExportWorkflowCodeDocument, FgRunOptimisationScanDocument, FgTriageFailedRunsDocument, FileDownloadUrlDocument, FluidgridsAvailableTagFieldsFragmentDoc, FluidgridsEntityTagsDocument, FluidgridsTagAssignmentFieldsFragmentDoc, GenerateWorkflowFromPromptDocument, ImportWorkflowDocument, ImportWorkflowTemplateDocument, LinkWorkflowGitRepositoryDocument, ListenForWebhookTestEventDocument, MoveWorkflowFolderDocument, NodeEndpointConfigDocument, NodeEndpointConfigsDocument, NodeManifestDocument, NodeSchemaIntrospectionDocument, NodeStatesDocument, NodeUsageStatusDocument, OptimisationSuggestionFieldsFragmentDoc, OptimisationSuggestionsDocument, PauseExecutionDocument, PinNodeDataDocument, PreviewScheduleDocument, ProposeOptimisationDocument, ProposeRunFixDocument, ProposeWorkflowChangeDocument, PushWorkflowToGitDocument, RegisterNodeDocument, RejectWorkflowPromotionDocument, RejectWorkflowProposalDocument, ReleaseWorkflowEditLeaseDocument, RemoveNodeFromWorkflowsDocument, RenameWorkflowFolderDocument, RenameWorkflowProjectDocument, ReplaceFluidgridsEntityTagsDocument, RequestWorkflowPromotionDocument, RestoreWorkflowFromGitDocument, RestoreWorkflowVersionDocument, ResumeExecutionDocument, RetryNodeDocument, RunCodeReplaceFieldsFragmentDoc, RunEventAppendedDocument, RunFailureClustersDocument, RunFailureTriageSettingsDocument, RunFromNodeDocument, RunFromNodeEligibilityDocument, RunLogAppendedDocument, RunLogLineFieldsFragmentDoc, RunLogsDocument, RunWorkflowTestsDocument, SearchFluidgridsTagsDocument, SetContinuousOptimisationEnabledDocument, SetRunFailureTriageEnabledDocument, SetWorkflowRolloutDocument, SetWorkflowRunVersioningOverrideDocument, SignalWorkflowRunDocument, SnoozeOptimisationSuggestionDocument, StopWebhookTestListenerDocument, TagFluidgridsEntityDocument, TakeOverWorkflowEditLeaseDocument, TerminateExecutionDocument, TerminateWorkflowRunDocument, TriggerWorkflowDocument, UnlinkWorkflowGitRepositoryDocument, UnpinNodeDataDocument, UntagFluidgridsEntityDocument, UpdateDurableHistoryCapsDocument, UpdateWorkflowDefinitionDocument, UpdateWorkflowEnvironmentPolicyDocument, UpdateWorkflowTestCaseDocument, UsageTimeSeriesDocument, WebhookTestListenerDocument, WorkflowAuthoringDocument, WorkflowCodeSourceDocument, WorkflowDefinitionDocument, WorkflowDefinitionsDocument, WorkflowDefinitionsTagsDocument, WorkflowEditLeaseDocument, WorkflowEditLeaseStatusDocument, WorkflowEnvironmentsDocument, WorkflowFoldersDocument, WorkflowGenerationDocument, WorkflowGenerationTemplatesDocument, WorkflowGitCommitsDocument, WorkflowGitDiffDocument, WorkflowGitPushesDocument, WorkflowGitRepositoryDocument, WorkflowPinnedDataDocument, WorkflowProjectsDocument, WorkflowPromotionRequestsDocument, WorkflowProposalDocument, WorkflowRolloutFieldsFragmentDoc, WorkflowRunDeterminismStatusDocument, WorkflowRunDocument, WorkflowRunEventFieldsFragmentDoc, WorkflowRunHistoryDocument, WorkflowRunMetadataDocument, WorkflowRunPendingDocument, WorkflowRunStackTraceDocument, WorkflowRunsCountDocument, WorkflowRunsDocument, WorkflowTestCaseFieldsFragmentDoc, WorkflowTestCaseResultFieldsFragmentDoc, WorkflowTestCasesDocument, WorkflowTestRunDocument, WorkflowTestRunFieldsFragmentDoc, WorkflowTestRunsDocument, WorkflowVersionDiffDocument, WorkflowVersionDrainageDocument, WorkflowVersioningDocument, WorkflowVersionsDocument, WorkspaceRunsQuotaDocument, useActivateWorkflowDefinitionMutation, useActiveExecutionsLazyQuery, useActiveExecutionsQuery, useActiveExecutionsSuspenseQuery, useAvailableFluidgridsTagsLazyQuery, useAvailableFluidgridsTagsQuery, useAvailableFluidgridsTagsSuspenseQuery, useCancelExecutionMutation, useCreateFluidgridsTagMutation, useCreateWorkflowDefinitionMutation, useCreateWorkflowVersionMutation, useDashboardSummaryLazyQuery, useDashboardSummaryQuery, useDashboardSummarySuspenseQuery, useDeactivateWorkflowDefinitionMutation, useDeleteWorkflowDefinitionMutation, useDuplicateWorkflowMutation, useEventRegistrationsLazyQuery, useEventRegistrationsQuery, useEventRegistrationsSuspenseQuery, useExecuteStepMutation, useExecutionDetailLazyQuery, useExecutionDetailQuery, useExecutionDetailSuspenseQuery, useExecutionLogsLazyQuery, useExecutionLogsQuery, useExecutionLogsSuspenseQuery, useExecutionStatsLazyQuery, useExecutionStatsQuery, useExecutionStatsSuspenseQuery, useExecutionsListLazyQuery, useExecutionsListQuery, useExecutionsListSuspenseQuery, useFluidgridsEntityTagsLazyQuery, useFluidgridsEntityTagsQuery, useFluidgridsEntityTagsSuspenseQuery, useImportWorkflowMutation, useImportWorkflowTemplateMutation, useNodeEndpointConfigLazyQuery, useNodeEndpointConfigQuery, useNodeEndpointConfigSuspenseQuery, useNodeEndpointConfigsLazyQuery, useNodeEndpointConfigsQuery, useNodeEndpointConfigsSuspenseQuery, useNodeManifestLazyQuery, useNodeManifestQuery, useNodeManifestSuspenseQuery, useNodeSchemaIntrospectionLazyQuery, useNodeSchemaIntrospectionQuery, useNodeSchemaIntrospectionSuspenseQuery, useNodeStatesLazyQuery, useNodeStatesQuery, useNodeStatesSuspenseQuery, useNodeUsageStatusLazyQuery, useNodeUsageStatusQuery, useNodeUsageStatusSuspenseQuery, usePauseExecutionMutation, usePinNodeDataMutation, usePreviewScheduleLazyQuery, usePreviewScheduleQuery, usePreviewScheduleSuspenseQuery, useRegisterNodeMutation, useRemoveNodeFromWorkflowsMutation, useReplaceFluidgridsEntityTagsMutation, useRestoreWorkflowVersionMutation, useResumeExecutionMutation, useRetryNodeMutation, useRunFromNodeEligibilityLazyQuery, useRunFromNodeEligibilityQuery, useRunFromNodeEligibilitySuspenseQuery, useRunFromNodeMutation, useRunLogAppendedSubscription, useRunLogsLazyQuery, useRunLogsQuery, useRunLogsSuspenseQuery, useSearchFluidgridsTagsLazyQuery, useSearchFluidgridsTagsQuery, useSearchFluidgridsTagsSuspenseQuery, useTagFluidgridsEntityMutation, useTerminateExecutionMutation, useTriggerWorkflowMutation, useUnpinNodeDataMutation, useUntagFluidgridsEntityMutation, useUpdateWorkflowDefinitionMutation, useUsageTimeSeriesLazyQuery, useUsageTimeSeriesQuery, useUsageTimeSeriesSuspenseQuery, useWorkflowDefinitionLazyQuery, useWorkflowDefinitionQuery, useWorkflowDefinitionSuspenseQuery, useWorkflowDefinitionsLazyQuery, useWorkflowDefinitionsQuery, useWorkflowDefinitionsSuspenseQuery, useWorkflowDefinitionsTagsLazyQuery, useWorkflowDefinitionsTagsQuery, useWorkflowDefinitionsTagsSuspenseQuery, useWorkflowPinnedDataLazyQuery, useWorkflowPinnedDataQuery, useWorkflowPinnedDataSuspenseQuery, useWorkflowRunLazyQuery, useWorkflowRunQuery, useWorkflowRunSuspenseQuery, useWorkflowRunsLazyQuery, useWorkflowRunsQuery, useWorkflowRunsSuspenseQuery, useWorkflowVersionsLazyQuery, useWorkflowVersionsQuery, useWorkflowVersionsSuspenseQuery } from './chunk-JTQFBZTV.js';
65
66
  import { useTr } from './chunk-UULVIT25.js';
66
67
  export { ENGLISH_FALLBACK_TRANSLATOR, FluidGridsTranslationProvider, useTr } from './chunk-UULVIT25.js';
67
68
  import { getFluidGridsClient, createFluidGridsClient } from './chunk-NTWG3CJX.js';
68
69
  export { createFluidGridsClient, getFluidGridsClient, getFluidGridsClientSafe, isFluidGridsClientReady, resetFluidGridsClient, setFluidGridsClient, waitForFluidGridsClient } from './chunk-NTWG3CJX.js';
69
70
  import * as React3 from 'react';
70
- import { lazy, Suspense, useState, useRef, useMemo, useCallback, useEffect } from 'react';
71
- import { Routes, Route, Navigate, useNavigate } from 'react-router';
71
+ import { lazy, memo, Suspense, useState, useRef, useMemo, useCallback, useEffect } from 'react';
72
+ import { Routes, Route, Navigate, useNavigate, useParams } from 'react-router';
72
73
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
73
74
  import { v4 } from 'uuid';
74
75
  import { toast } from 'sonner';
75
- import { ChevronRight, Check, Circle, Sparkles, Loader2, Square, Lightbulb, MessageCircleQuestion, RefreshCw, TriangleAlert, CheckCircle2, Pencil, Database, ArrowLeft, Plus, Table2, Search, ChevronDown, ChevronUp, Trash2, ArrowUpFromLine, ArrowDownToLine, ChevronLeft } from 'lucide-react';
76
+ import { ChevronRight, Check, Circle, Flag, Search, Calculator, ListTree, GitBranch, Play, Sparkles, Loader2, Square, Lightbulb, MessageCircleQuestion, RefreshCw, TriangleAlert, CheckCircle2, Pencil, Database, ArrowLeft, Plus, Table2, Scale, Trash2, ChevronDown, ChevronUp, ArrowUpFromLine, ArrowDownToLine, ChevronLeft, AlertTriangle, Save, FlaskConical, CircleSlash, XCircle } from 'lucide-react';
76
77
  import { Badge, Card, CardHeader, CardContent, Label, Textarea, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Button, Input, Tabs, TabsList, TabsTrigger, TabsContent, Table, TableHeader, TableRow, TableHead, TableBody, TableCell, Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, PagePurpose, NextSteps, CardTitle, IllustratedEmptyState, Switch, CardDescription } from '@burdenoff/fe-libs/ui';
77
78
  import { ErrorBoundary } from '@burdenoff/fe-libs/shared/components';
78
79
  import '@xyflow/react/dist/style.css';
@@ -80,6 +81,8 @@ import { Icon } from '@iconify/react';
80
81
  import { Button as Button$1 } from '@burdenoff/fe-libs/button';
81
82
  import { gql } from '@apollo/client';
82
83
  import { TagBadge } from '@burdenoff/fe-libs/tag';
84
+ import { MarkerType, Handle, Position, ReactFlowProvider, useReactFlow, useNodesState, useEdgesState, addEdge, ReactFlow, Background, Controls, MiniMap } from '@xyflow/react';
85
+ import { useTheme } from '@burdenoff/fe-libs/shared/hooks/shell';
83
86
  import * as TabsPrimitive from '@radix-ui/react-tabs';
84
87
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
85
88
  import * as SeparatorPrimitive from '@radix-ui/react-separator';
@@ -91,20 +94,20 @@ import { AgentToolError, defineAgentTool, assertNoUnsavedChanges } from '@burden
91
94
  import { z } from 'zod';
92
95
 
93
96
  var WorkflowsList2 = lazy(
94
- () => import('./WorkflowsList-R54WQMBJ.js').then((m) => ({ default: m.WorkflowsList }))
97
+ () => import('./WorkflowsList-NYSQEZWU.js').then((m) => ({ default: m.WorkflowsList }))
95
98
  );
96
99
  var WorkflowBuilder3 = lazy(
97
- () => import('./WorkflowBuilder-KY7WPG6S.js').then((m) => ({
100
+ () => import('./WorkflowBuilder-ZIXEU7DQ.js').then((m) => ({
98
101
  default: m.WorkflowBuilder
99
102
  }))
100
103
  );
101
104
  var ExecutionsListPage2 = lazy(
102
- () => import('./ExecutionsListPage-4JAHYMBY.js').then((m) => ({
105
+ () => import('./ExecutionsListPage-GTCSYSC6.js').then((m) => ({
103
106
  default: m.ExecutionsListPage
104
107
  }))
105
108
  );
106
109
  var ExecutionDetailPage2 = lazy(
107
- () => import('./ExecutionDetailPage-DSLBVHNF.js').then((m) => ({
110
+ () => import('./ExecutionDetailPage-XHII23QR.js').then((m) => ({
108
111
  default: m.ExecutionDetailPage
109
112
  }))
110
113
  );
@@ -5020,6 +5023,2580 @@ function DataTablesPage() {
5020
5023
  ] })
5021
5024
  );
5022
5025
  }
5026
+ var ISSUE_FIELDS = gql`
5027
+ fragment RuleIssueFields on RuleIssue {
5028
+ severity
5029
+ code
5030
+ message
5031
+ nodeId
5032
+ }
5033
+ `;
5034
+ var RULE_SET_FIELDS = gql`
5035
+ ${ISSUE_FIELDS}
5036
+ fragment RuleSetFields on RuleSet {
5037
+ id
5038
+ workspaceId
5039
+ name
5040
+ description
5041
+ definition
5042
+ sampleInput
5043
+ nodeCount
5044
+ version
5045
+ issues {
5046
+ ...RuleIssueFields
5047
+ }
5048
+ createdAt
5049
+ updatedAt
5050
+ createdBy
5051
+ updatedBy
5052
+ }
5053
+ `;
5054
+ var GET_RULE_SETS = gql`
5055
+ ${RULE_SET_FIELDS}
5056
+ query GetRuleSets($search: String, $limit: Int, $offset: Int) {
5057
+ ruleSets(search: $search, limit: $limit, offset: $offset) {
5058
+ ruleSets {
5059
+ ...RuleSetFields
5060
+ }
5061
+ total
5062
+ }
5063
+ }
5064
+ `;
5065
+ var GET_RULE_SET = gql`
5066
+ ${RULE_SET_FIELDS}
5067
+ query GetRuleSet($id: ID!) {
5068
+ ruleSet(id: $id) {
5069
+ ...RuleSetFields
5070
+ }
5071
+ }
5072
+ `;
5073
+ var GET_RULE_SET_TEMPLATES = gql`
5074
+ query GetRuleSetTemplates {
5075
+ ruleSetTemplates {
5076
+ id
5077
+ name
5078
+ description
5079
+ definition
5080
+ sampleInput
5081
+ }
5082
+ }
5083
+ `;
5084
+ var CREATE_RULE_SET = gql`
5085
+ ${RULE_SET_FIELDS}
5086
+ mutation CreateRuleSet($input: CreateRuleSetInput!) {
5087
+ createRuleSet(input: $input) {
5088
+ ...RuleSetFields
5089
+ }
5090
+ }
5091
+ `;
5092
+ var UPDATE_RULE_SET = gql`
5093
+ ${RULE_SET_FIELDS}
5094
+ mutation UpdateRuleSet($id: ID!, $input: UpdateRuleSetInput!) {
5095
+ updateRuleSet(id: $id, input: $input) {
5096
+ ...RuleSetFields
5097
+ }
5098
+ }
5099
+ `;
5100
+ var DELETE_RULE_SET = gql`
5101
+ mutation DeleteRuleSet($id: ID!) {
5102
+ deleteRuleSet(id: $id)
5103
+ }
5104
+ `;
5105
+ var TEST_RULE_SET = gql`
5106
+ ${ISSUE_FIELDS}
5107
+ mutation TestRuleSet($input: TestRuleSetInput!) {
5108
+ testRuleSet(input: $input) {
5109
+ status
5110
+ decision
5111
+ output
5112
+ variables
5113
+ path
5114
+ durationMs
5115
+ issues {
5116
+ ...RuleIssueFields
5117
+ }
5118
+ trace {
5119
+ index
5120
+ nodeId
5121
+ nodeType
5122
+ label
5123
+ outcome
5124
+ detail
5125
+ variables
5126
+ conditions {
5127
+ field
5128
+ operator
5129
+ expected
5130
+ actual
5131
+ passed
5132
+ }
5133
+ }
5134
+ }
5135
+ }
5136
+ `;
5137
+ function operationError2(error, fallback) {
5138
+ return new Error(describeOperationError(error, fallback));
5139
+ }
5140
+ var RULE_SET_LIST_LIMIT = 200;
5141
+ function useRuleSets(search) {
5142
+ const [ruleSets, setRuleSets] = useState([]);
5143
+ const [total, setTotal] = useState(0);
5144
+ const [loading, setLoading] = useState(true);
5145
+ const [error, setError] = useState(null);
5146
+ const latestRequest = useRef(0);
5147
+ const fetchRuleSets = useCallback(async () => {
5148
+ latestRequest.current += 1;
5149
+ const request = latestRequest.current;
5150
+ setLoading(true);
5151
+ setError(null);
5152
+ try {
5153
+ const result = throwIfResultError(
5154
+ await getFluidGridsClient().query({
5155
+ query: GET_RULE_SETS,
5156
+ variables: {
5157
+ search: search?.trim() || void 0,
5158
+ limit: RULE_SET_LIST_LIMIT
5159
+ },
5160
+ fetchPolicy: "network-only"
5161
+ })
5162
+ );
5163
+ if (request !== latestRequest.current) return;
5164
+ setRuleSets(result.data?.ruleSets.ruleSets ?? []);
5165
+ setTotal(result.data?.ruleSets.total ?? 0);
5166
+ } catch (err) {
5167
+ if (request !== latestRequest.current) return;
5168
+ setError(operationError2(err, "Failed to load rule sets"));
5169
+ } finally {
5170
+ setLoading(
5171
+ (current) => request === latestRequest.current ? false : current
5172
+ );
5173
+ }
5174
+ }, [search]);
5175
+ useEffect(() => {
5176
+ void fetchRuleSets();
5177
+ }, [fetchRuleSets]);
5178
+ return { ruleSets, total, loading, error, refetch: fetchRuleSets };
5179
+ }
5180
+ function useRuleSet(id) {
5181
+ const [ruleSet, setRuleSet] = useState(null);
5182
+ const [loading, setLoading] = useState(Boolean(id));
5183
+ const [error, setError] = useState(null);
5184
+ const fetchRuleSet = useCallback(async () => {
5185
+ if (!id) return;
5186
+ setLoading(true);
5187
+ setError(null);
5188
+ try {
5189
+ const result = throwIfResultError(
5190
+ await getFluidGridsClient().query({
5191
+ query: GET_RULE_SET,
5192
+ variables: { id },
5193
+ fetchPolicy: "network-only"
5194
+ })
5195
+ );
5196
+ setRuleSet(result.data?.ruleSet ?? null);
5197
+ } catch (err) {
5198
+ setError(operationError2(err, "Failed to load the rule set"));
5199
+ } finally {
5200
+ setLoading(false);
5201
+ }
5202
+ }, [id]);
5203
+ useEffect(() => {
5204
+ void fetchRuleSet();
5205
+ }, [fetchRuleSet]);
5206
+ return { ruleSet, setRuleSet, loading, error, refetch: fetchRuleSet };
5207
+ }
5208
+ function useRuleSetTemplates() {
5209
+ const [templates, setTemplates] = useState([]);
5210
+ const [loading, setLoading] = useState(true);
5211
+ useEffect(() => {
5212
+ let active = true;
5213
+ getFluidGridsClient().query({
5214
+ query: GET_RULE_SET_TEMPLATES,
5215
+ fetchPolicy: "cache-first"
5216
+ }).then((result) => {
5217
+ if (active) setTemplates(result.data?.ruleSetTemplates ?? []);
5218
+ }).catch(() => {
5219
+ if (active) setTemplates([]);
5220
+ }).finally(() => {
5221
+ if (active) setLoading(false);
5222
+ });
5223
+ return () => {
5224
+ active = false;
5225
+ };
5226
+ }, []);
5227
+ return { templates, loading };
5228
+ }
5229
+ function useRuleSetMutations() {
5230
+ const createRuleSet = useCallback(async (input) => {
5231
+ try {
5232
+ const result = throwIfResultError(
5233
+ await getFluidGridsClient().mutate({
5234
+ mutation: CREATE_RULE_SET,
5235
+ variables: { input }
5236
+ })
5237
+ );
5238
+ const created = result.data?.createRuleSet;
5239
+ if (!created) throw new Error("Failed to create the rule set");
5240
+ return created;
5241
+ } catch (err) {
5242
+ throw operationError2(err, "Failed to create the rule set");
5243
+ }
5244
+ }, []);
5245
+ const updateRuleSet = useCallback(
5246
+ async (id, input) => {
5247
+ try {
5248
+ const result = throwIfResultError(
5249
+ await getFluidGridsClient().mutate({
5250
+ mutation: UPDATE_RULE_SET,
5251
+ variables: { id, input }
5252
+ })
5253
+ );
5254
+ const updated = result.data?.updateRuleSet;
5255
+ if (!updated) throw new Error("Failed to save the rule set");
5256
+ return updated;
5257
+ } catch (err) {
5258
+ throw operationError2(err, "Failed to save the rule set");
5259
+ }
5260
+ },
5261
+ []
5262
+ );
5263
+ const deleteRuleSet = useCallback(async (id) => {
5264
+ try {
5265
+ const result = throwIfResultError(
5266
+ await getFluidGridsClient().mutate({
5267
+ mutation: DELETE_RULE_SET,
5268
+ variables: { id }
5269
+ })
5270
+ );
5271
+ return result.data?.deleteRuleSet === true;
5272
+ } catch (err) {
5273
+ throw operationError2(err, "Failed to delete the rule set");
5274
+ }
5275
+ }, []);
5276
+ const testRuleSet = useCallback(
5277
+ async (input) => {
5278
+ try {
5279
+ const result = throwIfResultError(
5280
+ await getFluidGridsClient().mutate({
5281
+ mutation: TEST_RULE_SET,
5282
+ variables: { input }
5283
+ })
5284
+ );
5285
+ const evaluation = result.data?.testRuleSet;
5286
+ if (!evaluation) throw new Error("Failed to test the rule set");
5287
+ return evaluation;
5288
+ } catch (err) {
5289
+ throw operationError2(err, "Failed to test the rule set");
5290
+ }
5291
+ },
5292
+ []
5293
+ );
5294
+ return { createRuleSet, updateRuleSet, deleteRuleSet, testRuleSet };
5295
+ }
5296
+ function CreateRuleSetDialog({
5297
+ open,
5298
+ onOpenChange,
5299
+ onCreated
5300
+ }) {
5301
+ const tr = useTr();
5302
+ const { templates } = useRuleSetTemplates();
5303
+ const { createRuleSet } = useRuleSetMutations();
5304
+ const [name, setName] = useState("");
5305
+ const [description, setDescription] = useState("");
5306
+ const [templateId, setTemplateId] = useState("loan-approval");
5307
+ const [saving, setSaving] = useState(false);
5308
+ const submit = async (event) => {
5309
+ event.preventDefault();
5310
+ const template = templates.find((item) => item.id === templateId);
5311
+ const finalName = name.trim() || template?.name || "";
5312
+ if (!finalName) {
5313
+ toast.error(
5314
+ tr("fluidgrids.rules.nameRequired", "Give the rule set a name")
5315
+ );
5316
+ return;
5317
+ }
5318
+ setSaving(true);
5319
+ try {
5320
+ const created = await createRuleSet({
5321
+ name: finalName,
5322
+ description: description.trim() || template?.description || void 0,
5323
+ ...templateId ? { templateId } : {}
5324
+ });
5325
+ onCreated(created);
5326
+ setName("");
5327
+ setDescription("");
5328
+ } catch (err) {
5329
+ toast.error(
5330
+ err instanceof Error ? err.message : tr(
5331
+ "fluidgrids.rules.createFailed",
5332
+ "Failed to create the rule set"
5333
+ )
5334
+ );
5335
+ } finally {
5336
+ setSaving(false);
5337
+ }
5338
+ };
5339
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-lg", children: [
5340
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(DialogTitle, { children: tr("fluidgrids.rules.newRuleSet", "New rule set") }) }),
5341
+ /* @__PURE__ */ jsxs(
5342
+ "form",
5343
+ {
5344
+ className: "flex flex-col gap-4",
5345
+ onSubmit: (event) => void submit(event),
5346
+ children: [
5347
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
5348
+ /* @__PURE__ */ jsx(Label, { children: tr("fluidgrids.rules.startFrom", "Start from") }),
5349
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
5350
+ templates.map((template) => /* @__PURE__ */ jsxs(
5351
+ "label",
5352
+ {
5353
+ className: `flex cursor-pointer gap-3 rounded-md border p-3 ${templateId === template.id ? "border-primary bg-primary/5" : "border-border-secondary"}`,
5354
+ children: [
5355
+ /* @__PURE__ */ jsx(
5356
+ "input",
5357
+ {
5358
+ type: "radio",
5359
+ name: "rule-template",
5360
+ value: template.id,
5361
+ checked: templateId === template.id,
5362
+ onChange: () => setTemplateId(template.id),
5363
+ className: "mt-1"
5364
+ }
5365
+ ),
5366
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-col", children: [
5367
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-text-primary", children: template.name }),
5368
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: template.description })
5369
+ ] })
5370
+ ]
5371
+ },
5372
+ template.id
5373
+ )),
5374
+ /* @__PURE__ */ jsxs(
5375
+ "label",
5376
+ {
5377
+ className: `flex cursor-pointer gap-3 rounded-md border p-3 ${templateId === "" ? "border-primary bg-primary/5" : "border-border-secondary"}`,
5378
+ children: [
5379
+ /* @__PURE__ */ jsx(
5380
+ "input",
5381
+ {
5382
+ type: "radio",
5383
+ name: "rule-template",
5384
+ value: "",
5385
+ checked: templateId === "",
5386
+ onChange: () => setTemplateId(""),
5387
+ className: "mt-1"
5388
+ }
5389
+ ),
5390
+ /* @__PURE__ */ jsxs("span", { className: "flex flex-col", children: [
5391
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-text-primary", children: tr("fluidgrids.rules.emptyRuleSet", "Empty canvas") }),
5392
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-text-secondary", children: tr(
5393
+ "fluidgrids.rules.emptyRuleSetHint",
5394
+ "No blocks; build the decision tree from scratch."
5395
+ ) })
5396
+ ] })
5397
+ ]
5398
+ }
5399
+ )
5400
+ ] })
5401
+ ] }),
5402
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
5403
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-set-name", children: tr("fluidgrids.rules.name", "Name") }),
5404
+ /* @__PURE__ */ jsx(
5405
+ Input,
5406
+ {
5407
+ id: "rule-set-name",
5408
+ value: name,
5409
+ maxLength: 200,
5410
+ placeholder: templates.find((item) => item.id === templateId)?.name ?? tr("fluidgrids.rules.namePlaceholder", "Loan approval decision"),
5411
+ onChange: (event) => setName(event.target.value)
5412
+ }
5413
+ )
5414
+ ] }),
5415
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
5416
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-set-description", children: tr("fluidgrids.rules.description", "Description") }),
5417
+ /* @__PURE__ */ jsx(
5418
+ Textarea,
5419
+ {
5420
+ id: "rule-set-description",
5421
+ rows: 2,
5422
+ maxLength: 2e3,
5423
+ value: description,
5424
+ onChange: (event) => setDescription(event.target.value)
5425
+ }
5426
+ )
5427
+ ] }),
5428
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
5429
+ /* @__PURE__ */ jsx(
5430
+ Button$1,
5431
+ {
5432
+ type: "button",
5433
+ variant: "outline",
5434
+ onClick: () => onOpenChange(false),
5435
+ children: tr("fluidgrids.rules.cancel", "Cancel")
5436
+ }
5437
+ ),
5438
+ /* @__PURE__ */ jsx(Button$1, { type: "submit", disabled: saving, children: saving ? tr("fluidgrids.rules.creating", "Creating\u2026") : tr("fluidgrids.rules.create", "Create and open") })
5439
+ ] })
5440
+ ]
5441
+ }
5442
+ )
5443
+ ] }) });
5444
+ }
5445
+ function RuleSetsPage() {
5446
+ const tr = useTr();
5447
+ const navigate = useNavigate();
5448
+ const [searchInput, setSearchInput] = useState("");
5449
+ const [search, setSearch] = useState("");
5450
+ const { ruleSets, total, loading, error, refetch } = useRuleSets(search);
5451
+ const { deleteRuleSet } = useRuleSetMutations();
5452
+ const [createOpen, setCreateOpen] = useState(false);
5453
+ const open = (ruleSet) => navigate(ruleSet.id);
5454
+ const remove = async (ruleSet) => {
5455
+ if (!window.confirm(
5456
+ tr(
5457
+ "fluidgrids.rules.confirmDelete",
5458
+ 'Delete the rule set "{{name}}"?',
5459
+ {
5460
+ name: ruleSet.name
5461
+ }
5462
+ )
5463
+ )) {
5464
+ return;
5465
+ }
5466
+ try {
5467
+ await deleteRuleSet(ruleSet.id);
5468
+ toast.success(tr("fluidgrids.rules.deleted", "Rule set deleted"));
5469
+ void refetch();
5470
+ } catch (err) {
5471
+ toast.error(
5472
+ err instanceof Error ? err.message : tr(
5473
+ "fluidgrids.rules.deleteFailed",
5474
+ "Failed to delete the rule set"
5475
+ )
5476
+ );
5477
+ }
5478
+ };
5479
+ const newButton = /* @__PURE__ */ jsx(
5480
+ SdkPermissionButton,
5481
+ {
5482
+ permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_CREATE,
5483
+ deniedTooltip: tr(
5484
+ "fluidgrids.rules.createDenied",
5485
+ "You don't have permission to create rule sets"
5486
+ ),
5487
+ children: /* @__PURE__ */ jsxs(Button$1, { onClick: () => setCreateOpen(true), "data-testid": "rule-set-new", children: [
5488
+ /* @__PURE__ */ jsx(Plus, { className: "mr-2 size-4", "aria-hidden": "true" }),
5489
+ tr("fluidgrids.rules.newRuleSet", "New rule set")
5490
+ ] })
5491
+ }
5492
+ );
5493
+ return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-background-primary p-4 pb-24 sm:p-6 sm:pb-24", children: [
5494
+ /* @__PURE__ */ jsxs("div", { className: "mx-auto flex max-w-[1200px] flex-col gap-5", children: [
5495
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [
5496
+ /* @__PURE__ */ jsxs("div", { children: [
5497
+ /* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center gap-2 text-sm text-text-secondary", children: [
5498
+ /* @__PURE__ */ jsx(Scale, { className: "size-4", "aria-hidden": "true" }),
5499
+ tr("fluidgrids.rules.eyebrow", "Decision logic")
5500
+ ] }),
5501
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold text-text-primary sm:text-3xl", children: tr("fluidgrids.rules.pageTitle", "Rule Builder") }),
5502
+ /* @__PURE__ */ jsx(PagePurpose, { icon: /* @__PURE__ */ jsx(Scale, { className: "size-4", "aria-hidden": "true" }), children: tr(
5503
+ "fluidgrids.rules.pageSubtitle",
5504
+ "Author decision trees visually from conditions, scoring rules, lookups and decisions, then test them against sample input and see every step of the evaluation."
5505
+ ) })
5506
+ ] }),
5507
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
5508
+ /* @__PURE__ */ jsxs(Button$1, { variant: "outline", onClick: () => navigate("../list"), children: [
5509
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2 size-4", "aria-hidden": "true" }),
5510
+ tr("fluidgrids.rules.backToWorkflows", "Back to Workflows")
5511
+ ] }),
5512
+ newButton
5513
+ ] })
5514
+ ] }),
5515
+ /* @__PURE__ */ jsxs(
5516
+ "form",
5517
+ {
5518
+ className: "flex max-w-md gap-2",
5519
+ onSubmit: (event) => {
5520
+ event.preventDefault();
5521
+ setSearch(searchInput);
5522
+ },
5523
+ children: [
5524
+ /* @__PURE__ */ jsxs("div", { className: "relative min-w-0 flex-1", children: [
5525
+ /* @__PURE__ */ jsx(
5526
+ Search,
5527
+ {
5528
+ className: "pointer-events-none absolute left-2.5 top-2.5 size-4 text-text-secondary",
5529
+ "aria-hidden": "true"
5530
+ }
5531
+ ),
5532
+ /* @__PURE__ */ jsx(
5533
+ Input,
5534
+ {
5535
+ className: "pl-8",
5536
+ value: searchInput,
5537
+ onChange: (event) => setSearchInput(event.target.value),
5538
+ placeholder: tr("fluidgrids.rules.search", "Search rule sets"),
5539
+ "aria-label": tr("fluidgrids.rules.search", "Search rule sets")
5540
+ }
5541
+ )
5542
+ ] }),
5543
+ /* @__PURE__ */ jsx(Button$1, { type: "submit", variant: "outline", children: tr("fluidgrids.rules.searchAction", "Search") })
5544
+ ]
5545
+ }
5546
+ ),
5547
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm text-status-error", role: "alert", children: error.message }),
5548
+ loading && ruleSets.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary", children: tr("fluidgrids.rules.loading", "Loading rule sets\u2026") }),
5549
+ !loading && !error && ruleSets.length === 0 && /* @__PURE__ */ jsx(
5550
+ IllustratedEmptyState,
5551
+ {
5552
+ className: "py-10",
5553
+ illustration: "onboarding",
5554
+ title: search ? tr(
5555
+ "fluidgrids.rules.noMatches",
5556
+ "No rule sets match your search"
5557
+ ) : tr("fluidgrids.rules.empty", "Build your first rule set"),
5558
+ description: tr(
5559
+ "fluidgrids.rules.emptyHint",
5560
+ "Start from the loan approval example or an empty canvas."
5561
+ ),
5562
+ action: search ? void 0 : newButton
5563
+ }
5564
+ ),
5565
+ ruleSets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
5566
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-text-secondary", children: tr("fluidgrids.rules.count", "{{count}} rule sets", {
5567
+ count: total
5568
+ }) }),
5569
+ /* @__PURE__ */ jsx("div", { className: "grid gap-3 md:grid-cols-2", children: ruleSets.map((ruleSet) => {
5570
+ const errors = ruleSet.issues.filter(
5571
+ (issue) => issue.severity === "ERROR"
5572
+ ).length;
5573
+ return /* @__PURE__ */ jsx(
5574
+ Card,
5575
+ {
5576
+ className: "border-border-secondary transition-colors hover:border-primary/50",
5577
+ "data-testid": "rule-set-card",
5578
+ children: /* @__PURE__ */ jsxs(CardContent, { className: "flex items-start gap-3 p-4", children: [
5579
+ /* @__PURE__ */ jsxs(
5580
+ "button",
5581
+ {
5582
+ type: "button",
5583
+ className: "flex min-w-0 flex-1 flex-col text-left",
5584
+ onClick: () => open(ruleSet),
5585
+ children: [
5586
+ /* @__PURE__ */ jsx("span", { className: "truncate font-semibold text-text-primary", children: ruleSet.name }),
5587
+ ruleSet.description && /* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-sm text-text-secondary", children: ruleSet.description }),
5588
+ /* @__PURE__ */ jsxs("span", { className: "mt-2 flex flex-wrap items-center gap-2 text-xs text-text-secondary", children: [
5589
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", children: tr(
5590
+ "fluidgrids.rules.blockCount",
5591
+ "{{count}} blocks",
5592
+ {
5593
+ count: ruleSet.nodeCount
5594
+ }
5595
+ ) }),
5596
+ /* @__PURE__ */ jsxs("span", { children: [
5597
+ "v",
5598
+ ruleSet.version
5599
+ ] }),
5600
+ /* @__PURE__ */ jsx("span", { children: tr(
5601
+ "fluidgrids.rules.updatedAt",
5602
+ "Updated {{date}}",
5603
+ {
5604
+ date: new Date(
5605
+ ruleSet.updatedAt
5606
+ ).toLocaleString()
5607
+ }
5608
+ ) }),
5609
+ errors > 0 && /* @__PURE__ */ jsx("span", { className: "text-status-error", children: tr(
5610
+ "fluidgrids.rules.needsAttention",
5611
+ "Needs attention"
5612
+ ) })
5613
+ ] })
5614
+ ]
5615
+ }
5616
+ ),
5617
+ /* @__PURE__ */ jsx(
5618
+ SdkPermissionButton,
5619
+ {
5620
+ permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_DELETE,
5621
+ deniedTooltip: tr(
5622
+ "fluidgrids.rules.deleteDenied",
5623
+ "You don't have permission to delete rule sets"
5624
+ ),
5625
+ children: /* @__PURE__ */ jsx(
5626
+ Button$1,
5627
+ {
5628
+ variant: "ghost",
5629
+ size: "sm",
5630
+ "aria-label": tr("fluidgrids.rules.delete", "Delete"),
5631
+ onClick: () => void remove(ruleSet),
5632
+ children: /* @__PURE__ */ jsx(Trash2, { className: "size-4", "aria-hidden": "true" })
5633
+ }
5634
+ )
5635
+ }
5636
+ )
5637
+ ] })
5638
+ },
5639
+ ruleSet.id
5640
+ );
5641
+ }) })
5642
+ ] })
5643
+ ] }),
5644
+ /* @__PURE__ */ jsx(
5645
+ CreateRuleSetDialog,
5646
+ {
5647
+ open: createOpen,
5648
+ onOpenChange: setCreateOpen,
5649
+ onCreated: (ruleSet) => {
5650
+ setCreateOpen(false);
5651
+ toast.success(tr("fluidgrids.rules.created", "Rule set created"));
5652
+ open(ruleSet);
5653
+ }
5654
+ }
5655
+ )
5656
+ ] });
5657
+ }
5658
+ var RULE_BLOCK_STYLES = {
5659
+ CONDITION: {
5660
+ icon: GitBranch,
5661
+ accent: "border-status-info",
5662
+ chip: "bg-status-info/10 text-status-info"
5663
+ },
5664
+ COMPLEX: {
5665
+ icon: ListTree,
5666
+ accent: "border-primary",
5667
+ chip: "bg-primary/10 text-primary"
5668
+ },
5669
+ SCORING: {
5670
+ icon: Calculator,
5671
+ accent: "border-status-warning",
5672
+ chip: "bg-status-warning/10 text-status-warning"
5673
+ },
5674
+ LOOKUP: {
5675
+ icon: Search,
5676
+ accent: "border-accent",
5677
+ chip: "bg-accent/10 text-accent"
5678
+ },
5679
+ DECISION: {
5680
+ icon: Flag,
5681
+ accent: "border-status-success",
5682
+ chip: "bg-status-success/10 text-status-success"
5683
+ }
5684
+ };
5685
+ var RULE_BLOCK_DRAG_MIME = "application/x-fluidgrids-rule-block";
5686
+ function ruleIssueKey(issue) {
5687
+ return `${issue.severity}:${issue.code}:${issue.nodeId ?? ""}:${issue.message}`;
5688
+ }
5689
+
5690
+ // src/modules/rule-builder/lib/rule-graph.ts
5691
+ var RULE_NODE_TYPES = [
5692
+ "CONDITION",
5693
+ "COMPLEX",
5694
+ "SCORING",
5695
+ "LOOKUP",
5696
+ "DECISION"
5697
+ ];
5698
+ var RULE_OPERATORS = [
5699
+ "EQ",
5700
+ "NEQ",
5701
+ "GT",
5702
+ "GTE",
5703
+ "LT",
5704
+ "LTE",
5705
+ "BETWEEN",
5706
+ "IN",
5707
+ "NOT_IN",
5708
+ "CONTAINS",
5709
+ "NOT_CONTAINS",
5710
+ "STARTS_WITH",
5711
+ "ENDS_WITH",
5712
+ "EXISTS",
5713
+ "NOT_EXISTS",
5714
+ "IS_TRUE",
5715
+ "IS_FALSE"
5716
+ ];
5717
+ var UNARY_OPERATORS = /* @__PURE__ */ new Set([
5718
+ "EXISTS",
5719
+ "NOT_EXISTS",
5720
+ "IS_TRUE",
5721
+ "IS_FALSE"
5722
+ ]);
5723
+ function configOf(_type, config2) {
5724
+ return config2;
5725
+ }
5726
+ function isPlainObject(value) {
5727
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5728
+ }
5729
+ function isBranching(type) {
5730
+ return type === "CONDITION" || type === "COMPLEX";
5731
+ }
5732
+ function branchesOf(type) {
5733
+ if (type === "DECISION") return [];
5734
+ return isBranching(type) ? ["TRUE", "FALSE"] : ["NEXT"];
5735
+ }
5736
+ function defaultConfig(type) {
5737
+ switch (type) {
5738
+ case "CONDITION":
5739
+ return { condition: { field: "", operator: "EQ", value: "" } };
5740
+ case "COMPLEX":
5741
+ return {
5742
+ combinator: "ALL",
5743
+ conditions: [{ field: "", operator: "EQ", value: "" }]
5744
+ };
5745
+ case "SCORING":
5746
+ return { variable: "score", base: 0, rules: [] };
5747
+ case "LOOKUP":
5748
+ return {
5749
+ key: "",
5750
+ variable: "result",
5751
+ source: { kind: "INLINE", entries: [] },
5752
+ defaultValue: null
5753
+ };
5754
+ case "DECISION":
5755
+ return { outcome: "APPROVED", output: {} };
5756
+ }
5757
+ }
5758
+ var DEFAULT_LABELS = {
5759
+ CONDITION: "Condition",
5760
+ COMPLEX: "Complex logic",
5761
+ SCORING: "Scoring rule",
5762
+ LOOKUP: "Lookup",
5763
+ DECISION: "Decision"
5764
+ };
5765
+ function nextNodeId(type, existing) {
5766
+ const taken = new Set(existing);
5767
+ const prefix = type.toLowerCase();
5768
+ for (let index = 1; ; index++) {
5769
+ const id = `${prefix}-${index}`;
5770
+ if (!taken.has(id)) return id;
5771
+ }
5772
+ }
5773
+ function createRuleNode(type, position, existingIds, label = DEFAULT_LABELS[type]) {
5774
+ return {
5775
+ id: nextNodeId(type, existingIds),
5776
+ type,
5777
+ label,
5778
+ position,
5779
+ config: defaultConfig(type)
5780
+ };
5781
+ }
5782
+ function readNode(value) {
5783
+ if (!isPlainObject(value)) return null;
5784
+ const type = value["type"];
5785
+ const id = value["id"];
5786
+ if (typeof id !== "string" || typeof type !== "string" || !RULE_NODE_TYPES.includes(type)) {
5787
+ return null;
5788
+ }
5789
+ const ruleType = type;
5790
+ const position = isPlainObject(value["position"]) ? value["position"] : {};
5791
+ const x = Number(position["x"]);
5792
+ const y = Number(position["y"]);
5793
+ const config2 = isPlainObject(value["config"]) ? {
5794
+ ...defaultConfig(ruleType),
5795
+ ...value["config"]
5796
+ } : defaultConfig(ruleType);
5797
+ return {
5798
+ id,
5799
+ type: ruleType,
5800
+ label: typeof value["label"] === "string" ? value["label"] : "",
5801
+ position: { x: Number.isFinite(x) ? x : 0, y: Number.isFinite(y) ? y : 0 },
5802
+ config: config2
5803
+ };
5804
+ }
5805
+ function readDefinition(value) {
5806
+ if (!isPlainObject(value)) return { startNodeId: null, nodes: [], edges: [] };
5807
+ const nodes = (Array.isArray(value["nodes"]) ? value["nodes"] : []).map(readNode).filter((node) => node !== null);
5808
+ const ids = new Set(nodes.map((node) => node.id));
5809
+ const edges = (Array.isArray(value["edges"]) ? value["edges"] : []).filter(isPlainObject).map((edge, index) => ({
5810
+ id: typeof edge["id"] === "string" ? edge["id"] : `edge-${index + 1}`,
5811
+ source: String(edge["source"] ?? ""),
5812
+ target: String(edge["target"] ?? ""),
5813
+ branch: branchFromHandle(
5814
+ typeof edge["branch"] === "string" ? edge["branch"] : null
5815
+ )
5816
+ })).filter((edge) => ids.has(edge.source) && ids.has(edge.target));
5817
+ const start = value["startNodeId"];
5818
+ return {
5819
+ startNodeId: typeof start === "string" && ids.has(start) ? start : null,
5820
+ nodes,
5821
+ edges
5822
+ };
5823
+ }
5824
+ function resolveStartNodeId(definition) {
5825
+ if (definition.startNodeId) return definition.startNodeId;
5826
+ const targets = new Set(definition.edges.map((edge) => edge.target));
5827
+ const roots = definition.nodes.filter((node) => !targets.has(node.id));
5828
+ return roots.length === 1 ? roots[0]?.id ?? null : null;
5829
+ }
5830
+ function toFlow(definition) {
5831
+ const start = resolveStartNodeId(definition);
5832
+ return {
5833
+ nodes: definition.nodes.map((node) => ({
5834
+ id: node.id,
5835
+ type: "rule",
5836
+ position: node.position,
5837
+ data: {
5838
+ ruleType: node.type,
5839
+ label: node.label,
5840
+ config: node.config,
5841
+ isStart: node.id === start
5842
+ }
5843
+ })),
5844
+ edges: definition.edges.map((edge) => toFlowEdge(edge))
5845
+ };
5846
+ }
5847
+ function toFlowEdge(edge) {
5848
+ return {
5849
+ id: edge.id,
5850
+ source: edge.source,
5851
+ target: edge.target,
5852
+ sourceHandle: edge.branch,
5853
+ label: edge.branch === "NEXT" ? void 0 : edge.branch,
5854
+ data: { branch: edge.branch }
5855
+ };
5856
+ }
5857
+ function fromFlow(nodes, edges, startNodeId) {
5858
+ const ids = new Set(nodes.map((node) => node.id));
5859
+ return {
5860
+ startNodeId: startNodeId && ids.has(startNodeId) ? startNodeId : null,
5861
+ nodes: nodes.map((node) => ({
5862
+ id: node.id,
5863
+ type: node.data.ruleType,
5864
+ label: node.data.label,
5865
+ position: {
5866
+ x: Math.round(node.position.x),
5867
+ y: Math.round(node.position.y)
5868
+ },
5869
+ config: node.data.config
5870
+ })),
5871
+ edges: edges.filter((edge) => ids.has(edge.source) && ids.has(edge.target)).map((edge) => ({
5872
+ id: edge.id,
5873
+ source: edge.source,
5874
+ target: edge.target,
5875
+ branch: edge.data?.branch ?? branchFromHandle(edge.sourceHandle)
5876
+ }))
5877
+ };
5878
+ }
5879
+ function branchFromHandle(handle) {
5880
+ return handle === "TRUE" || handle === "FALSE" ? handle : "NEXT";
5881
+ }
5882
+ function canConnect(edges, source, target, handle) {
5883
+ if (!source || !target || source === target) return false;
5884
+ const branch = branchFromHandle(handle);
5885
+ return !edges.some(
5886
+ (edge) => edge.source === source && (edge.data?.branch ?? branchFromHandle(edge.sourceHandle)) === branch
5887
+ );
5888
+ }
5889
+ function nextEdgeId(edges) {
5890
+ const taken = new Set(edges.map((edge) => edge.id));
5891
+ for (let index = edges.length + 1; ; index++) {
5892
+ const id = `edge-${index}`;
5893
+ if (!taken.has(id)) return id;
5894
+ }
5895
+ }
5896
+ function parseValueText(text) {
5897
+ const trimmed = text.trim();
5898
+ if (trimmed === "") return "";
5899
+ try {
5900
+ return JSON.parse(trimmed);
5901
+ } catch {
5902
+ return text;
5903
+ }
5904
+ }
5905
+ function formatValueText(value) {
5906
+ if (value === void 0 || value === null) return "";
5907
+ if (typeof value === "string") {
5908
+ return parseValueText(value) === value ? value : JSON.stringify(value);
5909
+ }
5910
+ return JSON.stringify(value);
5911
+ }
5912
+ function parseJsonText(text) {
5913
+ try {
5914
+ return { ok: true, value: JSON.parse(text) };
5915
+ } catch (error) {
5916
+ return {
5917
+ ok: false,
5918
+ error: error instanceof Error ? error.message : "Invalid JSON"
5919
+ };
5920
+ }
5921
+ }
5922
+
5923
+ // src/modules/rule-builder/lib/rule-labels.ts
5924
+ function ruleBlockTypeLabel(tr, type) {
5925
+ switch (type) {
5926
+ case "CONDITION":
5927
+ return tr("fluidgrids.rules.blockType.CONDITION", "Condition");
5928
+ case "COMPLEX":
5929
+ return tr("fluidgrids.rules.blockType.COMPLEX", "Complex logic");
5930
+ case "SCORING":
5931
+ return tr("fluidgrids.rules.blockType.SCORING", "Scoring rule");
5932
+ case "LOOKUP":
5933
+ return tr("fluidgrids.rules.blockType.LOOKUP", "Lookup");
5934
+ case "DECISION":
5935
+ return tr("fluidgrids.rules.blockType.DECISION", "Decision");
5936
+ }
5937
+ }
5938
+ function operatorLabel(tr, operator) {
5939
+ switch (operator) {
5940
+ case "EQ":
5941
+ return "=";
5942
+ case "NEQ":
5943
+ return "\u2260";
5944
+ case "GT":
5945
+ return ">";
5946
+ case "GTE":
5947
+ return "\u2265";
5948
+ case "LT":
5949
+ return "<";
5950
+ case "LTE":
5951
+ return "\u2264";
5952
+ case "BETWEEN":
5953
+ return tr("fluidgrids.rules.operator.BETWEEN", "between");
5954
+ case "IN":
5955
+ return tr("fluidgrids.rules.operator.IN", "in");
5956
+ case "NOT_IN":
5957
+ return tr("fluidgrids.rules.operator.NOT_IN", "not in");
5958
+ case "CONTAINS":
5959
+ return tr("fluidgrids.rules.operator.CONTAINS", "contains");
5960
+ case "NOT_CONTAINS":
5961
+ return tr("fluidgrids.rules.operator.NOT_CONTAINS", "does not contain");
5962
+ case "STARTS_WITH":
5963
+ return tr("fluidgrids.rules.operator.STARTS_WITH", "starts with");
5964
+ case "ENDS_WITH":
5965
+ return tr("fluidgrids.rules.operator.ENDS_WITH", "ends with");
5966
+ case "EXISTS":
5967
+ return tr("fluidgrids.rules.operator.EXISTS", "exists");
5968
+ case "NOT_EXISTS":
5969
+ return tr("fluidgrids.rules.operator.NOT_EXISTS", "is missing");
5970
+ case "IS_TRUE":
5971
+ return tr("fluidgrids.rules.operator.IS_TRUE", "is true");
5972
+ case "IS_FALSE":
5973
+ return tr("fluidgrids.rules.operator.IS_FALSE", "is false");
5974
+ default:
5975
+ return operator;
5976
+ }
5977
+ }
5978
+ function describeCondition(tr, condition) {
5979
+ const field = condition.field || "\u2026";
5980
+ const operator = operatorLabel(tr, condition.operator);
5981
+ if (UNARY_OPERATORS.has(condition.operator)) return `${field} ${operator}`;
5982
+ const value = isPlainObject(condition.value) ? typeof condition.value["$ref"] === "string" ? condition.value["$ref"] : JSON.stringify(condition.value) : formatValueText(condition.value) || "\u2026";
5983
+ return `${field} ${operator} ${value}`;
5984
+ }
5985
+ function summarizeNode(tr, type, config2) {
5986
+ switch (type) {
5987
+ case "CONDITION":
5988
+ return describeCondition(tr, configOf("CONDITION", config2).condition);
5989
+ case "COMPLEX": {
5990
+ const complex = configOf("COMPLEX", config2);
5991
+ const count = complex.conditions.length;
5992
+ if (complex.combinator === "ALL") {
5993
+ return count === 1 ? tr("fluidgrids.rules.summaryAllOne", "All of 1 condition") : tr("fluidgrids.rules.summaryAll", "All of {{count}} conditions", {
5994
+ count
5995
+ });
5996
+ }
5997
+ return count === 1 ? tr("fluidgrids.rules.summaryAnyOne", "Any of 1 condition") : tr("fluidgrids.rules.summaryAny", "Any of {{count}} conditions", {
5998
+ count
5999
+ });
6000
+ }
6001
+ case "SCORING": {
6002
+ const scoring = configOf("SCORING", config2);
6003
+ return scoring.rules.length === 1 ? tr(
6004
+ "fluidgrids.rules.summaryScoringOne",
6005
+ "1 scoring rule \u2192 {{variable}}",
6006
+ { variable: scoring.variable }
6007
+ ) : tr(
6008
+ "fluidgrids.rules.summaryScoring",
6009
+ "{{count}} scoring rules \u2192 {{variable}}",
6010
+ { count: scoring.rules.length, variable: scoring.variable }
6011
+ );
6012
+ }
6013
+ case "LOOKUP": {
6014
+ const lookup = configOf("LOOKUP", config2);
6015
+ const key = lookup.key || "\u2026";
6016
+ return lookup.source.kind === "DATA_TABLE" ? tr(
6017
+ "fluidgrids.rules.summaryLookupTable",
6018
+ "{{key}} \u2192 {{variable}} (data table)",
6019
+ { key, variable: lookup.variable }
6020
+ ) : lookup.source.entries.length === 1 ? tr(
6021
+ "fluidgrids.rules.summaryLookupInlineOne",
6022
+ "{{key}} \u2192 {{variable}} (1 entry)",
6023
+ { key, variable: lookup.variable }
6024
+ ) : tr(
6025
+ "fluidgrids.rules.summaryLookupInline",
6026
+ "{{key}} \u2192 {{variable}} ({{count}} entries)",
6027
+ {
6028
+ key,
6029
+ variable: lookup.variable,
6030
+ count: lookup.source.entries.length
6031
+ }
6032
+ );
6033
+ }
6034
+ case "DECISION":
6035
+ return configOf("DECISION", config2).outcome || "\u2026";
6036
+ }
6037
+ }
6038
+ function RuleBuilderHeader({
6039
+ version: version2,
6040
+ name,
6041
+ dirty,
6042
+ saving,
6043
+ canEdit,
6044
+ issues,
6045
+ onBack,
6046
+ onNameChange,
6047
+ onSave
6048
+ }) {
6049
+ const tr = useTr();
6050
+ const errorCount = issues.filter(
6051
+ (issue) => issue.severity === "ERROR"
6052
+ ).length;
6053
+ const warningCount = issues.length - errorCount;
6054
+ return /* @__PURE__ */ jsxs("header", { className: "flex flex-wrap items-center gap-3 border-b border-border-secondary px-4 py-3", children: [
6055
+ /* @__PURE__ */ jsx(
6056
+ Button$1,
6057
+ {
6058
+ variant: "ghost",
6059
+ size: "sm",
6060
+ onClick: onBack,
6061
+ "aria-label": tr("fluidgrids.rules.backToRuleSets", "Back to rule sets"),
6062
+ children: /* @__PURE__ */ jsx(ArrowLeft, { className: "size-4", "aria-hidden": "true" })
6063
+ }
6064
+ ),
6065
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
6066
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs text-text-secondary", children: [
6067
+ /* @__PURE__ */ jsx(Scale, { className: "size-3.5", "aria-hidden": "true" }),
6068
+ tr("fluidgrids.rules.ruleSet", "Rule set"),
6069
+ " \xB7 v",
6070
+ version2,
6071
+ dirty && /* @__PURE__ */ jsxs("span", { className: "text-status-warning", children: [
6072
+ "\xB7 ",
6073
+ tr("fluidgrids.rules.unsaved", "Unsaved changes")
6074
+ ] })
6075
+ ] }),
6076
+ /* @__PURE__ */ jsx(
6077
+ Input,
6078
+ {
6079
+ value: name,
6080
+ maxLength: 200,
6081
+ disabled: !canEdit,
6082
+ "aria-label": tr("fluidgrids.rules.name", "Name"),
6083
+ className: "h-8 max-w-md border-transparent px-1 text-lg font-semibold text-text-primary hover:border-input",
6084
+ onChange: (event) => onNameChange(event.target.value)
6085
+ }
6086
+ )
6087
+ ] }),
6088
+ (errorCount > 0 || warningCount > 0) && /* @__PURE__ */ jsxs(
6089
+ Badge,
6090
+ {
6091
+ variant: "outline",
6092
+ className: errorCount > 0 ? "text-status-error" : "text-status-warning",
6093
+ title: issues.map((issue) => issue.message).join("\n"),
6094
+ children: [
6095
+ /* @__PURE__ */ jsx(AlertTriangle, { className: "mr-1 size-3.5", "aria-hidden": "true" }),
6096
+ errorCount > 0 ? tr("fluidgrids.rules.errorCount", "{{count}} errors", {
6097
+ count: errorCount
6098
+ }) : tr("fluidgrids.rules.warningCount", "{{count}} warnings", {
6099
+ count: warningCount
6100
+ })
6101
+ ]
6102
+ }
6103
+ ),
6104
+ /* @__PURE__ */ jsx(
6105
+ SdkPermissionButton,
6106
+ {
6107
+ permission: FLUIDGRIDS_PERMISSIONS.WORKFLOW_UPDATE,
6108
+ deniedTooltip: tr(
6109
+ "fluidgrids.rules.saveDenied",
6110
+ "You don't have permission to edit rule sets"
6111
+ ),
6112
+ children: /* @__PURE__ */ jsxs(Button$1, { onClick: onSave, disabled: saving || !dirty, children: [
6113
+ /* @__PURE__ */ jsx(Save, { className: "mr-2 size-4", "aria-hidden": "true" }),
6114
+ saving ? tr("fluidgrids.rules.saving", "Saving\u2026") : tr("fluidgrids.rules.save", "Save")
6115
+ ] })
6116
+ }
6117
+ )
6118
+ ] });
6119
+ }
6120
+ function RulePalette({
6121
+ canEdit,
6122
+ onAdd
6123
+ }) {
6124
+ const tr = useTr();
6125
+ return /* @__PURE__ */ jsxs(
6126
+ "aside",
6127
+ {
6128
+ className: "flex shrink-0 gap-2 overflow-x-auto border-b border-border-secondary p-3 lg:w-52 lg:flex-col lg:border-b-0 lg:border-r",
6129
+ "aria-label": tr("fluidgrids.rules.palette", "Blocks"),
6130
+ children: [
6131
+ /* @__PURE__ */ jsx("div", { className: "hidden text-xs font-medium uppercase tracking-wide text-text-secondary lg:block", children: tr("fluidgrids.rules.palette", "Blocks") }),
6132
+ RULE_NODE_TYPES.map((type) => {
6133
+ const style = RULE_BLOCK_STYLES[type];
6134
+ const Icon6 = style.icon;
6135
+ return /* @__PURE__ */ jsxs(
6136
+ "button",
6137
+ {
6138
+ type: "button",
6139
+ draggable: canEdit,
6140
+ disabled: !canEdit,
6141
+ onDragStart: (event) => {
6142
+ event.dataTransfer.setData(RULE_BLOCK_DRAG_MIME, type);
6143
+ event.dataTransfer.effectAllowed = "move";
6144
+ },
6145
+ onClick: () => onAdd(type),
6146
+ className: "flex shrink-0 items-center gap-2 rounded-md border border-border-secondary px-2 py-2 text-left text-sm text-text-primary hover:bg-muted/40 disabled:opacity-50",
6147
+ "data-testid": `rule-palette-${type.toLowerCase()}`,
6148
+ children: [
6149
+ /* @__PURE__ */ jsx(
6150
+ "span",
6151
+ {
6152
+ className: `flex size-6 items-center justify-center rounded ${style.chip}`,
6153
+ children: /* @__PURE__ */ jsx(Icon6, { className: "size-3.5", "aria-hidden": "true" })
6154
+ }
6155
+ ),
6156
+ ruleBlockTypeLabel(tr, type)
6157
+ ]
6158
+ },
6159
+ type
6160
+ );
6161
+ }),
6162
+ /* @__PURE__ */ jsx("p", { className: "hidden text-xs text-text-secondary lg:block", children: tr(
6163
+ "fluidgrids.rules.paletteHint",
6164
+ "Click or drag a block onto the canvas, then connect its outputs. Condition blocks have a TRUE and a FALSE output."
6165
+ ) })
6166
+ ]
6167
+ }
6168
+ );
6169
+ }
6170
+ function RuleIssueList({
6171
+ issues,
6172
+ onFocusNode
6173
+ }) {
6174
+ const tr = useTr();
6175
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3 text-sm text-text-secondary", children: [
6176
+ /* @__PURE__ */ jsx("p", { children: tr("fluidgrids.rules.selectBlock", "Select a block to edit it.") }),
6177
+ issues.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1", children: issues.map((issue) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
6178
+ "button",
6179
+ {
6180
+ type: "button",
6181
+ className: `text-left text-xs ${issue.severity === "ERROR" ? "text-status-error" : "text-status-warning"}`,
6182
+ onClick: () => issue.nodeId && onFocusNode(issue.nodeId),
6183
+ children: issue.message
6184
+ }
6185
+ ) }, ruleIssueKey(issue))) })
6186
+ ] });
6187
+ }
6188
+ var HANDLE_OFFSETS = {
6189
+ TRUE: "30%",
6190
+ FALSE: "70%",
6191
+ NEXT: "50%"
6192
+ };
6193
+ function RuleNodeCardComponent({ data, selected }) {
6194
+ const tr = useTr();
6195
+ const style = RULE_BLOCK_STYLES[data.ruleType];
6196
+ const Icon6 = style.icon;
6197
+ const typeLabel = ruleBlockTypeLabel(tr, data.ruleType);
6198
+ const highlight = data.onPath ? "ring-2 ring-status-success" : selected ? "ring-2 ring-primary" : "";
6199
+ return /* @__PURE__ */ jsxs(
6200
+ "div",
6201
+ {
6202
+ className: `w-60 rounded-lg border-l-4 border border-border-secondary bg-background-primary shadow-sm ${style.accent} ${highlight}`,
6203
+ "data-testid": `rule-node-${data.ruleType.toLowerCase()}`,
6204
+ children: [
6205
+ /* @__PURE__ */ jsx(
6206
+ Handle,
6207
+ {
6208
+ type: "target",
6209
+ position: Position.Top,
6210
+ className: "!size-3 !border-2 !border-background-primary !bg-text-secondary"
6211
+ }
6212
+ ),
6213
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 p-3", children: [
6214
+ /* @__PURE__ */ jsx(
6215
+ "span",
6216
+ {
6217
+ className: `mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-md ${style.chip}`,
6218
+ children: /* @__PURE__ */ jsx(Icon6, { className: "size-4", "aria-hidden": "true" })
6219
+ }
6220
+ ),
6221
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
6222
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-[11px] font-medium uppercase tracking-wide text-text-secondary", children: [
6223
+ typeLabel,
6224
+ data.isStart && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-0.5 rounded bg-primary/10 px-1 text-primary normal-case", children: [
6225
+ /* @__PURE__ */ jsx(Play, { className: "size-3", "aria-hidden": "true" }),
6226
+ tr("fluidgrids.rules.start", "Start")
6227
+ ] })
6228
+ ] }),
6229
+ /* @__PURE__ */ jsx("div", { className: "truncate text-sm font-semibold text-text-primary", children: data.label || typeLabel }),
6230
+ /* @__PURE__ */ jsx("div", { className: "truncate text-xs text-text-secondary", children: summarizeNode(tr, data.ruleType, data.config) }),
6231
+ data.stepOutcome && /* @__PURE__ */ jsx("div", { className: "mt-1 text-[11px] font-medium text-status-success", children: tr("fluidgrids.rules.stepResult", "Result: {{outcome}}", {
6232
+ outcome: data.stepOutcome
6233
+ }) })
6234
+ ] })
6235
+ ] }),
6236
+ branchesOf(data.ruleType).map((branch) => /* @__PURE__ */ jsx(
6237
+ Handle,
6238
+ {
6239
+ id: branch,
6240
+ type: "source",
6241
+ position: Position.Bottom,
6242
+ style: { left: HANDLE_OFFSETS[branch] },
6243
+ className: `!size-3 !border-2 !border-background-primary ${branch === "FALSE" ? "!bg-status-error" : branch === "TRUE" ? "!bg-status-success" : "!bg-text-secondary"}`,
6244
+ title: branch
6245
+ },
6246
+ branch
6247
+ )),
6248
+ branchesOf(data.ruleType).length > 1 && /* @__PURE__ */ jsxs("div", { className: "flex justify-between px-[22%] pb-1 text-[10px] font-semibold text-text-secondary", children: [
6249
+ /* @__PURE__ */ jsx("span", { children: tr("fluidgrids.rules.branchTrue", "TRUE") }),
6250
+ /* @__PURE__ */ jsx("span", { children: tr("fluidgrids.rules.branchFalse", "FALSE") })
6251
+ ] })
6252
+ ]
6253
+ }
6254
+ );
6255
+ }
6256
+ var RuleNodeCard = memo(RuleNodeCardComponent);
6257
+ var sequence = 0;
6258
+ function newRowKey() {
6259
+ sequence += 1;
6260
+ return `row-${sequence}`;
6261
+ }
6262
+ function useRowKeys(count) {
6263
+ const [keys, setKeys] = useState(
6264
+ () => Array.from({ length: count }, newRowKey)
6265
+ );
6266
+ let aligned = keys;
6267
+ if (keys.length !== count) {
6268
+ aligned = keys.length < count ? [...keys, ...Array.from({ length: count - keys.length }, newRowKey)] : keys.slice(0, count);
6269
+ setKeys(aligned);
6270
+ }
6271
+ const append = useCallback(
6272
+ () => setKeys((current) => [...current, newRowKey()]),
6273
+ []
6274
+ );
6275
+ const remove = useCallback(
6276
+ (position) => setKeys((current) => current.filter((_, i) => i !== position)),
6277
+ []
6278
+ );
6279
+ return { keys: aligned, append, remove };
6280
+ }
6281
+ var SELECT_CLASS = "flex h-9 w-full rounded-md border border-input bg-background px-2 text-sm text-text-primary";
6282
+ function ValueInput({
6283
+ value,
6284
+ onChange,
6285
+ ariaLabel,
6286
+ placeholder
6287
+ }) {
6288
+ const [text, setText] = useState(() => formatValueText(value));
6289
+ return /* @__PURE__ */ jsx(
6290
+ Input,
6291
+ {
6292
+ value: text,
6293
+ "aria-label": ariaLabel,
6294
+ placeholder,
6295
+ onChange: (event) => {
6296
+ setText(event.target.value);
6297
+ onChange(parseValueText(event.target.value));
6298
+ }
6299
+ }
6300
+ );
6301
+ }
6302
+ function ConditionRow({
6303
+ condition,
6304
+ onChange,
6305
+ onRemove
6306
+ }) {
6307
+ const tr = useTr();
6308
+ const unary = UNARY_OPERATORS.has(condition.operator);
6309
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 rounded-md border border-border-secondary p-2", children: [
6310
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6311
+ /* @__PURE__ */ jsx(
6312
+ Input,
6313
+ {
6314
+ value: condition.field,
6315
+ "aria-label": tr("fluidgrids.rules.field", "Field"),
6316
+ placeholder: tr(
6317
+ "fluidgrids.rules.fieldPlaceholder",
6318
+ "applicant.creditScore"
6319
+ ),
6320
+ onChange: (event) => onChange({ ...condition, field: event.target.value })
6321
+ }
6322
+ ),
6323
+ onRemove && /* @__PURE__ */ jsx(
6324
+ Button$1,
6325
+ {
6326
+ variant: "ghost",
6327
+ size: "sm",
6328
+ onClick: onRemove,
6329
+ "aria-label": tr(
6330
+ "fluidgrids.rules.removeCondition",
6331
+ "Remove condition"
6332
+ ),
6333
+ children: /* @__PURE__ */ jsx(Trash2, { className: "size-4", "aria-hidden": "true" })
6334
+ }
6335
+ )
6336
+ ] }),
6337
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[8.5rem_minmax(0,1fr)] gap-2", children: [
6338
+ /* @__PURE__ */ jsx(
6339
+ "select",
6340
+ {
6341
+ className: SELECT_CLASS,
6342
+ value: condition.operator,
6343
+ "aria-label": tr("fluidgrids.rules.operator", "Operator"),
6344
+ onChange: (event) => {
6345
+ const operator = event.target.value;
6346
+ onChange(
6347
+ UNARY_OPERATORS.has(operator) ? { field: condition.field, operator } : { ...condition, operator, value: condition.value ?? "" }
6348
+ );
6349
+ },
6350
+ children: RULE_OPERATORS.map((operator) => /* @__PURE__ */ jsx("option", { value: operator, children: operatorLabel(tr, operator) }, operator))
6351
+ }
6352
+ ),
6353
+ !unary && /* @__PURE__ */ jsx(
6354
+ ValueInput,
6355
+ {
6356
+ value: condition.value,
6357
+ ariaLabel: tr("fluidgrids.rules.value", "Value"),
6358
+ placeholder: condition.operator === "BETWEEN" ? "[650, 749]" : condition.operator === "IN" || condition.operator === "NOT_IN" ? '["A", "B"]' : "750",
6359
+ onChange: (value) => onChange({ ...condition, value })
6360
+ }
6361
+ )
6362
+ ] })
6363
+ ] });
6364
+ }
6365
+ function isPlainObject2(value) {
6366
+ return value !== null && typeof value === "object" && !Array.isArray(value);
6367
+ }
6368
+ function JsonField({
6369
+ label,
6370
+ value,
6371
+ onChange,
6372
+ rows = 4,
6373
+ validate
6374
+ }) {
6375
+ const [text, setText] = useState(() => JSON.stringify(value ?? {}, null, 2));
6376
+ const [error, setError] = useState(null);
6377
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6378
+ /* @__PURE__ */ jsx(Label, { children: label }),
6379
+ /* @__PURE__ */ jsx(
6380
+ Textarea,
6381
+ {
6382
+ rows,
6383
+ className: "font-mono text-xs",
6384
+ value: text,
6385
+ "aria-label": label,
6386
+ onChange: (event) => {
6387
+ setText(event.target.value);
6388
+ const parsed = parseJsonText(event.target.value);
6389
+ if (parsed.ok) {
6390
+ const invalid = validate?.(parsed.value) ?? null;
6391
+ setError(invalid);
6392
+ if (invalid === null) onChange(parsed.value);
6393
+ } else {
6394
+ setError(parsed.error);
6395
+ }
6396
+ }
6397
+ }
6398
+ ),
6399
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-status-error", children: error })
6400
+ ] });
6401
+ }
6402
+ function RuleInspector({
6403
+ node,
6404
+ isStart,
6405
+ readOnly,
6406
+ dataTables,
6407
+ onChange,
6408
+ onDelete,
6409
+ onMakeStart
6410
+ }) {
6411
+ const tr = useTr();
6412
+ const { ruleType, config: config2 } = node.data;
6413
+ const setConfig = (next) => onChange({ config: next });
6414
+ return /* @__PURE__ */ jsxs(
6415
+ "fieldset",
6416
+ {
6417
+ className: "flex flex-col gap-3",
6418
+ disabled: readOnly,
6419
+ "aria-label": tr("fluidgrids.rules.blockSettings", "Block settings"),
6420
+ children: [
6421
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
6422
+ /* @__PURE__ */ jsxs("span", { className: "text-xs font-medium uppercase tracking-wide text-text-secondary", children: [
6423
+ ruleBlockTypeLabel(tr, ruleType),
6424
+ " \xB7 ",
6425
+ node.id
6426
+ ] }),
6427
+ /* @__PURE__ */ jsx(
6428
+ Button$1,
6429
+ {
6430
+ variant: "ghost",
6431
+ size: "sm",
6432
+ onClick: onDelete,
6433
+ "aria-label": tr("fluidgrids.rules.deleteBlock", "Delete block"),
6434
+ children: /* @__PURE__ */ jsx(Trash2, { className: "size-4", "aria-hidden": "true" })
6435
+ }
6436
+ )
6437
+ ] }),
6438
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6439
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-block-label", children: tr("fluidgrids.rules.label", "Label") }),
6440
+ /* @__PURE__ */ jsx(
6441
+ Input,
6442
+ {
6443
+ id: "rule-block-label",
6444
+ value: node.data.label,
6445
+ maxLength: 120,
6446
+ onChange: (event) => onChange({ label: event.target.value })
6447
+ }
6448
+ )
6449
+ ] }),
6450
+ !isStart && /* @__PURE__ */ jsxs(Button$1, { variant: "outline", size: "sm", onClick: onMakeStart, children: [
6451
+ /* @__PURE__ */ jsx(Play, { className: "mr-2 size-4", "aria-hidden": "true" }),
6452
+ tr("fluidgrids.rules.makeStart", "Start evaluation here")
6453
+ ] }),
6454
+ ruleType === "CONDITION" && /* @__PURE__ */ jsx(
6455
+ ConditionRow,
6456
+ {
6457
+ condition: configOf("CONDITION", config2).condition,
6458
+ onChange: (condition) => setConfig({ condition })
6459
+ }
6460
+ ),
6461
+ ruleType === "COMPLEX" && /* @__PURE__ */ jsx(
6462
+ ComplexEditor,
6463
+ {
6464
+ config: configOf("COMPLEX", config2),
6465
+ onChange: setConfig
6466
+ }
6467
+ ),
6468
+ ruleType === "SCORING" && /* @__PURE__ */ jsx(
6469
+ ScoringEditor,
6470
+ {
6471
+ config: configOf("SCORING", config2),
6472
+ onChange: setConfig
6473
+ }
6474
+ ),
6475
+ ruleType === "LOOKUP" && /* @__PURE__ */ jsx(
6476
+ LookupEditor,
6477
+ {
6478
+ config: configOf("LOOKUP", config2),
6479
+ dataTables,
6480
+ onChange: setConfig
6481
+ }
6482
+ ),
6483
+ ruleType === "DECISION" && /* @__PURE__ */ jsx(
6484
+ DecisionEditor,
6485
+ {
6486
+ config: configOf("DECISION", config2),
6487
+ onChange: setConfig
6488
+ },
6489
+ node.id
6490
+ )
6491
+ ]
6492
+ }
6493
+ );
6494
+ }
6495
+ function ComplexEditor({
6496
+ config: config2,
6497
+ onChange
6498
+ }) {
6499
+ const tr = useTr();
6500
+ const rows = useRowKeys(config2.conditions.length);
6501
+ const update = (index, condition) => onChange({
6502
+ ...config2,
6503
+ conditions: config2.conditions.map(
6504
+ (item, i) => i === index ? condition : item
6505
+ )
6506
+ });
6507
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
6508
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-combinator", children: tr("fluidgrids.rules.combinator", "Match") }),
6509
+ /* @__PURE__ */ jsxs(
6510
+ "select",
6511
+ {
6512
+ id: "rule-combinator",
6513
+ className: SELECT_CLASS,
6514
+ value: config2.combinator,
6515
+ onChange: (event) => onChange({
6516
+ ...config2,
6517
+ combinator: event.target.value === "ANY" ? "ANY" : "ALL"
6518
+ }),
6519
+ children: [
6520
+ /* @__PURE__ */ jsx("option", { value: "ALL", children: tr("fluidgrids.rules.combinatorAll", "All conditions (AND)") }),
6521
+ /* @__PURE__ */ jsx("option", { value: "ANY", children: tr("fluidgrids.rules.combinatorAny", "Any condition (OR)") })
6522
+ ]
6523
+ }
6524
+ ),
6525
+ config2.conditions.map((condition, position) => /* @__PURE__ */ jsx(
6526
+ ConditionRow,
6527
+ {
6528
+ condition,
6529
+ onChange: (next) => update(position, next),
6530
+ onRemove: () => {
6531
+ rows.remove(position);
6532
+ onChange({
6533
+ ...config2,
6534
+ conditions: config2.conditions.filter((_, i) => i !== position)
6535
+ });
6536
+ }
6537
+ },
6538
+ rows.keys[position]
6539
+ )),
6540
+ /* @__PURE__ */ jsxs(
6541
+ Button$1,
6542
+ {
6543
+ variant: "outline",
6544
+ size: "sm",
6545
+ onClick: () => {
6546
+ rows.append();
6547
+ onChange({
6548
+ ...config2,
6549
+ conditions: [
6550
+ ...config2.conditions,
6551
+ { field: "", operator: "EQ", value: "" }
6552
+ ]
6553
+ });
6554
+ },
6555
+ children: [
6556
+ /* @__PURE__ */ jsx(Plus, { className: "mr-2 size-4", "aria-hidden": "true" }),
6557
+ tr("fluidgrids.rules.addCondition", "Add condition")
6558
+ ]
6559
+ }
6560
+ )
6561
+ ] });
6562
+ }
6563
+ function ScoringEditor({
6564
+ config: config2,
6565
+ onChange
6566
+ }) {
6567
+ const tr = useTr();
6568
+ const rows = useRowKeys(config2.rules.length);
6569
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
6570
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
6571
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6572
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-score-variable", children: tr("fluidgrids.rules.variable", "Variable") }),
6573
+ /* @__PURE__ */ jsx(
6574
+ Input,
6575
+ {
6576
+ id: "rule-score-variable",
6577
+ value: config2.variable,
6578
+ onChange: (event) => onChange({ ...config2, variable: event.target.value })
6579
+ }
6580
+ )
6581
+ ] }),
6582
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6583
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-score-base", children: tr("fluidgrids.rules.basePoints", "Base points") }),
6584
+ /* @__PURE__ */ jsx(
6585
+ Input,
6586
+ {
6587
+ id: "rule-score-base",
6588
+ type: "number",
6589
+ value: String(config2.base),
6590
+ onChange: (event) => onChange({ ...config2, base: Number(event.target.value) || 0 })
6591
+ }
6592
+ )
6593
+ ] })
6594
+ ] }),
6595
+ config2.rules.map((rule, position) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6596
+ /* @__PURE__ */ jsx(
6597
+ ConditionRow,
6598
+ {
6599
+ condition: rule.condition,
6600
+ onChange: (condition) => onChange({
6601
+ ...config2,
6602
+ rules: config2.rules.map(
6603
+ (item, i) => i === position ? { ...item, condition } : item
6604
+ )
6605
+ }),
6606
+ onRemove: () => {
6607
+ rows.remove(position);
6608
+ onChange({
6609
+ ...config2,
6610
+ rules: config2.rules.filter((_, i) => i !== position)
6611
+ });
6612
+ }
6613
+ }
6614
+ ),
6615
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pl-2", children: [
6616
+ /* @__PURE__ */ jsx(
6617
+ Label,
6618
+ {
6619
+ className: "text-xs",
6620
+ htmlFor: `rule-points-${rows.keys[position]}`,
6621
+ children: tr("fluidgrids.rules.points", "Points")
6622
+ }
6623
+ ),
6624
+ /* @__PURE__ */ jsx(
6625
+ Input,
6626
+ {
6627
+ id: `rule-points-${rows.keys[position]}`,
6628
+ type: "number",
6629
+ className: "h-8 w-24",
6630
+ value: String(rule.points),
6631
+ onChange: (event) => onChange({
6632
+ ...config2,
6633
+ rules: config2.rules.map(
6634
+ (item, i) => i === position ? { ...item, points: Number(event.target.value) || 0 } : item
6635
+ )
6636
+ })
6637
+ }
6638
+ )
6639
+ ] })
6640
+ ] }, rows.keys[position])),
6641
+ /* @__PURE__ */ jsxs(
6642
+ Button$1,
6643
+ {
6644
+ variant: "outline",
6645
+ size: "sm",
6646
+ onClick: () => {
6647
+ rows.append();
6648
+ onChange({
6649
+ ...config2,
6650
+ rules: [
6651
+ ...config2.rules,
6652
+ {
6653
+ condition: { field: "", operator: "GTE", value: 0 },
6654
+ points: 10
6655
+ }
6656
+ ]
6657
+ });
6658
+ },
6659
+ children: [
6660
+ /* @__PURE__ */ jsx(Plus, { className: "mr-2 size-4", "aria-hidden": "true" }),
6661
+ tr("fluidgrids.rules.addScoringRule", "Add scoring rule")
6662
+ ]
6663
+ }
6664
+ )
6665
+ ] });
6666
+ }
6667
+ function LookupEditor({
6668
+ config: config2,
6669
+ dataTables,
6670
+ onChange
6671
+ }) {
6672
+ const tr = useTr();
6673
+ const source = config2.source;
6674
+ const rows = useRowKeys(source.kind === "INLINE" ? source.entries.length : 0);
6675
+ const selectedTable = source.kind === "DATA_TABLE" ? dataTables.find((table) => table.id === source.tableId) : void 0;
6676
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
6677
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6678
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-lookup-key", children: tr("fluidgrids.rules.lookupKey", "Key field") }),
6679
+ /* @__PURE__ */ jsx(
6680
+ Input,
6681
+ {
6682
+ id: "rule-lookup-key",
6683
+ value: config2.key,
6684
+ placeholder: "applicant.employmentType",
6685
+ onChange: (event) => onChange({ ...config2, key: event.target.value })
6686
+ }
6687
+ )
6688
+ ] }),
6689
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
6690
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6691
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-lookup-variable", children: tr("fluidgrids.rules.variable", "Variable") }),
6692
+ /* @__PURE__ */ jsx(
6693
+ Input,
6694
+ {
6695
+ id: "rule-lookup-variable",
6696
+ value: config2.variable,
6697
+ onChange: (event) => onChange({ ...config2, variable: event.target.value })
6698
+ }
6699
+ )
6700
+ ] }),
6701
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6702
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-lookup-default", children: tr("fluidgrids.rules.defaultValue", "Default") }),
6703
+ /* @__PURE__ */ jsx(
6704
+ ValueInput,
6705
+ {
6706
+ value: config2.defaultValue,
6707
+ ariaLabel: tr("fluidgrids.rules.defaultValue", "Default"),
6708
+ onChange: (defaultValue) => onChange({ ...config2, defaultValue })
6709
+ }
6710
+ )
6711
+ ] })
6712
+ ] }),
6713
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-lookup-source", children: tr("fluidgrids.rules.lookupSource", "Source") }),
6714
+ /* @__PURE__ */ jsxs(
6715
+ "select",
6716
+ {
6717
+ id: "rule-lookup-source",
6718
+ className: SELECT_CLASS,
6719
+ value: source.kind,
6720
+ onChange: (event) => onChange({
6721
+ ...config2,
6722
+ source: event.target.value === "DATA_TABLE" ? {
6723
+ kind: "DATA_TABLE",
6724
+ tableId: dataTables[0]?.id ?? "",
6725
+ keyColumn: dataTables[0]?.columns[0]?.key ?? "",
6726
+ valueColumn: dataTables[0]?.columns[1]?.key ?? ""
6727
+ } : { kind: "INLINE", entries: [] }
6728
+ }),
6729
+ children: [
6730
+ /* @__PURE__ */ jsx("option", { value: "INLINE", children: tr("fluidgrids.rules.sourceInline", "Entries in this block") }),
6731
+ /* @__PURE__ */ jsx("option", { value: "DATA_TABLE", children: tr("fluidgrids.rules.sourceDataTable", "A data table") })
6732
+ ]
6733
+ }
6734
+ ),
6735
+ source.kind === "INLINE" ? /* @__PURE__ */ jsxs(Fragment, { children: [
6736
+ source.entries.map((entry, position) => /* @__PURE__ */ jsxs(
6737
+ "div",
6738
+ {
6739
+ className: "grid grid-cols-[1fr_1fr_auto] gap-2",
6740
+ children: [
6741
+ /* @__PURE__ */ jsx(
6742
+ Input,
6743
+ {
6744
+ value: entry.key,
6745
+ "aria-label": tr("fluidgrids.rules.entryKey", "Key"),
6746
+ onChange: (event) => onChange({
6747
+ ...config2,
6748
+ source: {
6749
+ kind: "INLINE",
6750
+ entries: source.entries.map(
6751
+ (item, i) => i === position ? { ...item, key: event.target.value } : item
6752
+ )
6753
+ }
6754
+ })
6755
+ }
6756
+ ),
6757
+ /* @__PURE__ */ jsx(
6758
+ ValueInput,
6759
+ {
6760
+ value: entry.value,
6761
+ ariaLabel: tr("fluidgrids.rules.entryValue", "Value"),
6762
+ onChange: (value) => onChange({
6763
+ ...config2,
6764
+ source: {
6765
+ kind: "INLINE",
6766
+ entries: source.entries.map(
6767
+ (item, i) => i === position ? { ...item, value } : item
6768
+ )
6769
+ }
6770
+ })
6771
+ }
6772
+ ),
6773
+ /* @__PURE__ */ jsx(
6774
+ Button$1,
6775
+ {
6776
+ variant: "ghost",
6777
+ size: "sm",
6778
+ "aria-label": tr("fluidgrids.rules.removeEntry", "Remove entry"),
6779
+ onClick: () => {
6780
+ rows.remove(position);
6781
+ onChange({
6782
+ ...config2,
6783
+ source: {
6784
+ kind: "INLINE",
6785
+ entries: source.entries.filter((_, i) => i !== position)
6786
+ }
6787
+ });
6788
+ },
6789
+ children: /* @__PURE__ */ jsx(Trash2, { className: "size-4", "aria-hidden": "true" })
6790
+ }
6791
+ )
6792
+ ]
6793
+ },
6794
+ rows.keys[position]
6795
+ )),
6796
+ /* @__PURE__ */ jsxs(
6797
+ Button$1,
6798
+ {
6799
+ variant: "outline",
6800
+ size: "sm",
6801
+ onClick: () => {
6802
+ rows.append();
6803
+ onChange({
6804
+ ...config2,
6805
+ source: {
6806
+ kind: "INLINE",
6807
+ entries: [...source.entries, { key: "", value: "" }]
6808
+ }
6809
+ });
6810
+ },
6811
+ children: [
6812
+ /* @__PURE__ */ jsx(Plus, { className: "mr-2 size-4", "aria-hidden": "true" }),
6813
+ tr("fluidgrids.rules.addEntry", "Add entry")
6814
+ ]
6815
+ }
6816
+ )
6817
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
6818
+ dataTables.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: tr(
6819
+ "fluidgrids.rules.noDataTables",
6820
+ "This workspace has no data tables yet. Create one under Data Tables."
6821
+ ) }),
6822
+ /* @__PURE__ */ jsx(
6823
+ "select",
6824
+ {
6825
+ className: SELECT_CLASS,
6826
+ "aria-label": tr("fluidgrids.rules.dataTable", "Data table"),
6827
+ value: source.tableId,
6828
+ onChange: (event) => {
6829
+ const table = dataTables.find(
6830
+ (item) => item.id === event.target.value
6831
+ );
6832
+ onChange({
6833
+ ...config2,
6834
+ source: {
6835
+ kind: "DATA_TABLE",
6836
+ tableId: event.target.value,
6837
+ keyColumn: table?.columns[0]?.key ?? "",
6838
+ valueColumn: table?.columns[1]?.key ?? ""
6839
+ }
6840
+ });
6841
+ },
6842
+ children: dataTables.map((table) => /* @__PURE__ */ jsx("option", { value: table.id, children: table.name }, table.id))
6843
+ }
6844
+ ),
6845
+ ["keyColumn", "valueColumn"].map((column) => /* @__PURE__ */ jsx(
6846
+ "select",
6847
+ {
6848
+ className: SELECT_CLASS,
6849
+ "aria-label": column === "keyColumn" ? tr("fluidgrids.rules.keyColumn", "Key column") : tr("fluidgrids.rules.valueColumn", "Value column"),
6850
+ value: source[column],
6851
+ onChange: (event) => onChange({
6852
+ ...config2,
6853
+ source: { ...source, [column]: event.target.value }
6854
+ }),
6855
+ children: (selectedTable?.columns ?? []).map((item) => /* @__PURE__ */ jsx("option", { value: item.key, children: column === "keyColumn" ? tr("fluidgrids.rules.keyColumnOption", "Key: {{label}}", {
6856
+ label: item.label
6857
+ }) : tr(
6858
+ "fluidgrids.rules.valueColumnOption",
6859
+ "Value: {{label}}",
6860
+ { label: item.label }
6861
+ ) }, item.key))
6862
+ },
6863
+ column
6864
+ ))
6865
+ ] })
6866
+ ] });
6867
+ }
6868
+ function DecisionEditor({
6869
+ config: config2,
6870
+ onChange
6871
+ }) {
6872
+ const tr = useTr();
6873
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
6874
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6875
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-outcome", children: tr("fluidgrids.rules.outcome", "Outcome") }),
6876
+ /* @__PURE__ */ jsx(
6877
+ Input,
6878
+ {
6879
+ id: "rule-outcome",
6880
+ value: config2.outcome,
6881
+ maxLength: 80,
6882
+ onChange: (event) => onChange({ ...config2, outcome: event.target.value })
6883
+ }
6884
+ )
6885
+ ] }),
6886
+ /* @__PURE__ */ jsx(
6887
+ JsonField,
6888
+ {
6889
+ label: tr("fluidgrids.rules.output", "Output (JSON object)"),
6890
+ value: config2.output,
6891
+ validate: (output) => isPlainObject2(output) ? null : tr(
6892
+ "fluidgrids.rules.outputMustBeObject",
6893
+ 'The output must be a JSON object, for example {"approved": true}.'
6894
+ ),
6895
+ onChange: (output) => {
6896
+ if (isPlainObject2(output)) onChange({ ...config2, output });
6897
+ }
6898
+ }
6899
+ )
6900
+ ] });
6901
+ }
6902
+
6903
+ // src/modules/rule-builder/lib/content-keys.ts
6904
+ function contentKeys(items, keyOf) {
6905
+ const seen = /* @__PURE__ */ new Map();
6906
+ return items.map((item) => {
6907
+ const base = keyOf(item);
6908
+ const count = seen.get(base) ?? 0;
6909
+ seen.set(base, count + 1);
6910
+ return count === 0 ? base : `${base}#${count}`;
6911
+ });
6912
+ }
6913
+ function formatJson(value) {
6914
+ return value === void 0 ? "null" : JSON.stringify(value);
6915
+ }
6916
+ function issueKey(issue) {
6917
+ return `${issue.code}:${issue.nodeId ?? ""}:${issue.message}`;
6918
+ }
6919
+ function conditionKey(condition) {
6920
+ return `${condition.field}:${condition.operator}:${formatJson(condition.expected)}`;
6921
+ }
6922
+ function TraceConditionList({
6923
+ conditions
6924
+ }) {
6925
+ const tr = useTr();
6926
+ const keys = contentKeys(conditions, conditionKey);
6927
+ return /* @__PURE__ */ jsx("ul", { className: "mt-1 flex flex-col gap-0.5", children: conditions.map((condition, position) => /* @__PURE__ */ jsxs(
6928
+ "li",
6929
+ {
6930
+ className: "flex items-center gap-1 text-[11px] text-text-secondary",
6931
+ children: [
6932
+ condition.passed ? /* @__PURE__ */ jsx(
6933
+ CheckCircle2,
6934
+ {
6935
+ className: "size-3 text-status-success",
6936
+ "aria-hidden": "true"
6937
+ }
6938
+ ) : /* @__PURE__ */ jsx(XCircle, { className: "size-3 text-status-error", "aria-hidden": "true" }),
6939
+ /* @__PURE__ */ jsxs("span", { className: "truncate", children: [
6940
+ condition.field,
6941
+ " ",
6942
+ operatorLabel(tr, condition.operator),
6943
+ " ",
6944
+ formatJson(condition.expected),
6945
+ " (",
6946
+ formatJson(condition.actual),
6947
+ ")"
6948
+ ] })
6949
+ ]
6950
+ },
6951
+ keys[position]
6952
+ )) });
6953
+ }
6954
+ function RuleTestPanel({
6955
+ inputText,
6956
+ onInputTextChange,
6957
+ onRun,
6958
+ running,
6959
+ result,
6960
+ onSelectStep
6961
+ }) {
6962
+ const tr = useTr();
6963
+ const [error, setError] = useState(null);
6964
+ const issueKeys = contentKeys(result?.issues ?? [], issueKey);
6965
+ const run = () => {
6966
+ const parsed = parseJsonText(inputText);
6967
+ if (!parsed.ok) {
6968
+ setError(parsed.error);
6969
+ return;
6970
+ }
6971
+ setError(null);
6972
+ onRun(parsed.value);
6973
+ };
6974
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", "data-testid": "rule-test-panel", children: [
6975
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
6976
+ /* @__PURE__ */ jsx(Label, { htmlFor: "rule-test-input", children: tr("fluidgrids.rules.sampleInput", "Sample input (JSON)") }),
6977
+ /* @__PURE__ */ jsx(
6978
+ Textarea,
6979
+ {
6980
+ id: "rule-test-input",
6981
+ rows: 10,
6982
+ className: "font-mono text-xs",
6983
+ value: inputText,
6984
+ onChange: (event) => onInputTextChange(event.target.value)
6985
+ }
6986
+ ),
6987
+ error && /* @__PURE__ */ jsx("p", { className: "text-xs text-status-error", children: error })
6988
+ ] }),
6989
+ /* @__PURE__ */ jsxs(Button$1, { onClick: run, disabled: running, children: [
6990
+ /* @__PURE__ */ jsx(FlaskConical, { className: "mr-2 size-4", "aria-hidden": "true" }),
6991
+ running ? tr("fluidgrids.rules.testing", "Testing\u2026") : tr("fluidgrids.rules.runTest", "Test rule")
6992
+ ] }),
6993
+ result && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", "data-testid": "rule-test-result", children: [
6994
+ /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border-secondary p-3", children: [
6995
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-text-secondary", children: tr("fluidgrids.rules.decision", "Decision") }),
6996
+ result.status === "DECIDED" ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
6997
+ /* @__PURE__ */ jsx(
6998
+ CheckCircle2,
6999
+ {
7000
+ className: "size-5 text-status-success",
7001
+ "aria-hidden": "true"
7002
+ }
7003
+ ),
7004
+ /* @__PURE__ */ jsx(
7005
+ "span",
7006
+ {
7007
+ className: "text-lg font-semibold text-text-primary",
7008
+ "data-testid": "rule-test-decision",
7009
+ children: result.decision
7010
+ }
7011
+ )
7012
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-status-warning", children: [
7013
+ /* @__PURE__ */ jsx(CircleSlash, { className: "size-5", "aria-hidden": "true" }),
7014
+ /* @__PURE__ */ jsx("span", { className: "font-medium", "data-testid": "rule-test-decision", children: result.status === "INVALID" ? tr(
7015
+ "fluidgrids.rules.resultInvalid",
7016
+ "Not evaluated: fix the errors below"
7017
+ ) : tr(
7018
+ "fluidgrids.rules.resultNoDecision",
7019
+ "No decision reached"
7020
+ ) })
7021
+ ] }),
7022
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-text-secondary", children: tr(
7023
+ "fluidgrids.rules.evaluatedIn",
7024
+ "{{steps}} steps in {{ms}} ms",
7025
+ { steps: result.trace.length, ms: result.durationMs }
7026
+ ) }),
7027
+ result.output !== null && result.output !== void 0 && /* @__PURE__ */ jsx("pre", { className: "mt-2 overflow-x-auto rounded bg-muted/40 p-2 text-xs text-text-primary", children: JSON.stringify(result.output, null, 2) })
7028
+ ] }),
7029
+ result.issues.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1", children: result.issues.map((issue, position) => /* @__PURE__ */ jsx(
7030
+ "li",
7031
+ {
7032
+ className: `text-xs ${issue.severity === "ERROR" ? "text-status-error" : "text-status-warning"}`,
7033
+ children: issue.message
7034
+ },
7035
+ issueKeys[position]
7036
+ )) }),
7037
+ result.trace.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
7038
+ /* @__PURE__ */ jsx("div", { className: "text-xs font-medium uppercase tracking-wide text-text-secondary", children: tr("fluidgrids.rules.trace", "Evaluation trace") }),
7039
+ /* @__PURE__ */ jsx("ol", { className: "flex flex-col gap-2", children: result.trace.map((step) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
7040
+ "button",
7041
+ {
7042
+ type: "button",
7043
+ onClick: () => onSelectStep(step.nodeId),
7044
+ className: "w-full rounded-md border border-border-secondary p-2 text-left hover:bg-muted/40",
7045
+ children: [
7046
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
7047
+ /* @__PURE__ */ jsxs("span", { className: "truncate text-sm font-medium text-text-primary", children: [
7048
+ step.index + 1,
7049
+ ". ",
7050
+ step.label || step.nodeId
7051
+ ] }),
7052
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", children: step.outcome })
7053
+ ] }),
7054
+ /* @__PURE__ */ jsx("div", { className: "text-[11px] text-text-secondary", children: ruleBlockTypeLabel(tr, step.nodeType) }),
7055
+ /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-text-secondary", children: step.detail }),
7056
+ step.conditions.length > 1 && /* @__PURE__ */ jsx(TraceConditionList, { conditions: step.conditions })
7057
+ ]
7058
+ }
7059
+ ) }, `${step.index}-${step.nodeId}`)) })
7060
+ ] })
7061
+ ] })
7062
+ ] });
7063
+ }
7064
+ function RuleSidePanel({
7065
+ panel,
7066
+ onPanelChange,
7067
+ selectedNode,
7068
+ effectiveStart,
7069
+ canEdit,
7070
+ dataTables,
7071
+ onChangeSelected,
7072
+ onDeleteSelected,
7073
+ onMakeStart,
7074
+ issues,
7075
+ onFocusNode,
7076
+ inputText,
7077
+ onInputTextChange,
7078
+ onRunTest,
7079
+ testing,
7080
+ result
7081
+ }) {
7082
+ const tr = useTr();
7083
+ return /* @__PURE__ */ jsxs("aside", { className: "flex max-h-[50vh] shrink-0 flex-col border-t border-border-secondary lg:max-h-none lg:w-96 lg:border-l lg:border-t-0", children: [
7084
+ /* @__PURE__ */ jsx("div", { className: "flex border-b border-border-secondary", role: "tablist", children: ["block", "test"].map((tab) => /* @__PURE__ */ jsx(
7085
+ "button",
7086
+ {
7087
+ type: "button",
7088
+ role: "tab",
7089
+ "aria-selected": panel === tab,
7090
+ onClick: () => onPanelChange(tab),
7091
+ className: `flex-1 px-3 py-2 text-sm font-medium ${panel === tab ? "border-b-2 border-primary text-text-primary" : "text-text-secondary"}`,
7092
+ "data-testid": `rule-tab-${tab}`,
7093
+ children: tab === "block" ? tr("fluidgrids.rules.tabBlock", "Block") : tr("fluidgrids.rules.tabTest", "Test rule")
7094
+ },
7095
+ tab
7096
+ )) }),
7097
+ /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto p-4", children: [
7098
+ panel === "block" && (selectedNode ? /* @__PURE__ */ jsx(
7099
+ RuleInspector,
7100
+ {
7101
+ node: selectedNode,
7102
+ isStart: selectedNode.id === effectiveStart,
7103
+ readOnly: !canEdit,
7104
+ dataTables,
7105
+ onChange: onChangeSelected,
7106
+ onDelete: onDeleteSelected,
7107
+ onMakeStart: () => onMakeStart(selectedNode.id)
7108
+ },
7109
+ selectedNode.id
7110
+ ) : /* @__PURE__ */ jsx(RuleIssueList, { issues, onFocusNode })),
7111
+ panel === "test" && /* @__PURE__ */ jsx(
7112
+ RuleTestPanel,
7113
+ {
7114
+ inputText,
7115
+ onInputTextChange,
7116
+ onRun: onRunTest,
7117
+ running: testing,
7118
+ result,
7119
+ onSelectStep: onFocusNode
7120
+ }
7121
+ )
7122
+ ] })
7123
+ ] });
7124
+ }
7125
+ var NODE_TYPES = { rule: RuleNodeCard };
7126
+ var DEFAULT_EDGE_OPTIONS = {
7127
+ markerEnd: { type: MarkerType.ArrowClosed }
7128
+ };
7129
+ function useDecoratedGraph(nodes, edges, startNodeId, result) {
7130
+ const effectiveStart = useMemo(
7131
+ () => resolveStartNodeId(fromFlow(nodes, edges, startNodeId)),
7132
+ [nodes, edges, startNodeId]
7133
+ );
7134
+ const displayNodes = useMemo(() => {
7135
+ const steps = /* @__PURE__ */ new Map();
7136
+ for (const step of result?.trace ?? [])
7137
+ steps.set(step.nodeId, step.outcome);
7138
+ return nodes.map((node) => {
7139
+ const isStart = node.id === effectiveStart;
7140
+ const stepOutcome = steps.get(node.id);
7141
+ if (node.data.isStart === isStart && node.data.stepOutcome === stepOutcome)
7142
+ return node;
7143
+ return {
7144
+ ...node,
7145
+ data: {
7146
+ ...node.data,
7147
+ isStart,
7148
+ onPath: stepOutcome !== void 0,
7149
+ stepOutcome
7150
+ }
7151
+ };
7152
+ });
7153
+ }, [nodes, effectiveStart, result]);
7154
+ const displayEdges = useMemo(() => {
7155
+ const path = result?.path ?? [];
7156
+ const onPath = new Set(
7157
+ path.slice(1).map((target, index) => `${path[index]}->${target}`)
7158
+ );
7159
+ const taken = /* @__PURE__ */ new Map();
7160
+ for (const step of result?.trace ?? [])
7161
+ taken.set(step.nodeId, step.outcome);
7162
+ return edges.map((edge) => {
7163
+ const branch = edge.data?.branch ?? branchFromHandle(edge.sourceHandle);
7164
+ const active = onPath.has(`${edge.source}->${edge.target}`) && taken.get(edge.source) === branch;
7165
+ return active === Boolean(edge.animated) ? edge : { ...edge, animated: active };
7166
+ });
7167
+ }, [edges, result]);
7168
+ return { effectiveStart, displayNodes, displayEdges };
7169
+ }
7170
+ function RuleCanvas({
7171
+ nodes,
7172
+ edges,
7173
+ isEmpty,
7174
+ canEdit,
7175
+ colorMode,
7176
+ onNodesChange,
7177
+ onEdgesChange,
7178
+ onConnect,
7179
+ onDrop,
7180
+ onNodeClick,
7181
+ onNodesDelete,
7182
+ onPaneClick
7183
+ }) {
7184
+ const tr = useTr();
7185
+ return /* @__PURE__ */ jsxs(
7186
+ "div",
7187
+ {
7188
+ className: "relative min-h-[360px] flex-1",
7189
+ onDragOver: (event) => {
7190
+ event.preventDefault();
7191
+ event.dataTransfer.dropEffect = "move";
7192
+ },
7193
+ onDrop,
7194
+ "data-testid": "rule-canvas",
7195
+ children: [
7196
+ /* @__PURE__ */ jsxs(
7197
+ ReactFlow,
7198
+ {
7199
+ nodes,
7200
+ edges,
7201
+ nodeTypes: NODE_TYPES,
7202
+ defaultEdgeOptions: DEFAULT_EDGE_OPTIONS,
7203
+ colorMode,
7204
+ onNodesChange,
7205
+ onEdgesChange,
7206
+ onConnect,
7207
+ onNodeClick: (_event, node) => onNodeClick(node.id),
7208
+ onNodesDelete: (deleted) => onNodesDelete(deleted.map((node) => node.id)),
7209
+ onPaneClick,
7210
+ nodesDraggable: canEdit,
7211
+ nodesConnectable: canEdit,
7212
+ elementsSelectable: true,
7213
+ deleteKeyCode: canEdit ? ["Backspace", "Delete"] : null,
7214
+ fitView: true,
7215
+ fitViewOptions: { padding: 0.2 },
7216
+ proOptions: { hideAttribution: true },
7217
+ children: [
7218
+ /* @__PURE__ */ jsx(Background, { gap: 20 }),
7219
+ /* @__PURE__ */ jsx(Controls, { showInteractive: false }),
7220
+ /* @__PURE__ */ jsx(MiniMap, { pannable: true, zoomable: true, className: "!hidden md:!block" })
7221
+ ]
7222
+ }
7223
+ ),
7224
+ isEmpty && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center p-6 text-center text-sm text-text-secondary", children: tr(
7225
+ "fluidgrids.rules.emptyCanvas",
7226
+ "Add a block from the palette to start building this rule set."
7227
+ ) })
7228
+ ]
7229
+ }
7230
+ );
7231
+ }
7232
+ function useRuleTestRunner() {
7233
+ const tr = useTr();
7234
+ const { testRuleSet } = useRuleSetMutations();
7235
+ const revision = useRef(0);
7236
+ const [testing, setTesting] = useState(false);
7237
+ const [result, setResult] = useState(null);
7238
+ const invalidate = useCallback(() => {
7239
+ revision.current += 1;
7240
+ setResult(null);
7241
+ }, []);
7242
+ const runTest = useCallback(
7243
+ async (definition, input) => {
7244
+ const submitted = revision.current;
7245
+ setTesting(true);
7246
+ try {
7247
+ const evaluation = await testRuleSet({ definition, input });
7248
+ if (revision.current === submitted) setResult(evaluation);
7249
+ } catch (err) {
7250
+ if (revision.current === submitted) setResult(null);
7251
+ toast.error(
7252
+ err instanceof Error ? err.message : tr("fluidgrids.rules.testFailed", "Failed to test the rule set")
7253
+ );
7254
+ } finally {
7255
+ setTesting(false);
7256
+ }
7257
+ },
7258
+ [testRuleSet, tr]
7259
+ );
7260
+ return { testing, result, invalidate, runTest };
7261
+ }
7262
+ function useRuleSetSave(initial, onInvalidSample) {
7263
+ const tr = useTr();
7264
+ const { updateRuleSet } = useRuleSetMutations();
7265
+ const editRevision = useRef(0);
7266
+ const [saved, setSaved] = useState({
7267
+ version: initial.version,
7268
+ name: initial.name
7269
+ });
7270
+ const [issues, setIssues] = useState(initial.issues);
7271
+ const [dirty, setDirty] = useState(false);
7272
+ const [saving, setSaving] = useState(false);
7273
+ const markDirty = useCallback(() => {
7274
+ editRevision.current += 1;
7275
+ setDirty(true);
7276
+ }, []);
7277
+ const save = useCallback(
7278
+ async (draft) => {
7279
+ const submitted = editRevision.current;
7280
+ if (!draft.name.trim()) {
7281
+ toast.error(
7282
+ tr(
7283
+ "fluidgrids.rules.nameRequired",
7284
+ "Give the rule set a name before saving."
7285
+ )
7286
+ );
7287
+ return;
7288
+ }
7289
+ const sample = parseJsonText(draft.inputText);
7290
+ if (!sample.ok) {
7291
+ onInvalidSample();
7292
+ toast.error(
7293
+ tr(
7294
+ "fluidgrids.rules.sampleInvalid",
7295
+ "Fix the sample input before saving: {{error}}",
7296
+ { error: sample.error }
7297
+ )
7298
+ );
7299
+ return;
7300
+ }
7301
+ setSaving(true);
7302
+ try {
7303
+ const next = await updateRuleSet(initial.id, {
7304
+ name: draft.name.trim(),
7305
+ definition: draft.definition,
7306
+ sampleInput: sample.value,
7307
+ expectedVersion: saved.version
7308
+ });
7309
+ setSaved({ version: next.version, name: next.name });
7310
+ setIssues(next.issues);
7311
+ if (editRevision.current === submitted) setDirty(false);
7312
+ toast.success(tr("fluidgrids.rules.saved", "Rule set saved"));
7313
+ } catch (err) {
7314
+ toast.error(
7315
+ err instanceof Error ? err.message : tr("fluidgrids.rules.saveFailed", "Failed to save the rule set")
7316
+ );
7317
+ } finally {
7318
+ setSaving(false);
7319
+ }
7320
+ },
7321
+ [initial.id, onInvalidSample, saved, tr, updateRuleSet]
7322
+ );
7323
+ return { saved, issues, dirty, saving, markDirty, save };
7324
+ }
7325
+ function RuleEditor({ initial }) {
7326
+ const tr = useTr();
7327
+ const navigate = useNavigate();
7328
+ const { resolvedTheme = "light" } = useTheme();
7329
+ const { screenToFlowPosition, setCenter, getNode } = useReactFlow();
7330
+ const { testing, result, invalidate, runTest } = useRuleTestRunner();
7331
+ const { tables: dataTables } = useDataTables();
7332
+ const { allowed: canEdit } = useFluidGridsPermission(
7333
+ FLUIDGRIDS_PERMISSIONS.WORKFLOW_UPDATE
7334
+ );
7335
+ const [seed] = useState(() => {
7336
+ const definition = readDefinition(initial.definition);
7337
+ return { definition, flow: toFlow(definition) };
7338
+ });
7339
+ const [nodes, setNodes, onNodesChange] = useNodesState(
7340
+ seed.flow.nodes
7341
+ );
7342
+ const [edges, setEdges, onEdgesChange] = useEdgesState(
7343
+ seed.flow.edges
7344
+ );
7345
+ const [startNodeId, setStartNodeId] = useState(
7346
+ seed.definition.startNodeId
7347
+ );
7348
+ const [name, setName] = useState(initial.name);
7349
+ const [inputText, setInputText] = useState(
7350
+ () => JSON.stringify(initial.sampleInput ?? {}, null, 2)
7351
+ );
7352
+ const [selectedId, setSelectedId] = useState(null);
7353
+ const [panel, setPanel] = useState("block");
7354
+ const { saved, issues, dirty, saving, markDirty, save } = useRuleSetSave(
7355
+ initial,
7356
+ () => setPanel("test")
7357
+ );
7358
+ const { effectiveStart, displayNodes, displayEdges } = useDecoratedGraph(
7359
+ nodes,
7360
+ edges,
7361
+ startNodeId,
7362
+ result
7363
+ );
7364
+ const markTestInputDirty = useCallback(() => {
7365
+ markDirty();
7366
+ invalidate();
7367
+ }, [markDirty, invalidate]);
7368
+ const onConnect = useCallback(
7369
+ (connection) => {
7370
+ if (!canConnect(
7371
+ edges,
7372
+ connection.source,
7373
+ connection.target,
7374
+ connection.sourceHandle
7375
+ )) {
7376
+ toast.error(
7377
+ tr(
7378
+ "fluidgrids.rules.connectRefused",
7379
+ "That output is already connected. Remove its connection first."
7380
+ )
7381
+ );
7382
+ return;
7383
+ }
7384
+ const branch = branchFromHandle(connection.sourceHandle);
7385
+ setEdges(
7386
+ (current) => addEdge(
7387
+ toFlowEdge({
7388
+ id: nextEdgeId(current),
7389
+ source: connection.source,
7390
+ target: connection.target,
7391
+ branch
7392
+ }),
7393
+ current
7394
+ )
7395
+ );
7396
+ markTestInputDirty();
7397
+ },
7398
+ [edges, setEdges, markTestInputDirty, tr]
7399
+ );
7400
+ const addBlock = useCallback(
7401
+ (type, position) => {
7402
+ const lowest = nodes.reduce(
7403
+ (max, node) => Math.max(max, node.position.y),
7404
+ -160
7405
+ );
7406
+ const block = createRuleNode(
7407
+ type,
7408
+ position ?? { x: 0, y: lowest + 160 },
7409
+ nodes.map((node) => node.id),
7410
+ ruleBlockTypeLabel(tr, type)
7411
+ );
7412
+ const flowNode = toFlow({ startNodeId: null, nodes: [block], edges: [] }).nodes[0];
7413
+ setNodes((current) => [...current, flowNode]);
7414
+ setSelectedId(block.id);
7415
+ setPanel("block");
7416
+ markTestInputDirty();
7417
+ },
7418
+ [nodes, setNodes, markTestInputDirty, tr]
7419
+ );
7420
+ const onDrop = useCallback(
7421
+ (event) => {
7422
+ event.preventDefault();
7423
+ const type = event.dataTransfer.getData(RULE_BLOCK_DRAG_MIME);
7424
+ if (!RULE_NODE_TYPES.includes(type)) return;
7425
+ addBlock(
7426
+ type,
7427
+ screenToFlowPosition({ x: event.clientX, y: event.clientY })
7428
+ );
7429
+ },
7430
+ [addBlock, screenToFlowPosition]
7431
+ );
7432
+ const handleNodesChange = useCallback(
7433
+ (changes) => {
7434
+ onNodesChange(changes);
7435
+ if (changes.some(
7436
+ (change) => change.type !== "select" && change.type !== "dimensions"
7437
+ )) {
7438
+ markTestInputDirty();
7439
+ }
7440
+ },
7441
+ [onNodesChange, markTestInputDirty]
7442
+ );
7443
+ const handleEdgesChange = useCallback(
7444
+ (changes) => {
7445
+ onEdgesChange(changes);
7446
+ if (changes.some((change) => change.type === "remove"))
7447
+ markTestInputDirty();
7448
+ },
7449
+ [onEdgesChange, markTestInputDirty]
7450
+ );
7451
+ const selectedNode = nodes.find((node) => node.id === selectedId) ?? null;
7452
+ const updateSelected = useCallback(
7453
+ (patch) => {
7454
+ if (!selectedId) return;
7455
+ setNodes(
7456
+ (current) => current.map(
7457
+ (node) => node.id === selectedId ? { ...node, data: { ...node.data, ...patch } } : node
7458
+ )
7459
+ );
7460
+ markTestInputDirty();
7461
+ },
7462
+ [selectedId, setNodes, markTestInputDirty]
7463
+ );
7464
+ const deleteSelected = useCallback(() => {
7465
+ if (!selectedId) return;
7466
+ setNodes((current) => current.filter((node) => node.id !== selectedId));
7467
+ setEdges(
7468
+ (current) => current.filter(
7469
+ (edge) => edge.source !== selectedId && edge.target !== selectedId
7470
+ )
7471
+ );
7472
+ if (startNodeId === selectedId) setStartNodeId(null);
7473
+ setSelectedId(null);
7474
+ markTestInputDirty();
7475
+ }, [selectedId, startNodeId, setNodes, setEdges, markTestInputDirty]);
7476
+ const focusNode = useCallback(
7477
+ (nodeId) => {
7478
+ setSelectedId(nodeId);
7479
+ const node = getNode(nodeId);
7480
+ if (node) {
7481
+ void setCenter(node.position.x + 120, node.position.y + 50, {
7482
+ zoom: 1,
7483
+ duration: 300
7484
+ });
7485
+ }
7486
+ },
7487
+ [getNode, setCenter]
7488
+ );
7489
+ return /* @__PURE__ */ jsxs("div", { className: "flex h-[calc(100vh-4rem)] min-h-[560px] flex-col bg-background-primary", children: [
7490
+ /* @__PURE__ */ jsx(
7491
+ RuleBuilderHeader,
7492
+ {
7493
+ version: saved.version,
7494
+ name,
7495
+ dirty,
7496
+ saving,
7497
+ canEdit,
7498
+ issues,
7499
+ onBack: () => navigate("..", { relative: "path" }),
7500
+ onNameChange: (value) => {
7501
+ setName(value);
7502
+ markDirty();
7503
+ },
7504
+ onSave: () => void save({
7505
+ name,
7506
+ definition: fromFlow(nodes, edges, startNodeId),
7507
+ inputText
7508
+ })
7509
+ }
7510
+ ),
7511
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col lg:flex-row", children: [
7512
+ /* @__PURE__ */ jsx(RulePalette, { canEdit, onAdd: (type) => addBlock(type) }),
7513
+ /* @__PURE__ */ jsx(
7514
+ RuleCanvas,
7515
+ {
7516
+ nodes: displayNodes,
7517
+ edges: displayEdges,
7518
+ isEmpty: nodes.length === 0,
7519
+ canEdit,
7520
+ colorMode: resolvedTheme === "dark" ? "dark" : "light",
7521
+ onNodesChange: handleNodesChange,
7522
+ onEdgesChange: handleEdgesChange,
7523
+ onConnect,
7524
+ onDrop,
7525
+ onNodeClick: (nodeId) => {
7526
+ setSelectedId(nodeId);
7527
+ setPanel("block");
7528
+ },
7529
+ onNodesDelete: (deletedIds) => {
7530
+ if (startNodeId && deletedIds.includes(startNodeId)) {
7531
+ setStartNodeId(null);
7532
+ }
7533
+ setSelectedId(null);
7534
+ },
7535
+ onPaneClick: () => setSelectedId(null)
7536
+ }
7537
+ ),
7538
+ /* @__PURE__ */ jsx(
7539
+ RuleSidePanel,
7540
+ {
7541
+ panel,
7542
+ onPanelChange: setPanel,
7543
+ selectedNode,
7544
+ effectiveStart,
7545
+ canEdit,
7546
+ dataTables,
7547
+ onChangeSelected: updateSelected,
7548
+ onDeleteSelected: deleteSelected,
7549
+ onMakeStart: (nodeId) => {
7550
+ setStartNodeId(nodeId);
7551
+ markTestInputDirty();
7552
+ },
7553
+ issues,
7554
+ onFocusNode: focusNode,
7555
+ inputText,
7556
+ onInputTextChange: (text) => {
7557
+ setInputText(text);
7558
+ markTestInputDirty();
7559
+ },
7560
+ onRunTest: (input) => void runTest(fromFlow(nodes, edges, startNodeId), input),
7561
+ testing,
7562
+ result
7563
+ }
7564
+ )
7565
+ ] })
7566
+ ] });
7567
+ }
7568
+ function RuleBuilderLoader({ ruleSetId }) {
7569
+ const tr = useTr();
7570
+ const navigate = useNavigate();
7571
+ const { ruleSet, loading, error } = useRuleSet(ruleSetId);
7572
+ if (loading && !ruleSet) {
7573
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-[60vh] items-center justify-center text-text-secondary", children: [
7574
+ /* @__PURE__ */ jsx(Loader2, { className: "mr-2 size-5 animate-spin", "aria-hidden": "true" }),
7575
+ tr("fluidgrids.rules.loadingRuleSet", "Loading rule set\u2026")
7576
+ ] });
7577
+ }
7578
+ if (!ruleSet) {
7579
+ return /* @__PURE__ */ jsxs("div", { className: "flex min-h-[60vh] flex-col items-center justify-center gap-3 text-text-secondary", children: [
7580
+ /* @__PURE__ */ jsx("p", { children: error?.message ?? tr("fluidgrids.rules.notFound", "This rule set was not found.") }),
7581
+ /* @__PURE__ */ jsxs(
7582
+ Button$1,
7583
+ {
7584
+ variant: "outline",
7585
+ onClick: () => navigate("..", { relative: "path" }),
7586
+ children: [
7587
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "mr-2 size-4", "aria-hidden": "true" }),
7588
+ tr("fluidgrids.rules.backToRuleSets", "Back to rule sets")
7589
+ ]
7590
+ }
7591
+ )
7592
+ ] });
7593
+ }
7594
+ return /* @__PURE__ */ jsx(RuleEditor, { initial: ruleSet }, ruleSet.id);
7595
+ }
7596
+ function RuleBuilderPage() {
7597
+ const { ruleSetId } = useParams();
7598
+ return /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(RuleBuilderLoader, { ruleSetId: ruleSetId ?? "" }, ruleSetId) });
7599
+ }
5023
7600
 
5024
7601
  // src/graphql/client-helpers.ts
5025
7602
  function createFluidGridsClients(config2) {
@@ -5103,7 +7680,7 @@ var NODE_STATUS_CONFIG = {
5103
7680
  bgColor: "bg-bg-sunken"
5104
7681
  }
5105
7682
  };
5106
- var Textarea4 = React3.forwardRef(
7683
+ var Textarea7 = React3.forwardRef(
5107
7684
  ({ className, ...props }, ref) => {
5108
7685
  return /* @__PURE__ */ jsx(
5109
7686
  "textarea",
@@ -5118,7 +7695,7 @@ var Textarea4 = React3.forwardRef(
5118
7695
  );
5119
7696
  }
5120
7697
  );
5121
- Textarea4.displayName = "Textarea";
7698
+ Textarea7.displayName = "Textarea";
5122
7699
  function Tabs2({
5123
7700
  className,
5124
7701
  ...props
@@ -6124,4 +8701,4 @@ function createFluidGridsAgentTools(deps) {
6124
8701
  ];
6125
8702
  }
6126
8703
 
6127
- export { AiStudioPage, ApprovalInboxPage, Checkbox, DataTablesPage, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FluidGridsRoot, NODE_STATUS_CONFIG, RUN_STATUS_CONFIG, RunnersPage, ScrollArea, ScrollBar, Select3 as Select, SelectContent3 as SelectContent, SelectGroup, SelectItem3 as SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger3 as SelectTrigger, SelectValue3 as SelectValue, Separator, Switch2 as Switch, Tabs2 as Tabs, TabsContent2 as TabsContent, TabsList2 as TabsList, TabsTrigger2 as TabsTrigger, Textarea4 as Textarea, VariablesPage, WorkflowEmbedPage, createFluidGridsAgentTools, createFluidGridsClients, csvToRows, parseCsv, pickTriggerNode, rowsToCsv, triggerNodesOf, useCreateDataTable, useCreateVariable, useDataTableRows, useDataTables, useDecideToolApproval, useDeleteDataTable, useDeleteDataTableRows, useDeleteVariable, useInsertDataTableRow, usePendingToolApprovals, useRevealVariableValue, useSaveSecretsProviderConfig, useSecretsProviderConfigs, useTestSecretsProviderConnection, useUpdateDataTable, useUpdateDataTableRow, useUpdateVariable, useVariables };
8704
+ export { AiStudioPage, ApprovalInboxPage, Checkbox, DataTablesPage, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, FluidGridsRoot, NODE_STATUS_CONFIG, RUN_STATUS_CONFIG, RuleBuilderPage, RuleSetsPage, RunnersPage, ScrollArea, ScrollBar, Select3 as Select, SelectContent3 as SelectContent, SelectGroup, SelectItem3 as SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger3 as SelectTrigger, SelectValue3 as SelectValue, Separator, Switch2 as Switch, Tabs2 as Tabs, TabsContent2 as TabsContent, TabsList2 as TabsList, TabsTrigger2 as TabsTrigger, Textarea7 as Textarea, VariablesPage, WorkflowEmbedPage, createFluidGridsAgentTools, createFluidGridsClients, csvToRows, parseCsv, pickTriggerNode, rowsToCsv, triggerNodesOf, useCreateDataTable, useCreateVariable, useDataTableRows, useDataTables, useDecideToolApproval, useDeleteDataTable, useDeleteDataTableRows, useDeleteVariable, useInsertDataTableRow, usePendingToolApprovals, useRevealVariableValue, useRuleSet, useRuleSetMutations, useRuleSetTemplates, useRuleSets, useSaveSecretsProviderConfig, useSecretsProviderConfigs, useTestSecretsProviderConnection, useUpdateDataTable, useUpdateDataTableRow, useUpdateVariable, useVariables };