@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.
Files changed (321) hide show
  1. package/dist/Taskforce.module.css +290 -45
  2. package/dist/components/features/AiProfilesModule.js +3 -5
  3. package/dist/components/features/TaskSettings.js +70 -14
  4. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  5. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  6. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  7. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  8. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  9. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  10. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  11. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  12. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  13. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  14. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  15. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  16. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  17. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  18. package/dist/components/views/StandaloneLayout.js +27 -26
  19. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  20. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  21. package/dist/config/envSchema.js +48 -1
  22. package/dist/core/McpTokenService.d.ts +23 -1
  23. package/dist/core/McpTokenService.js +93 -10
  24. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  25. package/dist/core/TaskChecklistCommandService.js +83 -5
  26. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  27. package/dist/core/TaskLifecycleCommandService.js +6 -2
  28. package/dist/core/Taskforce.d.ts +32 -0
  29. package/dist/core/Taskforce.js +125 -4
  30. package/dist/core/types.d.ts +8 -0
  31. package/dist/documentReviews/commandService.d.ts +2 -1
  32. package/dist/documentReviews/commandService.js +6 -3
  33. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  34. package/dist/hooks/sync/orchestratorShared.js +2 -0
  35. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  36. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  37. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  38. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  39. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  40. package/dist/hooks/useSyncOrchestrator.js +111 -2
  41. package/dist/hooks/useTaskData.d.ts +31 -1
  42. package/dist/hooks/useTaskData.js +29 -7
  43. package/dist/hooks/useTaskMutations.d.ts +3 -1
  44. package/dist/hooks/useTaskMutations.js +46 -12
  45. package/dist/hooks/useTaskforce.d.ts +2 -0
  46. package/dist/hooks/useTaskforce.js +11 -2
  47. package/dist/mcp/clientRegistry.d.ts +2 -2
  48. package/dist/mcp/clientRegistry.js +1 -1
  49. package/dist/mcp/documentAssetRegistrar.js +9 -6
  50. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  51. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  52. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  53. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  54. package/dist/mcp/httpProtocolRouting.js +19 -0
  55. package/dist/mcp/localCliHealth.d.ts +2 -2
  56. package/dist/mcp/localCliHealth.js +2 -2
  57. package/dist/mcp/localServiceProxy.d.ts +1 -0
  58. package/dist/mcp/localServiceProxy.js +530 -68
  59. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  60. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  61. package/dist/mcp/runtime.d.ts +54 -79
  62. package/dist/mcp/runtime.js +384 -97
  63. package/dist/mcp/taskPlanningRegistrar.js +23 -4
  64. package/dist/mcp/toolProfiles.d.ts +2 -0
  65. package/dist/mcp/toolProfiles.js +10 -0
  66. package/dist/mcp/toolRegistry.d.ts +1 -0
  67. package/dist/mcp/toolRegistry.js +1 -0
  68. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  69. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  70. package/dist/migrations/taskSchemaMigrations.js +415 -0
  71. package/dist/runtime/appGates.d.ts +2 -1
  72. package/dist/runtime/appGates.js +7 -0
  73. package/dist/server/index.d.ts +3 -0
  74. package/dist/server/index.js +108 -11
  75. package/dist/server/localDatabaseIdentity.js +4 -1
  76. package/dist/server/localServiceLease.js +2 -1
  77. package/dist/server/localServiceSessions.d.ts +14 -17
  78. package/dist/server/localServiceSessions.js +308 -94
  79. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -14
  80. package/dist/server/routes/admin.d.ts +4 -0
  81. package/dist/server/routes/admin.js +112 -3
  82. package/dist/server/routes/agents.d.ts +7 -0
  83. package/dist/server/routes/agents.js +277 -24
  84. package/dist/server/routes/billing.js +5 -1
  85. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  86. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  87. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  88. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  89. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  90. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  91. package/dist/server/routes/githubReviewEvidence.js +116 -0
  92. package/dist/server/routes/localService.d.ts +15 -4
  93. package/dist/server/routes/localService.js +136 -40
  94. package/dist/server/routes/modelConnections.d.ts +24 -0
  95. package/dist/server/routes/modelConnections.js +205 -0
  96. package/dist/server/routes/shared.d.ts +19 -0
  97. package/dist/server/routes/shared.js +95 -19
  98. package/dist/server/routes/sync.js +1 -0
  99. package/dist/server/routes/syncAuxRoutes.js +5 -1
  100. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  101. package/dist/server/routes/syncPushRoutes.js +1 -0
  102. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  103. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  104. package/dist/server/routes/tasks.js +21 -2
  105. package/dist/server/routes/workflows.js +9 -1
  106. package/dist/server/routes.js +59 -0
  107. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  108. package/dist/services/codexAppServerModelGateway.js +246 -21
  109. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  110. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  111. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  112. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  113. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  114. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  115. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  116. package/dist/services/executorPhaseAApprovalService.js +609 -0
  117. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  118. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  119. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  120. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  121. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  122. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  123. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  124. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  125. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  126. package/dist/services/githubReviewEvidenceService.js +336 -0
  127. package/dist/services/modelGateway.d.ts +7 -0
  128. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  129. package/dist/services/modelProviderConnectionService.js +279 -0
  130. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  131. package/dist/services/modelProviderCredentialHome.js +271 -0
  132. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  133. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  134. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  135. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  136. package/dist/services/taskforceAgentMcpBridge.d.ts +1 -1
  137. package/dist/services/taskforceAgentMcpBridge.js +7 -24
  138. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  139. package/dist/shared/adminEdgeProxy.js +94 -0
  140. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  141. package/dist/shared/adminProxySessionCookies.js +86 -0
  142. package/dist/shared/aiProfileColors.d.ts +31 -1
  143. package/dist/shared/aiProfileColors.js +14 -6
  144. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  145. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  146. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  147. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  148. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  149. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  150. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  151. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  152. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  153. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  154. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  155. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  156. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  157. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  158. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  159. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  160. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  161. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  162. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  163. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  164. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  165. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  166. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  167. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  168. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  169. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  170. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  171. package/dist/shared/executorPhaseATiming.js +1 -0
  172. package/dist/shared/planningIdentity.js +1 -1
  173. package/dist/shared/productLogoKeys.d.ts +2 -0
  174. package/dist/shared/productLogoKeys.js +18 -0
  175. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  176. package/dist/shared/taskforceAgentDefinition.js +6 -9
  177. package/dist/shared/taskforceAgentModels.js +7 -3
  178. package/dist/shared/userFeatureGrants.d.ts +4 -0
  179. package/dist/shared/userFeatureGrants.js +7 -0
  180. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  181. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  182. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  183. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  184. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  185. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  186. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  187. package/dist/storage/modelProviderConnectionStore.js +446 -0
  188. package/dist/storage/postgresAdapter.d.ts +4 -0
  189. package/dist/storage/postgresAdapter.js +11 -0
  190. package/dist/storage/postgresWorker.js +9 -1
  191. package/dist/storage/postgresWorkerProtocol.d.ts +1 -0
  192. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  193. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  194. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  195. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  196. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  197. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  198. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  199. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  200. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  201. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  202. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  203. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  204. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  205. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  206. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  207. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  208. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  209. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  210. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  211. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  212. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  213. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  214. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  215. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  216. package/dist/sync/syncApplyHandlers.js +10 -1
  217. package/dist/sync/syncService.d.ts +15 -0
  218. package/dist/sync/syncService.js +83 -18
  219. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  220. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  221. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  222. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  223. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  224. package/dist/sync/v3/durableOperationReplay.js +18 -0
  225. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  226. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  227. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  228. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  229. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  230. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  231. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  232. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  233. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  234. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  235. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  236. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  237. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  238. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  239. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  240. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +8 -0
  241. package/dist/sync/v3/localTaskStatusOutboxService.js +219 -12
  242. package/dist/sync/v3/syncDurabilityStore.d.ts +34 -0
  243. package/dist/sync/v3/syncDurabilityStore.js +168 -2
  244. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  245. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  246. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  247. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  248. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  249. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  250. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  251. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  252. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  253. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  254. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  255. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  256. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  257. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  258. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  259. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  260. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  261. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  262. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  263. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  264. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  265. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  266. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  267. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  268. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  269. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  270. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  271. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  272. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  273. package/dist/sync/workspaceRepair.d.ts +5 -2
  274. package/dist/sync/workspaceRepair.js +161 -6
  275. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  276. package/dist/sync/workspaceSyncModel.js +35 -7
  277. package/dist/sync/workspaceSyncState.d.ts +1 -0
  278. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  279. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  280. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  281. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  282. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-BTM6nIg_.js} +1 -1
  283. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  284. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-Coa8yVGM.js} +1 -1
  285. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  286. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  287. package/dist/ui/assets/{PlanningModule-B5DWQOGz.js → PlanningModule-pRPjR7v5.js} +1 -1
  288. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-D86pZSSl.js} +1 -1
  289. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-BVIkU9yT.js} +1 -1
  290. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  291. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  292. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  293. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  294. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  295. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  296. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  297. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  298. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  299. package/dist/ui/branding/logos/signature_dark.png +0 -0
  300. package/dist/ui/branding/logos/signature_light.png +0 -0
  301. package/dist/ui/index.html +3 -3
  302. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  303. package/dist/utils/httpSetCookie.d.ts +1 -0
  304. package/dist/utils/httpSetCookie.js +4 -1
  305. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  306. package/dist/utils/localRuntimeUrl.js +14 -0
  307. package/dist/utils/productLogoRegistry.d.ts +2 -0
  308. package/dist/utils/productLogoRegistry.js +36 -0
  309. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  310. package/dist/utils/syncStatusPresentation.js +17 -0
  311. package/dist/utils/taskEvents.d.ts +2 -0
  312. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  313. package/dist/utils/workspaceSyncPresentation.js +23 -17
  314. package/package.json +22 -4
  315. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  316. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  317. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  318. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  319. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  320. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  321. 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 { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
10
- import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
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 extractMcpWriteToolNames(body) {
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 && isMcpWriteToolName(toolName) ? [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 toolName = resolveCanonicalMcpToolName(requestedToolName);
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 deniedToolName = findDeniedCloudMcpToolName(body, authScopes);
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
- // Intentionally isolate the MCP runtime per HTTP request. The runtime closes over
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
- runtime = createTaskforceMcpServer({
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 StreamableHTTPServerTransport({
565
+ const transport = runtimeLease?.transport || new NodeStreamableHTTPServerTransport({
512
566
  sessionIdGenerator: undefined,
513
567
  enableJsonResponse: true,
514
568
  });
515
569
  const transportStartedAtMs = Date.now();
516
- await runtime.server.connect(transport);
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 (runtime) {
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 })