@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
|
@@ -17,6 +17,8 @@ describe('Workflow export snapshots', () => {
|
|
|
17
17
|
for (const workflowName of workflowNames) {
|
|
18
18
|
it(`${envId}/${workflowName} export snapshot`, () => {
|
|
19
19
|
const result = engine.processTemplate(workflowName, envId);
|
|
20
|
+
expect(result.content).not.toContain('shared docs under `docs/`');
|
|
21
|
+
expect(result.content).not.toContain('store it under `docs/`');
|
|
20
22
|
expect({
|
|
21
23
|
filename: result.filename,
|
|
22
24
|
strategy: result.strategy,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const AI_PROFILE_SEAT_SCOPES: readonly ["cloud_metered", "local_unmetered"];
|
|
2
|
+
export type AiProfileSeatScope = typeof AI_PROFILE_SEAT_SCOPES[number];
|
|
3
|
+
export declare function isAiProfileSeatScope(value: unknown): value is AiProfileSeatScope;
|
|
4
|
+
export declare function parseAiProfileSeatScope(value: unknown): AiProfileSeatScope | null;
|
|
5
|
+
export declare function formatAiProfileSeatScopeLabel(value: AiProfileSeatScope): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const AI_PROFILE_SEAT_SCOPES = [
|
|
2
|
+
'cloud_metered',
|
|
3
|
+
'local_unmetered',
|
|
4
|
+
];
|
|
5
|
+
const AI_PROFILE_SEAT_SCOPE_LABELS = {
|
|
6
|
+
cloud_metered: 'Cloud MCP',
|
|
7
|
+
local_unmetered: 'Local MCP',
|
|
8
|
+
};
|
|
9
|
+
export function isAiProfileSeatScope(value) {
|
|
10
|
+
return typeof value === 'string'
|
|
11
|
+
&& AI_PROFILE_SEAT_SCOPES.includes(value);
|
|
12
|
+
}
|
|
13
|
+
export function parseAiProfileSeatScope(value) {
|
|
14
|
+
if (typeof value !== 'string')
|
|
15
|
+
return null;
|
|
16
|
+
const normalized = value.trim();
|
|
17
|
+
return isAiProfileSeatScope(normalized) ? normalized : null;
|
|
18
|
+
}
|
|
19
|
+
export function formatAiProfileSeatScopeLabel(value) {
|
|
20
|
+
return AI_PROFILE_SEAT_SCOPE_LABELS[value];
|
|
21
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const AI_PROFILE_SURFACE_TYPES: readonly ["chat_app", "ide", "
|
|
1
|
+
export declare const AI_PROFILE_SURFACE_TYPES: readonly ["chat_app", "ide", "cli", "coding_tool", "agent"];
|
|
2
2
|
export type AiProfileSurfaceType = typeof AI_PROFILE_SURFACE_TYPES[number];
|
|
3
3
|
export type AiProfileSurfaceTypeSection = AiProfileSurfaceType | 'unclassified';
|
|
4
4
|
export declare const AI_PROFILE_SURFACE_TYPE_SECTION_ORDER: AiProfileSurfaceTypeSection[];
|
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
export const AI_PROFILE_SURFACE_TYPES = [
|
|
2
2
|
'chat_app',
|
|
3
3
|
'ide',
|
|
4
|
+
'cli',
|
|
4
5
|
'coding_tool',
|
|
5
|
-
'agent'
|
|
6
|
-
'other'
|
|
6
|
+
'agent'
|
|
7
7
|
];
|
|
8
8
|
export const AI_PROFILE_SURFACE_TYPE_SECTION_ORDER = [
|
|
9
9
|
'chat_app',
|
|
10
10
|
'ide',
|
|
11
|
+
'cli',
|
|
11
12
|
'coding_tool',
|
|
12
13
|
'agent',
|
|
13
|
-
'other',
|
|
14
14
|
'unclassified'
|
|
15
15
|
];
|
|
16
16
|
const AI_PROFILE_SURFACE_TYPE_LABELS = {
|
|
17
|
-
chat_app: 'Chat
|
|
17
|
+
chat_app: 'Chat App',
|
|
18
18
|
ide: 'IDE',
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
cli: 'CLI',
|
|
20
|
+
coding_tool: 'Coding Tool',
|
|
21
|
+
agent: 'Agent'
|
|
22
22
|
};
|
|
23
23
|
const AI_PROFILE_SURFACE_TYPE_SECTION_LABELS = {
|
|
24
24
|
chat_app: 'Chat Apps',
|
|
25
25
|
ide: 'IDEs',
|
|
26
|
+
cli: 'CLI',
|
|
26
27
|
coding_tool: 'Coding Tools',
|
|
27
28
|
agent: 'Agents',
|
|
28
|
-
other: 'Other',
|
|
29
29
|
unclassified: 'Unclassified'
|
|
30
30
|
};
|
|
31
31
|
export function isAiProfileSurfaceType(value) {
|
|
@@ -36,6 +36,8 @@ export function parseAiProfileSurfaceType(value) {
|
|
|
36
36
|
if (typeof value !== 'string')
|
|
37
37
|
return null;
|
|
38
38
|
const normalized = value.trim();
|
|
39
|
+
if (normalized === 'other')
|
|
40
|
+
return 'agent';
|
|
39
41
|
return isAiProfileSurfaceType(normalized) ? normalized : null;
|
|
40
42
|
}
|
|
41
43
|
export function formatAiProfileSurfaceTypeLabel(surfaceType) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const MIN_PASSWORD_LENGTH = 12;
|
|
2
|
+
export type PasswordPolicyCode = 'PASSWORD_REQUIRED' | 'PASSWORD_TOO_SHORT' | 'PASSWORD_TOO_COMMON' | 'PASSWORD_CONTAINS_PERSONAL_INFO';
|
|
3
|
+
export interface PasswordPolicyResult {
|
|
4
|
+
ok: boolean;
|
|
5
|
+
code?: PasswordPolicyCode;
|
|
6
|
+
message?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PasswordPolicyContext {
|
|
9
|
+
email?: string | null;
|
|
10
|
+
displayName?: string | null;
|
|
11
|
+
}
|
|
12
|
+
export declare function getPasswordPolicyGuidance(): string[];
|
|
13
|
+
export declare function validatePasswordPolicy(password: string, context?: PasswordPolicyContext): PasswordPolicyResult;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export const MIN_PASSWORD_LENGTH = 12;
|
|
2
|
+
const COMMON_PASSWORDS = new Set([
|
|
3
|
+
'12345678',
|
|
4
|
+
'123456789',
|
|
5
|
+
'1234567890',
|
|
6
|
+
'admin123',
|
|
7
|
+
'changeme',
|
|
8
|
+
'letmein',
|
|
9
|
+
'letmein123',
|
|
10
|
+
'password',
|
|
11
|
+
'password1',
|
|
12
|
+
'password12',
|
|
13
|
+
'password123',
|
|
14
|
+
'password1234',
|
|
15
|
+
'qwerty',
|
|
16
|
+
'qwerty123',
|
|
17
|
+
'welcome',
|
|
18
|
+
'welcome123'
|
|
19
|
+
]);
|
|
20
|
+
const normalizeForComparison = (value) => (String(value || '')
|
|
21
|
+
.trim()
|
|
22
|
+
.toLowerCase()
|
|
23
|
+
.replace(/[^a-z0-9]/g, ''));
|
|
24
|
+
function extractPersonalInfoTokens(context) {
|
|
25
|
+
const tokens = new Set();
|
|
26
|
+
const email = String(context?.email || '').trim().toLowerCase();
|
|
27
|
+
const displayName = String(context?.displayName || '').trim().toLowerCase();
|
|
28
|
+
if (email.includes('@')) {
|
|
29
|
+
const localPart = email.split('@')[0] || '';
|
|
30
|
+
const compactLocalPart = localPart.replace(/[^a-z0-9]/g, '');
|
|
31
|
+
if (compactLocalPart.length >= 4)
|
|
32
|
+
tokens.add(compactLocalPart);
|
|
33
|
+
for (const part of localPart.split(/[^a-z0-9]+/)) {
|
|
34
|
+
if (part.length >= 4)
|
|
35
|
+
tokens.add(part);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const part of displayName.split(/[^a-z0-9]+/)) {
|
|
39
|
+
if (part.length >= 4)
|
|
40
|
+
tokens.add(part);
|
|
41
|
+
}
|
|
42
|
+
return [...tokens];
|
|
43
|
+
}
|
|
44
|
+
export function getPasswordPolicyGuidance() {
|
|
45
|
+
return [
|
|
46
|
+
`Use at least ${MIN_PASSWORD_LENGTH} characters.`,
|
|
47
|
+
'Avoid common passwords or obvious patterns.',
|
|
48
|
+
'Do not include your email or display name.'
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
export function validatePasswordPolicy(password, context) {
|
|
52
|
+
const rawPassword = String(password || '');
|
|
53
|
+
if (!rawPassword) {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
code: 'PASSWORD_REQUIRED',
|
|
57
|
+
message: 'Password is required.'
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (rawPassword.length < MIN_PASSWORD_LENGTH) {
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
code: 'PASSWORD_TOO_SHORT',
|
|
64
|
+
message: `Password must be at least ${MIN_PASSWORD_LENGTH} characters.`
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const normalizedPassword = normalizeForComparison(rawPassword);
|
|
68
|
+
if (COMMON_PASSWORDS.has(normalizedPassword)) {
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
code: 'PASSWORD_TOO_COMMON',
|
|
72
|
+
message: 'Choose a less common password.'
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const personalTokens = extractPersonalInfoTokens(context);
|
|
76
|
+
if (personalTokens.some((token) => normalizedPassword.includes(token))) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
code: 'PASSWORD_CONTAINS_PERSONAL_INFO',
|
|
80
|
+
message: 'Password cannot contain your email or display name.'
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return { ok: true };
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { getPasswordPolicyGuidance, MIN_PASSWORD_LENGTH, validatePasswordPolicy } from './passwordPolicy';
|
|
3
|
+
describe('passwordPolicy', () => {
|
|
4
|
+
it('describes the active password policy guidance', () => {
|
|
5
|
+
expect(getPasswordPolicyGuidance()).toEqual([
|
|
6
|
+
`Use at least ${MIN_PASSWORD_LENGTH} characters.`,
|
|
7
|
+
'Avoid common passwords or obvious patterns.',
|
|
8
|
+
'Do not include your email or display name.'
|
|
9
|
+
]);
|
|
10
|
+
});
|
|
11
|
+
it('rejects common passwords even when padded with punctuation', () => {
|
|
12
|
+
expect(validatePasswordPolicy('Password123!')).toEqual({
|
|
13
|
+
ok: false,
|
|
14
|
+
code: 'PASSWORD_TOO_COMMON',
|
|
15
|
+
message: 'Choose a less common password.'
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
it('rejects passwords containing personal information', () => {
|
|
19
|
+
expect(validatePasswordPolicy('RossBurkeSecure!2026', {
|
|
20
|
+
email: 'ross@example.com',
|
|
21
|
+
displayName: 'Ross Burke'
|
|
22
|
+
})).toEqual({
|
|
23
|
+
ok: false,
|
|
24
|
+
code: 'PASSWORD_CONTAINS_PERSONAL_INFO',
|
|
25
|
+
message: 'Password cannot contain your email or display name.'
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
it('accepts long passwords without common or personal tokens', () => {
|
|
29
|
+
expect(validatePasswordPolicy('MapleHarborOrbit!2026', {
|
|
30
|
+
email: 'ross@example.com',
|
|
31
|
+
displayName: 'Ross Burke'
|
|
32
|
+
})).toEqual({ ok: true });
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -9,7 +9,8 @@ export function toPublicObjectStorageConfig(config) {
|
|
|
9
9
|
endpoint: config.r2.endpoint,
|
|
10
10
|
keyPrefix: config.r2.keyPrefix,
|
|
11
11
|
signedUploadTtlSeconds: config.r2.signedUploadTtlSeconds,
|
|
12
|
-
signedDownloadTtlSeconds: config.r2.signedDownloadTtlSeconds
|
|
12
|
+
signedDownloadTtlSeconds: config.r2.signedDownloadTtlSeconds,
|
|
13
|
+
...(typeof config.r2.requestTimeoutMs === 'number' ? { requestTimeoutMs: config.r2.requestTimeoutMs } : {})
|
|
13
14
|
}
|
|
14
15
|
};
|
|
15
16
|
}
|
|
@@ -8,6 +8,7 @@ export declare class ObjectStorageClient {
|
|
|
8
8
|
constructor(config: ResolvedObjectStorageConfig);
|
|
9
9
|
provider(): ObjectStorageProvider;
|
|
10
10
|
keyForRelativePath(relativePath: string): string;
|
|
11
|
+
private requestTimeoutMs;
|
|
11
12
|
putObject(relativePath: string, body: Buffer, contentType: string): Promise<void>;
|
|
12
13
|
getObject(relativePath: string): Promise<StoredObject | null>;
|
|
13
14
|
objectExists(relativePath: string): Promise<boolean>;
|
|
@@ -4,6 +4,7 @@ const AWS_SERVICE = 's3';
|
|
|
4
4
|
const AWS_REGION = 'auto';
|
|
5
5
|
const TRANSIENT_GET_OBJECT_STATUS_CODES = new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
6
6
|
const MAX_GET_OBJECT_ATTEMPTS = 3;
|
|
7
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 15000;
|
|
7
8
|
function sha256Hex(value) {
|
|
8
9
|
return createHash('sha256').update(value).digest('hex');
|
|
9
10
|
}
|
|
@@ -77,6 +78,33 @@ function shouldRetryGetObjectError(error) {
|
|
|
77
78
|
|| message.includes('ecanceled')
|
|
78
79
|
|| message.includes('und_err');
|
|
79
80
|
}
|
|
81
|
+
async function fetchWithTimeout(url, init, timeoutMsRaw) {
|
|
82
|
+
const timeoutMs = Number.isFinite(timeoutMsRaw) && timeoutMsRaw > 0
|
|
83
|
+
? Math.floor(timeoutMsRaw)
|
|
84
|
+
: DEFAULT_REQUEST_TIMEOUT_MS;
|
|
85
|
+
const controller = new AbortController();
|
|
86
|
+
const timeout = setTimeout(() => {
|
|
87
|
+
controller.abort(new Error(`R2 request timed out after ${timeoutMs}ms`));
|
|
88
|
+
}, timeoutMs);
|
|
89
|
+
try {
|
|
90
|
+
return await fetch(url, {
|
|
91
|
+
...init,
|
|
92
|
+
signal: controller.signal
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
if (controller.signal.aborted) {
|
|
97
|
+
const reason = controller.signal.reason;
|
|
98
|
+
if (reason instanceof Error)
|
|
99
|
+
throw reason;
|
|
100
|
+
throw new Error(`R2 request timed out after ${timeoutMs}ms`);
|
|
101
|
+
}
|
|
102
|
+
throw error;
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
clearTimeout(timeout);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
80
108
|
function signRequest(params) {
|
|
81
109
|
const amzDate = createAmzDate(params.now);
|
|
82
110
|
const dateStamp = toDateStamp(amzDate);
|
|
@@ -117,6 +145,11 @@ export class ObjectStorageClient {
|
|
|
117
145
|
keyForRelativePath(relativePath) {
|
|
118
146
|
return buildObjectKey(this.config, relativePath);
|
|
119
147
|
}
|
|
148
|
+
requestTimeoutMs() {
|
|
149
|
+
return this.config.provider === 'r2'
|
|
150
|
+
? Number(this.config.r2?.requestTimeoutMs || DEFAULT_REQUEST_TIMEOUT_MS)
|
|
151
|
+
: DEFAULT_REQUEST_TIMEOUT_MS;
|
|
152
|
+
}
|
|
120
153
|
async putObject(relativePath, body, contentType) {
|
|
121
154
|
if (this.config.provider !== 'r2' || !this.config.r2) {
|
|
122
155
|
throw new Error('R2 object storage is not configured.');
|
|
@@ -131,7 +164,7 @@ export class ObjectStorageClient {
|
|
|
131
164
|
secretAccessKey: this.config.r2.secretAccessKey,
|
|
132
165
|
payloadHash
|
|
133
166
|
});
|
|
134
|
-
const response = await
|
|
167
|
+
const response = await fetchWithTimeout(url, {
|
|
135
168
|
method: 'PUT',
|
|
136
169
|
headers: {
|
|
137
170
|
'authorization': signed.authorization,
|
|
@@ -140,7 +173,7 @@ export class ObjectStorageClient {
|
|
|
140
173
|
'content-type': contentType
|
|
141
174
|
},
|
|
142
175
|
body: new Uint8Array(body)
|
|
143
|
-
});
|
|
176
|
+
}, this.requestTimeoutMs());
|
|
144
177
|
if (!response.ok) {
|
|
145
178
|
const text = await response.text().catch(() => '');
|
|
146
179
|
throw new Error(`Failed to upload object (${response.status}): ${text || response.statusText}`);
|
|
@@ -163,14 +196,14 @@ export class ObjectStorageClient {
|
|
|
163
196
|
payloadHash
|
|
164
197
|
});
|
|
165
198
|
try {
|
|
166
|
-
const response = await
|
|
199
|
+
const response = await fetchWithTimeout(url, {
|
|
167
200
|
method: 'GET',
|
|
168
201
|
headers: {
|
|
169
202
|
'authorization': signed.authorization,
|
|
170
203
|
'x-amz-date': signed.amzDate,
|
|
171
204
|
'x-amz-content-sha256': payloadHash
|
|
172
205
|
}
|
|
173
|
-
});
|
|
206
|
+
}, this.requestTimeoutMs());
|
|
174
207
|
if (response.status === 404)
|
|
175
208
|
return null;
|
|
176
209
|
if (!response.ok) {
|
|
@@ -211,14 +244,14 @@ export class ObjectStorageClient {
|
|
|
211
244
|
secretAccessKey: this.config.r2.secretAccessKey,
|
|
212
245
|
payloadHash
|
|
213
246
|
});
|
|
214
|
-
const response = await
|
|
247
|
+
const response = await fetchWithTimeout(url, {
|
|
215
248
|
method: 'HEAD',
|
|
216
249
|
headers: {
|
|
217
250
|
'authorization': signed.authorization,
|
|
218
251
|
'x-amz-date': signed.amzDate,
|
|
219
252
|
'x-amz-content-sha256': payloadHash
|
|
220
253
|
}
|
|
221
|
-
});
|
|
254
|
+
}, this.requestTimeoutMs());
|
|
222
255
|
if (response.status === 404)
|
|
223
256
|
return false;
|
|
224
257
|
if (!response.ok) {
|
|
@@ -241,14 +274,14 @@ export class ObjectStorageClient {
|
|
|
241
274
|
secretAccessKey: this.config.r2.secretAccessKey,
|
|
242
275
|
payloadHash
|
|
243
276
|
});
|
|
244
|
-
const response = await
|
|
277
|
+
const response = await fetchWithTimeout(url, {
|
|
245
278
|
method: 'DELETE',
|
|
246
279
|
headers: {
|
|
247
280
|
'authorization': signed.authorization,
|
|
248
281
|
'x-amz-date': signed.amzDate,
|
|
249
282
|
'x-amz-content-sha256': payloadHash
|
|
250
283
|
}
|
|
251
|
-
});
|
|
284
|
+
}, this.requestTimeoutMs());
|
|
252
285
|
if (response.status === 404)
|
|
253
286
|
return false;
|
|
254
287
|
if (!response.ok) {
|
|
@@ -10,9 +10,34 @@ const TEST_CONFIG = {
|
|
|
10
10
|
secretAccessKey: 'secret-key-1',
|
|
11
11
|
keyPrefix: '',
|
|
12
12
|
signedUploadTtlSeconds: 600,
|
|
13
|
-
signedDownloadTtlSeconds: 300
|
|
13
|
+
signedDownloadTtlSeconds: 300,
|
|
14
|
+
requestTimeoutMs: 15000
|
|
14
15
|
}
|
|
15
16
|
};
|
|
17
|
+
describe('ObjectStorageClient.putObject', () => {
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
vi.unstubAllGlobals();
|
|
20
|
+
vi.restoreAllMocks();
|
|
21
|
+
});
|
|
22
|
+
it('aborts stalled uploads before MCP tool calls can time out', async () => {
|
|
23
|
+
const fetchMock = vi.fn((_input, init) => (new Promise((_resolve, reject) => {
|
|
24
|
+
const signal = init?.signal;
|
|
25
|
+
signal?.addEventListener('abort', () => {
|
|
26
|
+
reject(signal.reason);
|
|
27
|
+
}, { once: true });
|
|
28
|
+
})));
|
|
29
|
+
vi.stubGlobal('fetch', fetchMock);
|
|
30
|
+
const client = new ObjectStorageClient({
|
|
31
|
+
...TEST_CONFIG,
|
|
32
|
+
r2: {
|
|
33
|
+
...TEST_CONFIG.r2,
|
|
34
|
+
requestTimeoutMs: 1
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
await expect(client.putObject('workspaces/workspace-1/assets/documents/doc-1.md', Buffer.from('# plan', 'utf8'), 'text/markdown')).rejects.toThrow('R2 request timed out after 1ms');
|
|
38
|
+
expect(fetchMock).toHaveBeenCalledTimes(1);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
16
41
|
describe('ObjectStorageClient.getObject', () => {
|
|
17
42
|
afterEach(() => {
|
|
18
43
|
vi.unstubAllGlobals();
|
|
@@ -31,6 +31,7 @@ export function resolveObjectStorageConfigFromEnv(env = process.env) {
|
|
|
31
31
|
: '';
|
|
32
32
|
const signedUploadTtlSeconds = readPositiveInteger(env.R2_SIGNED_UPLOAD_TTL_SECONDS, 600);
|
|
33
33
|
const signedDownloadTtlSeconds = readPositiveInteger(env.R2_SIGNED_DOWNLOAD_TTL_SECONDS, 300);
|
|
34
|
+
const requestTimeoutMs = readPositiveInteger(env.R2_REQUEST_TIMEOUT_MS, 15000);
|
|
34
35
|
return {
|
|
35
36
|
provider: 'r2',
|
|
36
37
|
r2: {
|
|
@@ -41,7 +42,8 @@ export function resolveObjectStorageConfigFromEnv(env = process.env) {
|
|
|
41
42
|
secretAccessKey,
|
|
42
43
|
keyPrefix,
|
|
43
44
|
signedUploadTtlSeconds,
|
|
44
|
-
signedDownloadTtlSeconds
|
|
45
|
+
signedDownloadTtlSeconds,
|
|
46
|
+
requestTimeoutMs
|
|
45
47
|
}
|
|
46
48
|
};
|
|
47
49
|
}
|
|
@@ -20,7 +20,8 @@ describe('resolveObjectStorageConfigFromEnv', () => {
|
|
|
20
20
|
secretAccessKey: 'secret-key-1',
|
|
21
21
|
keyPrefix: '',
|
|
22
22
|
signedUploadTtlSeconds: 600,
|
|
23
|
-
signedDownloadTtlSeconds: 300
|
|
23
|
+
signedDownloadTtlSeconds: 300,
|
|
24
|
+
requestTimeoutMs: 15000
|
|
24
25
|
}
|
|
25
26
|
});
|
|
26
27
|
});
|
|
@@ -35,4 +36,15 @@ describe('resolveObjectStorageConfigFromEnv', () => {
|
|
|
35
36
|
});
|
|
36
37
|
expect(config.r2?.keyPrefix).toBe('taskforce-assets');
|
|
37
38
|
});
|
|
39
|
+
it('reads a bounded R2 request timeout', () => {
|
|
40
|
+
const config = resolveObjectStorageConfigFromEnv({
|
|
41
|
+
TASKFORCE_OBJECT_STORAGE_PROVIDER: 'r2',
|
|
42
|
+
R2_ACCOUNT_ID: 'acct-1',
|
|
43
|
+
R2_BUCKET: 'taskforce-dev-assets',
|
|
44
|
+
R2_ACCESS_KEY_ID: 'access-key-1',
|
|
45
|
+
R2_SECRET_ACCESS_KEY: 'secret-key-1',
|
|
46
|
+
R2_REQUEST_TIMEOUT_MS: '2500'
|
|
47
|
+
});
|
|
48
|
+
expect(config.r2?.requestTimeoutMs).toBe(2500);
|
|
49
|
+
});
|
|
38
50
|
});
|
|
@@ -3,6 +3,7 @@ import type { ObjectStorageProvider } from './objectStorage.js';
|
|
|
3
3
|
export type WorkspaceAssetKind = 'document' | 'image' | 'file';
|
|
4
4
|
export type WorkspaceAssetScanStatus = 'pending' | 'clean' | 'infected' | 'failed';
|
|
5
5
|
export type WorkspaceAssetLinkRole = 'attachment' | 'image' | 'reference';
|
|
6
|
+
export type WorkspaceAssetLinkTargetType = 'task' | 'initiative' | 'workstream';
|
|
6
7
|
export interface WorkspaceAssetEntry {
|
|
7
8
|
assetId: string;
|
|
8
9
|
tenantId: string;
|
|
@@ -32,7 +33,9 @@ export interface WorkspaceAssetLinkEntry {
|
|
|
32
33
|
tenantId: string;
|
|
33
34
|
workspaceId: string;
|
|
34
35
|
assetId: string;
|
|
35
|
-
|
|
36
|
+
targetType: WorkspaceAssetLinkTargetType;
|
|
37
|
+
targetId: string;
|
|
38
|
+
taskId: string | null;
|
|
36
39
|
role: WorkspaceAssetLinkRole;
|
|
37
40
|
displayName: string | null;
|
|
38
41
|
sortOrder: number | null;
|
|
@@ -43,7 +46,9 @@ export interface WorkspaceAssetLinkEntry {
|
|
|
43
46
|
export declare class WorkspaceAssetStore {
|
|
44
47
|
private readonly db;
|
|
45
48
|
private readonly tenantId;
|
|
49
|
+
private supportsTargetTypeCache;
|
|
46
50
|
constructor(db: DatabaseAdapter, tenantId: string);
|
|
51
|
+
private supportsTargetType;
|
|
47
52
|
private normalizePersistedAsset;
|
|
48
53
|
get(assetIdRaw: string, workspaceIdRaw?: string): WorkspaceAssetEntry | null;
|
|
49
54
|
getByStorageKey(storageKeyRaw: string, workspaceIdRaw: string): WorkspaceAssetEntry | null;
|
|
@@ -98,7 +103,9 @@ export declare class WorkspaceAssetStore {
|
|
|
98
103
|
upsertLink(input: {
|
|
99
104
|
workspaceId: string;
|
|
100
105
|
assetId: string;
|
|
101
|
-
taskId
|
|
106
|
+
taskId?: string;
|
|
107
|
+
targetType?: WorkspaceAssetLinkTargetType;
|
|
108
|
+
targetId?: string;
|
|
102
109
|
role: WorkspaceAssetLinkRole;
|
|
103
110
|
displayName?: string | null;
|
|
104
111
|
sortOrder?: number | null;
|
|
@@ -109,13 +116,18 @@ export declare class WorkspaceAssetStore {
|
|
|
109
116
|
listLinksForTask(taskIdRaw: string, workspaceIdRaw: string, options?: {
|
|
110
117
|
includeDeleted?: boolean;
|
|
111
118
|
}): WorkspaceAssetLinkEntry[];
|
|
119
|
+
listLinksForTarget(targetTypeRaw: WorkspaceAssetLinkTargetType, targetIdRaw: string, workspaceIdRaw: string, options?: {
|
|
120
|
+
includeDeleted?: boolean;
|
|
121
|
+
}): WorkspaceAssetLinkEntry[];
|
|
112
122
|
listLinksForAsset(assetIdRaw: string, workspaceIdRaw: string, options?: {
|
|
113
123
|
includeDeleted?: boolean;
|
|
114
124
|
}): WorkspaceAssetLinkEntry[];
|
|
115
125
|
deleteLink(input: {
|
|
116
126
|
workspaceId: string;
|
|
117
127
|
assetId: string;
|
|
118
|
-
taskId
|
|
128
|
+
taskId?: string;
|
|
129
|
+
targetType?: WorkspaceAssetLinkTargetType;
|
|
130
|
+
targetId?: string;
|
|
119
131
|
role: WorkspaceAssetLinkRole;
|
|
120
132
|
hardDelete?: boolean;
|
|
121
133
|
}): boolean;
|