@taskforcehq/taskforce 0.3.328 → 0.3.329
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 +233 -34
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +147 -40
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +7 -31
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/config/envSchema.js +12 -0
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/Taskforce.d.ts +62 -2
- package/dist/core/Taskforce.js +635 -32
- package/dist/core/types.d.ts +6 -0
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useTaskData.d.ts +10 -1
- package/dist/hooks/useTaskData.js +216 -7
- package/dist/hooks/useTaskMutations.d.ts +10 -2
- package/dist/hooks/useTaskMutations.js +223 -43
- package/dist/hooks/useTaskforce.d.ts +37 -9
- package/dist/hooks/useTaskforce.js +349 -39
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/documentAssetRegistrar.js +44 -35
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/runtime.js +172 -42
- package/dist/mcp/taskPlanningRegistrar.js +41 -38
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/migrations/taskSchemaMigrations.js +12 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +12 -13
- package/dist/runtime/appGates.js +29 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +15 -3
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +9 -1
- package/dist/server/localWorkspaceSyncServerRuntime.js +10 -3
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.js +1 -0
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.js +118 -16
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +9 -2
- package/dist/server/routes/localService.js +2 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncV3FeedRoutes.js +18 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +10 -0
- package/dist/server/routes/tasks.js +103 -11
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +112 -0
- package/dist/services/codexAppServerModelGateway.js +438 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +7 -1
- package/dist/services/taskforceAgentMcpBridge.js +23 -3
- package/dist/shared/taskforceAgentDefinition.js +7 -1
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +30 -1
- package/dist/storage/postgresAdapter.d.ts +20 -3
- package/dist/storage/postgresAdapter.js +106 -14
- package/dist/storage/postgresWorker.js +13 -4
- package/dist/storage/postgresWorkerProtocol.d.ts +29 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +7 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +25 -8
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +8 -3
- package/dist/sync/syncService.d.ts +2 -0
- package/dist/sync/syncService.js +4 -1
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +11 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +4 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +27 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +54 -13
- package/dist/sync/v3/syncDurabilityStore.d.ts +7 -0
- package/dist/sync/v3/syncDurabilityStore.js +31 -11
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +4 -2
- package/dist/sync/v3/taskChecklistMutationService.js +4 -0
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +2 -0
- package/dist/sync/v3/taskStatusMutationService.js +4 -0
- package/dist/sync/v3/workflowAssignmentSync.d.ts +1 -0
- package/dist/sync/v3/workflowAssignmentSync.js +3 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -1
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +30 -18
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +98 -47
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +58 -21
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +3 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +18 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +19 -7
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +3 -0
- package/dist/sync/workspaceRepair.js +67 -6
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/{AiIdentityRosterCard-MZs7lVED.js → AiIdentityRosterCard-BZM4aQnM.js} +1 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-B68Wg-RV.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-C8Rztyal.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Cj3c7X9y.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-B5uvzems.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-BVFvCB5R.js} +1 -1
- package/dist/ui/assets/PlanningModule-B5DWQOGz.js +1 -0
- package/dist/ui/assets/PlansPage-AY4cGWco.js +1 -0
- package/dist/ui/assets/TaskContextUpload-DZxTVesW.js +1 -0
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +12 -0
- package/dist/ui/assets/{TaskforceAgentsModule-BazdUwxZ.js → TaskforceAgentsModule-BifCYtjR.js} +6 -6
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DEr5di_r.js} +1 -1
- package/dist/ui/assets/index-I5zhdtgt.js +7 -0
- package/dist/ui/assets/index-VRFsx3wz.css +1 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-D9Lpw-j4.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/package.json +16 -4
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
|
@@ -5,7 +5,7 @@ import { validateTaskActivityAuthoritativeRevision } from './taskActivityAuthori
|
|
|
5
5
|
import { serializeEntityActivityForSync, serializeTaskActivityForSync, WORKSPACE_SYNC_ENTITY_EVENT_APPEND, WORKSPACE_SYNC_ENTITY_EVENT_DOMAIN, } from './taskActivityJournal.js';
|
|
6
6
|
import { fingerprintWorkspaceSyncPayload, } from './syncDurabilityStore.js';
|
|
7
7
|
import { serializeTaskRootForSync } from './workspaceSyncV3TaskRootProjection.js';
|
|
8
|
-
import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, validateWorkspaceSyncV3TaskAttachmentLinksPayload, validateWorkspaceSyncV3TaskChecklistPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
8
|
+
import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, validateWorkspaceSyncV3TaskAttachmentLinksPayload, validateWorkspaceSyncV3TaskAttachmentLinksV2Payload, validateWorkspaceSyncV3TaskChecklistPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
9
9
|
export class LocalAuthoritativeTaskCreateError extends Error {
|
|
10
10
|
code = 'WORKSPACE_SYNC_AUTHORITATIVE_RESPONSE_INVALID';
|
|
11
11
|
constructor(message) {
|
|
@@ -264,7 +264,9 @@ export function applyAuthoritativeTaskCreateAndAck(input) {
|
|
|
264
264
|
throw new LocalAuthoritativeTaskCreateError('Authoritative task create attachment-link projection is invalid.');
|
|
265
265
|
}
|
|
266
266
|
try {
|
|
267
|
-
canonicalAttachmentProjection =
|
|
267
|
+
canonicalAttachmentProjection = Object.prototype.hasOwnProperty.call(attachmentProjection.payload, 'cardCoverAssetId')
|
|
268
|
+
? validateWorkspaceSyncV3TaskAttachmentLinksV2Payload(attachmentProjection.payload)
|
|
269
|
+
: validateWorkspaceSyncV3TaskAttachmentLinksPayload(attachmentProjection.payload);
|
|
268
270
|
}
|
|
269
271
|
catch {
|
|
270
272
|
throw new LocalAuthoritativeTaskCreateError('Authoritative task create attachment-link payload is invalid.');
|
|
@@ -272,10 +274,16 @@ export function applyAuthoritativeTaskCreateAndAck(input) {
|
|
|
272
274
|
if (canonicalAttachmentProjection.taskId !== task.id) {
|
|
273
275
|
throw new LocalAuthoritativeTaskCreateError('Authoritative task create attachment-link identity is invalid.');
|
|
274
276
|
}
|
|
275
|
-
const capturedAttachmentProjection =
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
277
|
+
const capturedAttachmentProjection = 'cardCoverAssetId' in canonicalAttachmentProjection
|
|
278
|
+
? serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
|
|
279
|
+
taskId: task.id,
|
|
280
|
+
links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.identity.workspaceId),
|
|
281
|
+
cardCoverAssetId: task.cardCoverAssetId ?? null,
|
|
282
|
+
})
|
|
283
|
+
: serializeWorkspaceSyncV3TaskAttachmentLinksPayload({
|
|
284
|
+
taskId: task.id,
|
|
285
|
+
links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.identity.workspaceId),
|
|
286
|
+
});
|
|
279
287
|
const relationshipIntent = (projection) => ({
|
|
280
288
|
taskId: projection.taskId,
|
|
281
289
|
links: projection.links.map(({ assetId, role, order, displayName }) => ({
|
|
@@ -284,6 +292,7 @@ export function applyAuthoritativeTaskCreateAndAck(input) {
|
|
|
284
292
|
order,
|
|
285
293
|
...(displayName ? { displayName } : {}),
|
|
286
294
|
})),
|
|
295
|
+
...('cardCoverAssetId' in projection ? { cardCoverAssetId: projection.cardCoverAssetId } : {}),
|
|
287
296
|
});
|
|
288
297
|
if (fingerprintWorkspaceSyncPayload(relationshipIntent(canonicalAttachmentProjection))
|
|
289
298
|
!== fingerprintWorkspaceSyncPayload(relationshipIntent(capturedAttachmentProjection))) {
|
|
@@ -7,6 +7,7 @@ export declare function createLocalTaskMetadataClient(input?: LocalTaskOperation
|
|
|
7
7
|
entityId: string;
|
|
8
8
|
patch: Partial<TaskItem>;
|
|
9
9
|
saveSource?: "manual" | "autosave";
|
|
10
|
+
expectedDetailRevision?: string;
|
|
10
11
|
isAuthenticated: boolean;
|
|
11
12
|
dispatchEnabled?: boolean;
|
|
12
13
|
}): Promise<LocalTaskMetadataMutationResult>;
|
|
@@ -15,6 +15,7 @@ export function createLocalTaskMetadataClient(input = {}) {
|
|
|
15
15
|
payload: {
|
|
16
16
|
patch,
|
|
17
17
|
...(inputValue.saveSource ? { saveSource: inputValue.saveSource } : {}),
|
|
18
|
+
...(inputValue.expectedDetailRevision ? { expectedDetailRevision: inputValue.expectedDetailRevision } : {}),
|
|
18
19
|
},
|
|
19
20
|
};
|
|
20
21
|
return client.execute({
|
|
@@ -18,12 +18,15 @@ function buildTaskMetadataEnvelope(record) {
|
|
|
18
18
|
throw new Error('Local outbox payload must be an object.');
|
|
19
19
|
}
|
|
20
20
|
const payloadRecord = payload;
|
|
21
|
-
const allowedKeys = new Set(['patch', 'saveSource', 'originActor']);
|
|
21
|
+
const allowedKeys = new Set(['patch', 'saveSource', 'expectedDetailRevision', 'originActor']);
|
|
22
22
|
if (!Object.prototype.hasOwnProperty.call(payloadRecord, 'patch')
|
|
23
23
|
|| Object.keys(payloadRecord).some((key) => !allowedKeys.has(key))) {
|
|
24
24
|
throw new Error('Local task metadata outbox payload must contain patch and optional saveSource/originActor.');
|
|
25
25
|
}
|
|
26
26
|
const saveSource = payloadRecord.saveSource;
|
|
27
|
+
const expectedDetailRevision = typeof payloadRecord.expectedDetailRevision === 'string'
|
|
28
|
+
? payloadRecord.expectedDetailRevision
|
|
29
|
+
: undefined;
|
|
27
30
|
if (saveSource !== undefined && saveSource !== 'manual' && saveSource !== 'autosave') {
|
|
28
31
|
throw new Error('Local task metadata outbox saveSource must be manual or autosave.');
|
|
29
32
|
}
|
|
@@ -41,6 +44,7 @@ function buildTaskMetadataEnvelope(record) {
|
|
|
41
44
|
payload: {
|
|
42
45
|
patch: validateDurableTaskMetadataPatch(payloadRecord.patch),
|
|
43
46
|
...(saveSource ? { saveSource } : {}),
|
|
47
|
+
...(expectedDetailRevision ? { expectedDetailRevision } : {}),
|
|
44
48
|
...(payloadRecord.originActor !== undefined
|
|
45
49
|
? { originActor: parseWorkspaceSyncV3OriginActor(payloadRecord.originActor) }
|
|
46
50
|
: {}),
|
|
@@ -17,6 +17,7 @@ export interface LocalTaskMetadataOutboxCore {
|
|
|
17
17
|
allowAuthoritativeReplacement?: boolean;
|
|
18
18
|
}): unknown;
|
|
19
19
|
notifyDurableTaskMetadataCommitted(workspaceId: string, taskId: string): void;
|
|
20
|
+
assertTaskDetailRevisionForUpdate?(id: string, expectedDetailRevision: string, workspaceId?: string): void;
|
|
20
21
|
}
|
|
21
22
|
export declare class LocalAuthoritativeTaskMetadataError extends Error {
|
|
22
23
|
readonly code = "WORKSPACE_SYNC_AUTHORITATIVE_RESPONSE_INVALID";
|
|
@@ -29,6 +30,7 @@ export declare function enqueueLocalTaskMetadataMutation(input: {
|
|
|
29
30
|
taskId: string;
|
|
30
31
|
patch: Partial<TaskItem>;
|
|
31
32
|
saveSource?: 'manual' | 'autosave';
|
|
33
|
+
expectedDetailRevision?: string;
|
|
32
34
|
now: string;
|
|
33
35
|
actorRef: string;
|
|
34
36
|
requireV3CombinedOwnership?: boolean;
|
|
@@ -30,10 +30,17 @@ export function enqueueLocalTaskMetadataMutation(input) {
|
|
|
30
30
|
payload: withOriginActorPayload({
|
|
31
31
|
patch,
|
|
32
32
|
...(input.saveSource ? { saveSource: input.saveSource } : {}),
|
|
33
|
+
...(input.expectedDetailRevision ? { expectedDetailRevision: input.expectedDetailRevision } : {}),
|
|
33
34
|
}, input.actorRef),
|
|
34
35
|
...(input.requireV3CombinedOwnership ? { requireV3PlanningOwnership: 'combined' } : {}),
|
|
35
36
|
now: input.now,
|
|
36
37
|
applyLocalMutation: () => {
|
|
38
|
+
if (input.expectedDetailRevision) {
|
|
39
|
+
if (!input.core.assertTaskDetailRevisionForUpdate) {
|
|
40
|
+
throw new DurableTaskMetadataMutationError('Task detail revision checks are unavailable.', 'DURABLE_TASK_PATCH_INVALID', 500);
|
|
41
|
+
}
|
|
42
|
+
input.core.assertTaskDetailRevisionForUpdate(input.taskId, input.expectedDetailRevision, input.identity.workspaceId);
|
|
43
|
+
}
|
|
37
44
|
const task = input.core.updateTask(input.taskId, patch, input.identity.workspaceId, {
|
|
38
45
|
persistBackup: false,
|
|
39
46
|
emitRealtime: false,
|
|
@@ -5,7 +5,7 @@ import { buildTaskLifecycleActivityEventId } from './taskLifecycleActivityIdenti
|
|
|
5
5
|
import { validateTaskActivityAuthoritativeRevision } from './taskActivityAuthoritativeRevision.js';
|
|
6
6
|
import { serializeTaskActivityForSync, WORKSPACE_SYNC_ENTITY_EVENT_APPEND, WORKSPACE_SYNC_ENTITY_EVENT_DOMAIN, } from './taskActivityJournal.js';
|
|
7
7
|
import { fingerprintWorkspaceSyncPayload, WorkspaceSyncIdempotencyConflictError, } from './syncDurabilityStore.js';
|
|
8
|
-
import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, validateWorkspaceSyncV3TaskAttachmentLinksPayload, validateWorkspaceSyncV3TaskChecklistPayload, validateWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
8
|
+
import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, validateWorkspaceSyncV3TaskAttachmentLinksV2Payload, validateWorkspaceSyncV3TaskAttachmentLinksPayload, validateWorkspaceSyncV3TaskChecklistPayload, validateWorkspaceSyncV3TaskCommentsPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
9
9
|
export class LocalAuthoritativeTaskRestoreError extends Error {
|
|
10
10
|
code = 'WORKSPACE_SYNC_AUTHORITATIVE_RESPONSE_INVALID';
|
|
11
11
|
constructor(message) {
|
|
@@ -190,7 +190,9 @@ export function applyAuthoritativeTaskRestoreAndAck(input) {
|
|
|
190
190
|
let canonicalAttachments;
|
|
191
191
|
try {
|
|
192
192
|
canonicalChecklist = validateWorkspaceSyncV3TaskChecklistPayload(checklist.payload);
|
|
193
|
-
canonicalAttachments =
|
|
193
|
+
canonicalAttachments = Object.prototype.hasOwnProperty.call(attachments.payload, 'cardCoverAssetId')
|
|
194
|
+
? validateWorkspaceSyncV3TaskAttachmentLinksV2Payload(attachments.payload)
|
|
195
|
+
: validateWorkspaceSyncV3TaskAttachmentLinksPayload(attachments.payload);
|
|
194
196
|
}
|
|
195
197
|
catch {
|
|
196
198
|
throw new LocalAuthoritativeTaskRestoreError('Authoritative task restore nested projection is invalid.');
|
|
@@ -214,10 +216,16 @@ export function applyAuthoritativeTaskRestoreAndAck(input) {
|
|
|
214
216
|
!== fingerprintWorkspaceSyncPayload(serializeWorkspaceSyncV3TaskChecklistPayload({ taskId: task.id, items: task.checklistItems || [] }))) {
|
|
215
217
|
throw new LocalAuthoritativeTaskRestoreError('Authoritative task restore projections do not match the task payload.');
|
|
216
218
|
}
|
|
217
|
-
const capturedAttachments =
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
219
|
+
const capturedAttachments = 'cardCoverAssetId' in canonicalAttachments
|
|
220
|
+
? serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
|
|
221
|
+
taskId: task.id,
|
|
222
|
+
links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.identity.workspaceId),
|
|
223
|
+
cardCoverAssetId: task.cardCoverAssetId ?? null,
|
|
224
|
+
})
|
|
225
|
+
: serializeWorkspaceSyncV3TaskAttachmentLinksPayload({
|
|
226
|
+
taskId: task.id,
|
|
227
|
+
links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.identity.workspaceId),
|
|
228
|
+
});
|
|
221
229
|
if (fingerprintWorkspaceSyncPayload(canonicalAttachments)
|
|
222
230
|
!== fingerprintWorkspaceSyncPayload(capturedAttachments)) {
|
|
223
231
|
throw new LocalAuthoritativeTaskRestoreError('Authoritative task restore attachment links do not match the captured projection.');
|
|
@@ -9,6 +9,7 @@ export type LocalTaskStatusMutationInput = {
|
|
|
9
9
|
assigneeIntent: DurableTaskStatusAssigneeIntent;
|
|
10
10
|
canceledReason: string | null;
|
|
11
11
|
metadataPatch?: Partial<TaskItem>;
|
|
12
|
+
expectedDetailRevision?: string;
|
|
12
13
|
isAuthenticated: boolean;
|
|
13
14
|
dispatchEnabled?: boolean;
|
|
14
15
|
};
|
|
@@ -20,7 +20,12 @@ export function createLocalTaskStatusClient(input = {}) {
|
|
|
20
20
|
domain: 'task',
|
|
21
21
|
entityId,
|
|
22
22
|
mutationKind: 'set-status',
|
|
23
|
-
payload
|
|
23
|
+
payload: {
|
|
24
|
+
...payload,
|
|
25
|
+
...(inputValue.expectedDetailRevision
|
|
26
|
+
? { expectedDetailRevision: inputValue.expectedDetailRevision }
|
|
27
|
+
: {}),
|
|
28
|
+
},
|
|
24
29
|
};
|
|
25
30
|
return client.execute({
|
|
26
31
|
workspaceId,
|
|
@@ -3,6 +3,7 @@ import { type DurableTaskStatusMutationCore, type DurableTaskStatusMutationPaylo
|
|
|
3
3
|
import { WorkspaceSyncDurabilityStore, type WorkspaceSyncOperationIdentity, type WorkspaceSyncOutboxRecord } from './syncDurabilityStore.js';
|
|
4
4
|
import type { DatabaseAdapter } from '../../storage/databaseAdapter.js';
|
|
5
5
|
export interface LocalTaskStatusOutboxCore extends DurableTaskStatusMutationCore {
|
|
6
|
+
assertTaskDetailRevisionForUpdate?(id: string, expectedDetailRevision: string, workspaceId?: string): void;
|
|
6
7
|
getDatabaseAdapter(): DatabaseAdapter;
|
|
7
8
|
getTenantId(): string;
|
|
8
9
|
installDurableTaskStatusAuthoritativeForSync(task: TaskItem, payload: DurableTaskStatusMutationPayload, installAssignee: boolean, workspaceId: string): TaskItem;
|
|
@@ -33,6 +34,7 @@ export declare function enqueueLocalTaskStatusMutation(input: {
|
|
|
33
34
|
identity: WorkspaceSyncOperationIdentity;
|
|
34
35
|
taskId: string;
|
|
35
36
|
payload: unknown;
|
|
37
|
+
expectedDetailRevision?: string;
|
|
36
38
|
now: string;
|
|
37
39
|
actorRef: string;
|
|
38
40
|
requireV3CombinedOwnership?: boolean;
|
|
@@ -74,23 +74,42 @@ export function enqueueLocalTaskStatusMutation(input) {
|
|
|
74
74
|
taskLifecycle: true,
|
|
75
75
|
taskAssignee: payload.assigneeIntent.kind !== 'preserve',
|
|
76
76
|
},
|
|
77
|
-
payload: withOriginActorPayload({
|
|
77
|
+
payload: withOriginActorPayload({
|
|
78
|
+
...payload,
|
|
79
|
+
...(input.expectedDetailRevision
|
|
80
|
+
? { expectedDetailRevision: input.expectedDetailRevision }
|
|
81
|
+
: {}),
|
|
82
|
+
}, input.actorRef),
|
|
78
83
|
...(payload.workflowAssignment ? {
|
|
79
84
|
coalesceWorkflowAssignmentExecutionId: payload.workflowAssignment.execution.id,
|
|
80
85
|
} : {}),
|
|
81
86
|
...(input.requireV3CombinedOwnership ? { requireV3PlanningOwnership: 'combined' } : {}),
|
|
82
87
|
now: input.now,
|
|
83
|
-
applyLocalMutation: () =>
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
applyLocalMutation: () => {
|
|
89
|
+
if (input.expectedDetailRevision) {
|
|
90
|
+
if (!input.core.assertTaskDetailRevisionForUpdate) {
|
|
91
|
+
throw new Error('Task detail revision checks are unavailable.');
|
|
92
|
+
}
|
|
93
|
+
input.core.assertTaskDetailRevisionForUpdate(taskId, input.expectedDetailRevision, input.identity.workspaceId);
|
|
94
|
+
}
|
|
95
|
+
return applyTaskStatusMutationForDurableSync({
|
|
96
|
+
core: input.core,
|
|
97
|
+
workspaceId: input.identity.workspaceId,
|
|
98
|
+
taskId,
|
|
99
|
+
targetStatus: statusPayload.status,
|
|
100
|
+
metadataPatch: statusPayload.metadataPatch,
|
|
101
|
+
assigneeIntent: statusPayload.assigneeIntent,
|
|
102
|
+
canceledReason: statusPayload.canceledReason,
|
|
103
|
+
updatedAt: input.now,
|
|
104
|
+
actorRef: input.actorRef,
|
|
105
|
+
taskEventId: activityEventId,
|
|
106
|
+
});
|
|
107
|
+
},
|
|
108
|
+
buildCanonicalIntent: (result) => ({
|
|
109
|
+
metadataPatch: Object.fromEntries(Object.keys(payload.metadataPatch).map((key) => [
|
|
110
|
+
key,
|
|
111
|
+
result.task[key] ?? null,
|
|
112
|
+
])),
|
|
94
113
|
}),
|
|
95
114
|
});
|
|
96
115
|
if (!result.enqueued)
|
|
@@ -189,9 +208,31 @@ export function applyAuthoritativeTaskStatusAndAck(input) {
|
|
|
189
208
|
const localCanonical = input.core.getTask(task.id, input.identity.workspaceId);
|
|
190
209
|
if (!localCanonical)
|
|
191
210
|
throw new LocalAuthoritativeTaskStatusError('Local task status projection is missing.');
|
|
211
|
+
let canonicalMetadataIntent = null;
|
|
212
|
+
if (input.record.canonicalIntentJson) {
|
|
213
|
+
try {
|
|
214
|
+
const parsed = JSON.parse(input.record.canonicalIntentJson);
|
|
215
|
+
canonicalMetadataIntent = parsed.metadataPatch
|
|
216
|
+
&& typeof parsed.metadataPatch === 'object'
|
|
217
|
+
&& !Array.isArray(parsed.metadataPatch)
|
|
218
|
+
? parsed.metadataPatch
|
|
219
|
+
: null;
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
canonicalMetadataIntent = null;
|
|
223
|
+
}
|
|
224
|
+
if (!canonicalMetadataIntent) {
|
|
225
|
+
throw new LocalAuthoritativeTaskStatusError('Persisted canonical task status intent is invalid.');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
192
228
|
for (const key of Object.keys(payload.metadataPatch)) {
|
|
229
|
+
if (canonicalMetadataIntent && !Object.prototype.hasOwnProperty.call(canonicalMetadataIntent, key)) {
|
|
230
|
+
throw new LocalAuthoritativeTaskStatusError('Persisted canonical task status intent is incomplete.');
|
|
231
|
+
}
|
|
193
232
|
const actual = task[key];
|
|
194
|
-
const expected =
|
|
233
|
+
const expected = canonicalMetadataIntent
|
|
234
|
+
? canonicalMetadataIntent[key]
|
|
235
|
+
: localCanonical[key];
|
|
195
236
|
if (fingerprintWorkspaceSyncPayload(actual ?? null) !== fingerprintWorkspaceSyncPayload(expected ?? null)) {
|
|
196
237
|
throw new LocalAuthoritativeTaskStatusError('Authoritative task metadata does not match the persisted request.');
|
|
197
238
|
}
|
|
@@ -80,6 +80,7 @@ export type WorkspaceSyncOutboxRecord = WorkspaceSyncOperationIdentity & {
|
|
|
80
80
|
baseLifecycleRevision: string;
|
|
81
81
|
payloadJson: string;
|
|
82
82
|
payloadFingerprint: string;
|
|
83
|
+
canonicalIntentJson: string | null;
|
|
83
84
|
status: string;
|
|
84
85
|
attemptCount: number;
|
|
85
86
|
initialNotFoundAttemptCount: number;
|
|
@@ -542,6 +543,7 @@ export declare class WorkspaceSyncDurabilityStore {
|
|
|
542
543
|
queuedTaskSuccessor?: boolean;
|
|
543
544
|
queuedWorkflowRuntimeSuccessor?: boolean;
|
|
544
545
|
coalesceWorkflowAssignmentExecutionId?: string;
|
|
546
|
+
buildCanonicalIntent?: (mutationResult: T) => unknown;
|
|
545
547
|
}): {
|
|
546
548
|
enqueued: boolean;
|
|
547
549
|
mutationResult?: T;
|
|
@@ -760,6 +762,11 @@ export declare class WorkspaceSyncDurabilityStore {
|
|
|
760
762
|
private assertTaskCommentAppendRecoveryEventOwned;
|
|
761
763
|
private isTaskCommentAppendRecoveryIntentSatisfied;
|
|
762
764
|
private prepareTaskRecoveryPayload;
|
|
765
|
+
lockWorkspaceSequenceForMutation(input: {
|
|
766
|
+
tenantId: string;
|
|
767
|
+
workspaceId: string;
|
|
768
|
+
now: string;
|
|
769
|
+
}): void;
|
|
763
770
|
private allocateSequenceRange;
|
|
764
771
|
private allocateOutboxEnqueueSequence;
|
|
765
772
|
private readOperationRow;
|
|
@@ -791,7 +791,7 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
791
791
|
mutation_kind, owns_task_metadata, owns_task_lifecycle, owns_task_assignee,
|
|
792
792
|
CAST(base_entity_revision AS TEXT) AS base_entity_revision,
|
|
793
793
|
CAST(base_lifecycle_revision AS TEXT) AS base_lifecycle_revision,
|
|
794
|
-
payload_json, payload_fingerprint, status, attempt_count,
|
|
794
|
+
payload_json, payload_fingerprint, canonical_intent_json, status, attempt_count,
|
|
795
795
|
initial_not_found_attempt_count,
|
|
796
796
|
CAST(enqueue_sequence AS TEXT) AS enqueue_sequence,
|
|
797
797
|
rebase_before_first_attempt, lease_owner, lease_expires_at
|
|
@@ -847,7 +847,7 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
847
847
|
mutation_kind, owns_task_metadata, owns_task_lifecycle, owns_task_assignee,
|
|
848
848
|
CAST(base_entity_revision AS TEXT) AS base_entity_revision,
|
|
849
849
|
CAST(base_lifecycle_revision AS TEXT) AS base_lifecycle_revision,
|
|
850
|
-
payload_json, payload_fingerprint, status, attempt_count,
|
|
850
|
+
payload_json, payload_fingerprint, canonical_intent_json, status, attempt_count,
|
|
851
851
|
initial_not_found_attempt_count,
|
|
852
852
|
CAST(enqueue_sequence AS TEXT) AS enqueue_sequence,
|
|
853
853
|
rebase_before_first_attempt, lease_owner, lease_expires_at
|
|
@@ -1028,7 +1028,7 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
1028
1028
|
mutation_kind, owns_task_metadata, owns_task_lifecycle, owns_task_assignee,
|
|
1029
1029
|
CAST(base_entity_revision AS TEXT) AS base_entity_revision,
|
|
1030
1030
|
CAST(base_lifecycle_revision AS TEXT) AS base_lifecycle_revision,
|
|
1031
|
-
payload_json, payload_fingerprint, status, attempt_count,
|
|
1031
|
+
payload_json, payload_fingerprint, canonical_intent_json, status, attempt_count,
|
|
1032
1032
|
initial_not_found_attempt_count,
|
|
1033
1033
|
CAST(enqueue_sequence AS TEXT) AS enqueue_sequence,
|
|
1034
1034
|
rebase_before_first_attempt, lease_owner, lease_expires_at
|
|
@@ -1396,7 +1396,8 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
1396
1396
|
const recoverySources = this.db.prepare(`
|
|
1397
1397
|
SELECT client_id, operation_id, dispatch_class, domain, entity_id, mutation_kind,
|
|
1398
1398
|
owns_task_metadata, owns_task_lifecycle, owns_task_assignee,
|
|
1399
|
-
payload_json, payload_fingerprint,
|
|
1399
|
+
payload_json, payload_fingerprint, canonical_intent_json,
|
|
1400
|
+
last_error_code, last_error_message,
|
|
1400
1401
|
EXISTS (
|
|
1401
1402
|
SELECT 1
|
|
1402
1403
|
FROM workspace_sync_outbox AS replay_candidate
|
|
@@ -1646,18 +1647,18 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
1646
1647
|
dispatch_class, domain, entity_id, mutation_kind,
|
|
1647
1648
|
owns_task_metadata, owns_task_lifecycle, owns_task_assignee,
|
|
1648
1649
|
base_entity_revision, base_lifecycle_revision,
|
|
1649
|
-
payload_json, payload_fingerprint, status, attempt_count,
|
|
1650
|
+
payload_json, payload_fingerprint, canonical_intent_json, status, attempt_count,
|
|
1650
1651
|
initial_not_found_attempt_count, enqueue_sequence, rebase_before_first_attempt,
|
|
1651
1652
|
next_attempt_at, recovery_batch_id,
|
|
1652
1653
|
replay_of_client_id, replay_of_operation_id, created_at, updated_at
|
|
1653
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', 0, 0, ?, 1,
|
|
1654
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', 0, 0, ?, 1,
|
|
1654
1655
|
?, ?, ?, ?, ?, ?)
|
|
1655
1656
|
ON CONFLICT (tenant_id, workspace_id, client_id, operation_id) DO NOTHING
|
|
1656
|
-
`).run(tenantId, workspaceId, operationId, WORKSPACE_SYNC_CONTRACT_VERSION, sourceClientId, requireOutboxDispatchClass(source.dispatch_class), requireText(source.domain, 'Source domain'), replayEntityId, replayPayload.replayMutationKind, Number(source.owns_task_metadata) === 1 ? 1 : 0, Number(source.owns_task_lifecycle) === 1 ? 1 : 0, Number(source.owns_task_assignee) === 1 ? 1 : 0, primary.revision.entityRevision, primary.revision.lifecycleRevision, replayPayload.payloadJson, replayPayload.payloadFingerprint, enqueueSequence, now, recoveryBatchId, sourceClientId, sourceOperationId, now, now);
|
|
1657
|
+
`).run(tenantId, workspaceId, operationId, WORKSPACE_SYNC_CONTRACT_VERSION, sourceClientId, requireOutboxDispatchClass(source.dispatch_class), requireText(source.domain, 'Source domain'), replayEntityId, replayPayload.replayMutationKind, Number(source.owns_task_metadata) === 1 ? 1 : 0, Number(source.owns_task_lifecycle) === 1 ? 1 : 0, Number(source.owns_task_assignee) === 1 ? 1 : 0, primary.revision.entityRevision, primary.revision.lifecycleRevision, replayPayload.payloadJson, replayPayload.payloadFingerprint, source.canonical_intent_json == null ? null : String(source.canonical_intent_json), enqueueSequence, now, recoveryBatchId, sourceClientId, sourceOperationId, now, now);
|
|
1657
1658
|
this.db.prepare(`
|
|
1658
1659
|
UPDATE workspace_sync_outbox
|
|
1659
1660
|
SET base_entity_revision = ?, base_lifecycle_revision = ?,
|
|
1660
|
-
payload_json = ?, payload_fingerprint = ?,
|
|
1661
|
+
payload_json = ?, payload_fingerprint = ?, canonical_intent_json = ?,
|
|
1661
1662
|
status = 'pending', attempt_count = 0, initial_not_found_attempt_count = 0,
|
|
1662
1663
|
rebase_before_first_attempt = 1, next_attempt_at = ?,
|
|
1663
1664
|
lease_owner = NULL, lease_expires_at = NULL,
|
|
@@ -1667,7 +1668,7 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
1667
1668
|
WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
|
|
1668
1669
|
AND recovery_batch_id = ? AND replay_of_client_id = ? AND replay_of_operation_id = ?
|
|
1669
1670
|
AND status = 'superseded'
|
|
1670
|
-
`).run(primary.revision.entityRevision, primary.revision.lifecycleRevision, replayPayload.payloadJson, replayPayload.payloadFingerprint, now, now, tenantId, workspaceId, sourceClientId, operationId, recoveryBatchId, sourceClientId, sourceOperationId);
|
|
1671
|
+
`).run(primary.revision.entityRevision, primary.revision.lifecycleRevision, replayPayload.payloadJson, replayPayload.payloadFingerprint, source.canonical_intent_json == null ? null : String(source.canonical_intent_json), now, now, tenantId, workspaceId, sourceClientId, operationId, recoveryBatchId, sourceClientId, sourceOperationId);
|
|
1671
1672
|
if (replayPayload.workflowDependencyCoalesced) {
|
|
1672
1673
|
this.db.prepare(`
|
|
1673
1674
|
UPDATE workspace_sync_outbox
|
|
@@ -2761,7 +2762,20 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
2761
2762
|
for (const target of targets) {
|
|
2762
2763
|
insertTarget.run(ids[0], ids[1], ids[2], ids[3], target.domain, target.entityId, target.mutationKind, target.baseEntityRevision, target.baseLifecycleRevision, target.ownsTaskMetadata ? 1 : 0, target.ownsTaskLifecycle ? 1 : 0, target.ownsTaskAssignee ? 1 : 0, now);
|
|
2763
2764
|
}
|
|
2764
|
-
|
|
2765
|
+
const mutationResult = input.applyLocalMutation();
|
|
2766
|
+
if (input.buildCanonicalIntent) {
|
|
2767
|
+
const canonicalIntentJson = canonicalWorkspaceSyncJson(input.buildCanonicalIntent(mutationResult));
|
|
2768
|
+
const updated = this.db.prepare(`
|
|
2769
|
+
UPDATE workspace_sync_outbox
|
|
2770
|
+
SET canonical_intent_json = ?, updated_at = ?
|
|
2771
|
+
WHERE tenant_id = ? AND workspace_id = ? AND client_id = ? AND operation_id = ?
|
|
2772
|
+
AND status = 'pending'
|
|
2773
|
+
`).run(canonicalIntentJson, now, ...ids);
|
|
2774
|
+
if (Number(updated.changes || 0) !== 1) {
|
|
2775
|
+
throw new Error('Workspace sync canonical intent changed before it was persisted.');
|
|
2776
|
+
}
|
|
2777
|
+
}
|
|
2778
|
+
return { enqueued: true, mutationResult };
|
|
2765
2779
|
}
|
|
2766
2780
|
const existing = this.db.prepare(`
|
|
2767
2781
|
SELECT contract_version, dispatch_class, domain, entity_id, mutation_kind,
|
|
@@ -3891,7 +3905,7 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
3891
3905
|
mutation_kind, owns_task_metadata, owns_task_lifecycle, owns_task_assignee,
|
|
3892
3906
|
CAST(base_entity_revision AS TEXT) AS base_entity_revision,
|
|
3893
3907
|
CAST(base_lifecycle_revision AS TEXT) AS base_lifecycle_revision,
|
|
3894
|
-
payload_json, payload_fingerprint, status, attempt_count,
|
|
3908
|
+
payload_json, payload_fingerprint, canonical_intent_json, status, attempt_count,
|
|
3895
3909
|
initial_not_found_attempt_count,
|
|
3896
3910
|
CAST(enqueue_sequence AS TEXT) AS enqueue_sequence,
|
|
3897
3911
|
rebase_before_first_attempt,
|
|
@@ -4664,6 +4678,9 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
4664
4678
|
workflowDependencyCoalesced: true,
|
|
4665
4679
|
};
|
|
4666
4680
|
}
|
|
4681
|
+
lockWorkspaceSequenceForMutation(input) {
|
|
4682
|
+
this.allocateSequenceRange(requireText(input.tenantId, 'Tenant id'), requireText(input.workspaceId, 'Workspace id'), requireIsoTimestamp(input.now, 'Lock time'), 0);
|
|
4683
|
+
}
|
|
4667
4684
|
allocateSequenceRange(tenantId, workspaceId, now, count) {
|
|
4668
4685
|
const row = this.db.prepare(`
|
|
4669
4686
|
INSERT INTO workspace_sync_sequences (tenant_id, workspace_id, last_sequence, updated_at)
|
|
@@ -4719,6 +4736,9 @@ export class WorkspaceSyncDurabilityStore {
|
|
|
4719
4736
|
baseLifecycleRevision: normalizeSequence(row.base_lifecycle_revision),
|
|
4720
4737
|
payloadJson: requireText(row.payload_json, 'Payload'),
|
|
4721
4738
|
payloadFingerprint: requireText(row.payload_fingerprint, 'Payload fingerprint'),
|
|
4739
|
+
canonicalIntentJson: row.canonical_intent_json == null
|
|
4740
|
+
? null
|
|
4741
|
+
: requireText(row.canonical_intent_json, 'Canonical intent'),
|
|
4722
4742
|
status: requireText(row.status, 'Outbox status'),
|
|
4723
4743
|
attemptCount: Number(row.attempt_count || 0),
|
|
4724
4744
|
initialNotFoundAttemptCount: Number(row.initial_not_found_attempt_count || 0),
|
|
@@ -2,15 +2,15 @@ import type { AttachmentItem, TaskEvent, TaskEventDetails, TaskItem } from '../.
|
|
|
2
2
|
import { serializeTaskRootForSync } from './workspaceSyncV3TaskRootProjection.js';
|
|
3
3
|
import { serializeTaskActivityForSync, type WorkspaceSyncActivityRevision } from './taskActivityJournal.js';
|
|
4
4
|
import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
|
|
5
|
-
import { type WorkspaceSyncV3TaskAttachmentLink, type
|
|
5
|
+
import { type WorkspaceSyncV3TaskAttachmentLink, type WorkspaceSyncV3TaskAttachmentLinksV2Payload } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
6
6
|
export declare class DurableTaskAttachmentLinksMutationError extends Error {
|
|
7
|
-
readonly code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_ATTACHMENT_LINKS_INVALID' | 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_ATTACHMENT_LINKS_DEPENDENCY_PENDING' | 'TASK_ATTACHMENT_ASSET_NOT_READY';
|
|
7
|
+
readonly code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_ATTACHMENT_LINKS_INVALID' | 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_ATTACHMENT_LINKS_DEPENDENCY_PENDING' | 'TASK_ATTACHMENT_ASSET_NOT_READY' | 'TASK_DETAIL_REVISION_CONFLICT';
|
|
8
8
|
readonly statusCode: number;
|
|
9
9
|
readonly details?: Record<string, unknown> | undefined;
|
|
10
10
|
readonly retryable?: boolean | undefined;
|
|
11
11
|
readonly retryAfterAt?: string | undefined;
|
|
12
12
|
readonly retryHint?: string | undefined;
|
|
13
|
-
constructor(message: string, code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_ATTACHMENT_LINKS_INVALID' | 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_ATTACHMENT_LINKS_DEPENDENCY_PENDING' | 'TASK_ATTACHMENT_ASSET_NOT_READY', statusCode: number, details?: Record<string, unknown> | undefined, retryable?: boolean | undefined, retryAfterAt?: string | undefined, retryHint?: string | undefined);
|
|
13
|
+
constructor(message: string, code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_ATTACHMENT_LINKS_INVALID' | 'TASK_ATTACHMENT_LINKS_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_ATTACHMENT_LINKS_DEPENDENCY_PENDING' | 'TASK_ATTACHMENT_ASSET_NOT_READY' | 'TASK_DETAIL_REVISION_CONFLICT', statusCode: number, details?: Record<string, unknown> | undefined, retryable?: boolean | undefined, retryAfterAt?: string | undefined, retryHint?: string | undefined);
|
|
14
14
|
}
|
|
15
15
|
export type DurableTaskAttachmentLinksResponse = {
|
|
16
16
|
success: true;
|
|
@@ -37,7 +37,7 @@ export type DurableTaskAttachmentLinksResponse = {
|
|
|
37
37
|
sequence: string;
|
|
38
38
|
entityRevision: string;
|
|
39
39
|
lifecycleRevision: string;
|
|
40
|
-
payload:
|
|
40
|
+
payload: WorkspaceSyncV3TaskAttachmentLinksV2Payload;
|
|
41
41
|
};
|
|
42
42
|
};
|
|
43
43
|
activity: ReturnType<typeof serializeTaskActivityForSync>;
|
|
@@ -108,5 +108,7 @@ export declare function runDurableTaskAttachmentLinksReplace(input: {
|
|
|
108
108
|
actorRef: string;
|
|
109
109
|
resolveActorRef?: () => string;
|
|
110
110
|
originActorRef?: string;
|
|
111
|
+
expectedDetailRevision?: string;
|
|
112
|
+
assertPrecondition?: () => void;
|
|
111
113
|
onPostCommitError?: (error: unknown) => void;
|
|
112
114
|
}): DurableTaskAttachmentLinksMutationResult;
|
|
@@ -3,7 +3,7 @@ import { serializeTaskRootForSync } from './workspaceSyncV3TaskRootProjection.js
|
|
|
3
3
|
import { buildTaskAttachmentLinksActivityEventId } from './taskAttachmentLinksActivityIdentity.js';
|
|
4
4
|
import { asWorkspaceSyncActivityRevision, buildTaskActivityJournalEntry, canonicalizeEntityActivityDetailsForSync, serializeTaskActivityForSync, } from './taskActivityJournal.js';
|
|
5
5
|
import { fingerprintWorkspaceSyncPayload, runReservedWorkspaceSyncV3Operation, WORKSPACE_SYNC_CONTRACT_VERSION, } from './syncDurabilityStore.js';
|
|
6
|
-
import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
6
|
+
import { serializeWorkspaceSyncV3TaskAttachmentLinksPayload, serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload, } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
7
7
|
import { resolveDeferredMutationActorRef } from './workspaceSyncV3OriginActor.js';
|
|
8
8
|
export class DurableTaskAttachmentLinksMutationError extends Error {
|
|
9
9
|
code;
|
|
@@ -61,6 +61,9 @@ export function runDurableTaskAttachmentLinksReplace(input) {
|
|
|
61
61
|
? { cardCoverAssetId: input.cardCoverAssetId }
|
|
62
62
|
: {}),
|
|
63
63
|
...(input.originActorRef ? { originActorRef: input.originActorRef } : {}),
|
|
64
|
+
...(input.expectedDetailRevision
|
|
65
|
+
? { expectedDetailRevision: input.expectedDetailRevision }
|
|
66
|
+
: {}),
|
|
64
67
|
},
|
|
65
68
|
});
|
|
66
69
|
const activityEventId = buildTaskAttachmentLinksActivityEventId({
|
|
@@ -74,6 +77,16 @@ export function runDurableTaskAttachmentLinksReplace(input) {
|
|
|
74
77
|
throw new Error('Durable task attachment-link activity was not persisted.');
|
|
75
78
|
return activity;
|
|
76
79
|
};
|
|
80
|
+
const readAttachmentPayload = () => {
|
|
81
|
+
const task = input.core.getTask(input.taskId, input.workspaceId);
|
|
82
|
+
if (!task)
|
|
83
|
+
throw new DurableTaskAttachmentLinksMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
|
|
84
|
+
return serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
|
|
85
|
+
taskId: input.taskId,
|
|
86
|
+
links: input.core.listTaskAttachmentLinksForDurableSync(input.taskId, input.workspaceId),
|
|
87
|
+
cardCoverAssetId: task.cardCoverAssetId ?? null,
|
|
88
|
+
});
|
|
89
|
+
};
|
|
77
90
|
const result = runReservedWorkspaceSyncV3Operation({
|
|
78
91
|
store: input.store, identity, requestFingerprint,
|
|
79
92
|
now: input.now, leaseExpiresAt: input.leaseExpiresAt, leaseOwner: input.leaseOwner,
|
|
@@ -101,16 +114,11 @@ export function runDurableTaskAttachmentLinksReplace(input) {
|
|
|
101
114
|
}, {
|
|
102
115
|
domain: 'task-attachment-links', entityId: input.taskId, mutationKind: 'replace', revisionKind: 'metadata',
|
|
103
116
|
baseEntityRevision: input.baseEntityRevision, baseLifecycleRevision: input.baseLifecycleRevision,
|
|
104
|
-
buildCanonicalFingerprint: () => fingerprintWorkspaceSyncPayload(
|
|
105
|
-
|
|
106
|
-
links: input.core.listTaskAttachmentLinksForDurableSync(input.taskId, input.workspaceId),
|
|
107
|
-
})),
|
|
108
|
-
buildAuthoritativePayload: () => serializeWorkspaceSyncV3TaskAttachmentLinksPayload({
|
|
109
|
-
taskId: input.taskId,
|
|
110
|
-
links: input.core.listTaskAttachmentLinksForDurableSync(input.taskId, input.workspaceId),
|
|
111
|
-
}),
|
|
117
|
+
buildCanonicalFingerprint: () => fingerprintWorkspaceSyncPayload(readAttachmentPayload()),
|
|
118
|
+
buildAuthoritativePayload: readAttachmentPayload,
|
|
112
119
|
}, buildTaskActivityJournalEntry({ eventId: activityEventId, readEvent: readActivity })],
|
|
113
120
|
applyMutation: () => {
|
|
121
|
+
input.assertPrecondition?.();
|
|
114
122
|
const existing = input.core.getTask(input.taskId, input.workspaceId);
|
|
115
123
|
if (!existing)
|
|
116
124
|
throw new DurableTaskAttachmentLinksMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
|
|
@@ -181,9 +189,10 @@ export function runDurableTaskAttachmentLinksReplace(input) {
|
|
|
181
189
|
sequence: attachmentLinksRevision.sequence,
|
|
182
190
|
entityRevision: attachmentLinksRevision.entityRevision,
|
|
183
191
|
lifecycleRevision: attachmentLinksRevision.lifecycleRevision,
|
|
184
|
-
payload:
|
|
192
|
+
payload: serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload({
|
|
185
193
|
taskId: task.id,
|
|
186
194
|
links: input.core.listTaskAttachmentLinksForDurableSync(task.id, input.workspaceId),
|
|
195
|
+
cardCoverAssetId: task.cardCoverAssetId ?? null,
|
|
187
196
|
}),
|
|
188
197
|
},
|
|
189
198
|
},
|
|
@@ -4,13 +4,13 @@ import { serializeTaskActivityForSync, type WorkspaceSyncActivityRevision } from
|
|
|
4
4
|
import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
|
|
5
5
|
import { type WorkspaceSyncV3TaskChecklistPayload } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
6
6
|
export declare class DurableTaskChecklistMutationError extends Error {
|
|
7
|
-
readonly code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_CHECKLIST_INVALID' | 'TASK_CHECKLIST_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_CHECKLIST_DEPENDENCY_PENDING';
|
|
7
|
+
readonly code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_CHECKLIST_INVALID' | 'TASK_CHECKLIST_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_CHECKLIST_DEPENDENCY_PENDING' | 'TASK_DETAIL_REVISION_CONFLICT';
|
|
8
8
|
readonly statusCode: number;
|
|
9
9
|
readonly details?: Record<string, unknown> | undefined;
|
|
10
10
|
readonly retryable?: boolean | undefined;
|
|
11
11
|
readonly retryAfterAt?: string | undefined;
|
|
12
12
|
readonly retryHint?: string | undefined;
|
|
13
|
-
constructor(message: string, code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_CHECKLIST_INVALID' | 'TASK_CHECKLIST_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_CHECKLIST_DEPENDENCY_PENDING', statusCode: number, details?: Record<string, unknown> | undefined, retryable?: boolean | undefined, retryAfterAt?: string | undefined, retryHint?: string | undefined);
|
|
13
|
+
constructor(message: string, code: 'TASK_NOT_FOUND' | 'TASK_ARCHIVED_READ_ONLY' | 'TASK_CHECKLIST_INVALID' | 'TASK_CHECKLIST_IDENTITY_CONFLICT' | 'WORKSPACE_SYNC_OPERATION_ID_REQUIRED' | 'TASK_CHECKLIST_DEPENDENCY_PENDING' | 'TASK_DETAIL_REVISION_CONFLICT', statusCode: number, details?: Record<string, unknown> | undefined, retryable?: boolean | undefined, retryAfterAt?: string | undefined, retryHint?: string | undefined);
|
|
14
14
|
}
|
|
15
15
|
export type DurableTaskChecklistResponse = {
|
|
16
16
|
success: true;
|
|
@@ -88,5 +88,7 @@ export declare function runDurableTaskChecklistReplace(input: {
|
|
|
88
88
|
actorRef: string;
|
|
89
89
|
resolveActorRef?: () => string;
|
|
90
90
|
originActorRef?: string;
|
|
91
|
+
expectedDetailRevision?: string;
|
|
92
|
+
assertPrecondition?: () => void;
|
|
91
93
|
onPostCommitError?: (error: unknown) => void;
|
|
92
94
|
}): DurableTaskChecklistMutationResult;
|
|
@@ -58,6 +58,9 @@ export function runDurableTaskChecklistReplace(input) {
|
|
|
58
58
|
baseLifecycleRevision: String(input.baseLifecycleRevision),
|
|
59
59
|
items,
|
|
60
60
|
...(input.originActorRef ? { originActorRef: input.originActorRef } : {}),
|
|
61
|
+
...(input.expectedDetailRevision
|
|
62
|
+
? { expectedDetailRevision: input.expectedDetailRevision }
|
|
63
|
+
: {}),
|
|
61
64
|
},
|
|
62
65
|
});
|
|
63
66
|
const activityEventId = buildTaskChecklistActivityEventId({
|
|
@@ -100,6 +103,7 @@ export function runDurableTaskChecklistReplace(input) {
|
|
|
100
103
|
}),
|
|
101
104
|
}, buildTaskActivityJournalEntry({ eventId: activityEventId, readEvent: readActivity })],
|
|
102
105
|
applyMutation: () => {
|
|
106
|
+
input.assertPrecondition?.();
|
|
103
107
|
const existing = input.core.getTask(input.taskId, input.workspaceId);
|
|
104
108
|
if (!existing)
|
|
105
109
|
throw new DurableTaskChecklistMutationError('Task not found.', 'TASK_NOT_FOUND', 404);
|
|
@@ -2,7 +2,7 @@ import { type DurableTaskCreateMutationCore } from '../../core/TaskDurableCreate
|
|
|
2
2
|
import type { EntityEvent, TaskEvent, TaskItem } from '../../core/Taskforce.js';
|
|
3
3
|
import { serializeTaskForSync } from '../taskSyncPayload.js';
|
|
4
4
|
import type { WorkspaceSyncTaskEventSnapshot } from '../workspaceSyncModel.js';
|
|
5
|
-
import {
|
|
5
|
+
import { serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload, serializeWorkspaceSyncV3TaskChecklistPayload, serializeWorkspaceSyncV3TaskCommentsPayload, type WorkspaceSyncV3TaskAttachmentLink } from './workspaceSyncV3NestedTaskCodecs.js';
|
|
6
6
|
import { type WorkspaceSyncActivityRevision } from './taskActivityJournal.js';
|
|
7
7
|
import { WorkspaceSyncDurabilityStore } from './syncDurabilityStore.js';
|
|
8
8
|
export interface DurableTaskCreateServiceCore extends DurableTaskCreateMutationCore {
|
|
@@ -64,7 +64,7 @@ export type DurableTaskCreateResponse = {
|
|
|
64
64
|
sequence: string;
|
|
65
65
|
entityRevision: string;
|
|
66
66
|
lifecycleRevision: string;
|
|
67
|
-
payload: ReturnType<typeof
|
|
67
|
+
payload: ReturnType<typeof serializeWorkspaceSyncV3TaskAttachmentLinksV2Payload>;
|
|
68
68
|
};
|
|
69
69
|
activity: WorkspaceSyncTaskEventSnapshot;
|
|
70
70
|
activityRevision: WorkspaceSyncActivityRevision;
|