@taskforcehq/taskforce 0.3.328 → 0.3.330
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Taskforce.module.css +523 -79
- package/dist/TaskforceCore.js +237 -230
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
- package/dist/cli.js +34 -0
- package/dist/cliCloudTargetGuard.d.ts +5 -0
- package/dist/cliCloudTargetGuard.js +11 -0
- package/dist/components/features/AiProfilesModule.js +3 -5
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
- package/dist/components/features/TaskSettings.d.ts +12 -1
- package/dist/components/features/TaskSettings.js +217 -54
- package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
- package/dist/components/features/TaskforceAgentsModule.js +586 -116
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
- package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
- package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
- package/dist/components/features/planning/PlanningModule.js +2 -5
- package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
- package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
- package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
- package/dist/components/features/planning/planningTaskArrangement.js +5 -5
- package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
- package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
- package/dist/components/features/taskforceAgentEditorModel.js +5 -1
- package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
- package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
- package/dist/components/task/TaskCard.d.ts +5 -0
- package/dist/components/task/TaskCard.js +65 -10
- package/dist/components/task/TaskImageReviews.js +14 -5
- package/dist/components/task/TaskKanban.d.ts +6 -1
- package/dist/components/task/TaskKanban.js +152 -6
- package/dist/components/task/TaskList.d.ts +5 -0
- package/dist/components/task/TaskList.js +3 -3
- package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
- package/dist/components/ui/PasswordInput.d.ts +6 -0
- package/dist/components/ui/PasswordInput.js +11 -0
- package/dist/components/ui/TopNoticeLayer.js +1 -1
- package/dist/components/views/AppShellHeader.js +32 -11
- package/dist/components/views/PlanComparisonPage.js +12 -0
- package/dist/components/views/StandaloneLayout.js +32 -55
- package/dist/components/views/WidgetView.js +3 -3
- package/dist/components/views/panels/PlanningDrawer.js +5 -12
- package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
- package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
- package/dist/config/envSchema.js +60 -1
- package/dist/config/localServiceRuntimeContract.d.ts +13 -0
- package/dist/config/localServiceRuntimeContract.js +135 -0
- package/dist/core/AiProfileService.js +46 -8
- package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
- package/dist/core/DeletedTaskLifecycleService.js +37 -6
- package/dist/core/McpTokenService.d.ts +23 -1
- package/dist/core/McpTokenService.js +93 -10
- package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
- package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
- package/dist/core/TaskChecklistCommandService.d.ts +27 -0
- package/dist/core/TaskChecklistCommandService.js +83 -5
- package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
- package/dist/core/TaskLifecycleCommandService.js +6 -2
- package/dist/core/Taskforce.d.ts +94 -2
- package/dist/core/Taskforce.js +760 -36
- package/dist/core/types.d.ts +14 -0
- package/dist/documentReviews/commandService.d.ts +2 -1
- package/dist/documentReviews/commandService.js +6 -3
- package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.js +2 -0
- package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
- package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
- package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
- package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
- package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
- package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
- package/dist/hooks/sync/useSyncStatusControls.js +47 -11
- package/dist/hooks/tasks/taskHttpMutation.js +1 -0
- package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
- package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
- package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
- package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
- package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
- package/dist/hooks/tasks/useTaskFormActions.js +65 -12
- package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
- package/dist/hooks/ui/useSettingsModel.js +13 -2
- package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
- package/dist/hooks/ui/useSettingsPersistence.js +74 -47
- package/dist/hooks/useFilterSort.d.ts +7 -3
- package/dist/hooks/useFilterSort.js +15 -5
- package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
- package/dist/hooks/useSyncOrchestrator.js +111 -2
- package/dist/hooks/useTaskData.d.ts +40 -1
- package/dist/hooks/useTaskData.js +240 -9
- package/dist/hooks/useTaskMutations.d.ts +12 -2
- package/dist/hooks/useTaskMutations.js +266 -52
- package/dist/hooks/useTaskforce.d.ts +39 -9
- package/dist/hooks/useTaskforce.js +359 -40
- package/dist/hooks/useUiNotice.d.ts +4 -0
- package/dist/hooks/useUiNotice.js +4 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
- package/dist/mcp/clientRegistry.d.ts +2 -2
- package/dist/mcp/clientRegistry.js +1 -1
- package/dist/mcp/documentAssetRegistrar.js +53 -41
- package/dist/mcp/documentHelpers.d.ts +1 -0
- package/dist/mcp/documentHelpers.js +7 -3
- package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
- package/dist/mcp/durableTaskMutationRouter.js +10 -0
- package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
- package/dist/mcp/httpProtocolRouting.d.ts +10 -0
- package/dist/mcp/httpProtocolRouting.js +19 -0
- package/dist/mcp/localCliHealth.d.ts +2 -2
- package/dist/mcp/localCliHealth.js +2 -2
- package/dist/mcp/localServiceProxy.d.ts +1 -0
- package/dist/mcp/localServiceProxy.js +530 -68
- package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
- package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
- package/dist/mcp/runtime.d.ts +54 -79
- package/dist/mcp/runtime.js +556 -139
- package/dist/mcp/taskPlanningRegistrar.js +64 -42
- package/dist/mcp/toolCallCompatibility.js +38 -1
- package/dist/mcp/toolCatalog.d.ts +1 -0
- package/dist/mcp/toolProfiles.d.ts +2 -0
- package/dist/mcp/toolProfiles.js +10 -0
- package/dist/mcp/toolRegistry.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +1 -0
- package/dist/mcp/workflowExecutionRegistrar.js +4 -4
- package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
- package/dist/migrations/taskSchemaMigrations.js +427 -0
- package/dist/runtime/appGateDefinitions.d.ts +30 -6
- package/dist/runtime/appGateDefinitions.js +6 -6
- package/dist/runtime/appGates.d.ts +13 -13
- package/dist/runtime/appGates.js +36 -13
- package/dist/runtime/nodeAppGates.d.ts +8 -0
- package/dist/runtime/nodeAppGates.js +27 -0
- package/dist/server/cloudCollectionRead.d.ts +1 -1
- package/dist/server/cloudCollectionRead.js +2 -2
- package/dist/server/index.d.ts +6 -0
- package/dist/server/index.js +123 -14
- package/dist/server/localDatabaseIdentity.js +4 -1
- package/dist/server/localServiceLease.d.ts +3 -0
- package/dist/server/localServiceLease.js +11 -2
- package/dist/server/localServiceSessions.d.ts +14 -17
- package/dist/server/localServiceSessions.js +308 -94
- package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
- package/dist/server/rateLimit.d.ts +1 -0
- package/dist/server/rateLimit.js +4 -0
- package/dist/server/realtimeSyncWs.js +36 -12
- package/dist/server/routes/admin.d.ts +4 -0
- package/dist/server/routes/admin.js +113 -3
- package/dist/server/routes/agentRoles.js +3 -2
- package/dist/server/routes/agentSkills.js +3 -2
- package/dist/server/routes/agents.d.ts +7 -0
- package/dist/server/routes/agents.js +394 -39
- package/dist/server/routes/annotatedAttachments.js +3 -2
- package/dist/server/routes/auth.js +3 -1
- package/dist/server/routes/billing.js +5 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
- package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
- package/dist/server/routes/executorPhaseAApprovals.js +140 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
- package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
- package/dist/server/routes/githubReviewEvidence.js +116 -0
- package/dist/server/routes/localService.d.ts +15 -4
- package/dist/server/routes/localService.js +138 -40
- package/dist/server/routes/modelConnections.d.ts +24 -0
- package/dist/server/routes/modelConnections.js +205 -0
- package/dist/server/routes/primitives.d.ts +2 -0
- package/dist/server/routes/shared.d.ts +19 -0
- package/dist/server/routes/shared.js +95 -19
- package/dist/server/routes/sync.js +1 -0
- package/dist/server/routes/syncAuxRoutes.js +9 -2
- package/dist/server/routes/syncPullApplyRoutes.js +23 -4
- package/dist/server/routes/syncPushRoutes.d.ts +1 -0
- package/dist/server/routes/syncPushRoutes.js +1 -0
- package/dist/server/routes/syncV3FeedRoutes.js +27 -16
- package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
- package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
- package/dist/server/routes/syncV3OperationRoutes.js +45 -9
- package/dist/server/routes/tasks.js +124 -13
- package/dist/server/routes/workflows.js +9 -1
- package/dist/server/routes/workspaces.js +43 -1
- package/dist/server/routes.js +59 -0
- package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
- package/dist/server/workspaceDeletionAdmission.js +50 -0
- package/dist/service/localServiceCli.js +16 -0
- package/dist/service/localServiceClientLifecycle.js +36 -10
- package/dist/services/codexAppServerModelGateway.d.ts +161 -0
- package/dist/services/codexAppServerModelGateway.js +663 -0
- package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
- package/dist/services/codexDeviceCodeLoginManager.js +265 -0
- package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
- package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
- package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
- package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
- package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
- package/dist/services/executorPhaseAApprovalService.js +609 -0
- package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
- package/dist/services/executorPhaseADriftEvaluator.js +93 -0
- package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
- package/dist/services/executorPhaseAIssuerCore.js +295 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
- package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
- package/dist/services/githubReviewEvidenceRuntime.js +30 -0
- package/dist/services/githubReviewEvidenceService.d.ts +93 -0
- package/dist/services/githubReviewEvidenceService.js +336 -0
- package/dist/services/modelGateway.d.ts +7 -0
- package/dist/services/modelProviderConnectionService.d.ts +71 -0
- package/dist/services/modelProviderConnectionService.js +279 -0
- package/dist/services/modelProviderCredentialHome.d.ts +32 -0
- package/dist/services/modelProviderCredentialHome.js +271 -0
- package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
- package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
- package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
- package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
- package/dist/services/taskforceAgentMcpBridge.js +30 -27
- package/dist/shared/adminEdgeProxy.d.ts +5 -0
- package/dist/shared/adminEdgeProxy.js +94 -0
- package/dist/shared/adminProxySessionCookies.d.ts +16 -0
- package/dist/shared/adminProxySessionCookies.js +86 -0
- package/dist/shared/aiProfileColors.d.ts +31 -1
- package/dist/shared/aiProfileColors.js +14 -6
- package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
- package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
- package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
- package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
- package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
- package/dist/shared/executorPhaseADriftContracts.js +63 -0
- package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
- package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
- package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
- package/dist/shared/executorPhaseARunAuthorization.js +232 -0
- package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
- package/dist/shared/executorPhaseASchemaValidation.js +53 -0
- package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
- package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
- package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
- package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
- package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
- package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
- package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
- package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
- package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
- package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
- package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
- package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
- package/dist/shared/executorPhaseATiming.d.ts +1 -0
- package/dist/shared/executorPhaseATiming.js +1 -0
- package/dist/shared/planningIdentity.js +1 -1
- package/dist/shared/productLogoKeys.d.ts +2 -0
- package/dist/shared/productLogoKeys.js +18 -0
- package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
- package/dist/shared/taskforceAgentDefinition.js +6 -3
- package/dist/shared/taskforceAgentModels.d.ts +1 -0
- package/dist/shared/taskforceAgentModels.js +36 -3
- package/dist/shared/userFeatureGrants.d.ts +4 -0
- package/dist/shared/userFeatureGrants.js +7 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
- package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
- package/dist/storage/modelProviderConnectionStore.js +446 -0
- package/dist/storage/postgresAdapter.d.ts +24 -3
- package/dist/storage/postgresAdapter.js +117 -14
- package/dist/storage/postgresWorker.js +22 -5
- package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
- package/dist/storage/postgresWorkerProtocol.js +30 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
- package/dist/sync/cloudSyncApi.d.ts +4 -1
- package/dist/sync/cloudSyncApi.js +7 -2
- package/dist/sync/contentSyncState.d.ts +1 -1
- package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
- package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
- package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
- package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
- package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
- package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
- package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
- package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
- package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
- package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
- package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
- package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
- package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
- package/dist/sync/syncApplyHandlers.d.ts +2 -0
- package/dist/sync/syncApplyHandlers.js +10 -1
- package/dist/sync/syncService.d.ts +17 -0
- package/dist/sync/syncService.js +87 -19
- package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
- package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
- package/dist/sync/v3/combinedFeedCapability.js +8 -0
- package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
- package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
- package/dist/sync/v3/durableOperationReplay.js +18 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
- package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
- package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
- package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
- package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
- package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
- package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
- package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
- package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
- package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
- package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
- package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
- package/dist/sync/v3/localTaskMetadataClient.js +1 -0
- package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
- package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
- package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
- package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
- package/dist/sync/v3/localTaskStatusClient.js +6 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
- package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
- package/dist/sync/v3/syncDurabilityStore.js +199 -13
- package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
- package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
- package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
- package/dist/sync/v3/taskChecklistMutationService.js +48 -1
- package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
- package/dist/sync/v3/taskCreateMutationService.js +7 -4
- package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
- package/dist/sync/v3/taskMetadataMutationService.js +4 -0
- package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
- package/dist/sync/v3/taskRestoreMutationService.js +7 -4
- package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
- package/dist/sync/v3/taskStatusMutationService.js +123 -3
- package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
- package/dist/sync/v3/workflowAssignmentSync.js +30 -0
- package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
- package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
- package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
- package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
- package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
- package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
- package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
- package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
- package/dist/sync/workspacePullFeed.js +2 -1
- package/dist/sync/workspaceRepair.d.ts +8 -2
- package/dist/sync/workspaceRepair.js +222 -6
- package/dist/sync/workspaceSyncModel.d.ts +21 -0
- package/dist/sync/workspaceSyncModel.js +35 -7
- package/dist/sync/workspaceSyncState.d.ts +1 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
- package/dist/types.d.ts +47 -1
- package/dist/types.js +6 -0
- package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
- package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
- package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
- package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
- package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
- package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
- package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
- package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
- package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
- package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
- package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
- package/dist/ui/assets/index-CTsDBaef.js +7 -0
- package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
- package/dist/ui/branding/logos/letterhead_dark.png +0 -0
- package/dist/ui/branding/logos/letterhead_light.png +0 -0
- package/dist/ui/branding/logos/signature_dark.png +0 -0
- package/dist/ui/branding/logos/signature_light.png +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/aiProfileDefaultLogo.js +16 -48
- package/dist/utils/httpSetCookie.d.ts +1 -0
- package/dist/utils/httpSetCookie.js +4 -1
- package/dist/utils/localRuntimeUrl.d.ts +1 -0
- package/dist/utils/localRuntimeUrl.js +14 -0
- package/dist/utils/productLogoRegistry.d.ts +2 -0
- package/dist/utils/productLogoRegistry.js +36 -0
- package/dist/utils/syncStatusPresentation.d.ts +4 -0
- package/dist/utils/syncStatusPresentation.js +17 -0
- package/dist/utils/taskActivity.d.ts +3 -2
- package/dist/utils/taskActivity.js +19 -2
- package/dist/utils/taskEditorReconciliation.d.ts +40 -0
- package/dist/utils/taskEditorReconciliation.js +217 -0
- package/dist/utils/taskEvents.d.ts +2 -0
- package/dist/utils/taskNormalization.d.ts +1 -0
- package/dist/utils/taskNormalization.js +39 -0
- package/dist/utils/taskSearch.js +2 -2
- package/dist/utils/uiNotice.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
- package/dist/utils/workspaceSyncPresentation.js +23 -17
- package/package.json +36 -6
- package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
- package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
- package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
- package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
- package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
- package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
- package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
- package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
- package/dist/ui/assets/index-BUplSsv_.js +0 -7
- package/dist/ui/assets/index-gz2EXuoK.css +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DatabaseAdapter } from '../storage/databaseAdapter.js';
|
|
2
|
-
import type { McpOAuthProvider, McpAccessTokenRecord, McpAccessTokenListResult, McpAccessTokenIssueResult, McpAccessTokenAuthResult, McpAccessTokenInspectionResult, McpOAuthClientRecord, McpOAuthConnectorGrantRecord, McpOAuthTokenExchangeResult, McpOAuthAccessTokenAuthResult } from './types.js';
|
|
2
|
+
import type { McpCloudToolProfile, McpOAuthProvider, McpAccessTokenRecord, McpAccessTokenListResult, McpAccessTokenIssueResult, McpAccessTokenAuthResult, McpAccessTokenInspectionResult, McpOAuthClientRecord, McpOAuthConnectorGrantRecord, McpOAuthTokenExchangeResult, McpOAuthAccessTokenAuthResult } from './types.js';
|
|
3
3
|
export interface McpTokenServiceDeps {
|
|
4
4
|
/** Resolve plan/account access state for a given user */
|
|
5
5
|
getAccountAccessStatus: (userId: string) => {
|
|
@@ -19,6 +19,8 @@ export declare class McpTokenService {
|
|
|
19
19
|
private normalizeAccessRole;
|
|
20
20
|
private normalizePermissionMode;
|
|
21
21
|
private normalizeMcpAccessTokenScopes;
|
|
22
|
+
private normalizeMcpCloudToolProfile;
|
|
23
|
+
private requireMcpCloudToolProfile;
|
|
22
24
|
private createMcpAccessTokenPrefix;
|
|
23
25
|
private parseMcpAccessToken;
|
|
24
26
|
private normalizeMcpOAuthProvider;
|
|
@@ -38,6 +40,7 @@ export declare class McpTokenService {
|
|
|
38
40
|
private resolveMcpAccessTokenStatus;
|
|
39
41
|
private rowToMcpAccessTokenRecord;
|
|
40
42
|
private assertCanManageOwnMcpAccessToken;
|
|
43
|
+
private requireMcpToolProfileAdministrator;
|
|
41
44
|
private countActiveMcpAccessTokens;
|
|
42
45
|
revokeMcpCredentialsForUserWorkspace(userId: string, workspaceId: string, revokedByUserId?: string | null): void;
|
|
43
46
|
revokeMcpCredentialsForWorkspace(workspaceId: string, revokedByUserId?: string | null): void;
|
|
@@ -52,6 +55,7 @@ export declare class McpTokenService {
|
|
|
52
55
|
workspaceId: string;
|
|
53
56
|
name: string;
|
|
54
57
|
scopes: unknown;
|
|
58
|
+
toolProfile?: McpCloudToolProfile;
|
|
55
59
|
expiresAt?: string | null;
|
|
56
60
|
createdByIp?: string | null;
|
|
57
61
|
}): McpAccessTokenIssueResult;
|
|
@@ -71,6 +75,15 @@ export declare class McpTokenService {
|
|
|
71
75
|
tokenId: string;
|
|
72
76
|
createdByIp?: string | null;
|
|
73
77
|
}): McpAccessTokenIssueResult;
|
|
78
|
+
updateMcpAccessTokenToolProfile(input: {
|
|
79
|
+
actorUserId: string;
|
|
80
|
+
workspaceId: string;
|
|
81
|
+
tokenId: string;
|
|
82
|
+
toolProfile: unknown;
|
|
83
|
+
}): {
|
|
84
|
+
record: McpAccessTokenRecord;
|
|
85
|
+
previousToolProfile: McpCloudToolProfile;
|
|
86
|
+
};
|
|
74
87
|
authenticateMcpAccessToken(token: string, workspaceId?: string): McpAccessTokenAuthResult | null;
|
|
75
88
|
inspectMcpAccessToken(token: string): McpAccessTokenInspectionResult | null;
|
|
76
89
|
recordMcpAccessTokenUsage(input: {
|
|
@@ -116,6 +129,15 @@ export declare class McpTokenService {
|
|
|
116
129
|
workspaceId: string;
|
|
117
130
|
grantId: string;
|
|
118
131
|
}): McpOAuthConnectorGrantRecord;
|
|
132
|
+
updateMcpOAuthConnectorGrantToolProfile(input: {
|
|
133
|
+
actorUserId: string;
|
|
134
|
+
workspaceId: string;
|
|
135
|
+
grantId: string;
|
|
136
|
+
toolProfile: unknown;
|
|
137
|
+
}): {
|
|
138
|
+
record: McpOAuthConnectorGrantRecord;
|
|
139
|
+
previousToolProfile: McpCloudToolProfile;
|
|
140
|
+
};
|
|
119
141
|
authenticateMcpOAuthAccessToken(token: string, workspaceId?: string): McpOAuthAccessTokenAuthResult | null;
|
|
120
142
|
bindMcpOAuthConnectorGrantAiProfile(input: {
|
|
121
143
|
grantId: string;
|
|
@@ -7,6 +7,7 @@ const MCP_ACCESS_TOKEN_DEFAULT_PAGE_SIZE = 20;
|
|
|
7
7
|
const MCP_ACCESS_TOKEN_MAX_PAGE_SIZE = 100;
|
|
8
8
|
const MCP_ACCESS_TOKEN_ALLOWED_SCOPES = ['tasks:read', 'tasks:write', 'workspace:read'];
|
|
9
9
|
const MCP_OAUTH_AUTH_CODE_TTL_MS = 10 * 60 * 1000;
|
|
10
|
+
const MCP_CLOUD_TOOL_PROFILES = ['default', 'extended'];
|
|
10
11
|
/**
|
|
11
12
|
* Handles MCP direct-access tokens and MCP OAuth connector flow
|
|
12
13
|
* (client registration, authorization codes, token exchange, grant lifecycle).
|
|
@@ -52,6 +53,19 @@ export class McpTokenService {
|
|
|
52
53
|
}
|
|
53
54
|
return unique;
|
|
54
55
|
}
|
|
56
|
+
normalizeMcpCloudToolProfile(value, fallback = 'default') {
|
|
57
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
58
|
+
return MCP_CLOUD_TOOL_PROFILES.includes(normalized)
|
|
59
|
+
? normalized
|
|
60
|
+
: fallback;
|
|
61
|
+
}
|
|
62
|
+
requireMcpCloudToolProfile(value) {
|
|
63
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
64
|
+
if (!MCP_CLOUD_TOOL_PROFILES.includes(normalized)) {
|
|
65
|
+
throw new TaskforceRuleError('toolProfile must be default or extended', 400, 'MCP_TOOL_PROFILE_INVALID');
|
|
66
|
+
}
|
|
67
|
+
return normalized;
|
|
68
|
+
}
|
|
55
69
|
createMcpAccessTokenPrefix() {
|
|
56
70
|
return `tfmcp_${randomBytes(6).toString('hex')}`;
|
|
57
71
|
}
|
|
@@ -204,6 +218,7 @@ export class McpTokenService {
|
|
|
204
218
|
workspaceId: String(row?.workspace_id || ''),
|
|
205
219
|
userId: String(row?.user_id || ''),
|
|
206
220
|
scopes,
|
|
221
|
+
toolProfile: this.normalizeMcpCloudToolProfile(row?.tool_profile),
|
|
207
222
|
tokenPrefix: String(row?.token_prefix || ''),
|
|
208
223
|
status: this.resolveMcpOAuthGrantStatus(row),
|
|
209
224
|
lastUsedAt: row?.last_used_at ? String(row.last_used_at) : null,
|
|
@@ -286,6 +301,7 @@ export class McpTokenService {
|
|
|
286
301
|
u.email AS user_email,
|
|
287
302
|
t.name,
|
|
288
303
|
t.scopes_json,
|
|
304
|
+
t.tool_profile,
|
|
289
305
|
t.token_prefix,
|
|
290
306
|
t.token_hash,
|
|
291
307
|
t.status,
|
|
@@ -331,6 +347,7 @@ export class McpTokenService {
|
|
|
331
347
|
userEmail: row.user_email ? String(row.user_email) : null,
|
|
332
348
|
name: String(row.name || ''),
|
|
333
349
|
scopes,
|
|
350
|
+
toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
|
|
334
351
|
tokenPrefix: String(row.token_prefix || ''),
|
|
335
352
|
status: this.resolveMcpAccessTokenStatus(row),
|
|
336
353
|
lastUsedAt: row.last_used_at ? String(row.last_used_at) : null,
|
|
@@ -353,6 +370,12 @@ export class McpTokenService {
|
|
|
353
370
|
throw new TaskforceRuleError('Forbidden', 403, 'FORBIDDEN');
|
|
354
371
|
}
|
|
355
372
|
}
|
|
373
|
+
requireMcpToolProfileAdministrator(actorUserId, workspaceId) {
|
|
374
|
+
const member = this.getActiveWorkspaceMemberForMcp(actorUserId, workspaceId);
|
|
375
|
+
if (member.role !== 'owner' && member.role !== 'admin') {
|
|
376
|
+
throw new TaskforceRuleError('Workspace owner or admin access is required', 403, 'MCP_TOOL_PROFILE_ADMIN_REQUIRED');
|
|
377
|
+
}
|
|
378
|
+
}
|
|
356
379
|
countActiveMcpAccessTokens(userId, workspaceId) {
|
|
357
380
|
const now = new Date().toISOString();
|
|
358
381
|
const row = this.db.prepare(`
|
|
@@ -446,6 +469,7 @@ export class McpTokenService {
|
|
|
446
469
|
u.email AS user_email,
|
|
447
470
|
t.name,
|
|
448
471
|
t.scopes_json,
|
|
472
|
+
t.tool_profile,
|
|
449
473
|
t.token_prefix,
|
|
450
474
|
t.token_hash,
|
|
451
475
|
t.status,
|
|
@@ -480,6 +504,7 @@ export class McpTokenService {
|
|
|
480
504
|
throw new TaskforceRuleError('Token name is required', 400, 'MCP_TOKEN_NAME_REQUIRED');
|
|
481
505
|
}
|
|
482
506
|
const scopes = this.normalizeMcpAccessTokenScopes(input.scopes);
|
|
507
|
+
const toolProfile = this.normalizeMcpCloudToolProfile(input.toolProfile);
|
|
483
508
|
const expiresAt = input.expiresAt ? String(input.expiresAt).trim() : null;
|
|
484
509
|
const now = new Date().toISOString();
|
|
485
510
|
if (expiresAt && expiresAt <= now) {
|
|
@@ -501,12 +526,12 @@ export class McpTokenService {
|
|
|
501
526
|
const createdByIp = input.createdByIp ? String(input.createdByIp).trim() : null;
|
|
502
527
|
this.db.prepare(`
|
|
503
528
|
INSERT INTO mcp_access_tokens (
|
|
504
|
-
id, tenant_id, workspace_id, user_id, name, scopes_json, token_prefix, token_hash, status,
|
|
529
|
+
id, tenant_id, workspace_id, user_id, name, scopes_json, tool_profile, token_prefix, token_hash, status,
|
|
505
530
|
last_used_at, last_used_ip, last_used_user_agent, created_by_ip, expires_at, revoked_at,
|
|
506
531
|
revoked_by_user_id, created_at, updated_at
|
|
507
532
|
)
|
|
508
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, NULL, NULL, ?, ?)
|
|
509
|
-
`).run(tokenId, this.tenantId, member.workspaceId, member.userId, name, JSON.stringify(scopes), tokenPrefix, tokenHash, createdByIp, expiresAt, now, now);
|
|
533
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, NULL, NULL, ?, ?)
|
|
534
|
+
`).run(tokenId, this.tenantId, member.workspaceId, member.userId, name, JSON.stringify(scopes), toolProfile, tokenPrefix, tokenHash, createdByIp, expiresAt, now, now);
|
|
510
535
|
const row = this.getMcpAccessTokenRow(tokenId, member.workspaceId);
|
|
511
536
|
if (!row) {
|
|
512
537
|
throw new TaskforceRuleError('Failed to create MCP token', 500, 'MCP_TOKEN_CREATE_FAILED');
|
|
@@ -573,18 +598,39 @@ export class McpTokenService {
|
|
|
573
598
|
workspaceId: revoked.workspaceId,
|
|
574
599
|
name: revoked.name,
|
|
575
600
|
scopes: revoked.scopes,
|
|
601
|
+
toolProfile: revoked.toolProfile,
|
|
576
602
|
expiresAt: revoked.expiresAt || null,
|
|
577
603
|
createdByIp: input.createdByIp || null,
|
|
578
604
|
});
|
|
579
605
|
});
|
|
580
606
|
return tx();
|
|
581
607
|
}
|
|
608
|
+
updateMcpAccessTokenToolProfile(input) {
|
|
609
|
+
this.requireMcpToolProfileAdministrator(input.actorUserId, input.workspaceId);
|
|
610
|
+
const row = this.getMcpAccessTokenRow(input.tokenId, input.workspaceId);
|
|
611
|
+
if (!row) {
|
|
612
|
+
throw new TaskforceRuleError('MCP token not found', 404, 'MCP_TOKEN_NOT_FOUND');
|
|
613
|
+
}
|
|
614
|
+
const previousToolProfile = this.normalizeMcpCloudToolProfile(row.tool_profile);
|
|
615
|
+
const toolProfile = this.requireMcpCloudToolProfile(input.toolProfile);
|
|
616
|
+
const now = new Date().toISOString();
|
|
617
|
+
this.db.prepare(`
|
|
618
|
+
UPDATE mcp_access_tokens
|
|
619
|
+
SET tool_profile = ?, updated_at = ?
|
|
620
|
+
WHERE tenant_id = ? AND workspace_id = ? AND id = ?
|
|
621
|
+
`).run(toolProfile, now, this.tenantId, input.workspaceId, row.id);
|
|
622
|
+
const updated = this.getMcpAccessTokenRow(row.id, input.workspaceId);
|
|
623
|
+
if (!updated) {
|
|
624
|
+
throw new TaskforceRuleError('MCP token not found', 404, 'MCP_TOKEN_NOT_FOUND');
|
|
625
|
+
}
|
|
626
|
+
return { record: this.rowToMcpAccessTokenRecord(updated), previousToolProfile };
|
|
627
|
+
}
|
|
582
628
|
authenticateMcpAccessToken(token, workspaceId) {
|
|
583
629
|
const parsed = this.parseMcpAccessToken(token);
|
|
584
630
|
if (!parsed)
|
|
585
631
|
return null;
|
|
586
632
|
const row = this.db.prepare(`
|
|
587
|
-
SELECT id, workspace_id, user_id, scopes_json, token_hash, status, expires_at, revoked_at
|
|
633
|
+
SELECT id, workspace_id, user_id, scopes_json, tool_profile, token_hash, status, expires_at, revoked_at
|
|
588
634
|
FROM mcp_access_tokens
|
|
589
635
|
WHERE tenant_id = ?
|
|
590
636
|
AND token_prefix = ?
|
|
@@ -612,6 +658,7 @@ export class McpTokenService {
|
|
|
612
658
|
workspaceId: row.workspace_id,
|
|
613
659
|
userId: row.user_id,
|
|
614
660
|
scopes,
|
|
661
|
+
toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
|
|
615
662
|
status,
|
|
616
663
|
};
|
|
617
664
|
}
|
|
@@ -620,7 +667,7 @@ export class McpTokenService {
|
|
|
620
667
|
if (!parsed)
|
|
621
668
|
return null;
|
|
622
669
|
const row = this.db.prepare(`
|
|
623
|
-
SELECT id, workspace_id, user_id, name, scopes_json, token_hash, status, expires_at, revoked_at
|
|
670
|
+
SELECT id, workspace_id, user_id, name, scopes_json, tool_profile, token_hash, status, expires_at, revoked_at
|
|
624
671
|
FROM mcp_access_tokens
|
|
625
672
|
WHERE tenant_id = ?
|
|
626
673
|
AND token_prefix = ?
|
|
@@ -644,6 +691,7 @@ export class McpTokenService {
|
|
|
644
691
|
userId: row.user_id,
|
|
645
692
|
name: String(row.name || ''),
|
|
646
693
|
scopes,
|
|
694
|
+
toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
|
|
647
695
|
status: this.resolveMcpAccessTokenStatus(row),
|
|
648
696
|
};
|
|
649
697
|
}
|
|
@@ -783,7 +831,7 @@ export class McpTokenService {
|
|
|
783
831
|
const clientName = String(client.client_name || this.defaultMcpOAuthClientName(provider)).trim() || this.defaultMcpOAuthClientName(provider);
|
|
784
832
|
const tx = this.db.transaction(() => {
|
|
785
833
|
const existingRows = this.db.prepare(`
|
|
786
|
-
SELECT id, ai_profile_id, ai_profile_token, ai_profile_name
|
|
834
|
+
SELECT id, tool_profile, ai_profile_id, ai_profile_token, ai_profile_name
|
|
787
835
|
FROM mcp_oauth_connector_grants
|
|
788
836
|
WHERE tenant_id = ?
|
|
789
837
|
AND provider = ?
|
|
@@ -794,6 +842,7 @@ export class McpTokenService {
|
|
|
794
842
|
ORDER BY created_at DESC
|
|
795
843
|
`).all(this.tenantId, provider, String(client.id), String(row.user_id), String(row.workspace_id));
|
|
796
844
|
const previousBinding = existingRows.find((existing) => existing.ai_profile_id && existing.ai_profile_token && existing.ai_profile_name) || null;
|
|
845
|
+
const toolProfile = this.normalizeMcpCloudToolProfile(existingRows[0]?.tool_profile);
|
|
797
846
|
const revokeTime = new Date().toISOString();
|
|
798
847
|
existingRows.forEach((existing) => {
|
|
799
848
|
if (!existing?.id)
|
|
@@ -819,12 +868,12 @@ export class McpTokenService {
|
|
|
819
868
|
const tokenHash = hashMcpOAuthSecret(secret);
|
|
820
869
|
this.db.prepare(`
|
|
821
870
|
INSERT INTO mcp_oauth_connector_grants (
|
|
822
|
-
id, tenant_id, provider, client_id, client_name, product_client_id, user_id, workspace_id, scopes_json,
|
|
871
|
+
id, tenant_id, provider, client_id, client_name, product_client_id, user_id, workspace_id, scopes_json, tool_profile,
|
|
823
872
|
token_prefix, token_hash, status, last_used_at, revoked_at, revoked_by_user_id,
|
|
824
873
|
ai_profile_id, ai_profile_token, ai_profile_name, created_at, updated_at
|
|
825
874
|
)
|
|
826
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, ?, ?, ?)
|
|
827
|
-
`).run(grantId, this.tenantId, provider, String(client.id || ''), clientName, client.product_client_id ? String(client.product_client_id) : null, String(row.user_id), String(row.workspace_id), JSON.stringify(scopes), tokenPrefix, tokenHash, previousBinding?.ai_profile_id || null, previousBinding?.ai_profile_token || null, previousBinding?.ai_profile_name || null, now, now);
|
|
875
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, NULL, ?, ?, ?, ?, ?)
|
|
876
|
+
`).run(grantId, this.tenantId, provider, String(client.id || ''), clientName, client.product_client_id ? String(client.product_client_id) : null, String(row.user_id), String(row.workspace_id), JSON.stringify(scopes), toolProfile, tokenPrefix, tokenHash, previousBinding?.ai_profile_id || null, previousBinding?.ai_profile_token || null, previousBinding?.ai_profile_name || null, now, now);
|
|
828
877
|
this.db.prepare(`
|
|
829
878
|
UPDATE mcp_oauth_auth_codes
|
|
830
879
|
SET used_at = ?
|
|
@@ -909,12 +958,45 @@ export class McpTokenService {
|
|
|
909
958
|
}
|
|
910
959
|
return this.rowToMcpOAuthConnectorGrantRecord(updated);
|
|
911
960
|
}
|
|
961
|
+
updateMcpOAuthConnectorGrantToolProfile(input) {
|
|
962
|
+
this.requireMcpToolProfileAdministrator(input.actorUserId, input.workspaceId);
|
|
963
|
+
const row = this.db.prepare(`
|
|
964
|
+
SELECT *
|
|
965
|
+
FROM mcp_oauth_connector_grants
|
|
966
|
+
WHERE tenant_id = ? AND workspace_id = ? AND id = ?
|
|
967
|
+
LIMIT 1
|
|
968
|
+
`).get(this.tenantId, input.workspaceId, String(input.grantId || '').trim());
|
|
969
|
+
if (!row?.id) {
|
|
970
|
+
throw new TaskforceRuleError('MCP connector grant not found', 404, 'MCP_OAUTH_GRANT_NOT_FOUND');
|
|
971
|
+
}
|
|
972
|
+
const previousToolProfile = this.normalizeMcpCloudToolProfile(row.tool_profile);
|
|
973
|
+
const toolProfile = this.requireMcpCloudToolProfile(input.toolProfile);
|
|
974
|
+
const now = new Date().toISOString();
|
|
975
|
+
this.db.prepare(`
|
|
976
|
+
UPDATE mcp_oauth_connector_grants
|
|
977
|
+
SET tool_profile = ?, updated_at = ?
|
|
978
|
+
WHERE tenant_id = ? AND workspace_id = ? AND id = ?
|
|
979
|
+
`).run(toolProfile, now, this.tenantId, input.workspaceId, String(row.id));
|
|
980
|
+
const updated = this.db.prepare(`
|
|
981
|
+
SELECT *
|
|
982
|
+
FROM mcp_oauth_connector_grants
|
|
983
|
+
WHERE tenant_id = ? AND workspace_id = ? AND id = ?
|
|
984
|
+
LIMIT 1
|
|
985
|
+
`).get(this.tenantId, input.workspaceId, String(row.id));
|
|
986
|
+
if (!updated) {
|
|
987
|
+
throw new TaskforceRuleError('MCP connector grant not found', 404, 'MCP_OAUTH_GRANT_NOT_FOUND');
|
|
988
|
+
}
|
|
989
|
+
return {
|
|
990
|
+
record: this.rowToMcpOAuthConnectorGrantRecord(updated),
|
|
991
|
+
previousToolProfile,
|
|
992
|
+
};
|
|
993
|
+
}
|
|
912
994
|
authenticateMcpOAuthAccessToken(token, workspaceId) {
|
|
913
995
|
const parsed = this.parseMcpOAuthOpaqueSecret(token, 'tfmcpoauth_');
|
|
914
996
|
if (!parsed)
|
|
915
997
|
return null;
|
|
916
998
|
const row = this.db.prepare(`
|
|
917
|
-
SELECT id, provider, client_id, product_client_id, user_id, workspace_id, scopes_json, token_hash, status, revoked_at,
|
|
999
|
+
SELECT id, provider, client_id, product_client_id, user_id, workspace_id, scopes_json, tool_profile, token_hash, status, revoked_at,
|
|
918
1000
|
ai_profile_id, ai_profile_token, ai_profile_name
|
|
919
1001
|
FROM mcp_oauth_connector_grants
|
|
920
1002
|
WHERE tenant_id = ?
|
|
@@ -945,6 +1027,7 @@ export class McpTokenService {
|
|
|
945
1027
|
provider: this.normalizeMcpOAuthProvider(row.provider),
|
|
946
1028
|
productClientId: row?.product_client_id ? String(row.product_client_id) : null,
|
|
947
1029
|
scopes,
|
|
1030
|
+
toolProfile: this.normalizeMcpCloudToolProfile(row.tool_profile),
|
|
948
1031
|
status: this.resolveMcpOAuthGrantStatus(row),
|
|
949
1032
|
aiProfileId: row?.ai_profile_id ? String(row.ai_profile_id) : null,
|
|
950
1033
|
aiProfileToken: row?.ai_profile_token ? String(row.ai_profile_token) : null,
|
|
@@ -8,7 +8,7 @@ export declare class DurableTaskAttachmentLinksApplyError extends Error {
|
|
|
8
8
|
constructor(message: string, code: 'TASK_ATTACHMENT_ASSET_NOT_READY' | 'TASK_ATTACHMENT_ASSET_INVALID' | 'TASK_ATTACHMENT_LINK_INVALID', statusCode: number, assetId?: string | undefined);
|
|
9
9
|
}
|
|
10
10
|
export interface DurableTaskAttachmentLinksCore {
|
|
11
|
-
getWorkspaceAssetStore(): Pick<WorkspaceAssetStore, 'get' | 'listLinksForTask' | 'adoptReadableReferenceNumber'>;
|
|
11
|
+
getWorkspaceAssetStore(): Pick<WorkspaceAssetStore, 'get' | 'listLinksForTask' | 'adoptReadableReferenceNumber' | 'restoreDeleted'>;
|
|
12
12
|
getWorkspaceAssetDispatchReadiness(assetId: string, workspaceId: string): {
|
|
13
13
|
ready: boolean;
|
|
14
14
|
retryable: boolean;
|
|
@@ -16,7 +16,7 @@ export interface DurableTaskAttachmentLinksCore {
|
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
export interface DurableWorkspaceTaskAttachmentLinksCore extends DurableTaskAttachmentLinksCore {
|
|
19
|
-
getWorkspaceAssetStore(): Pick<WorkspaceAssetStore, 'get' | 'listLinksForTask' | 'listLinksForWorkspace' | 'listAllNormalizedByWorkspace' | 'adoptReadableReferenceNumber'>;
|
|
19
|
+
getWorkspaceAssetStore(): Pick<WorkspaceAssetStore, 'get' | 'listLinksForTask' | 'listLinksForWorkspace' | 'listAllNormalizedByWorkspace' | 'adoptReadableReferenceNumber' | 'restoreDeleted'>;
|
|
20
20
|
}
|
|
21
21
|
export declare function resolveTaskCardCoverAssetIdForLinks(input: {
|
|
22
22
|
currentCardCoverAssetId?: string | null;
|
|
@@ -29,6 +29,7 @@ export declare function resolveTaskAttachmentLinksForDurableSync(core: DurableTa
|
|
|
29
29
|
requireDispatchReady?: boolean;
|
|
30
30
|
adoptAuthoritativeReferenceNumber?: boolean;
|
|
31
31
|
ignoreAssetMetadataSnapshots?: boolean;
|
|
32
|
+
restoreDeletedExternalAssetForAuthoritativeSync?: boolean;
|
|
32
33
|
}): AttachmentItem[];
|
|
33
34
|
export declare function normalizeTaskAttachmentDescriptorsForDurableSync(core: DurableTaskAttachmentLinksCore, workspaceId: string, attachments: readonly AttachmentItem[], options?: {
|
|
34
35
|
requireDispatchReady?: boolean;
|
|
@@ -53,6 +53,12 @@ function canonicalRole(asset, requested) {
|
|
|
53
53
|
}
|
|
54
54
|
return expected;
|
|
55
55
|
}
|
|
56
|
+
function canonicalPersistedRole(asset, persisted) {
|
|
57
|
+
// Historical external links predate the reference-only invariant. Repair
|
|
58
|
+
// projections must publish the current canonical shape, while mutation
|
|
59
|
+
// inputs continue through canonicalRole and remain strictly validated.
|
|
60
|
+
return asset.storageProvider === 'external' ? 'reference' : canonicalRole(asset, persisted);
|
|
61
|
+
}
|
|
56
62
|
function referenceFields(asset) {
|
|
57
63
|
if (!asset.referenceNumber)
|
|
58
64
|
return { referenceNumber: null, referenceLabel: null };
|
|
@@ -83,9 +89,13 @@ function assertReady(core, workspaceId, asset, options) {
|
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
function canonicalLink(asset, link, fallbackOrder) {
|
|
92
|
+
// Historical task links could persist an external asset as an attachment.
|
|
93
|
+
// External assets are references by contract, so repair/export must emit the
|
|
94
|
+
// canonical role rather than reproducing an un-installable legacy link.
|
|
95
|
+
const role = asset.storageProvider === 'external' ? 'reference' : link.role;
|
|
86
96
|
return {
|
|
87
97
|
assetId: asset.assetId,
|
|
88
|
-
role
|
|
98
|
+
role,
|
|
89
99
|
order: Number.isSafeInteger(link.sortOrder) && Number(link.sortOrder) >= 0
|
|
90
100
|
? Number(link.sortOrder)
|
|
91
101
|
: fallbackOrder,
|
|
@@ -107,7 +117,7 @@ export function listTaskAttachmentLinksForDurableSync(core, workspaceId, taskId)
|
|
|
107
117
|
fail(`Task attachment asset is deleted: ${link.assetId}`, 'TASK_ATTACHMENT_ASSET_INVALID', 400);
|
|
108
118
|
}
|
|
109
119
|
assertReady(core, workspaceId, asset);
|
|
110
|
-
return canonicalLink(asset, link, index);
|
|
120
|
+
return canonicalLink(asset, { ...link, role: canonicalPersistedRole(asset, link.role) }, index);
|
|
111
121
|
})
|
|
112
122
|
.sort((left, right) => left.order - right.order
|
|
113
123
|
|| (left.assetId < right.assetId ? -1 : left.assetId > right.assetId ? 1 : 0)
|
|
@@ -139,7 +149,7 @@ export function listWorkspaceTaskAttachmentLinksForDurableSync(core, workspaceId
|
|
|
139
149
|
fail(`Task attachment asset is deleted: ${link.assetId}`, 'TASK_ATTACHMENT_ASSET_INVALID', 400);
|
|
140
150
|
}
|
|
141
151
|
assertReady(core, workspaceId, asset);
|
|
142
|
-
return canonicalLink(asset, link, index);
|
|
152
|
+
return canonicalLink(asset, { ...link, role: canonicalPersistedRole(asset, link.role) }, index);
|
|
143
153
|
}).sort((left, right) => left.order - right.order
|
|
144
154
|
|| (left.assetId < right.assetId ? -1 : left.assetId > right.assetId ? 1 : 0)
|
|
145
155
|
|| (left.role < right.role ? -1 : left.role > right.role ? 1 : 0))
|
|
@@ -156,6 +166,14 @@ export function resolveTaskAttachmentLinksForDurableSync(core, workspaceId, link
|
|
|
156
166
|
if (!asset) {
|
|
157
167
|
fail(`Task attachment asset is unavailable because it has not reached this runtime: ${link.assetId}`, 'TASK_ATTACHMENT_ASSET_NOT_READY', 425, link.assetId);
|
|
158
168
|
}
|
|
169
|
+
if (asset.deletedAt
|
|
170
|
+
&& asset.storageProvider === 'external'
|
|
171
|
+
&& options?.restoreDeletedExternalAssetForAuthoritativeSync === true) {
|
|
172
|
+
// External pointers do not travel through binary content hydration.
|
|
173
|
+
// An active authoritative link is the lifecycle proof needed to
|
|
174
|
+
// revive the existing local placeholder inside the apply transaction.
|
|
175
|
+
asset = store.restoreDeleted(asset.assetId, workspaceId, asset.updatedAt) || asset;
|
|
176
|
+
}
|
|
159
177
|
assertReady(core, workspaceId, asset, options);
|
|
160
178
|
// Replicated apply may align independently hydrated local D-/I- numbers
|
|
161
179
|
// to cloud authority. Ordinary local/cloud mutation writers must never
|
|
@@ -175,8 +193,8 @@ export function resolveTaskAttachmentLinksForDurableSync(core, workspaceId, link
|
|
|
175
193
|
const displayName = String(link.displayName
|
|
176
194
|
|| (options?.ignoreAssetMetadataSnapshots === true ? '' : link.originalFilename)
|
|
177
195
|
|| (options?.ignoreAssetMetadataSnapshots === true ? '' : link.caption)
|
|
178
|
-
|| asset.originalFilename
|
|
179
|
-
|| asset.logicalName).trim() || null;
|
|
196
|
+
|| (options?.ignoreAssetMetadataSnapshots === true ? '' : asset.originalFilename)
|
|
197
|
+
|| (options?.ignoreAssetMetadataSnapshots === true ? '' : asset.logicalName)).trim() || null;
|
|
180
198
|
const projected = canonicalLink(asset, { role, displayName, sortOrder: index }, index);
|
|
181
199
|
if (options?.ignoreAssetMetadataSnapshots !== true
|
|
182
200
|
&& ((link.referenceNumber ?? null) !== (projected.referenceNumber ?? null)
|
|
@@ -187,12 +205,18 @@ export function resolveTaskAttachmentLinksForDurableSync(core, workspaceId, link
|
|
|
187
205
|
path: canonicalAssetPath(asset),
|
|
188
206
|
assetId: asset.assetId,
|
|
189
207
|
linkRole: role,
|
|
190
|
-
...(
|
|
208
|
+
...(options?.ignoreAssetMetadataSnapshots !== true
|
|
209
|
+
&& asset.kind === 'document'
|
|
210
|
+
&& asset.storageProvider !== 'external'
|
|
211
|
+
&& projected.caption !== undefined
|
|
191
212
|
? { caption: projected.caption } : {}),
|
|
192
213
|
...(projected.displayName !== undefined ? { displayName: projected.displayName } : {}),
|
|
193
|
-
...(
|
|
194
|
-
|
|
195
|
-
...(
|
|
214
|
+
...(options?.ignoreAssetMetadataSnapshots !== true && projected.originalFilename !== undefined
|
|
215
|
+
? { originalFilename: projected.originalFilename } : {}),
|
|
216
|
+
...(options?.ignoreAssetMetadataSnapshots !== true && projected.referenceNumber !== undefined
|
|
217
|
+
? { referenceNumber: projected.referenceNumber } : {}),
|
|
218
|
+
...(options?.ignoreAssetMetadataSnapshots !== true && projected.referenceLabel !== undefined
|
|
219
|
+
? { referenceLabel: projected.referenceLabel } : {}),
|
|
196
220
|
};
|
|
197
221
|
});
|
|
198
222
|
}
|
|
@@ -9,11 +9,23 @@ export interface TaskChecklistItem {
|
|
|
9
9
|
}
|
|
10
10
|
export interface TaskChecklistTask {
|
|
11
11
|
id: string;
|
|
12
|
+
checklistItems?: TaskChecklistItem[];
|
|
12
13
|
}
|
|
13
14
|
export interface TaskChecklistReplaceMutation {
|
|
14
15
|
taskId: string;
|
|
15
16
|
items: TaskChecklistItem[];
|
|
16
17
|
operationId: string;
|
|
18
|
+
expectedDetailRevision?: string;
|
|
19
|
+
requireDurableIdempotency?: boolean;
|
|
20
|
+
itemUpdateIntent?: {
|
|
21
|
+
kind: 'item-update';
|
|
22
|
+
itemId: string;
|
|
23
|
+
patch: {
|
|
24
|
+
text?: string;
|
|
25
|
+
done?: boolean;
|
|
26
|
+
order?: number;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
17
29
|
}
|
|
18
30
|
export interface TaskChecklistCommandServiceDependencies {
|
|
19
31
|
resolveTask(identifier: unknown): TaskChecklistTask;
|
|
@@ -35,6 +47,9 @@ export type ReplaceTaskChecklistCommandResult = {
|
|
|
35
47
|
export type AddTaskChecklistItemCommandResult = ReplaceTaskChecklistCommandResult & {
|
|
36
48
|
item: TaskChecklistItem | null;
|
|
37
49
|
};
|
|
50
|
+
export type UpdateTaskChecklistItemCommandResult = ReplaceTaskChecklistCommandResult & {
|
|
51
|
+
item: TaskChecklistItem;
|
|
52
|
+
};
|
|
38
53
|
export declare function createTaskChecklistCommandService(deps: TaskChecklistCommandServiceDependencies): {
|
|
39
54
|
replace(input: {
|
|
40
55
|
taskId: unknown;
|
|
@@ -47,4 +62,16 @@ export declare function createTaskChecklistCommandService(deps: TaskChecklistCom
|
|
|
47
62
|
isCompleted?: unknown;
|
|
48
63
|
done?: unknown;
|
|
49
64
|
}): AddTaskChecklistItemCommandResult;
|
|
65
|
+
update(input: {
|
|
66
|
+
taskId: unknown;
|
|
67
|
+
itemId: unknown;
|
|
68
|
+
title?: unknown;
|
|
69
|
+
text?: unknown;
|
|
70
|
+
isCompleted?: unknown;
|
|
71
|
+
done?: unknown;
|
|
72
|
+
order?: unknown;
|
|
73
|
+
expectedDetailRevision?: unknown;
|
|
74
|
+
operationId?: string;
|
|
75
|
+
requireDurableIdempotency?: boolean;
|
|
76
|
+
}): UpdateTaskChecklistItemCommandResult;
|
|
50
77
|
};
|
|
@@ -26,13 +26,21 @@ function requireMutationResult(task, taskId) {
|
|
|
26
26
|
throw new TaskChecklistCommandError(`Task ${taskId} not found`, 'TASK_NOT_FOUND', 404, { taskId });
|
|
27
27
|
}
|
|
28
28
|
export function createTaskChecklistCommandService(deps) {
|
|
29
|
-
const replaceItems = (taskId, items, operationKey) => {
|
|
30
|
-
|
|
29
|
+
const replaceItems = (taskId, items, operationKey, options) => {
|
|
30
|
+
const mutated = deps.replace({
|
|
31
31
|
taskId,
|
|
32
32
|
items,
|
|
33
|
-
operationId: deps.createId('operation', operationKey),
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
operationId: options?.operationId || deps.createId('operation', operationKey),
|
|
34
|
+
...(options?.expectedDetailRevision
|
|
35
|
+
? { expectedDetailRevision: options.expectedDetailRevision }
|
|
36
|
+
: {}),
|
|
37
|
+
...(options?.requireDurableIdempotency
|
|
38
|
+
? { requireDurableIdempotency: true }
|
|
39
|
+
: {}),
|
|
40
|
+
...(options?.itemUpdateIntent ? { itemUpdateIntent: options.itemUpdateIntent } : {}),
|
|
41
|
+
});
|
|
42
|
+
requireMutationResult(mutated, taskId);
|
|
43
|
+
return mutated?.checklistItems || deps.listItems(taskId);
|
|
36
44
|
};
|
|
37
45
|
return {
|
|
38
46
|
replace(input) {
|
|
@@ -107,5 +115,75 @@ export function createTaskChecklistCommandService(deps) {
|
|
|
107
115
|
items,
|
|
108
116
|
};
|
|
109
117
|
},
|
|
118
|
+
update(input) {
|
|
119
|
+
const task = deps.resolveTask(input.taskId);
|
|
120
|
+
const itemId = String(input.itemId ?? '').trim();
|
|
121
|
+
if (!itemId) {
|
|
122
|
+
throw new TaskChecklistCommandError('update_task_checklist_item requires itemId.');
|
|
123
|
+
}
|
|
124
|
+
const currentItems = deps.listItems(task.id);
|
|
125
|
+
const existingItem = currentItems.find((item) => item.id === itemId);
|
|
126
|
+
if (!existingItem) {
|
|
127
|
+
throw new TaskChecklistCommandError(`Checklist item ${itemId} was not found on task ${task.id}.`, 'TASK_CHECKLIST_ITEM_NOT_FOUND', 404, { taskId: task.id, itemId });
|
|
128
|
+
}
|
|
129
|
+
const hasTitle = input.title !== undefined || input.text !== undefined;
|
|
130
|
+
const hasCompleted = input.isCompleted !== undefined || input.done !== undefined;
|
|
131
|
+
const hasOrder = input.order !== undefined;
|
|
132
|
+
if (!hasTitle && !hasCompleted && !hasOrder) {
|
|
133
|
+
throw new TaskChecklistCommandError('update_task_checklist_item requires at least one of text, done, or order.');
|
|
134
|
+
}
|
|
135
|
+
const title = hasTitle
|
|
136
|
+
? normalizeTitle(input.title ?? input.text, 'update_task_checklist_item text')
|
|
137
|
+
: existingItem.title;
|
|
138
|
+
const completedInput = input.isCompleted ?? input.done;
|
|
139
|
+
if (hasCompleted && typeof completedInput !== 'boolean') {
|
|
140
|
+
throw new TaskChecklistCommandError('update_task_checklist_item done must be a boolean.');
|
|
141
|
+
}
|
|
142
|
+
const isCompleted = hasCompleted ? completedInput : existingItem.isCompleted;
|
|
143
|
+
const parsedOrder = hasOrder ? Number(input.order) : existingItem.order;
|
|
144
|
+
if (hasOrder && (!Number.isInteger(parsedOrder) || parsedOrder < 0)) {
|
|
145
|
+
throw new TaskChecklistCommandError('update_task_checklist_item order must be a non-negative integer.');
|
|
146
|
+
}
|
|
147
|
+
const expectedDetailRevision = input.expectedDetailRevision === undefined
|
|
148
|
+
? undefined
|
|
149
|
+
: String(input.expectedDetailRevision).trim();
|
|
150
|
+
if (input.expectedDetailRevision !== undefined && !expectedDetailRevision) {
|
|
151
|
+
throw new TaskChecklistCommandError('update_task_checklist_item expectedDetailRevision must contain non-whitespace text.');
|
|
152
|
+
}
|
|
153
|
+
const unchanged = existingItem.title === title
|
|
154
|
+
&& existingItem.isCompleted === isCompleted
|
|
155
|
+
&& existingItem.order === parsedOrder;
|
|
156
|
+
const nextItem = unchanged
|
|
157
|
+
? existingItem
|
|
158
|
+
: {
|
|
159
|
+
...existingItem,
|
|
160
|
+
title,
|
|
161
|
+
isCompleted,
|
|
162
|
+
order: parsedOrder,
|
|
163
|
+
updatedAt: deps.now(),
|
|
164
|
+
};
|
|
165
|
+
const nextItems = currentItems.map((item) => item.id === itemId ? nextItem : item);
|
|
166
|
+
const items = replaceItems(task.id, nextItems, `task-checklist-update:${task.id}:${itemId}`, {
|
|
167
|
+
operationId: input.operationId,
|
|
168
|
+
expectedDetailRevision,
|
|
169
|
+
requireDurableIdempotency: input.requireDurableIdempotency,
|
|
170
|
+
...(input.requireDurableIdempotency ? {
|
|
171
|
+
itemUpdateIntent: {
|
|
172
|
+
kind: 'item-update',
|
|
173
|
+
itemId,
|
|
174
|
+
patch: {
|
|
175
|
+
...(hasTitle ? { text: title } : {}),
|
|
176
|
+
...(hasCompleted ? { done: isCompleted } : {}),
|
|
177
|
+
...(hasOrder ? { order: parsedOrder } : {}),
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
} : {}),
|
|
181
|
+
});
|
|
182
|
+
const item = items.find((candidate) => candidate.id === itemId);
|
|
183
|
+
if (!item) {
|
|
184
|
+
throw new TaskChecklistCommandError(`Checklist item ${itemId} was not found after updating task ${task.id}.`, 'TASK_CHECKLIST_ITEM_NOT_FOUND', 404, { taskId: task.id, itemId });
|
|
185
|
+
}
|
|
186
|
+
return { taskId: task.id, item, items };
|
|
187
|
+
},
|
|
110
188
|
};
|
|
111
189
|
}
|
|
@@ -30,6 +30,7 @@ export interface TaskLifecycleCommandServiceDependencies {
|
|
|
30
30
|
updates: Record<string, unknown>;
|
|
31
31
|
forceDurable?: boolean;
|
|
32
32
|
assigneeIntent?: TaskLifecycleAssigneeIntent;
|
|
33
|
+
handoffComment?: string;
|
|
33
34
|
}): TaskLifecycleTask;
|
|
34
35
|
mutateLifecycle(input: {
|
|
35
36
|
taskId: string;
|
|
@@ -40,7 +41,7 @@ export interface TaskLifecycleCommandServiceDependencies {
|
|
|
40
41
|
reason: string | undefined;
|
|
41
42
|
};
|
|
42
43
|
}): TaskLifecycleTask | null;
|
|
43
|
-
resolveReviewer(task: TaskLifecycleTask): TaskLifecycleReviewerResolution;
|
|
44
|
+
resolveReviewer(task: TaskLifecycleTask, reviewer?: unknown): TaskLifecycleReviewerResolution;
|
|
44
45
|
}
|
|
45
46
|
export declare class TaskLifecycleCommandError extends Error {
|
|
46
47
|
readonly code: string;
|
|
@@ -81,6 +82,7 @@ export declare function createTaskLifecycleCommandService(deps: TaskLifecycleCom
|
|
|
81
82
|
finish(task: TaskLifecycleTask, input: {
|
|
82
83
|
outcome: unknown;
|
|
83
84
|
comment?: unknown;
|
|
85
|
+
reviewer?: unknown;
|
|
84
86
|
}): FinishTaskCommandResult;
|
|
85
87
|
reopen(task: TaskLifecycleTask, input: {
|
|
86
88
|
activeAiProfileId: string | null | undefined;
|
|
@@ -88,8 +88,12 @@ export function createTaskLifecycleCommandService(deps) {
|
|
|
88
88
|
nextTool: 'reopen_task',
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
|
+
const normalizedComment = typeof input.comment === 'string' ? input.comment.trim() : '';
|
|
92
|
+
if (normalizedOutcome === 'review' && !normalizedComment) {
|
|
93
|
+
throw new TaskLifecycleCommandError('finish_task requires a nonblank handoff comment when outcome is review.', 'TASK_FINISH_REVIEW_COMMENT_REQUIRED', 400, { taskId: task.id, outcome: normalizedOutcome });
|
|
94
|
+
}
|
|
91
95
|
const reviewerResolution = normalizedOutcome === 'review'
|
|
92
|
-
? deps.resolveReviewer(task)
|
|
96
|
+
? deps.resolveReviewer(task, input.reviewer)
|
|
93
97
|
: undefined;
|
|
94
98
|
const updated = deps.setStatus({
|
|
95
99
|
task,
|
|
@@ -99,8 +103,8 @@ export function createTaskLifecycleCommandService(deps) {
|
|
|
99
103
|
...(reviewerResolution
|
|
100
104
|
? { assigneeIntent: { kind: 'set', value: reviewerResolution.assignee } }
|
|
101
105
|
: {}),
|
|
106
|
+
...(normalizedOutcome === 'review' ? { handoffComment: normalizedComment } : {}),
|
|
102
107
|
});
|
|
103
|
-
const normalizedComment = typeof input.comment === 'string' ? input.comment.trim() : '';
|
|
104
108
|
return {
|
|
105
109
|
task: updated,
|
|
106
110
|
completion: {
|