@taskforcehq/taskforce 0.3.328 → 0.3.330
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/dist/Taskforce.module.css +523 -79
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/features/AiProfilesModule.js +3 -5
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +217 -54
- package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
- package/dist/components/features/TaskforceAgentsModule.js +586 -116
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
- package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
- package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
- package/dist/components/features/taskforceAgentEditorModel.js +5 -1
- package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
- package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +32 -55
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
- package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
- package/dist/config/envSchema.js +60 -1
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/McpTokenService.d.ts +23 -1
- package/dist/core/McpTokenService.js +93 -10
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/TaskChecklistCommandService.d.ts +27 -0
- package/dist/core/TaskChecklistCommandService.js +83 -5
- package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
- package/dist/core/TaskLifecycleCommandService.js +6 -2
- package/dist/core/Taskforce.d.ts +94 -2
- package/dist/core/Taskforce.js +760 -36
- package/dist/core/types.d.ts +14 -0
- package/dist/documentReviews/commandService.d.ts +2 -1
- package/dist/documentReviews/commandService.js +6 -3
- package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.js +2 -0
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
- package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
- package/dist/hooks/sync/useSyncStatusControls.js +47 -11
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
- package/dist/hooks/useSyncOrchestrator.js +111 -2
- package/dist/hooks/useTaskData.d.ts +40 -1
- package/dist/hooks/useTaskData.js +240 -9
- package/dist/hooks/useTaskMutations.d.ts +12 -2
- package/dist/hooks/useTaskMutations.js +266 -52
- package/dist/hooks/useTaskforce.d.ts +39 -9
- package/dist/hooks/useTaskforce.js +359 -40
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/clientRegistry.d.ts +2 -2
- package/dist/mcp/clientRegistry.js +1 -1
- package/dist/mcp/documentAssetRegistrar.js +53 -41
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
- package/dist/mcp/durableTaskMutationRouter.js +10 -0
- package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
- package/dist/mcp/httpProtocolRouting.d.ts +10 -0
- package/dist/mcp/httpProtocolRouting.js +19 -0
- package/dist/mcp/localCliHealth.d.ts +2 -2
- package/dist/mcp/localCliHealth.js +2 -2
- package/dist/mcp/localServiceProxy.d.ts +1 -0
- package/dist/mcp/localServiceProxy.js +530 -68
- package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
- package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
- package/dist/mcp/runtime.d.ts +54 -79
- package/dist/mcp/runtime.js +556 -139
- package/dist/mcp/taskPlanningRegistrar.js +64 -42
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/mcp/toolProfiles.d.ts +2 -0
- package/dist/mcp/toolProfiles.js +10 -0
- package/dist/mcp/toolRegistry.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +1 -0
- package/dist/mcp/workflowExecutionRegistrar.js +4 -4
- package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
- package/dist/migrations/taskSchemaMigrations.js +427 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +13 -13
- package/dist/runtime/appGates.js +36 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.js +123 -14
- package/dist/server/localDatabaseIdentity.js +4 -1
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +11 -2
- package/dist/server/localServiceSessions.d.ts +14 -17
- package/dist/server/localServiceSessions.js +308 -94
- package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.d.ts +4 -0
- package/dist/server/routes/admin.js +113 -3
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.d.ts +7 -0
- package/dist/server/routes/agents.js +394 -39
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/billing.js +5 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
- package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
- package/dist/server/routes/executorPhaseAApprovals.js +140 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
- package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
- package/dist/server/routes/githubReviewEvidence.js +116 -0
- package/dist/server/routes/localService.d.ts +15 -4
- package/dist/server/routes/localService.js +138 -40
- package/dist/server/routes/modelConnections.d.ts +24 -0
- package/dist/server/routes/modelConnections.js +205 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/shared.d.ts +19 -0
- package/dist/server/routes/shared.js +95 -19
- package/dist/server/routes/sync.js +1 -0
- package/dist/server/routes/syncAuxRoutes.js +9 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncPushRoutes.d.ts +1 -0
- package/dist/server/routes/syncPushRoutes.js +1 -0
- package/dist/server/routes/syncV3FeedRoutes.js +27 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +45 -9
- package/dist/server/routes/tasks.js +124 -13
- package/dist/server/routes/workflows.js +9 -1
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/routes.js +59 -0
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +161 -0
- package/dist/services/codexAppServerModelGateway.js +663 -0
- package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
- package/dist/services/codexDeviceCodeLoginManager.js +265 -0
- package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
- package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
- package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
- package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
- package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
- package/dist/services/executorPhaseAApprovalService.js +609 -0
- package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
- package/dist/services/executorPhaseADriftEvaluator.js +93 -0
- package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
- package/dist/services/executorPhaseAIssuerCore.js +295 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
- package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
- package/dist/services/githubReviewEvidenceRuntime.js +30 -0
- package/dist/services/githubReviewEvidenceService.d.ts +93 -0
- package/dist/services/githubReviewEvidenceService.js +336 -0
- package/dist/services/modelGateway.d.ts +7 -0
- package/dist/services/modelProviderConnectionService.d.ts +71 -0
- package/dist/services/modelProviderConnectionService.js +279 -0
- package/dist/services/modelProviderCredentialHome.d.ts +32 -0
- package/dist/services/modelProviderCredentialHome.js +271 -0
- package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
- package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
- package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
- package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
- package/dist/services/taskforceAgentMcpBridge.js +30 -27
- package/dist/shared/adminEdgeProxy.d.ts +5 -0
- package/dist/shared/adminEdgeProxy.js +94 -0
- package/dist/shared/adminProxySessionCookies.d.ts +16 -0
- package/dist/shared/adminProxySessionCookies.js +86 -0
- package/dist/shared/aiProfileColors.d.ts +31 -1
- package/dist/shared/aiProfileColors.js +14 -6
- package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
- package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
- package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
- package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
- package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
- package/dist/shared/executorPhaseADriftContracts.js +63 -0
- package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
- package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
- package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
- package/dist/shared/executorPhaseARunAuthorization.js +232 -0
- package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
- package/dist/shared/executorPhaseASchemaValidation.js +53 -0
- package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
- package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
- package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
- package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
- package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
- package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
- package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
- package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
- package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
- package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
- package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
- package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
- package/dist/shared/executorPhaseATiming.d.ts +1 -0
- package/dist/shared/executorPhaseATiming.js +1 -0
- package/dist/shared/planningIdentity.js +1 -1
- package/dist/shared/productLogoKeys.d.ts +2 -0
- package/dist/shared/productLogoKeys.js +18 -0
- package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
- package/dist/shared/taskforceAgentDefinition.js +6 -3
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +36 -3
- package/dist/shared/userFeatureGrants.d.ts +4 -0
- package/dist/shared/userFeatureGrants.js +7 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
- package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
- package/dist/storage/modelProviderConnectionStore.js +446 -0
- package/dist/storage/postgresAdapter.d.ts +24 -3
- package/dist/storage/postgresAdapter.js +117 -14
- package/dist/storage/postgresWorker.js +22 -5
- package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
- package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
- package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
- package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
- package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
- package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
- package/dist/sync/syncApplyHandlers.d.ts +2 -0
- package/dist/sync/syncApplyHandlers.js +10 -1
- package/dist/sync/syncService.d.ts +17 -0
- package/dist/sync/syncService.js +87 -19
- package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
- package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
- package/dist/sync/v3/combinedFeedCapability.js +8 -0
- package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
- package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
- package/dist/sync/v3/durableOperationReplay.js +18 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
- package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
- package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
- package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
- package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
- package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
- package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
- package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
- package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
- package/dist/sync/v3/syncDurabilityStore.js +199 -13
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
- package/dist/sync/v3/taskChecklistMutationService.js +48 -1
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
- package/dist/sync/v3/taskStatusMutationService.js +123 -3
- package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
- package/dist/sync/v3/workflowAssignmentSync.js +30 -0
- package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
- package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
- package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +8 -2
- package/dist/sync/workspaceRepair.js +222 -6
- package/dist/sync/workspaceSyncModel.d.ts +21 -0
- package/dist/sync/workspaceSyncModel.js +35 -7
- package/dist/sync/workspaceSyncState.d.ts +1 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
- package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
- package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
- package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
- package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
- package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
- package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
- package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
- package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
- package/dist/ui/assets/index-CTsDBaef.js +7 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
- package/dist/ui/branding/logos/letterhead_dark.png +0 -0
- package/dist/ui/branding/logos/letterhead_light.png +0 -0
- package/dist/ui/branding/logos/signature_dark.png +0 -0
- package/dist/ui/branding/logos/signature_light.png +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/aiProfileDefaultLogo.js +16 -48
- package/dist/utils/httpSetCookie.d.ts +1 -0
- package/dist/utils/httpSetCookie.js +4 -1
- package/dist/utils/localRuntimeUrl.d.ts +1 -0
- package/dist/utils/localRuntimeUrl.js +14 -0
- package/dist/utils/productLogoRegistry.d.ts +2 -0
- package/dist/utils/productLogoRegistry.js +36 -0
- package/dist/utils/syncStatusPresentation.d.ts +4 -0
- package/dist/utils/syncStatusPresentation.js +17 -0
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskEvents.d.ts +2 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
- package/dist/utils/workspaceSyncPresentation.js +23 -17
- package/package.json +36 -6
- package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
- package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
|
@@ -140,10 +140,19 @@ export function createDurableTaskAttachmentLinksMutationRouter(input) {
|
|
|
140
140
|
catch {
|
|
141
141
|
throw new DurableTaskAttachmentLinksMutationError('Captured task attachment-link payload is invalid.', 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT', 409);
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
const relationshipIntent = (entries) => entries.map((link) => ({
|
|
144
|
+
assetId: link.assetId,
|
|
145
|
+
role: link.role,
|
|
146
|
+
order: link.order,
|
|
147
|
+
}));
|
|
148
|
+
if (canonicalWorkspaceSyncJson(relationshipIntent(frozen))
|
|
149
|
+
!== canonicalWorkspaceSyncJson(relationshipIntent(links))
|
|
144
150
|
|| String(payload.cardCoverAssetId || '') !== String(cardCoverAssetId || '')) {
|
|
145
151
|
throw new DurableTaskAttachmentLinksMutationError('Operation identity is assigned to different task attachment links.', 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT', 409);
|
|
146
152
|
}
|
|
153
|
+
store.assertOutboxOperationIdentity(existing, {
|
|
154
|
+
domain: 'task-attachment-links', entityId: taskId, mutationKind: 'replace',
|
|
155
|
+
});
|
|
147
156
|
const task = input.core.getTask(taskId, workspaceId);
|
|
148
157
|
if (!task)
|
|
149
158
|
throw new DurableTaskAttachmentLinksMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
|
|
@@ -204,6 +213,10 @@ export function createDurableTaskAttachmentLinksMutationRouter(input) {
|
|
|
204
213
|
baseEntityRevision: coordinates.entityRevision, baseLifecycleRevision: coordinates.lifecycleRevision,
|
|
205
214
|
now: acceptedAtIso, leaseExpiresAt: new Date(acceptedAt.getTime() + OPERATION_LEASE_MS).toISOString(),
|
|
206
215
|
actorRef, onPostCommitError: input.onPostCommitError,
|
|
216
|
+
expectedDetailRevision: args.expectedDetailRevision,
|
|
217
|
+
assertPrecondition: args.expectedDetailRevision
|
|
218
|
+
? () => input.core.assertTaskDetailRevisionForUpdate(taskId, args.expectedDetailRevision, workspaceId)
|
|
219
|
+
: undefined,
|
|
207
220
|
});
|
|
208
221
|
if (result.state === 'in_progress')
|
|
209
222
|
throw new DurableTaskAttachmentLinksRouterInProgressError(result.retryAt);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ChecklistItem, TaskItem } from '../../core/Taskforce.js';
|
|
2
2
|
import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
|
|
3
3
|
import { type LocalTaskChecklistOutboxCore } from './localTaskChecklistOutboxService.js';
|
|
4
|
-
import { type DurableTaskChecklistServiceCore } from './taskChecklistMutationService.js';
|
|
4
|
+
import { type DurableTaskChecklistServiceCore, type TaskChecklistItemUpdateIntent } from './taskChecklistMutationService.js';
|
|
5
5
|
export declare function resolveTaskChecklistMutationCapability(input: {
|
|
6
6
|
runtimeMode: 'local' | 'cloud';
|
|
7
7
|
surface: 'http' | 'mcp';
|
|
@@ -11,6 +11,7 @@ export declare function resolveTaskChecklistMutationCapability(input: {
|
|
|
11
11
|
export type DurableTaskChecklistMutationRouterCore = DurableTaskChecklistServiceCore & LocalTaskChecklistOutboxCore & {
|
|
12
12
|
getDatabaseAdapter(): DatabaseAdapter;
|
|
13
13
|
getTask(id: string, workspaceId?: string): TaskItem | null;
|
|
14
|
+
assertTaskDetailRevisionForUpdate(id: string, expected: string, workspaceId?: string): void;
|
|
14
15
|
};
|
|
15
16
|
export declare class DurableTaskChecklistRouterDisabledError extends Error {
|
|
16
17
|
readonly code = "WORKSPACE_SYNC_V3_TASK_CHECKLIST_ROUTER_DISABLED";
|
|
@@ -38,6 +39,8 @@ export declare function createDurableTaskChecklistMutationRouter(input: {
|
|
|
38
39
|
replace(args: {
|
|
39
40
|
taskId: string;
|
|
40
41
|
items: readonly Partial<ChecklistItem>[];
|
|
42
|
+
expectedDetailRevision?: string;
|
|
43
|
+
itemUpdateIntent?: TaskChecklistItemUpdateIntent;
|
|
41
44
|
}): {
|
|
42
45
|
state: "pending" | "committed";
|
|
43
46
|
route: "local-outbox" | "cloud-acceptance";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { canonicalWorkspaceSyncJson } from './canonicalWorkspaceSyncJson.js';
|
|
2
2
|
import { LocalSyncIdentityStore } from './localSyncIdentityStore.js';
|
|
3
3
|
import { enqueueLocalTaskChecklistMutation, } from './localTaskChecklistOutboxService.js';
|
|
4
|
-
import { DurableTaskChecklistMutationError, runDurableTaskChecklistReplace, } from './taskChecklistMutationService.js';
|
|
4
|
+
import { DurableTaskChecklistMutationError, runDurableTaskChecklistReplace, validateTaskChecklistItemUpdateIntent, } from './taskChecklistMutationService.js';
|
|
5
5
|
import { WorkspaceSyncDurabilityStore, WorkspaceSyncEntityBusyError } from './syncDurabilityStore.js';
|
|
6
6
|
import { serializeWorkspaceSyncV3TaskChecklistPayload } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
7
7
|
const OPERATION_LEASE_MS = 30_000;
|
|
@@ -82,6 +82,18 @@ export function createDurableTaskChecklistMutationRouter(input) {
|
|
|
82
82
|
catch (error) {
|
|
83
83
|
throw new DurableTaskChecklistMutationError(error instanceof Error ? error.message : 'Task checklist is invalid.', 'TASK_CHECKLIST_INVALID', 400);
|
|
84
84
|
}
|
|
85
|
+
const itemUpdateIntent = args.itemUpdateIntent
|
|
86
|
+
? validateTaskChecklistItemUpdateIntent(args.itemUpdateIntent)
|
|
87
|
+
: undefined;
|
|
88
|
+
if (itemUpdateIntent) {
|
|
89
|
+
const target = items.find((item) => item.id === itemUpdateIntent.itemId);
|
|
90
|
+
if (!target
|
|
91
|
+
|| (itemUpdateIntent.patch.text !== undefined && target.title !== itemUpdateIntent.patch.text)
|
|
92
|
+
|| (itemUpdateIntent.patch.done !== undefined && target.isCompleted !== itemUpdateIntent.patch.done)
|
|
93
|
+
|| (itemUpdateIntent.patch.order !== undefined && target.order !== itemUpdateIntent.patch.order)) {
|
|
94
|
+
throw new DurableTaskChecklistMutationError('Task checklist item update intent does not match the replacement aggregate.', 'TASK_CHECKLIST_INVALID', 400);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
85
97
|
const acceptedAt = now();
|
|
86
98
|
const acceptedAtIso = acceptedAt.toISOString();
|
|
87
99
|
const operationId = operationIdRequired(input.operationId);
|
|
@@ -109,25 +121,43 @@ export function createDurableTaskChecklistMutationRouter(input) {
|
|
|
109
121
|
catch {
|
|
110
122
|
throw new DurableTaskChecklistMutationError('Captured task checklist payload is invalid.', 'TASK_CHECKLIST_IDENTITY_CONFLICT', 409);
|
|
111
123
|
}
|
|
112
|
-
|
|
124
|
+
const capturedIntent = payload.itemUpdateIntent
|
|
125
|
+
? validateTaskChecklistItemUpdateIntent(payload.itemUpdateIntent)
|
|
126
|
+
: undefined;
|
|
127
|
+
const requestedIntent = itemUpdateIntent;
|
|
128
|
+
if (capturedIntent || requestedIntent
|
|
129
|
+
? canonicalWorkspaceSyncJson(capturedIntent) !== canonicalWorkspaceSyncJson(requestedIntent)
|
|
130
|
+
: canonicalWorkspaceSyncJson(frozen) !== canonicalWorkspaceSyncJson(items)) {
|
|
113
131
|
throw new DurableTaskChecklistMutationError('Operation identity is assigned to a different task checklist.', 'TASK_CHECKLIST_IDENTITY_CONFLICT', 409);
|
|
114
132
|
}
|
|
133
|
+
if ((payload.expectedDetailRevision || undefined) !== (args.expectedDetailRevision || undefined)) {
|
|
134
|
+
throw new DurableTaskChecklistMutationError('Operation identity is assigned to a different task checklist precondition.', 'TASK_CHECKLIST_IDENTITY_CONFLICT', 409);
|
|
135
|
+
}
|
|
136
|
+
store.assertOutboxOperationIdentity(existing, {
|
|
137
|
+
domain: 'task-checklist', entityId: taskId, mutationKind: 'replace',
|
|
138
|
+
});
|
|
115
139
|
const task = input.core.getTask(taskId, workspaceId);
|
|
116
140
|
if (!task)
|
|
117
141
|
throw new DurableTaskChecklistMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
|
|
118
142
|
const installed = serializeWorkspaceSyncV3TaskChecklistPayload({
|
|
119
143
|
taskId, items: task.checklistItems || [],
|
|
120
144
|
}).items;
|
|
121
|
-
if (
|
|
145
|
+
if (!capturedIntent
|
|
146
|
+
&& canonicalWorkspaceSyncJson(installed) !== canonicalWorkspaceSyncJson(frozen)) {
|
|
122
147
|
throw new DurableTaskChecklistMutationError('Captured task checklist does not match local state.', 'TASK_CHECKLIST_IDENTITY_CONFLICT', 409);
|
|
123
148
|
}
|
|
124
|
-
return {
|
|
149
|
+
return {
|
|
150
|
+
state: 'pending', route: 'local-outbox', operationId,
|
|
151
|
+
task: capturedIntent ? { ...task, checklistItems: frozen } : task,
|
|
152
|
+
};
|
|
125
153
|
}
|
|
126
154
|
let result;
|
|
127
155
|
try {
|
|
128
156
|
result = enqueueLocalTaskChecklistMutation({
|
|
129
157
|
store, core: input.core, identity, taskId, items, now: acceptedAtIso,
|
|
130
158
|
actorRef, onPostCommitError: input.onPostCommitError,
|
|
159
|
+
expectedDetailRevision: args.expectedDetailRevision,
|
|
160
|
+
itemUpdateIntent,
|
|
131
161
|
requireV3CombinedOwnership: persistedOwnershipChecked,
|
|
132
162
|
});
|
|
133
163
|
}
|
|
@@ -142,6 +172,7 @@ export function createDurableTaskChecklistMutationRouter(input) {
|
|
|
142
172
|
return { state: 'pending', route: 'local-outbox', operationId, task };
|
|
143
173
|
}
|
|
144
174
|
const committed = store.readCommittedOperationResponse(identity);
|
|
175
|
+
let coordinates;
|
|
145
176
|
if (committed) {
|
|
146
177
|
let response;
|
|
147
178
|
try {
|
|
@@ -150,33 +181,49 @@ export function createDurableTaskChecklistMutationRouter(input) {
|
|
|
150
181
|
catch {
|
|
151
182
|
throw new DurableTaskChecklistMutationError('Committed task checklist response is invalid.', 'TASK_CHECKLIST_IDENTITY_CONFLICT', 409);
|
|
152
183
|
}
|
|
184
|
+
const projection = response.authoritative?.checklist;
|
|
185
|
+
const acceptedRevision = String(projection?.entityRevision || '');
|
|
186
|
+
const lifecycleRevision = String(projection?.lifecycleRevision || '');
|
|
153
187
|
if (response.workspaceId !== workspaceId || response.clientId !== clientId
|
|
154
188
|
|| response.operationId !== operationId || response.authoritative?.root?.entityId !== taskId
|
|
155
|
-
||
|
|
156
|
-
||
|
|
157
|
-
|
|
189
|
+
|| projection?.entityId !== taskId
|
|
190
|
+
|| !/^[1-9]\d*$/.test(acceptedRevision)
|
|
191
|
+
|| !/^(0|[1-9]\d*)$/.test(lifecycleRevision)) {
|
|
158
192
|
throw new DurableTaskChecklistMutationError('Operation identity is assigned to a different task checklist.', 'TASK_CHECKLIST_IDENTITY_CONFLICT', 409);
|
|
159
193
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
194
|
+
coordinates = {
|
|
195
|
+
entityRevision: String(BigInt(acceptedRevision) - 1n),
|
|
196
|
+
lifecycleRevision,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
coordinates = store.readEntityRevisionCoordinates({
|
|
201
|
+
tenantId, workspaceId, domain: 'task-checklist', entityId: taskId,
|
|
202
|
+
});
|
|
164
203
|
}
|
|
165
|
-
const coordinates = store.readEntityRevisionCoordinates({
|
|
166
|
-
tenantId, workspaceId, domain: 'task-checklist', entityId: taskId,
|
|
167
|
-
});
|
|
168
204
|
const result = runDurableTaskChecklistReplace({
|
|
169
205
|
store, core: input.core, tenantId, workspaceId, clientId, operationId, taskId, items,
|
|
170
206
|
baseEntityRevision: coordinates.entityRevision, baseLifecycleRevision: coordinates.lifecycleRevision,
|
|
171
207
|
now: acceptedAtIso, leaseExpiresAt: new Date(acceptedAt.getTime() + OPERATION_LEASE_MS).toISOString(),
|
|
172
208
|
actorRef, onPostCommitError: input.onPostCommitError,
|
|
209
|
+
expectedDetailRevision: args.expectedDetailRevision,
|
|
210
|
+
itemUpdateIntent,
|
|
211
|
+
assertPrecondition: args.expectedDetailRevision
|
|
212
|
+
? () => input.core.assertTaskDetailRevisionForUpdate(taskId, args.expectedDetailRevision, workspaceId)
|
|
213
|
+
: undefined,
|
|
173
214
|
});
|
|
174
215
|
if (result.state === 'in_progress')
|
|
175
216
|
throw new DurableTaskChecklistRouterInProgressError(result.retryAt);
|
|
176
217
|
const task = input.core.getTask(taskId, workspaceId);
|
|
177
218
|
if (!task)
|
|
178
219
|
throw new DurableTaskChecklistMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
|
|
179
|
-
return {
|
|
220
|
+
return {
|
|
221
|
+
state: 'committed', route: 'cloud-acceptance', operationId,
|
|
222
|
+
task: {
|
|
223
|
+
...task,
|
|
224
|
+
checklistItems: result.response.authoritative.checklist.payload.items,
|
|
225
|
+
},
|
|
226
|
+
};
|
|
180
227
|
},
|
|
181
228
|
};
|
|
182
229
|
}
|
|
@@ -113,6 +113,9 @@ export function createDurableTaskCommentMutationRouter(input) {
|
|
|
113
113
|
if (!sameCommentRetryIntent(existingPayload.comment, canonical)) {
|
|
114
114
|
throw new DurableTaskCommentMutationError('Operation identity is assigned to a different task comment.', 'TASK_COMMENT_IDENTITY_CONFLICT', 409);
|
|
115
115
|
}
|
|
116
|
+
store.assertOutboxOperationIdentity(existing, {
|
|
117
|
+
domain: 'task-comments', entityId: taskId, mutationKind: 'append',
|
|
118
|
+
});
|
|
116
119
|
const frozenComment = serializeWorkspaceSyncV3TaskCommentsPayload({
|
|
117
120
|
taskId, comments: [existingPayload.comment],
|
|
118
121
|
}).comments[0];
|
|
@@ -51,6 +51,7 @@ export declare function createDurableTaskHttpBulkMutationRouter(input: {
|
|
|
51
51
|
}>, options?: {
|
|
52
52
|
saveSource?: "manual" | "autosave";
|
|
53
53
|
atomicItemFailures?: boolean;
|
|
54
|
+
expectedDetailRevision?: string;
|
|
54
55
|
}): {
|
|
55
56
|
preview: import("../../core/Taskforce.js").BulkUpdateFieldsPreview;
|
|
56
57
|
results: TaskItem[];
|
|
@@ -222,7 +222,12 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
|
|
|
222
222
|
}, { atomicRecovery: true });
|
|
223
223
|
},
|
|
224
224
|
updateFields(updates, options = {}) {
|
|
225
|
-
return input.rootRouter.runBatch('bulk-update-fields', {
|
|
225
|
+
return input.rootRouter.runBatch('bulk-update-fields', {
|
|
226
|
+
updates,
|
|
227
|
+
...(options.expectedDetailRevision
|
|
228
|
+
? { expectedDetailRevision: options.expectedDetailRevision }
|
|
229
|
+
: {}),
|
|
230
|
+
}, (batch) => {
|
|
226
231
|
const preview = input.core.bulkUpdateFieldsPreview(updates, input.workspaceId);
|
|
227
232
|
const results = [];
|
|
228
233
|
const errors = preview.skipped
|
|
@@ -273,14 +278,21 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
|
|
|
273
278
|
&& !(durableAttachmentLinks && key === 'cardCoverAssetId'))))
|
|
274
279
|
: item.fields;
|
|
275
280
|
let updated = input.core.getTask(item.id, input.workspaceId);
|
|
281
|
+
let expectedDetailRevision = options.expectedDetailRevision;
|
|
276
282
|
if (Object.keys(rootFields).length > 0) {
|
|
277
283
|
const child = input.createChildRouter(input.deriveChildOperationId('bulk-update-fields-root', item.index, item.id), () => { });
|
|
278
284
|
updated = child.enabled
|
|
279
|
-
? batch.runChild(() => child.update(item.id, rootFields, options.saveSource || 'manual'))
|
|
280
|
-
:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
285
|
+
? batch.runChild(() => child.update(item.id, rootFields, options.saveSource || 'manual', undefined, expectedDetailRevision))
|
|
286
|
+
: (() => {
|
|
287
|
+
if (expectedDetailRevision) {
|
|
288
|
+
input.core.assertTaskDetailRevisionForUpdate(item.id, expectedDetailRevision, input.workspaceId);
|
|
289
|
+
}
|
|
290
|
+
return input.core.updateTask(item.id, rootFields, input.workspaceId, {
|
|
291
|
+
actorRef: 'user',
|
|
292
|
+
saveSource: options.saveSource || 'manual',
|
|
293
|
+
});
|
|
294
|
+
})();
|
|
295
|
+
expectedDetailRevision = undefined;
|
|
284
296
|
}
|
|
285
297
|
if (durableChecklist && checklist) {
|
|
286
298
|
const currentTask = input.core.getTask(item.id, input.workspaceId) || updated;
|
|
@@ -301,7 +313,12 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
|
|
|
301
313
|
updatedAt: String(unchanged ? existing.updatedAt : existing ? now : source.updatedAt || createdAt),
|
|
302
314
|
};
|
|
303
315
|
});
|
|
304
|
-
updated = batch.runChild(() => checklist.replace({
|
|
316
|
+
updated = batch.runChild(() => checklist.replace({
|
|
317
|
+
taskId: item.id,
|
|
318
|
+
items: normalizedChecklist,
|
|
319
|
+
expectedDetailRevision,
|
|
320
|
+
}).task);
|
|
321
|
+
expectedDetailRevision = undefined;
|
|
305
322
|
}
|
|
306
323
|
if (durableAttachmentLinks && attachmentLinks) {
|
|
307
324
|
updated = batch.runChild(() => attachmentLinks.replace({
|
|
@@ -312,7 +329,9 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
|
|
|
312
329
|
? null
|
|
313
330
|
: String(item.fields.cardCoverAssetId).trim(),
|
|
314
331
|
} : {}),
|
|
332
|
+
expectedDetailRevision,
|
|
315
333
|
}).task);
|
|
334
|
+
expectedDetailRevision = undefined;
|
|
316
335
|
}
|
|
317
336
|
if (updated)
|
|
318
337
|
results.push(updated);
|
|
@@ -327,7 +346,10 @@ export function createDurableTaskHttpBulkMutationRouter(input) {
|
|
|
327
346
|
}
|
|
328
347
|
batch.deferPostCommitNotification(() => input.core.notifyDurableTaskBatchCommitted(input.workspaceId, results.map((task) => task.id)));
|
|
329
348
|
return { preview, results, errors };
|
|
330
|
-
}, {
|
|
349
|
+
}, {
|
|
350
|
+
atomicRecovery: true,
|
|
351
|
+
allowIndependentNestedOwnership: true,
|
|
352
|
+
});
|
|
331
353
|
},
|
|
332
354
|
};
|
|
333
355
|
}
|
|
@@ -3,7 +3,8 @@ import type { TaskRestoreDestination } from '../../shared/taskRestoreDestination
|
|
|
3
3
|
export declare class DurableTaskHttpRootMutationError extends Error {
|
|
4
4
|
readonly code: string;
|
|
5
5
|
readonly statusCode: number;
|
|
6
|
-
|
|
6
|
+
readonly details?: Record<string, unknown> | undefined;
|
|
7
|
+
constructor(message: string, code: string, statusCode: number, details?: Record<string, unknown> | undefined);
|
|
7
8
|
}
|
|
8
9
|
export declare function resolveTaskHttpRootMutationCapability(input: {
|
|
9
10
|
runtimeMode: 'local' | 'cloud';
|
|
@@ -22,8 +23,9 @@ export declare function createDurableTaskHttpRootMutationRouter(input: {
|
|
|
22
23
|
deferPostCommitNotification?: (notify: () => void) => void;
|
|
23
24
|
}): {
|
|
24
25
|
enabled: boolean;
|
|
26
|
+
hasCommittedOperation(): boolean;
|
|
25
27
|
create(candidate: unknown): TaskItem;
|
|
26
|
-
update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed"): TaskItem;
|
|
28
|
+
update(taskIdInput: string, candidate: unknown, saveSource: "manual" | "autosave", activityAction?: "task-updated" | "task-schedule-changed", expectedDetailRevision?: string): TaskItem;
|
|
27
29
|
runBatch<T>(routeInput: string, request: unknown, apply: (context: {
|
|
28
30
|
runChild<R>(mutation: () => R): R;
|
|
29
31
|
deferPostCommitNotification(notify: () => void): void;
|
|
@@ -36,5 +38,5 @@ export declare function createDurableTaskHttpRootMutationRouter(input: {
|
|
|
36
38
|
restore(deletedRecordIdInput: string, restoreDestination?: TaskRestoreDestination): TaskItem;
|
|
37
39
|
delete(taskIdInput: string): DeletedTaskRecord;
|
|
38
40
|
};
|
|
39
|
-
type TaskforceCoreForHttpRootMutation = Pick<import('../../core/Taskforce.js').TaskforceCore, 'getDatabaseAdapter' | 'getTask' | 'listAssignableActors' | 'getDeletedTask' | 'updateTask' | 'hasTaskDeletionMarkerForSync' | 'createTask' | 'listTaskAttachmentLinksForDurableSync' | 'resolveTaskAttachmentLinksForDurableSync' | 'normalizeTaskAttachmentDescriptorsForDurableSync' | 'notifyDurableTaskCreateCommitted' | 'notifyDurableTaskBatchCommitted' | 'notifyDurableTaskMetadataCommitted' | 'notifyDurableTaskLifecycleCommitted' | 'notifyDurableTaskDeleteCommitted' | 'getTaskEventForSync' | 'getEntityEventForSync' | 'lockTaskLifecycleMutationDomain' | 'archiveTask' | 'unarchiveTask' | 'restoreDeletedTask' | 'addTaskStatusEventsForDurableSync' | 'lockTaskRelationshipMutationDomain' | 'listTaskRelationships' | 'getTaskRelationshipForSync' | 'deleteTaskForSync'>;
|
|
41
|
+
type TaskforceCoreForHttpRootMutation = Pick<import('../../core/Taskforce.js').TaskforceCore, 'getDatabaseAdapter' | 'getTask' | 'getTaskDetailRevision' | 'assertTaskDetailRevisionForUpdate' | 'listAssignableActors' | 'getDeletedTask' | 'updateTask' | 'hasTaskDeletionMarkerForSync' | 'createTask' | 'listTaskAttachmentLinksForDurableSync' | 'resolveTaskAttachmentLinksForDurableSync' | 'normalizeTaskAttachmentDescriptorsForDurableSync' | 'notifyDurableTaskCreateCommitted' | 'notifyDurableTaskBatchCommitted' | 'notifyDurableTaskMetadataCommitted' | 'notifyDurableTaskLifecycleCommitted' | 'notifyDurableTaskDeleteCommitted' | 'getTaskEventForSync' | 'getEntityEventForSync' | 'lockTaskLifecycleMutationDomain' | 'archiveTask' | 'unarchiveTask' | 'restoreDeletedTask' | 'addTaskStatusEventsForDurableSync' | 'addTaskCommentEventForDurableSync' | 'lockTaskRelationshipMutationDomain' | 'listTaskRelationships' | 'getTaskRelationshipForSync' | 'deleteTaskForSync'>;
|
|
40
42
|
export {};
|
|
@@ -2,6 +2,7 @@ import { selectDurableTaskMetadataPatch } from '../../core/TaskDurableSyncMutati
|
|
|
2
2
|
import { prepareTaskDeleteForDurableSync } from '../../core/TaskDurableDeleteMutationService.js';
|
|
3
3
|
import { selectTaskCreateActivationInput } from './taskCreateActivation.js';
|
|
4
4
|
import { resolveTaskAttachmentLinksMutationCapability } from './durableTaskAttachmentLinksMutationRouter.js';
|
|
5
|
+
import { areWorkflowRuntimeMutationsFenced, resolveWorkflowRuntimeDurableTransportCapability, } from './durableWorkflowRuntimeMutationRouter.js';
|
|
5
6
|
import { runDurableTaskCreate } from './taskCreateMutationService.js';
|
|
6
7
|
import { runDurableTaskDelete } from './taskDeleteMutationService.js';
|
|
7
8
|
import { runDurableTaskLifecycleMutation } from './taskLifecycleMutationService.js';
|
|
@@ -28,10 +29,12 @@ function requiredText(value, label) {
|
|
|
28
29
|
export class DurableTaskHttpRootMutationError extends Error {
|
|
29
30
|
code;
|
|
30
31
|
statusCode;
|
|
31
|
-
|
|
32
|
+
details;
|
|
33
|
+
constructor(message, code, statusCode, details) {
|
|
32
34
|
super(message);
|
|
33
35
|
this.code = code;
|
|
34
36
|
this.statusCode = statusCode;
|
|
37
|
+
this.details = details;
|
|
35
38
|
this.name = 'DurableTaskHttpRootMutationError';
|
|
36
39
|
}
|
|
37
40
|
}
|
|
@@ -57,6 +60,13 @@ export function createDurableTaskHttpRootMutationRouter(input) {
|
|
|
57
60
|
surface: 'http',
|
|
58
61
|
env: input.env,
|
|
59
62
|
});
|
|
63
|
+
const workflowRuntimeJournalEnabled = resolveWorkflowRuntimeDurableTransportCapability({
|
|
64
|
+
runtimeMode: input.runtimeMode,
|
|
65
|
+
surface: 'http',
|
|
66
|
+
env: input.env,
|
|
67
|
+
});
|
|
68
|
+
const rejectWorkflowRuntimeActivation = workflowRuntimeJournalEnabled
|
|
69
|
+
&& areWorkflowRuntimeMutationsFenced(input.env);
|
|
60
70
|
const store = new WorkspaceSyncDurabilityStore(input.core.getDatabaseAdapter());
|
|
61
71
|
const now = input.now || (() => new Date());
|
|
62
72
|
const notificationMethods = new Set([
|
|
@@ -120,6 +130,11 @@ export function createDurableTaskHttpRootMutationRouter(input) {
|
|
|
120
130
|
rethrowDurableReplayError(error, 'Committed durable task HTTP response is invalid.');
|
|
121
131
|
}
|
|
122
132
|
};
|
|
133
|
+
const detailRevisionPrecondition = (taskId, expectedDetailRevision) => {
|
|
134
|
+
if (!expectedDetailRevision)
|
|
135
|
+
return undefined;
|
|
136
|
+
return () => input.core.assertTaskDetailRevisionForUpdate(taskId, expectedDetailRevision, input.workspaceId);
|
|
137
|
+
};
|
|
123
138
|
const lifecycle = (taskIdInput, mutationKind, payload) => {
|
|
124
139
|
const taskId = requiredText(taskIdInput, 'Task id');
|
|
125
140
|
const operation = context();
|
|
@@ -144,6 +159,12 @@ export function createDurableTaskHttpRootMutationRouter(input) {
|
|
|
144
159
|
};
|
|
145
160
|
return {
|
|
146
161
|
enabled,
|
|
162
|
+
hasCommittedOperation() {
|
|
163
|
+
const operationId = String(input.operationId || '').trim();
|
|
164
|
+
if (!operationId)
|
|
165
|
+
return false;
|
|
166
|
+
return Boolean(store.readCommittedOperationResponse(operationIdentity(operationId)));
|
|
167
|
+
},
|
|
147
168
|
create(candidate) {
|
|
148
169
|
const source = candidate && typeof candidate === 'object' && !Array.isArray(candidate)
|
|
149
170
|
? candidate
|
|
@@ -183,7 +204,7 @@ export function createDurableTaskHttpRootMutationRouter(input) {
|
|
|
183
204
|
throw new DurableTaskHttpRootMutationError('The durable task mutation is already in progress.', 'WORKSPACE_SYNC_OPERATION_IN_PROGRESS', 409);
|
|
184
205
|
return result.response.authoritative.payload;
|
|
185
206
|
},
|
|
186
|
-
update(taskIdInput, candidate, saveSource, activityAction) {
|
|
207
|
+
update(taskIdInput, candidate, saveSource, activityAction, expectedDetailRevision) {
|
|
187
208
|
const taskId = requiredText(taskIdInput, 'Task id');
|
|
188
209
|
if (!candidate || typeof candidate !== 'object' || Array.isArray(candidate)) {
|
|
189
210
|
throw new DurableTaskHttpRootMutationError('Task patch must be an object.', 'DURABLE_TASK_PATCH_INVALID', 400);
|
|
@@ -224,6 +245,10 @@ export function createDurableTaskHttpRootMutationRouter(input) {
|
|
|
224
245
|
now: operation.acceptedAtIso,
|
|
225
246
|
leaseExpiresAt: new Date(operation.acceptedAt.getTime() + OPERATION_LEASE_MS).toISOString(),
|
|
226
247
|
actorRef: input.actorRef,
|
|
248
|
+
includeWorkflowRuntimeJournal: workflowRuntimeJournalEnabled,
|
|
249
|
+
rejectWorkflowRuntimeActivation,
|
|
250
|
+
expectedDetailRevision,
|
|
251
|
+
assertPrecondition: detailRevisionPrecondition(taskId, expectedDetailRevision),
|
|
227
252
|
onPostCommitError: input.onPostCommitError,
|
|
228
253
|
});
|
|
229
254
|
if (result.state === 'in_progress')
|
|
@@ -283,6 +308,8 @@ export function createDurableTaskHttpRootMutationRouter(input) {
|
|
|
283
308
|
actorRef: input.actorRef,
|
|
284
309
|
saveSource,
|
|
285
310
|
activityAction,
|
|
311
|
+
expectedDetailRevision,
|
|
312
|
+
assertPrecondition: detailRevisionPrecondition(taskId, expectedDetailRevision),
|
|
286
313
|
onPostCommitError: input.onPostCommitError,
|
|
287
314
|
});
|
|
288
315
|
if (result.state === 'in_progress')
|
|
@@ -341,6 +368,14 @@ export function createDurableTaskHttpRootMutationRouter(input) {
|
|
|
341
368
|
if (options?.atomicRecovery) {
|
|
342
369
|
const notifications = [];
|
|
343
370
|
const result = input.core.getDatabaseAdapter().transaction(() => {
|
|
371
|
+
// Child durable mutations lock the workspace sequence before
|
|
372
|
+
// touching task rows. Take the same lock first when a batch
|
|
373
|
+
// may combine a legacy root write with durable child owners.
|
|
374
|
+
store.lockWorkspaceSequenceForMutation({
|
|
375
|
+
tenantId: input.tenantId,
|
|
376
|
+
workspaceId: input.workspaceId,
|
|
377
|
+
now: operation.acceptedAtIso,
|
|
378
|
+
});
|
|
344
379
|
const value = apply({
|
|
345
380
|
runChild: (mutation) => input.core.getDatabaseAdapter().transaction(mutation)(),
|
|
346
381
|
deferPostCommitNotification: (notify) => notifications.push(notify),
|
|
@@ -185,6 +185,11 @@ export function createDurableTaxonomyMutationRouter(input) {
|
|
|
185
185
|
if (!sameTaxonomyState(storedPayload.state, canonicalState) || !Array.isArray(storedPayload.taskPatches)) {
|
|
186
186
|
throw new WorkspaceSyncIdempotencyConflictError();
|
|
187
187
|
}
|
|
188
|
+
store.assertOutboxOperationIdentity(existingOutbox, {
|
|
189
|
+
domain: WORKSPACE_SYNC_TAXONOMY_DOMAIN,
|
|
190
|
+
entityId: WORKSPACE_SYNC_TAXONOMY_ENTITY_ID,
|
|
191
|
+
mutationKind: WORKSPACE_SYNC_TAXONOMY_REPLACE_WITH_REMAPS,
|
|
192
|
+
});
|
|
188
193
|
enqueueLocalTaxonomyCompositeReplacement({
|
|
189
194
|
store,
|
|
190
195
|
core: input.core,
|
|
@@ -15,11 +15,22 @@ export declare class DurableWorkflowRuntimeRouterInProgressError extends Error {
|
|
|
15
15
|
readonly statusCode = 409;
|
|
16
16
|
constructor(retryAt: string);
|
|
17
17
|
}
|
|
18
|
+
export declare class DurableWorkflowRuntimeExecutionNotFoundError extends Error {
|
|
19
|
+
readonly code = "execution_not_found";
|
|
20
|
+
readonly statusCode = 404;
|
|
21
|
+
constructor();
|
|
22
|
+
}
|
|
23
|
+
export declare function areWorkflowRuntimeMutationsFenced(env?: NodeJS.ProcessEnv): boolean;
|
|
18
24
|
export declare function resolveWorkflowRuntimeMutationCapability(input: {
|
|
19
25
|
runtimeMode: 'local' | 'cloud';
|
|
20
26
|
surface: DurableWorkflowRuntimeSurface;
|
|
21
27
|
env?: NodeJS.ProcessEnv;
|
|
22
28
|
}): boolean;
|
|
29
|
+
export declare function resolveWorkflowRuntimeDurableTransportCapability(input: {
|
|
30
|
+
runtimeMode: 'local' | 'cloud';
|
|
31
|
+
surface: DurableWorkflowRuntimeSurface;
|
|
32
|
+
env?: NodeJS.ProcessEnv;
|
|
33
|
+
}): boolean;
|
|
23
34
|
export declare function createDurableWorkflowRuntimeMutationRouter(input: {
|
|
24
35
|
core: DurableWorkflowRuntimeMutationRouterCore;
|
|
25
36
|
runtimeMode: 'local' | 'cloud';
|
|
@@ -7,6 +7,7 @@ import { WorkspaceSyncDurabilityStore, } from './syncDurabilityStore.js';
|
|
|
7
7
|
import { runDurableWorkflowRuntimeMutation, } from './workflowRuntimeMutationService.js';
|
|
8
8
|
import { validateWorkflowRuntimeAuthoritativeResult, validateWorkflowRuntimeMutationCommand, } from './workflowRuntimeSync.js';
|
|
9
9
|
import { WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_SELECTOR } from './workspaceSyncV3WorkflowWireContract.js';
|
|
10
|
+
import { WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_SELECTOR, } from './workspaceSyncV3WorkflowTaskCoverWireContract.js';
|
|
10
11
|
const OPERATION_LEASE_MS = 30_000;
|
|
11
12
|
export class DurableWorkflowRuntimeRouterDisabledError extends Error {
|
|
12
13
|
code = 'WORKSPACE_SYNC_V3_WORKFLOW_RUNTIME_ROUTER_DISABLED';
|
|
@@ -26,31 +27,55 @@ export class DurableWorkflowRuntimeRouterInProgressError extends Error {
|
|
|
26
27
|
this.name = 'DurableWorkflowRuntimeRouterInProgressError';
|
|
27
28
|
}
|
|
28
29
|
}
|
|
30
|
+
export class DurableWorkflowRuntimeExecutionNotFoundError extends Error {
|
|
31
|
+
code = 'execution_not_found';
|
|
32
|
+
statusCode = 404;
|
|
33
|
+
constructor() {
|
|
34
|
+
super('Workflow execution not found.');
|
|
35
|
+
this.name = 'DurableWorkflowRuntimeExecutionNotFoundError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function areWorkflowRuntimeMutationsFenced(env = process.env) {
|
|
39
|
+
return String(env.TASKFORCE_SYNC_V3_WORKFLOW_RUNTIME_MUTATIONS_FENCED || '')
|
|
40
|
+
.trim()
|
|
41
|
+
.toLowerCase() === 'true';
|
|
42
|
+
}
|
|
29
43
|
function required(value, label) {
|
|
30
44
|
const normalized = String(value || '').trim();
|
|
31
45
|
if (!normalized)
|
|
32
46
|
throw new Error(`${label} is required.`);
|
|
33
47
|
return normalized;
|
|
34
48
|
}
|
|
35
|
-
|
|
49
|
+
const WORKFLOW_RUNTIME_COVERAGE_SELECTORS = [
|
|
50
|
+
WORKSPACE_SYNC_V3_WORKFLOW_COVERAGE_SELECTOR,
|
|
51
|
+
WORKSPACE_SYNC_V3_WORKFLOW_TASK_COVER_COVERAGE_SELECTOR,
|
|
52
|
+
];
|
|
53
|
+
function resolveSelectedWorkflowCoverage(env) {
|
|
36
54
|
try {
|
|
37
55
|
const coverage = resolveRequestedCombinedFeedCoverage(env);
|
|
38
|
-
return coverage.coverageProfileId ===
|
|
39
|
-
&& coverage.coverageVersion ===
|
|
40
|
-
&& coverage.coverageDigest ===
|
|
56
|
+
return WORKFLOW_RUNTIME_COVERAGE_SELECTORS.find((candidate) => (coverage.coverageProfileId === candidate.coverageProfileId
|
|
57
|
+
&& coverage.coverageVersion === candidate.coverageVersion
|
|
58
|
+
&& coverage.coverageDigest === candidate.coverageDigest)) || null;
|
|
41
59
|
}
|
|
42
60
|
catch {
|
|
43
|
-
return
|
|
61
|
+
return null;
|
|
44
62
|
}
|
|
45
63
|
}
|
|
46
64
|
export function resolveWorkflowRuntimeMutationCapability(input) {
|
|
47
65
|
const env = input.env || process.env;
|
|
48
|
-
if (
|
|
66
|
+
if (areWorkflowRuntimeMutationsFenced(env))
|
|
67
|
+
return false;
|
|
68
|
+
return resolveWorkflowRuntimeDurableTransportCapability(input);
|
|
69
|
+
}
|
|
70
|
+
export function resolveWorkflowRuntimeDurableTransportCapability(input) {
|
|
71
|
+
const env = input.env || process.env;
|
|
72
|
+
const coverage = resolveSelectedWorkflowCoverage(env);
|
|
73
|
+
if (!coverage)
|
|
49
74
|
return false;
|
|
50
75
|
const capability = resolveCombinedFeedCapability({
|
|
51
76
|
runtimeMode: input.runtimeMode,
|
|
52
77
|
env,
|
|
53
|
-
coverage
|
|
78
|
+
coverage,
|
|
54
79
|
}).combinedFeed;
|
|
55
80
|
return capability.activationReady;
|
|
56
81
|
}
|
|
@@ -62,7 +87,11 @@ function parseExistingLocalCommand(store, identity) {
|
|
|
62
87
|
throw new Error('Operation identity is assigned to another local mutation.');
|
|
63
88
|
}
|
|
64
89
|
try {
|
|
65
|
-
|
|
90
|
+
const command = validateWorkflowRuntimeMutationCommand(JSON.parse(existing.payloadJson));
|
|
91
|
+
store.assertOutboxOperationIdentity(existing, {
|
|
92
|
+
domain: 'workflow-execution', entityId: command.executionId, mutationKind: command.kind,
|
|
93
|
+
});
|
|
94
|
+
return command;
|
|
66
95
|
}
|
|
67
96
|
catch {
|
|
68
97
|
throw new Error('Captured workflow runtime command is invalid.');
|
|
@@ -254,7 +283,7 @@ export function createDurableWorkflowRuntimeMutationRouter(input) {
|
|
|
254
283
|
const workflowStore = new WorkflowStore(input.core.getDatabaseAdapter(), tenantId);
|
|
255
284
|
const snapshot = workflowStore.getExecutionStateSnapshot(workspaceId, args.executionId);
|
|
256
285
|
if (!snapshot)
|
|
257
|
-
throw new
|
|
286
|
+
throw new DurableWorkflowRuntimeExecutionNotFoundError();
|
|
258
287
|
const committed = readCommittedCloudResponse();
|
|
259
288
|
if (committed) {
|
|
260
289
|
const event = snapshot.events.find((candidate) => candidate.idempotencyKey === operationId);
|
|
@@ -307,7 +336,7 @@ export function createDurableWorkflowRuntimeMutationRouter(input) {
|
|
|
307
336
|
const workflowStore = new WorkflowStore(input.core.getDatabaseAdapter(), tenantId);
|
|
308
337
|
const snapshot = workflowStore.getExecutionStateSnapshot(workspaceId, args.executionId);
|
|
309
338
|
if (!snapshot)
|
|
310
|
-
throw new
|
|
339
|
+
throw new DurableWorkflowRuntimeExecutionNotFoundError();
|
|
311
340
|
const committed = readCommittedCloudResponse();
|
|
312
341
|
if (committed) {
|
|
313
342
|
const completedEvent = snapshot.events.find((event) => event.idempotencyKey === `${operationId}:step-completed`);
|
|
@@ -7,6 +7,7 @@ import { enqueueLocalWorkstreamMutation, } from './localWorkstreamOutboxService.
|
|
|
7
7
|
import { isWorkspaceSyncV3PlanningActivationEnabled } from './planningActivation.js';
|
|
8
8
|
import { serializeEntityActivityForSync } from './taskActivityJournal.js';
|
|
9
9
|
import { WorkspaceSyncDurabilityStore, WorkspaceSyncIdempotencyConflictError } from './syncDurabilityStore.js';
|
|
10
|
+
import { readDurableOperationReplay } from './durableOperationReplay.js';
|
|
10
11
|
import { buildWorkstreamActivityEventId } from './workstreamActivityIdentity.js';
|
|
11
12
|
const OPERATION_LEASE_MS = 30_000;
|
|
12
13
|
export class DurableWorkstreamMutationRouterDisabledError extends Error {
|
|
@@ -85,6 +86,9 @@ export function createDurableWorkstreamMutationRouter(input) {
|
|
|
85
86
|
if (persistedOutbox.domain !== 'workstream' || persistedOutbox.entityId !== workstreamId) {
|
|
86
87
|
throw new WorkspaceSyncIdempotencyConflictError();
|
|
87
88
|
}
|
|
89
|
+
store.assertOutboxOperationIdentity(persistedOutbox, {
|
|
90
|
+
domain: 'workstream', entityId: workstreamId, mutationKind: persistedOutbox.mutationKind,
|
|
91
|
+
});
|
|
88
92
|
return {
|
|
89
93
|
revisions: {
|
|
90
94
|
entityRevision: persistedOutbox.baseEntityRevision,
|
|
@@ -99,18 +103,22 @@ export function createDurableWorkstreamMutationRouter(input) {
|
|
|
99
103
|
if (operationState?.status === 'committed') {
|
|
100
104
|
if (!operationState.responseJson)
|
|
101
105
|
throw new Error('Committed operation is missing its response.');
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
const parsed = JSON.parse(operationState.responseJson);
|
|
107
|
+
const lifecycleMutation = parsed.authoritative.mutationKind === 'archive'
|
|
108
|
+
|| parsed.authoritative.mutationKind === 'unarchive';
|
|
109
|
+
const replay = readDurableOperationReplay({
|
|
110
|
+
responseJson: operationState.responseJson,
|
|
111
|
+
operationId,
|
|
112
|
+
domain: 'workstream',
|
|
113
|
+
entityId: workstreamId,
|
|
114
|
+
mutationKind: parsed.authoritative.mutationKind,
|
|
115
|
+
revisionMode: lifecycleMutation ? 'both' : 'metadata',
|
|
116
|
+
});
|
|
117
|
+
const response = replay.response;
|
|
108
118
|
return {
|
|
109
119
|
revisions: {
|
|
110
|
-
entityRevision:
|
|
111
|
-
lifecycleRevision:
|
|
112
|
-
? String(BigInt(response.authoritative.lifecycleRevision) - 1n)
|
|
113
|
-
: response.authoritative.lifecycleRevision,
|
|
120
|
+
entityRevision: replay.baseEntityRevision,
|
|
121
|
+
lifecycleRevision: replay.baseLifecycleRevision,
|
|
114
122
|
},
|
|
115
123
|
persistedOutbox: null,
|
|
116
124
|
committedResponse: response,
|