@taskforcehq/taskforce 0.3.328 → 0.3.330

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/dist/Taskforce.module.css +523 -79
  2. package/dist/TaskforceCore.js +237 -230
  3. package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +1 -1
  4. package/dist/cli.js +34 -0
  5. package/dist/cliCloudTargetGuard.d.ts +5 -0
  6. package/dist/cliCloudTargetGuard.js +11 -0
  7. package/dist/components/features/AiProfilesModule.js +3 -5
  8. package/dist/components/features/AnnotatedAttachmentWorkspace.js +24 -8
  9. package/dist/components/features/TaskSettings.d.ts +12 -1
  10. package/dist/components/features/TaskSettings.js +217 -54
  11. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  12. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  13. package/dist/components/features/agentCapabilities/AgentCapabilitiesPrototype.d.ts +1 -1
  14. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  15. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  16. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  17. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  18. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  19. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  20. package/dist/components/features/planning/PlanningModule.js +2 -5
  21. package/dist/components/features/planning/PlanningTaskOrderList.d.ts +1 -1
  22. package/dist/components/features/planning/PlanningTaskOrderList.js +17 -6
  23. package/dist/components/features/planning/planningTaskArrangement.d.ts +1 -0
  24. package/dist/components/features/planning/planningTaskArrangement.js +5 -5
  25. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  26. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  27. package/dist/components/features/taskforceAgentEditorModel.js +5 -1
  28. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  29. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  30. package/dist/components/task/TaskCard.d.ts +5 -0
  31. package/dist/components/task/TaskCard.js +65 -10
  32. package/dist/components/task/TaskImageReviews.js +14 -5
  33. package/dist/components/task/TaskKanban.d.ts +6 -1
  34. package/dist/components/task/TaskKanban.js +152 -6
  35. package/dist/components/task/TaskList.d.ts +5 -0
  36. package/dist/components/task/TaskList.js +3 -3
  37. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  38. package/dist/components/ui/PasswordInput.d.ts +6 -0
  39. package/dist/components/ui/PasswordInput.js +11 -0
  40. package/dist/components/ui/TopNoticeLayer.js +1 -1
  41. package/dist/components/views/AppShellHeader.js +32 -11
  42. package/dist/components/views/PlanComparisonPage.js +12 -0
  43. package/dist/components/views/StandaloneLayout.js +32 -55
  44. package/dist/components/views/WidgetView.js +3 -3
  45. package/dist/components/views/panels/PlanningDrawer.js +5 -12
  46. package/dist/components/views/standalone/modals/AccountSettingsModal.js +26 -17
  47. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  48. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  49. package/dist/config/envSchema.js +60 -1
  50. package/dist/config/localServiceRuntimeContract.d.ts +13 -0
  51. package/dist/config/localServiceRuntimeContract.js +135 -0
  52. package/dist/core/AiProfileService.js +46 -8
  53. package/dist/core/DeletedTaskLifecycleService.d.ts +1 -0
  54. package/dist/core/DeletedTaskLifecycleService.js +37 -6
  55. package/dist/core/McpTokenService.d.ts +23 -1
  56. package/dist/core/McpTokenService.js +93 -10
  57. package/dist/core/TaskAttachmentLinksDurableMutationService.d.ts +3 -2
  58. package/dist/core/TaskAttachmentLinksDurableMutationService.js +33 -9
  59. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  60. package/dist/core/TaskChecklistCommandService.js +83 -5
  61. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  62. package/dist/core/TaskLifecycleCommandService.js +6 -2
  63. package/dist/core/Taskforce.d.ts +94 -2
  64. package/dist/core/Taskforce.js +760 -36
  65. package/dist/core/types.d.ts +14 -0
  66. package/dist/documentReviews/commandService.d.ts +2 -1
  67. package/dist/documentReviews/commandService.js +6 -3
  68. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  69. package/dist/hooks/sync/orchestratorShared.js +2 -0
  70. package/dist/hooks/sync/useDurableLocalOutboxDrain.d.ts +1 -1
  71. package/dist/hooks/sync/useDurableTaskCreateMutation.js +1 -1
  72. package/dist/hooks/sync/useDurableTaskMetadataMutation.d.ts +1 -0
  73. package/dist/hooks/sync/useDurableTaskMetadataMutation.js +1 -0
  74. package/dist/hooks/sync/useDurableTaskStatusMutation.d.ts +1 -0
  75. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  76. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  77. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  78. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  79. package/dist/hooks/tasks/taskHttpMutation.js +1 -0
  80. package/dist/hooks/tasks/useCloudTaskSearch.d.ts +12 -0
  81. package/dist/hooks/tasks/useCloudTaskSearch.js +71 -0
  82. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.d.ts +16 -0
  83. package/dist/hooks/tasks/useTaskDescriptionImageDraftRecovery.js +197 -0
  84. package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +16 -3
  85. package/dist/hooks/tasks/useTaskEditorNavigation.js +72 -13
  86. package/dist/hooks/tasks/useTaskFormActions.d.ts +6 -0
  87. package/dist/hooks/tasks/useTaskFormActions.js +65 -12
  88. package/dist/hooks/ui/useSettingsModel.d.ts +24 -2
  89. package/dist/hooks/ui/useSettingsModel.js +13 -2
  90. package/dist/hooks/ui/useSettingsPersistence.d.ts +12 -1
  91. package/dist/hooks/ui/useSettingsPersistence.js +74 -47
  92. package/dist/hooks/useFilterSort.d.ts +7 -3
  93. package/dist/hooks/useFilterSort.js +15 -5
  94. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  95. package/dist/hooks/useSyncOrchestrator.js +111 -2
  96. package/dist/hooks/useTaskData.d.ts +40 -1
  97. package/dist/hooks/useTaskData.js +240 -9
  98. package/dist/hooks/useTaskMutations.d.ts +12 -2
  99. package/dist/hooks/useTaskMutations.js +266 -52
  100. package/dist/hooks/useTaskforce.d.ts +39 -9
  101. package/dist/hooks/useTaskforce.js +359 -40
  102. package/dist/hooks/useUiNotice.d.ts +4 -0
  103. package/dist/hooks/useUiNotice.js +4 -0
  104. package/dist/mcp/adminWorkspaceRegistrar.js +3 -3
  105. package/dist/mcp/clientRegistry.d.ts +2 -2
  106. package/dist/mcp/clientRegistry.js +1 -1
  107. package/dist/mcp/documentAssetRegistrar.js +53 -41
  108. package/dist/mcp/documentHelpers.d.ts +1 -0
  109. package/dist/mcp/documentHelpers.js +7 -3
  110. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  111. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  112. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  113. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  114. package/dist/mcp/httpProtocolRouting.js +19 -0
  115. package/dist/mcp/localCliHealth.d.ts +2 -2
  116. package/dist/mcp/localCliHealth.js +2 -2
  117. package/dist/mcp/localServiceProxy.d.ts +1 -0
  118. package/dist/mcp/localServiceProxy.js +530 -68
  119. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  120. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  121. package/dist/mcp/runtime.d.ts +54 -79
  122. package/dist/mcp/runtime.js +556 -139
  123. package/dist/mcp/taskPlanningRegistrar.js +64 -42
  124. package/dist/mcp/toolCallCompatibility.js +38 -1
  125. package/dist/mcp/toolCatalog.d.ts +1 -0
  126. package/dist/mcp/toolProfiles.d.ts +2 -0
  127. package/dist/mcp/toolProfiles.js +10 -0
  128. package/dist/mcp/toolRegistry.d.ts +1 -0
  129. package/dist/mcp/toolRegistry.js +1 -0
  130. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  131. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  132. package/dist/migrations/taskSchemaMigrations.js +427 -0
  133. package/dist/runtime/appGateDefinitions.d.ts +30 -6
  134. package/dist/runtime/appGateDefinitions.js +6 -6
  135. package/dist/runtime/appGates.d.ts +13 -13
  136. package/dist/runtime/appGates.js +36 -13
  137. package/dist/runtime/nodeAppGates.d.ts +8 -0
  138. package/dist/runtime/nodeAppGates.js +27 -0
  139. package/dist/server/cloudCollectionRead.d.ts +1 -1
  140. package/dist/server/cloudCollectionRead.js +2 -2
  141. package/dist/server/index.d.ts +6 -0
  142. package/dist/server/index.js +123 -14
  143. package/dist/server/localDatabaseIdentity.js +4 -1
  144. package/dist/server/localServiceLease.d.ts +3 -0
  145. package/dist/server/localServiceLease.js +11 -2
  146. package/dist/server/localServiceSessions.d.ts +14 -17
  147. package/dist/server/localServiceSessions.js +308 -94
  148. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -7
  149. package/dist/server/rateLimit.d.ts +1 -0
  150. package/dist/server/rateLimit.js +4 -0
  151. package/dist/server/realtimeSyncWs.js +36 -12
  152. package/dist/server/routes/admin.d.ts +4 -0
  153. package/dist/server/routes/admin.js +113 -3
  154. package/dist/server/routes/agentRoles.js +3 -2
  155. package/dist/server/routes/agentSkills.js +3 -2
  156. package/dist/server/routes/agents.d.ts +7 -0
  157. package/dist/server/routes/agents.js +394 -39
  158. package/dist/server/routes/annotatedAttachments.js +3 -2
  159. package/dist/server/routes/auth.js +3 -1
  160. package/dist/server/routes/billing.js +5 -1
  161. package/dist/server/routes/durableTaskHttpRouters.d.ts +11 -2
  162. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  163. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  164. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  165. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  166. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  167. package/dist/server/routes/githubReviewEvidence.js +116 -0
  168. package/dist/server/routes/localService.d.ts +15 -4
  169. package/dist/server/routes/localService.js +138 -40
  170. package/dist/server/routes/modelConnections.d.ts +24 -0
  171. package/dist/server/routes/modelConnections.js +205 -0
  172. package/dist/server/routes/primitives.d.ts +2 -0
  173. package/dist/server/routes/shared.d.ts +19 -0
  174. package/dist/server/routes/shared.js +95 -19
  175. package/dist/server/routes/sync.js +1 -0
  176. package/dist/server/routes/syncAuxRoutes.js +9 -2
  177. package/dist/server/routes/syncPullApplyRoutes.js +23 -4
  178. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  179. package/dist/server/routes/syncPushRoutes.js +1 -0
  180. package/dist/server/routes/syncV3FeedRoutes.js +27 -16
  181. package/dist/server/routes/syncV3LocalCaptureRoutes.js +28 -2
  182. package/dist/server/routes/syncV3LocalFeedApplyRoutes.d.ts +1 -0
  183. package/dist/server/routes/syncV3LocalFeedApplyRoutes.js +26 -0
  184. package/dist/server/routes/syncV3OperationRoutes.js +45 -9
  185. package/dist/server/routes/tasks.js +124 -13
  186. package/dist/server/routes/workflows.js +9 -1
  187. package/dist/server/routes/workspaces.js +43 -1
  188. package/dist/server/routes.js +59 -0
  189. package/dist/server/workspaceDeletionAdmission.d.ts +23 -0
  190. package/dist/server/workspaceDeletionAdmission.js +50 -0
  191. package/dist/service/localServiceCli.js +16 -0
  192. package/dist/service/localServiceClientLifecycle.js +36 -10
  193. package/dist/services/codexAppServerModelGateway.d.ts +161 -0
  194. package/dist/services/codexAppServerModelGateway.js +663 -0
  195. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  196. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  197. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  198. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  199. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  200. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  201. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  202. package/dist/services/executorPhaseAApprovalService.js +609 -0
  203. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  204. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  205. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  206. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  207. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  208. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  209. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  210. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  211. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  212. package/dist/services/githubReviewEvidenceService.js +336 -0
  213. package/dist/services/modelGateway.d.ts +7 -0
  214. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  215. package/dist/services/modelProviderConnectionService.js +279 -0
  216. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  217. package/dist/services/modelProviderCredentialHome.js +271 -0
  218. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  219. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  220. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  221. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  222. package/dist/services/taskforceAgentMcpBridge.d.ts +8 -2
  223. package/dist/services/taskforceAgentMcpBridge.js +30 -27
  224. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  225. package/dist/shared/adminEdgeProxy.js +94 -0
  226. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  227. package/dist/shared/adminProxySessionCookies.js +86 -0
  228. package/dist/shared/aiProfileColors.d.ts +31 -1
  229. package/dist/shared/aiProfileColors.js +14 -6
  230. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  231. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  232. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  233. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  234. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  235. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  236. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  237. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  238. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  239. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  240. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  241. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  242. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  243. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  244. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  245. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  246. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  247. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  248. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  249. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  250. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  251. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  252. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  253. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  254. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  255. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  256. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  257. package/dist/shared/executorPhaseATiming.js +1 -0
  258. package/dist/shared/planningIdentity.js +1 -1
  259. package/dist/shared/productLogoKeys.d.ts +2 -0
  260. package/dist/shared/productLogoKeys.js +18 -0
  261. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  262. package/dist/shared/taskforceAgentDefinition.js +6 -3
  263. package/dist/shared/taskforceAgentModels.d.ts +1 -0
  264. package/dist/shared/taskforceAgentModels.js +36 -3
  265. package/dist/shared/userFeatureGrants.d.ts +4 -0
  266. package/dist/shared/userFeatureGrants.js +7 -0
  267. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  268. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  269. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  270. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  271. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  272. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  273. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  274. package/dist/storage/modelProviderConnectionStore.js +446 -0
  275. package/dist/storage/postgresAdapter.d.ts +24 -3
  276. package/dist/storage/postgresAdapter.js +117 -14
  277. package/dist/storage/postgresWorker.js +22 -5
  278. package/dist/storage/postgresWorkerProtocol.d.ts +30 -0
  279. package/dist/storage/postgresWorkerProtocol.js +30 -0
  280. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  281. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  282. package/dist/sync/cloudSyncApi.d.ts +4 -1
  283. package/dist/sync/cloudSyncApi.js +7 -2
  284. package/dist/sync/contentSyncState.d.ts +1 -1
  285. package/dist/sync/coordinator/localSyncExecutionPermitStore.d.ts +1 -0
  286. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +67 -30
  287. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  288. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  289. package/dist/sync/coordinator/localWorkspaceSyncRunner.js +6 -2
  290. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  291. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  292. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  293. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  294. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  295. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  296. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  297. package/dist/sync/engine/workspaceSyncEngineBrowserGatewayRemoteServices.js +20 -2
  298. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  299. package/dist/sync/engine/workspaceSyncEngineLocalServices.d.ts +4 -0
  300. package/dist/sync/engine/workspaceSyncEngineLocalServices.js +11 -0
  301. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  302. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  303. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  304. package/dist/sync/engine/workspaceSyncEngineRemoteServices.d.ts +11 -0
  305. package/dist/sync/engine/workspaceSyncEngineRemoteServices.js +2 -1
  306. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  307. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  308. package/dist/sync/engine/workspaceSyncEngineServerRemoteServices.js +31 -4
  309. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.d.ts +3 -1
  310. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +134 -43
  311. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  312. package/dist/sync/engine/workspaceSyncEngineTransfers.d.ts +1 -1
  313. package/dist/sync/engine/workspaceSyncEngineTransfers.js +11 -4
  314. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  315. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  316. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  317. package/dist/sync/syncApplyHandlers.js +10 -1
  318. package/dist/sync/syncService.d.ts +17 -0
  319. package/dist/sync/syncService.js +87 -19
  320. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  321. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  322. package/dist/sync/v3/combinedFeedCapability.js +8 -0
  323. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  324. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  325. package/dist/sync/v3/durableOperationReplay.js +18 -0
  326. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.d.ts +2 -0
  327. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +14 -1
  328. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +4 -1
  329. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +62 -15
  330. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  331. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.d.ts +1 -0
  332. package/dist/sync/v3/durableTaskHttpBulkMutationRouter.js +30 -8
  333. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +5 -3
  334. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +37 -2
  335. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  336. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  337. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  338. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  339. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  340. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  341. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.d.ts +2 -0
  342. package/dist/sync/v3/localTaskAttachmentLinksOutboxService.js +47 -7
  343. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  344. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  345. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  346. package/dist/sync/v3/localTaskCreateOutboxService.js +15 -6
  347. package/dist/sync/v3/localTaskMetadataClient.d.ts +1 -0
  348. package/dist/sync/v3/localTaskMetadataClient.js +1 -0
  349. package/dist/sync/v3/localTaskMetadataOutboxHandler.js +5 -1
  350. package/dist/sync/v3/localTaskMetadataOutboxService.d.ts +2 -0
  351. package/dist/sync/v3/localTaskMetadataOutboxService.js +7 -0
  352. package/dist/sync/v3/localTaskRestoreOutboxService.js +14 -6
  353. package/dist/sync/v3/localTaskStatusClient.d.ts +1 -0
  354. package/dist/sync/v3/localTaskStatusClient.js +6 -1
  355. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +10 -0
  356. package/dist/sync/v3/localTaskStatusOutboxService.js +272 -24
  357. package/dist/sync/v3/syncDurabilityStore.d.ts +41 -0
  358. package/dist/sync/v3/syncDurabilityStore.js +199 -13
  359. package/dist/sync/v3/taskAttachmentLinksMutationService.d.ts +6 -4
  360. package/dist/sync/v3/taskAttachmentLinksMutationService.js +19 -10
  361. package/dist/sync/v3/taskChecklistMutationService.d.ts +15 -2
  362. package/dist/sync/v3/taskChecklistMutationService.js +48 -1
  363. package/dist/sync/v3/taskCreateMutationService.d.ts +2 -2
  364. package/dist/sync/v3/taskCreateMutationService.js +7 -4
  365. package/dist/sync/v3/taskMetadataMutationService.d.ts +3 -0
  366. package/dist/sync/v3/taskMetadataMutationService.js +4 -0
  367. package/dist/sync/v3/taskRestoreMutationService.d.ts +2 -2
  368. package/dist/sync/v3/taskRestoreMutationService.js +7 -4
  369. package/dist/sync/v3/taskStatusMutationService.d.ts +31 -1
  370. package/dist/sync/v3/taskStatusMutationService.js +123 -3
  371. package/dist/sync/v3/workflowAssignmentSync.d.ts +6 -0
  372. package/dist/sync/v3/workflowAssignmentSync.js +30 -0
  373. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  374. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  375. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  376. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.d.ts +1 -1
  377. package/dist/sync/v3/workspaceSyncV2ProjectionExclusions.js +13 -3
  378. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.d.ts +11 -0
  379. package/dist/sync/v3/workspaceSyncV3AttachmentApplyObligationStore.js +27 -10
  380. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.d.ts +2 -1
  381. package/dist/sync/v3/workspaceSyncV3AttachmentAssetHydration.js +52 -10
  382. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  383. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +18 -3
  384. package/dist/sync/v3/workspaceSyncV3CombinedFeedOrchestrator.js +8 -3
  385. package/dist/sync/v3/workspaceSyncV3CombinedLocalApply.js +51 -10
  386. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +14 -0
  387. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +49 -25
  388. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +13 -4
  389. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +124 -57
  390. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +20 -0
  391. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +106 -30
  392. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +4 -1
  393. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +34 -0
  394. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +12 -0
  395. package/dist/sync/v3/workspaceSyncV3FeedProfile.d.ts +1 -1
  396. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.d.ts +1 -0
  397. package/dist/sync/v3/workspaceSyncV3LegacyBoundaryAttestation.js +23 -10
  398. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.d.ts +3 -0
  399. package/dist/sync/v3/workspaceSyncV3NestedTaskApply.js +64 -13
  400. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.d.ts +9 -0
  401. package/dist/sync/v3/workspaceSyncV3NestedTaskCodecs.js +26 -0
  402. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.d.ts +15 -5
  403. package/dist/sync/v3/workspaceSyncV3NestedTaskProjection.js +50 -14
  404. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.d.ts +2 -1
  405. package/dist/sync/v3/workspaceSyncV3NestedTaskRepairSnapshot.js +11 -3
  406. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +5 -0
  407. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +7 -0
  408. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +55 -9
  409. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  410. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  411. package/dist/sync/v3/workspaceSyncV3TaskCommentAudit.js +9 -2
  412. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.d.ts +7 -0
  413. package/dist/sync/v3/workspaceSyncV3TaskCoverCoverage.js +37 -0
  414. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.d.ts +6 -0
  415. package/dist/sync/v3/workspaceSyncV3TaskCoverWireContract.js +9 -0
  416. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  417. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  418. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  419. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  420. package/dist/sync/workspacePullFeed.js +2 -1
  421. package/dist/sync/workspaceRepair.d.ts +8 -2
  422. package/dist/sync/workspaceRepair.js +222 -6
  423. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  424. package/dist/sync/workspaceSyncModel.js +35 -7
  425. package/dist/sync/workspaceSyncState.d.ts +1 -0
  426. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  427. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  428. package/dist/types.d.ts +47 -1
  429. package/dist/types.js +6 -0
  430. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  431. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  432. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTM6nIg_.js +3 -0
  433. package/dist/ui/assets/AnnotatedAttachmentWorkspace-TzYu7pkG.css +1 -0
  434. package/dist/ui/assets/{AssetTraySortControl-Kf1pelSy.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  435. package/dist/ui/assets/{ContextAttachmentManager-B8boOs6Q.js → ContextAttachmentManager-Coa8yVGM.js} +2 -2
  436. package/dist/ui/assets/{DocumentWorkspace-DXH4XUsB.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  437. package/dist/ui/assets/{EntityActivityTimeline-BtSTq0ON.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  438. package/dist/ui/assets/PlanningModule-pRPjR7v5.js +1 -0
  439. package/dist/ui/assets/PlansPage-D86pZSSl.js +1 -0
  440. package/dist/ui/assets/TaskContextUpload-BVIkU9yT.js +1 -0
  441. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  442. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  443. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  444. package/dist/ui/assets/{WorkflowManagerModule-DWFspC-o.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  445. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  446. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  447. package/dist/ui/assets/{vendor-icons-BkFLXavV.js → vendor-icons-Bsq-mcEn.js} +1 -1
  448. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  449. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  450. package/dist/ui/branding/logos/signature_dark.png +0 -0
  451. package/dist/ui/branding/logos/signature_light.png +0 -0
  452. package/dist/ui/index.html +3 -3
  453. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  454. package/dist/utils/httpSetCookie.d.ts +1 -0
  455. package/dist/utils/httpSetCookie.js +4 -1
  456. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  457. package/dist/utils/localRuntimeUrl.js +14 -0
  458. package/dist/utils/productLogoRegistry.d.ts +2 -0
  459. package/dist/utils/productLogoRegistry.js +36 -0
  460. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  461. package/dist/utils/syncStatusPresentation.js +17 -0
  462. package/dist/utils/taskActivity.d.ts +3 -2
  463. package/dist/utils/taskActivity.js +19 -2
  464. package/dist/utils/taskEditorReconciliation.d.ts +40 -0
  465. package/dist/utils/taskEditorReconciliation.js +217 -0
  466. package/dist/utils/taskEvents.d.ts +2 -0
  467. package/dist/utils/taskNormalization.d.ts +1 -0
  468. package/dist/utils/taskNormalization.js +39 -0
  469. package/dist/utils/taskSearch.js +2 -2
  470. package/dist/utils/uiNotice.d.ts +4 -0
  471. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  472. package/dist/utils/workspaceSyncPresentation.js +23 -17
  473. package/package.json +36 -6
  474. package/dist/ui/assets/AiIdentityRosterCard-MZs7lVED.js +0 -1
  475. package/dist/ui/assets/AiProfilesModule-C3i0LOxe.js +0 -1
  476. package/dist/ui/assets/AnnotatedAttachmentWorkspace-CBRZ8rca.css +0 -1
  477. package/dist/ui/assets/AnnotatedAttachmentWorkspace-DVZk5Tln.js +0 -3
  478. package/dist/ui/assets/PlanningModule-BPVyEa-f.js +0 -1
  479. package/dist/ui/assets/PlansPage-ChqgxALc.js +0 -1
  480. package/dist/ui/assets/TaskContextUpload-CB3ol0sN.js +0 -1
  481. package/dist/ui/assets/TaskSettings-g4ECKNOz.js +0 -12
  482. package/dist/ui/assets/TaskforceAgentsModule-BazdUwxZ.js +0 -21
  483. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  484. package/dist/ui/assets/index-BUplSsv_.js +0 -7
  485. package/dist/ui/assets/index-gz2EXuoK.css +0 -1
@@ -1,17 +1,65 @@
1
1
  import { randomUUID } from 'crypto';
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
- import { JSONRPCMessageSchema, } from '@modelcontextprotocol/sdk/types.js';
2
+ import { JSONRPCMessageSchema } from '@modelcontextprotocol/core';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';
4
4
  import { normalizeMcpConnectionId, parseMcpClientId } from './clientRegistry.js';
5
5
  import { normalizeMcpToolProfile } from './toolProfiles.js';
6
+ import { MCP_TOOL_REGISTRY, MCP_WRITE_TOOL_NAMES } from './toolRegistry.js';
6
7
  import { localServiceCloudTargetsEqual, parseLocalServiceCloudTarget, } from '../config/localServiceCloudTarget.js';
7
8
  import { discoverOrStartLocalService, LOCAL_SERVICE_API_BASE_PATH, LOCAL_SERVICE_PROTOCOL_VERSION, } from '../service/localServiceClientLifecycle.js';
8
9
  const REQUEST_TIMEOUT_MS = 120_000;
9
10
  const MAX_IN_FLIGHT = 32;
11
+ const RECOVERY_FAILURE_COOLDOWN_MS = 250;
12
+ const RECOVERY_TRANSITION_ATTEMPTS = 150;
13
+ const RECOVERY_TRANSITION_POLL_MS = 100;
14
+ const RECOVERY_TRANSITION_TIMEOUT_MS = 15_000;
10
15
  const MCP_PROTOCOL_ERROR = -32_000;
11
16
  const MCP_REQUEST_CANCELLED = -32_800;
17
+ const KNOWN_READ_METHODS = new Set([
18
+ 'initialize',
19
+ 'ping',
20
+ 'server/discover',
21
+ 'tools/list',
22
+ 'resources/list',
23
+ 'resources/templates/list',
24
+ 'resources/read',
25
+ 'prompts/list',
26
+ 'prompts/get',
27
+ 'completion/complete',
28
+ ]);
29
+ const RECOVERABLE_CONNECTION_CODES = new Set([
30
+ 'GENERATION_MISMATCH',
31
+ 'RUNTIME_CONTRACT_MISMATCH',
32
+ 'SESSION_INVALID',
33
+ 'SESSION_NOT_FOUND',
34
+ 'SESSION_AUTH_REQUIRED',
35
+ 'SERVICE_QUIESCING',
36
+ ]);
12
37
  function timeoutSignal(timeoutMs = REQUEST_TIMEOUT_MS) {
13
38
  return AbortSignal.timeout(timeoutMs);
14
39
  }
40
+ function waitWithinRecoveryDeadline(operation, signal, deadlineAt) {
41
+ const remainingMs = deadlineAt - Date.now();
42
+ if (signal.aborted)
43
+ return Promise.reject(new Error('Taskforce MCP proxy recovery was stopped.'));
44
+ if (remainingMs <= 0)
45
+ return Promise.reject(new Error('Taskforce shared local service recovery timed out.'));
46
+ return new Promise((resolve, reject) => {
47
+ let settled = false;
48
+ const finish = (callback) => {
49
+ if (settled)
50
+ return;
51
+ settled = true;
52
+ clearTimeout(timer);
53
+ signal.removeEventListener('abort', onAbort);
54
+ callback();
55
+ };
56
+ const onAbort = () => finish(() => reject(new Error('Taskforce MCP proxy recovery was stopped.')));
57
+ const timer = setTimeout(() => finish(() => reject(new Error('Taskforce shared local service recovery timed out.'))), remainingMs);
58
+ timer.unref?.();
59
+ signal.addEventListener('abort', onAbort, { once: true });
60
+ operation.then((value) => finish(() => resolve(value)), (error) => finish(() => reject(error)));
61
+ });
62
+ }
15
63
  async function readJson(response, label) {
16
64
  const text = await response.text();
17
65
  if (!response.ok) {
@@ -24,6 +72,117 @@ async function readJson(response, label) {
24
72
  throw new Error(`${label} returned invalid JSON.`);
25
73
  }
26
74
  }
75
+ function encodeMcpHeaderValue(value) {
76
+ const safeAscii = value.length > 0
77
+ && value === value.trim()
78
+ && !(value.startsWith('=?base64?') && value.endsWith('?='))
79
+ && [...value].every((character) => {
80
+ const codePoint = character.codePointAt(0) || 0;
81
+ return codePoint === 9 || (codePoint >= 32 && codePoint <= 126);
82
+ });
83
+ return safeAscii
84
+ ? value
85
+ : `=?base64?${Buffer.from(value, 'utf8').toString('base64')}?=`;
86
+ }
87
+ function modernRequestHeaders(message) {
88
+ if (!('method' in message) || !('id' in message))
89
+ return {};
90
+ const params = message.params;
91
+ const meta = params?._meta;
92
+ const version = meta?.['io.modelcontextprotocol/protocolVersion'];
93
+ if (typeof version !== 'string')
94
+ return {};
95
+ const name = message.method === 'resources/read'
96
+ ? params?.uri
97
+ : params?.name;
98
+ return {
99
+ 'mcp-protocol-version': version,
100
+ 'mcp-method': message.method,
101
+ ...(typeof name === 'string' ? { 'mcp-name': encodeMcpHeaderValue(name) } : {}),
102
+ };
103
+ }
104
+ function parseMcpRelayMessage(value) {
105
+ return JSONRPCMessageSchema.parse(value);
106
+ }
107
+ function parseSseFrame(frame) {
108
+ const data = frame
109
+ .split(/\r?\n/)
110
+ .filter((line) => line.startsWith('data:'))
111
+ .map((line) => line.slice(5).trimStart())
112
+ .join('\n');
113
+ return data ? parseMcpRelayMessage(JSON.parse(data)) : null;
114
+ }
115
+ async function* readMcpRelayMessages(response) {
116
+ const contentType = String(response.headers.get('content-type') || '').toLowerCase();
117
+ if (!contentType.includes('text/event-stream')) {
118
+ const text = await response.text();
119
+ let values;
120
+ try {
121
+ const body = JSON.parse(text);
122
+ values = Array.isArray(body) ? body : [body];
123
+ }
124
+ catch {
125
+ if (!response.ok)
126
+ throw new Error(`MCP relay failed (${response.status}): ${text.slice(0, 500)}`);
127
+ throw new Error('MCP relay returned an invalid JSON-RPC response.');
128
+ }
129
+ if (values.length === 0)
130
+ throw new Error(`MCP relay returned no JSON-RPC messages (${response.status}).`);
131
+ for (const value of values)
132
+ yield parseMcpRelayMessage(value);
133
+ return;
134
+ }
135
+ if (!response.body)
136
+ throw new Error(`MCP relay returned no JSON-RPC messages (${response.status}).`);
137
+ const reader = response.body.getReader();
138
+ const decoder = new TextDecoder();
139
+ let buffer = '';
140
+ let sample = '';
141
+ let count = 0;
142
+ try {
143
+ while (true) {
144
+ const { value, done } = await reader.read();
145
+ if (value) {
146
+ const decoded = decoder.decode(value, { stream: true });
147
+ buffer += decoded;
148
+ if (sample.length < 500)
149
+ sample += decoded.slice(0, 500 - sample.length);
150
+ }
151
+ if (done)
152
+ buffer += decoder.decode();
153
+ let boundary = buffer.match(/\r?\n\r?\n/);
154
+ while (boundary?.index !== undefined) {
155
+ const frame = buffer.slice(0, boundary.index);
156
+ buffer = buffer.slice(boundary.index + boundary[0].length);
157
+ const message = parseSseFrame(frame);
158
+ if (message) {
159
+ count += 1;
160
+ yield message;
161
+ }
162
+ boundary = buffer.match(/\r?\n\r?\n/);
163
+ }
164
+ if (done)
165
+ break;
166
+ }
167
+ const finalMessage = parseSseFrame(buffer);
168
+ if (finalMessage) {
169
+ count += 1;
170
+ yield finalMessage;
171
+ }
172
+ }
173
+ catch {
174
+ if (!response.ok)
175
+ throw new Error(`MCP relay failed (${response.status}): ${sample.slice(0, 500)}`);
176
+ throw new Error('MCP relay returned an invalid JSON-RPC response.');
177
+ }
178
+ finally {
179
+ await reader.cancel().catch(() => undefined);
180
+ reader.releaseLock();
181
+ }
182
+ if (count === 0) {
183
+ throw new Error(`MCP relay returned no JSON-RPC messages (${response.status}).`);
184
+ }
185
+ }
27
186
  function validateReadiness(readiness, descriptor) {
28
187
  const readinessCloudTarget = parseLocalServiceCloudTarget(readiness.cloudTarget);
29
188
  if (!readiness.ready)
@@ -52,13 +211,96 @@ function cancellationTarget(message) {
52
211
  function idKey(id) {
53
212
  return `${typeof id}:${String(id)}`;
54
213
  }
55
- function errorResponse(id, message, code, numericCode = MCP_PROTOCOL_ERROR) {
214
+ function errorResponse(id, message, code, numericCode = MCP_PROTOCOL_ERROR, data = {}) {
56
215
  return {
57
216
  jsonrpc: '2.0',
58
217
  id,
59
- error: { code: numericCode, message, data: { code } },
218
+ error: { code: numericCode, message, data: { code, ...data } },
60
219
  };
61
220
  }
221
+ function toolName(message) {
222
+ if (!('method' in message) || message.method !== 'tools/call')
223
+ return null;
224
+ const name = message.params?.name;
225
+ return typeof name === 'string' ? name : null;
226
+ }
227
+ function isKnownReadRequest(message) {
228
+ if (!('id' in message) || !('method' in message))
229
+ return false;
230
+ if (message.method === 'tools/call') {
231
+ const name = toolName(message);
232
+ return Boolean(name
233
+ && Object.prototype.hasOwnProperty.call(MCP_TOOL_REGISTRY, name)
234
+ && !MCP_WRITE_TOOL_NAMES.has(name));
235
+ }
236
+ return KNOWN_READ_METHODS.has(message.method);
237
+ }
238
+ function idempotencyKey(message) {
239
+ if (!('method' in message) || message.method !== 'tools/call')
240
+ return null;
241
+ const args = message.params?.arguments;
242
+ const value = args?.idempotencyKey ?? args?.operationKey;
243
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
244
+ }
245
+ function requestProfileToken(message) {
246
+ if (!('method' in message) || message.method !== 'tools/call')
247
+ return null;
248
+ const args = message.params?.arguments;
249
+ const value = args?.profileToken;
250
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
251
+ }
252
+ function responseProfileToken(message) {
253
+ if (!('result' in message) || !message.result || typeof message.result !== 'object')
254
+ return null;
255
+ const result = message.result;
256
+ if (result.isError === true)
257
+ return null;
258
+ const structuredToken = result.structuredContent?.profileToken;
259
+ if (typeof structuredToken === 'string' && structuredToken.trim())
260
+ return structuredToken.trim();
261
+ for (const item of result.content || []) {
262
+ if (item?.type !== 'text' || typeof item.text !== 'string')
263
+ continue;
264
+ try {
265
+ const parsed = JSON.parse(item.text);
266
+ if (typeof parsed?.profileToken === 'string' && parsed.profileToken.trim()) {
267
+ return parsed.profileToken.trim();
268
+ }
269
+ }
270
+ catch {
271
+ // Tool text is not generally JSON. Only resolve_profile's structured text is relevant here.
272
+ }
273
+ }
274
+ return null;
275
+ }
276
+ function isSuccessfulToolResponse(message) {
277
+ if (!('result' in message) || !message.result || typeof message.result !== 'object')
278
+ return false;
279
+ return message.result.isError !== true;
280
+ }
281
+ function descriptorsIdentifySameService(left, right) {
282
+ return left.generation === right.generation
283
+ && left.endpoint === right.endpoint
284
+ && left.protocolVersion === right.protocolVersion;
285
+ }
286
+ function isModernRequest(message) {
287
+ if (!('method' in message))
288
+ return false;
289
+ const meta = message.params?._meta;
290
+ return meta?.['io.modelcontextprotocol/protocolVersion'] === '2026-07-28';
291
+ }
292
+ async function recoverableResponseCode(response) {
293
+ if (![401, 409, 503].includes(response.status))
294
+ return null;
295
+ try {
296
+ const body = await response.clone().json();
297
+ const code = typeof body?.code === 'string' ? body.code : '';
298
+ return RECOVERABLE_CONNECTION_CODES.has(code) ? code : null;
299
+ }
300
+ catch {
301
+ return null;
302
+ }
303
+ }
62
304
  export async function startLocalServiceMcpProxy(options) {
63
305
  const env = options.env || process.env;
64
306
  const configuredSharedService = String(env.TASKFORCE_SHARED_LOCAL_MCP_ENABLED || '').trim();
@@ -91,51 +333,164 @@ export async function startLocalServiceMcpProxy(options) {
91
333
  if (!Number.isFinite(requestTimeoutMs) || requestTimeoutMs < 1)
92
334
  throw new Error('Local MCP proxy requestTimeoutMs must be positive.');
93
335
  const fetchFn = options.fetch || fetch;
94
- const descriptor = await (options.discover || discoverOrStartLocalService)({
336
+ const discover = options.discover || discoverOrStartLocalService;
337
+ const sleep = options.sleep || ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
338
+ let privateProfileToken = String(env.TASKFORCE_AI_PROFILE_TOKEN || '').trim() || undefined;
339
+ const discoverDescriptor = () => discover({
95
340
  projectRoot: options.projectRoot,
96
341
  env,
97
342
  executablePath: options.executablePath,
98
343
  cliEntryPath: options.cliEntryPath,
99
344
  execArgv: options.execArgv,
100
345
  });
101
- const readiness = await readJson(await fetchFn(`${descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/readiness`, { signal: timeoutSignal() }), 'Local service readiness');
102
- validateReadiness(readiness, descriptor);
103
- const registration = await readJson(await fetchFn(`${descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/sessions`, {
104
- method: 'POST',
105
- headers: {
106
- 'content-type': 'application/json',
107
- 'x-taskforce-local-service-capability': descriptor.bootstrapCapability,
108
- },
109
- body: JSON.stringify({
110
- clientId,
111
- connectionInstance,
112
- workspaceId,
113
- permissions: ['tasks:read', 'tasks:write', 'workspace:read'],
114
- toolProfile,
115
- protocolVersion: descriptor.protocolVersion,
116
- generation: descriptor.generation,
117
- profileToken: String(env.TASKFORCE_AI_PROFILE_TOKEN || '').trim() || undefined,
118
- }),
119
- signal: timeoutSignal(),
120
- }), 'Local service session registration');
121
- if (!registration.session?.id || !registration.bearerToken) {
122
- throw new Error('Local service session registration returned an invalid response.');
123
- }
346
+ const registerConnection = async (descriptor, recoverySignal) => {
347
+ const registrationSignal = recoverySignal
348
+ ? AbortSignal.any([recoverySignal, timeoutSignal()])
349
+ : timeoutSignal();
350
+ const readiness = await readJson(await fetchFn(`${descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/readiness`, { signal: registrationSignal }), 'Local service readiness');
351
+ validateReadiness(readiness, descriptor);
352
+ const registration = await readJson(await fetchFn(`${descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/sessions`, {
353
+ method: 'POST',
354
+ headers: {
355
+ 'content-type': 'application/json',
356
+ 'x-taskforce-local-service-capability': descriptor.bootstrapCapability,
357
+ },
358
+ body: JSON.stringify({
359
+ clientId,
360
+ connectionInstance,
361
+ workspaceId,
362
+ permissions: ['tasks:read', 'tasks:write', 'workspace:read'],
363
+ toolProfile,
364
+ protocolVersion: descriptor.protocolVersion,
365
+ generation: descriptor.generation,
366
+ profileToken: privateProfileToken,
367
+ }),
368
+ signal: registrationSignal,
369
+ }), 'Local service session registration');
370
+ if (!registration.session?.id || !registration.bearerToken) {
371
+ throw new Error('Local service session registration returned an invalid response.');
372
+ }
373
+ return { descriptor, registration };
374
+ };
375
+ const establishConnection = async () => (registerConnection(await discoverDescriptor()));
376
+ let connection = await establishConnection();
377
+ let terminal = false;
378
+ let recoveryState = null;
379
+ let lastRecoveryFailure = null;
380
+ let closing = false;
381
+ const recoveryIntentFor = (recoveryCode) => {
382
+ if (recoveryCode === null)
383
+ return 'probe';
384
+ if (recoveryCode === 'SESSION_INVALID' || recoveryCode === 'SESSION_NOT_FOUND') {
385
+ return 'register-current';
386
+ }
387
+ return 'replacement';
388
+ };
389
+ const raiseRecoveryIntent = (current, requested) => {
390
+ const priority = { probe: 0, 'register-current': 1, replacement: 2 };
391
+ return priority[requested] > priority[current] ? requested : current;
392
+ };
393
+ const recoverConnection = (failedConnection, recoveryCode) => {
394
+ if (closing || terminal)
395
+ return Promise.reject(new Error('Taskforce MCP proxy is closed.'));
396
+ if (connection !== failedConnection)
397
+ return Promise.resolve(connection);
398
+ const requestedIntent = recoveryIntentFor(recoveryCode);
399
+ if (recoveryState) {
400
+ recoveryState.intent = raiseRecoveryIntent(recoveryState.intent, requestedIntent);
401
+ return recoveryState.promise.then((replacement) => {
402
+ if (requestedIntent !== 'probe'
403
+ && descriptorsIdentifySameService(replacement.descriptor, failedConnection.descriptor)) {
404
+ return recoverConnection(failedConnection, recoveryCode);
405
+ }
406
+ return replacement;
407
+ });
408
+ }
409
+ if (lastRecoveryFailure?.connection === failedConnection
410
+ && Date.now() - lastRecoveryFailure.at < RECOVERY_FAILURE_COOLDOWN_MS) {
411
+ return Promise.reject(lastRecoveryFailure.error);
412
+ }
413
+ const state = {
414
+ controller: new AbortController(),
415
+ intent: requestedIntent,
416
+ promise: Promise.resolve(failedConnection),
417
+ };
418
+ recoveryState = state;
419
+ const deadlineAt = Date.now() + Math.min(requestTimeoutMs, RECOVERY_TRANSITION_TIMEOUT_MS);
420
+ const recoveryDeadlineTimer = setTimeout(() => state.controller.abort(), Math.max(1, deadlineAt - Date.now()));
421
+ recoveryDeadlineTimer.unref?.();
422
+ state.promise = (async () => {
423
+ let lastError = null;
424
+ for (let attempt = 0; attempt < RECOVERY_TRANSITION_ATTEMPTS; attempt += 1) {
425
+ if (closing || terminal || state.controller.signal.aborted) {
426
+ throw new Error('Taskforce MCP proxy is closed.');
427
+ }
428
+ let candidate;
429
+ try {
430
+ candidate = await waitWithinRecoveryDeadline(discoverDescriptor(), state.controller.signal, deadlineAt);
431
+ }
432
+ catch (error) {
433
+ lastError = error instanceof Error ? error : new Error(String(error));
434
+ if (Date.now() >= deadlineAt || state.controller.signal.aborted)
435
+ throw lastError;
436
+ if (attempt + 1 < RECOVERY_TRANSITION_ATTEMPTS) {
437
+ await waitWithinRecoveryDeadline(sleep(RECOVERY_TRANSITION_POLL_MS), state.controller.signal, deadlineAt);
438
+ }
439
+ continue;
440
+ }
441
+ if (!descriptorsIdentifySameService(candidate, failedConnection.descriptor)) {
442
+ return await waitWithinRecoveryDeadline(registerConnection(candidate, state.controller.signal), state.controller.signal, deadlineAt);
443
+ }
444
+ if (state.intent === 'probe')
445
+ return failedConnection;
446
+ if (state.intent === 'register-current') {
447
+ return await waitWithinRecoveryDeadline(registerConnection(candidate, state.controller.signal), state.controller.signal, deadlineAt);
448
+ }
449
+ if (attempt + 1 < RECOVERY_TRANSITION_ATTEMPTS) {
450
+ await waitWithinRecoveryDeadline(sleep(RECOVERY_TRANSITION_POLL_MS), state.controller.signal, deadlineAt);
451
+ }
452
+ }
453
+ throw lastError || new Error('Taskforce shared local service replacement did not become ready.');
454
+ })()
455
+ .then((replacement) => {
456
+ connection = replacement;
457
+ lastRecoveryFailure = null;
458
+ return replacement;
459
+ })
460
+ .catch((error) => {
461
+ const normalized = error instanceof Error ? error : new Error(String(error));
462
+ lastRecoveryFailure = { connection: failedConnection, error: normalized, at: Date.now() };
463
+ throw normalized;
464
+ })
465
+ .finally(() => {
466
+ clearTimeout(recoveryDeadlineTimer);
467
+ if (recoveryState === state)
468
+ recoveryState = null;
469
+ });
470
+ return state.promise;
471
+ };
124
472
  const stdio = new StdioServerTransport(options.stdin, options.stdout);
125
473
  const requests = new Map();
126
474
  const inFlight = new Set();
127
475
  let protocolVersion = null;
128
476
  let initializeRequestId = null;
129
- let terminal = false;
130
477
  let closePromise = null;
131
478
  let sendChain = Promise.resolve();
132
479
  const send = (message) => {
133
480
  sendChain = sendChain.then(() => stdio.send(message));
134
481
  return sendChain;
135
482
  };
483
+ const revokeConnection = async (target) => {
484
+ await fetchFn(`${target.descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/sessions/${encodeURIComponent(target.registration.session.id)}`, {
485
+ method: 'DELETE',
486
+ headers: { authorization: `Bearer ${target.registration.bearerToken}` },
487
+ signal: timeoutSignal(2_000),
488
+ }).then((response) => response.body?.cancel()).catch(() => undefined);
489
+ };
136
490
  const failTerminal = async (error, id) => {
137
491
  if (terminal)
138
492
  return;
493
+ const pendingRecovery = recoveryState?.promise || null;
139
494
  terminal = true;
140
495
  for (const pending of inFlight)
141
496
  pending.controller.abort();
@@ -145,8 +500,58 @@ export async function startLocalServiceMcpProxy(options) {
145
500
  else {
146
501
  (options.logError || console.error)(`[Taskforce MCP proxy] ${error.message}`);
147
502
  }
503
+ await pendingRecovery?.catch(() => undefined);
504
+ await revokeConnection(connection);
148
505
  options.onFatal?.(error);
149
506
  };
507
+ const relayOnce = async (message, target, state, cancelCorrelation) => {
508
+ const response = await fetchFn(`${target.descriptor.endpoint}/mcp`, {
509
+ method: 'POST',
510
+ headers: {
511
+ authorization: `Bearer ${target.registration.bearerToken}`,
512
+ 'content-type': 'application/json',
513
+ accept: 'application/json, text/event-stream',
514
+ ...(protocolVersion ? { 'mcp-protocol-version': protocolVersion } : {}),
515
+ ...modernRequestHeaders(message),
516
+ 'x-taskforce-mcp-request-correlation': state.correlationId,
517
+ ...(cancelCorrelation ? { 'x-taskforce-mcp-cancel-correlation': cancelCorrelation } : {}),
518
+ },
519
+ body: JSON.stringify(message),
520
+ signal: state.controller.signal,
521
+ });
522
+ const recoveryCode = await recoverableResponseCode(response);
523
+ if (recoveryCode) {
524
+ await response.body?.cancel();
525
+ return recoveryCode;
526
+ }
527
+ if (response.status === 202) {
528
+ await response.body?.cancel();
529
+ return null;
530
+ }
531
+ for await (const responseMessage of readMcpRelayMessages(response)) {
532
+ if (initializeRequestId !== null
533
+ && requestId(responseMessage) === initializeRequestId
534
+ && 'result' in responseMessage
535
+ && typeof responseMessage.result?.protocolVersion === 'string') {
536
+ protocolVersion = responseMessage.result.protocolVersion;
537
+ }
538
+ if (requestId(responseMessage) === requestId(message)) {
539
+ state.responseDelivered = true;
540
+ if (isSuccessfulToolResponse(responseMessage)) {
541
+ const suppliedProfileToken = requestProfileToken(message);
542
+ if (toolName(message) === 'resolve_profile') {
543
+ privateProfileToken = responseProfileToken(responseMessage)
544
+ || suppliedProfileToken
545
+ || privateProfileToken;
546
+ }
547
+ else if (suppliedProfileToken)
548
+ privateProfileToken = suppliedProfileToken;
549
+ }
550
+ }
551
+ await send(responseMessage);
552
+ }
553
+ return null;
554
+ };
150
555
  const forward = async (message) => {
151
556
  const id = requestId(message);
152
557
  if (terminal) {
@@ -173,7 +578,7 @@ export async function startLocalServiceMcpProxy(options) {
173
578
  }
174
579
  const controller = new AbortController();
175
580
  const key = id === null ? null : idKey(id);
176
- const state = { controller, cancelled: false, correlationId: randomUUID() };
581
+ const state = { controller, cancelled: false, correlationId: randomUUID(), responseDelivered: false };
177
582
  const requestTimer = setTimeout(() => controller.abort(), requestTimeoutMs);
178
583
  requestTimer.unref?.();
179
584
  inFlight.add(state);
@@ -181,41 +586,94 @@ export async function startLocalServiceMcpProxy(options) {
181
586
  requests.set(key, state);
182
587
  if ('method' in message && message.method === 'initialize' && id !== null)
183
588
  initializeRequestId = id;
589
+ let attemptedConnection = connection;
590
+ let retried = false;
591
+ let definitivelyRejected = false;
184
592
  try {
185
- const response = await fetchFn(`${descriptor.endpoint}/mcp`, {
186
- method: 'POST',
187
- headers: {
188
- authorization: `Bearer ${registration.bearerToken}`,
189
- 'content-type': 'application/json',
190
- accept: 'application/json, text/event-stream',
191
- ...(protocolVersion ? { 'mcp-protocol-version': protocolVersion } : {}),
192
- 'x-taskforce-mcp-request-correlation': state.correlationId,
193
- ...(cancelCorrelation ? { 'x-taskforce-mcp-cancel-correlation': cancelCorrelation } : {}),
194
- },
195
- body: JSON.stringify(message),
196
- signal: controller.signal,
197
- });
198
- if (response.status === 202) {
199
- await response.body?.cancel();
200
- return;
201
- }
202
- const body = await readJson(response, 'MCP relay');
203
- const messages = (Array.isArray(body) ? body : [body]).map((value) => JSONRPCMessageSchema.parse(value));
204
- for (const responseMessage of messages) {
205
- if (initializeRequestId !== null
206
- && requestId(responseMessage) === initializeRequestId
207
- && 'result' in responseMessage
208
- && typeof responseMessage.result?.protocolVersion === 'string') {
209
- protocolVersion = responseMessage.result.protocolVersion;
593
+ const recoveryCode = await relayOnce(message, attemptedConnection, state, cancelCorrelation);
594
+ if (recoveryCode) {
595
+ definitivelyRejected = true;
596
+ attemptedConnection = await recoverConnection(attemptedConnection, recoveryCode);
597
+ retried = true;
598
+ const repeatedRecoveryCode = await relayOnce(message, attemptedConnection, state, cancelCorrelation);
599
+ if (repeatedRecoveryCode) {
600
+ throw new Error(`Replacement local service rejected the credential (${repeatedRecoveryCode}).`);
210
601
  }
211
- await send(responseMessage);
212
602
  }
213
603
  }
214
604
  catch (error) {
605
+ if (closing)
606
+ return;
607
+ if (terminal)
608
+ return;
609
+ if (state.responseDelivered) {
610
+ (options.logError || console.error)(`[Taskforce MCP proxy] Relay failed after delivering the response: ${String(error?.message || error)}`);
611
+ return;
612
+ }
215
613
  if (state.cancelled && id !== null) {
216
614
  await send(errorResponse(id, 'Client stopped waiting; the operation may still complete.', 'REQUEST_CANCELLED_ADVISORY', MCP_REQUEST_CANCELLED));
217
615
  return;
218
616
  }
617
+ if (definitivelyRejected && !retried) {
618
+ await failTerminal(error instanceof Error ? error : new Error(String(error)), id);
619
+ return;
620
+ }
621
+ if (id !== null && isKnownReadRequest(message) && !retried && !state.controller.signal.aborted) {
622
+ try {
623
+ attemptedConnection = await recoverConnection(attemptedConnection, null);
624
+ retried = true;
625
+ const recoveryCode = await relayOnce(message, attemptedConnection, state, cancelCorrelation);
626
+ if (recoveryCode) {
627
+ throw new Error(`Replacement local service rejected the credential (${recoveryCode}).`);
628
+ }
629
+ return;
630
+ }
631
+ catch (retryError) {
632
+ await failTerminal(retryError instanceof Error ? retryError : new Error(String(retryError)), id);
633
+ return;
634
+ }
635
+ }
636
+ if (id !== null && !isKnownReadRequest(message)) {
637
+ await recoverConnection(attemptedConnection, null).catch((recoveryError) => {
638
+ (options.logError || console.error)(`[Taskforce MCP proxy] Recovery after an outcome-uncertain request failed: ${String(recoveryError?.message || recoveryError)}`);
639
+ });
640
+ if (closing)
641
+ return;
642
+ const operationKey = idempotencyKey(message);
643
+ const guidance = operationKey
644
+ ? 'Taskforce could not confirm whether the operation completed. Do not retry automatically. Preserve the idempotency key, verify the intended state with the relevant Taskforce read or search tool, and retry only after confirming the operation is absent.'
645
+ : 'Taskforce could not confirm whether the operation completed. Do not retry automatically. Verify the intended state with the relevant Taskforce read or search tool before deciding whether any manual retry is safe.';
646
+ const outcome = {
647
+ code: 'LOCAL_SERVICE_OUTCOME_UNCERTAIN',
648
+ outcomeUncertain: true,
649
+ retryable: false,
650
+ ...(operationKey ? { idempotencyKey: operationKey } : {}),
651
+ operationId: null,
652
+ operationLookup: {
653
+ endpointTemplate: `${connection.descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/operations/{operationId}`,
654
+ status: 'operation_id_required',
655
+ requiresPrivateProxyCredential: true,
656
+ },
657
+ verificationGuidance: 'Use the relevant Taskforce read or search tool with the original target and payload. The idempotency key is not the canonical operation ID.',
658
+ };
659
+ if (!('method' in message) || message.method !== 'tools/call') {
660
+ await send(errorResponse(id, guidance, 'LOCAL_SERVICE_OUTCOME_UNCERTAIN', MCP_PROTOCOL_ERROR, outcome));
661
+ return;
662
+ }
663
+ await send({
664
+ jsonrpc: '2.0',
665
+ id,
666
+ result: {
667
+ content: [{ type: 'text', text: guidance }],
668
+ structuredContent: outcome,
669
+ isError: true,
670
+ ...(isModernRequest(message)
671
+ ? { resultType: 'complete' }
672
+ : {}),
673
+ },
674
+ });
675
+ return;
676
+ }
219
677
  await failTerminal(error instanceof Error ? error : new Error(String(error)), id);
220
678
  }
221
679
  finally {
@@ -225,34 +683,38 @@ export async function startLocalServiceMcpProxy(options) {
225
683
  requests.delete(key);
226
684
  }
227
685
  };
228
- stdio.onmessage = (message) => { void forward(message); };
686
+ const forwardPromises = new Set();
687
+ stdio.onmessage = (message) => {
688
+ const pending = forward(message).finally(() => { forwardPromises.delete(pending); });
689
+ forwardPromises.add(pending);
690
+ };
229
691
  stdio.onerror = (error) => { void failTerminal(error, null); };
230
692
  try {
231
693
  await stdio.start();
232
694
  }
233
695
  catch (error) {
234
- await fetchFn(`${descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/sessions/${encodeURIComponent(registration.session.id)}`, {
235
- method: 'DELETE',
236
- headers: { authorization: `Bearer ${registration.bearerToken}` },
237
- signal: timeoutSignal(2_000),
238
- }).then((response) => response.body?.cancel()).catch(() => undefined);
696
+ await revokeConnection(connection);
239
697
  throw error;
240
698
  }
241
699
  const close = () => {
242
700
  if (closePromise)
243
701
  return closePromise;
702
+ closing = true;
244
703
  terminal = true;
704
+ const pendingRecovery = recoveryState?.promise || null;
245
705
  closePromise = (async () => {
246
706
  for (const pending of inFlight)
247
707
  pending.controller.abort();
248
708
  await stdio.close().catch(() => undefined);
249
- await fetchFn(`${descriptor.endpoint}${LOCAL_SERVICE_API_BASE_PATH}/sessions/${encodeURIComponent(registration.session.id)}`, {
250
- method: 'DELETE',
251
- headers: { authorization: `Bearer ${registration.bearerToken}` },
252
- signal: timeoutSignal(2_000),
253
- }).then((response) => response.body?.cancel()).catch(() => undefined);
709
+ await Promise.allSettled([...forwardPromises]);
710
+ await pendingRecovery?.catch(() => undefined);
711
+ const activeConnection = connection;
712
+ await revokeConnection(activeConnection);
254
713
  })();
255
714
  return closePromise;
256
715
  };
257
- return { close, sessionId: registration.session.id };
716
+ return {
717
+ close,
718
+ get sessionId() { return connection.registration.session.id; },
719
+ };
258
720
  }