@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
@@ -6,15 +6,23 @@
6
6
  * POST /api/taskforce/agents
7
7
  * PATCH /api/taskforce/agents/:agentId
8
8
  * DELETE /api/taskforce/agents/:agentId
9
+ * GET /api/taskforce/agents/:agentId/connection-binding
10
+ * PUT /api/taskforce/agents/:agentId/connection-binding
11
+ * DELETE /api/taskforce/agents/:agentId/connection-binding
9
12
  * GET /api/taskforce/agents/:agentId/conversations
10
13
  * POST /api/taskforce/agents/:agentId/conversation/new
11
14
  * POST /api/taskforce/agents/model-gateway/test
12
15
  * PATCH /api/taskforce/agents/:agentId/conversations/:conversationId
13
16
  */
17
+ import { createHash } from 'node:crypto';
14
18
  import { assignedAiProfileColor, normalizeAiProfileColor } from '../../shared/aiProfileColors.js';
15
19
  import { BedrockAnthropicMessagesModelGateway } from '../../services/bedrockAnthropicMessagesModelGateway.js';
16
20
  import { BedrockMantleModelGateway } from '../../services/bedrockMantleModelGateway.js';
17
21
  import { BedrockModelGateway } from '../../services/bedrockModelGateway.js';
22
+ import { CodexAppServerModelGateway } from '../../services/codexAppServerModelGateway.js';
23
+ import { OwnerScopedModelConnectionGateway } from '../../services/ownerScopedModelConnectionGateway.js';
24
+ import { ModelProviderConnectionService } from '../../services/modelProviderConnectionService.js';
25
+ import { ModelProviderCredentialHomeManager } from '../../services/modelProviderCredentialHome.js';
18
26
  import { saveAiProfileAvatarAssets } from '../aiProfileAvatarAssets.js';
19
27
  import { ModelGatewayConfigurationError, normalizePersistedModelGatewayMessages } from '../../services/modelGateway.js';
20
28
  import { BedrockAvatarImageProvider, buildTaskforceAgentAvatarPrompt, } from '../../services/taskforceAgentAvatarImageProvider.js';
