@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.
Files changed (383) hide show
  1. package/README.md +140 -247
  2. package/dist/Taskforce.module.css +295 -89
  3. package/dist/TaskforceCore.js +378 -111
  4. package/dist/TaskforceCore.test.js +1221 -107
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +52 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  16. package/dist/components/context/ContextAttachmentManager.js +549 -0
  17. package/dist/components/features/AgentsModule.d.ts +10 -1
  18. package/dist/components/features/AgentsModule.js +260 -15
  19. package/dist/components/features/AgentsModule.test.js +255 -5
  20. package/dist/components/features/DocumentIndex.d.ts +1 -1
  21. package/dist/components/features/DocumentIndex.js +1 -1
  22. package/dist/components/features/DocumentViewer.d.ts +6 -2
  23. package/dist/components/features/DocumentViewer.js +90 -10
  24. package/dist/components/features/DocumentWorkspace.d.ts +5 -22
  25. package/dist/components/features/DocumentWorkspace.js +12 -155
  26. package/dist/components/features/DocumentWorkspace.test.js +226 -6
  27. package/dist/components/features/TaskSettings.js +29 -3
  28. package/dist/components/features/TaskSettings.test.js +42 -1
  29. package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
  30. package/dist/components/features/documentWorkspaceModel.js +57 -0
  31. package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
  32. package/dist/components/features/useDocumentWorkspaceController.js +113 -0
  33. package/dist/components/task/TaskCard.js +19 -28
  34. package/dist/components/task/TaskCard.test.js +38 -3
  35. package/dist/components/task/TaskContextUpload.js +4 -526
  36. package/dist/components/task/TaskForm.d.ts +8 -8
  37. package/dist/components/task/TaskForm.js +362 -230
  38. package/dist/components/task/TaskForm.test.js +558 -381
  39. package/dist/components/task/TaskKanban.d.ts +2 -1
  40. package/dist/components/task/TaskKanban.js +96 -14
  41. package/dist/components/task/TaskKanban.test.js +36 -0
  42. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  43. package/dist/components/ui/EditableAvatarButton.js +18 -0
  44. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  45. package/dist/components/views/PlanComparisonPage.js +70 -17
  46. package/dist/components/views/PlanComparisonPage.test.js +289 -41
  47. package/dist/components/views/PlansPage.js +239 -106
  48. package/dist/components/views/PlansPage.test.js +593 -42
  49. package/dist/components/views/StandaloneLayout.js +310 -554
  50. package/dist/components/views/panels/FilterToolbar.test.js +6 -4
  51. package/dist/components/views/panels/PlanningDrawer.d.ts +8 -1
  52. package/dist/components/views/panels/PlanningDrawer.js +18 -11
  53. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  54. package/dist/components/views/panels/PlanningDrawer.test.js +141 -0
  55. package/dist/components/views/planningScope.d.ts +20 -0
  56. package/dist/components/views/planningScope.js +25 -0
  57. package/dist/components/views/planningScope.test.d.ts +1 -0
  58. package/dist/components/views/planningScope.test.js +60 -0
  59. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +27 -14
  60. package/dist/components/views/standalone/modals/AccountHubModal.js +87 -15
  61. package/dist/components/views/standalone/modals/AccountHubModal.test.js +42 -2
  62. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  63. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  64. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  65. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  66. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  67. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  68. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  69. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  70. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  71. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  72. package/dist/config/envSchema.js +1 -1
  73. package/dist/core/AiProfileService.d.ts +45 -3
  74. package/dist/core/AiProfileService.js +774 -63
  75. package/dist/core/AiProfileService.test.js +22 -2
  76. package/dist/core/AiProfiles.test.js +761 -2
  77. package/dist/core/AttachmentLinkService.js +57 -15
  78. package/dist/core/AuthIdentityService.d.ts +107 -0
  79. package/dist/core/AuthIdentityService.js +284 -0
  80. package/dist/core/AuthTokenService.d.ts +4 -0
  81. package/dist/core/AuthTokenService.js +34 -6
  82. package/dist/core/AuthTokenService.test.d.ts +1 -0
  83. package/dist/core/AuthTokenService.test.js +78 -0
  84. package/dist/core/EntitlementsPolicy.test.js +77 -15
  85. package/dist/core/GlobalSettingsService.js +115 -6
  86. package/dist/core/PlanEntitlementService.d.ts +30 -3
  87. package/dist/core/PlanEntitlementService.js +454 -93
  88. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  89. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  90. package/dist/core/PlanVersionPolicy.test.js +54 -28
  91. package/dist/core/PlanningEntities.test.js +52 -0
  92. package/dist/core/SignupMonetizationSettings.test.js +241 -44
  93. package/dist/core/SyncReconciliationService.js +2 -65
  94. package/dist/core/SystemAdmin.test.js +244 -88
  95. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  96. package/dist/core/TaskTaxonomyValidation.test.js +53 -0
  97. package/dist/core/Taskforce.d.ts +228 -14
  98. package/dist/core/Taskforce.js +814 -201
  99. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  100. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  101. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  102. package/dist/core/WorkspaceLifecycleService.js +0 -5
  103. package/dist/core/WorkspacePermissions.test.js +25 -1
  104. package/dist/core/WorkspacePlanMode.test.js +128 -27
  105. package/dist/core/shared.d.ts +3 -1
  106. package/dist/core/shared.js +16 -1
  107. package/dist/core/types.d.ts +68 -2
  108. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +26 -1
  109. package/dist/hooks/sync/auth.js +3 -1
  110. package/dist/hooks/sync/bootstrap.js +2 -0
  111. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  112. package/dist/hooks/sync/controlPlane.js +78 -0
  113. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  114. package/dist/hooks/sync/controlPlane.test.js +121 -0
  115. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  116. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  117. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  118. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  119. package/dist/hooks/sync/orchestratorShared.d.ts +10 -1
  120. package/dist/hooks/sync/orchestratorShared.js +68 -47
  121. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  122. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  123. package/dist/hooks/sync/pullLifecycle.js +24 -0
  124. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  125. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  126. package/dist/hooks/sync/recovery.d.ts +16 -2
  127. package/dist/hooks/sync/recovery.js +171 -53
  128. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  129. package/dist/hooks/sync/recovery.test.js +292 -0
  130. package/dist/hooks/sync/transfers.d.ts +16 -3
  131. package/dist/hooks/sync/transfers.js +186 -65
  132. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  133. package/dist/hooks/sync/transfers.test.js +396 -0
  134. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  135. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  136. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  137. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  138. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  139. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  140. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  141. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  142. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  143. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  144. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  145. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  146. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  147. package/dist/hooks/useSyncOrchestrator.d.ts +16 -6
  148. package/dist/hooks/useSyncOrchestrator.js +424 -175
  149. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +487 -10
  150. package/dist/hooks/useTaskData.js +8 -3
  151. package/dist/hooks/useTaskData.test.js +45 -0
  152. package/dist/hooks/useTaskMutations.d.ts +2 -1
  153. package/dist/hooks/useTaskMutations.js +12 -1
  154. package/dist/hooks/useTaskMutations.test.js +30 -1
  155. package/dist/hooks/useTaskforce.d.ts +65 -4
  156. package/dist/hooks/useTaskforce.js +564 -243
  157. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  158. package/dist/hooks/useTaskforce.runtime-routing.test.js +152 -0
  159. package/dist/hooks/useTaskforce.sync-behavior.test.js +2454 -208
  160. package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
  161. package/dist/hooks/useWorkspaceSyncController.js +17 -2
  162. package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
  163. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  164. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +316 -35
  165. package/dist/localization/locales/en-US.d.ts +0 -1
  166. package/dist/localization/locales/en-US.js +0 -1
  167. package/dist/localization/locales/es-419.js +0 -1
  168. package/dist/localization/locales/pt-BR.js +0 -1
  169. package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
  170. package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
  171. package/dist/mcp/collaborationRegistrar.d.ts +2 -0
  172. package/dist/mcp/collaborationRegistrar.js +71 -0
  173. package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
  174. package/dist/mcp/documentAssetRegistrar.js +346 -0
  175. package/dist/mcp/runtime.d.ts +2 -0
  176. package/dist/mcp/runtime.js +2433 -3534
  177. package/dist/mcp/runtime.test.js +440 -2
  178. package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
  179. package/dist/mcp/taskPlanningRegistrar.js +418 -0
  180. package/dist/mcp/toolCatalog.d.ts +35 -0
  181. package/dist/mcp/toolCatalog.js +3 -0
  182. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  183. package/dist/migrations/taskSchemaMigrations.js +171 -61
  184. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  185. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  186. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  187. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  188. package/dist/resources/templates/workflows/plan.yaml +1 -1
  189. package/dist/resources/templates/workflows/review.yaml +2 -2
  190. package/dist/server/annotatedAttachmentsRoutes.test.js +3 -3
  191. package/dist/server/auth/providers/apple.d.ts +33 -0
  192. package/dist/server/auth/providers/apple.js +82 -0
  193. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  194. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  195. package/dist/server/auth/providers/github.d.ts +26 -0
  196. package/dist/server/auth/providers/github.js +86 -0
  197. package/dist/server/auth/providers/google.d.ts +21 -0
  198. package/dist/server/auth/providers/google.js +56 -0
  199. package/dist/server/auth/providers/types.d.ts +21 -0
  200. package/dist/server/auth/providers/types.js +1 -0
  201. package/dist/server/auth.d.ts +2 -0
  202. package/dist/server/auth.js +6 -3
  203. package/dist/server/documentReviewRoutes.test.js +36 -3
  204. package/dist/server/index.cookieProxy.test.js +1 -0
  205. package/dist/server/index.d.ts +12 -0
  206. package/dist/server/index.js +120 -9
  207. package/dist/server/index.rateLimit.test.js +3 -0
  208. package/dist/server/index.test.js +106 -3
  209. package/dist/server/routes/admin.d.ts +4 -5
  210. package/dist/server/routes/admin.js +410 -80
  211. package/dist/server/routes/annotatedAttachments.d.ts +1 -1
  212. package/dist/server/routes/annotatedAttachments.js +1 -1
  213. package/dist/server/routes/auth.d.ts +16 -6
  214. package/dist/server/routes/auth.js +1015 -118
  215. package/dist/server/routes/authSupport.d.ts +30 -0
  216. package/dist/server/routes/authSupport.js +81 -0
  217. package/dist/server/routes/billing.d.ts +1 -1
  218. package/dist/server/routes/billing.js +276 -34
  219. package/dist/server/routes/billing.test.js +760 -52
  220. package/dist/server/routes/documentReviews.d.ts +1 -1
  221. package/dist/server/routes/documentReviews.js +1 -1
  222. package/dist/server/routes/documents.d.ts +5 -2
  223. package/dist/server/routes/documents.js +242 -74
  224. package/dist/server/routes/primitives.d.ts +11 -0
  225. package/dist/server/routes/primitives.js +73 -0
  226. package/dist/server/routes/resources.d.ts +1 -1
  227. package/dist/server/routes/resources.js +1 -1
  228. package/dist/server/routes/shared.d.ts +29 -3
  229. package/dist/server/routes/shared.js +69 -4
  230. package/dist/server/routes/sync.d.ts +1 -1
  231. package/dist/server/routes/sync.integration.test.js +437 -39
  232. package/dist/server/routes/sync.js +62 -606
  233. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  234. package/dist/server/routes/syncAuxRoutes.js +91 -0
  235. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  236. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  237. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  238. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  239. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  240. package/dist/server/routes/syncPushRoutes.js +212 -0
  241. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  242. package/dist/server/routes/syncRouteGuards.js +67 -0
  243. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  244. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  245. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  246. package/dist/server/routes/syncRouteTypes.js +1 -0
  247. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  248. package/dist/server/routes/syncSnapshotRoutes.js +180 -0
  249. package/dist/server/routes/tasks.d.ts +1 -1
  250. package/dist/server/routes/tasks.js +44 -2
  251. package/dist/server/routes/workspaces.d.ts +1 -1
  252. package/dist/server/routes/workspaces.js +37 -6
  253. package/dist/server/routes.d.ts +2 -9
  254. package/dist/server/routes.js +136 -165
  255. package/dist/server/routes.test.js +2457 -162
  256. package/dist/services/workflowExportSnapshots.test.js +2 -0
  257. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  258. package/dist/shared/aiProfileSeatScope.js +21 -0
  259. package/dist/shared/passwordPolicy.d.ts +13 -0
  260. package/dist/shared/passwordPolicy.js +84 -0
  261. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  262. package/dist/shared/passwordPolicy.test.js +34 -0
  263. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  264. package/dist/storage/workspaceAssetStore.js +132 -44
  265. package/dist/storage/workspaceAssetStore.test.js +93 -6
  266. package/dist/styles/fonts.css +70 -0
  267. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  268. package/dist/sync/collaborationSyncPayload.js +17 -11
  269. package/dist/sync/collaborationSyncPayload.test.js +13 -1
  270. package/dist/sync/contentSyncState.d.ts +4 -8
  271. package/dist/sync/contentSyncState.js +33 -77
  272. package/dist/sync/syncApplyHandlers.d.ts +7 -0
  273. package/dist/sync/syncApplyHandlers.js +28 -13
  274. package/dist/sync/syncApplyHandlers.test.js +72 -3
  275. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  276. package/dist/sync/syncFieldSemantics.js +55 -0
  277. package/dist/sync/syncResourceAdapters.d.ts +44 -0
  278. package/dist/sync/syncResourceAdapters.js +77 -0
  279. package/dist/sync/syncService.d.ts +6 -0
  280. package/dist/sync/syncService.js +60 -0
  281. package/dist/sync/syncService.test.js +71 -3
  282. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  283. package/dist/sync/taskSyncChangeKey.js +143 -0
  284. package/dist/sync/taskSyncPayload.js +3 -8
  285. package/dist/sync/workspacePullFeed.js +4 -3
  286. package/dist/sync/workspacePullFeed.test.js +43 -0
  287. package/dist/sync/workspaceRepair.js +5 -2
  288. package/dist/sync/workspaceSyncModel.d.ts +48 -0
  289. package/dist/sync/workspaceSyncModel.js +195 -31
  290. package/dist/sync/workspaceSyncModel.test.js +325 -12
  291. package/dist/sync/workspaceSyncState.d.ts +19 -0
  292. package/dist/sync/workspaceSyncState.js +3 -1
  293. package/dist/sync/workspaceSyncSurface.js +3 -8
  294. package/dist/types.d.ts +17 -0
  295. package/dist/ui/assets/AgentsModule-DrLawwNl.js +1 -0
  296. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BlS-cqnl.js → AnnotatedAttachmentWorkspace-Z9_whf7F.js} +1 -1
  297. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  298. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  299. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  300. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  301. package/dist/ui/assets/DocumentWorkspace-B03MaSkw.js +252 -0
  302. package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +1 -0
  303. package/dist/ui/assets/{InitiativesModule-BjR6iBf9.js → InitiativesModule-9E6ParrY.js} +1 -1
  304. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  305. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  306. package/dist/ui/assets/PlansPage-CvfnMiWq.css +1 -0
  307. package/dist/ui/assets/PlansPage-DRXscYxH.js +1 -0
  308. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  309. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  310. package/dist/ui/assets/TaskSettings-DZX4jk7e.js +9 -0
  311. package/dist/ui/assets/{WorkflowsModule-DnFqdUME.js → WorkflowsModule-BA7jcEpH.js} +1 -1
  312. package/dist/ui/assets/index-9eT8e0Lu.css +1 -0
  313. package/dist/ui/assets/index-C6k75jr8.js +6 -0
  314. package/dist/ui/assets/{vendor-icons-I7ZwG1z_.js → vendor-icons-DuEd_65c.js} +1 -1
  315. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  316. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  317. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  318. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  319. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  320. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  321. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  322. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  323. package/dist/ui/fonts/Noir_medium.otf +0 -0
  324. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  325. package/dist/ui/fonts/Noir_regular.otf +0 -0
  326. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  327. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  328. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  329. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  330. package/dist/ui/index.html +3 -3
  331. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  332. package/dist/utils/assignees.d.ts +2 -0
  333. package/dist/utils/assignees.js +2 -0
  334. package/dist/utils/avatarUpload.d.ts +27 -0
  335. package/dist/utils/avatarUpload.js +132 -0
  336. package/dist/utils/avatarUpload.test.d.ts +1 -0
  337. package/dist/utils/avatarUpload.test.js +40 -0
  338. package/dist/utils/bootstrapTrace.d.ts +7 -0
  339. package/dist/utils/bootstrapTrace.js +29 -0
  340. package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
  341. package/dist/utils/commercialLifecyclePresentation.js +199 -0
  342. package/dist/utils/contextAssetEvents.d.ts +2 -0
  343. package/dist/utils/syncEventDetails.d.ts +3 -0
  344. package/dist/utils/syncEventDetails.js +64 -0
  345. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  346. package/dist/utils/syncEventDetails.test.js +23 -0
  347. package/dist/utils/syncEventPresentation.d.ts +15 -0
  348. package/dist/utils/syncEventPresentation.js +129 -0
  349. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  350. package/dist/utils/syncEventPresentation.test.js +64 -0
  351. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  352. package/dist/utils/syncStatusPresentation.js +217 -0
  353. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  354. package/dist/utils/syncStatusPresentation.test.js +164 -0
  355. package/dist/utils/taskActivity.d.ts +2 -0
  356. package/dist/utils/taskActivity.js +228 -22
  357. package/dist/utils/taskActivity.test.js +119 -8
  358. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  359. package/dist/utils/workspaceSyncPresentation.js +68 -2
  360. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  361. package/package.json +10 -2
  362. package/scripts/check-cloud-mcp.mjs +83 -0
  363. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  364. package/scripts/playwright-auth.sh +5 -1
  365. package/scripts/run-billing-performance-smoke.sh +24 -0
  366. package/scripts/run-e2e-realtime.sh +17 -3
  367. package/scripts/run-smoke.sh +17 -5
  368. package/scripts/run-soak.sh +17 -5
  369. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  370. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  371. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  372. package/src/resources/templates/workflows/plan.yaml +1 -1
  373. package/src/resources/templates/workflows/review.yaml +2 -2
  374. package/dist/ui/assets/AgentsModule-BLWVbuKP.js +0 -1
  375. package/dist/ui/assets/DocumentWorkspace-BH_6DF6x.js +0 -250
  376. package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
  377. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  378. package/dist/ui/assets/PlansPage-CSDQ4sLa.js +0 -1
  379. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  380. package/dist/ui/assets/TaskSettings-CEDy34Jo.js +0 -9
  381. package/dist/ui/assets/index-DXUdtH1B.js +0 -6
  382. package/dist/ui/assets/index-Ii0B0rTO.css +0 -1
  383. package/scripts/migrate-planning-model.ts +0 -233
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
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 ACTIVE_ENTITLEMENT_STATES = new Set(['active', 'trialing', 'grace']);
12
- const GATE_MESSAGES = {
13
- planSelectionRequired: 'Choose a plan to continue.',
14
- checkoutPending: 'Complete checkout to continue.',
15
- misconfigured: 'Onboarding policy is misconfigured. Contact support or a system administrator.',
16
- missingEntitlement: 'No entitlement is linked to this account.'
17
- };
18
- const BILLING_CONFLICT_MESSAGES = {
19
- CHECKOUT_SESSION_EXPIRED: 'Your previous checkout expired. Choose a plan to continue.',
20
- CHECKOUT_SESSION_SUPERSEDED: 'A newer checkout replaced your previous checkout. Choose a plan to continue.'
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 pricingEndpoints = useMemo(() => {
86
- const endpoints = [
87
- normalizedApiBaseUrl ? `${normalizedApiBaseUrl}/api/taskforce/public/pricing` : '',
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
- if (hasResolvedActiveEntitlement)
103
+ const message = String(lifecyclePresentation.message || '').trim();
104
+ if (!message || message === HIDDEN_GATE_MESSAGE)
98
105
  return null;
99
- const billingConflictCode = String(accountProfileSummary?.billingConflictCode || '').trim().toUpperCase();
100
- if (billingConflictCode === 'CHECKOUT_SESSION_EXPIRED')
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 billingConflictCode = String(summary?.billingConflictCode || '').trim().toUpperCase();
161
- if (billingConflictCode === 'CHECKOUT_SESSION_EXPIRED')
162
- return BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_EXPIRED;
163
- if (billingConflictCode === 'CHECKOUT_SESSION_SUPERSEDED')
164
- return BILLING_CONFLICT_MESSAGES.CHECKOUT_SESSION_SUPERSEDED;
165
- const summaryMessage = String(summary?.message || '').trim();
166
- if (summaryMessage)
167
- return summaryMessage;
168
- return String(fallback || 'Unable to confirm checkout completion.').trim() || 'Unable to confirm checkout completion.';
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 (!hadActiveEntitlement && ACTIVE_ENTITLEMENT_STATES.has(summaryState)) {
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 (!hadActiveEntitlement && ACTIVE_ENTITLEMENT_STATES.has(summaryState)) {
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, hasResolvedActiveEntitlement, loadAccountProfileSummary, onContinueToTaskforce, runtimeMode]);
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
- invalidateAccountProfileSummaryCache(buildCloudBillingUrl(ACCOUNT_PROFILE_SUMMARY_PATH), { identityKey: authUserId });
279
- const summary = await loadAccountProfileSummary({ force: true });
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, onContinueToTaskforce]);
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(null);
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 confirmation = querySessionId
345
- ? await confirmCheckoutSession(querySessionId)
346
- : { confirmed: false, errorMessage: 'Checkout session is missing.' };
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
- scheduleTransientQueryClear();
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 startCheckout(queryPlanVersionId, queryInterval);
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: resolveGateFeedbackType(gateMessage), message: gateMessage });
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 === GATE_MESSAGES.planSelectionRequired)
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, confirmCheckoutSession, gateMessage, isAuthenticated, loadAccountProfileSummary, queryInterval, queryPlanVersionId, querySessionId, resolveGateFeedbackType, resolveRecoveryMessage, scheduleTransientQueryClear, startCheckout]);
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 onContinueToTaskforce();
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 continueAction = hasResolvedActiveEntitlement && onContinueToTaskforce ? (_jsx("button", { className: styles.navAction, onClick: () => { void onContinueToTaskforce(); }, disabled: continueBusy || actionBusy, children: "Take Me to Taskforce" })) : null;
439
- const topActions = embedded ? (_jsxs(_Fragment, { children: [continueAction, isAuthenticated && accountProfileSummary?.stripeCustomerId && (_jsx("button", { className: styles.navAction, onClick: () => { void openBillingPortal(); }, disabled: actionBusy, children: "Manage billing" }))] })) : (_jsxs(_Fragment, { children: [_jsx("button", { className: styles.navAction, onClick: handleBack, disabled: continueBusy || (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"] }))] }));
440
- const chrome = embedded ? null : (_jsx(AppShellHeader, { projectName: projectName, currentWorkspaceId: currentWorkspaceId, runtimeMode: runtimeMode === 'cloud' ? 'cloud' : 'local', theme: currentTheme, actions: topActions }));
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
  }