@taskforcehq/taskforce 0.3.329 → 0.3.332
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -2
- package/dist/Taskforce.module.css +290 -45
- package/dist/components/features/AiProfilesModule.js +3 -5
- package/dist/components/features/TaskSettings.js +70 -14
- package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
- package/dist/components/features/TaskforceAgentsModule.js +586 -116
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +2 -2
- package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.js +2 -2
- package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
- package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
- package/dist/components/features/planning/PlanningModule.js +15 -3
- package/dist/components/features/planning/planningMetadata.d.ts +10 -0
- package/dist/components/features/planning/planningMetadata.js +8 -0
- package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
- package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
- package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
- package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
- package/dist/components/views/StandaloneLayout.js +62 -27
- package/dist/components/views/panels/PlanningDrawer.d.ts +2 -1
- package/dist/components/views/panels/PlanningDrawer.js +12 -8
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
- package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
- package/dist/config/envSchema.js +55 -1
- package/dist/core/McpTokenService.d.ts +25 -1
- package/dist/core/McpTokenService.js +106 -15
- package/dist/core/TaskChecklistCommandService.d.ts +27 -0
- package/dist/core/TaskChecklistCommandService.js +83 -5
- package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
- package/dist/core/TaskLifecycleCommandService.js +6 -2
- package/dist/core/Taskforce.d.ts +43 -3
- package/dist/core/Taskforce.js +158 -7
- package/dist/core/types.d.ts +9 -0
- package/dist/documentReviews/DocumentReviewCommentStore.d.ts +2 -0
- package/dist/documentReviews/DocumentReviewCommentStore.js +28 -9
- package/dist/documentReviews/commandService.d.ts +2 -1
- package/dist/documentReviews/commandService.js +6 -3
- package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.js +2 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
- package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
- package/dist/hooks/sync/useSyncStatusControls.js +47 -11
- package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
- package/dist/hooks/useSyncOrchestrator.js +111 -2
- package/dist/hooks/useTaskData.d.ts +31 -1
- package/dist/hooks/useTaskData.js +29 -7
- package/dist/hooks/useTaskMutations.d.ts +3 -1
- package/dist/hooks/useTaskMutations.js +46 -12
- package/dist/hooks/useTaskforce.d.ts +2 -0
- package/dist/hooks/useTaskforce.js +11 -2
- package/dist/mcp/clientRegistry.d.ts +2 -2
- package/dist/mcp/clientRegistry.js +1 -1
- package/dist/mcp/documentAssetRegistrar.js +9 -6
- package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
- package/dist/mcp/durableTaskMutationRouter.js +10 -0
- package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
- package/dist/mcp/httpProtocolRouting.d.ts +11 -0
- package/dist/mcp/httpProtocolRouting.js +22 -0
- package/dist/mcp/localCliHealth.d.ts +2 -2
- package/dist/mcp/localCliHealth.js +2 -2
- package/dist/mcp/localServiceProxy.d.ts +1 -0
- package/dist/mcp/localServiceProxy.js +530 -68
- package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
- package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
- package/dist/mcp/runtime.d.ts +54 -79
- package/dist/mcp/runtime.js +408 -102
- package/dist/mcp/taskPlanningRegistrar.js +25 -6
- package/dist/mcp/toolProfiles.d.ts +2 -0
- package/dist/mcp/toolProfiles.js +11 -0
- package/dist/mcp/toolRegistry.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +9 -8
- package/dist/mcp/workflowExecutionRegistrar.js +4 -4
- package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
- package/dist/migrations/taskSchemaMigrations.js +415 -0
- package/dist/runtime/appGates.d.ts +2 -1
- package/dist/runtime/appGates.js +7 -0
- package/dist/server/buildInfo.d.ts +1 -0
- package/dist/server/buildInfo.js +5 -1
- package/dist/server/cloudMcpCapacityTelemetry.d.ts +68 -0
- package/dist/server/cloudMcpCapacityTelemetry.js +221 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +108 -11
- package/dist/server/localDatabaseIdentity.js +4 -1
- package/dist/server/localServiceLease.js +2 -1
- package/dist/server/localServiceSessions.d.ts +14 -17
- package/dist/server/localServiceSessions.js +308 -94
- package/dist/server/localWorkspaceSyncServerRuntime.js +25 -19
- package/dist/server/routes/admin.d.ts +4 -0
- package/dist/server/routes/admin.js +126 -5
- package/dist/server/routes/agents.d.ts +7 -0
- package/dist/server/routes/agents.js +277 -24
- package/dist/server/routes/billing.js +5 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
- package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
- package/dist/server/routes/executorPhaseAApprovals.js +140 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
- package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
- package/dist/server/routes/githubReviewEvidence.js +116 -0
- package/dist/server/routes/localService.d.ts +15 -4
- package/dist/server/routes/localService.js +136 -40
- package/dist/server/routes/modelConnections.d.ts +24 -0
- package/dist/server/routes/modelConnections.js +205 -0
- package/dist/server/routes/shared.d.ts +22 -0
- package/dist/server/routes/shared.js +298 -182
- package/dist/server/routes/sync.js +1 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -1
- package/dist/server/routes/syncPushRoutes.d.ts +1 -0
- package/dist/server/routes/syncPushRoutes.js +1 -0
- package/dist/server/routes/syncV3FeedRoutes.js +10 -1
- package/dist/server/routes/syncV3OperationRoutes.js +35 -9
- package/dist/server/routes/tasks.js +21 -2
- package/dist/server/routes/workflows.js +9 -1
- package/dist/server/routes.js +59 -0
- package/dist/service/localServiceCli.d.ts +2 -2
- package/dist/service/localServiceCli.js +4 -3
- package/dist/services/codexAppServerModelGateway.d.ts +54 -5
- package/dist/services/codexAppServerModelGateway.js +246 -21
- package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
- package/dist/services/codexDeviceCodeLoginManager.js +265 -0
- package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
- package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
- package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
- package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
- package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
- package/dist/services/executorPhaseAApprovalService.js +609 -0
- package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
- package/dist/services/executorPhaseADriftEvaluator.js +93 -0
- package/dist/services/executorPhaseAIssuerCore.d.ts +139 -0
- package/dist/services/executorPhaseAIssuerCore.js +402 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
- package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
- package/dist/services/githubReviewEvidenceRuntime.js +30 -0
- package/dist/services/githubReviewEvidenceService.d.ts +93 -0
- package/dist/services/githubReviewEvidenceService.js +336 -0
- package/dist/services/modelGateway.d.ts +7 -0
- package/dist/services/modelProviderConnectionService.d.ts +71 -0
- package/dist/services/modelProviderConnectionService.js +279 -0
- package/dist/services/modelProviderCredentialHome.d.ts +32 -0
- package/dist/services/modelProviderCredentialHome.js +271 -0
- package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
- package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
- package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
- package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +2 -2
- package/dist/services/taskforceAgentMcpBridge.js +42 -29
- package/dist/shared/adminEdgeProxy.d.ts +5 -0
- package/dist/shared/adminEdgeProxy.js +94 -0
- package/dist/shared/adminProxySessionCookies.d.ts +16 -0
- package/dist/shared/adminProxySessionCookies.js +86 -0
- package/dist/shared/aiProfileColors.d.ts +31 -1
- package/dist/shared/aiProfileColors.js +14 -6
- package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
- package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
- package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
- package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
- package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
- package/dist/shared/executorPhaseADriftContracts.js +63 -0
- package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
- package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
- package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
- package/dist/shared/executorPhaseARunAuthorization.js +232 -0
- package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
- package/dist/shared/executorPhaseASchemaValidation.js +53 -0
- package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
- package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
- package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
- package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
- package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
- package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
- package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
- package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
- package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
- package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
- package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
- package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
- package/dist/shared/executorPhaseATiming.d.ts +1 -0
- package/dist/shared/executorPhaseATiming.js +1 -0
- package/dist/shared/planningIdentity.js +1 -1
- package/dist/shared/productLogoKeys.d.ts +2 -0
- package/dist/shared/productLogoKeys.js +18 -0
- package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
- package/dist/shared/taskforceAgentDefinition.js +6 -9
- package/dist/shared/taskforceAgentModels.js +7 -3
- package/dist/shared/userFeatureGrants.d.ts +4 -0
- package/dist/shared/userFeatureGrants.js +7 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
- package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
- package/dist/storage/modelProviderConnectionStore.js +446 -0
- package/dist/storage/postgresAdapter.d.ts +4 -0
- package/dist/storage/postgresAdapter.js +14 -1
- package/dist/storage/postgresRequestDiagnostics.d.ts +9 -1
- package/dist/storage/postgresRequestDiagnostics.js +15 -2
- package/dist/storage/postgresWorker.js +20 -2
- package/dist/storage/postgresWorkerProtocol.d.ts +7 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
- package/dist/storage/workflowStore.d.ts +2 -0
- package/dist/storage/workflowStore.js +39 -2
- package/dist/sync/cloudSyncApi.js +4 -2
- package/dist/sync/collaborationSyncState.js +5 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
- package/dist/sync/coordinator/localWorkspaceSyncRunner.d.ts +3 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunner.js +18 -0
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
- package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
- package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
- package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
- package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
- package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
- package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +31 -0
- package/dist/sync/syncApplyHandlers.d.ts +3 -0
- package/dist/sync/syncApplyHandlers.js +81 -15
- package/dist/sync/syncService.d.ts +15 -0
- package/dist/sync/syncService.js +83 -18
- package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
- package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
- package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
- package/dist/sync/v3/durableOperationReplay.js +18 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
- package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
- package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +18 -7
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +89 -23
- package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
- package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
- package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
- package/dist/sync/v3/localOutboxRecoveryPreparationService.js +8 -2
- package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
- package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
- package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
- package/dist/sync/v3/localTaskCreateOutboxService.d.ts +3 -1
- package/dist/sync/v3/localTaskCreateOutboxService.js +6 -1
- package/dist/sync/v3/localTaskDeleteOutboxService.js +1 -0
- package/dist/sync/v3/localTaskLifecycleOutboxService.d.ts +2 -1
- package/dist/sync/v3/localTaskLifecycleOutboxService.js +5 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -1
- package/dist/sync/v3/localTaskMetadataOutboxService.js +6 -2
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -1
- package/dist/sync/v3/localTaskStatusOutboxService.js +238 -16
- package/dist/sync/v3/syncDurabilityStore.d.ts +36 -1
- package/dist/sync/v3/syncDurabilityStore.js +202 -8
- package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
- package/dist/sync/v3/taskChecklistMutationService.js +44 -1
- package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
- package/dist/sync/v3/taskStatusMutationService.js +119 -3
- package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
- package/dist/sync/v3/workflowAssignmentSync.js +27 -0
- package/dist/sync/v3/workflowRuntimeMutationService.d.ts +5 -0
- package/dist/sync/v3/workflowRuntimeMutationService.js +124 -71
- package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
- package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
- package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
- package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +25 -3
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3Feed.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3Feed.js +6 -1
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +2 -0
- package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +49 -18
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowRuntimeApply.js +50 -5
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
- package/dist/sync/workspaceRepair.d.ts +5 -2
- package/dist/sync/workspaceRepair.js +161 -6
- package/dist/sync/workspaceSyncModel.d.ts +21 -0
- package/dist/sync/workspaceSyncModel.js +35 -7
- package/dist/sync/workspaceSyncState.d.ts +1 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
- package/dist/ui/assets/AiIdentityRosterCard-CDMPtnbC.js +1 -0
- package/dist/ui/assets/AiProfilesModule-Cww85C4E.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-Dt9TKYSH.js} +1 -1
- package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-CKgapnxu.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-T-cEVcOZ.js} +2 -2
- package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-HD4MUjAZ.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-_V0zfMuh.js} +1 -1
- package/dist/ui/assets/PlanningModule-mTkBygsB.js +1 -0
- package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-Btiq06VO.js} +1 -1
- package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-C00NVUpn.js} +1 -1
- package/dist/ui/assets/TaskSettings-Cp-L-4xh.js +12 -0
- package/dist/ui/assets/TaskforceAgentsModule-Coq9-PUp.js +24 -0
- package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
- package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-CuqRzMmM.js} +1 -1
- package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
- package/dist/ui/assets/index-DSQINwt9.js +7 -0
- package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
- package/dist/ui/branding/logos/letterhead_dark.png +0 -0
- package/dist/ui/branding/logos/letterhead_light.png +0 -0
- package/dist/ui/branding/logos/signature_dark.png +0 -0
- package/dist/ui/branding/logos/signature_light.png +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/aiProfileDefaultLogo.js +16 -48
- package/dist/utils/httpSetCookie.d.ts +1 -0
- package/dist/utils/httpSetCookie.js +4 -1
- package/dist/utils/localRuntimeUrl.d.ts +1 -0
- package/dist/utils/localRuntimeUrl.js +14 -0
- package/dist/utils/productLogoRegistry.d.ts +2 -0
- package/dist/utils/productLogoRegistry.js +36 -0
- package/dist/utils/syncStatusPresentation.d.ts +4 -0
- package/dist/utils/syncStatusPresentation.js +17 -0
- package/dist/utils/taskEvents.d.ts +2 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
- package/dist/utils/workspaceSyncPresentation.js +23 -17
- package/package.json +24 -4
- package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
- package/dist/ui/assets/PlanningModule-B5DWQOGz.js +0 -1
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
- package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
- package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
- package/dist/ui/assets/index-I5zhdtgt.js +0 -7
- package/dist/ui/assets/index-VRFsx3wz.css +0 -1
|
@@ -6,20 +6,22 @@
|
|
|
6
6
|
* routes.ts at runtime.
|
|
7
7
|
*/
|
|
8
8
|
import { randomUUID } from 'crypto';
|
|
9
|
-
import {
|
|
10
|
-
import { isInitializeRequest } from '@modelcontextprotocol/
|
|
9
|
+
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
|
|
10
|
+
import { isInitializeRequest, isJsonContentType } from '@modelcontextprotocol/server';
|
|
11
11
|
import { TaskforceRuleError } from '../../core/Taskforce.js';
|
|
12
12
|
import { resolveRequestAccess, } from '../auth.js';
|
|
13
13
|
import { parseJsonBody } from './primitives.js';
|
|
14
|
-
import { createTaskforceMcpServer, isMcpWriteToolName } from '../../mcp/runtime.js';
|
|
14
|
+
import { createStatelessTaskforceMcpServer, createTaskforceMcpServer, isMcpWriteToolName, } from '../../mcp/runtime.js';
|
|
15
15
|
import { MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS } from '../../mcp/toolRegistry.js';
|
|
16
16
|
import { resolveCanonicalMcpToolName } from '../../mcp/toolCallCompatibility.js';
|
|
17
17
|
import { applyPrefixedRateLimitHeaders } from '../rateLimit.js';
|
|
18
18
|
import { parseAiProfileBootstrapHeaders } from '../../mcp/aiProfileBootstrap.js';
|
|
19
19
|
import { parseMcpClientId } from '../../mcp/clientRegistry.js';
|
|
20
|
+
import { handleModernMcpHttpRequest, isModernMcpHttpRequest, } from '../../mcp/httpProtocolRouting.js';
|
|
20
21
|
import { resolveAppAccessDeniedResponse } from '../appAccess.js';
|
|
21
22
|
import { resolveCloudApplicationBaseUrl } from '../../config/applicationBaseUrl.js';
|
|
22
23
|
import { getRequestPerformanceDiagnostics, runWithRequestPerformanceDiagnostics, } from '../../storage/postgresRequestDiagnostics.js';
|
|
24
|
+
import { beginCloudMcpCapacityRequest, isCloudMcpCapacityTelemetryEnabled, TASKFORCE_CAPACITY_TRACE_HEADER, } from '../cloudMcpCapacityTelemetry.js';
|
|
23
25
|
// === SECTION: Error helpers ===
|
|
24
26
|
export function resolveErrorStatusCode(error, fallback = 400) {
|
|
25
27
|
if (error instanceof TaskforceRuleError)
|
|
@@ -273,7 +275,14 @@ function writeMcpHttpError(res, statusCode, message, data) {
|
|
|
273
275
|
id: null,
|
|
274
276
|
}));
|
|
275
277
|
}
|
|
276
|
-
function
|
|
278
|
+
function resolveProductionCloudMcpToolPolicy(requestedToolName) {
|
|
279
|
+
const toolName = resolveCanonicalMcpToolName(requestedToolName);
|
|
280
|
+
return {
|
|
281
|
+
requiredScope: MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS[toolName] || null,
|
|
282
|
+
isWrite: isMcpWriteToolName(requestedToolName),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function extractMcpWriteToolNames(body, resolveToolPolicy) {
|
|
277
286
|
const messages = Array.isArray(body) ? body : [body];
|
|
278
287
|
const names = messages.flatMap((message) => {
|
|
279
288
|
if (!message || typeof message !== 'object')
|
|
@@ -282,7 +291,7 @@ function extractMcpWriteToolNames(body) {
|
|
|
282
291
|
if (method !== 'tools/call')
|
|
283
292
|
return [];
|
|
284
293
|
const toolName = String(message?.params?.name || '').trim();
|
|
285
|
-
return toolName &&
|
|
294
|
+
return toolName && resolveToolPolicy(toolName).isWrite ? [toolName] : [];
|
|
286
295
|
});
|
|
287
296
|
return Array.from(new Set(names));
|
|
288
297
|
}
|
|
@@ -299,7 +308,7 @@ function extractFirstMcpToolName(body) {
|
|
|
299
308
|
}
|
|
300
309
|
return null;
|
|
301
310
|
}
|
|
302
|
-
function findDeniedCloudMcpToolName(body, scopes) {
|
|
311
|
+
function findDeniedCloudMcpToolName(body, scopes, resolveToolPolicy) {
|
|
303
312
|
const messages = Array.isArray(body) ? body : [body];
|
|
304
313
|
for (const message of messages) {
|
|
305
314
|
if (!message || typeof message !== 'object')
|
|
@@ -309,15 +318,14 @@ function findDeniedCloudMcpToolName(body, scopes) {
|
|
|
309
318
|
const requestedToolName = String(message?.params?.name || '').trim();
|
|
310
319
|
if (!requestedToolName)
|
|
311
320
|
continue;
|
|
312
|
-
const
|
|
313
|
-
const requiredScope = MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS[toolName];
|
|
321
|
+
const requiredScope = resolveToolPolicy(requestedToolName).requiredScope;
|
|
314
322
|
if (!requiredScope || !scopes.includes(requiredScope))
|
|
315
323
|
return requestedToolName;
|
|
316
324
|
}
|
|
317
325
|
return null;
|
|
318
326
|
}
|
|
319
327
|
export function makeHandleCloudMcpRequest(core, deps) {
|
|
320
|
-
const { ensureAppAccess, resolveAuthenticatedUserId, writeRateLimit } = deps;
|
|
328
|
+
const { ensureAppAccess, resolveAuthenticatedUserId, writeRateLimit, createMcpServer = createTaskforceMcpServer, resolveMcpToolPolicy = resolveProductionCloudMcpToolPolicy, acquireMcpRuntime, capacityTelemetryEnabled = isCloudMcpCapacityTelemetryEnabled, beginCapacityRequest = beginCloudMcpCapacityRequest, } = deps;
|
|
321
329
|
const authenticateCloudMcpRequest = makeAuthenticateCloudMcpRequest(core, {
|
|
322
330
|
resolveAuthenticatedUserId,
|
|
323
331
|
writeMcpHttpError,
|
|
@@ -342,7 +350,7 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
342
350
|
const applyCloudMcpWriteRateLimit = (req, res, auth, body) => {
|
|
343
351
|
if (!writeRateLimit.enabled)
|
|
344
352
|
return true;
|
|
345
|
-
const writeTools = extractMcpWriteToolNames(body);
|
|
353
|
+
const writeTools = extractMcpWriteToolNames(body, resolveMcpToolPolicy);
|
|
346
354
|
if (writeTools.length === 0)
|
|
347
355
|
return true;
|
|
348
356
|
const actorKey = auth.authenticatedViaToken?.tokenId
|
|
@@ -398,97 +406,209 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
398
406
|
writeMcpHttpError(res, 400, 'The /mcp HTTP endpoint is only available in cloud runtime. In local runtime, use the local stdio MCP server (for example: `taskforce mcp <project-path>`).');
|
|
399
407
|
return;
|
|
400
408
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
const authScopes = auth.authenticatedViaToken?.scopes || auth.authenticatedViaOAuth?.scopes || [];
|
|
427
|
-
const requestId = String(req.headers['x-request-id'] || req.headers['x-railway-request-id'] || '').trim() || randomUUID();
|
|
428
|
-
res.setHeader('X-Request-ID', requestId);
|
|
429
|
-
const mcpMethod = !Array.isArray(body) && body !== null && typeof body === 'object'
|
|
430
|
-
? String(body.method || '')
|
|
431
|
-
: '';
|
|
432
|
-
const initializeRequest = isInitializeRequest(body)
|
|
433
|
-
|| mcpMethod === 'initialize';
|
|
434
|
-
const deniedToolName = findDeniedCloudMcpToolName(body, authScopes);
|
|
435
|
-
if (deniedToolName) {
|
|
436
|
-
core.addMcpAuditLog({
|
|
437
|
-
workspaceId: auth.workspaceId,
|
|
438
|
-
actorType: auth.authenticatedViaToken ? 'token' : auth.authenticatedViaOAuth ? 'oauth' : 'user',
|
|
439
|
-
actorUserId: auth.authenticatedViaToken?.userId || auth.authenticatedViaOAuth?.userId || auth.userId || 'anonymous',
|
|
440
|
-
tokenId: auth.authenticatedViaToken?.tokenId || auth.authenticatedViaOAuth?.grantId || null,
|
|
441
|
-
toolName: deniedToolName,
|
|
442
|
-
details: {
|
|
443
|
-
requestId,
|
|
444
|
-
ip: req.socket?.remoteAddress || null,
|
|
445
|
-
userAgent: requestHeader(req, 'user-agent', '') || null,
|
|
446
|
-
outcome: 'deny',
|
|
447
|
-
reasonCode: 'scope_denied',
|
|
448
|
-
scopes: authScopes
|
|
409
|
+
const capacityRequest = beginCapacityRequest();
|
|
410
|
+
const capacityTraceEnabled = requestHeader(req, TASKFORCE_CAPACITY_TRACE_HEADER, '').trim() === '1';
|
|
411
|
+
return runWithRequestPerformanceDiagnostics(capacityTelemetryEnabled(), async () => {
|
|
412
|
+
let capacitySettled = false;
|
|
413
|
+
const settleCapacity = (aborted = false) => {
|
|
414
|
+
if (capacitySettled)
|
|
415
|
+
return;
|
|
416
|
+
capacitySettled = true;
|
|
417
|
+
capacityRequest.finish({
|
|
418
|
+
statusCode: res.statusCode,
|
|
419
|
+
aborted,
|
|
420
|
+
postgres: getRequestPerformanceDiagnostics(),
|
|
421
|
+
});
|
|
422
|
+
};
|
|
423
|
+
const onFinish = () => settleCapacity(false);
|
|
424
|
+
const onClose = () => settleCapacity(!res.writableEnded);
|
|
425
|
+
res.once('finish', onFinish);
|
|
426
|
+
res.once('close', onClose);
|
|
427
|
+
try {
|
|
428
|
+
if (!ensureAppAccess(req, res))
|
|
429
|
+
return;
|
|
430
|
+
if (req.method !== 'POST' && req.method !== 'GET' && req.method !== 'DELETE') {
|
|
431
|
+
writeMcpHttpError(res, 405, 'Method not allowed.');
|
|
432
|
+
return;
|
|
449
433
|
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
434
|
+
const authStartedAtMs = Date.now();
|
|
435
|
+
const auth = authenticateCloudMcpRequest(req, res);
|
|
436
|
+
authMs = Date.now() - authStartedAtMs;
|
|
437
|
+
if (!auth)
|
|
438
|
+
return;
|
|
439
|
+
if (capacityTraceEnabled)
|
|
440
|
+
capacityRequest.setTraceHeaders(res);
|
|
441
|
+
if (req.method !== 'POST') {
|
|
442
|
+
writeMcpHttpError(res, 405, 'Method not allowed.');
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
if (!isJsonContentType(requestHeader(req, 'content-type', ''))) {
|
|
446
|
+
writeMcpHttpError(res, 415, 'Unsupported Media Type: Content-Type must be application/json');
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
let body = undefined;
|
|
450
|
+
try {
|
|
451
|
+
const bodyParseStartedAtMs = Date.now();
|
|
452
|
+
body = await parseJsonBody(req);
|
|
453
|
+
bodyParseMs = Date.now() - bodyParseStartedAtMs;
|
|
454
|
+
}
|
|
455
|
+
catch (error) {
|
|
456
|
+
writeMcpHttpError(res, resolveErrorStatusCode(error, 400), 'Invalid JSON body.');
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
const authScopes = auth.authenticatedViaToken?.scopes || auth.authenticatedViaOAuth?.scopes || [];
|
|
460
|
+
const requestId = String(req.headers['x-request-id'] || req.headers['x-railway-request-id'] || '').trim() || randomUUID();
|
|
461
|
+
res.setHeader('X-Request-ID', requestId);
|
|
462
|
+
const mcpMethod = !Array.isArray(body) && body !== null && typeof body === 'object'
|
|
463
|
+
? String(body.method || '')
|
|
464
|
+
: '';
|
|
465
|
+
const initializeRequest = isInitializeRequest(body)
|
|
466
|
+
|| mcpMethod === 'initialize';
|
|
467
|
+
const modernProtocolRequest = await isModernMcpHttpRequest(req, body);
|
|
468
|
+
const writeToolNames = extractMcpWriteToolNames(body, resolveMcpToolPolicy);
|
|
469
|
+
const requestClass = initializeRequest
|
|
470
|
+
? 'initialize'
|
|
471
|
+
: mcpMethod === 'server/discover'
|
|
472
|
+
? 'discover'
|
|
473
|
+
: mcpMethod === 'tools/list'
|
|
474
|
+
? 'tools_list'
|
|
475
|
+
: writeToolNames.length > 0
|
|
476
|
+
? 'write'
|
|
477
|
+
: extractFirstMcpToolName(body)
|
|
478
|
+
? 'read'
|
|
479
|
+
: 'other';
|
|
480
|
+
capacityRequest.classify(requestClass);
|
|
481
|
+
const deniedToolName = findDeniedCloudMcpToolName(body, authScopes, resolveMcpToolPolicy);
|
|
482
|
+
if (deniedToolName) {
|
|
483
|
+
core.addMcpAuditLog({
|
|
484
|
+
workspaceId: auth.workspaceId,
|
|
485
|
+
actorType: auth.authenticatedViaToken ? 'token' : auth.authenticatedViaOAuth ? 'oauth' : 'user',
|
|
486
|
+
actorUserId: auth.authenticatedViaToken?.userId || auth.authenticatedViaOAuth?.userId || auth.userId || 'anonymous',
|
|
487
|
+
tokenId: auth.authenticatedViaToken?.tokenId || auth.authenticatedViaOAuth?.grantId || null,
|
|
488
|
+
toolName: deniedToolName,
|
|
489
|
+
details: {
|
|
490
|
+
requestId,
|
|
491
|
+
ip: req.socket?.remoteAddress || null,
|
|
492
|
+
userAgent: requestHeader(req, 'user-agent', '') || null,
|
|
493
|
+
outcome: 'deny',
|
|
494
|
+
reasonCode: 'scope_denied',
|
|
495
|
+
scopes: authScopes
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
writeMcpHttpError(res, 403, 'Forbidden.');
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const rateLimitStartedAtMs = Date.now();
|
|
502
|
+
const rateLimitAllowed = applyCloudMcpWriteRateLimit(req, res, auth, body);
|
|
503
|
+
rateLimitMs = Date.now() - rateLimitStartedAtMs;
|
|
504
|
+
if (!rateLimitAllowed)
|
|
505
|
+
return;
|
|
506
|
+
let runtime = null;
|
|
507
|
+
let runtimeLease = null;
|
|
508
|
+
let runtimeConstructionMs = 0;
|
|
509
|
+
let transportConnectMs = 0;
|
|
510
|
+
let requestHandlingMs = 0;
|
|
511
|
+
let cleanupMs = 0;
|
|
512
|
+
let outcome = 'success';
|
|
513
|
+
const toolTimingState = { value: null };
|
|
514
|
+
try {
|
|
515
|
+
const runtimeStartedAtMs = Date.now();
|
|
516
|
+
// Production intentionally isolates the MCP runtime per HTTP request. The runtime closes over
|
|
517
|
+
// workspace auth, AI identity, permissions, subscriptions, and mutable helper state;
|
|
518
|
+
// sharing it could leak state across tenants or callers. Keep the transport stateless
|
|
519
|
+
// too. The timing event below measures construction cost so caching is only revisited
|
|
520
|
+
// with evidence and must preserve these boundaries (including dynamic tool schemas). The optional
|
|
521
|
+
// lease seam exists only for transport conformance tests that must carry legacy bidirectional calls.
|
|
522
|
+
const runtimeOptions = {
|
|
523
|
+
projectRoot: core.getPaths().projectRoot,
|
|
524
|
+
tenantId: core.getTenantId(),
|
|
525
|
+
workspaceId: auth.workspaceId,
|
|
526
|
+
core,
|
|
527
|
+
serverName: 'taskforce-cloud',
|
|
528
|
+
logStartup: false,
|
|
529
|
+
runtimeMode: 'cloud',
|
|
530
|
+
toolProfile: auth.authenticatedViaToken?.toolProfile || auth.authenticatedViaOAuth?.toolProfile || 'default',
|
|
531
|
+
applicationBaseUrl: resolveCloudApplicationBaseUrl(),
|
|
532
|
+
auth: buildCloudMcpRuntimeAuth({
|
|
533
|
+
req,
|
|
534
|
+
auth,
|
|
535
|
+
requestHeader,
|
|
536
|
+
requestId,
|
|
537
|
+
authScopes,
|
|
538
|
+
}),
|
|
539
|
+
onToolCallTiming: (timing) => {
|
|
540
|
+
toolTimingState.value = timing;
|
|
541
|
+
if (!res.headersSent) {
|
|
542
|
+
if (capacityTraceEnabled) {
|
|
543
|
+
capacityRequest.setTraceHeaders(res, getRequestPerformanceDiagnostics());
|
|
544
|
+
}
|
|
545
|
+
setServerTimingHeader(res, [
|
|
546
|
+
{ name: 'auth', durationMs: authMs },
|
|
547
|
+
{ name: 'body-parse', durationMs: bodyParseMs },
|
|
548
|
+
{ name: 'rate-limit', durationMs: rateLimitMs },
|
|
549
|
+
{ name: 'runtime', durationMs: runtimeConstructionMs },
|
|
550
|
+
{ name: 'transport-connect', durationMs: transportConnectMs },
|
|
551
|
+
{ name: 'tool-envelope-prepare', durationMs: timing.preparationMs },
|
|
552
|
+
{ name: 'tool-envelope-validate', durationMs: timing.validationMs },
|
|
553
|
+
{ name: 'tool-handler', durationMs: timing.handlerMs },
|
|
554
|
+
...Object.entries(timing.subphases).map(([phase, durationMs]) => ({
|
|
555
|
+
name: `tool-${phase}`,
|
|
556
|
+
durationMs,
|
|
557
|
+
})),
|
|
558
|
+
]);
|
|
559
|
+
}
|
|
560
|
+
},
|
|
561
|
+
};
|
|
562
|
+
if (modernProtocolRequest) {
|
|
563
|
+
const requestHandlingStartedAtMs = Date.now();
|
|
564
|
+
await handleModernMcpHttpRequest({
|
|
565
|
+
req,
|
|
566
|
+
res,
|
|
567
|
+
parsedBody: body,
|
|
568
|
+
factory: ({ era }) => {
|
|
569
|
+
const constructionStartedAtMs = Date.now();
|
|
570
|
+
const modernRuntime = createStatelessTaskforceMcpServer({
|
|
571
|
+
...runtimeOptions,
|
|
572
|
+
protocolEra: era,
|
|
573
|
+
}, createMcpServer);
|
|
574
|
+
runtimeConstructionMs = Date.now() - constructionStartedAtMs;
|
|
575
|
+
if (!res.headersSent) {
|
|
576
|
+
setServerTimingHeader(res, [
|
|
577
|
+
{ name: 'auth', durationMs: authMs },
|
|
578
|
+
{ name: 'body-parse', durationMs: bodyParseMs },
|
|
579
|
+
{ name: 'rate-limit', durationMs: rateLimitMs },
|
|
580
|
+
{ name: 'runtime', durationMs: runtimeConstructionMs },
|
|
581
|
+
]);
|
|
582
|
+
}
|
|
583
|
+
return modernRuntime.server;
|
|
584
|
+
},
|
|
585
|
+
onerror: (error) => {
|
|
586
|
+
console.warn('[Taskforce MCP] Modern cloud request rejected:', {
|
|
587
|
+
requestId,
|
|
588
|
+
message: error.message,
|
|
589
|
+
});
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
requestHandlingMs = Date.now() - requestHandlingStartedAtMs;
|
|
593
|
+
recordCloudMcpCredentialUsage(req, auth.authenticatedViaToken, auth.authenticatedViaOAuth);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
runtimeLease = acquireMcpRuntime
|
|
597
|
+
? await acquireMcpRuntime({ req, options: runtimeOptions })
|
|
598
|
+
: null;
|
|
599
|
+
runtime = runtimeLease?.runtime
|
|
600
|
+
|| createStatelessTaskforceMcpServer(runtimeOptions, createMcpServer);
|
|
601
|
+
runtimeConstructionMs = Date.now() - runtimeStartedAtMs;
|
|
602
|
+
const transport = runtimeLease?.transport || new NodeStreamableHTTPServerTransport({
|
|
603
|
+
sessionIdGenerator: undefined,
|
|
604
|
+
enableJsonResponse: true,
|
|
605
|
+
});
|
|
606
|
+
const transportStartedAtMs = Date.now();
|
|
607
|
+
if (!runtimeLease)
|
|
608
|
+
await runtime.server.connect(transport);
|
|
609
|
+
transportConnectMs = Date.now() - transportStartedAtMs;
|
|
610
|
+
// Set request-level phases before the SDK writes response headers. Tool calls replace this
|
|
611
|
+
// with the richer envelope/handler breakdown from onToolCallTiming above.
|
|
492
612
|
if (!res.headersSent) {
|
|
493
613
|
setServerTimingHeader(res, [
|
|
494
614
|
{ name: 'auth', durationMs: authMs },
|
|
@@ -496,94 +616,90 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
496
616
|
{ name: 'rate-limit', durationMs: rateLimitMs },
|
|
497
617
|
{ name: 'runtime', durationMs: runtimeConstructionMs },
|
|
498
618
|
{ name: 'transport-connect', durationMs: transportConnectMs },
|
|
499
|
-
{ name: 'tool-envelope-prepare', durationMs: timing.preparationMs },
|
|
500
|
-
{ name: 'tool-envelope-validate', durationMs: timing.validationMs },
|
|
501
|
-
{ name: 'tool-handler', durationMs: timing.handlerMs },
|
|
502
|
-
...Object.entries(timing.subphases).map(([phase, durationMs]) => ({
|
|
503
|
-
name: `tool-${phase}`,
|
|
504
|
-
durationMs,
|
|
505
|
-
})),
|
|
506
619
|
]);
|
|
507
620
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
sessionIdGenerator: undefined,
|
|
513
|
-
enableJsonResponse: true,
|
|
514
|
-
});
|
|
515
|
-
const transportStartedAtMs = Date.now();
|
|
516
|
-
await runtime.server.connect(transport);
|
|
517
|
-
transportConnectMs = Date.now() - transportStartedAtMs;
|
|
518
|
-
if (!initializeRequest) {
|
|
519
|
-
// Stateless cloud sessions still require a valid MCP JSON-RPC request;
|
|
520
|
-
// let the SDK validate and respond rather than trying to track sessions server-side.
|
|
521
|
-
}
|
|
522
|
-
const requestHandlingStartedAtMs = Date.now();
|
|
523
|
-
await transport.handleRequest(req, res, body);
|
|
524
|
-
requestHandlingMs = Date.now() - requestHandlingStartedAtMs;
|
|
525
|
-
recordCloudMcpCredentialUsage(req, auth.authenticatedViaToken, auth.authenticatedViaOAuth);
|
|
526
|
-
}
|
|
527
|
-
catch (error) {
|
|
528
|
-
outcome = 'failure';
|
|
529
|
-
console.error('[Taskforce MCP] Cloud transport request failed:', {
|
|
530
|
-
requestId,
|
|
531
|
-
kind: 'tool_transport_failure',
|
|
532
|
-
message: error instanceof Error ? error.message : String(error),
|
|
533
|
-
});
|
|
534
|
-
if (!res.headersSent) {
|
|
535
|
-
writeMcpHttpError(res, 500, 'MCP transport failure.', {
|
|
536
|
-
kind: 'tool_transport_failure',
|
|
537
|
-
retryable: true,
|
|
538
|
-
requestId,
|
|
539
|
-
});
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
finally {
|
|
543
|
-
if (runtime) {
|
|
544
|
-
const cleanupStartedAtMs = Date.now();
|
|
545
|
-
try {
|
|
546
|
-
await runtime.server.close();
|
|
621
|
+
const requestHandlingStartedAtMs = Date.now();
|
|
622
|
+
await transport.handleRequest(req, res, body);
|
|
623
|
+
requestHandlingMs = Date.now() - requestHandlingStartedAtMs;
|
|
624
|
+
recordCloudMcpCredentialUsage(req, auth.authenticatedViaToken, auth.authenticatedViaOAuth);
|
|
547
625
|
}
|
|
548
|
-
catch (
|
|
549
|
-
|
|
626
|
+
catch (error) {
|
|
627
|
+
outcome = 'failure';
|
|
628
|
+
console.error('[Taskforce MCP] Cloud transport request failed:', {
|
|
629
|
+
requestId,
|
|
630
|
+
kind: 'tool_transport_failure',
|
|
631
|
+
message: error instanceof Error ? error.message : String(error),
|
|
632
|
+
});
|
|
633
|
+
if (!res.headersSent) {
|
|
634
|
+
writeMcpHttpError(res, 500, 'MCP transport failure.', {
|
|
635
|
+
kind: 'tool_transport_failure',
|
|
636
|
+
retryable: true,
|
|
637
|
+
requestId,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
finally {
|
|
642
|
+
if (runtimeLease) {
|
|
643
|
+
const cleanupStartedAtMs = Date.now();
|
|
644
|
+
try {
|
|
645
|
+
await runtimeLease.release();
|
|
646
|
+
}
|
|
647
|
+
catch (closeError) {
|
|
648
|
+
console.warn('[Taskforce MCP] Cloud test runtime lease cleanup failed:', closeError);
|
|
649
|
+
}
|
|
650
|
+
cleanupMs = Date.now() - cleanupStartedAtMs;
|
|
651
|
+
}
|
|
652
|
+
else if (runtime) {
|
|
653
|
+
const cleanupStartedAtMs = Date.now();
|
|
654
|
+
try {
|
|
655
|
+
await runtime.server.close();
|
|
656
|
+
}
|
|
657
|
+
catch (closeError) {
|
|
658
|
+
console.warn('[Taskforce MCP] Cloud transport cleanup failed:', closeError);
|
|
659
|
+
}
|
|
660
|
+
cleanupMs = Date.now() - cleanupStartedAtMs;
|
|
661
|
+
}
|
|
662
|
+
const totalDurationMs = Date.now() - requestStartedAtMs;
|
|
663
|
+
if (initializeRequest || mcpMethod === 'tools/list' || writeToolNames.length > 0 || totalDurationMs >= 250) {
|
|
664
|
+
const timingSnapshot = toolTimingState.value;
|
|
665
|
+
console.info(`[Taskforce MCP] ${JSON.stringify({
|
|
666
|
+
event: 'cloud_request_timing',
|
|
667
|
+
requestId,
|
|
668
|
+
requestKind: initializeRequest
|
|
669
|
+
? 'initialize'
|
|
670
|
+
: mcpMethod === 'tools/list'
|
|
671
|
+
? 'tools_list'
|
|
672
|
+
: (extractFirstMcpToolName(body) ? 'tool_call' : 'other'),
|
|
673
|
+
method: mcpMethod || null,
|
|
674
|
+
toolName: extractFirstMcpToolName(body),
|
|
675
|
+
workspaceId: auth.workspaceId,
|
|
676
|
+
databaseProvider: core.getDatabaseProvider(),
|
|
677
|
+
authMode: auth.authenticatedViaToken ? 'token' : auth.authenticatedViaOAuth ? 'oauth' : 'user',
|
|
678
|
+
batchSize: Array.isArray(body) ? body.length : 1,
|
|
679
|
+
isWrite: writeToolNames.length > 0,
|
|
680
|
+
outcome,
|
|
681
|
+
httpStatus: res.statusCode,
|
|
682
|
+
responseBytes: timingSnapshot?.responseBytes ?? null,
|
|
683
|
+
totalDurationMs,
|
|
684
|
+
preRuntimeMs: Math.max(0, totalDurationMs - runtimeConstructionMs - transportConnectMs - requestHandlingMs - cleanupMs),
|
|
685
|
+
authMs,
|
|
686
|
+
bodyParseMs,
|
|
687
|
+
rateLimitMs,
|
|
688
|
+
runtimeConstructionMs,
|
|
689
|
+
transportConnectMs,
|
|
690
|
+
requestHandlingMs,
|
|
691
|
+
cleanupMs,
|
|
692
|
+
toolTiming: timingSnapshot,
|
|
693
|
+
})}`);
|
|
694
|
+
}
|
|
550
695
|
}
|
|
551
|
-
cleanupMs = Date.now() - cleanupStartedAtMs;
|
|
552
696
|
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
event: 'cloud_request_timing',
|
|
558
|
-
requestId,
|
|
559
|
-
requestKind: initializeRequest
|
|
560
|
-
? 'initialize'
|
|
561
|
-
: mcpMethod === 'tools/list'
|
|
562
|
-
? 'tools_list'
|
|
563
|
-
: (extractFirstMcpToolName(body) ? 'tool_call' : 'other'),
|
|
564
|
-
method: mcpMethod || null,
|
|
565
|
-
toolName: extractFirstMcpToolName(body),
|
|
566
|
-
workspaceId: auth.workspaceId,
|
|
567
|
-
databaseProvider: core.getDatabaseProvider(),
|
|
568
|
-
authMode: auth.authenticatedViaToken ? 'token' : auth.authenticatedViaOAuth ? 'oauth' : 'user',
|
|
569
|
-
batchSize: Array.isArray(body) ? body.length : 1,
|
|
570
|
-
isWrite: writeToolNames.length > 0,
|
|
571
|
-
outcome,
|
|
572
|
-
httpStatus: res.statusCode,
|
|
573
|
-
responseBytes: timingSnapshot?.responseBytes ?? null,
|
|
574
|
-
totalDurationMs,
|
|
575
|
-
preRuntimeMs: Math.max(0, totalDurationMs - runtimeConstructionMs - transportConnectMs - requestHandlingMs - cleanupMs),
|
|
576
|
-
authMs,
|
|
577
|
-
bodyParseMs,
|
|
578
|
-
rateLimitMs,
|
|
579
|
-
runtimeConstructionMs,
|
|
580
|
-
transportConnectMs,
|
|
581
|
-
requestHandlingMs,
|
|
582
|
-
cleanupMs,
|
|
583
|
-
toolTiming: timingSnapshot,
|
|
584
|
-
})}`);
|
|
697
|
+
finally {
|
|
698
|
+
settleCapacity(Boolean(req.destroyed && !res.writableEnded));
|
|
699
|
+
res.off('finish', onFinish);
|
|
700
|
+
res.off('close', onClose);
|
|
585
701
|
}
|
|
586
|
-
}
|
|
702
|
+
});
|
|
587
703
|
};
|
|
588
704
|
}
|
|
589
705
|
// === SECTION: Request header helpers ===
|
|
@@ -573,6 +573,7 @@ export function registerSyncRoutes(deps) {
|
|
|
573
573
|
}
|
|
574
574
|
const { result } = await dispatchWorkspaceSyncChanges(cloudWorkspaceId, fenced.changes, {
|
|
575
575
|
coexistenceDirection: 'cloud-push',
|
|
576
|
+
actorUserId: access.userId,
|
|
576
577
|
assertedActiveV3TaskMetadataIds,
|
|
577
578
|
assertedActiveV3TaskLifecycleIds,
|
|
578
579
|
assertedActiveV3TaskReopenAssigneeIds,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { applyWorkspaceRepair } from '../../sync/workspaceRepair.js';
|
|
2
|
+
import { WorkspaceSyncContentPullObligationStore } from '../../sync/engine/workspaceSyncContentPullObligationStore.js';
|
|
2
3
|
import { normalizeSyncEventDetails } from '../../utils/syncEventDetails.js';
|
|
3
4
|
import { parseJsonBody } from './primitives.js';
|
|
4
5
|
import { requireAuthenticatedSyncRequest } from './syncRouteGuards.js';
|
|
@@ -54,7 +55,9 @@ export function registerWorkspaceSyncAuxRoutes({ addRoute, core, context, resolv
|
|
|
54
55
|
// stale links. Does NOT tombstone metadata for files that appear missing locally — a single
|
|
55
56
|
// failed existence check at startup can mean the content is only temporarily unavailable
|
|
56
57
|
// (e.g. storage not yet mounted/synced), not deleted; that requires explicit admin
|
|
57
|
-
// confirmation via /api/taskforce/admin/workspace-repair/apply. Never deletes files.
|
|
58
|
+
// confirmation via /api/taskforce/admin/workspace-repair/apply. Never deletes files. When
|
|
59
|
+
// content availability genuinely can't be verified, queues a durable content-pull recovery
|
|
60
|
+
// obligation instead, which resolves automatically once a later scan confirms the content.
|
|
58
61
|
// Called once by the sync orchestrator when the workspace becomes active.
|
|
59
62
|
addRoute('POST', '/api/taskforce/sync/workspace/repair-startup', async (req, res) => {
|
|
60
63
|
const authConfig = context.authConfig;
|
|
@@ -83,6 +86,7 @@ export function registerWorkspaceSyncAuxRoutes({ addRoute, core, context, resolv
|
|
|
83
86
|
deletedTasks: core.listWorkspaceSyncDeletes(workspaceId) || [],
|
|
84
87
|
workspaceAssetStore,
|
|
85
88
|
publishedContentResolver,
|
|
89
|
+
contentPullObligationStore: new WorkspaceSyncContentPullObligationStore(core.getDatabaseAdapter()),
|
|
86
90
|
aiProfiles: typeof core.listAiProfiles === 'function'
|
|
87
91
|
? core.listAiProfiles(workspaceId, { includeArchived: true }) || []
|
|
88
92
|
: [],
|
|
@@ -21,6 +21,7 @@ interface RegisterWorkspacePushSyncRoutesArgs {
|
|
|
21
21
|
dispatchWorkspaceSyncChanges: (workspaceId: string, incomingChanges: WorkspaceSyncChange[], options?: {
|
|
22
22
|
allowReferenceNumberReassignment?: boolean;
|
|
23
23
|
coexistenceDirection?: 'cloud-push';
|
|
24
|
+
actorUserId?: string;
|
|
24
25
|
assertedActiveV3TaskMetadataIds?: ReadonlySet<string>;
|
|
25
26
|
assertedActiveV3TaskLifecycleIds?: ReadonlySet<string>;
|
|
26
27
|
assertedActiveV3TaskReopenAssigneeIds?: ReadonlySet<string>;
|
|
@@ -270,6 +270,7 @@ export function registerWorkspacePushSyncRoutes({ addRoute, core, context, audit
|
|
|
270
270
|
const { result, deleteCount, emittedEventIds } = await dispatchWorkspaceSyncChanges(targetWorkspaceId, incomingChanges, {
|
|
271
271
|
allowReferenceNumberReassignment,
|
|
272
272
|
coexistenceDirection: 'cloud-push',
|
|
273
|
+
actorUserId: String(access.userId || '').trim(),
|
|
273
274
|
assertedActiveV3TaskMetadataIds,
|
|
274
275
|
assertedActiveV3TaskLifecycleIds,
|
|
275
276
|
assertedActiveV3TaskReopenAssigneeIds,
|