@@ -22,13 +30,18 @@ import { hashTaskforceAgentMcpToolContract, isTaskforceAgentMutationToolName, pr
22
30
  import { TaskforceAgentConversationStore } from '../../storage/taskforceAgentConversationStore.js';
23
31
  import { TaskforceAgentDefinitionConflictError, TaskforceAgentStore, } from '../../storage/taskforceAgentStore.js';
24
32
  import { TaskforceAgentSkillStore } from '../../storage/taskforceAgentSkillStore.js';
33
+ import { ModelProviderConnectionError, ModelProviderConnectionStore, } from '../../storage/modelProviderConnectionStore.js';
34
+ import { TaskforceAgentConnectionBindingStore } from '../../storage/taskforceAgentConnectionBindingStore.js';
35
+ import { TaskforceAgentConnectionBindingError, TaskforceAgentConnectionBindingService, } from '../../services/taskforceAgentConnectionBindingService.js';
25
36
  import { WorkflowStore } from '../../storage/workflowStore.js';
26
37
  import { WorkspaceSyncDurabilityStore } from '../../sync/v3/syncDurabilityStore.js';
27
38
  import { projectLegacyTaskforceAgentResponse } from '../../compat/taskforceAgentDefinitionCompat.js';
28
- import { TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY, resolveAppGateAccess, } from '../../runtime/appGates.js';
29
- import { DEFAULT_TASKFORCE_AGENT_MODEL_KEY, DEFAULT_TASKFORCE_AGENT_PROVIDER_KEY, getTaskforceAgentModel, isTaskforceAgentModelVisible, labelForTaskforceAgentModel, labelForTaskforceAgentProvider, normalizeTaskforceAgentModelKey, normalizeTaskforceAgentModelSelection, normalizeTaskforceAgentProviderKey, } from '../../shared/taskforceAgentModels.js';
39
+ import { TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY, } from '../../runtime/appGates.js';
40
+ import { resolveNodeAppGateAccess } from '../../runtime/nodeAppGates.js';
41
+ import { DEFAULT_TASKFORCE_AGENT_MODEL_KEY, DEFAULT_TASKFORCE_AGENT_PROVIDER_KEY, TASKFORCE_AGENT_MODEL_OPTIONS, getTaskforceAgentModel, isTaskforceAgentModelVisible, labelForTaskforceAgentModel, labelForTaskforceAgentProvider, normalizeTaskforceAgentModelKey, normalizeTaskforceAgentModelSelection, normalizeTaskforceAgentProviderKey, } from '../../shared/taskforceAgentModels.js';
42
+ import { INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY } from '../../shared/userFeatureGrants.js';
30
43
  import { buildTaskforceAgentRunContext } from '../../shared/taskforceAgentRunContext.js';
31
- import { inspectAgentDefinition } from '../../shared/taskforceAgentDefinition.js';
44
+ import { inspectAgentDefinition, serializeCanonicalJson } from '../../shared/taskforceAgentDefinition.js';
32
45
  import { buildResolvedTaskforceAgentSystemPrompt, resolveTaskforceAgentRuntimeConfiguration, TaskforceAgentRuntimeResolutionError, } from '../../shared/taskforceAgentRuntimeResolution.js';
33
46
  import { serializeTaskforceAgentExecutionSnapshot } from '../../shared/taskforceAgentExecutionSnapshot.js';
34
47
  import { getTaskReferenceLabel } from '../../utils/taskReferences.js';
@@ -113,6 +126,11 @@ function normalizeMessages(value, fallbackPrompt) {
113
126
  return { error: 'Prompt must be 4,000 characters or less.' };
114
127
  return { messages: [{ role: 'user', content: prompt }] };
115
128
  }
129
+ function buildManagedAgentExecutionRequestId(input) {
130
+ return createHash('sha256')
131
+ .update(serializeCanonicalJson(input))
132
+ .digest('hex');
133
+ }
116
134
  function toGatewayMessages(messages) {
117
135
  return messages.map((message) => ({
118
136
  role: message.role,
@@ -122,7 +140,13 @@ function toGatewayMessages(messages) {
122
140
  function requestsWorkflowStepCompletion(messages) {
123
141
  const latestUserMessage = [...messages].reverse().find((message) => message.role === 'user');
124
142
  const content = String(latestUserMessage?.content || '').trim().toLowerCase();
125
- return /^(?:please\s+|(?:can|could|would)\s+you\s+)?(?:perform\s+and\s+complete|complete|finish)\s+(?:your|the|this)\s+(?:current\s+)?workflow\s+step[.!?]*$/.test(content);
143
+ return /^(?:(?:hey|hi|hello)\b[^,!?]{0,80},?\s+)?(?:please\s+|(?:can|could|would)\s+you\s+)?(?:perform\s+and\s+complete|complete|finish)\s+(?:your|the|this)\s+(?:current\s+)?workflow\s+step(?:\s+(?:on|for)\s+(?:task\s+)?(?:t-\d+|[a-z0-9][a-z0-9-]{0,119}))?[.!?]*$/.test(content);
144
+ }
145
+ function extractLatestExplicitTaskReference(messages) {
146
+ const latestUserMessage = [...messages].reverse().find((message) => message.role === 'user');
147
+ const matches = String(latestUserMessage?.content || '').match(/\bT-\d+\b/gi) || [];
148
+ const references = [...new Set(matches.map((match) => match.toUpperCase()))];
149
+ return references.length === 1 ? references[0] : null;
126
150
  }
127
151
  function normalizeTaskId(value) {
128
152
  const taskId = String(value || '').trim();
@@ -144,6 +168,18 @@ function resolveTaskContextTask(core, workspaceId, taskId) {
144
168
  return core.getTask(taskId, workspaceId)
145
169
  || (typeof core.resolveTaskIdentifier === 'function' ? core.resolveTaskIdentifier(taskId, workspaceId) : null);
146
170
  }
171
+ function workflowToolCallsTargetSameTask(core, workspaceId, left, right) {
172
+ const resolveCanonicalId = (value) => {
173
+ const taskId = normalizeTaskId(value);
174
+ if (!taskId)
175
+ return null;
176
+ const task = resolveTaskContextTask(core, workspaceId, taskId);
177
+ return normalizeTaskId(task?.id)?.toLowerCase() || taskId.toLowerCase();
178
+ };
179
+ const leftTaskId = resolveCanonicalId(left);
180
+ const rightTaskId = resolveCanonicalId(right);
181
+ return Boolean(leftTaskId && rightTaskId && leftTaskId === rightTaskId);
182
+ }
147
183
  function resolveTaskScopeContext(core, workspaceId, input) {
148
184
  const taskId = String(input.taskId || '').trim();
149
185
  if (!taskId)
@@ -196,6 +232,7 @@ function serializeModelGatewayResult(result) {
196
232
  stopReason: result.stopReason || null,
197
233
  latencyMs: result.latencyMs ?? null,
198
234
  usage: result.usage || null,
235
+ ...(result.sourceMetadata ? { sourceMetadata: result.sourceMetadata } : {}),
199
236
  };
200
237
  }
201
238
  export function serializeWorkflowCompletionProjection(core, workspaceId, _taskId, toolResults) {
@@ -237,13 +274,33 @@ export function serializeWorkflowCompletionProjection(core, workspaceId, _taskId
237
274
  taskAuthoritative,
238
275
  };
239
276
  }
240
- function createDefaultModelGateway(selection) {
277
+ function createDefaultModelGateway(selection, connectionService) {
241
278
  const model = getTaskforceAgentModel(selection?.modelKey);
242
279
  if (model && selection?.providerKey && model.providerKey !== selection.providerKey) {
243
280
  throw new ModelGatewayConfigurationError('The selected model does not belong to this provider.', 'MODEL_UNAVAILABLE');
244
281
  }
245
282
  const source = selection?.modelSource || model?.source || 'bedrock';
246
283
  const runtime = selection?.runtime || model?.runtime || 'bedrock-runtime';
284
+ if (source === 'subscription_dev' && runtime === 'subscription-dev') {
285
+ if (selection?.connectionScope === 'personal'
286
+ || (selection?.connectionScope === 'local_dev' && selection.connectionId)) {
287
+ const connectionId = String(selection.connectionId || '').trim();
288
+ const ownerUserId = String(selection.connectionOwnerUserId || '').trim();
289
+ if (!connectionService || !connectionId || !ownerUserId) {
290
+ throw new ModelGatewayConfigurationError('A verified personal model connection is required.', 'MODEL_PROVIDER_CONNECTION_REQUIRED');
291
+ }
292
+ return new OwnerScopedModelConnectionGateway(connectionService, ownerUserId, connectionId, (context) => new CodexAppServerModelGateway({
293
+ env: context.environment,
294
+ credentialPaths: context.environment.CODEX_HOME
295
+ ? [context.environment.CODEX_HOME]
296
+ : [],
297
+ }));
298
+ }
299
+ if (selection?.connectionScope !== 'local_dev') {
300
+ throw new ModelGatewayConfigurationError('A personal model connection is required.', 'MODEL_PROVIDER_CONNECTION_REQUIRED');
301
+ }
302
+ return new CodexAppServerModelGateway();
303
+ }
247
304
  if (source !== 'bedrock') {
248
305
  throw new ModelGatewayConfigurationError('Selected model source is not configured yet.', 'MODEL_SOURCE_NOT_IMPLEMENTED');
249
306
  }
@@ -576,7 +633,7 @@ function resolveWorkspaceId(req, body, requestWorkspaceId) {
576
633
  }
577
634
  return authoritativeWorkspaceId || requestedWorkspaceId || 'default';
578
635
  }
579
- function validateAgentInput(body, workspaceId, actorUserId) {
636
+ function validateAgentInput(body, workspaceId, actorUserId, isModelVisible = isTaskforceAgentModelVisible) {
580
637
  const name = String(body?.name || '').trim();
581
638
  if (!name)
582
639
  return { error: 'Agent name is required.' };
@@ -587,10 +644,14 @@ function validateAgentInput(body, workspaceId, actorUserId) {
587
644
  return { error: 'Agent instructions must be 4,000 characters or less.' };
588
645
  const providerKey = normalizeTaskforceAgentProviderKey(body?.providerKey || DEFAULT_TASKFORCE_AGENT_PROVIDER_KEY);
589
646
  const requestedModel = body?.modelKey !== undefined ? getTaskforceAgentModel(body.modelKey) : null;
590
- if (requestedModel && !isTaskforceAgentModelVisible(requestedModel)) {
647
+ if (requestedModel && !isModelVisible(requestedModel)) {
591
648
  return { error: 'Selected model is not available for this account.' };
592
649
  }
593
- const modelKey = normalizeTaskforceAgentModelKey(body?.modelKey || DEFAULT_TASKFORCE_AGENT_MODEL_KEY, providerKey);
650
+ const modelKey = requestedModel
651
+ && requestedModel.providerKey === providerKey
652
+ && isModelVisible(requestedModel)
653
+ ? requestedModel.key
654
+ : normalizeTaskforceAgentModelKey(body?.modelKey || DEFAULT_TASKFORCE_AGENT_MODEL_KEY, providerKey);
594
655
  if (!modelKey)
595
656
  return { error: 'Select a configured model for this provider.' };
596
657
  return {
@@ -632,10 +693,13 @@ function canonicalMutationError(error) {
632
693
  };
633
694
  }
634
695
  export function registerAgentsRoutes(deps) {
635
- const { addRoute, ensureAppAccess, core, requestWorkspaceId, resolveAuthenticatedUserId, resolveRuntimeMode = () => 'local', ensureWorkspaceAdminRole, agentStore, skillStore, conversationStore, createModelGateway = createDefaultModelGateway, prepareMcpBridge = prepareTaskforceAgentMcpBridge, aiProfileAvatarAssetDeps, avatarImageProvider, saveAiProfileAvatarAssets: saveAvatarAssets = saveAiProfileAvatarAssets, agentRuntimeReferenceResolvers, agentRuntimeReferenceResolversForWorkspace, } = deps;
696
+ const { addRoute, ensureAppAccess, core, requestWorkspaceId, resolveAuthenticatedUserId, resolveRuntimeMode = () => 'local', ensureWorkspaceAdminRole, agentStore, skillStore, conversationStore, connectionBindingService, createModelGateway, prepareMcpBridge = prepareTaskforceAgentMcpBridge, aiProfileAvatarAssetDeps, avatarImageProvider, saveAiProfileAvatarAssets: saveAvatarAssets = saveAiProfileAvatarAssets, agentRuntimeReferenceResolvers, agentRuntimeReferenceResolversForWorkspace, } = deps;
636
697
  let resolvedAgentStore = agentStore || null;
637
698
  let resolvedSkillStore = skillStore || null;
638
699
  let resolvedConversationStore = conversationStore || null;
700
+ let resolvedConnectionBindingService = connectionBindingService || null;
701
+ let resolvedModelConnectionService = deps.modelConnectionService || null;
702
+ let resolvedCredentialHomeManager = null;
639
703
  let resolvedAvatarImageProvider = avatarImageProvider || null;
640
704
  const getAgentStore = () => {
641
705
  if (resolvedAgentStore)
@@ -661,6 +725,66 @@ export function registerAgentsRoutes(deps) {
661
725
  resolvedSkillStore = new TaskforceAgentSkillStore(core.getDatabaseAdapter(), core.getTenantId());
662
726
  return resolvedSkillStore;
663
727
  };
728
+ const getModelConnectionService = () => {
729
+ if (resolvedModelConnectionService)
730
+ return resolvedModelConnectionService;
731
+ if (!core)
732
+ throw new Error('Model connection service is unavailable.');
733
+ resolvedCredentialHomeManager ||= new ModelProviderCredentialHomeManager();
734
+ resolvedModelConnectionService = new ModelProviderConnectionService(new ModelProviderConnectionStore(core.getDatabaseAdapter(), core.getTenantId()), resolvedCredentialHomeManager, (userId) => core.hasUserFeatureGrant(userId, INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY));
735
+ return resolvedModelConnectionService;
736
+ };
737
+ const getConnectionBindingService = () => {
738
+ if (resolvedConnectionBindingService)
739
+ return resolvedConnectionBindingService;
740
+ if (!core)
741
+ throw new Error('Agent connection binding service is unavailable.');
742
+ resolvedConnectionBindingService = new TaskforceAgentConnectionBindingService(new TaskforceAgentConnectionBindingStore(core.getDatabaseAdapter(), core.getTenantId()), getAgentStore(), new ModelProviderConnectionStore(core.getDatabaseAdapter(), core.getTenantId()), getModelConnectionService(), (userId) => core.hasUserFeatureGrant(userId, INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY));
743
+ return resolvedConnectionBindingService;
744
+ };
745
+ const buildModelGateway = (selection) => {
746
+ if (createModelGateway)
747
+ return createModelGateway(selection);
748
+ const needsPersonalConnection = selection?.modelSource === 'subscription_dev'
749
+ && Boolean(selection.connectionId);
750
+ return createDefaultModelGateway(selection, needsPersonalConnection ? getModelConnectionService() : undefined);
751
+ };
752
+ const authorizeConnectionBindingRequest = (req, res) => {
753
+ if (resolveRuntimeMode(req) !== 'cloud') {
754
+ writeJson(res, 404, {
755
+ success: false,
756
+ error: 'Agent connection bindings are unavailable in this runtime.',
757
+ code: 'AGENT_CONNECTION_BINDINGS_CLOUD_ONLY',
758
+ });
759
+ return null;
760
+ }
761
+ const actorUserId = String(resolveAuthenticatedUserId?.(req) || '').trim();
762
+ if (!actorUserId) {
763
+ writeJson(res, 401, {
764
+ success: false,
765
+ error: 'Authentication is required.',
766
+ code: 'AUTH_REQUIRED',
767
+ });
768
+ return null;
769
+ }
770
+ return actorUserId;
771
+ };
772
+ const writeConnectionBindingError = (res, error) => {
773
+ if (error instanceof TaskforceAgentConnectionBindingError
774
+ || error instanceof ModelProviderConnectionError) {
775
+ writeJson(res, error.statusCode, {
776
+ success: false,
777
+ error: error.message,
778
+ code: error.code,
779
+ });
780
+ return;
781
+ }
782
+ writeJson(res, 500, {
783
+ success: false,
784
+ error: 'Agent connection request failed.',
785
+ code: 'AGENT_CONNECTION_REQUEST_FAILED',
786
+ });
787
+ };
664
788
  const resolveRuntimeReferenceResolversForWorkspace = (workspaceId) => {
665
789
  const baseResolvers = agentRuntimeReferenceResolversForWorkspace?.(workspaceId)
666
790
  || agentRuntimeReferenceResolvers
@@ -693,7 +817,7 @@ export function registerAgentsRoutes(deps) {
693
817
  const ensureTaskforceAgentsAccess = (req, res) => {
694
818
  if (!ensureAppAccess(req, res))
695
819
  return false;
696
- const gate = resolveAppGateAccess(TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY);
820
+ const gate = resolveNodeAppGateAccess(TASKFORCE_AGENTS_WORKSPACE_FEATURE_KEY);
697
821
  if (gate.allowed)
698
822
  return true;
699
823
  writeJson(res, 403, {
@@ -703,6 +827,34 @@ export function registerAgentsRoutes(deps) {
703
827
  });
704
828
  return false;
705
829
  };
830
+ const isModelVisibleForRequest = (req, model) => {
831
+ if (resolveRuntimeMode(req) !== 'cloud' || model.source !== 'subscription_dev') {
832
+ return isTaskforceAgentModelVisible(model);
833
+ }
834
+ const actorUserId = resolveAuthenticatedUserId?.(req) || null;
835
+ return Boolean(model.visible
836
+ && model.availability !== 'account_unavailable'
837
+ && actorUserId
838
+ && core?.hasUserFeatureGrant(actorUserId, INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY));
839
+ };
840
+ const isModelPersistableForRequest = (req, model) => {
841
+ if (resolveRuntimeMode(req) === 'local' && model.source === 'subscription_dev') {
842
+ return model.visible && model.availability !== 'account_unavailable';
843
+ }
844
+ return isModelVisibleForRequest(req, model);
845
+ };
846
+ const ensureDefinitionModelAccess = (req, res, definition) => {
847
+ const modelKey = String(definition?.model?.modelKey || '').trim();
848
+ const model = getTaskforceAgentModel(modelKey);
849
+ if (!model || isModelPersistableForRequest(req, model))
850
+ return true;
851
+ writeJson(res, model.source === 'subscription_dev' ? 403 : 400, {
852
+ success: false,
853
+ error: 'Selected model is not available for this account.',
854
+ code: model.source === 'subscription_dev' ? 'SUBSCRIPTION_MODEL_ACCESS_REQUIRED' : 'MODEL_UNAVAILABLE',
855
+ });
856
+ return false;
857
+ };
706
858
  addRoute('GET', '/api/taskforce/agents', async (req, res) => {
707
859
  if (!ensureTaskforceAgentsAccess(req, res))
708
860
  return;
@@ -716,7 +868,8 @@ export function registerAgentsRoutes(deps) {
716
868
  const profile = profileMap.get(agent.id) || null;
717
869
  return serializeAgent(persistManagedProfileLink(agent, profile, actorUserId), profile);
718
870
  });
719
- writeJson(res, 200, { success: true, agents });
871
+ const modelCatalog = TASKFORCE_AGENT_MODEL_OPTIONS.filter((model) => isModelVisibleForRequest(req, model));
872
+ writeJson(res, 200, { success: true, agents, modelCatalog });
720
873
  }
721
874
  catch (error) {
722
875
  writeJson(res, resolveErrorStatusCode(error, 500), {
@@ -725,6 +878,80 @@ export function registerAgentsRoutes(deps) {
725
878
  });
726
879
  }
727
880
  });
881
+ addRoute('GET', '/api/taskforce/agents/model-catalog', async (req, res) => {
882
+ if (!ensureTaskforceAgentsAccess(req, res))
883
+ return;
884
+ const modelCatalog = TASKFORCE_AGENT_MODEL_OPTIONS.filter((model) => isModelVisibleForRequest(req, model));
885
+ writeJson(res, 200, { success: true, modelCatalog });
886
+ });
887
+ addRoute('GET', '/api/taskforce/agents/:agentId/connection-binding', async (req, res, params) => {
888
+ if (!ensureTaskforceAgentsAccess(req, res))
889
+ return;
890
+ const actorUserId = authorizeConnectionBindingRequest(req, res);
891
+ if (!actorUserId)
892
+ return;
893
+ try {
894
+ const workspaceId = resolveWorkspaceId(req, undefined, requestWorkspaceId);
895
+ const binding = getConnectionBindingService().inspect({
896
+ workspaceId,
897
+ agentId: params.agentId,
898
+ callerUserId: actorUserId,
899
+ });
900
+ writeJson(res, 200, { success: true, binding });
901
+ }
902
+ catch (error) {
903
+ writeConnectionBindingError(res, error);
904
+ }
905
+ });
906
+ addRoute('PUT', '/api/taskforce/agents/:agentId/connection-binding', async (req, res, params) => {
907
+ if (!ensureTaskforceAgentsAccess(req, res))
908
+ return;
909
+ const actorUserId = authorizeConnectionBindingRequest(req, res);
910
+ if (!actorUserId)
911
+ return;
912
+ try {
913
+ const body = await parseJsonBody(req, 16 * 1024);
914
+ const workspaceId = resolveWorkspaceId(req, body, requestWorkspaceId);
915
+ await getConnectionBindingService().bind({
916
+ workspaceId,
917
+ agentId: params.agentId,
918
+ connectionId: String(body?.connectionId || ''),
919
+ actorUserId,
920
+ });
921
+ const binding = getConnectionBindingService().inspect({
922
+ workspaceId,
923
+ agentId: params.agentId,
924
+ callerUserId: actorUserId,
925
+ });
926
+ writeJson(res, 200, { success: true, binding });
927
+ }
928
+ catch (error) {
929
+ writeConnectionBindingError(res, error);
930
+ }
931
+ });
932
+ addRoute('DELETE', '/api/taskforce/agents/:agentId/connection-binding', async (req, res, params) => {
933
+ if (!ensureTaskforceAgentsAccess(req, res))
934
+ return;
935
+ const actorUserId = authorizeConnectionBindingRequest(req, res);
936
+ if (!actorUserId)
937
+ return;
938
+ try {
939
+ const body = await parseJsonBody(req, 16 * 1024);
940
+ const workspaceId = resolveWorkspaceId(req, body, requestWorkspaceId);
941
+ getConnectionBindingService().clear({
942
+ workspaceId,
943
+ agentId: params.agentId,
944
+ actorUserId,
945
+ });
946
+ writeJson(res, 200, {
947
+ success: true,
948
+ binding: { bound: false, available: false },
949
+ });
950
+ }
951
+ catch (error) {
952
+ writeConnectionBindingError(res, error);
953
+ }
954
+ });
728
955
  addRoute('POST', '/api/taskforce/agents', async (req, res) => {
729
956
  if (!ensureTaskforceAgentsAccess(req, res))
730
957
  return;
@@ -739,6 +966,8 @@ export function registerAgentsRoutes(deps) {
739
966
  }
740
967
  let agent;
741
968
  if (Object.prototype.hasOwnProperty.call(body, 'definition')) {
969
+ if (!ensureDefinitionModelAccess(req, res, body.definition))
970
+ return;
742
971
  if (body.lifecycleStatus !== undefined
743
972
  && body.lifecycleStatus !== 'active'
744
973
  && body.lifecycleStatus !== 'disabled') {
@@ -757,7 +986,7 @@ export function registerAgentsRoutes(deps) {
757
986
  });
758
987
  }
759
988
  else {
760
- const input = validateAgentInput(body, workspaceId, actorUserId);
989
+ const input = validateAgentInput(body, workspaceId, actorUserId, (model) => isModelPersistableForRequest(req, model));
761
990
  if ('error' in input) {
762
991
  writeJson(res, 400, { success: false, error: input.error });
763
992
  return;
@@ -794,6 +1023,8 @@ export function registerAgentsRoutes(deps) {
794
1023
  }
795
1024
  let agent;
796
1025
  if (Object.prototype.hasOwnProperty.call(body, 'definition')) {
1026
+ if (!ensureDefinitionModelAccess(req, res, body.definition))
1027
+ return;
797
1028
  if (body.lifecycleStatus !== undefined
798
1029
  && body.lifecycleStatus !== 'active'
799
1030
  && body.lifecycleStatus !== 'disabled') {
@@ -823,7 +1054,7 @@ export function registerAgentsRoutes(deps) {
823
1054
  }
824
1055
  }
825
1056
  else {
826
- const input = validateAgentInput(body, workspaceId, actorUserId);
1057
+ const input = validateAgentInput(body, workspaceId, actorUserId, (model) => isModelPersistableForRequest(req, model));
827
1058
  if ('error' in input) {
828
1059
  writeJson(res, 400, { success: false, error: input.error });
829
1060
  return;
@@ -1124,7 +1355,11 @@ export function registerAgentsRoutes(deps) {
1124
1355
  if (agentId) {
1125
1356
  savedAgent = getAgentStore().get(workspaceId, agentId);
1126
1357
  if (!savedAgent) {
1127
- writeJson(res, 404, { success: false, error: 'Taskforce agent not found.' });
1358
+ writeJson(res, 409, {
1359
+ success: false,
1360
+ error: 'This Agent is not available in Taskforce Cloud yet. Wait for synchronization and try again.',
1361
+ code: 'AGENT_NOT_AVAILABLE_IN_CLOUD',
1362
+ });
1128
1363
  return;
1129
1364
  }
1130
1365
  if (typeof savedAgent.definitionRevision === 'number') {
@@ -1149,9 +1384,30 @@ export function registerAgentsRoutes(deps) {
1149
1384
  }
1150
1385
  }
1151
1386
  const savedConversationTaskId = savedConversation?.taskId ? normalizeTaskId(savedConversation.taskId) : null;
1152
- const taskId = hasTaskId ? bodyTaskId : savedConversationTaskId;
1153
- const taskReference = taskId ? normalizeTaskContextValue(body?.taskReference) : '';
1154
- const taskTitle = taskId ? normalizeTaskContextValue(body?.taskTitle) : '';
1387
+ const explicitTaskReference = extractLatestExplicitTaskReference(normalizedMessages.messages);
1388
+ const explicitTask = explicitTaskReference
1389
+ ? resolveTaskContextTask(core, workspaceId, explicitTaskReference)
1390
+ : null;
1391
+ if (explicitTaskReference
1392
+ && !explicitTask
1393
+ && requestsWorkflowStepCompletion(normalizedMessages.messages)) {
1394
+ writeJson(res, 404, {
1395
+ success: false,
1396
+ error: `Task ${explicitTaskReference} was not found.`,
1397
+ code: 'TASK_NOT_FOUND',
1398
+ });
1399
+ return;
1400
+ }
1401
+ const taskId = normalizeTaskId(explicitTask?.id)
1402
+ || (explicitTaskReference ? null : hasTaskId ? bodyTaskId : savedConversationTaskId);
1403
+ const taskReference = taskId
1404
+ ? normalizeTaskContextValue(getTaskReferenceLabel(explicitTask)
1405
+ || (explicitTask ? explicitTaskReference : null)
1406
+ || body?.taskReference)
1407
+ : '';
1408
+ const taskTitle = taskId
1409
+ ? normalizeTaskContextValue(explicitTask?.title || body?.taskTitle)
1410
+ : '';
1155
1411
  if (resolvedRuntimeConfiguration) {
1156
1412
  const definition = resolvedRuntimeConfiguration.definition;
1157
1413
  const draftDiffers = ((body?.providerKey !== undefined
@@ -1183,22 +1439,38 @@ export function registerAgentsRoutes(deps) {
1183
1439
  return;
1184
1440
  }
1185
1441
  const requestedModel = body?.modelKey !== undefined ? getTaskforceAgentModel(body.modelKey) : null;
1186
- if (requestedModel && !isTaskforceAgentModelVisible(requestedModel)) {
1187
- writeJson(res, 400, { success: false, error: 'Selected model is not available for this account.' });
1442
+ if (requestedModel && !isModelVisibleForRequest(req, requestedModel)) {
1443
+ writeJson(res, requestedModel.source === 'subscription_dev' ? 403 : 400, {
1444
+ success: false,
1445
+ error: 'Selected model is not available for this account.',
1446
+ code: requestedModel.source === 'subscription_dev' ? 'SUBSCRIPTION_MODEL_ACCESS_REQUIRED' : 'MODEL_UNAVAILABLE',
1447
+ });
1188
1448
  return;
1189
1449
  }
1190
- const modelKey = resolvedRuntimeConfiguration
1191
- ? resolvedRuntimeConfiguration.definition.model.modelKey
1192
- : body?.modelKey !== undefined || body?.providerKey !== undefined
1193
- ? normalizeTaskforceAgentModelKey(body?.modelKey, providerKey)
1194
- : savedAgent?.modelKey || normalizeTaskforceAgentModelKey(undefined, providerKey);
1450
+ let modelKey;
1451
+ if (resolvedRuntimeConfiguration) {
1452
+ modelKey = resolvedRuntimeConfiguration.definition.model.modelKey;
1453
+ }
1454
+ else if (requestedModel && requestedModel.providerKey === providerKey) {
1455
+ modelKey = requestedModel.key;
1456
+ }
1457
+ else if (body?.modelKey !== undefined || body?.providerKey !== undefined) {
1458
+ modelKey = normalizeTaskforceAgentModelKey(body?.modelKey, providerKey);
1459
+ }
1460
+ else {
1461
+ modelKey = savedAgent?.modelKey || normalizeTaskforceAgentModelKey(undefined, providerKey);
1462
+ }
1195
1463
  if (!modelKey) {
1196
1464
  writeJson(res, 400, { success: false, error: 'Select a configured model for this provider.' });
1197
1465
  return;
1198
1466
  }
1199
1467
  const model = getTaskforceAgentModel(modelKey);
1200
- if (!model || !isTaskforceAgentModelVisible(model)) {
1201
- writeJson(res, 400, { success: false, error: 'Selected model is not available for this account.' });
1468
+ if (!model || !isModelVisibleForRequest(req, model)) {
1469
+ writeJson(res, model?.source === 'subscription_dev' ? 403 : 400, {
1470
+ success: false,
1471
+ error: 'Selected model is not available for this account.',
1472
+ code: model?.source === 'subscription_dev' ? 'SUBSCRIPTION_MODEL_ACCESS_REQUIRED' : 'MODEL_UNAVAILABLE',
1473
+ });
1202
1474
  return;
1203
1475
  }
1204
1476
  const modelSelection = normalizeTaskforceAgentModelSelection({
@@ -1206,21 +1478,55 @@ export function registerAgentsRoutes(deps) {
1206
1478
  modelKey,
1207
1479
  modelSource: resolvedRuntimeConfiguration?.definition.model.modelSource ?? body?.modelSource ?? model.source,
1208
1480
  connectionScope: resolvedRuntimeConfiguration?.definition.model.connectionScope ?? body?.connectionScope,
1209
- connectionId: resolvedRuntimeConfiguration?.definition.model.connectionId ?? body?.connectionId,
1481
+ connectionId: body?.connectionId,
1210
1482
  });
1211
1483
  if (!modelSelection) {
1212
1484
  writeJson(res, 400, { success: false, error: 'Selected model source is not available for this model.' });
1213
1485
  return;
1214
1486
  }
1215
- const gateway = createModelGateway({
1487
+ let runtimeConnectionId = null;
1488
+ let runtimeConnectionOwnerUserId = null;
1489
+ if (modelSelection.modelSource === 'subscription_dev'
1490
+ && (modelSelection.connectionScope === 'personal'
1491
+ || (modelSelection.connectionScope === 'local_dev' && resolveRuntimeMode(req) === 'cloud'))) {
1492
+ if (!actorUserId) {
1493
+ writeJson(res, 401, {
1494
+ success: false,
1495
+ error: 'Authentication is required.',
1496
+ code: 'AUTH_REQUIRED',
1497
+ });
1498
+ return;
1499
+ }
1500
+ const resolvedBinding = savedAgent
1501
+ ? getConnectionBindingService().resolveSaved({
1502
+ workspaceId,
1503
+ agentId: savedAgent.id,
1504
+ callerUserId: actorUserId,
1505
+ })
1506
+ : null;
1507
+ const resolvedConnection = resolvedBinding?.connection
1508
+ || getConnectionBindingService().resolveDraft({
1509
+ callerUserId: actorUserId,
1510
+ connectionId: modelSelection.connectionId || '',
1511
+ providerKey: modelSelection.providerKey,
1512
+ });
1513
+ runtimeConnectionId = resolvedConnection.id;
1514
+ runtimeConnectionOwnerUserId = resolvedBinding?.binding.ownerUserId || actorUserId;
1515
+ }
1516
+ const gateway = buildModelGateway({
1216
1517
  providerKey: modelSelection.providerKey,
1217
1518
  modelKey: modelSelection.modelKey,
1218
1519
  modelSource: modelSelection.modelSource,
1219
1520
  runtime: model.runtime,
1220
1521
  workspaceId,
1221
1522
  actorUserId,
1222
- connectionScope: modelSelection.connectionScope,
1223
- connectionId: modelSelection.connectionId,
1523
+ ...(modelSelection.connectionScope
1524
+ ? { connectionScope: modelSelection.connectionScope }
1525
+ : {}),
1526
+ ...(runtimeConnectionId ? { connectionId: runtimeConnectionId } : {}),
1527
+ ...(runtimeConnectionOwnerUserId
1528
+ ? { connectionOwnerUserId: runtimeConnectionOwnerUserId }
1529
+ : {}),
1224
1530
  });
1225
1531
  const runContext = buildTaskforceAgentRunContext({
1226
1532
  source: 'agent-manager-test',
@@ -1272,6 +1578,13 @@ export function registerAgentsRoutes(deps) {
1272
1578
  allowedMutationTaskId: taskId ?? null,
1273
1579
  readOnly: !savedAgent,
1274
1580
  toolPolicy: resolvedRuntimeConfiguration?.definition.toolPolicy,
1581
+ executionRequestId: buildManagedAgentExecutionRequestId({
1582
+ workspaceId,
1583
+ agentId: savedAgent?.id || agentId || null,
1584
+ conversationId,
1585
+ taskId: taskId ?? null,
1586
+ messages: normalizedMessages.messages,
1587
+ }),
1275
1588
  system: scopedAgentSystem,
1276
1589
  });
1277
1590
  const executionSnapshot = savedAgent && resolvedRuntimeConfiguration
@@ -1304,21 +1617,40 @@ export function registerAgentsRoutes(deps) {
1304
1617
  && mcpBridge?.availableToolNames.includes('complete_workflow_step')
1305
1618
  && requestsWorkflowStepCompletion(gatewayInput.messages));
1306
1619
  let workflowCompletionCorrectionSent = false;
1620
+ let reservedWorkflowCompletionUsed = false;
1307
1621
  while (mcpBridge) {
1308
1622
  if (requestedToolCall) {
1309
- if (mcpToolResults.length >= MAX_MCP_TOOL_ITERATIONS)
1623
+ const activeToolCall = requestedToolCall;
1624
+ const workflowStepAlreadyCompleted = mcpToolResults.some((toolResult) => (toolResult.name === 'complete_workflow_step' && toolResult.ok));
1625
+ const workflowStepLoaded = activeToolCall.name === 'complete_workflow_step'
1626
+ && mcpToolResults.some((toolResult) => (toolResult.name === 'get_task_workflow'
1627
+ && toolResult.ok
1628
+ && workflowToolCallsTargetSameTask(core, workspaceId, toolResult.arguments?.taskId, activeToolCall.arguments?.taskId)));
1629
+ const canUseReservedWorkflowCompletion = Boolean(workflowCompletionRequested
1630
+ && !workflowStepAlreadyCompleted
1631
+ && !reservedWorkflowCompletionUsed
1632
+ && activeToolCall.name === 'complete_workflow_step'
1633
+ && workflowStepLoaded
1634
+ && unresolvedFailedMutations.size === 0);
1635
+ if (mcpToolResults.length >= MAX_MCP_TOOL_ITERATIONS
1636
+ && !canUseReservedWorkflowCompletion)
1310
1637
  break;
1311
- const blocksWorkflowCompletion = requestedToolCall.name === 'complete_workflow_step'
1312
- && unresolvedFailedMutations.size > 0;
1638
+ if (mcpToolResults.length >= MAX_MCP_TOOL_ITERATIONS) {
1639
+ reservedWorkflowCompletionUsed = true;
1640
+ }
1641
+ const blocksWorkflowCompletion = activeToolCall.name === 'complete_workflow_step'
1642
+ && (!workflowStepLoaded || unresolvedFailedMutations.size > 0);
1313
1643
  const unresolvedMutationNames = [...new Set(unresolvedFailedMutations.values())];
1314
1644
  const toolResult = blocksWorkflowCompletion
1315
1645
  ? {
1316
- name: requestedToolCall.name,
1317
- arguments: requestedToolCall.arguments,
1646
+ name: activeToolCall.name,
1647
+ arguments: activeToolCall.arguments,
1318
1648
  ok: false,
1319
- text: `Taskforce refused workflow completion because these earlier changes failed: ${unresolvedMutationNames.join(', ')}. Retry the failed changes successfully before completing the step.`,
1649
+ text: !workflowStepLoaded
1650
+ ? 'Taskforce refused workflow completion because the current workflow step was not loaded successfully. Call get_task_workflow first, perform its instructions, then retry completion.'
1651
+ : `Taskforce refused workflow completion because these earlier changes failed: ${unresolvedMutationNames.join(', ')}. Retry the failed changes successfully before completing the step.`,
1320
1652
  }
1321
- : await mcpBridge.executeToolCall(requestedToolCall);
1653
+ : await mcpBridge.executeToolCall(activeToolCall);
1322
1654
  mcpToolResults.push(toolResult);
1323
1655
  if (isTaskforceAgentMutationToolName(toolResult.name)
1324
1656
  && toolResult.name !== 'complete_workflow_step') {
@@ -1349,6 +1681,17 @@ export function registerAgentsRoutes(deps) {
1349
1681
  throw error;
1350
1682
  }
1351
1683
  requestedToolCall = mcpBridge.parseToolCall(result.text);
1684
+ if (toolResult.name === 'complete_workflow_step'
1685
+ && toolResult.ok
1686
+ && requestedToolCall
1687
+ && mcpToolResults.length >= MAX_MCP_TOOL_ITERATIONS) {
1688
+ result = {
1689
+ ...result,
1690
+ text: 'Workflow step completed successfully.',
1691
+ };
1692
+ requestedToolCall = null;
1693
+ break;
1694
+ }
1352
1695
  continue;
1353
1696
  }
1354
1697
  const workflowStepCompleted = mcpToolResults.some((toolResult) => (toolResult.name === 'complete_workflow_step' && toolResult.ok));
@@ -1358,7 +1701,7 @@ export function registerAgentsRoutes(deps) {
1358
1701
  role: 'user',
1359
1702
  content: unresolvedFailedMutations.size > 0
1360
1703
  ? `The workflow step is not complete because these Taskforce changes failed: ${[...new Set(unresolvedFailedMutations.values())].join(', ')}. Retry those exact changes successfully before calling complete_workflow_step. If they cannot succeed, respond exactly WORKFLOW_STEP_INCOMPLETE: followed by the reason.`
1361
- : 'The workflow step is not authoritatively complete. If all required work succeeded, call complete_workflow_step now. Otherwise respond exactly WORKFLOW_STEP_INCOMPLETE: followed by the reason. Do not claim completion without a successful tool result.',
1704
+ : 'The workflow step is not authoritatively complete. Call get_task_workflow first if it has not succeeded in this response, perform the returned step instructions, then call complete_workflow_step. Otherwise respond exactly WORKFLOW_STEP_INCOMPLETE: followed by the reason. Do not claim completion without successful tool results.',
1362
1705
  });
1363
1706
  result = await gateway.generate({
1364
1707
  ...gatewayInput,
@@ -1370,7 +1713,19 @@ export function registerAgentsRoutes(deps) {
1370
1713
  break;
1371
1714
  }
1372
1715
  if (requestedToolCall) {
1373
- throw new Error('Taskforce tool call limit reached before the agent returned a final response.');
1716
+ mcpToolResults.push({
1717
+ name: requestedToolCall.name,
1718
+ arguments: requestedToolCall.arguments,
1719
+ ok: false,
1720
+ text: 'Taskforce did not execute this call because the per-message tool limit was reached.',
1721
+ });
1722
+ result = {
1723
+ ...result,
1724
+ text: workflowCompletionRequested
1725
+ ? 'WORKFLOW_STEP_INCOMPLETE: Taskforce reached the per-message tool limit before finishing the workflow step. Review Tool Activity and retry.'
1726
+ : 'Taskforce reached the per-message tool limit. Review Tool Activity and retry.',
1727
+ };
1728
+ requestedToolCall = null;
1374
1729
  }
1375
1730
  if (workflowCompletionRequested && !mcpToolResults.some((toolResult) => (toolResult.name === 'complete_workflow_step' && toolResult.ok))) {
1376
1731
  const incompletePrefix = 'WORKFLOW_STEP_INCOMPLETE:';