@taskforcehq/taskforce 0.3.329 → 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 +290 -45
- package/dist/components/features/AiProfilesModule.js +3 -5
- package/dist/components/features/TaskSettings.js +70 -14
- package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
- package/dist/components/features/TaskforceAgentsModule.js +586 -116
- 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/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
- package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
- package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
- package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
- package/dist/components/views/StandaloneLayout.js +27 -26
- 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 +48 -1
- package/dist/core/McpTokenService.d.ts +23 -1
- package/dist/core/McpTokenService.js +93 -10
- 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 +32 -0
- package/dist/core/Taskforce.js +125 -4
- package/dist/core/types.d.ts +8 -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/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/useSyncOrchestrator.d.ts +3 -0
- package/dist/hooks/useSyncOrchestrator.js +111 -2
- package/dist/hooks/useTaskData.d.ts +31 -1
- package/dist/hooks/useTaskData.js +29 -7
- package/dist/hooks/useTaskMutations.d.ts +3 -1
- package/dist/hooks/useTaskMutations.js +46 -12
- package/dist/hooks/useTaskforce.d.ts +2 -0
- package/dist/hooks/useTaskforce.js +11 -2
- package/dist/mcp/clientRegistry.d.ts +2 -2
- package/dist/mcp/clientRegistry.js +1 -1
- package/dist/mcp/documentAssetRegistrar.js +9 -6
- 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 +384 -97
- package/dist/mcp/taskPlanningRegistrar.js +23 -4
- 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 +415 -0
- package/dist/runtime/appGates.d.ts +2 -1
- package/dist/runtime/appGates.js +7 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +108 -11
- package/dist/server/localDatabaseIdentity.js +4 -1
- package/dist/server/localServiceLease.js +2 -1
- package/dist/server/localServiceSessions.d.ts +14 -17
- package/dist/server/localServiceSessions.js +308 -94
- package/dist/server/localWorkspaceSyncServerRuntime.js +12 -14
- package/dist/server/routes/admin.d.ts +4 -0
- package/dist/server/routes/admin.js +112 -3
- package/dist/server/routes/agents.d.ts +7 -0
- package/dist/server/routes/agents.js +277 -24
- package/dist/server/routes/billing.js +5 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
- 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 +136 -40
- package/dist/server/routes/modelConnections.d.ts +24 -0
- package/dist/server/routes/modelConnections.js +205 -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 +5 -1
- package/dist/server/routes/syncPushRoutes.d.ts +1 -0
- package/dist/server/routes/syncPushRoutes.js +1 -0
- package/dist/server/routes/syncV3FeedRoutes.js +10 -1
- package/dist/server/routes/syncV3OperationRoutes.js +35 -9
- package/dist/server/routes/tasks.js +21 -2
- package/dist/server/routes/workflows.js +9 -1
- package/dist/server/routes.js +59 -0
- package/dist/services/codexAppServerModelGateway.d.ts +54 -5
- package/dist/services/codexAppServerModelGateway.js +246 -21
- 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 +1 -1
- package/dist/services/taskforceAgentMcpBridge.js +7 -24
- 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 -9
- package/dist/shared/taskforceAgentModels.js +7 -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 +4 -0
- package/dist/storage/postgresAdapter.js +11 -0
- package/dist/storage/postgresWorker.js +9 -1
- package/dist/storage/postgresWorkerProtocol.d.ts +1 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
- 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/workspaceSyncEngineLifecyclePolicy.js +6 -6
- 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/workspaceSyncEngineRuntime.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
- package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
- 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 +15 -0
- package/dist/sync/syncService.js +83 -18
- package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
- package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
- package/dist/sync/v3/combinedFeedCapability.js +4 -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.js +3 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
- package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
- 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/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/localTaskStatusOutboxService.d.ts +8 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +219 -12
- package/dist/sync/v3/syncDurabilityStore.d.ts +34 -0
- package/dist/sync/v3/syncDurabilityStore.js +168 -2
- package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
- package/dist/sync/v3/taskChecklistMutationService.js +44 -1
- package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
- package/dist/sync/v3/taskStatusMutationService.js +119 -3
- package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
- package/dist/sync/v3/workflowAssignmentSync.js +27 -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/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -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/workspaceRepair.d.ts +5 -2
- package/dist/sync/workspaceRepair.js +161 -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/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
- package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-BTM6nIg_.js} +1 -1
- package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-DabEG8L4.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-Coa8yVGM.js} +1 -1
- package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-BB0qhdix.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
- package/dist/ui/assets/{PlanningModule-B5DWQOGz.js → PlanningModule-pRPjR7v5.js} +1 -1
- package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-D86pZSSl.js} +1 -1
- package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-BVIkU9yT.js} +1 -1
- 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-DEr5di_r.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-D9Lpw-j4.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/taskEvents.d.ts +2 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
- package/dist/utils/workspaceSyncPresentation.js +23 -17
- package/package.json +22 -4
- package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
- package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
- package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
- package/dist/ui/assets/index-I5zhdtgt.js +0 -7
- package/dist/ui/assets/index-VRFsx3wz.css +0 -1
|
@@ -22,6 +22,37 @@ export class DurableTaskChecklistMutationError extends Error {
|
|
|
22
22
|
this.name = 'DurableTaskChecklistMutationError';
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
+
export function validateTaskChecklistItemUpdateIntent(value) {
|
|
26
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
27
|
+
throw new DurableTaskChecklistMutationError('Task checklist item update intent is invalid.', 'TASK_CHECKLIST_INVALID', 400);
|
|
28
|
+
}
|
|
29
|
+
const source = value;
|
|
30
|
+
const patch = source.patch;
|
|
31
|
+
if (source.kind !== 'item-update'
|
|
32
|
+
|| Object.keys(source).some((key) => key !== 'kind' && key !== 'itemId' && key !== 'patch')
|
|
33
|
+
|| typeof source.itemId !== 'string' || !source.itemId.trim()
|
|
34
|
+
|| !patch || typeof patch !== 'object' || Array.isArray(patch)) {
|
|
35
|
+
throw new DurableTaskChecklistMutationError('Task checklist item update intent is invalid.', 'TASK_CHECKLIST_INVALID', 400);
|
|
36
|
+
}
|
|
37
|
+
const patchSource = patch;
|
|
38
|
+
if (Object.keys(patchSource).some((key) => key !== 'text' && key !== 'done' && key !== 'order')
|
|
39
|
+
|| Object.keys(patchSource).length === 0
|
|
40
|
+
|| (patchSource.text !== undefined && (typeof patchSource.text !== 'string' || !patchSource.text.trim()))
|
|
41
|
+
|| (patchSource.done !== undefined && typeof patchSource.done !== 'boolean')
|
|
42
|
+
|| (patchSource.order !== undefined
|
|
43
|
+
&& (!Number.isInteger(patchSource.order) || Number(patchSource.order) < 0))) {
|
|
44
|
+
throw new DurableTaskChecklistMutationError('Task checklist item update intent is invalid.', 'TASK_CHECKLIST_INVALID', 400);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
kind: 'item-update',
|
|
48
|
+
itemId: source.itemId.trim(),
|
|
49
|
+
patch: {
|
|
50
|
+
...(patchSource.text !== undefined ? { text: patchSource.text.trim() } : {}),
|
|
51
|
+
...(patchSource.done !== undefined ? { done: patchSource.done } : {}),
|
|
52
|
+
...(patchSource.order !== undefined ? { order: Number(patchSource.order) } : {}),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
25
56
|
function canonicalItems(taskId, items) {
|
|
26
57
|
try {
|
|
27
58
|
return serializeWorkspaceSyncV3TaskChecklistPayload({ taskId, items }).items;
|
|
@@ -46,6 +77,18 @@ function revision(revisions, domain) {
|
|
|
46
77
|
}
|
|
47
78
|
export function runDurableTaskChecklistReplace(input) {
|
|
48
79
|
const items = canonicalItems(input.taskId, input.items);
|
|
80
|
+
const itemUpdateIntent = input.itemUpdateIntent
|
|
81
|
+
? validateTaskChecklistItemUpdateIntent(input.itemUpdateIntent)
|
|
82
|
+
: undefined;
|
|
83
|
+
if (itemUpdateIntent) {
|
|
84
|
+
const target = items.find((item) => item.id === itemUpdateIntent.itemId);
|
|
85
|
+
if (!target
|
|
86
|
+
|| (itemUpdateIntent.patch.text !== undefined && target.title !== itemUpdateIntent.patch.text)
|
|
87
|
+
|| (itemUpdateIntent.patch.done !== undefined && target.isCompleted !== itemUpdateIntent.patch.done)
|
|
88
|
+
|| (itemUpdateIntent.patch.order !== undefined && target.order !== itemUpdateIntent.patch.order)) {
|
|
89
|
+
throw new DurableTaskChecklistMutationError('Task checklist item update intent does not match the replacement aggregate.', 'TASK_CHECKLIST_INVALID', 400);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
49
92
|
const identity = {
|
|
50
93
|
tenantId: input.tenantId, workspaceId: input.workspaceId, clientId: input.clientId, operationId: input.operationId,
|
|
51
94
|
};
|
|
@@ -56,7 +99,7 @@ export function runDurableTaskChecklistReplace(input) {
|
|
|
56
99
|
domain: 'task-checklist', entityId: input.taskId, mutationKind: 'replace',
|
|
57
100
|
baseEntityRevision: String(input.baseEntityRevision),
|
|
58
101
|
baseLifecycleRevision: String(input.baseLifecycleRevision),
|
|
59
|
-
items,
|
|
102
|
+
...(itemUpdateIntent ? { itemUpdateIntent } : { items }),
|
|
60
103
|
...(input.originActorRef ? { originActorRef: input.originActorRef } : {}),
|
|
61
104
|
...(input.expectedDetailRevision
|
|
62
105
|
? { expectedDetailRevision: input.expectedDetailRevision }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EntityEvent, TaskEvent } from '../../core/Taskforce.js';
|
|
1
|
+
import type { Comment, EntityEvent, TaskEvent } from '../../core/Taskforce.js';
|
|
2
2
|
import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
|
|
3
3
|
import type { TaskActor } from '../../types.js';
|
|
4
4
|
import { type DurableTaskStatusMutationCore } from '../../core/TaskDurableStatusMutationService.js';
|
|
@@ -6,6 +6,7 @@ import { serializeTaskForSync } from '../taskSyncPayload.js';
|
|
|
6
6
|
import type { WorkflowAssignmentSyncRecord } from '../../storage/workflowStore.js';
|
|
7
7
|
import { type WorkspaceSyncActivityRevision } from './taskActivityJournal.js';
|
|
8
8
|
import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
|
|
9
|
+
import { type WorkspaceSyncV3TaskCommentsPayload } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
9
10
|
export interface DurableTaskStatusServiceCore extends DurableTaskStatusMutationCore {
|
|
10
11
|
notifyDurableTaskLifecycleCommitted(workspaceId: string, taskId: string): void;
|
|
11
12
|
getTaskEventForSync(input: {
|
|
@@ -19,6 +20,14 @@ export interface DurableTaskStatusServiceCore extends DurableTaskStatusMutationC
|
|
|
19
20
|
}): EntityEvent | null;
|
|
20
21
|
listAssignableActors(workspaceId: string): TaskActor[];
|
|
21
22
|
getDatabaseAdapter(): DatabaseAdapter;
|
|
23
|
+
addTaskCommentEventForDurableSync(event: {
|
|
24
|
+
taskId: string;
|
|
25
|
+
workspaceId: string;
|
|
26
|
+
actor: string;
|
|
27
|
+
eventId: string;
|
|
28
|
+
createdAt: string;
|
|
29
|
+
comment: Comment;
|
|
30
|
+
}): void;
|
|
22
31
|
}
|
|
23
32
|
export type DurableTaskStatusResponse = {
|
|
24
33
|
success: true;
|
|
@@ -45,7 +54,25 @@ export type DurableTaskStatusResponse = {
|
|
|
45
54
|
dependentActivities?: EntityEvent[];
|
|
46
55
|
dependentActivityRevisions?: WorkspaceSyncActivityRevision[];
|
|
47
56
|
workflowAssignment?: WorkflowAssignmentSyncRecord;
|
|
57
|
+
reviewHandoff?: {
|
|
58
|
+
comments: {
|
|
59
|
+
domain: 'task-comments';
|
|
60
|
+
entityId: string;
|
|
61
|
+
mutationKind: 'append';
|
|
62
|
+
sequence: string;
|
|
63
|
+
entityRevision: string;
|
|
64
|
+
lifecycleRevision: string;
|
|
65
|
+
payload: WorkspaceSyncV3TaskCommentsPayload;
|
|
66
|
+
};
|
|
67
|
+
activity: TaskEvent;
|
|
68
|
+
activityRevision: WorkspaceSyncActivityRevision;
|
|
69
|
+
};
|
|
48
70
|
};
|
|
71
|
+
export declare class WorkflowRuntimeActivationFencedError extends Error {
|
|
72
|
+
readonly code = "WORKFLOW_RUNTIME_MUTATIONS_FENCED";
|
|
73
|
+
readonly statusCode = 503;
|
|
74
|
+
constructor();
|
|
75
|
+
}
|
|
49
76
|
export declare function runDurableTaskStatusMutation(input: {
|
|
50
77
|
store: WorkspaceSyncDurabilityStore;
|
|
51
78
|
core: DurableTaskStatusServiceCore;
|
|
@@ -64,6 +91,7 @@ export declare function runDurableTaskStatusMutation(input: {
|
|
|
64
91
|
resolveActorRef?: () => string;
|
|
65
92
|
originActorRef?: string;
|
|
66
93
|
includeWorkflowRuntimeJournal?: boolean;
|
|
94
|
+
rejectWorkflowRuntimeActivation?: boolean;
|
|
67
95
|
expectedDetailRevision?: string;
|
|
68
96
|
assertPrecondition?: () => void;
|
|
69
97
|
onPostCommitError?: (error: unknown) => void;
|
|
@@ -8,7 +8,27 @@ import { asWorkspaceSyncActivityRevision, buildEntityActivityJournalEntry, build
|
|
|
8
8
|
import { fingerprintWorkspaceSyncPayload, WORKSPACE_SYNC_CONTRACT_VERSION, } from './syncDurabilityStore.js';
|
|
9
9
|
import { resolveDeferredMutationActorRef } from './workspaceSyncV3OriginActor.js';
|
|
10
10
|
import { buildWorkflowRuntimeEventId } from './workflowRuntimeOperationIdentity.js';
|
|
11
|
+
import { buildTaskCommentActivityEventId } from './taskCommentActivityIdentity.js';
|
|
12
|
+
import { serializeWorkspaceSyncV3TaskCommentAppendPayload, serializeWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
11
13
|
import { fingerprintWorkflowRuntimePayload, serializeWorkflowExecutionEventSyncPayload, serializeWorkflowExecutionRootSyncPayload, serializeWorkflowPublishedDefinitionSyncPayload, } from './workflowRuntimeSync.js';
|
|
14
|
+
export class WorkflowRuntimeActivationFencedError extends Error {
|
|
15
|
+
code = 'WORKFLOW_RUNTIME_MUTATIONS_FENCED';
|
|
16
|
+
statusCode = 503;
|
|
17
|
+
constructor() {
|
|
18
|
+
super('Workflow execution changes are temporarily paused.');
|
|
19
|
+
this.name = 'WorkflowRuntimeActivationFencedError';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function nextTaskUpdatedAt(current, requested) {
|
|
23
|
+
const currentMs = Date.parse(current);
|
|
24
|
+
const requestedMs = Date.parse(requested);
|
|
25
|
+
if (!Number.isFinite(requestedMs) || new Date(requestedMs).toISOString() !== requested) {
|
|
26
|
+
throw new Error('Task status operation timestamp is invalid.');
|
|
27
|
+
}
|
|
28
|
+
return Number.isFinite(currentMs) && currentMs >= requestedMs
|
|
29
|
+
? new Date(currentMs + 1).toISOString()
|
|
30
|
+
: requested;
|
|
31
|
+
}
|
|
12
32
|
export function runDurableTaskStatusMutation(input) {
|
|
13
33
|
const operationPayload = normalizeTaskStatusOperationWithWorkflowAssignment(input.payload);
|
|
14
34
|
const payload = validateDurableTaskStatusMutationPayload({
|
|
@@ -48,10 +68,24 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
48
68
|
});
|
|
49
69
|
const membershipRemovedEventId = `${activityEventId}:workstream-removed`;
|
|
50
70
|
const membershipAddedEventId = `${activityEventId}:workstream-added`;
|
|
71
|
+
const requestedReviewComment = operationPayload.reviewHandoff?.comment || null;
|
|
72
|
+
let reviewComment = null;
|
|
73
|
+
const reviewCommentActivityEventId = requestedReviewComment ? buildTaskCommentActivityEventId({
|
|
74
|
+
workspaceId: input.workspaceId,
|
|
75
|
+
clientId: input.clientId,
|
|
76
|
+
operationId: input.operationId,
|
|
77
|
+
taskId: input.taskId,
|
|
78
|
+
commentId: requestedReviewComment.id,
|
|
79
|
+
}) : null;
|
|
51
80
|
const workflowStore = new WorkflowStore(input.core.getDatabaseAdapter(), input.tenantId);
|
|
52
81
|
const workflowActivationService = new WorkflowTaskActivationService(workflowStore, (workspaceId) => input.core.listAssignableActors(workspaceId));
|
|
53
82
|
const pendingAssignment = operationPayload.workflowAssignment
|
|
54
83
|
|| workflowStore.getAssignmentForTaskSync(input.workspaceId, input.taskId);
|
|
84
|
+
if (input.rejectWorkflowRuntimeActivation === true
|
|
85
|
+
&& payload.status === 'in-progress'
|
|
86
|
+
&& pendingAssignment?.execution.status === 'pending') {
|
|
87
|
+
throw new WorkflowRuntimeActivationFencedError();
|
|
88
|
+
}
|
|
55
89
|
const workflowStartEventId = buildWorkflowRuntimeEventId({
|
|
56
90
|
workspaceId: input.workspaceId,
|
|
57
91
|
clientId: input.clientId,
|
|
@@ -95,6 +129,16 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
95
129
|
throw new Error('Task status activity was not committed.');
|
|
96
130
|
return activity;
|
|
97
131
|
};
|
|
132
|
+
const readReviewCommentActivity = () => {
|
|
133
|
+
const activity = input.core.getTaskEventForSync({
|
|
134
|
+
workspaceId: input.workspaceId,
|
|
135
|
+
taskId: input.taskId,
|
|
136
|
+
eventId: reviewCommentActivityEventId,
|
|
137
|
+
});
|
|
138
|
+
if (!activity)
|
|
139
|
+
throw new Error('Review handoff comment activity was not committed.');
|
|
140
|
+
return activity;
|
|
141
|
+
};
|
|
98
142
|
const workflowAssignmentAfterMutation = () => {
|
|
99
143
|
const assignment = workflowStore.getAssignmentForTaskSync(input.workspaceId, input.taskId);
|
|
100
144
|
if (!assignment || assignment.execution.id !== pendingAssignment?.execution.id) {
|
|
@@ -158,7 +202,22 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
158
202
|
reopenAssigneeOwned: (result) => result.assigneeOwned,
|
|
159
203
|
buildCanonicalFingerprint: (result) => (fingerprintWorkspaceSyncPayload(serializeTaskForSync(result.task))),
|
|
160
204
|
buildAuthoritativePayload: (result) => serializeTaskForSync(result.task),
|
|
161
|
-
}, {
|
|
205
|
+
}, ...(requestedReviewComment ? [{
|
|
206
|
+
domain: 'task-comments', entityId: input.taskId, mutationKind: 'append', revisionKind: 'metadata',
|
|
207
|
+
baseEntityRevision: 0, baseLifecycleRevision: 0, baseRevisionPolicy: 'current',
|
|
208
|
+
buildCanonicalFingerprint: (result) => fingerprintWorkspaceSyncPayload(serializeWorkspaceSyncV3TaskCommentsPayload({
|
|
209
|
+
taskId: result.task.id,
|
|
210
|
+
comments: result.task.comments || [],
|
|
211
|
+
})),
|
|
212
|
+
buildAuthoritativePayload: (result) => (serializeWorkspaceSyncV3TaskCommentAppendPayload({
|
|
213
|
+
taskId: result.task.id,
|
|
214
|
+
comment: reviewComment,
|
|
215
|
+
commentsAfterAppend: result.task.comments || [],
|
|
216
|
+
})),
|
|
217
|
+
}, buildTaskActivityJournalEntry({
|
|
218
|
+
eventId: reviewCommentActivityEventId,
|
|
219
|
+
readEvent: readReviewCommentActivity,
|
|
220
|
+
})] : []), {
|
|
162
221
|
...buildTaskActivityJournalEntry({ eventId: activityEventId, readEvent: readActivity }),
|
|
163
222
|
include: (result) => !result.noOp,
|
|
164
223
|
}, {
|
|
@@ -208,7 +267,7 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
208
267
|
})
|
|
209
268
|
: null;
|
|
210
269
|
const actorRef = resolveDeferredMutationActorRef(input);
|
|
211
|
-
|
|
270
|
+
let result = applyTaskStatusMutationForDurableSync({
|
|
212
271
|
core: input.core,
|
|
213
272
|
workspaceId: input.workspaceId,
|
|
214
273
|
taskId: input.taskId,
|
|
@@ -224,6 +283,42 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
224
283
|
actorRef,
|
|
225
284
|
taskEventId: activityEventId,
|
|
226
285
|
});
|
|
286
|
+
if (requestedReviewComment) {
|
|
287
|
+
const authoritativeReviewComment = {
|
|
288
|
+
...requestedReviewComment,
|
|
289
|
+
author: actorRef,
|
|
290
|
+
submittedAuthor: actorRef,
|
|
291
|
+
timestamp: input.now,
|
|
292
|
+
};
|
|
293
|
+
reviewComment = authoritativeReviewComment;
|
|
294
|
+
const existingComments = serializeWorkspaceSyncV3TaskCommentsPayload({
|
|
295
|
+
taskId: result.task.id,
|
|
296
|
+
comments: result.task.comments || [],
|
|
297
|
+
}).comments;
|
|
298
|
+
const collision = existingComments.find((comment) => comment.id === authoritativeReviewComment.id);
|
|
299
|
+
if (collision) {
|
|
300
|
+
throw new Error(`Review handoff comment identity conflict: ${authoritativeReviewComment.id}.`);
|
|
301
|
+
}
|
|
302
|
+
const updatedAt = nextTaskUpdatedAt(String(result.task.updatedAt || result.task.createdAt), input.now);
|
|
303
|
+
const updated = input.core.updateTask(result.task.id, { comments: [...existingComments, authoritativeReviewComment] }, input.workspaceId, {
|
|
304
|
+
persistBackup: false,
|
|
305
|
+
emitRealtime: false,
|
|
306
|
+
skipTaskEvents: true,
|
|
307
|
+
syncUpdatedAt: updatedAt,
|
|
308
|
+
allowV3OwnedMetadataWrite: true,
|
|
309
|
+
});
|
|
310
|
+
if (!updated)
|
|
311
|
+
throw new Error('Review handoff task disappeared during comment persistence.');
|
|
312
|
+
input.core.addTaskCommentEventForDurableSync({
|
|
313
|
+
taskId: updated.id,
|
|
314
|
+
workspaceId: input.workspaceId,
|
|
315
|
+
actor: actorRef,
|
|
316
|
+
eventId: reviewCommentActivityEventId,
|
|
317
|
+
createdAt: String(updated.updatedAt),
|
|
318
|
+
comment: authoritativeReviewComment,
|
|
319
|
+
});
|
|
320
|
+
result = { ...result, task: updated };
|
|
321
|
+
}
|
|
227
322
|
if (activation) {
|
|
228
323
|
workflowActivationService.start({
|
|
229
324
|
workspaceId: input.workspaceId,
|
|
@@ -261,6 +356,9 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
261
356
|
throw new Error('Dependent task status activity was not committed.');
|
|
262
357
|
return event;
|
|
263
358
|
});
|
|
359
|
+
const reviewCommentsRevision = reviewComment ? revisions.find((revision) => (revision.domain === 'task-comments' && revision.entityId === input.taskId)) : null;
|
|
360
|
+
const reviewActivityRevisionValue = reviewComment ? revisions.find((revision) => (revision.domain === 'entity-event' && revision.entityId === reviewCommentActivityEventId)) : null;
|
|
361
|
+
const reviewActivity = reviewComment ? readReviewCommentActivity() : null;
|
|
264
362
|
return {
|
|
265
363
|
success: true,
|
|
266
364
|
contractVersion: WORKSPACE_SYNC_CONTRACT_VERSION,
|
|
@@ -285,6 +383,24 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
285
383
|
activityRevision,
|
|
286
384
|
...(dependentActivities.length > 0 ? { dependentActivities } : {}),
|
|
287
385
|
...(dependentActivityRevisions.length > 0 ? { dependentActivityRevisions } : {}),
|
|
386
|
+
...(reviewComment && reviewCommentsRevision && reviewActivityRevisionValue && reviewActivity ? {
|
|
387
|
+
reviewHandoff: {
|
|
388
|
+
comments: {
|
|
389
|
+
domain: 'task-comments',
|
|
390
|
+
entityId: result.task.id,
|
|
391
|
+
mutationKind: 'append',
|
|
392
|
+
sequence: reviewCommentsRevision.sequence,
|
|
393
|
+
entityRevision: reviewCommentsRevision.entityRevision,
|
|
394
|
+
lifecycleRevision: reviewCommentsRevision.lifecycleRevision,
|
|
395
|
+
payload: serializeWorkspaceSyncV3TaskCommentsPayload({
|
|
396
|
+
taskId: result.task.id,
|
|
397
|
+
comments: result.task.comments || [],
|
|
398
|
+
}),
|
|
399
|
+
},
|
|
400
|
+
activity: reviewActivity,
|
|
401
|
+
activityRevision: asWorkspaceSyncActivityRevision(reviewActivityRevisionValue),
|
|
402
|
+
},
|
|
403
|
+
} : {}),
|
|
288
404
|
...(workflowStore.getAssignmentForTaskSync(input.workspaceId, result.task.id)
|
|
289
405
|
? { workflowAssignment: workflowStore.getAssignmentForTaskSync(input.workspaceId, result.task.id) }
|
|
290
406
|
: {}),
|
|
@@ -292,7 +408,7 @@ export function runDurableTaskStatusMutation(input) {
|
|
|
292
408
|
},
|
|
293
409
|
});
|
|
294
410
|
const response = JSON.parse(accepted.responseJson);
|
|
295
|
-
if (response.activity) {
|
|
411
|
+
if (response.activity || response.reviewHandoff) {
|
|
296
412
|
try {
|
|
297
413
|
input.core.notifyDurableTaskLifecycleCommitted(input.workspaceId, input.taskId);
|
|
298
414
|
}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import type { WorkflowAssignmentSyncRecord, WorkflowExecutionEventRecord, WorkflowExecutionRecord, WorkflowStepRecord, WorkflowTemplateRecord, WorkflowVersionRecord } from '../../storage/workflowStore.js';
|
|
2
|
+
import type { Comment } from '../../core/Taskforce.js';
|
|
2
3
|
import { type DurableTaskStatusMutationPayload } from '../../core/TaskDurableStatusMutationService.js';
|
|
4
|
+
export type TaskStatusReviewHandoff = {
|
|
5
|
+
comment: Pick<Comment, 'id' | 'author' | 'submittedAuthor' | 'text'>;
|
|
6
|
+
};
|
|
3
7
|
export type TaskStatusOperationWithWorkflowAssignment = DurableTaskStatusMutationPayload & {
|
|
4
8
|
workflowAssignment?: WorkflowAssignmentSyncRecord;
|
|
5
9
|
expectedDetailRevision?: string;
|
|
10
|
+
reviewHandoff?: TaskStatusReviewHandoff;
|
|
6
11
|
};
|
|
7
12
|
export declare class WorkflowAssignmentSyncError extends Error {
|
|
8
13
|
readonly code = "WORKFLOW_ASSIGNMENT_SYNC_INVALID";
|
|
@@ -203,11 +203,38 @@ export function normalizeTaskStatusOperationWithWorkflowAssignment(raw) {
|
|
|
203
203
|
}
|
|
204
204
|
originActor = { kind: 'ai-profile', profileId };
|
|
205
205
|
}
|
|
206
|
+
let reviewHandoff;
|
|
207
|
+
if (source.reviewHandoff !== undefined) {
|
|
208
|
+
if (status.status !== 'review') {
|
|
209
|
+
throw new WorkflowAssignmentSyncError('reviewHandoff is valid only when status is review.');
|
|
210
|
+
}
|
|
211
|
+
const handoff = object(source.reviewHandoff, 'reviewHandoff');
|
|
212
|
+
if (Object.keys(handoff).join(',') !== 'comment') {
|
|
213
|
+
throw new WorkflowAssignmentSyncError('reviewHandoff must contain exactly comment.');
|
|
214
|
+
}
|
|
215
|
+
const comment = object(handoff.comment, 'reviewHandoff.comment');
|
|
216
|
+
if (Object.keys(comment).sort().join(',') !== 'author,id,submittedAuthor,text') {
|
|
217
|
+
throw new WorkflowAssignmentSyncError('reviewHandoff.comment must contain exactly id, author, submittedAuthor, and text.');
|
|
218
|
+
}
|
|
219
|
+
const author = text(comment.author, 'reviewHandoff.comment.author');
|
|
220
|
+
const submittedAuthor = text(comment.submittedAuthor, 'reviewHandoff.comment.submittedAuthor');
|
|
221
|
+
const commentText = text(comment.text, 'reviewHandoff.comment.text');
|
|
222
|
+
if (author !== submittedAuthor) {
|
|
223
|
+
throw new WorkflowAssignmentSyncError('reviewHandoff comment authorship is invalid.');
|
|
224
|
+
}
|
|
225
|
+
reviewHandoff = { comment: {
|
|
226
|
+
id: text(comment.id, 'reviewHandoff.comment.id'),
|
|
227
|
+
author,
|
|
228
|
+
submittedAuthor,
|
|
229
|
+
text: commentText,
|
|
230
|
+
} };
|
|
231
|
+
}
|
|
206
232
|
return {
|
|
207
233
|
...status,
|
|
208
234
|
...(source.workflowAssignment === undefined
|
|
209
235
|
? {}
|
|
210
236
|
: { workflowAssignment: normalizeWorkflowAssignmentSyncRecord(source.workflowAssignment) }),
|
|
237
|
+
...(reviewHandoff ? { reviewHandoff } : {}),
|
|
211
238
|
...(originActor ? { originActor } : {}),
|
|
212
239
|
...(typeof source.expectedDetailRevision === 'string' && source.expectedDetailRevision.trim()
|
|
213
240
|
? { expectedDetailRevision: source.expectedDetailRevision.trim() }
|
|
@@ -31,7 +31,7 @@ export class WorkspaceSyncJournalReader {
|
|
|
31
31
|
CAST(lifecycle_revision AS TEXT) AS lifecycle_revision, content_sha256,
|
|
32
32
|
CAST(size_bytes AS TEXT) AS size_bytes, payload_json, occurred_at FROM workspace_sync_journal
|
|
33
33
|
WHERE tenant_id = ? AND workspace_id = ? AND sequence > ? AND sequence <= ?
|
|
34
|
-
ORDER BY sequence ASC LIMIT ?`).all(input.tenantId, input.workspaceId, sequence(input.afterSequence), sequence(input.throughSequence), Math.max(1, Math.min(10_101, Math.floor(input.limit))));
|
|
34
|
+
ORDER BY workspace_sync_journal.sequence ASC LIMIT ?`).all(input.tenantId, input.workspaceId, sequence(input.afterSequence), sequence(input.throughSequence), Math.max(1, Math.min(10_101, Math.floor(input.limit))));
|
|
35
35
|
return rows.map((row) => ({
|
|
36
36
|
sequence: sequence(row.sequence), contractVersion: Number(row.contract_version), clientId: String(row.client_id || ''),
|
|
37
37
|
operationId: String(row.operation_id || ''), domain: String(row.domain || ''),
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
|
|
2
|
+
export declare const WORKSPACE_SYNC_OPERATION_RETENTION_DAYS = 90;
|
|
3
|
+
export declare const WORKSPACE_SYNC_OPERATION_RETENTION_INTERVAL_MS: number;
|
|
4
|
+
export declare const WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE = 100;
|
|
5
|
+
export declare const WORKSPACE_SYNC_OPERATION_RETENTION_WORKSPACE_LIMIT = 100;
|
|
6
|
+
export interface WorkspaceSyncOperationRetentionResult {
|
|
7
|
+
deletedOutbox: number;
|
|
8
|
+
deletedResults: number;
|
|
9
|
+
remainingEligible: number;
|
|
10
|
+
workspacesProcessed: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function pruneRetainedWorkspaceSyncOperations(input: {
|
|
13
|
+
db: DatabaseAdapter;
|
|
14
|
+
tenantId: string;
|
|
15
|
+
now?: Date;
|
|
16
|
+
}): WorkspaceSyncOperationRetentionResult;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
|
|
2
|
+
export const WORKSPACE_SYNC_OPERATION_RETENTION_DAYS = 90;
|
|
3
|
+
export const WORKSPACE_SYNC_OPERATION_RETENTION_INTERVAL_MS = 24 * 60 * 60_000;
|
|
4
|
+
export const WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE = 100;
|
|
5
|
+
export const WORKSPACE_SYNC_OPERATION_RETENTION_WORKSPACE_LIMIT = 100;
|
|
6
|
+
export function pruneRetainedWorkspaceSyncOperations(input) {
|
|
7
|
+
const now = input.now || new Date();
|
|
8
|
+
const cutoff = new Date(now.getTime() - WORKSPACE_SYNC_OPERATION_RETENTION_DAYS * 24 * 60 * 60_000).toISOString();
|
|
9
|
+
const workspaceRows = input.db.prepare(`
|
|
10
|
+
SELECT eligible.workspace_id
|
|
11
|
+
FROM (
|
|
12
|
+
SELECT candidate.workspace_id, candidate.updated_at AS terminal_at
|
|
13
|
+
FROM workspace_sync_outbox AS candidate
|
|
14
|
+
WHERE candidate.tenant_id = ?
|
|
15
|
+
AND candidate.status IN ('accepted', 'superseded')
|
|
16
|
+
AND candidate.updated_at < ?
|
|
17
|
+
AND NOT EXISTS (
|
|
18
|
+
SELECT 1
|
|
19
|
+
FROM workspace_sync_outbox AS replay
|
|
20
|
+
WHERE replay.tenant_id = candidate.tenant_id
|
|
21
|
+
AND replay.workspace_id = candidate.workspace_id
|
|
22
|
+
AND replay.replay_of_client_id = candidate.client_id
|
|
23
|
+
AND replay.replay_of_operation_id = candidate.operation_id
|
|
24
|
+
)
|
|
25
|
+
UNION ALL
|
|
26
|
+
SELECT workspace_id, updated_at AS terminal_at
|
|
27
|
+
FROM workspace_sync_operation_results
|
|
28
|
+
WHERE tenant_id = ? AND status = 'committed' AND updated_at < ?
|
|
29
|
+
) AS eligible
|
|
30
|
+
GROUP BY eligible.workspace_id
|
|
31
|
+
ORDER BY MIN(eligible.terminal_at), eligible.workspace_id
|
|
32
|
+
LIMIT ?
|
|
33
|
+
`).all(input.tenantId, cutoff, input.tenantId, cutoff, WORKSPACE_SYNC_OPERATION_RETENTION_WORKSPACE_LIMIT);
|
|
34
|
+
const store = new WorkspaceSyncDurabilityStore(input.db);
|
|
35
|
+
let deletedOutbox = 0;
|
|
36
|
+
let deletedResults = 0;
|
|
37
|
+
for (const row of workspaceRows) {
|
|
38
|
+
const workspaceId = String(row.workspace_id || '').trim();
|
|
39
|
+
if (!workspaceId)
|
|
40
|
+
continue;
|
|
41
|
+
const outboxResult = store.pruneTerminalOutboxOperations({
|
|
42
|
+
tenantId: input.tenantId,
|
|
43
|
+
workspaceId,
|
|
44
|
+
terminalBefore: cutoff,
|
|
45
|
+
limit: WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE,
|
|
46
|
+
});
|
|
47
|
+
deletedOutbox += outboxResult.deleted;
|
|
48
|
+
const result = store.pruneCommittedOperationResults({
|
|
49
|
+
tenantId: input.tenantId,
|
|
50
|
+
workspaceId,
|
|
51
|
+
terminalBefore: cutoff,
|
|
52
|
+
limit: WORKSPACE_SYNC_OPERATION_RETENTION_BATCH_SIZE,
|
|
53
|
+
});
|
|
54
|
+
deletedResults += result.deleted;
|
|
55
|
+
}
|
|
56
|
+
const remaining = input.db.prepare(`
|
|
57
|
+
SELECT (
|
|
58
|
+
SELECT COUNT(*)
|
|
59
|
+
FROM workspace_sync_outbox AS candidate
|
|
60
|
+
WHERE candidate.tenant_id = ?
|
|
61
|
+
AND candidate.status IN ('accepted', 'superseded')
|
|
62
|
+
AND candidate.updated_at < ?
|
|
63
|
+
AND NOT EXISTS (
|
|
64
|
+
SELECT 1
|
|
65
|
+
FROM workspace_sync_outbox AS replay
|
|
66
|
+
WHERE replay.tenant_id = candidate.tenant_id
|
|
67
|
+
AND replay.workspace_id = candidate.workspace_id
|
|
68
|
+
AND replay.replay_of_client_id = candidate.client_id
|
|
69
|
+
AND replay.replay_of_operation_id = candidate.operation_id
|
|
70
|
+
)
|
|
71
|
+
) + (
|
|
72
|
+
SELECT COUNT(*)
|
|
73
|
+
FROM workspace_sync_operation_results
|
|
74
|
+
WHERE tenant_id = ? AND status = 'committed' AND updated_at < ?
|
|
75
|
+
) AS count
|
|
76
|
+
`).get(input.tenantId, cutoff, input.tenantId, cutoff);
|
|
77
|
+
return {
|
|
78
|
+
deletedOutbox,
|
|
79
|
+
deletedResults,
|
|
80
|
+
remainingEligible: Number(remaining?.count || 0),
|
|
81
|
+
workspacesProcessed: workspaceRows.length,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
@@ -46,6 +46,7 @@ export type WorkspaceSyncV3CloudOperationContext = {
|
|
|
46
46
|
/** @deprecated Prefer resolveOriginActorRef; retained for create callers. */
|
|
47
47
|
resolveTaskCreateActorRef?: (originActor: NonNullable<WorkspaceSyncV3TaskCreateEnvelope['operation']['payload']['originActor']>) => string;
|
|
48
48
|
onPostCommitError?: (error: unknown) => void;
|
|
49
|
+
includeWorkflowRuntimeJournal?: boolean;
|
|
49
50
|
};
|
|
50
51
|
export type WorkspaceSyncV3CloudOperationHandler = {
|
|
51
52
|
key: string;
|
|
@@ -197,6 +197,7 @@ export function createWorkspaceSyncV3CloudOperationHandlers() {
|
|
|
197
197
|
taskId: operation.entityId,
|
|
198
198
|
payload,
|
|
199
199
|
expectedDetailRevision,
|
|
200
|
+
includeWorkflowRuntimeJournal: context.includeWorkflowRuntimeJournal,
|
|
200
201
|
assertPrecondition: expectedDetailRevision && context.core.assertTaskDetailRevisionForUpdate
|
|
201
202
|
? () => context.core.assertTaskDetailRevisionForUpdate(operation.entityId, expectedDetailRevision, context.workspaceId)
|
|
202
203
|
: undefined,
|
|
@@ -237,10 +238,16 @@ export function createWorkspaceSyncV3CloudOperationHandlers() {
|
|
|
237
238
|
supports: (envelope) => envelope.operation.domain === 'task-checklist' && envelope.operation.mutationKind === 'replace',
|
|
238
239
|
apply: (envelope, context) => {
|
|
239
240
|
const operation = envelope.operation;
|
|
241
|
+
const { originActor, expectedDetailRevision, itemUpdateIntent, items } = operation.payload;
|
|
240
242
|
return runDurableTaskChecklistReplace({
|
|
241
|
-
...withDeferredOriginActor(context,
|
|
243
|
+
...withDeferredOriginActor(context, originActor),
|
|
242
244
|
taskId: operation.entityId,
|
|
243
|
-
items
|
|
245
|
+
items,
|
|
246
|
+
expectedDetailRevision,
|
|
247
|
+
itemUpdateIntent,
|
|
248
|
+
assertPrecondition: expectedDetailRevision && context.core.assertTaskDetailRevisionForUpdate
|
|
249
|
+
? () => context.core.assertTaskDetailRevisionForUpdate(operation.entityId, expectedDetailRevision, context.workspaceId)
|
|
250
|
+
: undefined,
|
|
244
251
|
baseEntityRevision: operation.baseEntityRevision,
|
|
245
252
|
baseLifecycleRevision: operation.baseLifecycleRevision,
|
|
246
253
|
});
|
|
@@ -6,6 +6,7 @@ export declare function prepareWorkspaceSyncV3CombinedRepairSnapshot(input: {
|
|
|
6
6
|
now?: string;
|
|
7
7
|
nestedCoverage?: boolean;
|
|
8
8
|
workflowCoverage?: boolean;
|
|
9
|
+
workflowTaskCoverCoverage?: boolean;
|
|
9
10
|
planningOrderCoverage?: boolean;
|
|
10
11
|
taskCoverCoverage?: boolean;
|
|
11
12
|
coveredLegacyWritesFenced?: boolean;
|
|
@@ -42,6 +43,12 @@ export declare function prepareWorkspaceSyncV3TaskCoverRepairSnapshot(input: {
|
|
|
42
43
|
now?: string;
|
|
43
44
|
coveredLegacyWritesFenced?: boolean;
|
|
44
45
|
}): ReturnType<typeof prepareWorkspaceSyncV3CombinedRepairSnapshot>;
|
|
46
|
+
export declare function prepareWorkspaceSyncV3WorkflowTaskCoverRepairSnapshot(input: {
|
|
47
|
+
core: TaskforceCore;
|
|
48
|
+
workspaceId: string;
|
|
49
|
+
now?: string;
|
|
50
|
+
coveredLegacyWritesFenced?: boolean;
|
|
51
|
+
}): ReturnType<typeof prepareWorkspaceSyncV3CombinedRepairSnapshot>;
|
|
45
52
|
export declare function ensureWorkspaceSyncV3CombinedRepairBaselines(input: {
|
|
46
53
|
core: TaskforceCore;
|
|
47
54
|
workspaceId: string;
|