@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function
|
|
1
|
+
function normalizeEntityEventActor(deps, actorRef, workspaceId) {
|
|
2
2
|
const actorProfile = deps.resolveWorkspaceActor(workspaceId, actorRef);
|
|
3
3
|
const actor = String(actorRef || '').trim() || 'system';
|
|
4
4
|
if (actor === 'system') {
|
|
@@ -10,25 +10,48 @@ function normalizeTaskEventActor(deps, actorRef, workspaceId) {
|
|
|
10
10
|
actorProfile
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
function
|
|
13
|
+
function normalizeEntityEventDetails(details) {
|
|
14
14
|
if (!details || typeof details !== 'object' || Array.isArray(details))
|
|
15
15
|
return {};
|
|
16
16
|
return details;
|
|
17
17
|
}
|
|
18
|
-
function
|
|
18
|
+
function normalizeEntityType(value) {
|
|
19
|
+
return value === 'initiative' || value === 'workstream' ? value : 'task';
|
|
20
|
+
}
|
|
21
|
+
function mapEntityEventRow(deps, row) {
|
|
19
22
|
const workspaceId = deps.normalizeWorkspaceId(typeof row.workspace_id === 'string' ? row.workspace_id : undefined);
|
|
20
23
|
const actor = String(row.actor || 'system').trim() || 'system';
|
|
24
|
+
const entityType = normalizeEntityType(row.entity_type);
|
|
25
|
+
const entityId = String(row.entity_id || row.task_id || '').trim();
|
|
21
26
|
let details = {};
|
|
22
27
|
try {
|
|
23
|
-
details =
|
|
28
|
+
details = normalizeEntityEventDetails(row.details_json ? JSON.parse(String(row.details_json)) : {});
|
|
24
29
|
}
|
|
25
30
|
catch {
|
|
26
31
|
details = {};
|
|
27
32
|
}
|
|
33
|
+
if (entityType === 'task') {
|
|
34
|
+
return {
|
|
35
|
+
id: String(row.id || '').trim(),
|
|
36
|
+
taskId: entityId,
|
|
37
|
+
workspaceId,
|
|
38
|
+
entityType,
|
|
39
|
+
entityId,
|
|
40
|
+
action: String(row.action || '').trim(),
|
|
41
|
+
actor,
|
|
42
|
+
actorType: row.actor_type === 'ai' || row.actor_type === 'human' || row.actor_type === 'system'
|
|
43
|
+
? row.actor_type
|
|
44
|
+
: 'system',
|
|
45
|
+
createdAt: String(row.created_at || ''),
|
|
46
|
+
details,
|
|
47
|
+
actorProfile: actor === 'system' ? null : deps.resolveWorkspaceActor(workspaceId, actor)
|
|
48
|
+
};
|
|
49
|
+
}
|
|
28
50
|
return {
|
|
29
51
|
id: String(row.id || '').trim(),
|
|
30
|
-
taskId: String(row.task_id || '').trim(),
|
|
31
52
|
workspaceId,
|
|
53
|
+
entityType,
|
|
54
|
+
entityId,
|
|
32
55
|
action: String(row.action || '').trim(),
|
|
33
56
|
actor,
|
|
34
57
|
actorType: row.actor_type === 'ai' || row.actor_type === 'human' || row.actor_type === 'system'
|
|
@@ -39,16 +62,124 @@ function mapTaskEventRow(deps, row) {
|
|
|
39
62
|
actorProfile: actor === 'system' ? null : deps.resolveWorkspaceActor(workspaceId, actor)
|
|
40
63
|
};
|
|
41
64
|
}
|
|
65
|
+
function mapEntityEventSyncRow(deps, row) {
|
|
66
|
+
const workspaceId = deps.normalizeWorkspaceId(typeof row.workspace_id === 'string' ? row.workspace_id : undefined);
|
|
67
|
+
const entityType = normalizeEntityType(row.entity_type);
|
|
68
|
+
const entityId = String(row.entity_id || row.task_id || '').trim();
|
|
69
|
+
let details = {};
|
|
70
|
+
try {
|
|
71
|
+
details = normalizeEntityEventDetails(row.details_json ? JSON.parse(String(row.details_json)) : {});
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
details = {};
|
|
75
|
+
}
|
|
76
|
+
if (entityType === 'task') {
|
|
77
|
+
return {
|
|
78
|
+
id: String(row.id || '').trim(),
|
|
79
|
+
taskId: entityId,
|
|
80
|
+
workspaceId,
|
|
81
|
+
entityType: 'task',
|
|
82
|
+
entityId,
|
|
83
|
+
action: String(row.action || '').trim(),
|
|
84
|
+
actor: String(row.actor || 'system').trim() || 'system',
|
|
85
|
+
actorType: row.actor_type === 'ai' || row.actor_type === 'human' || row.actor_type === 'system'
|
|
86
|
+
? row.actor_type
|
|
87
|
+
: 'system',
|
|
88
|
+
createdAt: String(row.created_at || ''),
|
|
89
|
+
details,
|
|
90
|
+
// Sync only needs the stable event payload. Avoid actor hydration so
|
|
91
|
+
// large workspace snapshots don't blow up the Postgres worker buffer.
|
|
92
|
+
actorProfile: null
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
id: String(row.id || '').trim(),
|
|
97
|
+
workspaceId,
|
|
98
|
+
entityType,
|
|
99
|
+
entityId,
|
|
100
|
+
action: String(row.action || '').trim(),
|
|
101
|
+
actor: String(row.actor || 'system').trim() || 'system',
|
|
102
|
+
actorType: row.actor_type === 'ai' || row.actor_type === 'human' || row.actor_type === 'system'
|
|
103
|
+
? row.actor_type
|
|
104
|
+
: 'system',
|
|
105
|
+
createdAt: String(row.created_at || ''),
|
|
106
|
+
details,
|
|
107
|
+
// Sync only needs the stable event payload. Avoid actor hydration so
|
|
108
|
+
// large workspace snapshots don't blow up the Postgres worker buffer.
|
|
109
|
+
actorProfile: null
|
|
110
|
+
};
|
|
111
|
+
}
|
|
42
112
|
export function listWorkspaceTaskEventsService(deps, workspaceId) {
|
|
43
113
|
const normalizedWorkspaceId = deps.normalizeWorkspaceId(workspaceId);
|
|
44
114
|
const rows = deps.db.prepare(`
|
|
45
|
-
SELECT id,
|
|
46
|
-
FROM
|
|
115
|
+
SELECT id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
116
|
+
FROM entity_events
|
|
117
|
+
WHERE tenant_id = ?
|
|
118
|
+
AND workspace_id = ?
|
|
119
|
+
AND entity_type = 'task'
|
|
120
|
+
ORDER BY created_at ASC, id ASC
|
|
121
|
+
`).all(deps.tenantId, normalizedWorkspaceId);
|
|
122
|
+
return rows.map((row) => mapEntityEventRow(deps, row));
|
|
123
|
+
}
|
|
124
|
+
export function listWorkspaceEntityEventsService(deps, workspaceId) {
|
|
125
|
+
const normalizedWorkspaceId = deps.normalizeWorkspaceId(workspaceId);
|
|
126
|
+
const rows = deps.db.prepare(`
|
|
127
|
+
SELECT id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
128
|
+
FROM entity_events
|
|
129
|
+
WHERE tenant_id = ?
|
|
130
|
+
AND workspace_id = ?
|
|
131
|
+
ORDER BY created_at ASC, id ASC
|
|
132
|
+
`).all(deps.tenantId, normalizedWorkspaceId);
|
|
133
|
+
return rows.map((row) => mapEntityEventRow(deps, row));
|
|
134
|
+
}
|
|
135
|
+
export function listWorkspaceEntityEventsForSyncService(deps, workspaceId) {
|
|
136
|
+
const normalizedWorkspaceId = deps.normalizeWorkspaceId(workspaceId);
|
|
137
|
+
const rows = deps.db.prepare(`
|
|
138
|
+
SELECT id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
139
|
+
FROM entity_events
|
|
47
140
|
WHERE tenant_id = ?
|
|
48
141
|
AND workspace_id = ?
|
|
49
142
|
ORDER BY created_at ASC, id ASC
|
|
50
143
|
`).all(deps.tenantId, normalizedWorkspaceId);
|
|
51
|
-
return rows.map((row) =>
|
|
144
|
+
return rows.map((row) => mapEntityEventSyncRow(deps, row));
|
|
145
|
+
}
|
|
146
|
+
export function listWorkspaceTaskEventsForSyncService(deps, workspaceId) {
|
|
147
|
+
const normalizedWorkspaceId = deps.normalizeWorkspaceId(workspaceId);
|
|
148
|
+
const rows = deps.db.prepare(`
|
|
149
|
+
SELECT id, entity_id AS task_id, workspace_id, action, actor, actor_type, details_json, created_at
|
|
150
|
+
FROM entity_events
|
|
151
|
+
WHERE tenant_id = ?
|
|
152
|
+
AND workspace_id = ?
|
|
153
|
+
AND entity_type = 'task'
|
|
154
|
+
ORDER BY created_at ASC, id ASC
|
|
155
|
+
`).all(deps.tenantId, normalizedWorkspaceId);
|
|
156
|
+
return rows.map((row) => mapEntityEventSyncRow(deps, { ...row, entity_type: 'task', entity_id: row.task_id }));
|
|
157
|
+
}
|
|
158
|
+
export function getTaskEventForSyncService(deps, input) {
|
|
159
|
+
const normalizedWorkspaceId = deps.normalizeWorkspaceId(input.workspaceId);
|
|
160
|
+
const row = deps.db.prepare(`
|
|
161
|
+
SELECT id, entity_id AS task_id, workspace_id, action, actor, actor_type, details_json, created_at
|
|
162
|
+
FROM entity_events
|
|
163
|
+
WHERE tenant_id = ?
|
|
164
|
+
AND workspace_id = ?
|
|
165
|
+
AND entity_type = 'task'
|
|
166
|
+
AND entity_id = ?
|
|
167
|
+
AND id = ?
|
|
168
|
+
LIMIT 1
|
|
169
|
+
`).get(deps.tenantId, normalizedWorkspaceId, String(input.taskId || '').trim(), String(input.eventId || '').trim());
|
|
170
|
+
return row ? mapEntityEventSyncRow(deps, { ...row, entity_type: 'task', entity_id: row.task_id }) : null;
|
|
171
|
+
}
|
|
172
|
+
export function getEntityEventForSyncService(deps, input) {
|
|
173
|
+
const normalizedWorkspaceId = deps.normalizeWorkspaceId(input.workspaceId);
|
|
174
|
+
const row = deps.db.prepare(`
|
|
175
|
+
SELECT id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
176
|
+
FROM entity_events
|
|
177
|
+
WHERE tenant_id = ?
|
|
178
|
+
AND workspace_id = ?
|
|
179
|
+
AND id = ?
|
|
180
|
+
LIMIT 1
|
|
181
|
+
`).get(deps.tenantId, normalizedWorkspaceId, String(input.eventId || '').trim());
|
|
182
|
+
return row ? mapEntityEventSyncRow(deps, row) : null;
|
|
52
183
|
}
|
|
53
184
|
export function replaceTaskCommentsService(deps, taskId, workspaceId, comments) {
|
|
54
185
|
const normalizedWorkspaceId = deps.normalizeWorkspaceId(workspaceId);
|
|
@@ -73,19 +204,24 @@ export function replaceTaskCommentsService(deps, taskId, workspaceId, comments)
|
|
|
73
204
|
});
|
|
74
205
|
}
|
|
75
206
|
}
|
|
76
|
-
export function
|
|
207
|
+
export function listEntityEventsInternalService(deps, entityType, entityId, workspaceId) {
|
|
77
208
|
const rows = deps.db.prepare(`
|
|
78
|
-
SELECT id,
|
|
79
|
-
FROM
|
|
209
|
+
SELECT id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
210
|
+
FROM entity_events
|
|
80
211
|
WHERE tenant_id = ?
|
|
81
212
|
AND workspace_id = ?
|
|
82
|
-
AND
|
|
213
|
+
AND entity_type = ?
|
|
214
|
+
AND entity_id = ?
|
|
83
215
|
ORDER BY created_at ASC, id ASC
|
|
84
|
-
`).all(deps.tenantId, workspaceId,
|
|
85
|
-
return rows.map((row) =>
|
|
216
|
+
`).all(deps.tenantId, workspaceId, entityType, entityId);
|
|
217
|
+
return rows.map((row) => mapEntityEventRow(deps, row));
|
|
86
218
|
}
|
|
87
|
-
export function
|
|
88
|
-
|
|
219
|
+
export function listTaskEventsInternalService(deps, taskId, workspaceId) {
|
|
220
|
+
return listEntityEventsInternalService(deps, 'task', taskId, workspaceId);
|
|
221
|
+
}
|
|
222
|
+
export function buildEntityActivityService(comments, entityEvents, options) {
|
|
223
|
+
const hiddenActions = new Set(options?.hiddenActions || []);
|
|
224
|
+
const visibleEvents = entityEvents.filter((event) => !hiddenActions.has(event.action));
|
|
89
225
|
return [
|
|
90
226
|
...comments.map((comment) => ({
|
|
91
227
|
id: `comment:${comment.id}`,
|
|
@@ -93,7 +229,7 @@ export function buildTaskActivityService(comments, taskEvents) {
|
|
|
93
229
|
timestamp: comment.timestamp,
|
|
94
230
|
comment
|
|
95
231
|
})),
|
|
96
|
-
...
|
|
232
|
+
...visibleEvents.map((event) => ({
|
|
97
233
|
id: `event:${event.id}`,
|
|
98
234
|
type: 'event',
|
|
99
235
|
timestamp: event.createdAt,
|
|
@@ -108,68 +244,113 @@ export function buildTaskActivityService(comments, taskEvents) {
|
|
|
108
244
|
return String(left.id || '').localeCompare(String(right.id || ''));
|
|
109
245
|
});
|
|
110
246
|
}
|
|
111
|
-
export function
|
|
247
|
+
export function buildTaskActivityService(comments, taskEvents) {
|
|
248
|
+
return buildEntityActivityService(comments, taskEvents, {
|
|
249
|
+
hiddenActions: ['task-comment-added']
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
export function addEntityEventService(deps, input) {
|
|
112
253
|
const action = String(input.action || '').trim();
|
|
113
254
|
if (!action)
|
|
114
255
|
return;
|
|
115
|
-
const
|
|
116
|
-
if (!
|
|
256
|
+
const entityId = String(input.entityId || '').trim();
|
|
257
|
+
if (!entityId)
|
|
117
258
|
return;
|
|
259
|
+
const entityType = normalizeEntityType(input.entityType);
|
|
118
260
|
const workspaceId = deps.normalizeWorkspaceId(input.workspaceId);
|
|
119
261
|
const createdAt = String(input.createdAt || '').trim() || new Date().toISOString();
|
|
120
|
-
const { actor, actorType } =
|
|
262
|
+
const { actor, actorType } = normalizeEntityEventActor(deps, input.actor, workspaceId);
|
|
121
263
|
deps.db.prepare(`
|
|
122
|
-
INSERT INTO
|
|
123
|
-
id, tenant_id, workspace_id,
|
|
124
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
125
|
-
`).run(deps.generateEntityId('
|
|
264
|
+
INSERT INTO entity_events (
|
|
265
|
+
id, tenant_id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
266
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
267
|
+
`).run(deps.generateEntityId('entity-event'), deps.tenantId, workspaceId, entityType, entityId, action, actor, actorType, JSON.stringify(normalizeEntityEventDetails(input.details)), createdAt);
|
|
126
268
|
}
|
|
127
|
-
export function
|
|
269
|
+
export function addTaskEventService(deps, input) {
|
|
270
|
+
addEntityEventService(deps, {
|
|
271
|
+
entityType: 'task',
|
|
272
|
+
entityId: input.taskId,
|
|
273
|
+
workspaceId: input.workspaceId,
|
|
274
|
+
action: input.action,
|
|
275
|
+
actor: input.actor,
|
|
276
|
+
createdAt: input.createdAt,
|
|
277
|
+
details: input.details,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
export function replaceEntityEventsService(deps, entityType, entityId, workspaceId, entityEvents) {
|
|
128
281
|
const normalizedWorkspaceId = deps.normalizeWorkspaceId(workspaceId);
|
|
129
|
-
deps.db.prepare('DELETE FROM
|
|
130
|
-
.run(deps.tenantId, normalizedWorkspaceId,
|
|
131
|
-
if (
|
|
282
|
+
deps.db.prepare('DELETE FROM entity_events WHERE tenant_id = ? AND workspace_id = ? AND entity_type = ? AND entity_id = ?')
|
|
283
|
+
.run(deps.tenantId, normalizedWorkspaceId, entityType, entityId);
|
|
284
|
+
if (entityEvents.length === 0)
|
|
132
285
|
return;
|
|
133
|
-
const
|
|
134
|
-
INSERT INTO
|
|
135
|
-
id, tenant_id, workspace_id,
|
|
136
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
286
|
+
const insertEntityEvent = deps.db.prepare(`
|
|
287
|
+
INSERT INTO entity_events (
|
|
288
|
+
id, tenant_id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
289
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
137
290
|
`);
|
|
138
|
-
for (const event of
|
|
139
|
-
|
|
291
|
+
for (const event of entityEvents) {
|
|
292
|
+
insertEntityEvent.run(event.id, deps.tenantId, normalizedWorkspaceId, event.entityType, event.entityId, event.action, event.actor, event.actorType, JSON.stringify(normalizeEntityEventDetails(event.details)), event.createdAt);
|
|
140
293
|
}
|
|
141
294
|
}
|
|
142
|
-
export function
|
|
295
|
+
export function replaceTaskEventsService(deps, taskId, workspaceId, taskEvents) {
|
|
296
|
+
replaceEntityEventsService(deps, 'task', taskId, workspaceId, taskEvents.map((event) => ({
|
|
297
|
+
...event,
|
|
298
|
+
entityType: 'task',
|
|
299
|
+
entityId: String(event.entityId || event.taskId || taskId).trim(),
|
|
300
|
+
taskId: String(event.taskId || taskId).trim(),
|
|
301
|
+
})));
|
|
302
|
+
}
|
|
303
|
+
export function upsertEntityEventForSyncService(deps, event) {
|
|
143
304
|
const workspaceId = deps.normalizeWorkspaceId(event.workspaceId);
|
|
305
|
+
const entityType = normalizeEntityType(event.entityType);
|
|
144
306
|
const normalizedEvent = {
|
|
145
307
|
id: String(event.id || '').trim(),
|
|
146
|
-
taskId: String(event.taskId || '').trim(),
|
|
147
308
|
workspaceId,
|
|
309
|
+
entityType,
|
|
310
|
+
entityId: String(event.entityId || (entityType === 'task' ? event.taskId : '') || '').trim(),
|
|
148
311
|
action: String(event.action || '').trim(),
|
|
149
312
|
actor: String(event.actor || 'system').trim() || 'system',
|
|
150
313
|
actorType: event.actorType === 'ai' || event.actorType === 'human' || event.actorType === 'system'
|
|
151
314
|
? event.actorType
|
|
152
315
|
: 'system',
|
|
153
316
|
createdAt: String(event.createdAt || '').trim() || new Date().toISOString(),
|
|
154
|
-
details:
|
|
317
|
+
details: normalizeEntityEventDetails(event.details)
|
|
155
318
|
};
|
|
156
319
|
deps.db.prepare(`
|
|
157
|
-
INSERT INTO
|
|
158
|
-
id, tenant_id, workspace_id,
|
|
159
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
320
|
+
INSERT INTO entity_events (
|
|
321
|
+
id, tenant_id, workspace_id, entity_type, entity_id, action, actor, actor_type, details_json, created_at
|
|
322
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
160
323
|
ON CONFLICT (id) DO UPDATE SET
|
|
161
324
|
workspace_id = excluded.workspace_id,
|
|
162
|
-
|
|
325
|
+
entity_type = excluded.entity_type,
|
|
326
|
+
entity_id = excluded.entity_id,
|
|
163
327
|
action = excluded.action,
|
|
164
328
|
actor = excluded.actor,
|
|
165
329
|
actor_type = excluded.actor_type,
|
|
166
330
|
details_json = excluded.details_json,
|
|
167
331
|
created_at = excluded.created_at
|
|
168
|
-
`).run(normalizedEvent.id, deps.tenantId, workspaceId, normalizedEvent.
|
|
332
|
+
`).run(normalizedEvent.id, deps.tenantId, workspaceId, normalizedEvent.entityType, normalizedEvent.entityId, normalizedEvent.action, normalizedEvent.actor, normalizedEvent.actorType, JSON.stringify(normalizedEvent.details), normalizedEvent.createdAt);
|
|
333
|
+
const actorProfile = normalizedEvent.actor === 'system'
|
|
334
|
+
? null
|
|
335
|
+
: deps.resolveWorkspaceActor(workspaceId, normalizedEvent.actor);
|
|
336
|
+
if (normalizedEvent.entityType === 'task') {
|
|
337
|
+
return {
|
|
338
|
+
...normalizedEvent,
|
|
339
|
+
entityType: 'task',
|
|
340
|
+
taskId: normalizedEvent.entityId,
|
|
341
|
+
actorProfile,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
169
344
|
return {
|
|
170
345
|
...normalizedEvent,
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
: deps.resolveWorkspaceActor(workspaceId, normalizedEvent.actor)
|
|
346
|
+
entityType: normalizedEvent.entityType,
|
|
347
|
+
actorProfile,
|
|
174
348
|
};
|
|
175
349
|
}
|
|
350
|
+
export function upsertTaskEventForSyncService(deps, event) {
|
|
351
|
+
return upsertEntityEventForSyncService(deps, {
|
|
352
|
+
...event,
|
|
353
|
+
entityType: 'task',
|
|
354
|
+
entityId: event.taskId,
|
|
355
|
+
});
|
|
356
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { TaskforceCore } from './Taskforce';
|
|
6
|
+
function makeCore() {
|
|
7
|
+
const projectRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'taskforce-activity-sync-'));
|
|
8
|
+
const core = new TaskforceCore({
|
|
9
|
+
projectRoot,
|
|
10
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
core,
|
|
14
|
+
cleanup: () => {
|
|
15
|
+
core.close();
|
|
16
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
describe('TaskforceCore sync activity reads', () => {
|
|
21
|
+
it('lists workspace entity events for sync without hydrating actor profiles', () => {
|
|
22
|
+
const { core, cleanup } = makeCore();
|
|
23
|
+
try {
|
|
24
|
+
const task = core.createTask({ title: 'Sync task event seed', createdBy: 'user-1' }, {
|
|
25
|
+
workspaceId: 'workspace-a',
|
|
26
|
+
actorRef: 'user-1'
|
|
27
|
+
});
|
|
28
|
+
const initiative = core.createInitiative({ title: 'Initiative seed' }, 'workspace-a', {
|
|
29
|
+
actorRef: 'user-1'
|
|
30
|
+
});
|
|
31
|
+
core.recordTaskEvent({
|
|
32
|
+
taskId: task.id,
|
|
33
|
+
workspaceId: 'workspace-a',
|
|
34
|
+
action: 'task-updated',
|
|
35
|
+
actor: 'user-1',
|
|
36
|
+
createdAt: '2026-04-28T10:00:00.000Z',
|
|
37
|
+
details: { changes: { assignee: { from: 'user-1', to: 'ai-1' } } }
|
|
38
|
+
});
|
|
39
|
+
core.updateInitiative(initiative.id, { description: 'Updated initiative body' }, 'workspace-a', {
|
|
40
|
+
actorRef: 'user-1'
|
|
41
|
+
});
|
|
42
|
+
vi.spyOn(core, 'resolveWorkspaceActor').mockImplementation(() => {
|
|
43
|
+
throw new Error('sync snapshot should not hydrate actor profiles');
|
|
44
|
+
});
|
|
45
|
+
const events = core.listEntityEventsForSync({ workspaceId: 'workspace-a' });
|
|
46
|
+
expect(events.map((event) => event.action)).toEqual(expect.arrayContaining([
|
|
47
|
+
'task-created',
|
|
48
|
+
'task-updated',
|
|
49
|
+
'initiative-created',
|
|
50
|
+
'initiative-updated',
|
|
51
|
+
]));
|
|
52
|
+
expect(events.every((event) => event.actorProfile === null)).toBe(true);
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
cleanup();
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
it('looks up one entity event for sync without hydrating actor profiles', () => {
|
|
59
|
+
const { core, cleanup } = makeCore();
|
|
60
|
+
try {
|
|
61
|
+
const workstream = core.createWorkstream({ title: 'Single sync event seed' }, 'workspace-a', {
|
|
62
|
+
actorRef: 'user-1'
|
|
63
|
+
});
|
|
64
|
+
core.updateWorkstream(workstream.id, {
|
|
65
|
+
description: 'Workstream moved forward'
|
|
66
|
+
}, 'workspace-a', {
|
|
67
|
+
actorRef: 'user-1'
|
|
68
|
+
});
|
|
69
|
+
const target = core.getWorkstream(workstream.id, 'workspace-a')?.entityEvents?.find((event) => event.action === 'workstream-updated');
|
|
70
|
+
expect(target).toBeTruthy();
|
|
71
|
+
vi.spyOn(core, 'resolveWorkspaceActor').mockImplementation(() => {
|
|
72
|
+
throw new Error('single sync lookup should not hydrate actor profiles');
|
|
73
|
+
});
|
|
74
|
+
const syncEvent = core.getEntityEventForSync({
|
|
75
|
+
workspaceId: 'workspace-a',
|
|
76
|
+
eventId: target.id,
|
|
77
|
+
});
|
|
78
|
+
expect(syncEvent).toEqual(expect.objectContaining({
|
|
79
|
+
id: target.id,
|
|
80
|
+
entityType: 'workstream',
|
|
81
|
+
entityId: workstream.id,
|
|
82
|
+
action: 'workstream-updated',
|
|
83
|
+
actorProfile: null,
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
cleanup();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -91,6 +91,56 @@ describe('TaskforceCore canonical task attachments', () => {
|
|
|
91
91
|
})
|
|
92
92
|
]);
|
|
93
93
|
});
|
|
94
|
+
it('starts cleanly with legacy workspace asset links that predate target_type', () => {
|
|
95
|
+
const projectRoot = createProjectRoot();
|
|
96
|
+
const core = new TaskforceCore({ projectRoot, storagePath: '.taskforce' });
|
|
97
|
+
const created = core.createTask({
|
|
98
|
+
title: 'Legacy attachment startup task'
|
|
99
|
+
}, { workspaceId: 'default' });
|
|
100
|
+
const db = core.getDatabaseAdapter();
|
|
101
|
+
const now = new Date().toISOString();
|
|
102
|
+
const storageKey = 'workspaces/default/assets/documents/asset-legacy-doc-1-spec.md';
|
|
103
|
+
db.exec(`
|
|
104
|
+
DROP TABLE IF EXISTS workspace_asset_links;
|
|
105
|
+
CREATE TABLE workspace_asset_links (
|
|
106
|
+
tenant_id TEXT NOT NULL DEFAULT 'default',
|
|
107
|
+
workspace_id TEXT NOT NULL,
|
|
108
|
+
asset_id TEXT NOT NULL,
|
|
109
|
+
task_id TEXT NOT NULL,
|
|
110
|
+
role TEXT NOT NULL,
|
|
111
|
+
display_name TEXT,
|
|
112
|
+
sort_order INTEGER,
|
|
113
|
+
created_at TEXT NOT NULL,
|
|
114
|
+
updated_at TEXT NOT NULL,
|
|
115
|
+
deleted_at TEXT,
|
|
116
|
+
PRIMARY KEY (tenant_id, workspace_id, asset_id, task_id, role)
|
|
117
|
+
);
|
|
118
|
+
`);
|
|
119
|
+
db.prepare(`
|
|
120
|
+
INSERT INTO workspace_assets (
|
|
121
|
+
asset_id, tenant_id, workspace_id, kind, logical_name, original_filename, mime_type,
|
|
122
|
+
storage_provider, storage_key, content_sha256, size_bytes, document_id, reference_number, version,
|
|
123
|
+
is_latest, scan_status, created_at, updated_at
|
|
124
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
125
|
+
`).run('asset-legacy-doc-1', 'default', 'default', 'document', 'Legacy Spec', 'spec.md', 'text/markdown', 'r2', storageKey, 'sha-legacy-doc-1', 120, 'doc-legacy-1', 1, 1, 1, 'clean', now, now);
|
|
126
|
+
db.prepare(`
|
|
127
|
+
INSERT INTO workspace_asset_links (
|
|
128
|
+
tenant_id, workspace_id, asset_id, task_id, role, display_name, created_at, updated_at
|
|
129
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
130
|
+
`).run('default', 'default', 'asset-legacy-doc-1', created.id, 'attachment', 'Legacy Spec', now, now);
|
|
131
|
+
core.close();
|
|
132
|
+
const repairedCore = new TaskforceCore({ projectRoot, storagePath: '.taskforce' });
|
|
133
|
+
const tasks = repairedCore.listTasks('default').tasks;
|
|
134
|
+
const task = tasks.find((entry) => entry.id === created.id);
|
|
135
|
+
expect(task?.attachments).toEqual([
|
|
136
|
+
expect.objectContaining({
|
|
137
|
+
path: '/api/taskforce/documents/asset-legacy-doc-1/content',
|
|
138
|
+
fsPath: storageKey,
|
|
139
|
+
caption: 'Legacy Spec',
|
|
140
|
+
assetId: 'asset-legacy-doc-1'
|
|
141
|
+
})
|
|
142
|
+
]);
|
|
143
|
+
});
|
|
94
144
|
it('renders canonical image attachments through the unified context route', () => {
|
|
95
145
|
const projectRoot = createProjectRoot();
|
|
96
146
|
const core = new TaskforceCore({ projectRoot, storagePath: '.taskforce' });
|
|
@@ -246,7 +296,7 @@ describe('TaskforceCore canonical task attachments', () => {
|
|
|
246
296
|
taskId: created.id,
|
|
247
297
|
imageAssetId: 'asset-image-repair',
|
|
248
298
|
includeDeleted: true,
|
|
249
|
-
});
|
|
299
|
+
}).filter((session) => session.taskId === created.id);
|
|
250
300
|
const unattachedSessions = repairedCore.listAnnotatedAttachmentSessions({
|
|
251
301
|
workspaceId: 'default',
|
|
252
302
|
imageAssetId: 'asset-image-repair',
|
|
@@ -183,6 +183,102 @@ describe('TaskforceCore task audit timeline', () => {
|
|
|
183
183
|
cleanup();
|
|
184
184
|
}
|
|
185
185
|
});
|
|
186
|
+
it('records initiative and workstream activity events and exposes them on hydrated planning entities', () => {
|
|
187
|
+
const { core, cleanup } = makeCore();
|
|
188
|
+
try {
|
|
189
|
+
core.createWorkspace({ workspaceId: 'workspace-a', name: 'Workspace A' });
|
|
190
|
+
const initiative = core.createInitiative({ title: 'Planning initiative' }, 'workspace-a', { actorRef: 'user' });
|
|
191
|
+
const nestedInitiative = core.createInitiative({ title: 'Nested initiative' }, 'workspace-a', { actorRef: 'user' });
|
|
192
|
+
const workstream = core.createWorkstream({
|
|
193
|
+
title: 'Planning workstream',
|
|
194
|
+
initiativeId: initiative.id,
|
|
195
|
+
}, 'workspace-a', { actorRef: 'user' });
|
|
196
|
+
const siblingWorkstream = core.createWorkstream({
|
|
197
|
+
title: 'Sibling workstream',
|
|
198
|
+
initiativeId: initiative.id,
|
|
199
|
+
}, 'workspace-a', { actorRef: 'user' });
|
|
200
|
+
core.updateInitiative(initiative.id, {
|
|
201
|
+
description: 'Refined initiative description',
|
|
202
|
+
attachments: [{ path: 'https://example.com/initiative-spec.md', caption: 'initiative spec' }],
|
|
203
|
+
}, 'workspace-a', { actorRef: 'user' });
|
|
204
|
+
core.archiveInitiative(initiative.id, 'workspace-a', { actorRef: 'user' });
|
|
205
|
+
core.unarchiveInitiative(initiative.id, 'workspace-a', { actorRef: 'user' });
|
|
206
|
+
core.updateWorkstream(workstream.id, {
|
|
207
|
+
initiativeId: nestedInitiative.id,
|
|
208
|
+
}, 'workspace-a', { actorRef: 'user' });
|
|
209
|
+
core.archiveWorkstream(workstream.id, 'workspace-a', { actorRef: 'user' });
|
|
210
|
+
core.unarchiveWorkstream(workstream.id, 'workspace-a', { actorRef: 'user' });
|
|
211
|
+
const linkedTask = core.createTask({
|
|
212
|
+
title: 'Linked task',
|
|
213
|
+
createdBy: 'user',
|
|
214
|
+
workstreamId: workstream.id,
|
|
215
|
+
}, { workspaceId: 'workspace-a', actorRef: 'user' });
|
|
216
|
+
core.updateTask(linkedTask.id, { workstreamId: siblingWorkstream.id }, 'workspace-a', { actorRef: 'user' });
|
|
217
|
+
core.updateTask(linkedTask.id, { workstreamId: null }, 'workspace-a', { actorRef: 'user' });
|
|
218
|
+
const hydratedInitiative = core.getInitiative(initiative.id, 'workspace-a');
|
|
219
|
+
const hydratedWorkstream = core.getWorkstream(workstream.id, 'workspace-a');
|
|
220
|
+
const hydratedSiblingWorkstream = core.getWorkstream(siblingWorkstream.id, 'workspace-a');
|
|
221
|
+
const initiativeActions = (hydratedInitiative?.activity || [])
|
|
222
|
+
.filter((item) => item.type === 'event')
|
|
223
|
+
.map((item) => item.event.action);
|
|
224
|
+
const workstreamRelationshipEvent = (hydratedWorkstream?.activity || [])
|
|
225
|
+
.filter((item) => item.type === 'event')
|
|
226
|
+
.map((item) => item.event)
|
|
227
|
+
.find((event) => event.action === 'workstream-relationship-changed');
|
|
228
|
+
const workstreamActions = (hydratedWorkstream?.activity || [])
|
|
229
|
+
.filter((item) => item.type === 'event')
|
|
230
|
+
.map((item) => item.event.action);
|
|
231
|
+
const siblingWorkstreamActions = (hydratedSiblingWorkstream?.activity || [])
|
|
232
|
+
.filter((item) => item.type === 'event')
|
|
233
|
+
.map((item) => item.event.action);
|
|
234
|
+
const workstreamTaskAddedEvent = (hydratedWorkstream?.activity || [])
|
|
235
|
+
.filter((item) => item.type === 'event')
|
|
236
|
+
.map((item) => item.event)
|
|
237
|
+
.find((event) => event.action === 'workstream-task-added');
|
|
238
|
+
const workstreamTaskRemovedEvent = (hydratedWorkstream?.activity || [])
|
|
239
|
+
.filter((item) => item.type === 'event')
|
|
240
|
+
.map((item) => item.event)
|
|
241
|
+
.find((event) => event.action === 'workstream-task-removed');
|
|
242
|
+
expect(initiativeActions).toEqual(expect.arrayContaining([
|
|
243
|
+
'initiative-created',
|
|
244
|
+
'initiative-updated',
|
|
245
|
+
'initiative-archived',
|
|
246
|
+
'initiative-unarchived',
|
|
247
|
+
]));
|
|
248
|
+
expect(workstreamActions).toEqual(expect.arrayContaining([
|
|
249
|
+
'workstream-created',
|
|
250
|
+
'workstream-relationship-changed',
|
|
251
|
+
'workstream-task-added',
|
|
252
|
+
'workstream-task-removed',
|
|
253
|
+
'workstream-archived',
|
|
254
|
+
'workstream-unarchived',
|
|
255
|
+
]));
|
|
256
|
+
expect(siblingWorkstreamActions).toEqual(expect.arrayContaining([
|
|
257
|
+
'workstream-created',
|
|
258
|
+
'workstream-task-added',
|
|
259
|
+
'workstream-task-removed',
|
|
260
|
+
]));
|
|
261
|
+
expect(workstreamRelationshipEvent?.details?.changes?.initiativeId).toEqual({
|
|
262
|
+
from: initiative.id,
|
|
263
|
+
to: nestedInitiative.id,
|
|
264
|
+
});
|
|
265
|
+
expect(workstreamTaskAddedEvent?.details?.taskId).toBe(linkedTask.id);
|
|
266
|
+
expect(workstreamTaskAddedEvent?.details?.taskTitle).toBe('Linked task');
|
|
267
|
+
expect(workstreamTaskAddedEvent?.details?.changes?.workstreamId).toEqual({
|
|
268
|
+
from: null,
|
|
269
|
+
to: workstream.id,
|
|
270
|
+
});
|
|
271
|
+
expect(workstreamTaskRemovedEvent?.details?.changes?.workstreamId).toEqual({
|
|
272
|
+
from: workstream.id,
|
|
273
|
+
to: siblingWorkstream.id,
|
|
274
|
+
});
|
|
275
|
+
expect(hydratedInitiative?.entityEvents?.every((event) => event.entityType === 'initiative')).toBe(true);
|
|
276
|
+
expect(hydratedWorkstream?.entityEvents?.every((event) => event.entityType === 'workstream')).toBe(true);
|
|
277
|
+
}
|
|
278
|
+
finally {
|
|
279
|
+
cleanup();
|
|
280
|
+
}
|
|
281
|
+
});
|
|
186
282
|
it('repairs legacy comments tables so raw submitted authors can be stored', () => {
|
|
187
283
|
const { core, cleanup } = makeCore();
|
|
188
284
|
try {
|