@taskforcehq/taskforce 0.3.329 → 0.3.332
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- 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/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
- 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 +15 -3
- package/dist/components/features/planning/planningMetadata.d.ts +10 -0
- package/dist/components/features/planning/planningMetadata.js +8 -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 +62 -27
- package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
- package/dist/components/views/panels/PlanningDrawer.js +12 -8
- 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 +55 -1
- package/dist/core/McpTokenService.d.ts +25 -1
- package/dist/core/McpTokenService.js +106 -15
- 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 +43 -3
- package/dist/core/Taskforce.js +158 -7
- package/dist/core/types.d.ts +9 -0
- package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
- package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
- 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 +11 -0
- package/dist/mcp/httpProtocolRouting.js +22 -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 +408 -102
- package/dist/mcp/taskPlanningRegistrar.js +25 -6
- package/dist/mcp/toolProfiles.d.ts +2 -0
- package/dist/mcp/toolProfiles.js +11 -0
- package/dist/mcp/toolRegistry.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +9 -8
- 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/buildInfo.d.ts +1 -0
- package/dist/server/buildInfo.js +5 -1
- package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
- package/dist/server/cloudMcpCapacityTelemetry.js +221 -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 +25 -19
- package/dist/server/routes/admin.d.ts +4 -0
- package/dist/server/routes/admin.js +126 -5
- 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 +22 -0
- package/dist/server/routes/shared.js +298 -182
- 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/service/localServiceCli.d.ts +2 -2
- package/dist/service/localServiceCli.js +4 -3
- 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 +139 -0
- package/dist/services/executorPhaseAIssuerCore.js +402 -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 +2 -2
- package/dist/services/taskforceAgentMcpBridge.js +42 -29
- 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 +14 -1
- package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
- package/dist/storage/postgresRequestDiagnostics.js +15 -2
- package/dist/storage/postgresWorker.js +20 -2
- package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
- package/dist/storage/workflowStore.d.ts +2 -0
- package/dist/storage/workflowStore.js +39 -2
- package/dist/sync/cloudSyncApi.js +4 -2
- package/dist/sync/collaborationSyncState.js +5 -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/localWorkspaceSyncRunner.d.ts +3 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -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 +31 -0
- package/dist/sync/syncApplyHandlers.d.ts +3 -0
- package/dist/sync/syncApplyHandlers.js +81 -15
- 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 +18 -7
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
- 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/localOutboxRecoveryPreparationService.js +8 -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/localTaskCreateOutboxService.d.ts +3 -1
- package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
- package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
- package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
- package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
- package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
- package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
- package/dist/sync/v3/syncDurabilityStore.js +202 -8
- 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/workflowRuntimeMutationService.d.ts +5 -0
- package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
- 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/workspaceSyncV3CombinedLocalApply.js +25 -3
- 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/workspaceSyncV3Feed.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
- 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/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
- 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-CDMPtnbC.js +1 -0
- package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
- package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
- package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
- package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
- package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
- package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
- package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
- package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
- package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
- package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
- package/dist/ui/assets/index-DSQINwt9.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 +24 -4
- package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
- package/dist/ui/assets/PlanningModule-B5DWQOGz.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
|
@@ -11,6 +11,7 @@ import { WorkspaceSyncJournalReader } from './workspaceSyncJournalReader.js';
|
|
|
11
11
|
import { isLegacyEntityEventAdoptionIdentity, LEGACY_ENTITY_EVENT_ADOPTION_MAX_PAYLOAD_BYTES, } from './entityEventLegacyAdoptionContract.js';
|
|
12
12
|
import { validateWorkspaceSyncV3EntityEventPayload } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
13
13
|
import { fingerprintWorkspaceSyncPayload } from './workspaceSyncPayloadFingerprint.js';
|
|
14
|
+
import { assertDurableOperationFingerprint, assertDurableOperationIdentity, DurableOperationReplayIdentityConflictError, } from './durableOperationReplay.js';
|
|
14
15
|
export { canonicalWorkspaceSyncJson } from './canonicalWorkspaceSyncJson.js';
|
|
15
16
|
export { fingerprintWorkspaceSyncPayload } from './workspaceSyncPayloadFingerprint.js';
|
|
16
17
|
export const WORKSPACE_SYNC_CONTRACT_VERSION = 3;
|
|
@@ -26,6 +27,7 @@ const TASK_AGGREGATE_SUCCESSOR_MUTATIONS = new Map([
|
|
|
26
27
|
const TASK_ROOT_SUCCESSOR_MUTATIONS = new Set([
|
|
27
28
|
'metadata-update', 'set-status', 'archive', 'unarchive', 'complete', 'reopen',
|
|
28
29
|
]);
|
|
30
|
+
const TASK_TERMINAL_SUCCESSOR_MUTATIONS = new Set(['delete']);
|
|
29
31
|
const TASK_CREATE_RECOVERY_ERROR_CODES = new Set([
|
|
30
32
|
'TASK_CREATE_ID_CONFLICT',
|
|
31
33
|
'WORKSPACE_SYNC_REVISION_CONFLICT',
|
|
@@ -794,12 +796,137 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
794
796
|
payload_json, payload_fingerprint, canonical_intent_json, status, attempt_count,
|
|
795
797
|
initial_not_found_attempt_count,
|
|
796
798
|
CAST(enqueue_sequence AS TEXT) AS enqueue_sequence,
|
|
797
|
-
rebase_before_first_attempt, lease_owner, lease_expires_at
|
|
799
|
+
rebase_before_first_attempt, lease_owner, lease_expires_at,
|
|
800
|
+
last_error_code
|
|
798
801
|
FROM workspace_sync_outbox
|
|
799
802
|
WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
|
|
800
803
|
`).get(...operationParams(identity));
|
|
801
804
|
return row ? this.mapOutboxRow(row) : null;
|
|
802
805
|
}
|
|
806
|
+
assertOutboxOperationIdentity(record, expected) {
|
|
807
|
+
assertDurableOperationIdentity({
|
|
808
|
+
operationId: record.operationId,
|
|
809
|
+
domain: record.domain,
|
|
810
|
+
entityId: record.entityId,
|
|
811
|
+
mutationKind: record.mutationKind,
|
|
812
|
+
payloadFingerprint: record.payloadFingerprint,
|
|
813
|
+
}, {
|
|
814
|
+
operationId: record.operationId,
|
|
815
|
+
domain: expected.domain,
|
|
816
|
+
entityId: expected.entityId,
|
|
817
|
+
mutationKind: expected.mutationKind,
|
|
818
|
+
payloadFingerprint: expected.payloadFingerprint || record.payloadFingerprint,
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
readOutboxOperationLookup(identity) {
|
|
822
|
+
const row = this.db.prepare(`
|
|
823
|
+
SELECT status, authoritative_response_json, created_at,
|
|
824
|
+
mutation_kind, payload_fingerprint, domain, entity_id
|
|
825
|
+
FROM workspace_sync_outbox
|
|
826
|
+
WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
|
|
827
|
+
LIMIT 1
|
|
828
|
+
`).get(...operationParams(identity));
|
|
829
|
+
if (!row)
|
|
830
|
+
return null;
|
|
831
|
+
return {
|
|
832
|
+
...identity,
|
|
833
|
+
status: requireText(row.status, 'Outbox status'),
|
|
834
|
+
createdAt: requireIsoTimestamp(row.created_at, 'Outbox creation time'),
|
|
835
|
+
domain: requireText(row.domain, 'Outbox domain'),
|
|
836
|
+
entityId: requireText(row.entity_id, 'Outbox entity id'),
|
|
837
|
+
mutationKind: requireText(row.mutation_kind, 'Outbox mutation kind'),
|
|
838
|
+
payloadFingerprint: requireText(row.payload_fingerprint, 'Outbox payload fingerprint'),
|
|
839
|
+
authoritativeResponseJson: row.authoritative_response_json == null
|
|
840
|
+
? null
|
|
841
|
+
: requireText(row.authoritative_response_json, 'Outbox authoritative response'),
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
pruneTerminalOutboxOperations(input) {
|
|
845
|
+
const tenantId = requireText(input.tenantId, 'Tenant id');
|
|
846
|
+
const workspaceId = requireText(input.workspaceId, 'Workspace id');
|
|
847
|
+
const terminalBefore = requireIsoTimestamp(input.terminalBefore, 'Operation retention cutoff');
|
|
848
|
+
const limit = Math.max(1, Math.min(1_000, Math.floor(input.limit ?? 100)));
|
|
849
|
+
const eligibility = `
|
|
850
|
+
candidate.tenant_id = ? AND candidate.workspace_id = ?
|
|
851
|
+
AND candidate.status IN ('accepted', 'superseded')
|
|
852
|
+
AND candidate.updated_at < ?
|
|
853
|
+
AND NOT EXISTS (
|
|
854
|
+
SELECT 1
|
|
855
|
+
FROM workspace_sync_outbox AS replay
|
|
856
|
+
WHERE replay.tenant_id = candidate.tenant_id
|
|
857
|
+
AND replay.workspace_id = candidate.workspace_id
|
|
858
|
+
AND replay.replay_of_client_id = candidate.client_id
|
|
859
|
+
AND replay.replay_of_operation_id = candidate.operation_id
|
|
860
|
+
)
|
|
861
|
+
`;
|
|
862
|
+
return this.db.transaction(() => {
|
|
863
|
+
const candidates = this.db.prepare(`
|
|
864
|
+
SELECT candidate.client_id, candidate.operation_id
|
|
865
|
+
FROM workspace_sync_outbox AS candidate
|
|
866
|
+
WHERE ${eligibility}
|
|
867
|
+
ORDER BY candidate.updated_at, candidate.client_id, candidate.operation_id
|
|
868
|
+
LIMIT ?
|
|
869
|
+
`).all(tenantId, workspaceId, terminalBefore, limit);
|
|
870
|
+
let deleted = 0;
|
|
871
|
+
for (const candidate of candidates) {
|
|
872
|
+
const clientId = requireText(candidate.client_id, 'Retention client id');
|
|
873
|
+
const operationId = requireText(candidate.operation_id, 'Retention operation id');
|
|
874
|
+
const result = this.db.prepare(`
|
|
875
|
+
DELETE FROM workspace_sync_outbox AS candidate
|
|
876
|
+
WHERE ${eligibility}
|
|
877
|
+
AND candidate.client_id = ? AND candidate.operation_id = ?
|
|
878
|
+
`).run(tenantId, workspaceId, terminalBefore, clientId, operationId);
|
|
879
|
+
if (Number(result.changes || 0) !== 1)
|
|
880
|
+
continue;
|
|
881
|
+
this.db.prepare(`
|
|
882
|
+
DELETE FROM workspace_sync_outbox_targets
|
|
883
|
+
WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
|
|
884
|
+
`).run(tenantId, workspaceId, clientId, operationId);
|
|
885
|
+
deleted += 1;
|
|
886
|
+
}
|
|
887
|
+
const remaining = this.db.prepare(`
|
|
888
|
+
SELECT COUNT(*) AS count
|
|
889
|
+
FROM workspace_sync_outbox AS candidate
|
|
890
|
+
WHERE ${eligibility}
|
|
891
|
+
`).get(tenantId, workspaceId, terminalBefore);
|
|
892
|
+
return { deleted, remainingEligible: Number(remaining?.count || 0) };
|
|
893
|
+
})();
|
|
894
|
+
}
|
|
895
|
+
pruneCommittedOperationResults(input) {
|
|
896
|
+
const tenantId = requireText(input.tenantId, 'Tenant id');
|
|
897
|
+
const workspaceId = requireText(input.workspaceId, 'Workspace id');
|
|
898
|
+
const terminalBefore = requireIsoTimestamp(input.terminalBefore, 'Operation retention cutoff');
|
|
899
|
+
const limit = Math.max(1, Math.min(1_000, Math.floor(input.limit ?? 100)));
|
|
900
|
+
return this.db.transaction(() => {
|
|
901
|
+
const candidates = this.db.prepare(`
|
|
902
|
+
SELECT client_id, operation_id
|
|
903
|
+
FROM workspace_sync_operation_results
|
|
904
|
+
WHERE tenant_id = ? AND workspace_id = ?
|
|
905
|
+
AND status = 'committed' AND updated_at < ?
|
|
906
|
+
ORDER BY updated_at, client_id, operation_id
|
|
907
|
+
LIMIT ?
|
|
908
|
+
`).all(tenantId, workspaceId, terminalBefore, limit);
|
|
909
|
+
let deleted = 0;
|
|
910
|
+
for (const candidate of candidates) {
|
|
911
|
+
const clientId = requireText(candidate.client_id, 'Retention client id');
|
|
912
|
+
const operationId = requireText(candidate.operation_id, 'Retention operation id');
|
|
913
|
+
const result = this.db.prepare(`
|
|
914
|
+
DELETE FROM workspace_sync_operation_results
|
|
915
|
+
WHERE tenant_id = ? AND workspace_id = ?
|
|
916
|
+
AND client_id = ? AND operation_id = ?
|
|
917
|
+
AND status = 'committed' AND updated_at < ?
|
|
918
|
+
`).run(tenantId, workspaceId, clientId, operationId, terminalBefore);
|
|
919
|
+
deleted += Number(result.changes || 0);
|
|
920
|
+
}
|
|
921
|
+
const remaining = this.db.prepare(`
|
|
922
|
+
SELECT COUNT(*) AS count
|
|
923
|
+
FROM workspace_sync_operation_results
|
|
924
|
+
WHERE tenant_id = ? AND workspace_id = ?
|
|
925
|
+
AND status = 'committed' AND updated_at < ?
|
|
926
|
+
`).get(tenantId, workspaceId, terminalBefore);
|
|
927
|
+
return { deleted, remainingEligible: Number(remaining?.count || 0) };
|
|
928
|
+
})();
|
|
929
|
+
}
|
|
803
930
|
readV3DispatchSettlementEvidence(identity) {
|
|
804
931
|
const row = this.db.prepare(`
|
|
805
932
|
SELECT outbox.status, outbox.authoritative_response_json,
|
|
@@ -1218,6 +1345,17 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
1218
1345
|
}
|
|
1219
1346
|
}
|
|
1220
1347
|
}
|
|
1348
|
+
else if (input.replayPolicy === 'authoritative-workflow-runtime') {
|
|
1349
|
+
if (selected.length !== 1) {
|
|
1350
|
+
throw new Error('Workflow runtime recovery has intersecting intent that requires semantic history reconciliation.');
|
|
1351
|
+
}
|
|
1352
|
+
const candidate = selected[0];
|
|
1353
|
+
if (candidate.domain !== 'workflow-execution'
|
|
1354
|
+
|| candidate.mutation_kind !== 'complete-step'
|
|
1355
|
+
|| candidate.last_error_code !== 'WORKFLOW_RUNTIME_SEMANTIC_REPLAY_REQUIRED') {
|
|
1356
|
+
throw new Error('Workflow runtime recovery requires an exact authoritative semantic replay conflict.');
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1221
1359
|
this.db.prepare(`
|
|
1222
1360
|
INSERT INTO workspace_sync_outbox_recoveries (
|
|
1223
1361
|
tenant_id, workspace_id, recovery_batch_id,
|
|
@@ -1486,6 +1624,11 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
1486
1624
|
}
|
|
1487
1625
|
}
|
|
1488
1626
|
const sources = recoverySources.filter((source) => {
|
|
1627
|
+
if (source.domain === 'workflow-execution'
|
|
1628
|
+
&& source.mutation_kind === 'complete-step'
|
|
1629
|
+
&& source.last_error_code === 'WORKFLOW_RUNTIME_SEMANTIC_REPLAY_REQUIRED') {
|
|
1630
|
+
return false;
|
|
1631
|
+
}
|
|
1489
1632
|
if (source.domain === 'task-comments' && source.mutation_kind === 'append') {
|
|
1490
1633
|
return !this.isTaskCommentAppendRecoveryIntentSatisfied(tenantId, workspaceId, source);
|
|
1491
1634
|
}
|
|
@@ -2457,9 +2600,21 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
2457
2600
|
})()
|
|
2458
2601
|
: null;
|
|
2459
2602
|
const taskAggregateRootTarget = additionalTargets[0];
|
|
2603
|
+
const queueableTaskReviewHandoff = domain === 'task'
|
|
2604
|
+
&& mutationKind === 'set-status'
|
|
2605
|
+
&& additionalTargets.length === 1
|
|
2606
|
+
&& taskAggregateRootTarget.domain === 'task-comments'
|
|
2607
|
+
&& taskAggregateRootTarget.entityId === entityId
|
|
2608
|
+
&& taskAggregateRootTarget.mutationKind === 'append';
|
|
2460
2609
|
const queueableTaskRoot = domain === 'task'
|
|
2461
2610
|
&& TASK_ROOT_SUCCESSOR_MUTATIONS.has(mutationKind)
|
|
2462
|
-
&& additionalTargets.length === 0;
|
|
2611
|
+
&& (additionalTargets.length === 0 || queueableTaskReviewHandoff);
|
|
2612
|
+
const queueableTaskDelete = domain === 'task'
|
|
2613
|
+
&& TASK_TERMINAL_SUCCESSOR_MUTATIONS.has(mutationKind)
|
|
2614
|
+
&& additionalTargets.length === 0
|
|
2615
|
+
&& ownsTaskMetadata
|
|
2616
|
+
&& ownsTaskLifecycle
|
|
2617
|
+
&& !ownsTaskAssignee;
|
|
2463
2618
|
const queueableTaskAggregate = Boolean(TASK_AGGREGATE_SUCCESSOR_MUTATIONS.get(domain)?.has(mutationKind))
|
|
2464
2619
|
&& ((domain === 'task-comments' && mutationKind === 'reconcile' && additionalTargets.length === 0)
|
|
2465
2620
|
|| (additionalTargets.length === 1
|
|
@@ -2470,7 +2625,8 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
2470
2625
|
&& !taskAggregateRootTarget.ownsTaskLifecycle
|
|
2471
2626
|
&& !taskAggregateRootTarget.ownsTaskAssignee))
|
|
2472
2627
|
&& !ownsTaskMetadata && !ownsTaskLifecycle && !ownsTaskAssignee;
|
|
2473
|
-
if (queuedTaskSuccessor && (input.revisionSource !== 'current'
|
|
2628
|
+
if (queuedTaskSuccessor && (input.revisionSource !== 'current'
|
|
2629
|
+
|| (!queueableTaskRoot && !queueableTaskDelete && !queueableTaskAggregate))) {
|
|
2474
2630
|
throw new Error('Queued task successors require a recognized task root or aggregate operation.');
|
|
2475
2631
|
}
|
|
2476
2632
|
const additionalTargetKeys = new Set();
|
|
@@ -2682,11 +2838,13 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
2682
2838
|
const isTaskRoot = activeDomain === 'task'
|
|
2683
2839
|
&& row.entity_id === entityId
|
|
2684
2840
|
&& (TASK_ROOT_SUCCESSOR_MUTATIONS.has(activeMutationKind)
|
|
2685
|
-
|| (
|
|
2841
|
+
|| (activeMutationKind === 'create'
|
|
2842
|
+
&& Number(row.owns_task_metadata) === 0
|
|
2843
|
+
&& Number(row.owns_task_lifecycle) === 0
|
|
2844
|
+
&& Number(row.owns_task_assignee) === 0))
|
|
2686
2845
|
&& Number(row.target_count) === 1;
|
|
2687
|
-
return isTaskRoot
|
|
2688
|
-
||
|
|
2689
|
-
|| isCompatibleWorkflowRuntimeAggregate(row);
|
|
2846
|
+
return isTaskRoot || (!queueableTaskDelete && (isCompatibleTaskAggregate(row)
|
|
2847
|
+
|| isCompatibleWorkflowRuntimeAggregate(row)));
|
|
2690
2848
|
});
|
|
2691
2849
|
const compatibleWorkflowRuntimeSuccessor = queuedWorkflowRuntimeSuccessor
|
|
2692
2850
|
&& active.every((row) => (row.domain === 'workflow-execution'
|
|
@@ -2786,6 +2944,32 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
2786
2944
|
FROM workspace_sync_outbox
|
|
2787
2945
|
WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
|
|
2788
2946
|
`).get(...ids);
|
|
2947
|
+
if (existing) {
|
|
2948
|
+
try {
|
|
2949
|
+
const existingPayloadFingerprint = String(existing.payload_fingerprint || '');
|
|
2950
|
+
assertDurableOperationIdentity({
|
|
2951
|
+
operationId: ids[3],
|
|
2952
|
+
domain: String(existing.domain || ''),
|
|
2953
|
+
entityId: String(existing.entity_id || ''),
|
|
2954
|
+
mutationKind: String(existing.mutation_kind || ''),
|
|
2955
|
+
payloadFingerprint: existingPayloadFingerprint,
|
|
2956
|
+
}, {
|
|
2957
|
+
operationId: ids[3],
|
|
2958
|
+
domain,
|
|
2959
|
+
entityId,
|
|
2960
|
+
mutationKind,
|
|
2961
|
+
payloadFingerprint: existingPayloadFingerprint === coalescedWorkflowPayloadFingerprint
|
|
2962
|
+
? coalescedWorkflowPayloadFingerprint
|
|
2963
|
+
: payloadFingerprint,
|
|
2964
|
+
});
|
|
2965
|
+
}
|
|
2966
|
+
catch (error) {
|
|
2967
|
+
if (error instanceof DurableOperationReplayIdentityConflictError) {
|
|
2968
|
+
throw new WorkspaceSyncIdempotencyConflictError();
|
|
2969
|
+
}
|
|
2970
|
+
throw error;
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2789
2973
|
const matches = existing
|
|
2790
2974
|
&& Number(existing.contract_version) === WORKSPACE_SYNC_CONTRACT_VERSION
|
|
2791
2975
|
&& existing.dispatch_class === dispatchClass
|
|
@@ -4715,9 +4899,18 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
4715
4899
|
assertMatchingOperation(row, requestFingerprint) {
|
|
4716
4900
|
if (!row)
|
|
4717
4901
|
throw new Error('Workspace sync operation does not exist.');
|
|
4718
|
-
if (Number(row.contract_version) !== WORKSPACE_SYNC_CONTRACT_VERSION
|
|
4902
|
+
if (Number(row.contract_version) !== WORKSPACE_SYNC_CONTRACT_VERSION) {
|
|
4719
4903
|
throw new WorkspaceSyncIdempotencyConflictError();
|
|
4720
4904
|
}
|
|
4905
|
+
try {
|
|
4906
|
+
assertDurableOperationFingerprint(String(row.request_fingerprint || ''), requestFingerprint);
|
|
4907
|
+
}
|
|
4908
|
+
catch (error) {
|
|
4909
|
+
if (error instanceof DurableOperationReplayIdentityConflictError) {
|
|
4910
|
+
throw new WorkspaceSyncIdempotencyConflictError();
|
|
4911
|
+
}
|
|
4912
|
+
throw error;
|
|
4913
|
+
}
|
|
4721
4914
|
}
|
|
4722
4915
|
mapOutboxRow(row) {
|
|
4723
4916
|
return {
|
|
@@ -4748,6 +4941,7 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
4748
4941
|
initiativeMetadataRevisionRebaseCount: Number(row.initiative_metadata_revision_rebase_count || 0),
|
|
4749
4942
|
leaseOwner: row.lease_owner == null ? null : String(row.lease_owner),
|
|
4750
4943
|
leaseExpiresAt: row.lease_expires_at == null ? null : String(row.lease_expires_at),
|
|
4944
|
+
lastErrorCode: row.last_error_code == null ? null : String(row.last_error_code),
|
|
4751
4945
|
};
|
|
4752
4946
|
}
|
|
4753
4947
|
}
|
|
@@ -52,6 +52,16 @@ export type DurableTaskChecklistMutationResult = {
|
|
|
52
52
|
responseJson: string;
|
|
53
53
|
response: DurableTaskChecklistResponse;
|
|
54
54
|
};
|
|
55
|
+
export type TaskChecklistItemUpdateIntent = {
|
|
56
|
+
kind: 'item-update';
|
|
57
|
+
itemId: string;
|
|
58
|
+
patch: {
|
|
59
|
+
text?: string;
|
|
60
|
+
done?: boolean;
|
|
61
|
+
order?: number;
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
export declare function validateTaskChecklistItemUpdateIntent(value: unknown): TaskChecklistItemUpdateIntent;
|
|
55
65
|
export interface DurableTaskChecklistServiceCore {
|
|
56
66
|
getTask(id: string, workspaceId?: string): TaskItem | null;
|
|
57
67
|
updateTask(id: string, updates: Partial<TaskItem>, workspaceId?: string, options?: {
|
|
@@ -89,6 +99,7 @@ export declare function runDurableTaskChecklistReplace(input: {
|
|
|
89
99
|
resolveActorRef?: () => string;
|
|
90
100
|
originActorRef?: string;
|
|
91
101
|
expectedDetailRevision?: string;
|
|
102
|
+
itemUpdateIntent?: TaskChecklistItemUpdateIntent;
|
|
92
103
|
assertPrecondition?: () => void;
|
|
93
104
|
onPostCommitError?: (error: unknown) => void;
|
|
94
105
|
}): DurableTaskChecklistMutationResult;
|
|
@@ -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";
|