@taskforcehq/taskforce 0.3.329 → 0.3.330
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Taskforce.module.css +290 -45
- package/dist/components/features/AiProfilesModule.js +3 -5
- package/dist/components/features/TaskSettings.js +70 -14
- package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
- package/dist/components/features/TaskforceAgentsModule.js +586 -116
- package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
- package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
- package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
- package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
- package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
- package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
- package/dist/components/features/taskforceAgentEditorModel.js +3 -1
- package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
- package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
- package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
- package/dist/components/views/StandaloneLayout.js +27 -26
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
- package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
- package/dist/config/envSchema.js +48 -1
- package/dist/core/McpTokenService.d.ts +23 -1
- package/dist/core/McpTokenService.js +93 -10
- package/dist/core/TaskChecklistCommandService.d.ts +27 -0
- package/dist/core/TaskChecklistCommandService.js +83 -5
- package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
- package/dist/core/TaskLifecycleCommandService.js +6 -2
- package/dist/core/Taskforce.d.ts +32 -0
- package/dist/core/Taskforce.js +125 -4
- package/dist/core/types.d.ts +8 -0
- package/dist/documentReviews/commandService.d.ts +2 -1
- package/dist/documentReviews/commandService.js +6 -3
- package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.js +2 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
- package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
- package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
- package/dist/hooks/sync/useSyncStatusControls.js +47 -11
- package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
- package/dist/hooks/useSyncOrchestrator.js +111 -2
- package/dist/hooks/useTaskData.d.ts +31 -1
- package/dist/hooks/useTaskData.js +29 -7
- package/dist/hooks/useTaskMutations.d.ts +3 -1
- package/dist/hooks/useTaskMutations.js +46 -12
- package/dist/hooks/useTaskforce.d.ts +2 -0
- package/dist/hooks/useTaskforce.js +11 -2
- package/dist/mcp/clientRegistry.d.ts +2 -2
- package/dist/mcp/clientRegistry.js +1 -1
- package/dist/mcp/documentAssetRegistrar.js +9 -6
- package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
- package/dist/mcp/durableTaskMutationRouter.js +10 -0
- package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
- package/dist/mcp/httpProtocolRouting.d.ts +10 -0
- package/dist/mcp/httpProtocolRouting.js +19 -0
- package/dist/mcp/localCliHealth.d.ts +2 -2
- package/dist/mcp/localCliHealth.js +2 -2
- package/dist/mcp/localServiceProxy.d.ts +1 -0
- package/dist/mcp/localServiceProxy.js +530 -68
- package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
- package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
- package/dist/mcp/runtime.d.ts +54 -79
- package/dist/mcp/runtime.js +384 -97
- package/dist/mcp/taskPlanningRegistrar.js +23 -4
- package/dist/mcp/toolProfiles.d.ts +2 -0
- package/dist/mcp/toolProfiles.js +10 -0
- package/dist/mcp/toolRegistry.d.ts +1 -0
- package/dist/mcp/toolRegistry.js +1 -0
- package/dist/mcp/workflowExecutionRegistrar.js +4 -4
- package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
- package/dist/migrations/taskSchemaMigrations.js +415 -0
- package/dist/runtime/appGates.d.ts +2 -1
- package/dist/runtime/appGates.js +7 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +108 -11
- package/dist/server/localDatabaseIdentity.js +4 -1
- package/dist/server/localServiceLease.js +2 -1
- package/dist/server/localServiceSessions.d.ts +14 -17
- package/dist/server/localServiceSessions.js +308 -94
- package/dist/server/localWorkspaceSyncServerRuntime.js +12 -14
- package/dist/server/routes/admin.d.ts +4 -0
- package/dist/server/routes/admin.js +112 -3
- package/dist/server/routes/agents.d.ts +7 -0
- package/dist/server/routes/agents.js +277 -24
- package/dist/server/routes/billing.js +5 -1
- package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
- package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
- package/dist/server/routes/executorPhaseAApprovals.js +140 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
- package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
- package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
- package/dist/server/routes/githubReviewEvidence.js +116 -0
- package/dist/server/routes/localService.d.ts +15 -4
- package/dist/server/routes/localService.js +136 -40
- package/dist/server/routes/modelConnections.d.ts +24 -0
- package/dist/server/routes/modelConnections.js +205 -0
- package/dist/server/routes/shared.d.ts +19 -0
- package/dist/server/routes/shared.js +95 -19
- package/dist/server/routes/sync.js +1 -0
- package/dist/server/routes/syncAuxRoutes.js +5 -1
- package/dist/server/routes/syncPushRoutes.d.ts +1 -0
- package/dist/server/routes/syncPushRoutes.js +1 -0
- package/dist/server/routes/syncV3FeedRoutes.js +10 -1
- package/dist/server/routes/syncV3OperationRoutes.js +35 -9
- package/dist/server/routes/tasks.js +21 -2
- package/dist/server/routes/workflows.js +9 -1
- package/dist/server/routes.js +59 -0
- package/dist/services/codexAppServerModelGateway.d.ts +54 -5
- package/dist/services/codexAppServerModelGateway.js +246 -21
- package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
- package/dist/services/codexDeviceCodeLoginManager.js +265 -0
- package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
- package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
- package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
- package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
- package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
- package/dist/services/executorPhaseAApprovalService.js +609 -0
- package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
- package/dist/services/executorPhaseADriftEvaluator.js +93 -0
- package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
- package/dist/services/executorPhaseAIssuerCore.js +295 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
- package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
- package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
- package/dist/services/githubReviewEvidenceRuntime.js +30 -0
- package/dist/services/githubReviewEvidenceService.d.ts +93 -0
- package/dist/services/githubReviewEvidenceService.js +336 -0
- package/dist/services/modelGateway.d.ts +7 -0
- package/dist/services/modelProviderConnectionService.d.ts +71 -0
- package/dist/services/modelProviderConnectionService.js +279 -0
- package/dist/services/modelProviderCredentialHome.d.ts +32 -0
- package/dist/services/modelProviderCredentialHome.js +271 -0
- package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
- package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
- package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
- package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
- package/dist/services/taskforceAgentMcpBridge.d.ts +1 -1
- package/dist/services/taskforceAgentMcpBridge.js +7 -24
- package/dist/shared/adminEdgeProxy.d.ts +5 -0
- package/dist/shared/adminEdgeProxy.js +94 -0
- package/dist/shared/adminProxySessionCookies.d.ts +16 -0
- package/dist/shared/adminProxySessionCookies.js +86 -0
- package/dist/shared/aiProfileColors.d.ts +31 -1
- package/dist/shared/aiProfileColors.js +14 -6
- package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
- package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
- package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
- package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
- package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
- package/dist/shared/executorPhaseADriftContracts.js +63 -0
- package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
- package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
- package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
- package/dist/shared/executorPhaseARunAuthorization.js +232 -0
- package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
- package/dist/shared/executorPhaseASchemaValidation.js +53 -0
- package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
- package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
- package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
- package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
- package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
- package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
- package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
- package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
- package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
- package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
- package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
- package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
- package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
- package/dist/shared/executorPhaseATiming.d.ts +1 -0
- package/dist/shared/executorPhaseATiming.js +1 -0
- package/dist/shared/planningIdentity.js +1 -1
- package/dist/shared/productLogoKeys.d.ts +2 -0
- package/dist/shared/productLogoKeys.js +18 -0
- package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
- package/dist/shared/taskforceAgentDefinition.js +6 -9
- package/dist/shared/taskforceAgentModels.js +7 -3
- package/dist/shared/userFeatureGrants.d.ts +4 -0
- package/dist/shared/userFeatureGrants.js +7 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
- package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
- package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
- package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
- package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
- package/dist/storage/modelProviderConnectionStore.js +446 -0
- package/dist/storage/postgresAdapter.d.ts +4 -0
- package/dist/storage/postgresAdapter.js +11 -0
- package/dist/storage/postgresWorker.js +9 -1
- package/dist/storage/postgresWorkerProtocol.d.ts +1 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
- package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
- package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
- package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
- package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
- package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
- package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
- package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
- package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
- package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
- package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
- package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
- package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
- package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
- package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
- package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
- package/dist/sync/syncApplyHandlers.d.ts +2 -0
- package/dist/sync/syncApplyHandlers.js +10 -1
- package/dist/sync/syncService.d.ts +15 -0
- package/dist/sync/syncService.js +83 -18
- package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
- package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
- package/dist/sync/v3/combinedFeedCapability.js +4 -0
- package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
- package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
- package/dist/sync/v3/durableOperationReplay.js +18 -0
- package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
- package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
- package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
- package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
- package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
- package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
- package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
- package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
- package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
- package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
- package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
- package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
- package/dist/sync/v3/localTaskStatusOutboxService.d.ts +8 -0
- package/dist/sync/v3/localTaskStatusOutboxService.js +219 -12
- package/dist/sync/v3/syncDurabilityStore.d.ts +34 -0
- package/dist/sync/v3/syncDurabilityStore.js +168 -2
- package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
- package/dist/sync/v3/taskChecklistMutationService.js +44 -1
- package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
- package/dist/sync/v3/taskStatusMutationService.js +119 -3
- package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
- package/dist/sync/v3/workflowAssignmentSync.js +27 -0
- package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
- package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
- package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
- package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
- package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
- package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
- package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
- package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
- package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
- package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
- package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
- package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
- package/dist/sync/workspaceRepair.d.ts +5 -2
- package/dist/sync/workspaceRepair.js +161 -6
- package/dist/sync/workspaceSyncModel.d.ts +21 -0
- package/dist/sync/workspaceSyncModel.js +35 -7
- package/dist/sync/workspaceSyncState.d.ts +1 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
- package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
- package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
- package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-BTM6nIg_.js} +1 -1
- package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-DabEG8L4.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-Coa8yVGM.js} +1 -1
- package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-BB0qhdix.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
- package/dist/ui/assets/{PlanningModule-B5DWQOGz.js → PlanningModule-pRPjR7v5.js} +1 -1
- package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-D86pZSSl.js} +1 -1
- package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-BVIkU9yT.js} +1 -1
- package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
- package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
- package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
- package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
- package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
- package/dist/ui/assets/index-CTsDBaef.js +7 -0
- package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
- package/dist/ui/branding/logos/letterhead_dark.png +0 -0
- package/dist/ui/branding/logos/letterhead_light.png +0 -0
- package/dist/ui/branding/logos/signature_dark.png +0 -0
- package/dist/ui/branding/logos/signature_light.png +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/utils/aiProfileDefaultLogo.js +16 -48
- package/dist/utils/httpSetCookie.d.ts +1 -0
- package/dist/utils/httpSetCookie.js +4 -1
- package/dist/utils/localRuntimeUrl.d.ts +1 -0
- package/dist/utils/localRuntimeUrl.js +14 -0
- package/dist/utils/productLogoRegistry.d.ts +2 -0
- package/dist/utils/productLogoRegistry.js +36 -0
- package/dist/utils/syncStatusPresentation.d.ts +4 -0
- package/dist/utils/syncStatusPresentation.js +17 -0
- package/dist/utils/taskEvents.d.ts +2 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
- package/dist/utils/workspaceSyncPresentation.js +23 -17
- package/package.json +22 -4
- package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
- package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
- package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
- package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
- package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
- package/dist/ui/assets/index-I5zhdtgt.js +0 -7
- package/dist/ui/assets/index-VRFsx3wz.css +0 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY } from '../../shared/userFeatureGrants.js';
|
|
2
|
+
import { ModelProviderConnectionError, ModelProviderConnectionStore, } from '../../storage/modelProviderConnectionStore.js';
|
|
3
|
+
import { ModelProviderCredentialHomeManager } from '../../services/modelProviderCredentialHome.js';
|
|
4
|
+
import { ModelProviderConnectionService, } from '../../services/modelProviderConnectionService.js';
|
|
5
|
+
import { CodexDeviceCodeLoginManager, } from '../../services/codexDeviceCodeLoginManager.js';
|
|
6
|
+
import { createCodexModelProviderConnectionLifecycleHandlers } from '../../services/codexModelProviderConnectionLifecycle.js';
|
|
7
|
+
import { parseJsonBody } from './primitives.js';
|
|
8
|
+
function writeJson(res, statusCode, payload) {
|
|
9
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
10
|
+
res.end(JSON.stringify(payload));
|
|
11
|
+
}
|
|
12
|
+
function writeError(res, error) {
|
|
13
|
+
const knownError = error instanceof ModelProviderConnectionError;
|
|
14
|
+
const statusCode = Number(error?.statusCode);
|
|
15
|
+
const safeStatusCode = Number.isInteger(statusCode) && statusCode >= 400 && statusCode <= 599
|
|
16
|
+
? statusCode
|
|
17
|
+
: 500;
|
|
18
|
+
const code = knownError && typeof error?.code === 'string'
|
|
19
|
+
? String(error.code)
|
|
20
|
+
: 'MODEL_CONNECTION_REQUEST_FAILED';
|
|
21
|
+
const message = knownError
|
|
22
|
+
? String(error?.message || 'Model connection request failed.')
|
|
23
|
+
: 'Model connection request failed.';
|
|
24
|
+
writeJson(res, safeStatusCode, { success: false, error: message, code });
|
|
25
|
+
}
|
|
26
|
+
export function registerModelConnectionsRoutes(deps) {
|
|
27
|
+
const { addRoute, ensureAppAccess, resolveAuthenticatedUserId, resolveRuntimeMode, core, } = deps;
|
|
28
|
+
let resolvedService = deps.service;
|
|
29
|
+
let resolvedLoginManager = deps.loginManager;
|
|
30
|
+
let resolvedStore = null;
|
|
31
|
+
const store = () => {
|
|
32
|
+
if (resolvedStore)
|
|
33
|
+
return resolvedStore;
|
|
34
|
+
if (!core)
|
|
35
|
+
throw new Error('Model connection store is unavailable.');
|
|
36
|
+
resolvedStore = new ModelProviderConnectionStore(core.getDatabaseAdapter(), core.getTenantId());
|
|
37
|
+
return resolvedStore;
|
|
38
|
+
};
|
|
39
|
+
const service = () => {
|
|
40
|
+
if (resolvedService)
|
|
41
|
+
return resolvedService;
|
|
42
|
+
if (!core)
|
|
43
|
+
throw new Error('Model connection service is unavailable.');
|
|
44
|
+
const lifecycleHandlers = deps.lifecycleHandlers || [{
|
|
45
|
+
providerKey: 'openai',
|
|
46
|
+
authenticationType: 'chatgpt_device_code',
|
|
47
|
+
lifecycle: createCodexModelProviderConnectionLifecycleHandlers(),
|
|
48
|
+
}];
|
|
49
|
+
resolvedService = new ModelProviderConnectionService(store(), new ModelProviderCredentialHomeManager(deps.credentialStoragePath), (userId) => core.hasUserFeatureGrant(userId, INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY), lifecycleHandlers);
|
|
50
|
+
return resolvedService;
|
|
51
|
+
};
|
|
52
|
+
const loginManager = () => {
|
|
53
|
+
if (resolvedLoginManager)
|
|
54
|
+
return resolvedLoginManager;
|
|
55
|
+
const connectionService = service();
|
|
56
|
+
if (!(connectionService instanceof ModelProviderConnectionService)) {
|
|
57
|
+
throw new Error('Model connection login manager is unavailable.');
|
|
58
|
+
}
|
|
59
|
+
resolvedLoginManager = new CodexDeviceCodeLoginManager(connectionService, store());
|
|
60
|
+
return resolvedLoginManager;
|
|
61
|
+
};
|
|
62
|
+
const authorize = (req, res) => {
|
|
63
|
+
if (!ensureAppAccess(req, res))
|
|
64
|
+
return null;
|
|
65
|
+
if (resolveRuntimeMode(req) !== 'cloud') {
|
|
66
|
+
writeJson(res, 404, {
|
|
67
|
+
success: false,
|
|
68
|
+
error: 'Model connections are unavailable in this runtime.',
|
|
69
|
+
code: 'MODEL_CONNECTIONS_CLOUD_ONLY',
|
|
70
|
+
});
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
const userId = String(resolveAuthenticatedUserId(req) || '').trim();
|
|
74
|
+
if (!userId) {
|
|
75
|
+
writeJson(res, 401, {
|
|
76
|
+
success: false,
|
|
77
|
+
error: 'Authentication is required.',
|
|
78
|
+
code: 'AUTH_REQUIRED',
|
|
79
|
+
});
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return userId;
|
|
83
|
+
};
|
|
84
|
+
addRoute('GET', '/api/taskforce/model-connections', async (req, res) => {
|
|
85
|
+
const ownerUserId = authorize(req, res);
|
|
86
|
+
if (!ownerUserId)
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
writeJson(res, 200, {
|
|
90
|
+
success: true,
|
|
91
|
+
eligible: core ? core.hasUserFeatureGrant(ownerUserId, INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY) : true,
|
|
92
|
+
connections: service().list(ownerUserId),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
writeError(res, error);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
addRoute('POST', '/api/taskforce/model-connections', async (req, res) => {
|
|
100
|
+
const ownerUserId = authorize(req, res);
|
|
101
|
+
if (!ownerUserId)
|
|
102
|
+
return;
|
|
103
|
+
try {
|
|
104
|
+
const body = await parseJsonBody(req, 16 * 1024);
|
|
105
|
+
const connection = service().create({
|
|
106
|
+
ownerUserId,
|
|
107
|
+
providerKey: String(body?.providerKey || ''),
|
|
108
|
+
authenticationType: String(body?.authenticationType || ''),
|
|
109
|
+
});
|
|
110
|
+
writeJson(res, 201, { success: true, connection });
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
writeError(res, error);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
addRoute('GET', '/api/taskforce/model-connections/:connectionId', async (req, res, params) => {
|
|
117
|
+
const ownerUserId = authorize(req, res);
|
|
118
|
+
if (!ownerUserId)
|
|
119
|
+
return;
|
|
120
|
+
try {
|
|
121
|
+
writeJson(res, 200, {
|
|
122
|
+
success: true,
|
|
123
|
+
connection: service().get(ownerUserId, params.connectionId),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
writeError(res, error);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
addRoute('PATCH', '/api/taskforce/model-connections/:connectionId', async (req, res, params) => {
|
|
131
|
+
const ownerUserId = authorize(req, res);
|
|
132
|
+
if (!ownerUserId)
|
|
133
|
+
return;
|
|
134
|
+
try {
|
|
135
|
+
const body = await parseJsonBody(req, 16 * 1024);
|
|
136
|
+
const connection = service().rename(ownerUserId, params.connectionId, body?.displayName);
|
|
137
|
+
writeJson(res, 200, { success: true, connection });
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
writeError(res, error);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
addRoute('POST', '/api/taskforce/model-connections/:connectionId/login', async (req, res, params) => {
|
|
144
|
+
const ownerUserId = authorize(req, res);
|
|
145
|
+
if (!ownerUserId)
|
|
146
|
+
return;
|
|
147
|
+
try {
|
|
148
|
+
const login = await loginManager().start(ownerUserId, params.connectionId);
|
|
149
|
+
writeJson(res, 202, { success: true, login });
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
writeError(res, error);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
addRoute('GET', '/api/taskforce/model-connections/:connectionId/login/:sessionId', async (req, res, params) => {
|
|
156
|
+
const ownerUserId = authorize(req, res);
|
|
157
|
+
if (!ownerUserId)
|
|
158
|
+
return;
|
|
159
|
+
try {
|
|
160
|
+
const login = loginManager().get(ownerUserId, params.connectionId, params.sessionId);
|
|
161
|
+
writeJson(res, 200, { success: true, login });
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
writeError(res, error);
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
addRoute('POST', '/api/taskforce/model-connections/:connectionId/login/:sessionId/cancel', async (req, res, params) => {
|
|
168
|
+
const ownerUserId = authorize(req, res);
|
|
169
|
+
if (!ownerUserId)
|
|
170
|
+
return;
|
|
171
|
+
try {
|
|
172
|
+
const login = await loginManager().cancel(ownerUserId, params.connectionId, params.sessionId);
|
|
173
|
+
writeJson(res, 200, { success: true, login });
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
writeError(res, error);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
for (const operation of ['verify', 'refresh', 'disconnect']) {
|
|
180
|
+
addRoute('POST', `/api/taskforce/model-connections/:connectionId/${operation}`, async (req, res, params) => {
|
|
181
|
+
const ownerUserId = authorize(req, res);
|
|
182
|
+
if (!ownerUserId)
|
|
183
|
+
return;
|
|
184
|
+
try {
|
|
185
|
+
const connection = await service()[operation](ownerUserId, params.connectionId);
|
|
186
|
+
writeJson(res, 200, { success: true, connection });
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
writeError(res, error);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
addRoute('DELETE', '/api/taskforce/model-connections/:connectionId', async (req, res, params) => {
|
|
194
|
+
const ownerUserId = authorize(req, res);
|
|
195
|
+
if (!ownerUserId)
|
|
196
|
+
return;
|
|
197
|
+
try {
|
|
198
|
+
const result = await service().cleanup(ownerUserId, params.connectionId);
|
|
199
|
+
writeJson(res, 200, { success: true, ...result });
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
writeError(res, error);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* routes.ts at runtime.
|
|
7
7
|
*/
|
|
8
8
|
import { IncomingMessage, ServerResponse } from 'http';
|
|
9
|
+
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
|
|
9
10
|
import { TaskforceCore } from '../../core/Taskforce.js';
|
|
10
11
|
import type { McpAccessTokenAuthResult, McpOAuthAccessTokenAuthResult, McpAccessTokenScope } from '../../core/Taskforce.js';
|
|
11
12
|
import { type RouteContext } from './primitives.js';
|
|
13
|
+
import { type McpRuntimeFactory, type TaskforceMcpServerOptions } from '../../mcp/runtime.js';
|
|
12
14
|
import { type AiProfileBootstrapConfig } from '../../mcp/aiProfileBootstrap.js';
|
|
13
15
|
import type { AiProfileSeatScope } from '../../shared/aiProfileSeatScope.js';
|
|
14
16
|
import { type RequestPerformanceDiagnostics } from '../../storage/postgresRequestDiagnostics.js';
|
|
@@ -100,6 +102,20 @@ export declare function makeAuthenticateCloudMcpRequest(core: TaskforceCore, dep
|
|
|
100
102
|
resolveAuthenticatedUserId: (req: IncomingMessage) => string;
|
|
101
103
|
writeMcpHttpError: (res: ServerResponse, statusCode: number, message: string, data?: Record<string, unknown>) => void;
|
|
102
104
|
}): (req: IncomingMessage, res: ServerResponse) => CloudMcpRequestAuth | null;
|
|
105
|
+
export type CloudMcpToolPolicy = {
|
|
106
|
+
requiredScope: McpAccessTokenScope | null;
|
|
107
|
+
isWrite: boolean;
|
|
108
|
+
};
|
|
109
|
+
export type CloudMcpToolPolicyResolver = (toolName: string) => CloudMcpToolPolicy;
|
|
110
|
+
export interface CloudMcpRuntimeLease {
|
|
111
|
+
runtime: ReturnType<McpRuntimeFactory>;
|
|
112
|
+
transport: NodeStreamableHTTPServerTransport;
|
|
113
|
+
release(): Promise<void>;
|
|
114
|
+
}
|
|
115
|
+
export type AcquireCloudMcpRuntime = (input: {
|
|
116
|
+
req: IncomingMessage;
|
|
117
|
+
options: TaskforceMcpServerOptions;
|
|
118
|
+
}) => Promise<CloudMcpRuntimeLease>;
|
|
103
119
|
export declare function makeHandleCloudMcpRequest(core: TaskforceCore, deps: {
|
|
104
120
|
ensureAppAccess: (req: IncomingMessage, res: ServerResponse) => boolean;
|
|
105
121
|
resolveAuthenticatedUserId: (req: IncomingMessage) => string;
|
|
@@ -109,6 +125,9 @@ export declare function makeHandleCloudMcpRequest(core: TaskforceCore, deps: {
|
|
|
109
125
|
workspaceMaxRequests: number;
|
|
110
126
|
windowMs: number;
|
|
111
127
|
};
|
|
128
|
+
createMcpServer?: McpRuntimeFactory;
|
|
129
|
+
resolveMcpToolPolicy?: CloudMcpToolPolicyResolver;
|
|
130
|
+
acquireMcpRuntime?: AcquireCloudMcpRuntime;
|
|
112
131
|
}): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
113
132
|
export declare function requestHeader(req: IncomingMessage, name: string, fallback?: string): string;
|
|
114
133
|
export declare function requestWorkspaceHeader(req: IncomingMessage): string;
|
|
@@ -6,17 +6,18 @@
|
|
|
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';
|
|
@@ -273,7 +274,14 @@ function writeMcpHttpError(res, statusCode, message, data) {
|
|
|
273
274
|
id: null,
|
|
274
275
|
}));
|
|
275
276
|
}
|
|
276
|
-
function
|
|
277
|
+
function resolveProductionCloudMcpToolPolicy(requestedToolName) {
|
|
278
|
+
const toolName = resolveCanonicalMcpToolName(requestedToolName);
|
|
279
|
+
return {
|
|
280
|
+
requiredScope: MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS[toolName] || null,
|
|
281
|
+
isWrite: isMcpWriteToolName(requestedToolName),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function extractMcpWriteToolNames(body, resolveToolPolicy) {
|
|
277
285
|
const messages = Array.isArray(body) ? body : [body];
|
|
278
286
|
const names = messages.flatMap((message) => {
|
|
279
287
|
if (!message || typeof message !== 'object')
|
|
@@ -282,7 +290,7 @@ function extractMcpWriteToolNames(body) {
|
|
|
282
290
|
if (method !== 'tools/call')
|
|
283
291
|
return [];
|
|
284
292
|
const toolName = String(message?.params?.name || '').trim();
|
|
285
|
-
return toolName &&
|
|
293
|
+
return toolName && resolveToolPolicy(toolName).isWrite ? [toolName] : [];
|
|
286
294
|
});
|
|
287
295
|
return Array.from(new Set(names));
|
|
288
296
|
}
|
|
@@ -299,7 +307,7 @@ function extractFirstMcpToolName(body) {
|
|
|
299
307
|
}
|
|
300
308
|
return null;
|
|
301
309
|
}
|
|
302
|
-
function findDeniedCloudMcpToolName(body, scopes) {
|
|
310
|
+
function findDeniedCloudMcpToolName(body, scopes, resolveToolPolicy) {
|
|
303
311
|
const messages = Array.isArray(body) ? body : [body];
|
|
304
312
|
for (const message of messages) {
|
|
305
313
|
if (!message || typeof message !== 'object')
|
|
@@ -309,15 +317,14 @@ function findDeniedCloudMcpToolName(body, scopes) {
|
|
|
309
317
|
const requestedToolName = String(message?.params?.name || '').trim();
|
|
310
318
|
if (!requestedToolName)
|
|
311
319
|
continue;
|
|
312
|
-
const
|
|
313
|
-
const requiredScope = MCP_CLOUD_TOOL_SCOPE_REQUIREMENTS[toolName];
|
|
320
|
+
const requiredScope = resolveToolPolicy(requestedToolName).requiredScope;
|
|
314
321
|
if (!requiredScope || !scopes.includes(requiredScope))
|
|
315
322
|
return requestedToolName;
|
|
316
323
|
}
|
|
317
324
|
return null;
|
|
318
325
|
}
|
|
319
326
|
export function makeHandleCloudMcpRequest(core, deps) {
|
|
320
|
-
const { ensureAppAccess, resolveAuthenticatedUserId, writeRateLimit } = deps;
|
|
327
|
+
const { ensureAppAccess, resolveAuthenticatedUserId, writeRateLimit, createMcpServer = createTaskforceMcpServer, resolveMcpToolPolicy = resolveProductionCloudMcpToolPolicy, acquireMcpRuntime, } = deps;
|
|
321
328
|
const authenticateCloudMcpRequest = makeAuthenticateCloudMcpRequest(core, {
|
|
322
329
|
resolveAuthenticatedUserId,
|
|
323
330
|
writeMcpHttpError,
|
|
@@ -342,7 +349,7 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
342
349
|
const applyCloudMcpWriteRateLimit = (req, res, auth, body) => {
|
|
343
350
|
if (!writeRateLimit.enabled)
|
|
344
351
|
return true;
|
|
345
|
-
const writeTools = extractMcpWriteToolNames(body);
|
|
352
|
+
const writeTools = extractMcpWriteToolNames(body, resolveMcpToolPolicy);
|
|
346
353
|
if (writeTools.length === 0)
|
|
347
354
|
return true;
|
|
348
355
|
const actorKey = auth.authenticatedViaToken?.tokenId
|
|
@@ -413,6 +420,10 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
413
420
|
writeMcpHttpError(res, 405, 'Method not allowed.');
|
|
414
421
|
return;
|
|
415
422
|
}
|
|
423
|
+
if (!isJsonContentType(requestHeader(req, 'content-type', ''))) {
|
|
424
|
+
writeMcpHttpError(res, 415, 'Unsupported Media Type: Content-Type must be application/json');
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
416
427
|
let body = undefined;
|
|
417
428
|
try {
|
|
418
429
|
const bodyParseStartedAtMs = Date.now();
|
|
@@ -431,7 +442,8 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
431
442
|
: '';
|
|
432
443
|
const initializeRequest = isInitializeRequest(body)
|
|
433
444
|
|| mcpMethod === 'initialize';
|
|
434
|
-
const
|
|
445
|
+
const modernProtocolRequest = await isModernMcpHttpRequest(req, body);
|
|
446
|
+
const deniedToolName = findDeniedCloudMcpToolName(body, authScopes, resolveMcpToolPolicy);
|
|
435
447
|
if (deniedToolName) {
|
|
436
448
|
core.addMcpAuditLog({
|
|
437
449
|
workspaceId: auth.workspaceId,
|
|
@@ -451,13 +463,14 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
451
463
|
writeMcpHttpError(res, 403, 'Forbidden.');
|
|
452
464
|
return;
|
|
453
465
|
}
|
|
454
|
-
const writeToolNames = extractMcpWriteToolNames(body);
|
|
466
|
+
const writeToolNames = extractMcpWriteToolNames(body, resolveMcpToolPolicy);
|
|
455
467
|
const rateLimitStartedAtMs = Date.now();
|
|
456
468
|
const rateLimitAllowed = applyCloudMcpWriteRateLimit(req, res, auth, body);
|
|
457
469
|
rateLimitMs = Date.now() - rateLimitStartedAtMs;
|
|
458
470
|
if (!rateLimitAllowed)
|
|
459
471
|
return;
|
|
460
472
|
let runtime = null;
|
|
473
|
+
let runtimeLease = null;
|
|
461
474
|
let runtimeConstructionMs = 0;
|
|
462
475
|
let transportConnectMs = 0;
|
|
463
476
|
let requestHandlingMs = 0;
|
|
@@ -466,12 +479,13 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
466
479
|
const toolTimingState = { value: null };
|
|
467
480
|
try {
|
|
468
481
|
const runtimeStartedAtMs = Date.now();
|
|
469
|
-
//
|
|
482
|
+
// Production intentionally isolates the MCP runtime per HTTP request. The runtime closes over
|
|
470
483
|
// workspace auth, AI identity, permissions, subscriptions, and mutable helper state;
|
|
471
484
|
// sharing it could leak state across tenants or callers. Keep the transport stateless
|
|
472
485
|
// too. The timing event below measures construction cost so caching is only revisited
|
|
473
|
-
// with evidence and must preserve these boundaries (including dynamic tool schemas).
|
|
474
|
-
|
|
486
|
+
// with evidence and must preserve these boundaries (including dynamic tool schemas). The optional
|
|
487
|
+
// lease seam exists only for transport conformance tests that must carry legacy bidirectional calls.
|
|
488
|
+
const runtimeOptions = {
|
|
475
489
|
projectRoot: core.getPaths().projectRoot,
|
|
476
490
|
tenantId: core.getTenantId(),
|
|
477
491
|
workspaceId: auth.workspaceId,
|
|
@@ -479,6 +493,7 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
479
493
|
serverName: 'taskforce-cloud',
|
|
480
494
|
logStartup: false,
|
|
481
495
|
runtimeMode: 'cloud',
|
|
496
|
+
toolProfile: auth.authenticatedViaToken?.toolProfile || auth.authenticatedViaOAuth?.toolProfile || 'default',
|
|
482
497
|
applicationBaseUrl: resolveCloudApplicationBaseUrl(),
|
|
483
498
|
auth: buildCloudMcpRuntimeAuth({
|
|
484
499
|
req,
|
|
@@ -506,15 +521,66 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
506
521
|
]);
|
|
507
522
|
}
|
|
508
523
|
},
|
|
509
|
-
}
|
|
524
|
+
};
|
|
525
|
+
if (modernProtocolRequest) {
|
|
526
|
+
const requestHandlingStartedAtMs = Date.now();
|
|
527
|
+
await handleModernMcpHttpRequest({
|
|
528
|
+
req,
|
|
529
|
+
res,
|
|
530
|
+
parsedBody: body,
|
|
531
|
+
factory: ({ era }) => {
|
|
532
|
+
const constructionStartedAtMs = Date.now();
|
|
533
|
+
const modernRuntime = createStatelessTaskforceMcpServer({
|
|
534
|
+
...runtimeOptions,
|
|
535
|
+
protocolEra: era,
|
|
536
|
+
}, createMcpServer);
|
|
537
|
+
runtimeConstructionMs = Date.now() - constructionStartedAtMs;
|
|
538
|
+
if (!res.headersSent) {
|
|
539
|
+
setServerTimingHeader(res, [
|
|
540
|
+
{ name: 'auth', durationMs: authMs },
|
|
541
|
+
{ name: 'body-parse', durationMs: bodyParseMs },
|
|
542
|
+
{ name: 'rate-limit', durationMs: rateLimitMs },
|
|
543
|
+
{ name: 'runtime', durationMs: runtimeConstructionMs },
|
|
544
|
+
]);
|
|
545
|
+
}
|
|
546
|
+
return modernRuntime.server;
|
|
547
|
+
},
|
|
548
|
+
onerror: (error) => {
|
|
549
|
+
console.warn('[Taskforce MCP] Modern cloud request rejected:', {
|
|
550
|
+
requestId,
|
|
551
|
+
message: error.message,
|
|
552
|
+
});
|
|
553
|
+
},
|
|
554
|
+
});
|
|
555
|
+
requestHandlingMs = Date.now() - requestHandlingStartedAtMs;
|
|
556
|
+
recordCloudMcpCredentialUsage(req, auth.authenticatedViaToken, auth.authenticatedViaOAuth);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
runtimeLease = acquireMcpRuntime
|
|
560
|
+
? await acquireMcpRuntime({ req, options: runtimeOptions })
|
|
561
|
+
: null;
|
|
562
|
+
runtime = runtimeLease?.runtime
|
|
563
|
+
|| createStatelessTaskforceMcpServer(runtimeOptions, createMcpServer);
|
|
510
564
|
runtimeConstructionMs = Date.now() - runtimeStartedAtMs;
|
|
511
|
-
const transport = new
|
|
565
|
+
const transport = runtimeLease?.transport || new NodeStreamableHTTPServerTransport({
|
|
512
566
|
sessionIdGenerator: undefined,
|
|
513
567
|
enableJsonResponse: true,
|
|
514
568
|
});
|
|
515
569
|
const transportStartedAtMs = Date.now();
|
|
516
|
-
|
|
570
|
+
if (!runtimeLease)
|
|
571
|
+
await runtime.server.connect(transport);
|
|
517
572
|
transportConnectMs = Date.now() - transportStartedAtMs;
|
|
573
|
+
// Set request-level phases before the SDK writes response headers. Tool calls replace this
|
|
574
|
+
// with the richer envelope/handler breakdown from onToolCallTiming above.
|
|
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
|
+
{ name: 'transport-connect', durationMs: transportConnectMs },
|
|
582
|
+
]);
|
|
583
|
+
}
|
|
518
584
|
if (!initializeRequest) {
|
|
519
585
|
// Stateless cloud sessions still require a valid MCP JSON-RPC request;
|
|
520
586
|
// let the SDK validate and respond rather than trying to track sessions server-side.
|
|
@@ -540,7 +606,17 @@ export function makeHandleCloudMcpRequest(core, deps) {
|
|
|
540
606
|
}
|
|
541
607
|
}
|
|
542
608
|
finally {
|
|
543
|
-
if (
|
|
609
|
+
if (runtimeLease) {
|
|
610
|
+
const cleanupStartedAtMs = Date.now();
|
|
611
|
+
try {
|
|
612
|
+
await runtimeLease.release();
|
|
613
|
+
}
|
|
614
|
+
catch (closeError) {
|
|
615
|
+
console.warn('[Taskforce MCP] Cloud test runtime lease cleanup failed:', closeError);
|
|
616
|
+
}
|
|
617
|
+
cleanupMs = Date.now() - cleanupStartedAtMs;
|
|
618
|
+
}
|
|
619
|
+
else if (runtime) {
|
|
544
620
|
const cleanupStartedAtMs = Date.now();
|
|
545
621
|
try {
|
|
546
622
|
await runtime.server.close();
|
|
@@ -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,
|
|
@@ -5,7 +5,7 @@ import { buildWorkspaceSyncV3InitiativeRepairPage, decodeWorkspaceSyncV3Initiati
|
|
|
5
5
|
import { WORKSPACE_SYNC_V3_COVERAGE_PROFILE } from '../../sync/v3/workspaceSyncV3FeedProfile.js';
|
|
6
6
|
import { isWorkspaceSyncV3InitiativeLegacyPushDisabled } from '../../sync/v3/planningActivation.js';
|
|
7
7
|
import { WORKSPACE_SYNC_V3_COMBINED_COVERAGE_PROFILE } from '../../sync/v3/workspaceSyncV3CombinedCoverage.js';
|
|
8
|
-
import { buildWorkspaceSyncV3CombinedRepairPage, decodeWorkspaceSyncV3CombinedRepairCursor, decodeWorkspaceSyncV3NestedRepairCursor, decodeWorkspaceSyncV3PlanningOrderRepairCursor, decodeWorkspaceSyncV3TaskCoverRepairCursor, decodeWorkspaceSyncV3WorkflowRepairCursor, WorkspaceSyncV3CombinedRepairSnapshotUnavailableError, } from '../../sync/v3/workspaceSyncV3CombinedRepairMaterialization.js';
|
|
8
|
+
import { buildWorkspaceSyncV3CombinedRepairPage, decodeWorkspaceSyncV3CombinedRepairCursor, decodeWorkspaceSyncV3NestedRepairCursor, decodeWorkspaceSyncV3PlanningOrderRepairCursor, decodeWorkspaceSyncV3TaskCoverRepairCursor, decodeWorkspaceSyncV3WorkflowRepairCursor, decodeWorkspaceSyncV3WorkflowTaskCoverRepairCursor, WorkspaceSyncV3CombinedRepairSnapshotUnavailableError, } from '../../sync/v3/workspaceSyncV3CombinedRepairMaterialization.js';
|
|
9
9
|
import { isWorkspaceSyncV3CombinedLegacyFenceEnabled } from '../../sync/v3/workspaceSyncV2ProjectionExclusions.js';
|
|
10
10
|
import { resolveCombinedFeedCapability } from '../../sync/v3/combinedFeedCapability.js';
|
|
11
11
|
import { resolveWorkspaceSyncV3RegisteredCoverage } from '../../sync/v3/workspaceSyncV3CoverageRegistry.js';
|
|
@@ -22,6 +22,9 @@ function json(res, status, body) {
|
|
|
22
22
|
res.end(JSON.stringify(body));
|
|
23
23
|
}
|
|
24
24
|
function decodeCombinedRepairCursorForContract(rawCursor, keyring, wire) {
|
|
25
|
+
if (wire.taskCoverProjectionRequired && wire.workflowWriterPrerequisitesRequired) {
|
|
26
|
+
return decodeWorkspaceSyncV3WorkflowTaskCoverRepairCursor(rawCursor, keyring);
|
|
27
|
+
}
|
|
25
28
|
if (wire.taskCoverProjectionRequired)
|
|
26
29
|
return decodeWorkspaceSyncV3TaskCoverRepairCursor(rawCursor, keyring);
|
|
27
30
|
if (wire.workflowWriterPrerequisitesRequired)
|
|
@@ -236,6 +239,8 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
236
239
|
cursorKeyring: keyring, cursor, pageSize: Number.isFinite(limit) ? limit : undefined,
|
|
237
240
|
nestedCoverage: requestedWire.nestedWriterPrerequisitesRequired,
|
|
238
241
|
workflowCoverage: requestedWire.workflowWriterPrerequisitesRequired,
|
|
242
|
+
workflowTaskCoverCoverage: requestedWire.workflowWriterPrerequisitesRequired
|
|
243
|
+
&& requestedWire.taskCoverProjectionRequired,
|
|
239
244
|
planningOrderCoverage: requestedWire.planningOrderWriterPrerequisitesRequired,
|
|
240
245
|
taskCoverCoverage: requestedWire.taskCoverProjectionRequired });
|
|
241
246
|
json(res, 200, attestLegacyPushBoundary({ ...page }, {
|
|
@@ -352,6 +357,8 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
352
357
|
pageSize: Number.isFinite(limit) ? limit : undefined,
|
|
353
358
|
nestedCoverage: coverage.wire.nestedWriterPrerequisitesRequired,
|
|
354
359
|
workflowCoverage: coverage.wire.workflowWriterPrerequisitesRequired,
|
|
360
|
+
workflowTaskCoverCoverage: coverage.wire.workflowWriterPrerequisitesRequired
|
|
361
|
+
&& coverage.wire.taskCoverProjectionRequired,
|
|
355
362
|
planningOrderCoverage: coverage.wire.planningOrderWriterPrerequisitesRequired,
|
|
356
363
|
taskCoverCoverage: coverage.wire.taskCoverProjectionRequired,
|
|
357
364
|
coveredLegacyWritesFenced: combinedLegacyPushDisabled })
|
|
@@ -399,6 +406,8 @@ export function registerWorkspaceSyncV3FeedRoutes(input) {
|
|
|
399
406
|
cursorKeyring: cursorKeyring, pageSize: Number.isFinite(limit) ? limit : undefined,
|
|
400
407
|
nestedCoverage: coverage.wire.nestedWriterPrerequisitesRequired,
|
|
401
408
|
workflowCoverage: coverage.wire.workflowWriterPrerequisitesRequired,
|
|
409
|
+
workflowTaskCoverCoverage: coverage.wire.workflowWriterPrerequisitesRequired
|
|
410
|
+
&& coverage.wire.taskCoverProjectionRequired,
|
|
402
411
|
planningOrderCoverage: coverage.wire.planningOrderWriterPrerequisitesRequired,
|
|
403
412
|
taskCoverCoverage: coverage.wire.taskCoverProjectionRequired,
|
|
404
413
|
coveredLegacyWritesFenced: combinedLegacyPushDisabled })
|