@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
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { ExecutorPhaseAApprovalError } from '../../services/executorPhaseAApprovalService.js';
|
|
2
|
+
import { ExecutorPhaseAApprovalConflictError } from '../../storage/executorPhaseAApprovalReceiptStore.js';
|
|
3
|
+
import { EXECUTOR_PHASE_A_ISSUANCE_REQUEST_SCHEMA, EXECUTOR_PHASE_A_MAX_PREFLIGHT_BYTES } from '../../shared/executorPhaseAApprovalReceipt.js';
|
|
4
|
+
import { parseJsonBody } from './primitives.js';
|
|
5
|
+
export const EXECUTOR_PHASE_A_APPROVAL_PAGE_PATH = '/taskforce/admin/executor/phase-a-approval';
|
|
6
|
+
export const EXECUTOR_PHASE_A_APPROVAL_PAGE_SCRIPT_PATH = '/taskforce/admin/executor/phase-a-approval.js';
|
|
7
|
+
export const EXECUTOR_PHASE_A_APPROVAL_ISSUE_PATH = '/api/taskforce/admin/executor/phase-a-approval-receipts';
|
|
8
|
+
function writeJson(res, statusCode, body) {
|
|
9
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
10
|
+
res.end(JSON.stringify(body));
|
|
11
|
+
}
|
|
12
|
+
function isSameOriginJson(req, allowedOrigin) {
|
|
13
|
+
const contentType = String(req.headers['content-type'] || '').split(';')[0].trim().toLowerCase();
|
|
14
|
+
if (contentType !== 'application/json')
|
|
15
|
+
return false;
|
|
16
|
+
const origin = String(req.headers.origin || '').trim();
|
|
17
|
+
if (!origin || origin === 'null')
|
|
18
|
+
return false;
|
|
19
|
+
if (String(req.headers['sec-fetch-site'] || '').trim().toLowerCase() === 'cross-site')
|
|
20
|
+
return false;
|
|
21
|
+
try {
|
|
22
|
+
return origin === allowedOrigin && new URL(origin).origin === allowedOrigin;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function renderPage(issuePath) {
|
|
29
|
+
return `<!doctype html>
|
|
30
|
+
<html lang="en">
|
|
31
|
+
<head>
|
|
32
|
+
<meta charset="utf-8" />
|
|
33
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
34
|
+
<title>Phase A Approval</title>
|
|
35
|
+
<style>
|
|
36
|
+
body{margin:0;background:#f5f6f8;color:#17191d;font:15px system-ui,sans-serif}.bar{height:56px;background:#fff;border-bottom:1px solid #dfe2e7;display:flex;align-items:center;padding:0 24px;font-weight:700}.main{max-width:760px;margin:40px auto;padding:0 24px}.panel{background:#fff;border:1px solid #dfe2e7;border-radius:8px;padding:24px}h1{font-size:24px;margin:0 0 24px}label{display:block;font-weight:650;margin-bottom:8px}input{width:100%;box-sizing:border-box;border:1px solid #aeb4bd;padding:12px;border-radius:6px}button{margin-top:20px;background:#176b4d;color:#fff;border:0;border-radius:6px;padding:11px 16px;font-weight:700;cursor:pointer}button:disabled{opacity:.45;cursor:not-allowed}pre{white-space:pre-wrap;background:#f7f8fa;border:1px solid #e2e5e9;padding:12px;min-height:48px;max-height:280px;overflow:auto}
|
|
37
|
+
</style>
|
|
38
|
+
</head>
|
|
39
|
+
<body><div class="bar">Taskforce System Administration</div><main class="main" data-issue-path="${issuePath}" data-request-schema="${EXECUTOR_PHASE_A_ISSUANCE_REQUEST_SCHEMA}"><section class="panel">
|
|
40
|
+
<h1>Phase A Approval</h1>
|
|
41
|
+
<label for="preflight">Canonical preflight JSON</label><input id="preflight" type="file" accept="application/json,.json" />
|
|
42
|
+
<pre id="summary">No preflight selected.</pre><button id="approve" type="button" disabled>Approve and download receipt</button>
|
|
43
|
+
</section></main><script src="${EXECUTOR_PHASE_A_APPROVAL_PAGE_SCRIPT_PATH}" defer></script></body></html>`;
|
|
44
|
+
}
|
|
45
|
+
function renderPageScript() {
|
|
46
|
+
return `const root=document.querySelector('main[data-issue-path]'),file=document.getElementById('preflight'),button=document.getElementById('approve'),summary=document.getElementById('summary');let encoded='';
|
|
47
|
+
file.addEventListener('change',async()=>{button.disabled=true;encoded='';const selected=file.files[0];if(!selected)return;const bytes=new Uint8Array(await selected.arrayBuffer());let binary='';for(const value of bytes)binary+=String.fromCharCode(value);encoded=btoa(binary).replace(/\\+/g,'-').replace(/\\//g,'_').replace(/=+$/,'');try{const value=JSON.parse(new TextDecoder().decode(bytes));summary.textContent=JSON.stringify({runId:value.runId,status:value.status,failures:value.failures,authority:value.approvalContext,target:value.target,source:value.source,budgets:value.budgets,pricing:value.pricing,cleanupInventory:value.logicalEnvelope?.cleanupInventory,collectedAt:value.collectedAt,expiresAt:value.expiresAt},null,2);button.disabled=false}catch{summary.textContent='Invalid JSON.'}});
|
|
48
|
+
button.addEventListener('click',async()=>{button.disabled=true;const response=await fetch(root.dataset.issuePath,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({schema:root.dataset.requestSchema,preflightBase64Url:encoded})});if(!response.ok){let message='Approval failed.';try{message=(await response.json()).error||message}catch{}summary.textContent=message;button.disabled=false;return}const blob=await response.blob(),link=document.createElement('a');link.href=URL.createObjectURL(blob);link.download='taskforce-phase-a-approval-receipt.json';link.click();URL.revokeObjectURL(link.href);summary.textContent='Approval receipt issued.'});`;
|
|
49
|
+
}
|
|
50
|
+
export function registerExecutorPhaseAApprovalRoutes(deps) {
|
|
51
|
+
const authorize = (req, res) => {
|
|
52
|
+
if (!deps.requireCloudRuntime(res, 'Executor Phase A approvals'))
|
|
53
|
+
return null;
|
|
54
|
+
if (!deps.performanceEnvironment) {
|
|
55
|
+
writeJson(res, 404, { error: 'Executor Phase A approvals are available only in the performance environment.' });
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
if (!deps.ensureAppAccess(req, res))
|
|
59
|
+
return null;
|
|
60
|
+
const actorUserId = String(deps.resolveHumanSystemAdminActor(req) || '').trim();
|
|
61
|
+
if (!actorUserId) {
|
|
62
|
+
deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'human_system_admin_required' }, deps.workspaceId);
|
|
63
|
+
writeJson(res, 403, { error: 'Human system administrator access is required.' });
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
if (!deps.hasActiveWorkspaceMembership(deps.workspaceId, actorUserId)) {
|
|
67
|
+
deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'active_workspace_membership_required' }, deps.workspaceId);
|
|
68
|
+
writeJson(res, 403, { error: 'Active membership in the Phase A workspace is required.' });
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return actorUserId;
|
|
72
|
+
};
|
|
73
|
+
deps.addRoute('GET', EXECUTOR_PHASE_A_APPROVAL_PAGE_PATH, async (req, res) => {
|
|
74
|
+
if (!authorize(req, res))
|
|
75
|
+
return;
|
|
76
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });
|
|
77
|
+
res.end(renderPage(EXECUTOR_PHASE_A_APPROVAL_ISSUE_PATH));
|
|
78
|
+
});
|
|
79
|
+
deps.addRoute('GET', EXECUTOR_PHASE_A_APPROVAL_PAGE_SCRIPT_PATH, async (req, res) => {
|
|
80
|
+
if (!authorize(req, res))
|
|
81
|
+
return;
|
|
82
|
+
res.writeHead(200, { 'Content-Type': 'application/javascript; charset=utf-8', 'Cache-Control': 'no-store' });
|
|
83
|
+
res.end(renderPageScript());
|
|
84
|
+
});
|
|
85
|
+
deps.addRoute('POST', EXECUTOR_PHASE_A_APPROVAL_ISSUE_PATH, async (req, res) => {
|
|
86
|
+
const actorUserId = authorize(req, res);
|
|
87
|
+
if (!actorUserId)
|
|
88
|
+
return;
|
|
89
|
+
if (!isSameOriginJson(req, deps.allowedOrigin)) {
|
|
90
|
+
deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'same_origin_json_required' }, deps.workspaceId);
|
|
91
|
+
writeJson(res, 403, { error: 'Same-origin application/json submission is required.' });
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (!deps.service) {
|
|
95
|
+
deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code: 'issuer_not_configured' }, deps.workspaceId);
|
|
96
|
+
writeJson(res, 503, { error: 'Phase A approval receipt signing is not configured.' });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const body = await parseJsonBody(req, Math.ceil(EXECUTOR_PHASE_A_MAX_PREFLIGHT_BYTES * 1.4));
|
|
101
|
+
if (!body || typeof body !== 'object' || Array.isArray(body) || Object.keys(body).length !== 2
|
|
102
|
+
|| body.schema !== EXECUTOR_PHASE_A_ISSUANCE_REQUEST_SCHEMA || typeof body.preflightBase64Url !== 'string') {
|
|
103
|
+
throw new ExecutorPhaseAApprovalError('Request does not match the Phase A issuance request schema.');
|
|
104
|
+
}
|
|
105
|
+
const encoded = body.preflightBase64Url;
|
|
106
|
+
if (!/^[A-Za-z0-9_-]+$/.test(encoded)) {
|
|
107
|
+
throw new ExecutorPhaseAApprovalError('preflightBase64Url must be unpadded base64url.');
|
|
108
|
+
}
|
|
109
|
+
const preflightBytes = Buffer.from(encoded, 'base64url');
|
|
110
|
+
if (preflightBytes.toString('base64url') !== encoded) {
|
|
111
|
+
throw new ExecutorPhaseAApprovalError('preflightBase64Url is not canonical base64url.');
|
|
112
|
+
}
|
|
113
|
+
const result = deps.service.issue(preflightBytes, actorUserId);
|
|
114
|
+
deps.auditAuthAction(req, result.created ? 'executor.phase-a.approval.issued' : 'executor.phase-a.approval.retried', {
|
|
115
|
+
receiptId: result.receiptId,
|
|
116
|
+
receiptSha256: result.digest,
|
|
117
|
+
}, deps.workspaceId);
|
|
118
|
+
res.writeHead(result.created ? 201 : 200, {
|
|
119
|
+
'Content-Type': 'application/json',
|
|
120
|
+
'Content-Disposition': 'attachment; filename="taskforce-phase-a-approval-receipt.json"',
|
|
121
|
+
'Cache-Control': 'no-store',
|
|
122
|
+
'X-Taskforce-Receipt-Sha256': result.digest,
|
|
123
|
+
});
|
|
124
|
+
res.end(result.bytes);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
const statusCode = error instanceof ExecutorPhaseAApprovalError || error instanceof ExecutorPhaseAApprovalConflictError
|
|
128
|
+
? error.statusCode
|
|
129
|
+
: Number(error?.statusCode) || 500;
|
|
130
|
+
const code = error instanceof ExecutorPhaseAApprovalError || error instanceof ExecutorPhaseAApprovalConflictError
|
|
131
|
+
? error.code
|
|
132
|
+
: 'internal_error';
|
|
133
|
+
deps.auditAuthAction(req, 'executor.phase-a.approval.denied', { code }, deps.workspaceId);
|
|
134
|
+
writeJson(res, statusCode, {
|
|
135
|
+
error: statusCode >= 500 ? 'Internal server error.' : String(error?.message || 'Approval failed.'),
|
|
136
|
+
code,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { RouteHandler } from './primitives.js';
|
|
3
|
+
export interface ExecutorPhaseAIssuerRedemptionRouteDependencies {
|
|
4
|
+
addRoute: (method: string, path: string, handler: RouteHandler) => void;
|
|
5
|
+
requireCloudRuntime: (res: ServerResponse, feature: string) => boolean;
|
|
6
|
+
performanceEnvironment: boolean;
|
|
7
|
+
featureEnabled: boolean;
|
|
8
|
+
auditAuthAction: (req: IncomingMessage, action: string, details: Record<string, unknown>, workspaceIdOverride?: string | null) => void;
|
|
9
|
+
workspaceId: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function registerExecutorPhaseAIssuerRedemptionRoutes(deps: ExecutorPhaseAIssuerRedemptionRouteDependencies): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { EXECUTOR_PHASE_A_ISSUER_REDEMPTION_PATH } from '../../shared/executorPhaseAIssuerContracts.js';
|
|
2
|
+
function writeJson(res, statusCode, body) {
|
|
3
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
4
|
+
res.end(JSON.stringify(body));
|
|
5
|
+
}
|
|
6
|
+
export function registerExecutorPhaseAIssuerRedemptionRoutes(deps) {
|
|
7
|
+
deps.addRoute('POST', EXECUTOR_PHASE_A_ISSUER_REDEMPTION_PATH, async (req, res) => {
|
|
8
|
+
if (!deps.requireCloudRuntime(res, 'Executor Phase A issuer redemption'))
|
|
9
|
+
return;
|
|
10
|
+
if (!deps.performanceEnvironment || !deps.featureEnabled) {
|
|
11
|
+
writeJson(res, 404, { error: 'Not found.' });
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
// Package 1 deliberately has no integration path. Package 2 must install the
|
|
15
|
+
// independently reviewed pre-Lambda machine-authentication gate first.
|
|
16
|
+
deps.auditAuthAction(req, 'executor.phase-a.issuer-redemption.denied', {
|
|
17
|
+
code: 'broker_preintegration_authentication_not_configured',
|
|
18
|
+
}, deps.workspaceId);
|
|
19
|
+
writeJson(res, 503, {
|
|
20
|
+
error: 'Phase A broker authentication is not configured.',
|
|
21
|
+
code: 'broker_preintegration_authentication_not_configured',
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
+
import { type GitHubReviewEvidenceInstallationStore } from '../../storage/githubReviewEvidenceInstallationStore.js';
|
|
3
|
+
import type { GitHubInstallationInspection } from '../../services/githubReviewEvidenceService.js';
|
|
4
|
+
import { type RouteHandler } from './primitives.js';
|
|
5
|
+
export interface GitHubReviewEvidenceRouteDependencies {
|
|
6
|
+
addRoute: (method: string, path: string, handler: RouteHandler) => void;
|
|
7
|
+
store: GitHubReviewEvidenceInstallationStore;
|
|
8
|
+
configured: boolean;
|
|
9
|
+
inspectInstallation: (installationId: string) => Promise<GitHubInstallationInspection>;
|
|
10
|
+
requestWorkspaceId: (req: IncomingMessage) => string;
|
|
11
|
+
requestRole: (req: IncomingMessage) => string;
|
|
12
|
+
resolveAuthenticatedUserId: (req: IncomingMessage) => string;
|
|
13
|
+
ensureAppAccess: (req: IncomingMessage, res: ServerResponse) => boolean;
|
|
14
|
+
ensureWorkspaceAdminRole: (req: IncomingMessage, workspaceIdOverride?: string | null) => boolean;
|
|
15
|
+
ensureAdminRole: (req: IncomingMessage) => boolean;
|
|
16
|
+
requireCloudRuntime: (res: ServerResponse, feature: string) => boolean;
|
|
17
|
+
auditAuthAction: (req: IncomingMessage, action: string, details: Record<string, unknown>, workspaceIdOverride?: string | null) => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function registerGitHubReviewEvidenceRoutes(deps: GitHubReviewEvidenceRouteDependencies): void;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { GitHubReviewEvidenceInstallationConflictError, } from '../../storage/githubReviewEvidenceInstallationStore.js';
|
|
2
|
+
import { GitHubReviewEvidenceError } from '../../services/githubReviewEvidenceService.js';
|
|
3
|
+
import { parseJsonBody } from './primitives.js';
|
|
4
|
+
const SETTINGS_PATH = '/api/taskforce/settings/github-review-evidence/installation';
|
|
5
|
+
function writeJson(res, statusCode, body) {
|
|
6
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
7
|
+
res.end(JSON.stringify(body));
|
|
8
|
+
}
|
|
9
|
+
function publicBinding(binding) {
|
|
10
|
+
if (!binding)
|
|
11
|
+
return null;
|
|
12
|
+
return {
|
|
13
|
+
installationId: binding.installationId,
|
|
14
|
+
accountId: binding.accountId,
|
|
15
|
+
accountLogin: binding.accountLogin,
|
|
16
|
+
accountType: binding.accountType,
|
|
17
|
+
repositorySelection: binding.repositorySelection,
|
|
18
|
+
createdAt: binding.createdAt,
|
|
19
|
+
updatedAt: binding.updatedAt,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function writeProviderError(res, error) {
|
|
23
|
+
if (error instanceof GitHubReviewEvidenceError) {
|
|
24
|
+
if (error.retryAfterSeconds)
|
|
25
|
+
res.setHeader('Retry-After', String(error.retryAfterSeconds));
|
|
26
|
+
writeJson(res, error.statusCode, { error: error.message, code: error.code });
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (error instanceof GitHubReviewEvidenceInstallationConflictError) {
|
|
30
|
+
writeJson(res, error.statusCode, { error: error.message, code: error.code });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
writeJson(res, 500, { error: 'Internal server error.' });
|
|
34
|
+
}
|
|
35
|
+
export function registerGitHubReviewEvidenceRoutes(deps) {
|
|
36
|
+
const { addRoute, store, configured, inspectInstallation, requestWorkspaceId, requestRole, resolveAuthenticatedUserId, ensureAppAccess, ensureWorkspaceAdminRole, ensureAdminRole, requireCloudRuntime, auditAuthAction, } = deps;
|
|
37
|
+
const authorize = (req, res, systemAdminRequired = false) => {
|
|
38
|
+
if (!ensureAppAccess(req, res))
|
|
39
|
+
return null;
|
|
40
|
+
if (!requireCloudRuntime(res, 'GitHub review evidence'))
|
|
41
|
+
return null;
|
|
42
|
+
const workspaceId = String(requestWorkspaceId(req) || '').trim();
|
|
43
|
+
if (!workspaceId) {
|
|
44
|
+
writeJson(res, 400, { error: 'Workspace ID is required.' });
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
const actorUserId = String(resolveAuthenticatedUserId(req) || '').trim();
|
|
48
|
+
if (!actorUserId || actorUserId === 'anonymous') {
|
|
49
|
+
writeJson(res, 401, { error: 'Authentication is required.' });
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
if (systemAdminRequired ? !ensureAdminRole(req) : !ensureWorkspaceAdminRole(req, workspaceId)) {
|
|
53
|
+
writeJson(res, 403, {
|
|
54
|
+
error: systemAdminRequired
|
|
55
|
+
? 'System administrator access is required.'
|
|
56
|
+
: 'Workspace owner or admin access is required.',
|
|
57
|
+
});
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
return workspaceId;
|
|
61
|
+
};
|
|
62
|
+
addRoute('GET', SETTINGS_PATH, async (req, res) => {
|
|
63
|
+
const workspaceId = authorize(req, res);
|
|
64
|
+
if (!workspaceId)
|
|
65
|
+
return;
|
|
66
|
+
writeJson(res, 200, { configured, installation: publicBinding(store.get(workspaceId)) });
|
|
67
|
+
});
|
|
68
|
+
addRoute('PUT', SETTINGS_PATH, async (req, res) => {
|
|
69
|
+
const workspaceId = authorize(req, res, true);
|
|
70
|
+
if (!workspaceId)
|
|
71
|
+
return;
|
|
72
|
+
try {
|
|
73
|
+
const body = await parseJsonBody(req, 16 * 1024);
|
|
74
|
+
const installation = await inspectInstallation(String(body?.installationId || '').trim());
|
|
75
|
+
const actorUserId = String(resolveAuthenticatedUserId(req) || '').trim();
|
|
76
|
+
const binding = store.put({
|
|
77
|
+
workspaceId,
|
|
78
|
+
installationId: installation.installationId,
|
|
79
|
+
accountId: installation.accountId,
|
|
80
|
+
accountLogin: installation.accountLogin,
|
|
81
|
+
accountType: installation.accountType,
|
|
82
|
+
repositorySelection: installation.repositorySelection,
|
|
83
|
+
boundByUserId: actorUserId,
|
|
84
|
+
});
|
|
85
|
+
auditAuthAction(req, 'github.review-evidence.installation.bound', {
|
|
86
|
+
installationId: binding.installationId,
|
|
87
|
+
accountId: binding.accountId,
|
|
88
|
+
accountLogin: binding.accountLogin,
|
|
89
|
+
repositorySelection: binding.repositorySelection,
|
|
90
|
+
}, workspaceId);
|
|
91
|
+
writeJson(res, 200, { success: true, installation: publicBinding(binding) });
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
auditAuthAction(req, 'github.review-evidence.installation.bind-failed', {
|
|
95
|
+
code: error instanceof GitHubReviewEvidenceError || error instanceof GitHubReviewEvidenceInstallationConflictError
|
|
96
|
+
? error.code
|
|
97
|
+
: 'internal_error',
|
|
98
|
+
}, workspaceId);
|
|
99
|
+
writeProviderError(res, error);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
addRoute('DELETE', SETTINGS_PATH, async (req, res) => {
|
|
103
|
+
const workspaceId = authorize(req, res);
|
|
104
|
+
if (!workspaceId)
|
|
105
|
+
return;
|
|
106
|
+
const existing = store.get(workspaceId);
|
|
107
|
+
const removed = store.delete(workspaceId);
|
|
108
|
+
auditAuthAction(req, 'github.review-evidence.installation.unbound', {
|
|
109
|
+
installationId: existing?.installationId || null,
|
|
110
|
+
accountId: existing?.accountId || null,
|
|
111
|
+
removed,
|
|
112
|
+
actorRole: requestRole(req),
|
|
113
|
+
}, workspaceId);
|
|
114
|
+
writeJson(res, 200, { success: true, removed });
|
|
115
|
+
});
|
|
116
|
+
}
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { IncomingMessage } from 'http';
|
|
2
|
+
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
|
|
2
3
|
import type { TaskforceCore } from '../../core/Taskforce.js';
|
|
3
|
-
import {
|
|
4
|
+
import { type McpRuntimeFactory, type TaskforceMcpServerOptions } from '../../mcp/runtime.js';
|
|
4
5
|
import { type LocalServiceRouteContext, type RouteHandler } from './primitives.js';
|
|
6
|
+
export interface LocalMcpRuntimeLease {
|
|
7
|
+
runtime: ReturnType<McpRuntimeFactory>;
|
|
8
|
+
transport: NodeStreamableHTTPServerTransport;
|
|
9
|
+
release(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export type AcquireLocalMcpRuntime = (input: {
|
|
12
|
+
req: IncomingMessage;
|
|
13
|
+
options: TaskforceMcpServerOptions;
|
|
14
|
+
}) => Promise<LocalMcpRuntimeLease>;
|
|
5
15
|
interface LocalServiceRouteDependencies {
|
|
6
16
|
addRoute: (method: string, path: string, handler: RouteHandler) => void;
|
|
7
17
|
core: TaskforceCore;
|
|
8
18
|
context: LocalServiceRouteContext | undefined;
|
|
9
|
-
createMcpServer?:
|
|
10
|
-
createMcpTransport?: () =>
|
|
19
|
+
createMcpServer?: McpRuntimeFactory;
|
|
20
|
+
createMcpTransport?: () => NodeStreamableHTTPServerTransport;
|
|
21
|
+
acquireMcpRuntime?: AcquireLocalMcpRuntime;
|
|
11
22
|
}
|
|
12
23
|
export declare function registerLocalServiceRoutes(deps: LocalServiceRouteDependencies): void;
|
|
13
24
|
export {};
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { createHash, timingSafeEqual } from 'crypto';
|
|
2
|
-
import {
|
|
2
|
+
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
|
|
3
|
+
import { isJsonContentType } from '@modelcontextprotocol/server';
|
|
3
4
|
import { parseMcpClientId } from '../../mcp/clientRegistry.js';
|
|
4
|
-
import {
|
|
5
|
+
import { handleModernMcpHttpRequest, isModernMcpHttpRequest, } from '../../mcp/httpProtocolRouting.js';
|
|
6
|
+
import { createStatelessTaskforceMcpServer, createTaskforceMcpServer, } from '../../mcp/runtime.js';
|
|
5
7
|
import { MCP_TOOL_PROFILES } from '../../mcp/toolRegistry.js';
|
|
6
8
|
import { parseJsonBody } from './primitives.js';
|
|
9
|
+
import { setServerTimingHeader } from './shared.js';
|
|
7
10
|
import { LocalServiceSessionError } from '../localServiceSessions.js';
|
|
11
|
+
import { WorkspaceSyncDurabilityStore } from '../../sync/v3/syncDurabilityStore.js';
|
|
12
|
+
import { assertDurableOperationIdentity, DurableOperationReplayIdentityConflictError, } from '../../sync/v3/durableOperationReplay.js';
|
|
8
13
|
const API_BASE = '/api/taskforce/local-service/v1';
|
|
9
14
|
const ALLOWED_SCOPES = new Set(['tasks:read', 'tasks:write', 'workspace:read']);
|
|
10
15
|
const MAX_REGISTRATION_BODY_BYTES = 32 * 1024;
|
|
@@ -16,6 +21,13 @@ function writeJson(res, statusCode, body) {
|
|
|
16
21
|
function fail(res, statusCode, error, code) {
|
|
17
22
|
writeJson(res, statusCode, { error, code });
|
|
18
23
|
}
|
|
24
|
+
function failMcp(res, statusCode, message) {
|
|
25
|
+
writeJson(res, statusCode, {
|
|
26
|
+
jsonrpc: '2.0',
|
|
27
|
+
error: { code: -32000, message },
|
|
28
|
+
id: null,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
19
31
|
function isLoopback(req) {
|
|
20
32
|
const address = String(req.socket.remoteAddress || '').toLowerCase();
|
|
21
33
|
return address === '127.0.0.1' || address === '::1' || address === '::ffff:127.0.0.1';
|
|
@@ -59,7 +71,17 @@ function authenticateSession(req, res, context) {
|
|
|
59
71
|
fail(res, 401, 'A valid local service session bearer is required.', 'SESSION_AUTH_REQUIRED');
|
|
60
72
|
return null;
|
|
61
73
|
}
|
|
62
|
-
|
|
74
|
+
let session;
|
|
75
|
+
try {
|
|
76
|
+
session = context.sessions.authenticate(token);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
if (error instanceof LocalServiceSessionError) {
|
|
80
|
+
fail(res, error.statusCode, error.message, error.code);
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
63
85
|
if (!session) {
|
|
64
86
|
fail(res, 401, 'The local service session is invalid or expired.', 'SESSION_INVALID');
|
|
65
87
|
return null;
|
|
@@ -110,42 +132,60 @@ function normalizeRegistration(body, context) {
|
|
|
110
132
|
profileToken: profileToken || null,
|
|
111
133
|
};
|
|
112
134
|
}
|
|
113
|
-
function
|
|
135
|
+
function lookupDurableOperation(core, context, session, operationId, req) {
|
|
114
136
|
const url = new URL(req.url || '/', 'http://127.0.0.1');
|
|
115
137
|
const expectedMutationKind = String(url.searchParams.get('mutationKind') || '').trim() || null;
|
|
116
138
|
const expectedPayloadFingerprint = String(url.searchParams.get('payloadFingerprint') || '').trim() || null;
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
139
|
+
const row = new WorkspaceSyncDurabilityStore(core.getDatabaseAdapter()).readOutboxOperationLookup({
|
|
140
|
+
tenantId: core.getTenantId(),
|
|
141
|
+
workspaceId: session.workspaceId,
|
|
142
|
+
clientId: context.operationClientId,
|
|
143
|
+
operationId,
|
|
120
144
|
});
|
|
121
|
-
if (!binding)
|
|
122
|
-
return null;
|
|
123
|
-
const row = core.getDatabaseAdapter().prepare(`
|
|
124
|
-
SELECT status, authoritative_response_json, created_at,
|
|
125
|
-
mutation_kind, payload_fingerprint
|
|
126
|
-
FROM workspace_sync_outbox
|
|
127
|
-
WHERE tenant_id = ?
|
|
128
|
-
AND workspace_id = ?
|
|
129
|
-
AND client_id = ?
|
|
130
|
-
AND operation_id = ?
|
|
131
|
-
LIMIT 1
|
|
132
|
-
`).get(core.getTenantId(), session.workspaceId, context.operationClientId, operationId);
|
|
133
145
|
if (!row)
|
|
134
146
|
return null;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
147
|
+
try {
|
|
148
|
+
assertDurableOperationIdentity({
|
|
149
|
+
operationId: row.operationId,
|
|
150
|
+
domain: row.domain,
|
|
151
|
+
entityId: row.entityId,
|
|
152
|
+
mutationKind: row.mutationKind,
|
|
153
|
+
payloadFingerprint: row.payloadFingerprint,
|
|
154
|
+
}, {
|
|
155
|
+
operationId,
|
|
156
|
+
domain: row.domain,
|
|
157
|
+
entityId: row.entityId,
|
|
158
|
+
mutationKind: expectedMutationKind || row.mutationKind,
|
|
159
|
+
payloadFingerprint: expectedPayloadFingerprint || row.payloadFingerprint,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (!(error instanceof DurableOperationReplayIdentityConflictError))
|
|
164
|
+
throw error;
|
|
165
|
+
throw new LocalServiceSessionError('Operation identity is assigned to a different durable mutation.', 409, 'OPERATION_IDENTITY_CONFLICT');
|
|
166
|
+
}
|
|
167
|
+
const responseJson = row.authoritativeResponseJson;
|
|
138
168
|
if (responseJson && Buffer.byteLength(responseJson, 'utf8') > MAX_MCP_BODY_BYTES) {
|
|
139
169
|
throw new LocalServiceSessionError('Operation response exceeds the local service limit.', 500, 'OPERATION_RESPONSE_INVALID');
|
|
140
170
|
}
|
|
171
|
+
let response = null;
|
|
172
|
+
if (responseJson) {
|
|
173
|
+
try {
|
|
174
|
+
response = JSON.parse(responseJson);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
throw new LocalServiceSessionError('Operation response is invalid.', 500, 'OPERATION_RESPONSE_INVALID');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
141
180
|
return {
|
|
142
181
|
operationId,
|
|
143
182
|
status: row.status,
|
|
144
|
-
createdAt: row.
|
|
145
|
-
mutationKind: row.
|
|
146
|
-
payloadFingerprint:
|
|
147
|
-
|
|
148
|
-
|
|
183
|
+
createdAt: row.createdAt,
|
|
184
|
+
mutationKind: row.mutationKind,
|
|
185
|
+
payloadFingerprint: row.payloadFingerprint,
|
|
186
|
+
domain: row.domain,
|
|
187
|
+
entityId: row.entityId,
|
|
188
|
+
response,
|
|
149
189
|
};
|
|
150
190
|
}
|
|
151
191
|
function auditShutdown(core, context, input) {
|
|
@@ -255,7 +295,7 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
255
295
|
if (!session)
|
|
256
296
|
return;
|
|
257
297
|
try {
|
|
258
|
-
const operation =
|
|
298
|
+
const operation = lookupDurableOperation(deps.core, context, session, params.operationId, req);
|
|
259
299
|
if (!operation) {
|
|
260
300
|
fail(res, 404, 'Operation not found.', 'OPERATION_NOT_FOUND');
|
|
261
301
|
return;
|
|
@@ -343,21 +383,34 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
343
383
|
deps.addRoute('POST', '/mcp', async (req, res) => {
|
|
344
384
|
if (!guardLocalRequest(req, res))
|
|
345
385
|
return;
|
|
386
|
+
const authStartedAtMs = Date.now();
|
|
346
387
|
const session = authenticateSession(req, res, context);
|
|
347
388
|
if (!session)
|
|
348
389
|
return;
|
|
390
|
+
if (!isJsonContentType(header(req, 'content-type'))) {
|
|
391
|
+
failMcp(res, 415, 'Unsupported Media Type: Content-Type must be application/json');
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const authMs = Date.now() - authStartedAtMs;
|
|
349
395
|
let runtime = null;
|
|
396
|
+
let runtimeLease = null;
|
|
397
|
+
let bodyParseMs = 0;
|
|
398
|
+
let runtimeConstructionMs = 0;
|
|
399
|
+
let transportConnectMs = 0;
|
|
350
400
|
let requestStarted = false;
|
|
351
401
|
let unregisterCancellation = () => { };
|
|
352
402
|
let resolveCancellation = () => { };
|
|
353
403
|
const cancellation = new Promise((resolve) => { resolveCancellation = resolve; });
|
|
354
404
|
try {
|
|
405
|
+
const bodyParseStartedAtMs = Date.now();
|
|
355
406
|
const body = await parseJsonBody(req, MAX_MCP_BODY_BYTES);
|
|
407
|
+
bodyParseMs = Date.now() - bodyParseStartedAtMs;
|
|
408
|
+
const modernProtocolRequest = await isModernMcpHttpRequest(req, body);
|
|
356
409
|
const cancellationId = body?.method === 'notifications/cancelled'
|
|
357
410
|
&& (typeof body?.params?.requestId === 'string' || typeof body?.params?.requestId === 'number')
|
|
358
411
|
? body.params.requestId
|
|
359
412
|
: null;
|
|
360
|
-
if (cancellationId !== null) {
|
|
413
|
+
if (cancellationId !== null && !modernProtocolRequest) {
|
|
361
414
|
const correlationId = requestCorrelation(req, 'x-taskforce-mcp-cancel-correlation');
|
|
362
415
|
if (correlationId)
|
|
363
416
|
context.sessions.cancelRequest(session.id, correlationId);
|
|
@@ -377,7 +430,8 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
377
430
|
}
|
|
378
431
|
if (cancelled)
|
|
379
432
|
return;
|
|
380
|
-
|
|
433
|
+
const runtimeStartedAtMs = Date.now();
|
|
434
|
+
const runtimeOptions = {
|
|
381
435
|
projectRoot: deps.core.getPaths().projectRoot,
|
|
382
436
|
tenantId: deps.core.getTenantId(),
|
|
383
437
|
workspaceId: session.workspaceId,
|
|
@@ -386,8 +440,6 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
386
440
|
logStartup: false,
|
|
387
441
|
runtimeMode: 'local',
|
|
388
442
|
operationIdentityScope: {
|
|
389
|
-
generation: context.generation,
|
|
390
|
-
sessionId: session.id,
|
|
391
443
|
connectionInstance: session.connectionInstance,
|
|
392
444
|
},
|
|
393
445
|
toolProfile: session.toolProfile,
|
|
@@ -404,18 +456,59 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
404
456
|
userAgent: header(req, 'user-agent').trim() || null,
|
|
405
457
|
},
|
|
406
458
|
onAiProfileBound: (profileId) => context.sessions.bindAiProfile(session.id, profileId),
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
459
|
+
};
|
|
460
|
+
if (modernProtocolRequest) {
|
|
461
|
+
const handling = handleModernMcpHttpRequest({
|
|
462
|
+
req,
|
|
463
|
+
res,
|
|
464
|
+
parsedBody: body,
|
|
465
|
+
factory: ({ era }) => {
|
|
466
|
+
const constructionStartedAtMs = Date.now();
|
|
467
|
+
const modernRuntime = createStatelessTaskforceMcpServer({ ...runtimeOptions, protocolEra: era }, deps.createMcpServer || createTaskforceMcpServer);
|
|
468
|
+
runtimeConstructionMs = Date.now() - constructionStartedAtMs;
|
|
469
|
+
if (!res.headersSent) {
|
|
470
|
+
setServerTimingHeader(res, [
|
|
471
|
+
{ name: 'auth', durationMs: authMs },
|
|
472
|
+
{ name: 'body-parse', durationMs: bodyParseMs },
|
|
473
|
+
{ name: 'runtime', durationMs: runtimeConstructionMs },
|
|
474
|
+
]);
|
|
475
|
+
}
|
|
476
|
+
return modernRuntime.server;
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
await Promise.race([handling, cancellation]);
|
|
480
|
+
if (cancelled)
|
|
481
|
+
void handling.catch(() => undefined);
|
|
482
|
+
if (cancellationId !== null && res.statusCode === 202) {
|
|
483
|
+
const cancellationCorrelation = requestCorrelation(req, 'x-taskforce-mcp-cancel-correlation');
|
|
484
|
+
if (cancellationCorrelation) {
|
|
485
|
+
context.sessions.cancelRequest(session.id, cancellationCorrelation);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
runtimeLease = deps.acquireMcpRuntime
|
|
491
|
+
? await deps.acquireMcpRuntime({ req, options: runtimeOptions })
|
|
492
|
+
: null;
|
|
493
|
+
runtime = runtimeLease?.runtime
|
|
494
|
+
|| createStatelessTaskforceMcpServer(runtimeOptions, deps.createMcpServer || createTaskforceMcpServer);
|
|
495
|
+
runtimeConstructionMs = Date.now() - runtimeStartedAtMs;
|
|
496
|
+
const transport = runtimeLease?.transport || deps.createMcpTransport?.() || new NodeStreamableHTTPServerTransport({
|
|
413
497
|
sessionIdGenerator: undefined,
|
|
414
498
|
enableJsonResponse: true,
|
|
415
499
|
});
|
|
416
|
-
|
|
500
|
+
const transportStartedAtMs = Date.now();
|
|
501
|
+
if (!runtimeLease)
|
|
502
|
+
await runtime.server.connect(transport);
|
|
503
|
+
transportConnectMs = Date.now() - transportStartedAtMs;
|
|
417
504
|
if (cancelled)
|
|
418
505
|
return;
|
|
506
|
+
setServerTimingHeader(res, [
|
|
507
|
+
{ name: 'auth', durationMs: authMs },
|
|
508
|
+
{ name: 'body-parse', durationMs: bodyParseMs },
|
|
509
|
+
{ name: 'runtime', durationMs: runtimeConstructionMs },
|
|
510
|
+
{ name: 'transport-connect', durationMs: transportConnectMs },
|
|
511
|
+
]);
|
|
419
512
|
const handling = transport.handleRequest(req, res, body);
|
|
420
513
|
await Promise.race([handling, cancellation]);
|
|
421
514
|
if (cancelled)
|
|
@@ -430,7 +523,10 @@ export function registerLocalServiceRoutes(deps) {
|
|
|
430
523
|
}
|
|
431
524
|
finally {
|
|
432
525
|
unregisterCancellation();
|
|
433
|
-
|
|
526
|
+
if (runtimeLease)
|
|
527
|
+
await runtimeLease.release().catch(() => undefined);
|
|
528
|
+
else
|
|
529
|
+
await runtime?.server.close().catch(() => undefined);
|
|
434
530
|
if (requestStarted)
|
|
435
531
|
context.sessions.endRequest(session.id);
|
|
436
532
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { TaskforceCore } from '../../core/Taskforce.js';
|
|
3
|
+
import { ModelProviderConnectionService, type ModelProviderConnectionLifecycleHandlers } from '../../services/modelProviderConnectionService.js';
|
|
4
|
+
import { CodexDeviceCodeLoginManager } from '../../services/codexDeviceCodeLoginManager.js';
|
|
5
|
+
import { type RouteHandler } from './primitives.js';
|
|
6
|
+
type ConnectionService = Pick<ModelProviderConnectionService, 'create' | 'list' | 'get' | 'rename' | 'verify' | 'refresh' | 'disconnect' | 'cleanup'>;
|
|
7
|
+
type DeviceCodeLoginManager = Pick<CodexDeviceCodeLoginManager, 'start' | 'get' | 'cancel'>;
|
|
8
|
+
export interface ModelConnectionsRouteDependencies {
|
|
9
|
+
addRoute: (method: string, path: string, handler: RouteHandler) => void;
|
|
10
|
+
ensureAppAccess: (req: IncomingMessage, res: ServerResponse) => boolean;
|
|
11
|
+
resolveAuthenticatedUserId: (req: IncomingMessage) => string | null;
|
|
12
|
+
resolveRuntimeMode: (req: IncomingMessage) => 'local' | 'cloud';
|
|
13
|
+
core?: TaskforceCore;
|
|
14
|
+
service?: ConnectionService;
|
|
15
|
+
loginManager?: DeviceCodeLoginManager;
|
|
16
|
+
credentialStoragePath?: string | null;
|
|
17
|
+
lifecycleHandlers?: Array<{
|
|
18
|
+
providerKey: string;
|
|
19
|
+
authenticationType: string;
|
|
20
|
+
lifecycle: ModelProviderConnectionLifecycleHandlers;
|
|
21
|
+
}>;
|
|
22
|
+
}
|
|
23
|
+
export declare function registerModelConnectionsRoutes(deps: ModelConnectionsRouteDependencies): void;
|
|
24
|
+
export {};
|