@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
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/ui/index.html
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png" />
|
|
9
9
|
<link rel="apple-touch-icon" href="/taskforce/favicon/apple-touch-icon.png" />
|
|
10
10
|
<title>Taskforce</title>
|
|
11
|
-
<script type="module" crossorigin src="/taskforce/assets/index-
|
|
11
|
+
<script type="module" crossorigin src="/taskforce/assets/index-607WPo_X.js"></script>
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-react-CKJs5o3c.js">
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-icons-
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-icons-B32hGuF2.js">
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-markdown-BUxTU7dS.js">
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-dnd-DRzYolkg.js">
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-router-BbWMxlnO.js">
|
|
17
|
-
<link rel="stylesheet" crossorigin href="/taskforce/assets/index-
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/taskforce/assets/index-CYyodXsg.css">
|
|
18
18
|
</head>
|
|
19
19
|
<body>
|
|
20
20
|
<div id="root"></div>
|
|
Binary file
|
|
Binary file
|
|
@@ -21,6 +21,11 @@ export type AccountProfileSummary = {
|
|
|
21
21
|
canManageWorkspace?: boolean;
|
|
22
22
|
teamPlanMode?: 'personal' | 'team' | 'unknown';
|
|
23
23
|
teamManagementAllowed?: boolean;
|
|
24
|
+
aiProfileSeatUsage?: {
|
|
25
|
+
used: number;
|
|
26
|
+
limit: number | null;
|
|
27
|
+
remaining: number | null;
|
|
28
|
+
} | null;
|
|
24
29
|
};
|
|
25
30
|
export declare function invalidateAccountProfileSummaryCache(rawUrl: string, options?: {
|
|
26
31
|
identityKey?: string | null;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const TASKFORCE_AI_PROFILES_MUTATED_EVENT = "taskforce:ai-profiles-mutated";
|
|
2
|
+
export interface TaskforceAiProfilesMutatedDetail {
|
|
3
|
+
workspaceId?: string | null;
|
|
4
|
+
profileId?: string | null;
|
|
5
|
+
reason?: 'avatar' | 'merge' | 'archive' | 'update';
|
|
6
|
+
}
|
|
7
|
+
export declare function dispatchTaskforceAiProfilesMutated(detail: TaskforceAiProfilesMutatedDetail): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const TASKFORCE_AI_PROFILES_MUTATED_EVENT = 'taskforce:ai-profiles-mutated';
|
|
2
|
+
export function dispatchTaskforceAiProfilesMutated(detail) {
|
|
3
|
+
if (typeof window === 'undefined' || typeof window.dispatchEvent !== 'function')
|
|
4
|
+
return;
|
|
5
|
+
window.dispatchEvent(new CustomEvent(TASKFORCE_AI_PROFILES_MUTATED_EVENT, { detail }));
|
|
6
|
+
}
|
|
@@ -6,6 +6,7 @@ export interface WorkspaceAssigneeCandidate {
|
|
|
6
6
|
userId: string;
|
|
7
7
|
email: string;
|
|
8
8
|
displayName?: string | null;
|
|
9
|
+
avatarUrl?: string | null;
|
|
9
10
|
}
|
|
10
11
|
export interface TaskAssigneeOption {
|
|
11
12
|
value: TaskAssignee;
|
|
@@ -13,6 +14,13 @@ export interface TaskAssigneeOption {
|
|
|
13
14
|
icon: string;
|
|
14
15
|
color: string;
|
|
15
16
|
kind: AssigneeKind;
|
|
17
|
+
avatarUrl?: string | null;
|
|
18
|
+
avatarRevision?: number | null;
|
|
19
|
+
avatarUpdatedAt?: string | null;
|
|
20
|
+
username?: string | null;
|
|
21
|
+
archivedAt?: string | null;
|
|
22
|
+
createdAt?: string | null;
|
|
23
|
+
updatedAt?: string | null;
|
|
16
24
|
}
|
|
17
25
|
export declare function isAgentAssignee(value: unknown): boolean;
|
|
18
26
|
export declare function isUnassignedAssignee(value: unknown): boolean;
|
package/dist/utils/assignees.js
CHANGED
|
@@ -49,6 +49,7 @@ export function createWorkspaceAssigneeOptions(candidates) {
|
|
|
49
49
|
icon: 'User',
|
|
50
50
|
color: '#22c55e',
|
|
51
51
|
kind: 'member',
|
|
52
|
+
avatarUrl: typeof candidate.avatarUrl === 'string' && candidate.avatarUrl.trim().length > 0 ? candidate.avatarUrl.trim() : null,
|
|
52
53
|
});
|
|
53
54
|
}
|
|
54
55
|
return mergeAssigneeOptions(Array.from(deduped.values()));
|
|
@@ -60,7 +61,8 @@ export function mergeAssigneeOptions(options) {
|
|
|
60
61
|
}
|
|
61
62
|
for (const option of Array.isArray(options) ? options : []) {
|
|
62
63
|
const value = String(option?.value || '').trim();
|
|
63
|
-
|
|
64
|
+
const archivedAt = typeof option?.archivedAt === 'string' ? option.archivedAt.trim() : '';
|
|
65
|
+
if (!value || archivedAt || value === TASK_ASSIGNEE_UNASSIGNED || value === TASK_ASSIGNEE_AGENT)
|
|
64
66
|
continue;
|
|
65
67
|
deduped.set(value, {
|
|
66
68
|
value,
|
|
@@ -68,6 +70,13 @@ export function mergeAssigneeOptions(options) {
|
|
|
68
70
|
icon: String(option.icon || (option.kind === 'agent' ? 'Bot' : 'User')),
|
|
69
71
|
color: String(option.color || (option.kind === 'agent' ? '#8b5cf6' : '#22c55e')),
|
|
70
72
|
kind: option.kind === 'agent' ? 'agent' : 'member',
|
|
73
|
+
avatarUrl: typeof option.avatarUrl === 'string' && option.avatarUrl.trim().length > 0 ? option.avatarUrl.trim() : null,
|
|
74
|
+
avatarRevision: Number.isFinite(Number(option.avatarRevision)) ? Math.max(0, Math.floor(Number(option.avatarRevision))) : null,
|
|
75
|
+
avatarUpdatedAt: typeof option.avatarUpdatedAt === 'string' && option.avatarUpdatedAt.trim().length > 0 ? option.avatarUpdatedAt.trim() : null,
|
|
76
|
+
username: typeof option.username === 'string' && option.username.trim().length > 0 ? option.username.trim() : null,
|
|
77
|
+
archivedAt: null,
|
|
78
|
+
createdAt: typeof option.createdAt === 'string' && option.createdAt.trim().length > 0 ? option.createdAt.trim() : null,
|
|
79
|
+
updatedAt: typeof option.updatedAt === 'string' && option.updatedAt.trim().length > 0 ? option.updatedAt.trim() : null,
|
|
71
80
|
});
|
|
72
81
|
}
|
|
73
82
|
const defaults = [TASK_ASSIGNEE_UNASSIGNED];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { mergeAssigneeOptions } from './assignees';
|
|
3
|
+
describe('mergeAssigneeOptions', () => {
|
|
4
|
+
it('keeps one unassigned option and filters archived AI profile options', () => {
|
|
5
|
+
expect(mergeAssigneeOptions([
|
|
6
|
+
{ value: 'unassigned', label: 'Unassigned', icon: 'HelpCircle', color: '#999', kind: 'unassigned' },
|
|
7
|
+
{ value: 'ai-profile-retired', label: 'Retired Agent', icon: 'Bot', color: '#8b5cf6', kind: 'agent', archivedAt: '2026-04-24T15:28:13.577Z' },
|
|
8
|
+
{ value: 'ai-profile-codex', label: 'Codex', icon: 'Bot', color: '#8b5cf6', kind: 'agent' },
|
|
9
|
+
])).toEqual([
|
|
10
|
+
{ value: 'unassigned', label: 'Unassigned', icon: 'HelpCircle', color: 'var(--text-secondary)', kind: 'unassigned' },
|
|
11
|
+
{
|
|
12
|
+
value: 'ai-profile-codex',
|
|
13
|
+
label: 'Codex',
|
|
14
|
+
icon: 'Bot',
|
|
15
|
+
color: '#8b5cf6',
|
|
16
|
+
kind: 'agent',
|
|
17
|
+
avatarUrl: null,
|
|
18
|
+
username: null,
|
|
19
|
+
archivedAt: null,
|
|
20
|
+
createdAt: null,
|
|
21
|
+
updatedAt: null,
|
|
22
|
+
},
|
|
23
|
+
]);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildVersionedAvatarUrl(url: unknown, revision?: unknown, updatedAt?: unknown): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function buildVersionedAvatarUrl(url, revision, updatedAt) {
|
|
2
|
+
const normalizedUrl = typeof url === 'string' ? url.trim() : '';
|
|
3
|
+
if (!normalizedUrl || normalizedUrl.startsWith('data:') || normalizedUrl.startsWith('blob:')) {
|
|
4
|
+
return normalizedUrl;
|
|
5
|
+
}
|
|
6
|
+
const normalizedRevision = Number(revision);
|
|
7
|
+
const version = Number.isFinite(normalizedRevision) && normalizedRevision > 0
|
|
8
|
+
? String(Math.floor(normalizedRevision))
|
|
9
|
+
: (typeof updatedAt === 'string' && updatedAt.trim().length > 0 ? updatedAt.trim() : '');
|
|
10
|
+
if (!version)
|
|
11
|
+
return normalizedUrl;
|
|
12
|
+
const [base, hash = ''] = normalizedUrl.split('#');
|
|
13
|
+
const separator = base.includes('?') ? '&' : '?';
|
|
14
|
+
return `${base}${separator}v=${encodeURIComponent(version)}${hash ? `#${hash}` : ''}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare const RESIZABLE_AVATAR_MIME_TYPES: Set<string>;
|
|
2
|
+
export interface PreparedAvatarUploadFile {
|
|
3
|
+
file: File;
|
|
4
|
+
optimized: boolean;
|
|
5
|
+
exceededLimit: boolean;
|
|
6
|
+
}
|
|
7
|
+
interface LoadedImage {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
source: CanvasImageSource;
|
|
11
|
+
}
|
|
12
|
+
interface RenderToBlobInput {
|
|
13
|
+
image: LoadedImage;
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
type: string;
|
|
17
|
+
quality?: number;
|
|
18
|
+
}
|
|
19
|
+
interface AvatarUploadDeps {
|
|
20
|
+
loadImage: (file: File) => Promise<LoadedImage>;
|
|
21
|
+
renderToBlob: (input: RenderToBlobInput) => Promise<Blob>;
|
|
22
|
+
}
|
|
23
|
+
export declare function prepareAvatarUploadFile(file: File, options?: {
|
|
24
|
+
maxBytes?: number;
|
|
25
|
+
maxDimension?: number;
|
|
26
|
+
}, deps?: AvatarUploadDeps): Promise<PreparedAvatarUploadFile>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const DEFAULT_MAX_DIMENSION = 1024;
|
|
2
|
+
const DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
|
|
3
|
+
const WEBP_QUALITY_STEPS = [0.9, 0.82, 0.74, 0.66, 0.58];
|
|
4
|
+
const JPEG_QUALITY_STEPS = [0.9, 0.82, 0.74, 0.66, 0.58];
|
|
5
|
+
const SCALE_STEPS = [1, 0.85, 0.7, 0.55, 0.4];
|
|
6
|
+
export const RESIZABLE_AVATAR_MIME_TYPES = new Set(['image/png', 'image/jpeg', 'image/webp']);
|
|
7
|
+
function createCanvas(width, height) {
|
|
8
|
+
const canvas = document.createElement('canvas');
|
|
9
|
+
canvas.width = Math.max(1, Math.round(width));
|
|
10
|
+
canvas.height = Math.max(1, Math.round(height));
|
|
11
|
+
return canvas;
|
|
12
|
+
}
|
|
13
|
+
async function defaultLoadImage(file) {
|
|
14
|
+
const objectUrl = URL.createObjectURL(file);
|
|
15
|
+
try {
|
|
16
|
+
const image = await new Promise((resolve, reject) => {
|
|
17
|
+
const element = new Image();
|
|
18
|
+
element.onload = () => resolve(element);
|
|
19
|
+
element.onerror = () => reject(new Error('Failed to load image.'));
|
|
20
|
+
element.src = objectUrl;
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
width: image.naturalWidth || image.width,
|
|
24
|
+
height: image.naturalHeight || image.height,
|
|
25
|
+
source: image
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
URL.revokeObjectURL(objectUrl);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function defaultRenderToBlob(input) {
|
|
33
|
+
const canvas = createCanvas(input.width, input.height);
|
|
34
|
+
const context = canvas.getContext('2d');
|
|
35
|
+
if (!context) {
|
|
36
|
+
throw new Error('Image optimization requires a 2D canvas context.');
|
|
37
|
+
}
|
|
38
|
+
context.drawImage(input.image.source, 0, 0, canvas.width, canvas.height);
|
|
39
|
+
return await new Promise((resolve, reject) => {
|
|
40
|
+
canvas.toBlob((blob) => {
|
|
41
|
+
if (blob) {
|
|
42
|
+
resolve(blob);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
reject(new Error('Failed to encode resized image.'));
|
|
46
|
+
}, input.type, input.quality);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const defaultDeps = {
|
|
50
|
+
loadImage: defaultLoadImage,
|
|
51
|
+
renderToBlob: defaultRenderToBlob
|
|
52
|
+
};
|
|
53
|
+
function extensionForMimeType(type, fallbackName) {
|
|
54
|
+
if (type === 'image/png')
|
|
55
|
+
return '.png';
|
|
56
|
+
if (type === 'image/jpeg')
|
|
57
|
+
return '.jpg';
|
|
58
|
+
if (type === 'image/webp')
|
|
59
|
+
return '.webp';
|
|
60
|
+
const ext = fallbackName.includes('.') ? fallbackName.slice(fallbackName.lastIndexOf('.')) : '';
|
|
61
|
+
return ext || '.img';
|
|
62
|
+
}
|
|
63
|
+
function replaceFileExtension(name, nextExt) {
|
|
64
|
+
const trimmed = String(name || '').trim();
|
|
65
|
+
if (!trimmed)
|
|
66
|
+
return `avatar${nextExt}`;
|
|
67
|
+
const dotIndex = trimmed.lastIndexOf('.');
|
|
68
|
+
if (dotIndex <= 0)
|
|
69
|
+
return `${trimmed}${nextExt}`;
|
|
70
|
+
return `${trimmed.slice(0, dotIndex)}${nextExt}`;
|
|
71
|
+
}
|
|
72
|
+
function buildCandidateMimeTypes(inputType) {
|
|
73
|
+
const preferred = inputType === 'image/jpeg' ? 'image/jpeg' : 'image/webp';
|
|
74
|
+
return Array.from(new Set([preferred, 'image/webp', 'image/jpeg']));
|
|
75
|
+
}
|
|
76
|
+
function buildQualitySteps(type) {
|
|
77
|
+
if (type === 'image/webp')
|
|
78
|
+
return WEBP_QUALITY_STEPS;
|
|
79
|
+
if (type === 'image/jpeg')
|
|
80
|
+
return JPEG_QUALITY_STEPS;
|
|
81
|
+
return [undefined];
|
|
82
|
+
}
|
|
83
|
+
export async function prepareAvatarUploadFile(file, options, deps = defaultDeps) {
|
|
84
|
+
const maxBytes = Number.isFinite(options?.maxBytes) && (options?.maxBytes || 0) > 0
|
|
85
|
+
? Math.floor(options?.maxBytes)
|
|
86
|
+
: DEFAULT_MAX_BYTES;
|
|
87
|
+
const maxDimension = Number.isFinite(options?.maxDimension) && (options?.maxDimension || 0) > 0
|
|
88
|
+
? Math.floor(options?.maxDimension)
|
|
89
|
+
: DEFAULT_MAX_DIMENSION;
|
|
90
|
+
if (file.size <= maxBytes) {
|
|
91
|
+
return { file, optimized: false, exceededLimit: false };
|
|
92
|
+
}
|
|
93
|
+
if (!RESIZABLE_AVATAR_MIME_TYPES.has(file.type)) {
|
|
94
|
+
return { file, optimized: false, exceededLimit: true };
|
|
95
|
+
}
|
|
96
|
+
const image = await deps.loadImage(file);
|
|
97
|
+
const longestEdge = Math.max(image.width, image.height, 1);
|
|
98
|
+
const baseScale = Math.min(1, maxDimension / longestEdge);
|
|
99
|
+
let bestBlob = null;
|
|
100
|
+
for (const scaleStep of SCALE_STEPS) {
|
|
101
|
+
const scale = Math.min(1, baseScale * scaleStep);
|
|
102
|
+
const width = Math.max(1, Math.round(image.width * scale));
|
|
103
|
+
const height = Math.max(1, Math.round(image.height * scale));
|
|
104
|
+
for (const type of buildCandidateMimeTypes(file.type)) {
|
|
105
|
+
for (const quality of buildQualitySteps(type)) {
|
|
106
|
+
const blob = await deps.renderToBlob({ image, width, height, type, quality });
|
|
107
|
+
if (!bestBlob || blob.size < bestBlob.size) {
|
|
108
|
+
bestBlob = blob;
|
|
109
|
+
}
|
|
110
|
+
if (blob.size <= maxBytes) {
|
|
111
|
+
const preparedFile = new File([blob], replaceFileExtension(file.name, extensionForMimeType(blob.type || type, file.name)), {
|
|
112
|
+
type: blob.type || type,
|
|
113
|
+
lastModified: file.lastModified
|
|
114
|
+
});
|
|
115
|
+
return { file: preparedFile, optimized: true, exceededLimit: false };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (!bestBlob) {
|
|
121
|
+
return { file, optimized: false, exceededLimit: true };
|
|
122
|
+
}
|
|
123
|
+
const fallbackFile = new File([bestBlob], replaceFileExtension(file.name, extensionForMimeType(bestBlob.type || file.type, file.name)), {
|
|
124
|
+
type: bestBlob.type || file.type,
|
|
125
|
+
lastModified: file.lastModified
|
|
126
|
+
});
|
|
127
|
+
return {
|
|
128
|
+
file: fallbackFile,
|
|
129
|
+
optimized: fallbackFile.size < file.size,
|
|
130
|
+
exceededLimit: fallbackFile.size > maxBytes
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { prepareAvatarUploadFile } from './avatarUpload';
|
|
3
|
+
describe('prepareAvatarUploadFile', () => {
|
|
4
|
+
it('optimizes oversized jpeg uploads down under the limit', async () => {
|
|
5
|
+
const file = new File([new Uint8Array(8)], 'portrait.jpg', {
|
|
6
|
+
type: 'image/jpeg',
|
|
7
|
+
lastModified: 123
|
|
8
|
+
});
|
|
9
|
+
Object.defineProperty(file, 'size', { configurable: true, value: 8_000_000 });
|
|
10
|
+
let renderCallCount = 0;
|
|
11
|
+
const prepared = await prepareAvatarUploadFile(file, { maxBytes: 5 * 1024 * 1024 }, {
|
|
12
|
+
loadImage: async () => ({
|
|
13
|
+
width: 3200,
|
|
14
|
+
height: 2400,
|
|
15
|
+
source: {}
|
|
16
|
+
}),
|
|
17
|
+
renderToBlob: async ({ type, width }) => {
|
|
18
|
+
renderCallCount += 1;
|
|
19
|
+
const bytes = renderCallCount === 1 ? 6_000_000 : 4_000_000;
|
|
20
|
+
return new Blob([new Uint8Array(bytes)], { type: type || (width < 3200 ? 'image/webp' : 'image/jpeg') });
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
expect(prepared.optimized).toBe(true);
|
|
24
|
+
expect(prepared.exceededLimit).toBe(false);
|
|
25
|
+
expect(prepared.file.size).toBe(4_000_000);
|
|
26
|
+
expect(['image/jpeg', 'image/webp']).toContain(prepared.file.type);
|
|
27
|
+
expect(prepared.file.name).toMatch(/^portrait\.(jpg|webp)$/);
|
|
28
|
+
});
|
|
29
|
+
it('keeps oversized gif uploads rejected because they are not resized', async () => {
|
|
30
|
+
const file = new File([new Uint8Array(8)], 'animated.gif', {
|
|
31
|
+
type: 'image/gif',
|
|
32
|
+
lastModified: 123
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(file, 'size', { configurable: true, value: 8_000_000 });
|
|
35
|
+
const prepared = await prepareAvatarUploadFile(file, { maxBytes: 5 * 1024 * 1024 });
|
|
36
|
+
expect(prepared.optimized).toBe(false);
|
|
37
|
+
expect(prepared.exceededLimit).toBe(true);
|
|
38
|
+
expect(prepared.file).toBe(file);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function buildBootstrapTraceId(input: {
|
|
2
|
+
workspaceId?: string | null;
|
|
3
|
+
epoch?: number | null;
|
|
4
|
+
seed?: string | number | null;
|
|
5
|
+
phase?: string | null;
|
|
6
|
+
}): string;
|
|
7
|
+
export declare function withBootstrapTraceHeader(init: RequestInit | undefined, traceId: string): RequestInit | undefined;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function buildBootstrapTraceId(input) {
|
|
2
|
+
const workspaceId = String(input.workspaceId || 'default')
|
|
3
|
+
.trim()
|
|
4
|
+
.replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
5
|
+
.replace(/^-+|-+$/g, '')
|
|
6
|
+
|| 'default';
|
|
7
|
+
const epoch = Number.isFinite(Number(input.epoch)) ? Math.max(0, Math.floor(Number(input.epoch))) : 0;
|
|
8
|
+
const seed = String(input.seed || 'session')
|
|
9
|
+
.trim()
|
|
10
|
+
.replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
11
|
+
.replace(/^-+|-+$/g, '')
|
|
12
|
+
|| 'session';
|
|
13
|
+
const phase = String(input.phase || 'bootstrap')
|
|
14
|
+
.trim()
|
|
15
|
+
.replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
16
|
+
.replace(/^-+|-+$/g, '')
|
|
17
|
+
|| 'bootstrap';
|
|
18
|
+
return `tfb-${seed}-${workspaceId}-e${epoch}-${phase}`;
|
|
19
|
+
}
|
|
20
|
+
export function withBootstrapTraceHeader(init, traceId) {
|
|
21
|
+
const normalizedTraceId = String(traceId || '').trim();
|
|
22
|
+
if (!normalizedTraceId)
|
|
23
|
+
return init;
|
|
24
|
+
const headers = new Headers(init?.headers || undefined);
|
|
25
|
+
if (!headers.has('x-taskforce-bootstrap-trace-id')) {
|
|
26
|
+
headers.set('x-taskforce-bootstrap-trace-id', normalizedTraceId);
|
|
27
|
+
}
|
|
28
|
+
return { ...(init || {}), headers };
|
|
29
|
+
}
|
|
@@ -26,6 +26,9 @@ function resolveTrialMessage(summary) {
|
|
|
26
26
|
if (trialEnd) {
|
|
27
27
|
const formatted = new Date(trialEnd);
|
|
28
28
|
if (!Number.isNaN(formatted.getTime())) {
|
|
29
|
+
if (formatted.getTime() <= Date.now()) {
|
|
30
|
+
return 'Your trial end date has passed. Billing status is updating.';
|
|
31
|
+
}
|
|
29
32
|
return `Your trial is active through ${formatted.toLocaleString()}.`;
|
|
30
33
|
}
|
|
31
34
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export declare const TASKFORCE_CONTEXT_ASSETS_MUTATED_EVENT = "taskforce:context-assets-mutated";
|
|
2
2
|
export interface TaskforceContextAssetsMutatedDetail {
|
|
3
3
|
workspaceId?: string | null;
|
|
4
|
+
ownerType?: 'task' | 'initiative' | 'workstream';
|
|
5
|
+
ownerId?: string | null;
|
|
4
6
|
taskId?: string | null;
|
|
5
7
|
reason?: 'upload' | 'delete' | 'update';
|
|
6
8
|
}
|
|
@@ -2,11 +2,13 @@ export interface OpenMarkdownEditorDetail {
|
|
|
2
2
|
path: string;
|
|
3
3
|
fsPath: string;
|
|
4
4
|
assetId?: string;
|
|
5
|
+
taskId?: string | null;
|
|
5
6
|
}
|
|
6
7
|
type MarkdownOpenTarget = string | {
|
|
7
8
|
path: string;
|
|
8
9
|
fsPath?: string;
|
|
9
|
-
assetId?: string;
|
|
10
|
+
assetId?: string | null;
|
|
11
|
+
taskId?: string | null;
|
|
10
12
|
caption?: string;
|
|
11
13
|
displayName?: string;
|
|
12
14
|
originalFilename?: string;
|
|
@@ -77,7 +77,8 @@ export function dispatchOpenMarkdownDocument(target, fsPath) {
|
|
|
77
77
|
detail: {
|
|
78
78
|
path: sourcePath,
|
|
79
79
|
fsPath: resolvedFsPath,
|
|
80
|
-
...(assetId ? { assetId } : {})
|
|
80
|
+
...(assetId ? { assetId } : {}),
|
|
81
|
+
...((typeof target !== 'string' && target.taskId) ? { taskId: target.taskId } : {})
|
|
81
82
|
},
|
|
82
83
|
cancelable: true
|
|
83
84
|
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const MAX_SYNC_EVENT_DETAIL_DEPTH = 4;
|
|
2
|
+
const MAX_SYNC_EVENT_DETAIL_ENTRIES = 100;
|
|
3
|
+
function normalizeSyncEventDetailValue(value, depth, seen) {
|
|
4
|
+
if (value === null)
|
|
5
|
+
return null;
|
|
6
|
+
if (typeof value === 'string' || typeof value === 'boolean')
|
|
7
|
+
return value;
|
|
8
|
+
if (typeof value === 'number')
|
|
9
|
+
return Number.isFinite(value) ? value : String(value);
|
|
10
|
+
if (typeof value === 'bigint')
|
|
11
|
+
return value.toString();
|
|
12
|
+
if (value instanceof Date)
|
|
13
|
+
return value.toISOString();
|
|
14
|
+
if (depth >= MAX_SYNC_EVENT_DETAIL_DEPTH)
|
|
15
|
+
return '[MaxDepth]';
|
|
16
|
+
if (typeof value === 'function' || typeof value === 'symbol' || typeof value === 'undefined') {
|
|
17
|
+
return String(value);
|
|
18
|
+
}
|
|
19
|
+
if (Array.isArray(value)) {
|
|
20
|
+
return value
|
|
21
|
+
.slice(0, MAX_SYNC_EVENT_DETAIL_ENTRIES)
|
|
22
|
+
.map((entry) => normalizeSyncEventDetailValue(entry, depth + 1, seen));
|
|
23
|
+
}
|
|
24
|
+
if (value instanceof Set) {
|
|
25
|
+
return Array.from(value.values())
|
|
26
|
+
.slice(0, MAX_SYNC_EVENT_DETAIL_ENTRIES)
|
|
27
|
+
.map((entry) => normalizeSyncEventDetailValue(entry, depth + 1, seen));
|
|
28
|
+
}
|
|
29
|
+
if (value instanceof Map) {
|
|
30
|
+
const normalized = {};
|
|
31
|
+
for (const [key, entryValue] of Array.from(value.entries()).slice(0, MAX_SYNC_EVENT_DETAIL_ENTRIES)) {
|
|
32
|
+
normalized[String(key)] = normalizeSyncEventDetailValue(entryValue, depth + 1, seen);
|
|
33
|
+
}
|
|
34
|
+
return normalized;
|
|
35
|
+
}
|
|
36
|
+
if (typeof value === 'object') {
|
|
37
|
+
if (seen.has(value))
|
|
38
|
+
return '[Circular]';
|
|
39
|
+
seen.add(value);
|
|
40
|
+
const normalized = {};
|
|
41
|
+
for (const [key, entryValue] of Object.entries(value).slice(0, MAX_SYNC_EVENT_DETAIL_ENTRIES)) {
|
|
42
|
+
normalized[key] = normalizeSyncEventDetailValue(entryValue, depth + 1, seen);
|
|
43
|
+
}
|
|
44
|
+
seen.delete(value);
|
|
45
|
+
return normalized;
|
|
46
|
+
}
|
|
47
|
+
return String(value);
|
|
48
|
+
}
|
|
49
|
+
export function normalizeSyncEventDetails(details) {
|
|
50
|
+
if (!details || typeof details !== 'object' || Array.isArray(details))
|
|
51
|
+
return undefined;
|
|
52
|
+
return normalizeSyncEventDetailValue(details, 0, new WeakSet());
|
|
53
|
+
}
|
|
54
|
+
export function stableStringifySyncEventDetails(details) {
|
|
55
|
+
const normalized = normalizeSyncEventDetails(details);
|
|
56
|
+
if (!normalized)
|
|
57
|
+
return 'null';
|
|
58
|
+
try {
|
|
59
|
+
return JSON.stringify(normalized);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return '[UnserializableSyncEventDetails]';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { normalizeSyncEventDetails, stableStringifySyncEventDetails } from './syncEventDetails';
|
|
3
|
+
describe('syncEventDetails', () => {
|
|
4
|
+
it('normalizes non-JSON sync event details into a safe record', () => {
|
|
5
|
+
const circular = {
|
|
6
|
+
bigint: 4n,
|
|
7
|
+
map: new Map([['assetId', 'asset-1']]),
|
|
8
|
+
set: new Set(['doc-1', 'doc-2'])
|
|
9
|
+
};
|
|
10
|
+
circular.self = circular;
|
|
11
|
+
expect(normalizeSyncEventDetails(circular)).toEqual({
|
|
12
|
+
bigint: '4',
|
|
13
|
+
map: { assetId: 'asset-1' },
|
|
14
|
+
set: ['doc-1', 'doc-2'],
|
|
15
|
+
self: '[Circular]'
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
it('returns a stable string even for malformed details', () => {
|
|
19
|
+
const details = {};
|
|
20
|
+
details.self = details;
|
|
21
|
+
expect(stableStringifySyncEventDetails(details)).toContain('[Circular]');
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type SyncEventRecord = {
|
|
2
|
+
id?: number | string | null;
|
|
3
|
+
occurredAt?: string | null;
|
|
4
|
+
eventType?: string | null;
|
|
5
|
+
status?: string | null;
|
|
6
|
+
statusCode?: number | null;
|
|
7
|
+
errorMessage?: string | null;
|
|
8
|
+
changeCount?: number | null;
|
|
9
|
+
requestMs?: number | null;
|
|
10
|
+
details?: Record<string, unknown> | null;
|
|
11
|
+
};
|
|
12
|
+
export declare function getSyncEventStableKey(event: SyncEventRecord, index?: number): string;
|
|
13
|
+
export declare function mergeRecentSyncEvents(previous: SyncEventRecord[], incoming: SyncEventRecord[], limit?: number): SyncEventRecord[];
|
|
14
|
+
export declare function areSyncEventListsEqual(left: SyncEventRecord[], right: SyncEventRecord[]): boolean;
|
|
15
|
+
export declare function formatSyncEventLine(event: SyncEventRecord): string;
|