@taskforcehq/taskforce 0.3.302 → 0.3.303

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 (77) hide show
  1. package/dist/Taskforce.module.css +11 -0
  2. package/dist/TaskforceCore.js +59 -9
  3. package/dist/TaskforceCore.test.js +717 -14
  4. package/dist/components/task/TaskKanban.test.js +17 -0
  5. package/dist/components/views/PlansPage.d.ts +3 -1
  6. package/dist/components/views/PlansPage.js +110 -51
  7. package/dist/components/views/PlansPage.test.d.ts +1 -0
  8. package/dist/components/views/PlansPage.test.js +100 -0
  9. package/dist/components/views/StandaloneLayout.d.ts +1 -0
  10. package/dist/components/views/StandaloneLayout.js +106 -151
  11. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +8 -3
  12. package/dist/components/views/standalone/modals/AccountHubModal.js +16 -2
  13. package/dist/components/views/standalone/modals/AccountHubModal.test.d.ts +1 -0
  14. package/dist/components/views/standalone/modals/AccountHubModal.test.js +26 -0
  15. package/dist/core/EntitlementsPolicy.test.js +2 -2
  16. package/dist/core/GlobalSettingsService.js +78 -18
  17. package/dist/core/PlanEntitlementService.d.ts +29 -5
  18. package/dist/core/PlanEntitlementService.js +297 -219
  19. package/dist/core/SignupMonetizationSettings.test.js +173 -49
  20. package/dist/core/SystemAdmin.test.js +186 -96
  21. package/dist/core/Taskforce.d.ts +51 -10
  22. package/dist/core/Taskforce.js +218 -49
  23. package/dist/core/Taskforce.mcpAuth.test.js +0 -2
  24. package/dist/core/UserProfileAvatarDrafts.test.js +12 -3
  25. package/dist/core/types.d.ts +11 -12
  26. package/dist/hooks/useSyncOrchestrator.js +17 -3
  27. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +97 -5
  28. package/dist/hooks/useTaskforce.d.ts +3 -0
  29. package/dist/hooks/useTaskforce.js +9 -4
  30. package/dist/mcp/runtime.js +90 -29
  31. package/dist/mcp/runtime.test.js +272 -81
  32. package/dist/migrations/billingSchemaParity.test.js +3 -0
  33. package/dist/migrations/taskSchemaMigrations.js +15 -0
  34. package/dist/server/index.cookieProxy.test.js +1 -0
  35. package/dist/server/index.js +2 -0
  36. package/dist/server/index.test.js +2 -1
  37. package/dist/server/mockStripe.d.ts +1 -0
  38. package/dist/server/mockStripe.js +2 -0
  39. package/dist/server/routes/admin.js +80 -23
  40. package/dist/server/routes/auth.d.ts +1 -0
  41. package/dist/server/routes/auth.js +194 -53
  42. package/dist/server/routes/billing.js +506 -23
  43. package/dist/server/routes/billing.test.js +937 -45
  44. package/dist/server/routes/shared.js +5 -3
  45. package/dist/server/routes/sync.integration.test.js +160 -0
  46. package/dist/server/routes/sync.js +15 -5
  47. package/dist/server/routes.js +3 -3
  48. package/dist/server/routes.test.js +287 -76
  49. package/dist/sync/cloudSyncApi.d.ts +1 -0
  50. package/dist/sync/contentSyncState.d.ts +10 -0
  51. package/dist/sync/contentSyncState.js +277 -16
  52. package/dist/sync/syncService.d.ts +1 -0
  53. package/dist/sync/syncService.js +21 -8
  54. package/dist/sync/workspacePullFeed.d.ts +10 -0
  55. package/dist/sync/workspacePullFeed.js +111 -63
  56. package/dist/sync/workspacePullFeed.test.js +112 -0
  57. package/dist/ui/assets/{AgentsModule-JG5jc3he.js → AgentsModule-CpsTmrIW.js} +1 -1
  58. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-Dvi02Y7q.js → AnnotatedAttachmentWorkspace-C_TmXZwA.js} +1 -1
  59. package/dist/ui/assets/{DocumentWorkspace-iys3zfca.js → DocumentWorkspace-C3GyzrWm.js} +1 -1
  60. package/dist/ui/assets/{InitiativesModule-DJvLJI3A.js → InitiativesModule-4-Rh2K2n.js} +1 -1
  61. package/dist/ui/assets/PlansPage-BP7AYOqr.js +1 -0
  62. package/dist/ui/assets/{TaskSettings-Bqd4cCzW.js → TaskSettings-BOC5F6Ag.js} +1 -1
  63. package/dist/ui/assets/{WorkflowsModule-BguHeQaV.js → WorkflowsModule-CGk9s3NJ.js} +1 -1
  64. package/dist/ui/assets/index-CLIMgR6g.js +6 -0
  65. package/dist/ui/assets/index-DneETxcu.css +1 -0
  66. package/dist/ui/assets/{vendor-icons-C8EED3Oh.js → vendor-icons-pWocEipT.js} +1 -1
  67. package/dist/ui/index.html +3 -3
  68. package/dist/utils/accountProfileSummaryCache.d.ts +31 -0
  69. package/dist/utils/accountProfileSummaryCache.js +97 -0
  70. package/dist/utils/accountProfileSummaryCache.test.d.ts +1 -0
  71. package/dist/utils/accountProfileSummaryCache.test.js +63 -0
  72. package/package.json +3 -3
  73. package/dist/ui/assets/PlansPage-BMPlpFpw.js +0 -1
  74. package/dist/ui/assets/index-MXeWoebC.css +0 -1
  75. package/dist/ui/assets/index-YJ4k5QNa.js +0 -6
  76. package/dist/utils/billingStatusCache.d.ts +0 -21
  77. package/dist/utils/billingStatusCache.js +0 -70
