@taskforcehq/taskforce 0.3.305 → 0.3.307
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 +0 -2
- package/dist/Taskforce.module.css +603 -107
- package/dist/TaskforceCore.js +216 -43
- package/dist/TaskforceCore.test.js +611 -28
- 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 +46 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
- package/dist/components/activity/EntityActivityTimeline.js +81 -0
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +561 -0
- package/dist/components/features/AgentsModule.d.ts +14 -1
- package/dist/components/features/AgentsModule.js +366 -18
- package/dist/components/features/AgentsModule.test.js +507 -8
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
- package/dist/components/features/DocumentIndex.d.ts +2 -2
- package/dist/components/features/DocumentIndex.js +3 -4
- package/dist/components/features/DocumentViewer.d.ts +7 -1
- package/dist/components/features/DocumentViewer.js +62 -4
- package/dist/components/features/DocumentWorkspace.d.ts +10 -2
- package/dist/components/features/DocumentWorkspace.js +15 -4
- package/dist/components/features/DocumentWorkspace.test.js +51 -1
- package/dist/components/features/TaskSettings.d.ts +2 -0
- package/dist/components/features/TaskSettings.js +83 -78
- package/dist/components/features/TaskSettings.test.js +171 -82
- package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
- package/dist/components/task/TaskActionHeader.js +11 -5
- package/dist/components/task/TaskActionHeader.test.js +10 -0
- package/dist/components/task/TaskCard.js +24 -29
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskContextUpload.test.js +3 -3
- package/dist/components/task/TaskForm.js +61 -116
- package/dist/components/task/TaskForm.test.js +110 -8
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +94 -21
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/task/TaskList.js +5 -1
- package/dist/components/task/TaskList.test.js +4 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
- package/dist/components/ui/HierarchyActionBadge.js +5 -0
- package/dist/components/views/AppShellHeader.d.ts +3 -1
- package/dist/components/views/AppShellHeader.js +27 -11
- package/dist/components/views/AppShellHeader.test.js +18 -1
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +78 -14
- package/dist/components/views/PlanComparisonPage.test.js +257 -0
- package/dist/components/views/PlansPage.js +127 -36
- package/dist/components/views/PlansPage.test.js +294 -12
- package/dist/components/views/StandaloneLayout.js +529 -592
- package/dist/components/views/WidgetView.js +10 -8
- package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
- package/dist/components/views/panels/PlanningDrawer.js +270 -55
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +529 -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 +26 -1
- package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
- 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 -0
- package/dist/core/AiProfileService.d.ts +46 -2
- package/dist/core/AiProfileService.js +1073 -82
- package/dist/core/AiProfileService.test.js +19 -1
- package/dist/core/AiProfiles.test.js +1249 -44
- package/dist/core/AttachmentLinkService.d.ts +3 -0
- package/dist/core/AttachmentLinkService.js +110 -23
- 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.js +3 -3
- package/dist/core/EntitlementsPolicy.test.js +2 -2
- package/dist/core/GlobalSettingsService.js +127 -6
- package/dist/core/McpTokenService.d.ts +12 -0
- package/dist/core/McpTokenService.js +44 -1
- package/dist/core/PlanEntitlementService.d.ts +23 -2
- package/dist/core/PlanEntitlementService.js +343 -57
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +35 -2
- package/dist/core/PlanningEntities.test.js +418 -4
- package/dist/core/SignupMonetizationSettings.test.js +199 -27
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +42 -42
- package/dist/core/TaskActivityService.d.ts +28 -1
- package/dist/core/TaskActivityService.js +227 -46
- package/dist/core/TaskActivitySync.test.d.ts +1 -0
- package/dist/core/TaskActivitySync.test.js +90 -0
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskAuditTimeline.test.js +96 -0
- package/dist/core/Taskforce.d.ts +415 -40
- package/dist/core/Taskforce.ids.test.js +58 -0
- package/dist/core/Taskforce.js +1543 -266
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/Taskforce.mcpAuth.test.js +109 -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 +117 -16
- package/dist/core/shared.d.ts +1 -1
- package/dist/core/shared.js +5 -1
- package/dist/core/types.d.ts +75 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
- package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
- package/dist/hooks/bootstrapTimeouts.js +8 -0
- package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
- package/dist/hooks/bootstrapTimeouts.test.js +12 -0
- 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 +13 -4
- package/dist/hooks/sync/orchestratorShared.js +129 -48
- 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 +179 -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 +210 -66
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +928 -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/useFilterSort.js +13 -13
- package/dist/hooks/useFilterSort.test.js +87 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
- package/dist/hooks/useSyncOrchestrator.js +409 -183
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskforce.d.ts +145 -52
- package/dist/hooks/useTaskforce.js +592 -253
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
- package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.js +13 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
- 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/canonicalAssetHelpers.d.ts +16 -4
- package/dist/mcp/canonicalAssetHelpers.js +18 -10
- package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
- package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
- package/dist/mcp/clientIntegrations.d.ts +1 -0
- package/dist/mcp/clientIntegrations.js +25 -0
- package/dist/mcp/clientIntegrations.test.js +14 -3
- package/dist/mcp/clientProfileDefaults.js +3 -3
- package/dist/mcp/collaborationRegistrar.js +7 -7
- package/dist/mcp/documentAssetRegistrar.js +116 -10
- package/dist/mcp/runtime.d.ts +3 -0
- package/dist/mcp/runtime.js +1099 -185
- package/dist/mcp/runtime.test.js +1491 -140
- package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
- package/dist/mcp/taskPlanningRegistrar.js +48 -0
- package/dist/mcp/toolRegistry.d.ts +56 -0
- package/dist/mcp/toolRegistry.js +8 -0
- package/dist/mcp/toolRegistry.test.js +4 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +192 -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/aiProfileAvatarAssets.d.ts +49 -0
- package/dist/server/aiProfileAvatarAssets.js +319 -0
- package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
- package/dist/server/aiProfileAvatarAssets.test.js +213 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
- 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 +124 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +111 -3
- package/dist/server/routes/admin.d.ts +3 -0
- package/dist/server/routes/admin.js +459 -28
- package/dist/server/routes/annotatedAttachments.js +51 -0
- package/dist/server/routes/auth.d.ts +26 -2
- package/dist/server/routes/auth.js +1170 -71
- package/dist/server/routes/authSupport.d.ts +5 -1
- package/dist/server/routes/authSupport.js +13 -2
- package/dist/server/routes/billing.js +372 -35
- package/dist/server/routes/billing.test.js +595 -12
- package/dist/server/routes/documents.d.ts +1 -0
- package/dist/server/routes/documents.js +182 -70
- package/dist/server/routes/shared.d.ts +28 -2
- package/dist/server/routes/shared.js +69 -14
- package/dist/server/routes/sync.integration.test.js +658 -39
- package/dist/server/routes/sync.js +74 -608
- 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 +182 -0
- package/dist/server/routes/tasks.js +55 -10
- package/dist/server/routes/workspaces.js +36 -5
- package/dist/server/routes.js +147 -11
- package/dist/server/routes.test.js +2704 -183
- 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/aiProfileSurfaceType.d.ts +1 -1
- package/dist/shared/aiProfileSurfaceType.js +10 -8
- 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/objectStorage.d.ts +1 -0
- package/dist/storage/objectStorage.js +2 -1
- package/dist/storage/objectStorageClient.d.ts +1 -0
- package/dist/storage/objectStorageClient.js +41 -8
- package/dist/storage/objectStorageClient.test.js +26 -1
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.js +13 -1
- 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 +19 -11
- package/dist/sync/collaborationSyncPayload.test.js +14 -1
- package/dist/sync/collaborationSyncState.d.ts +3 -3
- package/dist/sync/collaborationSyncState.js +19 -12
- package/dist/sync/contentSyncPayload.d.ts +5 -1
- package/dist/sync/contentSyncPayload.js +9 -0
- package/dist/sync/contentSyncPayload.test.js +39 -0
- package/dist/sync/contentSyncState.d.ts +9 -9
- package/dist/sync/contentSyncState.js +248 -107
- package/dist/sync/planningSyncPayload.js +5 -0
- package/dist/sync/planningSyncPayload.test.js +24 -0
- package/dist/sync/syncApplyHandlers.d.ts +11 -4
- package/dist/sync/syncApplyHandlers.js +115 -42
- package/dist/sync/syncApplyHandlers.test.js +251 -4
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +46 -0
- package/dist/sync/syncResourceAdapters.js +79 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +65 -1
- package/dist/sync/syncService.test.js +96 -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.d.ts +4 -0
- package/dist/sync/workspacePullFeed.js +132 -72
- package/dist/sync/workspacePullFeed.test.js +92 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +73 -6
- package/dist/sync/workspaceSyncModel.js +342 -73
- package/dist/sync/workspaceSyncModel.test.js +559 -14
- package/dist/sync/workspaceSyncState.d.ts +17 -0
- package/dist/sync/workspaceSyncState.js +2 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +50 -2
- package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
- package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
- 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-D4rJKXzd.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
- package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
- package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
- package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.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-D5AcbO0L.js +1 -0
- package/dist/ui/assets/PlansPage-Dvqsz5zc.css +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/TaskContextUpload-uC5qx4Bv.js +1 -0
- package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
- package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
- package/dist/ui/assets/index-607WPo_X.js +4 -0
- package/dist/ui/assets/index-CYyodXsg.css +1 -0
- package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.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/ui/product/agent manager.png +0 -0
- package/dist/ui/product/agent_manager_02.png +0 -0
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/aiProfileEvents.d.ts +7 -0
- package/dist/utils/aiProfileEvents.js +6 -0
- package/dist/utils/assignees.d.ts +8 -0
- package/dist/utils/assignees.js +10 -1
- package/dist/utils/assignees.test.d.ts +1 -0
- package/dist/utils/assignees.test.js +25 -0
- package/dist/utils/avatarDisplay.d.ts +1 -0
- package/dist/utils/avatarDisplay.js +15 -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.js +3 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- package/dist/utils/contextFiles.d.ts +3 -1
- package/dist/utils/contextFiles.js +2 -1
- 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 +9 -1
- package/dist/utils/taskActivity.js +290 -22
- package/dist/utils/taskActivity.test.js +141 -8
- package/dist/utils/taskSearch.d.ts +22 -0
- package/dist/utils/taskSearch.js +87 -0
- package/dist/utils/taskSearch.test.d.ts +1 -0
- package/dist/utils/taskSearch.test.js +69 -0
- package/dist/utils/taskUtils.js +10 -3
- package/dist/utils/taskUtils.test.d.ts +1 -0
- package/dist/utils/taskUtils.test.js +19 -0
- 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 +3 -2
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- 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-N2MnQBZk.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
- package/dist/ui/assets/index-C2-OXZV7.css +0 -1
- package/dist/ui/assets/index-DcSI5F86.js +0 -6
- package/scripts/migrate-planning-model.ts +0 -233
package/dist/sync/syncService.js
CHANGED
|
@@ -15,6 +15,14 @@ function resolveWorkspaceAccessConflictMessage(data, fallbackStatus) {
|
|
|
15
15
|
}
|
|
16
16
|
return rawError || `Workspace provisioning failed (${fallbackStatus})`;
|
|
17
17
|
}
|
|
18
|
+
function isMissingCloudWorkspaceSelection(data, status) {
|
|
19
|
+
if (status !== 400)
|
|
20
|
+
return false;
|
|
21
|
+
const code = String(data.code || '').trim().toUpperCase();
|
|
22
|
+
const rawError = String(data.error || '').trim().toLowerCase();
|
|
23
|
+
return code === 'WORKSPACE_ID_REQUIRED'
|
|
24
|
+
&& rawError.includes('no cloud workspace is selected');
|
|
25
|
+
}
|
|
18
26
|
export async function ensureCloudWorkspaceReadyForSyncService(input) {
|
|
19
27
|
if (!input.cloudAuthConfigured)
|
|
20
28
|
return { success: false, error: 'Cloud auth endpoint is not configured.' };
|
|
@@ -44,6 +52,39 @@ export async function ensureCloudWorkspaceReadyForSyncService(input) {
|
|
|
44
52
|
error: String(data.error || 'Workspace sync rate limited. Please retry later.')
|
|
45
53
|
};
|
|
46
54
|
}
|
|
55
|
+
if (isMissingCloudWorkspaceSelection(data, handshakeResult.status)) {
|
|
56
|
+
const provisionResult = await provisionWorkspace(input.resolveCloudAuthUrl, {
|
|
57
|
+
workspaceId: input.workspaceId,
|
|
58
|
+
name: input.workspaceName || input.workspaceId
|
|
59
|
+
});
|
|
60
|
+
if (!provisionResult.ok) {
|
|
61
|
+
const provisionError = asObjectRecord(provisionResult.data);
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
statusCode: provisionResult.status,
|
|
65
|
+
transient: isTransientWorkspaceSyncStatus(provisionResult.status),
|
|
66
|
+
retryAfterMs: provisionResult.retryAfterMs,
|
|
67
|
+
error: resolveWorkspaceAccessConflictMessage(provisionError, provisionResult.status)
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
handshakeResult = await handshakeWorkspace(input.resolveCloudAuthUrl, input.workspaceId);
|
|
71
|
+
if (!handshakeResult.ok) {
|
|
72
|
+
const retryData = asObjectRecord(handshakeResult.data);
|
|
73
|
+
if (handshakeResult.status === 401) {
|
|
74
|
+
return { success: false, statusCode: 401, transient: false, error: String(retryData.error || 'Authentication required for workspace sync.') };
|
|
75
|
+
}
|
|
76
|
+
if (handshakeResult.status === 429) {
|
|
77
|
+
return { success: false, statusCode: 429, retryAfterMs: handshakeResult.retryAfterMs, transient: true, error: String(retryData.error || 'Workspace sync rate limited. Please retry later.') };
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
statusCode: handshakeResult.status,
|
|
82
|
+
transient: isTransientWorkspaceSyncStatus(handshakeResult.status),
|
|
83
|
+
error: String(retryData.error || `Workspace sync handshake failed (${handshakeResult.status})`)
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return { success: true, provisioned: true };
|
|
87
|
+
}
|
|
47
88
|
if (handshakeResult.status === 409 && data.code === 'WORKSPACE_ID_MISMATCH') {
|
|
48
89
|
if (input.allowProvisionOnMismatch === false) {
|
|
49
90
|
return {
|
|
@@ -173,6 +214,8 @@ export async function runWorkspacePushSyncService(input) {
|
|
|
173
214
|
changeCount,
|
|
174
215
|
deleteCount,
|
|
175
216
|
currentTaskIds: input.payload.currentTaskIds,
|
|
217
|
+
currentTaskWatermarks: input.payload.currentTaskWatermarks ?? new Map(),
|
|
218
|
+
currentTaskChangeKeys: input.payload.currentTaskChangeKeys ?? new Map(),
|
|
176
219
|
deleteTaskIds: input.payload.deleteTaskIds,
|
|
177
220
|
currentInitiativeIds: input.payload.currentInitiativeIds,
|
|
178
221
|
currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
|
|
@@ -180,6 +223,7 @@ export async function runWorkspacePushSyncService(input) {
|
|
|
180
223
|
currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
|
|
181
224
|
currentAiProfileIds: input.payload.currentAiProfileIds,
|
|
182
225
|
currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
|
|
226
|
+
currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
|
|
183
227
|
currentDocumentPaths: input.payload.currentDocumentPaths,
|
|
184
228
|
deleteDocumentPaths: input.payload.deleteDocumentPaths,
|
|
185
229
|
currentDocumentWatermarks: input.payload.currentDocumentWatermarks,
|
|
@@ -197,6 +241,7 @@ export async function runWorkspacePushSyncService(input) {
|
|
|
197
241
|
currentAnnotatedAttachmentSessionWatermarks: input.payload.currentAnnotatedAttachmentSessionWatermarks,
|
|
198
242
|
currentTaskEventWatermarks: input.payload.currentTaskEventWatermarks,
|
|
199
243
|
pushedWatermarks: new Map(),
|
|
244
|
+
pushedTaskChangeKeys: new Map(),
|
|
200
245
|
emittedEventIds: [],
|
|
201
246
|
appliedTaskUpserts: []
|
|
202
247
|
};
|
|
@@ -231,6 +276,8 @@ export async function runWorkspacePushSyncService(input) {
|
|
|
231
276
|
changeCount,
|
|
232
277
|
deleteCount,
|
|
233
278
|
currentTaskIds: input.payload.currentTaskIds,
|
|
279
|
+
currentTaskWatermarks: input.payload.currentTaskWatermarks ?? new Map(),
|
|
280
|
+
currentTaskChangeKeys: input.payload.currentTaskChangeKeys ?? new Map(),
|
|
234
281
|
deleteTaskIds: input.payload.deleteTaskIds,
|
|
235
282
|
currentInitiativeIds: input.payload.currentInitiativeIds,
|
|
236
283
|
currentInitiativeWatermarks: input.payload.currentInitiativeWatermarks,
|
|
@@ -238,6 +285,7 @@ export async function runWorkspacePushSyncService(input) {
|
|
|
238
285
|
currentWorkstreamWatermarks: input.payload.currentWorkstreamWatermarks,
|
|
239
286
|
currentAiProfileIds: input.payload.currentAiProfileIds,
|
|
240
287
|
currentAiProfileWatermarks: input.payload.currentAiProfileWatermarks,
|
|
288
|
+
currentAiProfileChangeKeys: input.payload.currentAiProfileChangeKeys ?? new Map(),
|
|
241
289
|
currentDocumentPaths: input.payload.currentDocumentPaths,
|
|
242
290
|
deleteDocumentPaths: input.payload.deleteDocumentPaths,
|
|
243
291
|
currentDocumentWatermarks: input.payload.currentDocumentWatermarks,
|
|
@@ -255,6 +303,7 @@ export async function runWorkspacePushSyncService(input) {
|
|
|
255
303
|
currentAnnotatedAttachmentSessionWatermarks: input.payload.currentAnnotatedAttachmentSessionWatermarks,
|
|
256
304
|
currentTaskEventWatermarks: input.payload.currentTaskEventWatermarks,
|
|
257
305
|
pushedWatermarks: input.payload.pushedWatermarks,
|
|
306
|
+
pushedTaskChangeKeys: input.payload.pushedTaskChangeKeys ?? new Map(),
|
|
258
307
|
emittedEventIds,
|
|
259
308
|
appliedTaskUpserts
|
|
260
309
|
};
|
|
@@ -270,6 +319,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
270
319
|
let pulledActiveUpserts = false;
|
|
271
320
|
let pulledArchivedUpserts = false;
|
|
272
321
|
let pulledTaskEventUpserts = false;
|
|
322
|
+
let pulledPlanningUpserts = false;
|
|
273
323
|
const documentDecryptFailures = new Set();
|
|
274
324
|
const emittedEventIds = new Set();
|
|
275
325
|
const pulledAnnotatedAttachmentSessionIds = new Set();
|
|
@@ -296,10 +346,13 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
296
346
|
}
|
|
297
347
|
}
|
|
298
348
|
if (!pullRes.ok) {
|
|
349
|
+
const pullErrorData = asObjectRecord(pullRes.data);
|
|
299
350
|
return {
|
|
300
351
|
success: false,
|
|
301
352
|
kind: 'pull_http',
|
|
302
353
|
status: pullRes.status,
|
|
354
|
+
errorCode: typeof pullErrorData.code === 'string' ? pullErrorData.code : undefined,
|
|
355
|
+
error: typeof pullErrorData.error === 'string' ? pullErrorData.error : undefined,
|
|
303
356
|
retryAfterMs: pullRes.retryAfterMs,
|
|
304
357
|
transient: isTransientWorkspaceSyncStatus(pullRes.status),
|
|
305
358
|
cursor,
|
|
@@ -311,6 +364,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
311
364
|
pulledActiveUpserts,
|
|
312
365
|
pulledArchivedUpserts,
|
|
313
366
|
pulledTaskEventUpserts,
|
|
367
|
+
pulledPlanningUpserts,
|
|
314
368
|
documentDecryptFailures: Array.from(documentDecryptFailures),
|
|
315
369
|
serverDiagnostics: null
|
|
316
370
|
};
|
|
@@ -340,10 +394,14 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
340
394
|
pulledAnnotatedAttachmentSessionIds.add(sessionId);
|
|
341
395
|
continue;
|
|
342
396
|
}
|
|
343
|
-
if (change.op === 'task-event-upsert') {
|
|
397
|
+
if (change.op === 'task-event-upsert' || change.op === 'entity-event-upsert') {
|
|
344
398
|
pulledTaskEventUpserts = true;
|
|
345
399
|
continue;
|
|
346
400
|
}
|
|
401
|
+
if (change.op === 'initiative-upsert' || change.op === 'workstream-upsert') {
|
|
402
|
+
pulledPlanningUpserts = true;
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
347
405
|
if (change.op === 'document-upsert') {
|
|
348
406
|
if (typeof change.content === 'string' && typeof process !== 'undefined' && process.env?.TASKFORCE_SYNC_KEY) {
|
|
349
407
|
try {
|
|
@@ -435,6 +493,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
435
493
|
pulledActiveUpserts,
|
|
436
494
|
pulledArchivedUpserts,
|
|
437
495
|
pulledTaskEventUpserts,
|
|
496
|
+
pulledPlanningUpserts,
|
|
438
497
|
documentDecryptFailures: Array.from(documentDecryptFailures),
|
|
439
498
|
emittedEventIds: Array.from(emittedEventIds),
|
|
440
499
|
serverDiagnostics: lastServerDiagnostics
|
|
@@ -457,6 +516,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
457
516
|
pulledActiveUpserts,
|
|
458
517
|
pulledArchivedUpserts,
|
|
459
518
|
pulledTaskEventUpserts,
|
|
519
|
+
pulledPlanningUpserts,
|
|
460
520
|
documentDecryptFailures: Array.from(documentDecryptFailures),
|
|
461
521
|
emittedEventIds: Array.from(emittedEventIds),
|
|
462
522
|
serverDiagnostics: lastServerDiagnostics
|
|
@@ -508,6 +568,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
508
568
|
pulledActiveUpserts,
|
|
509
569
|
pulledArchivedUpserts,
|
|
510
570
|
pulledTaskEventUpserts,
|
|
571
|
+
pulledPlanningUpserts,
|
|
511
572
|
documentDecryptFailures: Array.from(documentDecryptFailures),
|
|
512
573
|
emittedEventIds: Array.from(emittedEventIds),
|
|
513
574
|
serverDiagnostics: lastServerDiagnostics
|
|
@@ -537,6 +598,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
537
598
|
pulledActiveUpserts,
|
|
538
599
|
pulledArchivedUpserts,
|
|
539
600
|
pulledTaskEventUpserts,
|
|
601
|
+
pulledPlanningUpserts,
|
|
540
602
|
documentDecryptFailures: Array.from(documentDecryptFailures),
|
|
541
603
|
emittedEventIds: Array.from(emittedEventIds),
|
|
542
604
|
serverDiagnostics: lastServerDiagnostics
|
|
@@ -556,6 +618,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
556
618
|
pulledActiveUpserts,
|
|
557
619
|
pulledArchivedUpserts,
|
|
558
620
|
pulledTaskEventUpserts,
|
|
621
|
+
pulledPlanningUpserts,
|
|
559
622
|
documentDecryptFailures: Array.from(documentDecryptFailures),
|
|
560
623
|
emittedEventIds: Array.from(emittedEventIds),
|
|
561
624
|
serverDiagnostics: lastServerDiagnostics
|
|
@@ -577,6 +640,7 @@ export async function runWorkspacePullSyncService(input) {
|
|
|
577
640
|
pulledActiveUpserts,
|
|
578
641
|
pulledArchivedUpserts,
|
|
579
642
|
pulledTaskEventUpserts,
|
|
643
|
+
pulledPlanningUpserts,
|
|
580
644
|
documentDecryptFailures: Array.from(documentDecryptFailures),
|
|
581
645
|
emittedEventIds: Array.from(emittedEventIds),
|
|
582
646
|
serverDiagnostics: null
|
|
@@ -443,7 +443,7 @@ describe('syncService', () => {
|
|
|
443
443
|
status: 200,
|
|
444
444
|
data: {
|
|
445
445
|
success: true,
|
|
446
|
-
changes: [{ op: 'upsert', task: { id: '
|
|
446
|
+
changes: [{ op: 'upsert', task: { id: 'task-apply-error', title: 'Apply error', status: 'done', updatedAt: '2026-03-15T20:27:08.000Z' } }],
|
|
447
447
|
nextCursor: null,
|
|
448
448
|
hasMore: false
|
|
449
449
|
}
|
|
@@ -452,7 +452,7 @@ describe('syncService', () => {
|
|
|
452
452
|
ok: false,
|
|
453
453
|
status: 400,
|
|
454
454
|
failures: ['/api/taskforce/sync/workspace/apply-local:400'],
|
|
455
|
-
data: { error: '
|
|
455
|
+
data: { error: 'Task apply rejected by local validation' }
|
|
456
456
|
});
|
|
457
457
|
const res = await runWorkspacePullSyncService({
|
|
458
458
|
resolveCloudAuthUrl: mockResolveCloudAuthUrl,
|
|
@@ -463,7 +463,7 @@ describe('syncService', () => {
|
|
|
463
463
|
expect(res.success).toBe(false);
|
|
464
464
|
expect(res.kind).toBe('apply_all_candidates');
|
|
465
465
|
expect(res.status).toBe(400);
|
|
466
|
-
expect(res.error).toBe('
|
|
466
|
+
expect(res.error).toBe('Task apply rejected by local validation');
|
|
467
467
|
});
|
|
468
468
|
it('surfaces document decryption failures without failing pull', async () => {
|
|
469
469
|
const previousKey = process.env.TASKFORCE_SYNC_KEY;
|
|
@@ -548,6 +548,45 @@ describe('syncService', () => {
|
|
|
548
548
|
expect(res.pulledActiveUpserts).toBe(false);
|
|
549
549
|
expect(res.pulledArchivedUpserts).toBe(false);
|
|
550
550
|
});
|
|
551
|
+
it('marks planning upserts when the pull contains initiative or workstream changes', async () => {
|
|
552
|
+
vi.mocked(pullWorkspaceChanges).mockResolvedValueOnce({
|
|
553
|
+
ok: true,
|
|
554
|
+
status: 200,
|
|
555
|
+
data: {
|
|
556
|
+
success: true,
|
|
557
|
+
changes: [{
|
|
558
|
+
op: 'workstream-upsert',
|
|
559
|
+
updatedAt: '2026-04-27T22:00:00.000Z',
|
|
560
|
+
workstream: {
|
|
561
|
+
id: 'ws-123',
|
|
562
|
+
title: 'Planning sync workstream',
|
|
563
|
+
description: 'Contains planning attachments',
|
|
564
|
+
createdAt: '2026-04-27T21:00:00.000Z',
|
|
565
|
+
updatedAt: '2026-04-27T22:00:00.000Z',
|
|
566
|
+
attachments: []
|
|
567
|
+
}
|
|
568
|
+
}],
|
|
569
|
+
nextCursor: null,
|
|
570
|
+
hasMore: false
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
vi.mocked(applyLocalWorkspaceChanges).mockResolvedValueOnce({
|
|
574
|
+
ok: true,
|
|
575
|
+
failures: [],
|
|
576
|
+
appliedCount: 1,
|
|
577
|
+
data: { success: true }
|
|
578
|
+
});
|
|
579
|
+
const res = await runWorkspacePullSyncService({
|
|
580
|
+
resolveCloudAuthUrl: mockResolveCloudAuthUrl,
|
|
581
|
+
workspaceId: 'ws-1',
|
|
582
|
+
cursor: null,
|
|
583
|
+
bootstrap: false
|
|
584
|
+
});
|
|
585
|
+
expect(res.success).toBe(true);
|
|
586
|
+
expect(res.pulledPlanningUpserts).toBe(true);
|
|
587
|
+
expect(res.pulledActiveUpserts).toBe(false);
|
|
588
|
+
expect(res.pulledArchivedUpserts).toBe(false);
|
|
589
|
+
});
|
|
551
590
|
it('zero-change bootstrap pull (no changes, hasMore false) returns success true', async () => {
|
|
552
591
|
vi.mocked(pullWorkspaceChanges).mockResolvedValueOnce({
|
|
553
592
|
ok: true,
|
|
@@ -702,6 +741,60 @@ describe('syncService', () => {
|
|
|
702
741
|
expect(res.statusCode).toBe(0);
|
|
703
742
|
expect(res.transient).toBe(true);
|
|
704
743
|
});
|
|
744
|
+
it('recovers from missing cloud workspace selection by provisioning and retrying handshake', async () => {
|
|
745
|
+
vi.mocked(handshakeWorkspace)
|
|
746
|
+
.mockResolvedValueOnce({
|
|
747
|
+
ok: false,
|
|
748
|
+
status: 400,
|
|
749
|
+
data: {
|
|
750
|
+
code: 'WORKSPACE_ID_REQUIRED',
|
|
751
|
+
error: 'No cloud workspace is selected. Complete workspace setup first.'
|
|
752
|
+
}
|
|
753
|
+
})
|
|
754
|
+
.mockResolvedValueOnce({
|
|
755
|
+
ok: true,
|
|
756
|
+
status: 200,
|
|
757
|
+
data: {}
|
|
758
|
+
});
|
|
759
|
+
vi.mocked(provisionWorkspace).mockResolvedValueOnce({
|
|
760
|
+
ok: true,
|
|
761
|
+
status: 200,
|
|
762
|
+
data: {
|
|
763
|
+
success: true,
|
|
764
|
+
existing: true
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
const res = await ensureCloudWorkspaceReadyForSyncService(baseHandshakeInput);
|
|
768
|
+
expect(res.success).toBe(true);
|
|
769
|
+
expect(res.provisioned).toBe(true);
|
|
770
|
+
expect(provisionWorkspace).toHaveBeenCalledWith(mockResolveCloudAuthUrl, {
|
|
771
|
+
workspaceId: 'ws-test',
|
|
772
|
+
name: 'Test Workspace'
|
|
773
|
+
});
|
|
774
|
+
expect(handshakeWorkspace).toHaveBeenCalledTimes(2);
|
|
775
|
+
});
|
|
776
|
+
it('surfaces provisioning failure when recovering missing cloud workspace selection', async () => {
|
|
777
|
+
vi.mocked(handshakeWorkspace).mockResolvedValueOnce({
|
|
778
|
+
ok: false,
|
|
779
|
+
status: 400,
|
|
780
|
+
data: {
|
|
781
|
+
code: 'WORKSPACE_ID_REQUIRED',
|
|
782
|
+
error: 'No cloud workspace is selected. Complete workspace setup first.'
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
vi.mocked(provisionWorkspace).mockResolvedValueOnce({
|
|
786
|
+
ok: false,
|
|
787
|
+
status: 409,
|
|
788
|
+
data: {
|
|
789
|
+
code: 'WORKSPACE_ID_ALREADY_EXISTS',
|
|
790
|
+
error: 'Workspace ID already exists'
|
|
791
|
+
}
|
|
792
|
+
});
|
|
793
|
+
const res = await ensureCloudWorkspaceReadyForSyncService(baseHandshakeInput);
|
|
794
|
+
expect(res.success).toBe(false);
|
|
795
|
+
expect(res.statusCode).toBe(409);
|
|
796
|
+
expect(res.error).toContain('already linked to another cloud account');
|
|
797
|
+
});
|
|
705
798
|
it('returns failure when cloudAuthConfigured is false', async () => {
|
|
706
799
|
const res = await ensureCloudWorkspaceReadyForSyncService({
|
|
707
800
|
...baseHandshakeInput,
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { serializeTaskForSync } from './taskSyncPayload.js';
|
|
2
|
+
import { normalizeSyncNullableId, normalizeSyncNullableIsoString, normalizeSyncNullableString, normalizeSyncOptionalId, normalizeSyncOptionalString, } from './syncFieldSemantics.js';
|
|
3
|
+
function normalizeConflictTaxonomies(value) {
|
|
4
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
5
|
+
return {};
|
|
6
|
+
const entries = Object.entries(value)
|
|
7
|
+
.filter(([key]) => String(key || '').trim().length > 0)
|
|
8
|
+
.sort(([left], [right]) => left.localeCompare(right));
|
|
9
|
+
const normalized = {};
|
|
10
|
+
for (const [key, raw] of entries) {
|
|
11
|
+
if (Array.isArray(raw)) {
|
|
12
|
+
normalized[key] = raw.map((entry) => String(entry ?? '')).sort((left, right) => left.localeCompare(right));
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (raw === undefined || raw === null)
|
|
16
|
+
continue;
|
|
17
|
+
normalized[key] = String(raw);
|
|
18
|
+
}
|
|
19
|
+
return normalized;
|
|
20
|
+
}
|
|
21
|
+
function normalizeConflictChecklistItems(value) {
|
|
22
|
+
if (!Array.isArray(value))
|
|
23
|
+
return [];
|
|
24
|
+
return value
|
|
25
|
+
.map((item) => {
|
|
26
|
+
const entry = item && typeof item === 'object' ? item : {};
|
|
27
|
+
return {
|
|
28
|
+
id: String(entry.id || '').trim(),
|
|
29
|
+
title: String(entry.title || '').trim(),
|
|
30
|
+
isCompleted: Boolean(entry.isCompleted),
|
|
31
|
+
order: entry.order === undefined || entry.order === null ? '' : String(entry.order),
|
|
32
|
+
};
|
|
33
|
+
})
|
|
34
|
+
.sort((left, right) => {
|
|
35
|
+
const leftOrder = Number.parseInt(left.order, 10);
|
|
36
|
+
const rightOrder = Number.parseInt(right.order, 10);
|
|
37
|
+
if (Number.isFinite(leftOrder) && Number.isFinite(rightOrder) && leftOrder !== rightOrder) {
|
|
38
|
+
return leftOrder - rightOrder;
|
|
39
|
+
}
|
|
40
|
+
if (left.title !== right.title)
|
|
41
|
+
return left.title.localeCompare(right.title);
|
|
42
|
+
return left.id.localeCompare(right.id);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function normalizeSyncComments(value) {
|
|
46
|
+
if (!Array.isArray(value))
|
|
47
|
+
return [];
|
|
48
|
+
return value
|
|
49
|
+
.map((entry) => {
|
|
50
|
+
const comment = entry && typeof entry === 'object' ? entry : null;
|
|
51
|
+
return {
|
|
52
|
+
id: String(comment?.id || '').trim(),
|
|
53
|
+
author: String(comment?.author || '').trim(),
|
|
54
|
+
submittedAuthor: normalizeSyncOptionalString(comment?.submittedAuthor) || '',
|
|
55
|
+
text: String(comment?.text || ''),
|
|
56
|
+
timestamp: normalizeSyncNullableIsoString(comment?.timestamp) || '',
|
|
57
|
+
actor: comment?.actor ?? null,
|
|
58
|
+
};
|
|
59
|
+
})
|
|
60
|
+
.sort((left, right) => {
|
|
61
|
+
if (left.timestamp !== right.timestamp)
|
|
62
|
+
return left.timestamp.localeCompare(right.timestamp);
|
|
63
|
+
if (left.id !== right.id)
|
|
64
|
+
return left.id.localeCompare(right.id);
|
|
65
|
+
if (left.author !== right.author)
|
|
66
|
+
return left.author.localeCompare(right.author);
|
|
67
|
+
return left.text.localeCompare(right.text);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function normalizeSyncAttachments(value) {
|
|
71
|
+
if (!Array.isArray(value))
|
|
72
|
+
return [];
|
|
73
|
+
return value
|
|
74
|
+
.map((entry) => {
|
|
75
|
+
if (typeof entry === 'string') {
|
|
76
|
+
const path = entry.trim();
|
|
77
|
+
return {
|
|
78
|
+
path,
|
|
79
|
+
fsPath: '',
|
|
80
|
+
caption: '',
|
|
81
|
+
displayName: '',
|
|
82
|
+
originalFilename: '',
|
|
83
|
+
assetId: '',
|
|
84
|
+
referenceNumber: '',
|
|
85
|
+
taskId: '',
|
|
86
|
+
timestamp: '',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const attachment = entry && typeof entry === 'object' ? entry : null;
|
|
90
|
+
return {
|
|
91
|
+
path: String(attachment?.path || '').trim(),
|
|
92
|
+
fsPath: normalizeSyncOptionalString(attachment?.fsPath) || '',
|
|
93
|
+
caption: normalizeSyncOptionalString(attachment?.caption) || '',
|
|
94
|
+
displayName: normalizeSyncOptionalString(attachment?.displayName) || '',
|
|
95
|
+
originalFilename: normalizeSyncOptionalString(attachment?.originalFilename) || '',
|
|
96
|
+
assetId: normalizeSyncOptionalId(attachment?.assetId) || '',
|
|
97
|
+
referenceNumber: attachment?.referenceNumber === undefined || attachment.referenceNumber === null
|
|
98
|
+
? ''
|
|
99
|
+
: String(attachment.referenceNumber),
|
|
100
|
+
taskId: normalizeSyncNullableId(attachment?.taskId) || '',
|
|
101
|
+
timestamp: normalizeSyncNullableIsoString(attachment?.timestamp) || '',
|
|
102
|
+
};
|
|
103
|
+
})
|
|
104
|
+
.sort((left, right) => {
|
|
105
|
+
if (left.path !== right.path)
|
|
106
|
+
return left.path.localeCompare(right.path);
|
|
107
|
+
if (left.assetId !== right.assetId)
|
|
108
|
+
return left.assetId.localeCompare(right.assetId);
|
|
109
|
+
if (left.timestamp !== right.timestamp)
|
|
110
|
+
return left.timestamp.localeCompare(right.timestamp);
|
|
111
|
+
return JSON.stringify(left).localeCompare(JSON.stringify(right));
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
export function buildTaskSyncChangeKey(task, archivedValue) {
|
|
115
|
+
const source = serializeTaskForSync(task);
|
|
116
|
+
return JSON.stringify({
|
|
117
|
+
id: source.id,
|
|
118
|
+
title: source.title,
|
|
119
|
+
description: normalizeSyncNullableString(source.description) || '',
|
|
120
|
+
category: source.category,
|
|
121
|
+
type: source.type,
|
|
122
|
+
priority: source.priority === undefined || source.priority === null ? '' : String(source.priority),
|
|
123
|
+
complexity: source.complexity === undefined || source.complexity === null ? '' : String(source.complexity),
|
|
124
|
+
status: source.status,
|
|
125
|
+
approach: normalizeSyncOptionalString(source.approach) || '',
|
|
126
|
+
canceledReason: normalizeSyncNullableString(source.canceledReason) || '',
|
|
127
|
+
createdAt: source.createdAt,
|
|
128
|
+
completedAt: normalizeSyncNullableIsoString(source.completedAt) || '',
|
|
129
|
+
taxonomies: normalizeConflictTaxonomies(source.taxonomies),
|
|
130
|
+
createdBy: normalizeSyncOptionalId(source.createdBy) || '',
|
|
131
|
+
assignee: normalizeSyncOptionalId(source.assignee) || '',
|
|
132
|
+
scheduledDate: normalizeSyncNullableString(source.scheduledDate) || '',
|
|
133
|
+
dueDate: normalizeSyncNullableString(source.dueDate) || '',
|
|
134
|
+
scheduledWeekKey: normalizeSyncNullableString(source.scheduledWeekKey) || '',
|
|
135
|
+
orderInDay: source.orderInDay === undefined || source.orderInDay === null ? '' : String(source.orderInDay),
|
|
136
|
+
workstreamId: normalizeSyncNullableId(source.workstreamId) || '',
|
|
137
|
+
referenceNumber: source.referenceNumber === undefined || source.referenceNumber === null ? '' : String(source.referenceNumber),
|
|
138
|
+
comments: normalizeSyncComments(source.comments),
|
|
139
|
+
attachments: normalizeSyncAttachments(source.attachments),
|
|
140
|
+
checklistItems: normalizeConflictChecklistItems(source.checklistItems),
|
|
141
|
+
isArchived: archivedValue ? '1' : '0'
|
|
142
|
+
});
|
|
143
|
+
}
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
+
import { normalizeSyncNullableString, normalizeSyncOptionalString, } from './syncFieldSemantics.js';
|
|
1
2
|
function toOptionalString(value) {
|
|
2
|
-
|
|
3
|
-
return undefined;
|
|
4
|
-
const normalized = String(value).trim();
|
|
5
|
-
return normalized.length > 0 ? normalized : undefined;
|
|
3
|
+
return normalizeSyncOptionalString(value);
|
|
6
4
|
}
|
|
7
5
|
function toNullableString(value) {
|
|
8
6
|
if (value === undefined)
|
|
9
7
|
return undefined;
|
|
10
|
-
|
|
11
|
-
return null;
|
|
12
|
-
const normalized = String(value).trim();
|
|
13
|
-
return normalized.length > 0 ? normalized : null;
|
|
8
|
+
return normalizeSyncNullableString(value);
|
|
14
9
|
}
|
|
15
10
|
function toOptionalBoolean(value) {
|
|
16
11
|
return typeof value === 'boolean' ? value : undefined;
|