@taskforcehq/taskforce 0.3.304 → 0.3.306
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -247
- package/dist/Taskforce.module.css +295 -89
- package/dist/TaskforceCore.js +378 -111
- package/dist/TaskforceCore.test.js +1221 -107
- package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/assets/fonts/Noir_medium.woff2 +0 -0
- package/dist/assets/fonts/Noir_regular.woff2 +0 -0
- package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/compat/workspaceSyncCompat.js +52 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +549 -0
- package/dist/components/features/AgentsModule.d.ts +10 -1
- package/dist/components/features/AgentsModule.js +260 -15
- package/dist/components/features/AgentsModule.test.js +255 -5
- package/dist/components/features/DocumentIndex.d.ts +1 -1
- package/dist/components/features/DocumentIndex.js +1 -1
- package/dist/components/features/DocumentViewer.d.ts +6 -2
- package/dist/components/features/DocumentViewer.js +90 -10
- package/dist/components/features/DocumentWorkspace.d.ts +5 -22
- package/dist/components/features/DocumentWorkspace.js +12 -155
- package/dist/components/features/DocumentWorkspace.test.js +226 -6
- package/dist/components/features/TaskSettings.js +29 -3
- package/dist/components/features/TaskSettings.test.js +42 -1
- package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
- package/dist/components/features/documentWorkspaceModel.js +57 -0
- package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
- package/dist/components/features/useDocumentWorkspaceController.js +113 -0
- package/dist/components/task/TaskCard.js +19 -28
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskForm.d.ts +8 -8
- package/dist/components/task/TaskForm.js +362 -230
- package/dist/components/task/TaskForm.test.js +558 -381
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +96 -14
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +70 -17
- package/dist/components/views/PlanComparisonPage.test.js +289 -41
- package/dist/components/views/PlansPage.js +239 -106
- package/dist/components/views/PlansPage.test.js +593 -42
- package/dist/components/views/StandaloneLayout.js +310 -554
- package/dist/components/views/panels/FilterToolbar.test.js +6 -4
- package/dist/components/views/panels/PlanningDrawer.d.ts +8 -1
- package/dist/components/views/panels/PlanningDrawer.js +18 -11
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +141 -0
- package/dist/components/views/planningScope.d.ts +20 -0
- package/dist/components/views/planningScope.js +25 -0
- package/dist/components/views/planningScope.test.d.ts +1 -0
- package/dist/components/views/planningScope.test.js +60 -0
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +27 -14
- package/dist/components/views/standalone/modals/AccountHubModal.js +87 -15
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +42 -2
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
- package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
- package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
- package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
- package/dist/config/envSchema.js +1 -1
- package/dist/core/AiProfileService.d.ts +45 -3
- package/dist/core/AiProfileService.js +774 -63
- package/dist/core/AiProfileService.test.js +22 -2
- package/dist/core/AiProfiles.test.js +761 -2
- package/dist/core/AttachmentLinkService.js +57 -15
- package/dist/core/AuthIdentityService.d.ts +107 -0
- package/dist/core/AuthIdentityService.js +284 -0
- package/dist/core/AuthTokenService.d.ts +4 -0
- package/dist/core/AuthTokenService.js +34 -6
- package/dist/core/AuthTokenService.test.d.ts +1 -0
- package/dist/core/AuthTokenService.test.js +78 -0
- package/dist/core/EntitlementsPolicy.test.js +77 -15
- package/dist/core/GlobalSettingsService.js +115 -6
- package/dist/core/PlanEntitlementService.d.ts +30 -3
- package/dist/core/PlanEntitlementService.js +454 -93
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +54 -28
- package/dist/core/PlanningEntities.test.js +52 -0
- package/dist/core/SignupMonetizationSettings.test.js +241 -44
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +244 -88
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskTaxonomyValidation.test.js +53 -0
- package/dist/core/Taskforce.d.ts +228 -14
- package/dist/core/Taskforce.js +814 -201
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
- package/dist/core/WorkspaceLifecycleService.js +0 -5
- package/dist/core/WorkspacePermissions.test.js +25 -1
- package/dist/core/WorkspacePlanMode.test.js +128 -27
- package/dist/core/shared.d.ts +3 -1
- package/dist/core/shared.js +16 -1
- package/dist/core/types.d.ts +68 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +26 -1
- package/dist/hooks/sync/auth.js +3 -1
- package/dist/hooks/sync/bootstrap.js +2 -0
- package/dist/hooks/sync/controlPlane.d.ts +37 -0
- package/dist/hooks/sync/controlPlane.js +78 -0
- package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
- package/dist/hooks/sync/controlPlane.test.js +121 -0
- package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
- package/dist/hooks/sync/lifecyclePolicy.js +93 -0
- package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
- package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +10 -1
- package/dist/hooks/sync/orchestratorShared.js +68 -47
- package/dist/hooks/sync/orchestratorShared.test.js +50 -1
- package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
- package/dist/hooks/sync/pullLifecycle.js +24 -0
- package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
- package/dist/hooks/sync/pullLifecycle.test.js +80 -0
- package/dist/hooks/sync/recovery.d.ts +16 -2
- package/dist/hooks/sync/recovery.js +171 -53
- package/dist/hooks/sync/recovery.test.d.ts +1 -0
- package/dist/hooks/sync/recovery.test.js +292 -0
- package/dist/hooks/sync/transfers.d.ts +16 -3
- package/dist/hooks/sync/transfers.js +186 -65
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +396 -0
- package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
- package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
- package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
- package/dist/hooks/sync/useSyncStatusActions.js +88 -0
- package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
- package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
- package/dist/hooks/sync/useSyncStatusControls.js +60 -0
- package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +16 -6
- package/dist/hooks/useSyncOrchestrator.js +424 -175
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +487 -10
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskMutations.d.ts +2 -1
- package/dist/hooks/useTaskMutations.js +12 -1
- package/dist/hooks/useTaskMutations.test.js +30 -1
- package/dist/hooks/useTaskforce.d.ts +65 -4
- package/dist/hooks/useTaskforce.js +564 -243
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +152 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2454 -208
- package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
- package/dist/hooks/useWorkspaceSyncController.js +17 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +316 -35
- package/dist/localization/locales/en-US.d.ts +0 -1
- package/dist/localization/locales/en-US.js +0 -1
- package/dist/localization/locales/es-419.js +0 -1
- package/dist/localization/locales/pt-BR.js +0 -1
- package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
- package/dist/mcp/collaborationRegistrar.d.ts +2 -0
- package/dist/mcp/collaborationRegistrar.js +71 -0
- package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
- package/dist/mcp/documentAssetRegistrar.js +346 -0
- package/dist/mcp/runtime.d.ts +2 -0
- package/dist/mcp/runtime.js +2433 -3534
- package/dist/mcp/runtime.test.js +440 -2
- package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
- package/dist/mcp/taskPlanningRegistrar.js +418 -0
- package/dist/mcp/toolCatalog.d.ts +35 -0
- package/dist/mcp/toolCatalog.js +3 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +171 -61
- package/dist/migrations/taskSchemaMigrations.test.js +15 -0
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/dist/resources/templates/workflows/collaborate.yaml +1 -1
- package/dist/resources/templates/workflows/evaluate.yaml +2 -2
- package/dist/resources/templates/workflows/plan.yaml +1 -1
- package/dist/resources/templates/workflows/review.yaml +2 -2
- package/dist/server/annotatedAttachmentsRoutes.test.js +3 -3
- package/dist/server/auth/providers/apple.d.ts +33 -0
- package/dist/server/auth/providers/apple.js +82 -0
- package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
- package/dist/server/auth/providers/appleClientSecret.js +65 -0
- package/dist/server/auth/providers/github.d.ts +26 -0
- package/dist/server/auth/providers/github.js +86 -0
- package/dist/server/auth/providers/google.d.ts +21 -0
- package/dist/server/auth/providers/google.js +56 -0
- package/dist/server/auth/providers/types.d.ts +21 -0
- package/dist/server/auth/providers/types.js +1 -0
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +6 -3
- package/dist/server/documentReviewRoutes.test.js +36 -3
- package/dist/server/index.cookieProxy.test.js +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +120 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +106 -3
- package/dist/server/routes/admin.d.ts +4 -5
- package/dist/server/routes/admin.js +410 -80
- package/dist/server/routes/annotatedAttachments.d.ts +1 -1
- package/dist/server/routes/annotatedAttachments.js +1 -1
- package/dist/server/routes/auth.d.ts +16 -6
- package/dist/server/routes/auth.js +1015 -118
- package/dist/server/routes/authSupport.d.ts +30 -0
- package/dist/server/routes/authSupport.js +81 -0
- package/dist/server/routes/billing.d.ts +1 -1
- package/dist/server/routes/billing.js +276 -34
- package/dist/server/routes/billing.test.js +760 -52
- package/dist/server/routes/documentReviews.d.ts +1 -1
- package/dist/server/routes/documentReviews.js +1 -1
- package/dist/server/routes/documents.d.ts +5 -2
- package/dist/server/routes/documents.js +242 -74
- package/dist/server/routes/primitives.d.ts +11 -0
- package/dist/server/routes/primitives.js +73 -0
- package/dist/server/routes/resources.d.ts +1 -1
- package/dist/server/routes/resources.js +1 -1
- package/dist/server/routes/shared.d.ts +29 -3
- package/dist/server/routes/shared.js +69 -4
- package/dist/server/routes/sync.d.ts +1 -1
- package/dist/server/routes/sync.integration.test.js +437 -39
- package/dist/server/routes/sync.js +62 -606
- package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
- package/dist/server/routes/syncAuxRoutes.js +91 -0
- package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
- package/dist/server/routes/syncAuxRoutes.test.js +158 -0
- package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
- package/dist/server/routes/syncPullApplyRoutes.js +204 -0
- package/dist/server/routes/syncPushRoutes.d.ts +24 -0
- package/dist/server/routes/syncPushRoutes.js +212 -0
- package/dist/server/routes/syncRouteGuards.d.ts +36 -0
- package/dist/server/routes/syncRouteGuards.js +67 -0
- package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
- package/dist/server/routes/syncRouteGuards.test.js +94 -0
- package/dist/server/routes/syncRouteTypes.d.ts +13 -0
- package/dist/server/routes/syncRouteTypes.js +1 -0
- package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
- package/dist/server/routes/syncSnapshotRoutes.js +180 -0
- package/dist/server/routes/tasks.d.ts +1 -1
- package/dist/server/routes/tasks.js +44 -2
- package/dist/server/routes/workspaces.d.ts +1 -1
- package/dist/server/routes/workspaces.js +37 -6
- package/dist/server/routes.d.ts +2 -9
- package/dist/server/routes.js +136 -165
- package/dist/server/routes.test.js +2457 -162
- package/dist/services/workflowExportSnapshots.test.js +2 -0
- package/dist/shared/aiProfileSeatScope.d.ts +5 -0
- package/dist/shared/aiProfileSeatScope.js +21 -0
- package/dist/shared/passwordPolicy.d.ts +13 -0
- package/dist/shared/passwordPolicy.js +84 -0
- package/dist/shared/passwordPolicy.test.d.ts +1 -0
- package/dist/shared/passwordPolicy.test.js +34 -0
- package/dist/storage/workspaceAssetStore.d.ts +15 -3
- package/dist/storage/workspaceAssetStore.js +132 -44
- package/dist/storage/workspaceAssetStore.test.js +93 -6
- package/dist/styles/fonts.css +70 -0
- package/dist/sync/collaborationSyncPayload.d.ts +6 -1
- package/dist/sync/collaborationSyncPayload.js +17 -11
- package/dist/sync/collaborationSyncPayload.test.js +13 -1
- package/dist/sync/contentSyncState.d.ts +4 -8
- package/dist/sync/contentSyncState.js +33 -77
- package/dist/sync/syncApplyHandlers.d.ts +7 -0
- package/dist/sync/syncApplyHandlers.js +28 -13
- package/dist/sync/syncApplyHandlers.test.js +72 -3
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +44 -0
- package/dist/sync/syncResourceAdapters.js +77 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +60 -0
- package/dist/sync/syncService.test.js +71 -3
- package/dist/sync/taskSyncChangeKey.d.ts +2 -0
- package/dist/sync/taskSyncChangeKey.js +143 -0
- package/dist/sync/taskSyncPayload.js +3 -8
- package/dist/sync/workspacePullFeed.js +4 -3
- package/dist/sync/workspacePullFeed.test.js +43 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +48 -0
- package/dist/sync/workspaceSyncModel.js +195 -31
- package/dist/sync/workspaceSyncModel.test.js +325 -12
- package/dist/sync/workspaceSyncState.d.ts +19 -0
- package/dist/sync/workspaceSyncState.js +3 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +17 -0
- package/dist/ui/assets/AgentsModule-DrLawwNl.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BlS-cqnl.js → AnnotatedAttachmentWorkspace-Z9_whf7F.js} +1 -1
- package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
- package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +252 -0
- package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +1 -0
- package/dist/ui/assets/{InitiativesModule-BjR6iBf9.js → InitiativesModule-9E6ParrY.js} +1 -1
- package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
- package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
- package/dist/ui/assets/PlansPage-CvfnMiWq.css +1 -0
- package/dist/ui/assets/PlansPage-DRXscYxH.js +1 -0
- package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
- package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
- package/dist/ui/assets/TaskSettings-DZX4jk7e.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-DnFqdUME.js → WorkflowsModule-BA7jcEpH.js} +1 -1
- package/dist/ui/assets/index-9eT8e0Lu.css +1 -0
- package/dist/ui/assets/index-C6k75jr8.js +6 -0
- package/dist/ui/assets/{vendor-icons-I7ZwG1z_.js → vendor-icons-DuEd_65c.js} +1 -1
- package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/ui/fonts/Noir_medium.otf +0 -0
- package/dist/ui/fonts/Noir_medium.woff2 +0 -0
- package/dist/ui/fonts/Noir_regular.otf +0 -0
- package/dist/ui/fonts/Noir_regular.woff2 +0 -0
- package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/assignees.d.ts +2 -0
- package/dist/utils/assignees.js +2 -0
- package/dist/utils/avatarUpload.d.ts +27 -0
- package/dist/utils/avatarUpload.js +132 -0
- package/dist/utils/avatarUpload.test.d.ts +1 -0
- package/dist/utils/avatarUpload.test.js +40 -0
- package/dist/utils/bootstrapTrace.d.ts +7 -0
- package/dist/utils/bootstrapTrace.js +29 -0
- package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
- package/dist/utils/commercialLifecyclePresentation.js +199 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- package/dist/utils/syncEventDetails.d.ts +3 -0
- package/dist/utils/syncEventDetails.js +64 -0
- package/dist/utils/syncEventDetails.test.d.ts +1 -0
- package/dist/utils/syncEventDetails.test.js +23 -0
- package/dist/utils/syncEventPresentation.d.ts +15 -0
- package/dist/utils/syncEventPresentation.js +129 -0
- package/dist/utils/syncEventPresentation.test.d.ts +1 -0
- package/dist/utils/syncEventPresentation.test.js +64 -0
- package/dist/utils/syncStatusPresentation.d.ts +72 -0
- package/dist/utils/syncStatusPresentation.js +217 -0
- package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
- package/dist/utils/syncStatusPresentation.test.js +164 -0
- package/dist/utils/taskActivity.d.ts +2 -0
- package/dist/utils/taskActivity.js +228 -22
- package/dist/utils/taskActivity.test.js +119 -8
- package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.js +68 -2
- package/dist/utils/workspaceSyncPresentation.test.js +36 -1
- package/package.json +10 -2
- package/scripts/check-cloud-mcp.mjs +83 -0
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- package/scripts/playwright-auth.sh +5 -1
- package/scripts/run-billing-performance-smoke.sh +24 -0
- package/scripts/run-e2e-realtime.sh +17 -3
- package/scripts/run-smoke.sh +17 -5
- package/scripts/run-soak.sh +17 -5
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/src/resources/templates/workflows/collaborate.yaml +1 -1
- package/src/resources/templates/workflows/evaluate.yaml +2 -2
- package/src/resources/templates/workflows/plan.yaml +1 -1
- package/src/resources/templates/workflows/review.yaml +2 -2
- package/dist/ui/assets/AgentsModule-BLWVbuKP.js +0 -1
- package/dist/ui/assets/DocumentWorkspace-BH_6DF6x.js +0 -250
- package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-CSDQ4sLa.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/TaskSettings-CEDy34Jo.js +0 -9
- package/dist/ui/assets/index-DXUdtH1B.js +0 -6
- package/dist/ui/assets/index-Ii0B0rTO.css +0 -1
- package/scripts/migrate-planning-model.ts +0 -233
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { useLocation, useNavigate } from 'react-router-dom';
|
|
4
4
|
import { User } from 'lucide-react';
|
|
@@ -7,21 +7,31 @@ import { PlanComparisonPage } from './PlanComparisonPage';
|
|
|
7
7
|
import { AppShellHeader } from './AppShellHeader';
|
|
8
8
|
import { resolveTaskforceCloudEnvironmentFromBaseUrl } from '../../config/cloudEnvironment';
|
|
9
9
|
import { ACCOUNT_PROFILE_SUMMARY_PATH, invalidateAccountProfileSummaryCache, loadAccountProfileSummaryCached } from '../../utils/accountProfileSummaryCache';
|
|
10
|
+
import { isCommercialEntitlementActive, resolveCommercialLifecyclePresentation } from '../../utils/commercialLifecyclePresentation';
|
|
10
11
|
const TRANSIENT_CHECKOUT_QUERY_CLEAR_DELAY_MS = 1600;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
const CHECKOUT_CONFIRM_INITIAL_RETRY_DELAYS_MS = [0, 500, 1000, 2000];
|
|
13
|
+
const CHECKOUT_CONFIRM_RETRY_INTERVAL_MS = 5000;
|
|
14
|
+
const CHECKOUT_CONFIRM_MAX_AUTO_RETRY_MS = 45000;
|
|
15
|
+
const HIDDEN_GATE_MESSAGE = 'Choose a plan to continue.';
|
|
16
|
+
function shouldRetryCheckoutConfirmation(statusCode, errorCode) {
|
|
17
|
+
if (statusCode === 401) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
const normalizedErrorCode = String(errorCode || '').trim().toUpperCase();
|
|
21
|
+
return normalizedErrorCode === 'CHECKOUT_SESSION_INCOMPLETE'
|
|
22
|
+
|| normalizedErrorCode === 'CHECKOUT_PLAN_VERSION_UNRESOLVED';
|
|
23
|
+
}
|
|
22
24
|
function parseInterval(raw) {
|
|
23
25
|
return raw === 'year' ? 'year' : 'month';
|
|
24
26
|
}
|
|
27
|
+
function normalizeIntervalValue(raw) {
|
|
28
|
+
const normalized = String(raw || '').trim().toLowerCase();
|
|
29
|
+
if (normalized === 'year')
|
|
30
|
+
return 'year';
|
|
31
|
+
if (normalized === 'month')
|
|
32
|
+
return 'month';
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
25
35
|
function normalizeApiBaseUrl(raw) {
|
|
26
36
|
const trimmed = String(raw || '').trim();
|
|
27
37
|
if (!trimmed)
|
|
@@ -43,15 +53,19 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
43
53
|
const location = useLocation();
|
|
44
54
|
const [accountProfileSummary, setAccountProfileSummary] = useState(null);
|
|
45
55
|
const [actionBusy, setActionBusy] = useState(false);
|
|
56
|
+
const [continueActionBusy, setContinueActionBusy] = useState(false);
|
|
46
57
|
const [feedback, setFeedback] = useState(null);
|
|
47
58
|
const checkoutStartRan = useRef(false);
|
|
59
|
+
const checkoutSuccessSettledRef = useRef(null);
|
|
48
60
|
const transientQueryClearTimeoutRef = useRef(null);
|
|
61
|
+
const onContinueToTaskforceRef = useRef(onContinueToTaskforce);
|
|
49
62
|
const query = useMemo(() => new URLSearchParams(location.search), [location.search]);
|
|
50
63
|
const checkoutState = String(query.get('checkout') || '').trim().toLowerCase();
|
|
51
64
|
const gateState = String(query.get('gate') || '').trim().toLowerCase();
|
|
52
65
|
const queryPlanId = String(query.get('planId') || '').trim();
|
|
53
66
|
const queryPlanVersionId = String(query.get('planVersionId') || '').trim();
|
|
54
67
|
const queryInterval = parseInterval(query.get('interval'));
|
|
68
|
+
const queryIntervalValue = normalizeIntervalValue(query.get('interval'));
|
|
55
69
|
const querySessionId = String(query.get('session_id') || '').trim();
|
|
56
70
|
const normalizedApiBaseUrl = useMemo(() => normalizeApiBaseUrl(apiBaseUrl), [apiBaseUrl]);
|
|
57
71
|
const normalizedConnectedEnvironmentSource = useMemo(() => normalizeApiBaseUrl(connectedEnvironmentSource), [connectedEnvironmentSource]);
|
|
@@ -82,39 +96,15 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
82
96
|
const nextQuery = params.toString();
|
|
83
97
|
navigate(`/${nextQuery ? `?${nextQuery}` : ''}${location.hash || ''}`);
|
|
84
98
|
}, [location.hash, location.search, navigate]);
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
'/api/taskforce/public/pricing'
|
|
89
|
-
].map((value) => String(value || '').trim()).filter((value, index, all) => value && all.indexOf(value) === index);
|
|
90
|
-
return endpoints;
|
|
91
|
-
}, [normalizedApiBaseUrl]);
|
|
92
|
-
const hasResolvedActiveEntitlement = useMemo(() => {
|
|
93
|
-
const entitlementState = String(accountProfileSummary?.entitlementState || '').trim().toLowerCase();
|
|
94
|
-
return ACTIVE_ENTITLEMENT_STATES.has(entitlementState);
|
|
95
|
-
}, [accountProfileSummary?.entitlementState]);
|
|
99
|
+
const pricingEndpoint = useMemo(() => buildCloudBillingUrl('/api/taskforce/public/pricing'), [buildCloudBillingUrl]);
|
|
100
|
+
const lifecyclePresentation = useMemo(() => resolveCommercialLifecyclePresentation(accountProfileSummary, gateState), [accountProfileSummary, gateState]);
|
|
101
|
+
const hasResolvedActiveEntitlement = useMemo(() => lifecyclePresentation.allowReturnToApp, [lifecyclePresentation.allowReturnToApp]);
|
|
96
102
|
const gateMessage = useMemo(() => {
|
|
97
|
-
|
|
103
|
+
const message = String(lifecyclePresentation.message || '').trim();
|
|
104
|
+
if (!message || message === HIDDEN_GATE_MESSAGE)
|
|
98
105
|
return null;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_EXPIRED;
|
|
102
|
-
if (billingConflictCode === 'CHECKOUT_SESSION_SUPERSEDED')
|
|
103
|
-
return BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_SUPERSEDED;
|
|
104
|
-
const summaryMessage = String(accountProfileSummary?.message || '').trim();
|
|
105
|
-
if (summaryMessage)
|
|
106
|
-
return summaryMessage;
|
|
107
|
-
const effectiveGateState = String(accountProfileSummary?.gate || gateState || '').trim().toLowerCase();
|
|
108
|
-
if (effectiveGateState === 'plan_selection_required')
|
|
109
|
-
return GATE_MESSAGES.planSelectionRequired;
|
|
110
|
-
if (effectiveGateState === 'checkout_pending')
|
|
111
|
-
return GATE_MESSAGES.checkoutPending;
|
|
112
|
-
if (effectiveGateState === 'misconfigured')
|
|
113
|
-
return GATE_MESSAGES.misconfigured;
|
|
114
|
-
if (effectiveGateState === 'missing_entitlement')
|
|
115
|
-
return GATE_MESSAGES.missingEntitlement;
|
|
116
|
-
return null;
|
|
117
|
-
}, [accountProfileSummary?.billingConflictCode, accountProfileSummary?.gate, accountProfileSummary?.message, gateState, hasResolvedActiveEntitlement]);
|
|
106
|
+
return message;
|
|
107
|
+
}, [lifecyclePresentation.message]);
|
|
118
108
|
const clearTransientQueryState = useCallback(() => {
|
|
119
109
|
const next = new URLSearchParams(location.search);
|
|
120
110
|
next.delete('checkout');
|
|
@@ -135,6 +125,9 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
135
125
|
transientQueryClearTimeoutRef.current = null;
|
|
136
126
|
}, TRANSIENT_CHECKOUT_QUERY_CLEAR_DELAY_MS);
|
|
137
127
|
}, [clearTransientQueryState]);
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
onContinueToTaskforceRef.current = onContinueToTaskforce;
|
|
130
|
+
}, [onContinueToTaskforce]);
|
|
138
131
|
const loadAccountProfileSummary = useCallback(async (options) => {
|
|
139
132
|
const accountProfileSummaryUrl = buildCloudBillingUrl(ACCOUNT_PROFILE_SUMMARY_PATH);
|
|
140
133
|
if (!isAuthenticated) {
|
|
@@ -156,31 +149,23 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
156
149
|
return null;
|
|
157
150
|
}
|
|
158
151
|
}, [authUserId, buildCloudBillingUrl, isAuthenticated, onAccountProfileSummaryChange]);
|
|
159
|
-
const resolveRecoveryMessage = useCallback((summary, fallback) => {
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
162
|
-
return
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const resolveGateFeedbackType = useCallback((message) => {
|
|
171
|
-
const normalized = String(message || '').trim();
|
|
172
|
-
if (normalized === GATE_MESSAGES.planSelectionRequired
|
|
173
|
-
|| normalized === GATE_MESSAGES.checkoutPending) {
|
|
174
|
-
return 'info';
|
|
175
|
-
}
|
|
176
|
-
return 'error';
|
|
152
|
+
const resolveRecoveryMessage = useCallback((summary, fallback, options) => {
|
|
153
|
+
const normalizedFallback = String(fallback || '').trim();
|
|
154
|
+
if (options?.preferFallback && normalizedFallback)
|
|
155
|
+
return normalizedFallback;
|
|
156
|
+
const message = resolveCommercialLifecyclePresentation(summary, gateState).message;
|
|
157
|
+
if (message)
|
|
158
|
+
return message;
|
|
159
|
+
return normalizedFallback || 'Unable to confirm checkout completion.';
|
|
160
|
+
}, [gateState]);
|
|
161
|
+
const shouldAutoContinueAfterActivation = useCallback((summary, fallbackGate) => {
|
|
162
|
+
return !resolveCommercialLifecyclePresentation(summary, fallbackGate).allowReturnToApp;
|
|
177
163
|
}, []);
|
|
178
|
-
const startCheckout = useCallback(async (planVersionId, interval) => {
|
|
164
|
+
const startCheckout = useCallback(async (planVersionId, interval, options) => {
|
|
179
165
|
if (!planVersionId) {
|
|
180
166
|
setFeedback({ type: 'error', message: 'Selected plan is missing a default plan version.' });
|
|
181
167
|
return;
|
|
182
168
|
}
|
|
183
|
-
const hadActiveEntitlement = hasResolvedActiveEntitlement;
|
|
184
169
|
setActionBusy(true);
|
|
185
170
|
setFeedback(null);
|
|
186
171
|
try {
|
|
@@ -201,7 +186,7 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
201
186
|
invalidateAccountProfileSummaryCache(buildCloudBillingUrl(ACCOUNT_PROFILE_SUMMARY_PATH), { identityKey: authUserId });
|
|
202
187
|
const summary = await loadAccountProfileSummary({ force: true });
|
|
203
188
|
const summaryState = String(summary?.entitlementState || '').trim().toLowerCase();
|
|
204
|
-
if (
|
|
189
|
+
if (options?.autoContinueOnActivation === true && isCommercialEntitlementActive(summaryState)) {
|
|
205
190
|
await onContinueToTaskforce?.();
|
|
206
191
|
}
|
|
207
192
|
return;
|
|
@@ -211,7 +196,7 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
211
196
|
invalidateAccountProfileSummaryCache(buildCloudBillingUrl(ACCOUNT_PROFILE_SUMMARY_PATH), { identityKey: authUserId });
|
|
212
197
|
const summary = await loadAccountProfileSummary({ force: true });
|
|
213
198
|
const summaryState = String(summary?.entitlementState || '').trim().toLowerCase();
|
|
214
|
-
if (
|
|
199
|
+
if (options?.autoContinueOnActivation === true && isCommercialEntitlementActive(summaryState)) {
|
|
215
200
|
await onContinueToTaskforce?.();
|
|
216
201
|
}
|
|
217
202
|
return;
|
|
@@ -253,14 +238,56 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
253
238
|
finally {
|
|
254
239
|
setActionBusy(false);
|
|
255
240
|
}
|
|
256
|
-
}, [authUserId, buildCloudBillingUrl,
|
|
257
|
-
const confirmCheckoutSession = useCallback(async (sessionId) => {
|
|
241
|
+
}, [authUserId, buildCloudBillingUrl, loadAccountProfileSummary, onContinueToTaskforce, runtimeMode]);
|
|
242
|
+
const confirmCheckoutSession = useCallback(async (sessionId, options) => {
|
|
258
243
|
if (!sessionId) {
|
|
259
244
|
return {
|
|
260
245
|
confirmed: false,
|
|
261
|
-
errorMessage: 'Checkout session is missing.'
|
|
246
|
+
errorMessage: 'Checkout session is missing.',
|
|
247
|
+
retryable: false
|
|
262
248
|
};
|
|
263
249
|
}
|
|
250
|
+
const confirmViaSummary = async () => {
|
|
251
|
+
invalidateAccountProfileSummaryCache(buildCloudBillingUrl(ACCOUNT_PROFILE_SUMMARY_PATH), { identityKey: authUserId });
|
|
252
|
+
const summary = await loadAccountProfileSummary({ force: true });
|
|
253
|
+
const summaryState = String(summary?.entitlementState || '').trim().toLowerCase();
|
|
254
|
+
if (!isCommercialEntitlementActive(summaryState)) {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
const expectedPlanId = queryPlanId;
|
|
258
|
+
const expectedPlanVersionId = queryPlanVersionId;
|
|
259
|
+
const expectedInterval = queryIntervalValue;
|
|
260
|
+
const currentPlanId = String(summary?.planId || '').trim();
|
|
261
|
+
const currentPlanVersionId = String(summary?.planVersionId || '').trim();
|
|
262
|
+
const currentInterval = normalizeIntervalValue(summary?.billingInterval ?? null);
|
|
263
|
+
const preSummary = options?.preConfirmationSummary ?? null;
|
|
264
|
+
const preState = String(preSummary?.entitlementState || '').trim().toLowerCase();
|
|
265
|
+
const preWasActive = isCommercialEntitlementActive(preState);
|
|
266
|
+
const prePlanId = String(preSummary?.planId || '').trim();
|
|
267
|
+
const prePlanVersionId = String(preSummary?.planVersionId || '').trim();
|
|
268
|
+
const preInterval = normalizeIntervalValue(preSummary?.billingInterval ?? null);
|
|
269
|
+
if (expectedPlanId && currentPlanId && currentPlanId !== expectedPlanId) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
272
|
+
if (expectedPlanVersionId && currentPlanVersionId && currentPlanVersionId !== expectedPlanVersionId) {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
if (expectedInterval && currentInterval && currentInterval !== expectedInterval) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
if (preWasActive) {
|
|
279
|
+
const requestedPlanChanged = Boolean(expectedPlanId) && currentPlanId === expectedPlanId && prePlanId !== currentPlanId;
|
|
280
|
+
const requestedPlanVersionChanged = Boolean(expectedPlanVersionId) && currentPlanVersionId === expectedPlanVersionId && prePlanVersionId !== currentPlanVersionId;
|
|
281
|
+
const requestedIntervalChanged = Boolean(expectedInterval) && currentInterval === expectedInterval && preInterval !== currentInterval;
|
|
282
|
+
if (!requestedPlanChanged && !requestedPlanVersionChanged && !requestedIntervalChanged) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (options?.autoContinueOnActivation === true) {
|
|
287
|
+
await onContinueToTaskforceRef.current?.();
|
|
288
|
+
}
|
|
289
|
+
return true;
|
|
290
|
+
};
|
|
264
291
|
try {
|
|
265
292
|
const res = await fetch(buildCloudBillingUrl('/api/taskforce/billing/checkout-session/confirm'), {
|
|
266
293
|
method: 'POST',
|
|
@@ -270,33 +297,37 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
270
297
|
});
|
|
271
298
|
const payload = await res.json().catch(() => ({}));
|
|
272
299
|
if (!res.ok) {
|
|
300
|
+
const errorCode = String(payload?.code || '').trim();
|
|
301
|
+
const retryable = shouldRetryCheckoutConfirmation(res.status, errorCode);
|
|
302
|
+
if (retryable && await confirmViaSummary()) {
|
|
303
|
+
return { confirmed: true };
|
|
304
|
+
}
|
|
273
305
|
return {
|
|
274
306
|
confirmed: false,
|
|
275
|
-
errorMessage: String(payload?.error || 'Unable to confirm checkout completion.')
|
|
307
|
+
errorMessage: String(payload?.error || 'Unable to confirm checkout completion.'),
|
|
308
|
+
retryable
|
|
276
309
|
};
|
|
277
310
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const summaryState = String(summary?.entitlementState || '').trim().toLowerCase();
|
|
281
|
-
if (ACTIVE_ENTITLEMENT_STATES.has(summaryState)) {
|
|
282
|
-
await onContinueToTaskforce?.();
|
|
311
|
+
if (await confirmViaSummary()) {
|
|
312
|
+
return { confirmed: true };
|
|
283
313
|
}
|
|
284
314
|
return { confirmed: true };
|
|
285
315
|
}
|
|
286
316
|
catch {
|
|
287
317
|
return {
|
|
288
318
|
confirmed: false,
|
|
289
|
-
errorMessage: 'Unable to confirm checkout completion.'
|
|
319
|
+
errorMessage: 'Unable to confirm checkout completion.',
|
|
320
|
+
retryable: true
|
|
290
321
|
};
|
|
291
322
|
}
|
|
292
|
-
}, [authUserId, buildCloudBillingUrl, loadAccountProfileSummary,
|
|
323
|
+
}, [authUserId, buildCloudBillingUrl, loadAccountProfileSummary, queryIntervalValue, queryPlanId, queryPlanVersionId]);
|
|
293
324
|
const openBillingPortal = useCallback(async () => {
|
|
294
325
|
if (!isAuthenticated) {
|
|
295
326
|
navigate(`/login?mode=login&next=${encodeURIComponent(buildEmbeddedPlansPath())}`);
|
|
296
327
|
return;
|
|
297
328
|
}
|
|
298
329
|
setActionBusy(true);
|
|
299
|
-
setFeedback(
|
|
330
|
+
setFeedback({ type: 'info', message: 'Opening billing portal...' });
|
|
300
331
|
try {
|
|
301
332
|
const res = await fetch(buildCloudBillingUrl('/api/taskforce/billing/portal-session'), {
|
|
302
333
|
method: 'POST',
|
|
@@ -321,6 +352,17 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
321
352
|
setActionBusy(false);
|
|
322
353
|
}
|
|
323
354
|
}, [buildCloudBillingUrl, isAuthenticated, navigate]);
|
|
355
|
+
const handleContinueToTaskforce = useCallback(async () => {
|
|
356
|
+
if (!onContinueToTaskforce || continueActionBusy || continueBusy)
|
|
357
|
+
return;
|
|
358
|
+
setContinueActionBusy(true);
|
|
359
|
+
try {
|
|
360
|
+
await onContinueToTaskforce();
|
|
361
|
+
}
|
|
362
|
+
finally {
|
|
363
|
+
setContinueActionBusy(false);
|
|
364
|
+
}
|
|
365
|
+
}, [continueActionBusy, continueBusy, onContinueToTaskforce]);
|
|
324
366
|
useEffect(() => {
|
|
325
367
|
void loadAccountProfileSummary();
|
|
326
368
|
}, [loadAccountProfileSummary]);
|
|
@@ -337,26 +379,115 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
337
379
|
}
|
|
338
380
|
}, []);
|
|
339
381
|
useEffect(() => {
|
|
382
|
+
if (checkoutState !== 'success') {
|
|
383
|
+
checkoutSuccessSettledRef.current = null;
|
|
384
|
+
}
|
|
385
|
+
}, [checkoutState]);
|
|
386
|
+
useEffect(() => {
|
|
387
|
+
let cancelled = false;
|
|
388
|
+
const pendingRetryTimeouts = new Set();
|
|
389
|
+
const waitForRetry = async (delayMs) => {
|
|
390
|
+
if (delayMs <= 0)
|
|
391
|
+
return;
|
|
392
|
+
await new Promise((resolve) => {
|
|
393
|
+
const timeoutId = window.setTimeout(() => {
|
|
394
|
+
pendingRetryTimeouts.delete(timeoutId);
|
|
395
|
+
resolve();
|
|
396
|
+
}, delayMs);
|
|
397
|
+
pendingRetryTimeouts.add(timeoutId);
|
|
398
|
+
});
|
|
399
|
+
};
|
|
340
400
|
if (checkoutState === 'success') {
|
|
341
401
|
checkoutStartRan.current = true;
|
|
342
402
|
setFeedback({ type: 'success', message: 'Checkout completed successfully. Finalizing your plan...' });
|
|
403
|
+
const shouldWaitForAuthBootstrap = !isAuthenticated && !authSessionResolved;
|
|
404
|
+
if (shouldWaitForAuthBootstrap) {
|
|
405
|
+
return () => {
|
|
406
|
+
cancelled = true;
|
|
407
|
+
pendingRetryTimeouts.forEach((timeoutId) => window.clearTimeout(timeoutId));
|
|
408
|
+
pendingRetryTimeouts.clear();
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
if (!isAuthenticated) {
|
|
412
|
+
setFeedback({ type: 'error', message: 'Sign in to finish activating your plan.' });
|
|
413
|
+
return () => {
|
|
414
|
+
cancelled = true;
|
|
415
|
+
pendingRetryTimeouts.forEach((timeoutId) => window.clearTimeout(timeoutId));
|
|
416
|
+
pendingRetryTimeouts.clear();
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
const successFlowKey = querySessionId || '__missing_session__';
|
|
420
|
+
if (checkoutSuccessSettledRef.current === successFlowKey) {
|
|
421
|
+
return () => {
|
|
422
|
+
cancelled = true;
|
|
423
|
+
pendingRetryTimeouts.forEach((timeoutId) => window.clearTimeout(timeoutId));
|
|
424
|
+
pendingRetryTimeouts.clear();
|
|
425
|
+
};
|
|
426
|
+
}
|
|
343
427
|
void (async () => {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
428
|
+
const autoConfirmStartedAt = Date.now();
|
|
429
|
+
const preConfirmationSummary = await loadAccountProfileSummary({ force: true });
|
|
430
|
+
if (cancelled)
|
|
431
|
+
return;
|
|
432
|
+
let confirmation = querySessionId
|
|
433
|
+
? { confirmed: false, errorMessage: 'Unable to confirm checkout completion.', retryable: true }
|
|
434
|
+
: { confirmed: false, errorMessage: 'Checkout session is missing.', retryable: false };
|
|
435
|
+
let attemptIndex = 0;
|
|
436
|
+
while (true) {
|
|
437
|
+
const delayMs = attemptIndex < CHECKOUT_CONFIRM_INITIAL_RETRY_DELAYS_MS.length
|
|
438
|
+
? CHECKOUT_CONFIRM_INITIAL_RETRY_DELAYS_MS[attemptIndex]
|
|
439
|
+
: CHECKOUT_CONFIRM_RETRY_INTERVAL_MS;
|
|
440
|
+
attemptIndex += 1;
|
|
441
|
+
await waitForRetry(delayMs);
|
|
442
|
+
if (cancelled)
|
|
443
|
+
return;
|
|
444
|
+
confirmation = querySessionId
|
|
445
|
+
? await confirmCheckoutSession(querySessionId, {
|
|
446
|
+
autoContinueOnActivation: shouldAutoContinueAfterActivation(preConfirmationSummary, gateState),
|
|
447
|
+
preConfirmationSummary
|
|
448
|
+
})
|
|
449
|
+
: { confirmed: false, errorMessage: 'Checkout session is missing.', retryable: false };
|
|
450
|
+
if (cancelled)
|
|
451
|
+
return;
|
|
452
|
+
if (confirmation.confirmed) {
|
|
453
|
+
checkoutSuccessSettledRef.current = successFlowKey;
|
|
454
|
+
setFeedback({ type: 'success', message: 'Checkout completed successfully.' });
|
|
455
|
+
scheduleTransientQueryClear();
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
if (!confirmation.retryable) {
|
|
459
|
+
break;
|
|
460
|
+
}
|
|
461
|
+
if ((Date.now() - autoConfirmStartedAt) >= CHECKOUT_CONFIRM_MAX_AUTO_RETRY_MS) {
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
if (cancelled)
|
|
466
|
+
return;
|
|
347
467
|
if (!confirmation.confirmed) {
|
|
348
468
|
const summary = await loadAccountProfileSummary({ force: true });
|
|
469
|
+
if (cancelled)
|
|
470
|
+
return;
|
|
471
|
+
if (!confirmation.retryable) {
|
|
472
|
+
checkoutSuccessSettledRef.current = successFlowKey;
|
|
473
|
+
}
|
|
349
474
|
setFeedback({
|
|
350
475
|
type: 'error',
|
|
351
|
-
message: resolveRecoveryMessage(summary, confirmation.errorMessage
|
|
476
|
+
message: resolveRecoveryMessage(summary, confirmation.errorMessage, {
|
|
477
|
+
preferFallback: !confirmation.retryable
|
|
478
|
+
})
|
|
352
479
|
});
|
|
353
|
-
|
|
480
|
+
if (!confirmation.retryable) {
|
|
481
|
+
scheduleTransientQueryClear();
|
|
482
|
+
}
|
|
354
483
|
return;
|
|
355
484
|
}
|
|
356
|
-
setFeedback({ type: 'success', message: 'Checkout completed successfully.' });
|
|
357
|
-
scheduleTransientQueryClear();
|
|
358
485
|
})();
|
|
359
|
-
return
|
|
486
|
+
return () => {
|
|
487
|
+
cancelled = true;
|
|
488
|
+
pendingRetryTimeouts.forEach((timeoutId) => window.clearTimeout(timeoutId));
|
|
489
|
+
pendingRetryTimeouts.clear();
|
|
490
|
+
};
|
|
360
491
|
}
|
|
361
492
|
if (checkoutState === 'cancel') {
|
|
362
493
|
void (async () => {
|
|
@@ -371,29 +502,31 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
371
502
|
}
|
|
372
503
|
if ((checkoutState === 'start' || checkoutState === 'free') && isAuthenticated && queryPlanVersionId && !checkoutStartRan.current) {
|
|
373
504
|
checkoutStartRan.current = true;
|
|
374
|
-
void
|
|
505
|
+
void (async () => {
|
|
506
|
+
const preCheckoutSummary = await loadAccountProfileSummary({ force: true });
|
|
507
|
+
await startCheckout(queryPlanVersionId, queryInterval, {
|
|
508
|
+
autoContinueOnActivation: shouldAutoContinueAfterActivation(preCheckoutSummary, gateState)
|
|
509
|
+
});
|
|
510
|
+
})();
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
}, [authSessionResolved, checkoutState, confirmCheckoutSession, gateState, isAuthenticated, loadAccountProfileSummary, queryInterval, queryPlanVersionId, querySessionId, resolveRecoveryMessage, scheduleTransientQueryClear, shouldAutoContinueAfterActivation, startCheckout]);
|
|
514
|
+
useEffect(() => {
|
|
515
|
+
if (checkoutState === 'success' || checkoutState === 'cancel' || checkoutState === 'start' || checkoutState === 'free') {
|
|
375
516
|
return;
|
|
376
517
|
}
|
|
377
518
|
if (gateMessage) {
|
|
378
|
-
setFeedback({ type:
|
|
519
|
+
setFeedback({ type: lifecyclePresentation.statusTone, message: gateMessage });
|
|
379
520
|
return;
|
|
380
521
|
}
|
|
381
522
|
setFeedback((current) => {
|
|
382
523
|
if (!current || current.type !== 'error')
|
|
383
524
|
return current;
|
|
384
|
-
if (current.message ===
|
|
385
|
-
return null;
|
|
386
|
-
if (current.message === GATE_MESSAGES.misconfigured)
|
|
387
|
-
return null;
|
|
388
|
-
if (current.message === GATE_MESSAGES.missingEntitlement)
|
|
389
|
-
return null;
|
|
390
|
-
if (current.message === BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_EXPIRED)
|
|
391
|
-
return null;
|
|
392
|
-
if (current.message === BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_SUPERSEDED)
|
|
525
|
+
if (current.message === lifecyclePresentation.message)
|
|
393
526
|
return null;
|
|
394
527
|
return current;
|
|
395
528
|
});
|
|
396
|
-
}, [checkoutState,
|
|
529
|
+
}, [checkoutState, gateMessage, lifecyclePresentation.message, lifecyclePresentation.statusTone]);
|
|
397
530
|
const handleSelectPlan = useCallback(async (intent) => {
|
|
398
531
|
if (!isAuthenticated) {
|
|
399
532
|
const nextCheckoutState = intent.pricingType === 'free' ? 'free' : 'start';
|
|
@@ -414,15 +547,16 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
414
547
|
await openBillingPortal();
|
|
415
548
|
return;
|
|
416
549
|
}
|
|
550
|
+
const autoContinueOnActivation = shouldAutoContinueAfterActivation(accountProfileSummary, gateState);
|
|
417
551
|
if (intent.pricingType === 'free') {
|
|
418
|
-
await startCheckout(intent.planVersionId, intent.interval);
|
|
552
|
+
await startCheckout(intent.planVersionId, intent.interval, { autoContinueOnActivation });
|
|
419
553
|
return;
|
|
420
554
|
}
|
|
421
|
-
await startCheckout(intent.planVersionId, intent.interval);
|
|
422
|
-
}, [isAuthenticated, navigate, openBillingPortal, startCheckout]);
|
|
555
|
+
await startCheckout(intent.planVersionId, intent.interval, { autoContinueOnActivation });
|
|
556
|
+
}, [accountProfileSummary, gateState, isAuthenticated, navigate, openBillingPortal, shouldAutoContinueAfterActivation, startCheckout]);
|
|
423
557
|
const handleBack = useCallback(() => {
|
|
424
558
|
if (hasResolvedActiveEntitlement && onContinueToTaskforce) {
|
|
425
|
-
void
|
|
559
|
+
void handleContinueToTaskforce();
|
|
426
560
|
return;
|
|
427
561
|
}
|
|
428
562
|
if (embedded) {
|
|
@@ -434,9 +568,8 @@ export function PlansPage({ isAuthenticated, authUserId, runtimeMode, authSessio
|
|
|
434
568
|
return;
|
|
435
569
|
}
|
|
436
570
|
navigate('/');
|
|
437
|
-
}, [closeEmbeddedPlansScreen, embedded, hasResolvedActiveEntitlement, navigate, onContinueToTaskforce]);
|
|
438
|
-
const
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
return (_jsx(PlanComparisonPage, { chrome: chrome, heading: "Subscription Plans", subtitle: "Manage your subscription and explore available features. Your current plan is highlighted below.", isAuthenticated: isAuthenticated, authSessionResolved: authSessionResolved, currentPlanId: String(accountProfileSummary?.planId || queryPlanId || '').trim() || null, currentPlanVersionId: String(accountProfileSummary?.planVersionId || queryPlanVersionId || '').trim() || null, currentEntitlementState: String(accountProfileSummary?.entitlementState || '').trim() || null, canManageCurrentPlan: Boolean(accountProfileSummary?.stripeCustomerId), pricingEndpoint: pricingEndpoints[0], statusBanner: feedback, onBack: handleBack, backLabel: hasResolvedActiveEntitlement ? 'Take Me to Taskforce' : (embedded ? 'Back to Board' : 'Back to App'), backDisabled: continueBusy || (isAuthenticated && !hasResolvedActiveEntitlement), topActions: embedded ? topActions : null, shellOwnsScroll: shellOwnsScroll, showPageBackButton: !embedded, fallbackPricingSource: fallbackPricingSource, onSelectPlan: handleSelectPlan }));
|
|
571
|
+
}, [closeEmbeddedPlansScreen, embedded, handleContinueToTaskforce, hasResolvedActiveEntitlement, navigate, onContinueToTaskforce]);
|
|
572
|
+
const headerActions = embedded ? null : (_jsxs(_Fragment, { children: [_jsx("button", { className: styles.navAction, onClick: handleBack, disabled: continueBusy || continueActionBusy || (isAuthenticated && !hasResolvedActiveEntitlement), children: hasResolvedActiveEntitlement ? 'Take Me to Taskforce' : 'Back' }), isAuthenticated && accountProfileSummary?.stripeCustomerId && (_jsx("button", { className: styles.navAction, onClick: () => { void openBillingPortal(); }, disabled: actionBusy, children: "Manage billing" })), !isAuthenticated && (_jsxs("button", { className: styles.navAction, onClick: () => navigate(`/login?mode=login&next=${encodeURIComponent(buildEmbeddedPlansPath())}`), children: [_jsx(User, { size: 16, style: { marginRight: '8px', verticalAlign: 'text-bottom' } }), "Sign In"] }))] }));
|
|
573
|
+
const chrome = embedded ? null : (_jsx(AppShellHeader, { projectName: projectName, currentWorkspaceId: currentWorkspaceId, runtimeMode: runtimeMode === 'cloud' ? 'cloud' : 'local', theme: currentTheme, actions: headerActions }));
|
|
574
|
+
return (_jsx(PlanComparisonPage, { chrome: chrome, heading: "Subscription Plans", subtitle: "Manage your subscription and explore available features. Your current plan is highlighted below.", isAuthenticated: isAuthenticated, authSessionResolved: authSessionResolved, currentPlanId: String(accountProfileSummary?.planId || queryPlanId || '').trim() || null, currentPlanVersionId: String(accountProfileSummary?.planVersionId || queryPlanVersionId || '').trim() || null, currentEntitlementState: String(accountProfileSummary?.entitlementState || '').trim() || null, markCurrentPlan: lifecyclePresentation.markCurrentPlan, canManageCurrentPlan: Boolean(accountProfileSummary?.stripeCustomerId), pricingEndpoint: pricingEndpoint, statusBanner: feedback, onBack: handleBack, backLabel: hasResolvedActiveEntitlement ? 'Take Me to Taskforce' : (embedded ? 'Back to Board' : 'Back to App'), backDisabled: continueBusy || continueActionBusy || (isAuthenticated && !hasResolvedActiveEntitlement), topActions: null, shellOwnsScroll: shellOwnsScroll, showPageBackButton: false, showHeaderBarWithChrome: false, currentPlanCardActionMode: "manage", fallbackPricingSource: fallbackPricingSource, onSelectPlan: handleSelectPlan }));
|
|
442
575
|
}
|