@@ -173,6 +173,7 @@
173
173
  display: inline-flex;
174
174
  align-items: center;
175
175
  justify-content: center;
176
+ gap: 6px;
176
177
  background: var(--surface-page);
177
178
  color: var(--text-secondary);
178
179
  font-size: 12px;
@@ -185,6 +186,16 @@
185
186
  margin-left: 8px;
186
187
  }
187
188
 
189
+ .taskCountBadgeIcon {
190
+ flex: 0 0 auto;
191
+ }
192
+
193
+ .taskCountBadgeAlert {
194
+ color: #f87171;
195
+ border-color: color-mix(in srgb, #ef4444 45%, var(--border-default));
196
+ box-shadow: 0 0 10px rgba(239, 68, 68, 0.18);
197
+ }
198
+
188
199
  .headerActions {
189
200
  display: flex;
190
201
  align-items: center;
@@ -27,6 +27,16 @@ function defaultSetupTaxonomySections(pack) {
27
27
  priorities: Boolean(pack?.priorities?.length),
28
28
  };
29
29
  }
30
+ function buildPlansPath(params = {}) {
31
+ const query = new URLSearchParams();
32
+ query.set('screen', 'plans');
33
+ for (const [key, value] of Object.entries(params)) {
34
+ const normalized = String(value || '').trim();
35
+ if (normalized)
36
+ query.set(key, normalized);
37
+ }
38
+ return `/?${query.toString()}`;
39
+ }
30
40
  function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange, onHeaderMouseDown, isDragging, onClose, mode = 'standalone' }) {
31
41
  const location = useLocation();
32
42
  const routeQuery = useMemo(() => new URLSearchParams(location.search), [location.search]);
@@ -36,13 +46,15 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
36
46
  const isPricingRoute = location.pathname === '/pricing';
37
47
  const isPlansRoute = location.pathname === '/plans';
38
48
  const isPlansScreen = location.pathname === '/' && String(routeQuery.get('screen') || '').trim().toLowerCase() === 'plans';
39
- const planSelectionPath = '/?screen=plans&gate=plan_selection_required';
49
+ const planSelectionPath = buildPlansPath({ gate: 'plan_selection_required' });
40
50
  const navigate = useNavigate();
41
51
  const [loginEmail, setLoginEmail] = useState('');
42
52
  const [loginDisplayName, setLoginDisplayName] = useState('');
43
53
  const [loginPassword, setLoginPassword] = useState('');
44
54
  const [authMode, setAuthMode] = useState('login');
45
55
  const [verificationToken, setVerificationToken] = useState('');
56
+ const [pendingVerificationWorkspaceSetupRequired, setPendingVerificationWorkspaceSetupRequired] = useState(false);
57
+ const [pendingVerificationRedirectPath, setPendingVerificationRedirectPath] = useState(null);
46
58
  const [resetToken, setResetToken] = useState('');
47
59
  const [inviteToken, setInviteToken] = useState('');
48
60
  const [inviteEmail, setInviteEmail] = useState(null);
@@ -200,12 +212,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
200
212
  if (cancelled || !res.ok)
201
213
  return;
202
214
  const gate = String(payload?.gate || '').trim().toLowerCase();
203
- if (gate !== 'ok' && gate !== 'plan_selection_required' && gate !== 'misconfigured' && gate !== 'missing_entitlement') {
215
+ if (gate !== 'ok' && gate !== 'plan_selection_required' && gate !== 'checkout_pending' && gate !== 'misconfigured' && gate !== 'missing_entitlement') {
204
216
  setAccountAccessGate(null);
205
217
  return;
206
218
  }
207
219
  setAccountAccessGate({
208
- gate,
220
+ gate: gate,
209
221
  canAccessApp: payload?.canAccessApp === true,
210
222
  canAccessPlans: payload?.canAccessPlans !== false,
211
223
  message: typeof payload?.message === 'string' ? payload.message : null
@@ -351,6 +363,28 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
351
363
  return '/';
352
364
  return raw;
353
365
  }, [location.search]);
366
+ const resolvedSignupInterval = selectedSignupInterval === 'year' ? 'year' : 'month';
367
+ const resolvePostRegistrationPath = useCallback((input) => {
368
+ if (input?.planSelectionRequired || input?.commercialState === 'pending_plan_selection') {
369
+ return planSelectionPath;
370
+ }
371
+ if (input?.checkoutPending || input?.commercialState === 'checkout_pending') {
372
+ return buildPlansPath({
373
+ gate: 'checkout_pending',
374
+ checkout: selectedSignupPlanVersionId ? 'start' : null,
375
+ planId: selectedSignupPlanId || null,
376
+ planVersionId: selectedSignupPlanVersionId || null,
377
+ interval: selectedSignupPlanVersionId ? resolvedSignupInterval : null
378
+ });
379
+ }
380
+ return nextPath;
381
+ }, [
382
+ nextPath,
383
+ planSelectionPath,
384
+ resolvedSignupInterval,
385
+ selectedSignupPlanId,
386
+ selectedSignupPlanVersionId
387
+ ]);
354
388
  const loginRouteMode = useMemo(() => {
355
389
  const modeRaw = String(new URLSearchParams(location.search).get('mode') || '').trim().toLowerCase();
356
390
  if (modeRaw === 'register') {
@@ -405,6 +439,14 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
405
439
  if (loginRouteMode === 'invite' && loginRouteToken)
406
440
  setInviteToken(loginRouteToken);
407
441
  }, [isLoginRoute, loginRouteMode, loginRouteToken]);
442
+ useEffect(() => {
443
+ if (authMode === 'verify')
444
+ return;
445
+ if (isLoginRoute && loginRouteMode === 'verify')
446
+ return;
447
+ setPendingVerificationWorkspaceSetupRequired(false);
448
+ setPendingVerificationRedirectPath(null);
449
+ }, [authMode, isLoginRoute, loginRouteMode]);
408
450
  useEffect(() => {
409
451
  if (!isLoginRoute || authMode !== 'invite' || !inviteToken.trim())
410
452
  return;
@@ -710,11 +752,10 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
710
752
  }
711
753
  }
712
754
  else if (authMode === 'register') {
713
- if (await routeToWorkspaceSetupIfNeeded(result.workspaceSetupRequired)) {
714
- setLoginBusy(false);
715
- return;
716
- }
755
+ const postRegistrationPath = resolvePostRegistrationPath(result);
717
756
  if (result.verificationRequired) {
757
+ setPendingVerificationWorkspaceSetupRequired(Boolean(result.workspaceSetupRequired));
758
+ setPendingVerificationRedirectPath(postRegistrationPath);
718
759
  if (result.verificationToken)
719
760
  setVerificationToken(result.verificationToken);
720
761
  setVerifyCooldownUntil(Date.now() + 30_000);
@@ -724,17 +765,26 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
724
765
  : 'Account created. Check your email for verification instructions.');
725
766
  }
726
767
  else {
768
+ await retryBootstrapChecks();
769
+ if (await routeToWorkspaceSetupIfNeeded(result.workspaceSetupRequired)) {
770
+ setLoginBusy(false);
771
+ return;
772
+ }
727
773
  setLoginEmail('');
728
774
  setLoginDisplayName('');
729
775
  setLoginPassword('');
730
- navigate(nextPath, { replace: true });
776
+ navigate(postRegistrationPath, { replace: true });
731
777
  }
732
778
  }
733
779
  else if (authMode === 'verify') {
734
780
  await retryBootstrapChecks();
781
+ if (await routeToWorkspaceSetupIfNeeded(pendingVerificationWorkspaceSetupRequired)) {
782
+ setLoginBusy(false);
783
+ return;
784
+ }
735
785
  setLoginEmail('');
736
786
  setLoginPassword('');
737
- navigate(nextPath, { replace: true });
787
+ navigate(pendingVerificationRedirectPath || nextPath, { replace: true });
738
788
  }
739
789
  else if (authMode === 'forgot') {
740
790
  if (result.resetToken)