@taskforcehq/taskforce 0.3.329 → 0.3.330

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/dist/Taskforce.module.css +290 -45
  2. package/dist/components/features/AiProfilesModule.js +3 -5
  3. package/dist/components/features/TaskSettings.js +70 -14
  4. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  5. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  6. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  7. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  8. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  9. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  10. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  11. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  12. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  13. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  14. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  15. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  16. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  17. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  18. package/dist/components/views/StandaloneLayout.js +27 -26
  19. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  20. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  21. package/dist/config/envSchema.js +48 -1
  22. package/dist/core/McpTokenService.d.ts +23 -1
  23. package/dist/core/McpTokenService.js +93 -10
  24. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  25. package/dist/core/TaskChecklistCommandService.js +83 -5
  26. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  27. package/dist/core/TaskLifecycleCommandService.js +6 -2
  28. package/dist/core/Taskforce.d.ts +32 -0
  29. package/dist/core/Taskforce.js +125 -4
  30. package/dist/core/types.d.ts +8 -0
  31. package/dist/documentReviews/commandService.d.ts +2 -1
  32. package/dist/documentReviews/commandService.js +6 -3
  33. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  34. package/dist/hooks/sync/orchestratorShared.js +2 -0
  35. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  36. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  37. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  38. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  39. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  40. package/dist/hooks/useSyncOrchestrator.js +111 -2
  41. package/dist/hooks/useTaskData.d.ts +31 -1
  42. package/dist/hooks/useTaskData.js +29 -7
  43. package/dist/hooks/useTaskMutations.d.ts +3 -1
  44. package/dist/hooks/useTaskMutations.js +46 -12
  45. package/dist/hooks/useTaskforce.d.ts +2 -0
  46. package/dist/hooks/useTaskforce.js +11 -2
  47. package/dist/mcp/clientRegistry.d.ts +2 -2
  48. package/dist/mcp/clientRegistry.js +1 -1
  49. package/dist/mcp/documentAssetRegistrar.js +9 -6
  50. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  51. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  52. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  53. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  54. package/dist/mcp/httpProtocolRouting.js +19 -0
  55. package/dist/mcp/localCliHealth.d.ts +2 -2
  56. package/dist/mcp/localCliHealth.js +2 -2
  57. package/dist/mcp/localServiceProxy.d.ts +1 -0
  58. package/dist/mcp/localServiceProxy.js +530 -68
  59. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  60. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  61. package/dist/mcp/runtime.d.ts +54 -79
  62. package/dist/mcp/runtime.js +384 -97
  63. package/dist/mcp/taskPlanningRegistrar.js +23 -4
  64. package/dist/mcp/toolProfiles.d.ts +2 -0
  65. package/dist/mcp/toolProfiles.js +10 -0
  66. package/dist/mcp/toolRegistry.d.ts +1 -0
  67. package/dist/mcp/toolRegistry.js +1 -0
  68. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  69. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  70. package/dist/migrations/taskSchemaMigrations.js +415 -0
  71. package/dist/runtime/appGates.d.ts +2 -1
  72. package/dist/runtime/appGates.js +7 -0
  73. package/dist/server/index.d.ts +3 -0
  74. package/dist/server/index.js +108 -11
  75. package/dist/server/localDatabaseIdentity.js +4 -1
  76. package/dist/server/localServiceLease.js +2 -1
  77. package/dist/server/localServiceSessions.d.ts +14 -17
  78. package/dist/server/localServiceSessions.js +308 -94
  79. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -14
  80. package/dist/server/routes/admin.d.ts +4 -0
  81. package/dist/server/routes/admin.js +112 -3
  82. package/dist/server/routes/agents.d.ts +7 -0
  83. package/dist/server/routes/agents.js +277 -24
  84. package/dist/server/routes/billing.js +5 -1
  85. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  86. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  87. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  88. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  89. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  90. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  91. package/dist/server/routes/githubReviewEvidence.js +116 -0
  92. package/dist/server/routes/localService.d.ts +15 -4
  93. package/dist/server/routes/localService.js +136 -40
  94. package/dist/server/routes/modelConnections.d.ts +24 -0
  95. package/dist/server/routes/modelConnections.js +205 -0
  96. package/dist/server/routes/shared.d.ts +19 -0
  97. package/dist/server/routes/shared.js +95 -19
  98. package/dist/server/routes/sync.js +1 -0
  99. package/dist/server/routes/syncAuxRoutes.js +5 -1
  100. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  101. package/dist/server/routes/syncPushRoutes.js +1 -0
  102. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  103. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  104. package/dist/server/routes/tasks.js +21 -2
  105. package/dist/server/routes/workflows.js +9 -1
  106. package/dist/server/routes.js +59 -0
  107. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  108. package/dist/services/codexAppServerModelGateway.js +246 -21
  109. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  110. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  111. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  112. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  113. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  114. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  115. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  116. package/dist/services/executorPhaseAApprovalService.js +609 -0
  117. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  118. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  119. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  120. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  121. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  122. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  123. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  124. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  125. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  126. package/dist/services/githubReviewEvidenceService.js +336 -0
  127. package/dist/services/modelGateway.d.ts +7 -0
  128. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  129. package/dist/services/modelProviderConnectionService.js +279 -0
  130. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  131. package/dist/services/modelProviderCredentialHome.js +271 -0
  132. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  133. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  134. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  135. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  136. package/dist/services/taskforceAgentMcpBridge.d.ts +1 -1
  137. package/dist/services/taskforceAgentMcpBridge.js +7 -24
  138. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  139. package/dist/shared/adminEdgeProxy.js +94 -0
  140. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  141. package/dist/shared/adminProxySessionCookies.js +86 -0
  142. package/dist/shared/aiProfileColors.d.ts +31 -1
  143. package/dist/shared/aiProfileColors.js +14 -6
  144. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  145. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  146. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  147. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  148. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  149. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  150. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  151. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  152. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  153. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  154. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  155. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  156. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  157. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  158. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  159. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  160. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  161. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  162. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  163. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  164. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  165. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  166. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  167. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  168. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  169. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  170. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  171. package/dist/shared/executorPhaseATiming.js +1 -0
  172. package/dist/shared/planningIdentity.js +1 -1
  173. package/dist/shared/productLogoKeys.d.ts +2 -0
  174. package/dist/shared/productLogoKeys.js +18 -0
  175. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  176. package/dist/shared/taskforceAgentDefinition.js +6 -9
  177. package/dist/shared/taskforceAgentModels.js +7 -3
  178. package/dist/shared/userFeatureGrants.d.ts +4 -0
  179. package/dist/shared/userFeatureGrants.js +7 -0
  180. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  181. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  182. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  183. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  184. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  185. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  186. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  187. package/dist/storage/modelProviderConnectionStore.js +446 -0
  188. package/dist/storage/postgresAdapter.d.ts +4 -0
  189. package/dist/storage/postgresAdapter.js +11 -0
  190. package/dist/storage/postgresWorker.js +9 -1
  191. package/dist/storage/postgresWorkerProtocol.d.ts +1 -0
  192. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  193. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  194. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  195. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  196. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  197. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  198. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  199. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  200. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  201. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  202. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  203. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  204. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  205. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  206. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  207. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  208. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  209. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  210. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  211. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  212. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  213. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  214. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  215. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  216. package/dist/sync/syncApplyHandlers.js +10 -1
  217. package/dist/sync/syncService.d.ts +15 -0
  218. package/dist/sync/syncService.js +83 -18
  219. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  220. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  221. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  222. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  223. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  224. package/dist/sync/v3/durableOperationReplay.js +18 -0
  225. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  226. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  227. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  228. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  229. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  230. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  231. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  232. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  233. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  234. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  235. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  236. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  237. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  238. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  239. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  240. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +8 -0
  241. package/dist/sync/v3/localTaskStatusOutboxService.js +219 -12
  242. package/dist/sync/v3/syncDurabilityStore.d.ts +34 -0
  243. package/dist/sync/v3/syncDurabilityStore.js +168 -2
  244. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  245. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  246. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  247. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  248. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  249. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  250. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  251. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  252. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  253. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  254. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  255. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  256. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  257. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  258. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  259. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  260. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  261. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  262. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  263. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  264. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  265. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  266. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  267. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  268. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  269. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  270. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  271. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  272. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  273. package/dist/sync/workspaceRepair.d.ts +5 -2
  274. package/dist/sync/workspaceRepair.js +161 -6
  275. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  276. package/dist/sync/workspaceSyncModel.js +35 -7
  277. package/dist/sync/workspaceSyncState.d.ts +1 -0
  278. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  279. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  280. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  281. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  282. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-BTM6nIg_.js} +1 -1
  283. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  284. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-Coa8yVGM.js} +1 -1
  285. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  286. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  287. package/dist/ui/assets/{PlanningModule-B5DWQOGz.js → PlanningModule-pRPjR7v5.js} +1 -1
  288. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-D86pZSSl.js} +1 -1
  289. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-BVIkU9yT.js} +1 -1
  290. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  291. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  292. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  293. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  294. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  295. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  296. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  297. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  298. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  299. package/dist/ui/branding/logos/signature_dark.png +0 -0
  300. package/dist/ui/branding/logos/signature_light.png +0 -0
  301. package/dist/ui/index.html +3 -3
  302. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  303. package/dist/utils/httpSetCookie.d.ts +1 -0
  304. package/dist/utils/httpSetCookie.js +4 -1
  305. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  306. package/dist/utils/localRuntimeUrl.js +14 -0
  307. package/dist/utils/productLogoRegistry.d.ts +2 -0
  308. package/dist/utils/productLogoRegistry.js +36 -0
  309. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  310. package/dist/utils/syncStatusPresentation.js +17 -0
  311. package/dist/utils/taskEvents.d.ts +2 -0
  312. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  313. package/dist/utils/workspaceSyncPresentation.js +23 -17
  314. package/package.json +22 -4
  315. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  316. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  317. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  318. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  319. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  320. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  321. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -26,13 +26,21 @@ function requireMutationResult(task, taskId) {
26
26
  throw new TaskChecklistCommandError(`Task ${taskId} not found`, 'TASK_NOT_FOUND', 404, { taskId });
27
27
  }
28
28
  export function createTaskChecklistCommandService(deps) {
29
- const replaceItems = (taskId, items, operationKey) => {
30
- requireMutationResult(deps.replace({
29
+ const replaceItems = (taskId, items, operationKey, options) => {
30
+ const mutated = deps.replace({
31
31
  taskId,
32
32
  items,
33
- operationId: deps.createId('operation', operationKey),
34
- }), taskId);
35
- return deps.listItems(taskId);
33
+ operationId: options?.operationId || deps.createId('operation', operationKey),
34
+ ...(options?.expectedDetailRevision
35
+ ? { expectedDetailRevision: options.expectedDetailRevision }
36
+ : {}),
37
+ ...(options?.requireDurableIdempotency
38
+ ? { requireDurableIdempotency: true }
39
+ : {}),
40
+ ...(options?.itemUpdateIntent ? { itemUpdateIntent: options.itemUpdateIntent } : {}),
41
+ });
42
+ requireMutationResult(mutated, taskId);
43
+ return mutated?.checklistItems || deps.listItems(taskId);
36
44
  };
37
45
  return {
38
46
  replace(input) {
@@ -107,5 +115,75 @@ export function createTaskChecklistCommandService(deps) {
107
115
  items,
108
116
  };
109
117
  },
118
+ update(input) {
119
+ const task = deps.resolveTask(input.taskId);
120
+ const itemId = String(input.itemId ?? '').trim();
121
+ if (!itemId) {
122
+ throw new TaskChecklistCommandError('update_task_checklist_item requires itemId.');
123
+ }
124
+ const currentItems = deps.listItems(task.id);
125
+ const existingItem = currentItems.find((item) => item.id === itemId);
126
+ if (!existingItem) {
127
+ throw new TaskChecklistCommandError(`Checklist item ${itemId} was not found on task ${task.id}.`, 'TASK_CHECKLIST_ITEM_NOT_FOUND', 404, { taskId: task.id, itemId });
128
+ }
129
+ const hasTitle = input.title !== undefined || input.text !== undefined;
130
+ const hasCompleted = input.isCompleted !== undefined || input.done !== undefined;
131
+ const hasOrder = input.order !== undefined;
132
+ if (!hasTitle && !hasCompleted && !hasOrder) {
133
+ throw new TaskChecklistCommandError('update_task_checklist_item requires at least one of text, done, or order.');
134
+ }
135
+ const title = hasTitle
136
+ ? normalizeTitle(input.title ?? input.text, 'update_task_checklist_item text')
137
+ : existingItem.title;
138
+ const completedInput = input.isCompleted ?? input.done;
139
+ if (hasCompleted && typeof completedInput !== 'boolean') {
140
+ throw new TaskChecklistCommandError('update_task_checklist_item done must be a boolean.');
141
+ }
142
+ const isCompleted = hasCompleted ? completedInput : existingItem.isCompleted;
143
+ const parsedOrder = hasOrder ? Number(input.order) : existingItem.order;
144
+ if (hasOrder && (!Number.isInteger(parsedOrder) || parsedOrder < 0)) {
145
+ throw new TaskChecklistCommandError('update_task_checklist_item order must be a non-negative integer.');
146
+ }
147
+ const expectedDetailRevision = input.expectedDetailRevision === undefined
148
+ ? undefined
149
+ : String(input.expectedDetailRevision).trim();
150
+ if (input.expectedDetailRevision !== undefined && !expectedDetailRevision) {
151
+ throw new TaskChecklistCommandError('update_task_checklist_item expectedDetailRevision must contain non-whitespace text.');
152
+ }
153
+ const unchanged = existingItem.title === title
154
+ && existingItem.isCompleted === isCompleted
155
+ && existingItem.order === parsedOrder;
156
+ const nextItem = unchanged
157
+ ? existingItem
158
+ : {
159
+ ...existingItem,
160
+ title,
161
+ isCompleted,
162
+ order: parsedOrder,
163
+ updatedAt: deps.now(),
164
+ };
165
+ const nextItems = currentItems.map((item) => item.id === itemId ? nextItem : item);
166
+ const items = replaceItems(task.id, nextItems, `task-checklist-update:${task.id}:${itemId}`, {
167
+ operationId: input.operationId,
168
+ expectedDetailRevision,
169
+ requireDurableIdempotency: input.requireDurableIdempotency,
170
+ ...(input.requireDurableIdempotency ? {
171
+ itemUpdateIntent: {
172
+ kind: 'item-update',
173
+ itemId,
174
+ patch: {
175
+ ...(hasTitle ? { text: title } : {}),
176
+ ...(hasCompleted ? { done: isCompleted } : {}),
177
+ ...(hasOrder ? { order: parsedOrder } : {}),
178
+ },
179
+ },
180
+ } : {}),
181
+ });
182
+ const item = items.find((candidate) => candidate.id === itemId);
183
+ if (!item) {
184
+ throw new TaskChecklistCommandError(`Checklist item ${itemId} was not found after updating task ${task.id}.`, 'TASK_CHECKLIST_ITEM_NOT_FOUND', 404, { taskId: task.id, itemId });
185
+ }
186
+ return { taskId: task.id, item, items };
187
+ },
110
188
  };
111
189
  }
@@ -30,6 +30,7 @@ export interface TaskLifecycleCommandServiceDependencies {
30
30
  updates: Record<string, unknown>;
31
31
  forceDurable?: boolean;
32
32
  assigneeIntent?: TaskLifecycleAssigneeIntent;
33
+ handoffComment?: string;
33
34
  }): TaskLifecycleTask;
34
35
  mutateLifecycle(input: {
35
36
  taskId: string;
@@ -40,7 +41,7 @@ export interface TaskLifecycleCommandServiceDependencies {
40
41
  reason: string | undefined;
41
42
  };
42
43
  }): TaskLifecycleTask | null;
43
- resolveReviewer(task: TaskLifecycleTask): TaskLifecycleReviewerResolution;
44
+ resolveReviewer(task: TaskLifecycleTask, reviewer?: unknown): TaskLifecycleReviewerResolution;
44
45
  }
45
46
  export declare class TaskLifecycleCommandError extends Error {
46
47
  readonly code: string;
@@ -81,6 +82,7 @@ export declare function createTaskLifecycleCommandService(deps: TaskLifecycleCom
81
82
  finish(task: TaskLifecycleTask, input: {
82
83
  outcome: unknown;
83
84
  comment?: unknown;
85
+ reviewer?: unknown;
84
86
  }): FinishTaskCommandResult;
85
87
  reopen(task: TaskLifecycleTask, input: {
86
88
  activeAiProfileId: string | null | undefined;
@@ -88,8 +88,12 @@ export function createTaskLifecycleCommandService(deps) {
88
88
  nextTool: 'reopen_task',
89
89
  });
90
90
  }
91
+ const normalizedComment = typeof input.comment === 'string' ? input.comment.trim() : '';
92
+ if (normalizedOutcome === 'review' && !normalizedComment) {
93
+ throw new TaskLifecycleCommandError('finish_task requires a nonblank handoff comment when outcome is review.', 'TASK_FINISH_REVIEW_COMMENT_REQUIRED', 400, { taskId: task.id, outcome: normalizedOutcome });
94
+ }
91
95
  const reviewerResolution = normalizedOutcome === 'review'
92
- ? deps.resolveReviewer(task)
96
+ ? deps.resolveReviewer(task, input.reviewer)
93
97
  : undefined;
94
98
  const updated = deps.setStatus({
95
99
  task,
@@ -99,8 +103,8 @@ export function createTaskLifecycleCommandService(deps) {
99
103
  ...(reviewerResolution
100
104
  ? { assigneeIntent: { kind: 'set', value: reviewerResolution.assignee } }
101
105
  : {}),
106
+ ...(normalizedOutcome === 'review' ? { handoffComment: normalizedComment } : {}),
102
107
  });
103
- const normalizedComment = typeof input.comment === 'string' ? input.comment.trim() : '';
104
108
  return {
105
109
  task: updated,
106
110
  completion: {
@@ -5,6 +5,7 @@ import type { DurableTaskStatusMutationPayload } from './TaskDurableStatusMutati
5
5
  import { WorkspaceAssetStore } from '../storage/workspaceAssetStore.js';
6
6
  import { resolveAdminAuditRetentionPolicy, type AdminAuditRetentionDiagnostics, type AdminAuditRetentionRun } from './AdminAuditRetentionService.js';
7
7
  import type { WorkspaceSyncV3TaskAttachmentLink } from '../sync/v3/workspaceSyncV3NestedTaskCodecs.js';
8
+ import { type InternalUserFeatureKey } from '../shared/userFeatureGrants.js';
8
9
  import type { TaskRestoreDestination } from '../shared/taskRestoreDestination.js';
9
10
  import { type SyncEventInput } from './SyncReconciliationService.js';
10
11
  import { type FirstClassTaxonomyDisplayLabels, type NormalizedWorkspaceTaxonomyState, type WorkspaceTaxonomyState } from '../shared/taxonomyState.js';
@@ -458,6 +459,7 @@ export type SystemRole = 'system_admin' | 'user';
458
459
  type PermissionMode = 'read-only' | 'read-write';
459
460
  type AuthTokenPurpose = 'email_verification' | 'password_reset' | 'invite_accept';
460
461
  export type McpAccessTokenScope = 'tasks:read' | 'tasks:write' | 'workspace:read';
462
+ export type McpCloudToolProfile = 'default' | 'extended';
461
463
  type McpAccessTokenStatus = 'active' | 'revoked' | 'expired';
462
464
  export type McpOAuthProvider = 'chatgpt' | 'claude' | 'grok' | 'gemini' | 'mistral' | 'perplexity';
463
465
  type McpOAuthClientStatus = 'active' | 'revoked';
@@ -586,6 +588,7 @@ interface SystemUserRecord {
586
588
  systemRole: SystemRole;
587
589
  betaAccess: boolean;
588
590
  disabled: boolean;
591
+ internalFeatureGrants: InternalUserFeatureKey[];
589
592
  planId?: string | null;
590
593
  planName?: string | null;
591
594
  planVersionId?: string | null;
@@ -608,6 +611,7 @@ export interface PurgedSystemUserSummary {
608
611
  deletedMcpOauthConnectorGrantCount: number;
609
612
  deletedUiStateCount: number;
610
613
  deletedUserPreferenceCount: number;
614
+ deletedUserFeatureGrantCount: number;
611
615
  deletedEntitlementCount: number;
612
616
  deletedUserBillingCount: number;
613
617
  deletedUserCount: number;
@@ -772,6 +776,7 @@ export interface McpAccessTokenRecord {
772
776
  userEmail?: string | null;
773
777
  name: string;
774
778
  scopes: McpAccessTokenScope[];
779
+ toolProfile: McpCloudToolProfile;
775
780
  tokenPrefix: string;
776
781
  status: McpAccessTokenStatus;
777
782
  lastUsedAt?: string | null;
@@ -799,6 +804,7 @@ export interface McpAccessTokenAuthResult {
799
804
  workspaceId: string;
800
805
  userId: string;
801
806
  scopes: McpAccessTokenScope[];
807
+ toolProfile?: McpCloudToolProfile;
802
808
  status: McpAccessTokenStatus;
803
809
  }
804
810
  export interface McpAccessTokenInspectionResult {
@@ -808,6 +814,7 @@ export interface McpAccessTokenInspectionResult {
808
814
  userId: string;
809
815
  name: string;
810
816
  scopes: McpAccessTokenScope[];
817
+ toolProfile: McpCloudToolProfile;
811
818
  status: McpAccessTokenStatus;
812
819
  }
813
820
  export interface McpOAuthClientRecord {
@@ -829,6 +836,7 @@ export interface McpOAuthConnectorGrantRecord {
829
836
  workspaceId: string;
830
837
  userId: string;
831
838
  scopes: McpAccessTokenScope[];
839
+ toolProfile: McpCloudToolProfile;
832
840
  tokenPrefix: string;
833
841
  status: McpOAuthGrantStatus;
834
842
  lastUsedAt?: string | null;
@@ -851,6 +859,7 @@ export interface McpOAuthAccessTokenAuthResult {
851
859
  provider: McpOAuthProvider;
852
860
  productClientId?: string | null;
853
861
  scopes: McpAccessTokenScope[];
862
+ toolProfile?: McpCloudToolProfile;
854
863
  status: McpOAuthGrantStatus;
855
864
  aiProfileId?: string | null;
856
865
  aiProfileToken?: string | null;
@@ -1633,6 +1642,9 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
1633
1642
  setSystemRole(userId: string, role: SystemRole): boolean;
1634
1643
  setUserDisabledGlobal(userId: string, disabled: boolean): boolean;
1635
1644
  setUserBetaAccessGlobal(userId: string, enabled: boolean): boolean;
1645
+ hasUserFeatureGrant(userId: string, featureKey: unknown): boolean;
1646
+ listUserFeatureGrants(userId: string): InternalUserFeatureKey[];
1647
+ setUserFeatureGrant(userId: string, featureKey: unknown, enabled: boolean, updatedBy?: string | null): boolean;
1636
1648
  markUserEmailVerified(userId: string): {
1637
1649
  emailVerifiedAt: string;
1638
1650
  } | null;
@@ -2208,6 +2220,15 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
2208
2220
  tokenId: string;
2209
2221
  createdByIp?: string | null;
2210
2222
  }): McpAccessTokenIssueResult;
2223
+ updateMcpAccessTokenToolProfile(input: {
2224
+ actorUserId: string;
2225
+ workspaceId: string;
2226
+ tokenId: string;
2227
+ toolProfile: unknown;
2228
+ }): {
2229
+ record: McpAccessTokenRecord;
2230
+ previousToolProfile: McpCloudToolProfile;
2231
+ };
2211
2232
  authenticateMcpAccessToken(token: string, workspaceId?: string): McpAccessTokenAuthResult | null;
2212
2233
  inspectMcpAccessToken(token: string): McpAccessTokenInspectionResult | null;
2213
2234
  recordMcpAccessTokenUsage(input: {
@@ -2253,6 +2274,15 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
2253
2274
  workspaceId: string;
2254
2275
  grantId: string;
2255
2276
  }): McpOAuthConnectorGrantRecord;
2277
+ updateMcpOAuthConnectorGrantToolProfile(input: {
2278
+ actorUserId: string;
2279
+ workspaceId: string;
2280
+ grantId: string;
2281
+ toolProfile: unknown;
2282
+ }): {
2283
+ record: McpOAuthConnectorGrantRecord;
2284
+ previousToolProfile: McpCloudToolProfile;
2285
+ };
2256
2286
  authenticateMcpOAuthAccessToken(token: string, workspaceId?: string): McpOAuthAccessTokenAuthResult | null;
2257
2287
  bindMcpOAuthConnectorGrantAiProfile(input: {
2258
2288
  grantId: string;
@@ -2467,8 +2497,10 @@ export declare class TaskforceCore implements TaskforceSyncCapable {
2467
2497
  notifyDurableTaskMetadataCommitted(workspaceId: string, taskId: string): void;
2468
2498
  addComment(id: string, text: string, author: string, workspaceId?: string, options?: {
2469
2499
  persistBackup?: boolean;
2500
+ emitRealtime?: boolean;
2470
2501
  actorRef?: string;
2471
2502
  skipTaskEvents?: boolean;
2503
+ commentId?: string;
2472
2504
  }): TaskItem | null;
2473
2505
  private addPlanningEntityComment;
2474
2506
  addInitiativeComment(id: string, text: string, author: string, workspaceId?: string, options?: {
@@ -27,6 +27,7 @@ import { listTaskAttachmentLinksForDurableSync as listTaskAttachmentLinksForDura
27
27
  import { EntityEventIdentityCollisionError, addEntityEventService, addTaskEventService, buildEntityActivityService, buildTaskActivityService, getEntityEventForSyncService, getTaskEventForSyncService, listEntityEventsInternalService, listWorkspaceEntityEventsForSyncService, listTaskEventsInternalService, listWorkspaceTaskEventsForSyncService, replaceEntityEventsService, replaceTaskCommentsService, replaceTaskEventsService, upsertEntityEventForSyncService, deleteEntityEventForSyncService, upsertTaskEventForSyncService, } from './TaskActivityService.js';
28
28
  import { addDeletedTaskRecordService, getDeletedTaskService, listDeletedTasksService, listDeletedTasksReadOnlyService, mapDeletedTaskRowService, normalizeTaskSnapshotForRestoreService, normalizeDeletedTaskRestoreLifecycleService, purgeExpiredDeletedTasksService, } from './DeletedTaskLifecycleService.js';
29
29
  import { DELETED_TASK_RETENTION_DAYS } from '../shared/deletedTaskRetention.js';
30
+ import { INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY, isSupportedInternalUserFeatureKey, } from '../shared/userFeatureGrants.js';
30
31
  import { applyWorkspaceSyncSnapshotService, claimPushIdempotencyService, completePushIdempotencyClaimService, deleteDocumentWatermarkService, deleteDocumentWatermarkStrictService, getDocumentWatermarkService, listTasksForSyncService, listWorkspaceSyncDeletesSinceService, readPushIdempotencyService, releasePushIdempotencyClaimService, renewPushIdempotencyClaimService, recordSyncEventDurablyService, recordSyncEventService, upsertDocumentWatermarkService, upsertDocumentWatermarkStrictService, writePushIdempotencyService, } from './SyncReconciliationService.js';
31
32
  import { getGlobalSettingsService, hasPersistedGlobalSettingsService, readGlobalConfigService, updateGlobalSettingsService, writeGlobalConfigService, } from './GlobalSettingsService.js';
32
33
  import { getWorkspaceTaxonomyStateService, upsertWorkspaceTaxonomyStateService, } from './TaxonomySettingsService.js';
@@ -62,7 +63,7 @@ import { getCanonicalDocumentName } from '../utils/documentNames.js';
62
63
  import { isPathInsideRoot, resolveStorageKeyPathInsideRoot } from '../utils/pathSafety.js';
63
64
  import { DEFAULT_TASKFORCE_THEME } from '../utils/theme.js';
64
65
  import { normalizeTaskSearchQuery } from '../utils/taskSearch.js';
65
- import { ensureAssigneeTaskSchema, ensureAnnotatedAttachmentSessionsSchema, ensureAuthIdentitySchema, backfillPlanningAttachmentAssetIdentities, ensureBillingSchema, ensureDocumentReviewSessionsSchema, ensureDocumentReferenceSchema, ensureEntitlementsSchema, ensurePlanningReferenceSchema, ensureScheduleTaskSchema, ensureWorkstreamTaskOrderSchema, ensureTaskAssetsSchema, ensureTaskApproachRemoved, ensureAgentRolesSchema, ensureTaskforceAgentsSchema, ensureTaskforceAgentSkillsSchema, ensureTaskReferenceSchema, ensureTenantSchema, ensureWorkflowSchema, ensureWorkspaceAssetsSchema, ensureWorkspaceSchema, ensureLocalSyncCoordinatorSchema, ensureWorkspaceSyncDurabilitySchema } from '../migrations/taskSchemaMigrations.js';
66
+ import { ensureAssigneeTaskSchema, ensureAnnotatedAttachmentSessionsSchema, ensureAuthIdentitySchema, backfillPlanningAttachmentAssetIdentities, ensureBillingSchema, ensureDocumentReviewSessionsSchema, ensureDocumentReferenceSchema, ensureEntitlementsSchema, ensurePlanningReferenceSchema, ensureScheduleTaskSchema, ensureWorkstreamTaskOrderSchema, ensureTaskAssetsSchema, ensureTaskApproachRemoved, ensureAgentRolesSchema, ensureGitHubReviewEvidenceInstallationBindingsSchema, ensureExecutorPhaseAApprovalReceiptsSchema, ensureExecutorPhaseARunAuthorizationsSchema, ensureModelProviderConnectionsSchema, ensureTaskforceAgentConnectionBindingsSchema, ensureTaskforceAgentsSchema, ensureTaskforceAgentSkillsSchema, ensureTaskReferenceSchema, ensureTenantSchema, ensureWorkflowSchema, ensureWorkspaceAssetsSchema, ensureWorkspaceSchema, ensureLocalSyncCoordinatorSchema, ensureWorkspaceSyncDurabilitySchema } from '../migrations/taskSchemaMigrations.js';
66
67
  import { repairTaskUpdatedAtOnlySyncDrift } from '../migrations/taskUpdatedAtSyncDriftMigration.js';
67
68
  export class TaskforceRuleError extends Error {
68
69
  statusCode;
@@ -1457,7 +1458,14 @@ export class TaskforceCore {
1457
1458
  ensureDocumentReferenceSchema(this.db);
1458
1459
  ensureDocumentReviewSessionsSchema(this.db);
1459
1460
  ensureAnnotatedAttachmentSessionsSchema(this.db);
1461
+ ensureModelProviderConnectionsSchema(this.db);
1460
1462
  ensureTaskforceAgentsSchema(this.db);
1463
+ ensureTaskforceAgentConnectionBindingsSchema(this.db);
1464
+ ensureGitHubReviewEvidenceInstallationBindingsSchema(this.db);
1465
+ if (this.runtimeMode === 'cloud') {
1466
+ ensureExecutorPhaseAApprovalReceiptsSchema(this.db);
1467
+ ensureExecutorPhaseARunAuthorizationsSchema(this.db);
1468
+ }
1461
1469
  ensureAgentRolesSchema(this.db);
1462
1470
  ensureTaskforceAgentSkillsSchema(this.db);
1463
1471
  ensureWorkflowSchema(this.db);
@@ -1969,6 +1977,18 @@ export class TaskforceCore {
1969
1977
  PRIMARY KEY (tenant_id, user_id, prefs_key)
1970
1978
  );
1971
1979
 
1980
+ CREATE TABLE IF NOT EXISTS user_feature_grants (
1981
+ tenant_id TEXT NOT NULL DEFAULT 'default',
1982
+ user_id TEXT NOT NULL,
1983
+ feature_key TEXT NOT NULL,
1984
+ enabled INTEGER NOT NULL DEFAULT 0,
1985
+ created_at TEXT NOT NULL,
1986
+ updated_at TEXT NOT NULL,
1987
+ updated_by TEXT,
1988
+ PRIMARY KEY (tenant_id, user_id, feature_key),
1989
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
1990
+ );
1991
+
1972
1992
  CREATE TABLE IF NOT EXISTS admin_audit_logs (
1973
1993
  id TEXT PRIMARY KEY,
1974
1994
  tenant_id TEXT NOT NULL DEFAULT 'default',
@@ -2047,6 +2067,7 @@ export class TaskforceCore {
2047
2067
  user_id TEXT NOT NULL,
2048
2068
  workspace_id TEXT NOT NULL DEFAULT 'default',
2049
2069
  scopes_json TEXT NOT NULL,
2070
+ tool_profile TEXT NOT NULL DEFAULT 'default',
2050
2071
  token_prefix TEXT NOT NULL,
2051
2072
  token_hash TEXT NOT NULL,
2052
2073
  status TEXT NOT NULL DEFAULT 'active',
@@ -2188,6 +2209,7 @@ export class TaskforceCore {
2188
2209
  CREATE INDEX IF NOT EXISTS idx_ui_state_workspace_key ON ui_state(workspace_id, state_key);
2189
2210
  CREATE INDEX IF NOT EXISTS idx_workspace_settings_workspace_key ON workspace_settings(workspace_id, settings_key);
2190
2211
  CREATE INDEX IF NOT EXISTS idx_user_preferences_user_key ON user_preferences(user_id, prefs_key);
2212
+ CREATE INDEX IF NOT EXISTS idx_user_feature_grants_feature_enabled ON user_feature_grants(tenant_id, feature_key, enabled);
2191
2213
  CREATE INDEX IF NOT EXISTS idx_admin_audit_logs_tenant_created ON admin_audit_logs(tenant_id, created_at);
2192
2214
  CREATE INDEX IF NOT EXISTS idx_admin_audit_logs_workspace_created ON admin_audit_logs(workspace_id, created_at);
2193
2215
  CREATE INDEX IF NOT EXISTS idx_task_events_task_created ON task_events(tenant_id, workspace_id, task_id, created_at);
@@ -2376,6 +2398,9 @@ export class TaskforceCore {
2376
2398
  if (!mcpOauthGrantColumns.some((c) => c.name === 'ai_profile_name')) {
2377
2399
  this.db.exec(`ALTER TABLE mcp_oauth_connector_grants ADD COLUMN ai_profile_name TEXT`);
2378
2400
  }
2401
+ if (!mcpOauthGrantColumns.some((c) => c.name === 'tool_profile')) {
2402
+ this.db.exec(`ALTER TABLE mcp_oauth_connector_grants ADD COLUMN tool_profile TEXT NOT NULL DEFAULT 'default'`);
2403
+ }
2379
2404
  }
2380
2405
  else {
2381
2406
  try {
@@ -2384,6 +2409,7 @@ export class TaskforceCore {
2384
2409
  this.db.exec(`ALTER TABLE mcp_oauth_connector_grants ADD COLUMN IF NOT EXISTS ai_profile_id TEXT`);
2385
2410
  this.db.exec(`ALTER TABLE mcp_oauth_connector_grants ADD COLUMN IF NOT EXISTS ai_profile_token TEXT`);
2386
2411
  this.db.exec(`ALTER TABLE mcp_oauth_connector_grants ADD COLUMN IF NOT EXISTS ai_profile_name TEXT`);
2412
+ this.db.exec(`ALTER TABLE mcp_oauth_connector_grants ADD COLUMN IF NOT EXISTS tool_profile TEXT NOT NULL DEFAULT 'default'`);
2387
2413
  }
2388
2414
  catch {
2389
2415
  // Best-effort schema repair for existing deployments.
@@ -6956,7 +6982,7 @@ export class TaskforceCore {
6956
6982
  OR LOWER(COALESCE(u.system_role, 'user')) LIKE ?
6957
6983
  )`
6958
6984
  : '';
6959
- const params = [this.tenantId];
6985
+ const params = [INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY, this.tenantId];
6960
6986
  if (query) {
6961
6987
  params.push(queryPattern, queryPattern, queryPattern, queryPattern, queryPattern, queryPattern, queryPattern);
6962
6988
  }
@@ -6969,6 +6995,14 @@ export class TaskforceCore {
6969
6995
  COALESCE(u.system_role, 'user') AS system_role,
6970
6996
  COALESCE(u.beta_access, 1) AS beta_access,
6971
6997
  COALESCE(u.is_disabled, 0) AS is_disabled,
6998
+ CASE WHEN EXISTS (
6999
+ SELECT 1
7000
+ FROM user_feature_grants g
7001
+ WHERE g.tenant_id = u.tenant_id
7002
+ AND g.user_id = u.id
7003
+ AND g.feature_key = ?
7004
+ AND g.enabled = 1
7005
+ ) THEN 1 ELSE 0 END AS subscription_model_access,
6972
7006
  u.created_at,
6973
7007
  u.updated_at,
6974
7008
  u.email_verified_at,
@@ -7000,6 +7034,9 @@ export class TaskforceCore {
7000
7034
  systemRole: this.normalizeSystemRole(row.system_role, 'user'),
7001
7035
  betaAccess: row.beta_access === undefined || row.beta_access === null ? true : Boolean(row.beta_access),
7002
7036
  disabled: Boolean(row.is_disabled),
7037
+ internalFeatureGrants: Boolean(row.subscription_model_access)
7038
+ ? [INTERNAL_SUBSCRIPTION_MODEL_FEATURE_KEY]
7039
+ : [],
7003
7040
  planId: row.plan_id ? String(row.plan_id) : null,
7004
7041
  planName: row.plan_name ? String(row.plan_name) : null,
7005
7042
  planVersionId: row.plan_version_id ? String(row.plan_version_id) : null,
@@ -7073,6 +7110,53 @@ export class TaskforceCore {
7073
7110
  `).run(enabled ? 1 : 0, new Date().toISOString(), this.tenantId, normalizedUserId);
7074
7111
  return Number(result?.changes || 0) > 0;
7075
7112
  }
7113
+ hasUserFeatureGrant(userId, featureKey) {
7114
+ const normalizedUserId = String(userId || '').trim();
7115
+ if (!normalizedUserId || !isSupportedInternalUserFeatureKey(featureKey))
7116
+ return false;
7117
+ const row = this.db.prepare(`
7118
+ SELECT enabled
7119
+ FROM user_feature_grants
7120
+ WHERE tenant_id = ? AND user_id = ? AND feature_key = ?
7121
+ LIMIT 1
7122
+ `).get(this.tenantId, normalizedUserId, featureKey);
7123
+ return Boolean(row?.enabled);
7124
+ }
7125
+ listUserFeatureGrants(userId) {
7126
+ const normalizedUserId = String(userId || '').trim();
7127
+ if (!normalizedUserId)
7128
+ return [];
7129
+ const rows = this.db.prepare(`
7130
+ SELECT feature_key
7131
+ FROM user_feature_grants
7132
+ WHERE tenant_id = ? AND user_id = ? AND enabled = 1
7133
+ ORDER BY feature_key
7134
+ `).all(this.tenantId, normalizedUserId);
7135
+ return rows
7136
+ .map((row) => row.feature_key)
7137
+ .filter(isSupportedInternalUserFeatureKey);
7138
+ }
7139
+ setUserFeatureGrant(userId, featureKey, enabled, updatedBy) {
7140
+ const normalizedUserId = String(userId || '').trim();
7141
+ if (!normalizedUserId || !isSupportedInternalUserFeatureKey(featureKey))
7142
+ return false;
7143
+ const user = this.db.prepare(`
7144
+ SELECT id FROM users WHERE tenant_id = ? AND id = ? LIMIT 1
7145
+ `).get(this.tenantId, normalizedUserId);
7146
+ if (!user?.id)
7147
+ return false;
7148
+ const now = new Date().toISOString();
7149
+ this.db.prepare(`
7150
+ INSERT INTO user_feature_grants (
7151
+ tenant_id, user_id, feature_key, enabled, created_at, updated_at, updated_by
7152
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
7153
+ ON CONFLICT (tenant_id, user_id, feature_key) DO UPDATE SET
7154
+ enabled = excluded.enabled,
7155
+ updated_at = excluded.updated_at,
7156
+ updated_by = excluded.updated_by
7157
+ `).run(this.tenantId, normalizedUserId, featureKey, enabled ? 1 : 0, now, now, String(updatedBy || '').trim() || null);
7158
+ return true;
7159
+ }
7076
7160
  markUserEmailVerified(userId) {
7077
7161
  const normalizedUserId = String(userId || '').trim();
7078
7162
  if (!normalizedUserId)
@@ -7179,6 +7263,14 @@ export class TaskforceCore {
7179
7263
  if (hasCommercialBillingState) {
7180
7264
  throw new TaskforceRuleError('Cannot purge a user with active commercial billing state', 409, 'SYSTEM_USER_PURGE_BLOCKED_BILLING_STATE');
7181
7265
  }
7266
+ const modelConnectionCount = Number(this.db.prepare(`
7267
+ SELECT COUNT(*) AS count
7268
+ FROM model_provider_connections
7269
+ WHERE tenant_id = ? AND owner_user_id = ?
7270
+ `).get(this.tenantId, targetUserId)?.count || 0);
7271
+ if (modelConnectionCount > 0) {
7272
+ throw new TaskforceRuleError('Disconnect and clean up the user model connections before purging this account', 409, 'SYSTEM_USER_PURGE_BLOCKED_MODEL_CONNECTIONS');
7273
+ }
7182
7274
  const now = new Date().toISOString();
7183
7275
  const runCount = (sql, ...params) => Number(this.db.prepare(sql).run(...params)?.changes || 0);
7184
7276
  const workspaceIds = this.db.prepare(`
@@ -7278,6 +7370,11 @@ export class TaskforceCore {
7278
7370
  WHERE tenant_id = ?
7279
7371
  AND user_id = ?
7280
7372
  `, this.tenantId, targetUserId);
7373
+ const deletedUserFeatureGrantCount = runCount(`
7374
+ DELETE FROM user_feature_grants
7375
+ WHERE tenant_id = ?
7376
+ AND user_id = ?
7377
+ `, this.tenantId, targetUserId);
7281
7378
  const deletedUserBillingCount = runCount(`
7282
7379
  DELETE FROM user_billing
7283
7380
  WHERE tenant_id = ?
@@ -7305,6 +7402,7 @@ export class TaskforceCore {
7305
7402
  deletedMcpOauthConnectorGrantCount,
7306
7403
  deletedUiStateCount,
7307
7404
  deletedUserPreferenceCount,
7405
+ deletedUserFeatureGrantCount,
7308
7406
  deletedEntitlementCount,
7309
7407
  deletedUserBillingCount,
7310
7408
  deletedUserCount
@@ -8743,6 +8841,9 @@ export class TaskforceCore {
8743
8841
  regenerateMcpAccessToken(input) {
8744
8842
  return this.mcpTokenService.regenerateMcpAccessToken(input);
8745
8843
  }
8844
+ updateMcpAccessTokenToolProfile(input) {
8845
+ return this.mcpTokenService.updateMcpAccessTokenToolProfile(input);
8846
+ }
8746
8847
  authenticateMcpAccessToken(token, workspaceId) {
8747
8848
  return this.mcpTokenService.authenticateMcpAccessToken(token, workspaceId);
8748
8849
  }
@@ -8770,6 +8871,9 @@ export class TaskforceCore {
8770
8871
  revokeMcpOAuthConnectorGrant(input) {
8771
8872
  return this.mcpTokenService.revokeMcpOAuthConnectorGrant(input);
8772
8873
  }
8874
+ updateMcpOAuthConnectorGrantToolProfile(input) {
8875
+ return this.mcpTokenService.updateMcpOAuthConnectorGrantToolProfile(input);
8876
+ }
8773
8877
  authenticateMcpOAuthAccessToken(token, workspaceId) {
8774
8878
  return this.mcpTokenService.authenticateMcpOAuthAccessToken(token, workspaceId);
8775
8879
  }
@@ -10653,8 +10757,25 @@ export class TaskforceCore {
10653
10757
  return null;
10654
10758
  const submittedAuthor = String(author || '').trim() || 'user';
10655
10759
  const normalizedAuthor = this.normalizeCommentAuthor(author, normalizedWorkspaceId);
10760
+ const explicitCommentId = String(options?.commentId || '').trim();
10761
+ if (explicitCommentId) {
10762
+ const persisted = this.db.prepare(`
10763
+ SELECT task_id, text, author, submitted_author
10764
+ FROM comments
10765
+ WHERE tenant_id = ? AND workspace_id = ? AND id = ?
10766
+ `).get(this.tenantId, normalizedWorkspaceId, explicitCommentId);
10767
+ if (persisted) {
10768
+ if (persisted.task_id !== id
10769
+ || persisted.text !== text
10770
+ || persisted.author !== normalizedAuthor
10771
+ || String(persisted.submitted_author || persisted.author) !== submittedAuthor) {
10772
+ throw new TaskforceRuleError('Task comment identity is assigned to different content.', 409, 'TASK_COMMENT_IDENTITY_CONFLICT');
10773
+ }
10774
+ return this.getTask(id, normalizedWorkspaceId);
10775
+ }
10776
+ }
10656
10777
  const comment = {
10657
- id: this.generateEntityId('comment'),
10778
+ id: explicitCommentId || this.generateEntityId('comment'),
10658
10779
  author: normalizedAuthor,
10659
10780
  submittedAuthor,
10660
10781
  text,
@@ -10697,7 +10818,7 @@ export class TaskforceCore {
10697
10818
  if (options?.persistBackup !== false)
10698
10819
  this.persistBackup();
10699
10820
  const updated = this.getTask(id, normalizedWorkspaceId);
10700
- if (updated) {
10821
+ if (updated && options?.emitRealtime !== false) {
10701
10822
  this.emitRealtimeMutation({
10702
10823
  workspaceId: normalizedWorkspaceId,
10703
10824
  entityType: 'task',
@@ -15,6 +15,7 @@
15
15
  import type { DatabaseProvider } from '../storage/databaseAdapter.js';
16
16
  export type { TaskforceTheme } from '../utils/theme.js';
17
17
  import type { TaskforceTheme } from '../utils/theme.js';
18
+ import type { InternalUserFeatureKey } from '../shared/userFeatureGrants.js';
18
19
  export interface Comment {
19
20
  id: string;
20
21
  author: string;
@@ -344,6 +345,7 @@ export type SystemRole = 'system_admin' | 'user';
344
345
  export type PermissionMode = 'read-only' | 'read-write';
345
346
  export type AuthTokenPurpose = 'email_verification' | 'password_reset' | 'invite_accept';
346
347
  export type McpAccessTokenScope = 'tasks:read' | 'tasks:write' | 'workspace:read';
348
+ export type McpCloudToolProfile = 'default' | 'extended';
347
349
  export type UserAuthProvider = 'password' | 'google' | 'github' | 'apple';
348
350
  export interface UserAuthIdentity {
349
351
  id: string;
@@ -417,6 +419,7 @@ export interface SystemUserRecord {
417
419
  systemRole: SystemRole;
418
420
  betaAccess: boolean;
419
421
  disabled: boolean;
422
+ internalFeatureGrants: InternalUserFeatureKey[];
420
423
  planId?: string | null;
421
424
  planName?: string | null;
422
425
  planVersionId?: string | null;
@@ -613,6 +616,7 @@ export interface McpAccessTokenRecord {
613
616
  userEmail?: string | null;
614
617
  name: string;
615
618
  scopes: McpAccessTokenScope[];
619
+ toolProfile: McpCloudToolProfile;
616
620
  tokenPrefix: string;
617
621
  status: McpAccessTokenStatus;
618
622
  lastUsedAt?: string | null;
@@ -640,6 +644,7 @@ export interface McpAccessTokenAuthResult {
640
644
  workspaceId: string;
641
645
  userId: string;
642
646
  scopes: McpAccessTokenScope[];
647
+ toolProfile?: McpCloudToolProfile;
643
648
  status: McpAccessTokenStatus;
644
649
  }
645
650
  export interface McpAccessTokenInspectionResult {
@@ -649,6 +654,7 @@ export interface McpAccessTokenInspectionResult {
649
654
  userId: string;
650
655
  name: string;
651
656
  scopes: McpAccessTokenScope[];
657
+ toolProfile: McpCloudToolProfile;
652
658
  status: McpAccessTokenStatus;
653
659
  }
654
660
  export interface McpOAuthClientRecord {
@@ -670,6 +676,7 @@ export interface McpOAuthConnectorGrantRecord {
670
676
  workspaceId: string;
671
677
  userId: string;
672
678
  scopes: McpAccessTokenScope[];
679
+ toolProfile: McpCloudToolProfile;
673
680
  tokenPrefix: string;
674
681
  status: McpOAuthGrantStatus;
675
682
  lastUsedAt?: string | null;
@@ -692,6 +699,7 @@ export interface McpOAuthAccessTokenAuthResult {
692
699
  provider: McpOAuthProvider;
693
700
  productClientId?: string | null;
694
701
  scopes: McpAccessTokenScope[];
702
+ toolProfile?: McpCloudToolProfile;
695
703
  status: McpOAuthGrantStatus;
696
704
  aiProfileId?: string | null;
697
705
  aiProfileToken?: string | null;
@@ -6,6 +6,7 @@ export interface ReviewDocumentCommandComment {
6
6
  export interface ReviewDocumentCommandInput {
7
7
  workspaceId: string;
8
8
  assetId: string;
9
+ documentVersion: number | null;
9
10
  documentLabel?: string | null;
10
11
  sessionId?: string | null;
11
12
  title?: string | null;
@@ -43,7 +44,7 @@ export declare class DocumentReviewCommandError extends Error {
43
44
  }
44
45
  export interface ReviewDocumentCommandResult {
45
46
  session: DocumentReviewSession;
46
- sessionAction: 'reused' | 'created';
47
+ sessionAction: 'reused' | 'created' | 'created-for-current-version';
47
48
  postedCommentIds: string[];
48
49
  }
49
50
  export declare function createDocumentReviewCommandService(deps: DocumentReviewCommandServiceDependencies): {
@@ -29,8 +29,9 @@ export function createDocumentReviewCommandService(deps) {
29
29
  workspaceId: input.workspaceId,
30
30
  assetId: input.assetId,
31
31
  }).filter((candidate) => candidate.status === 'open');
32
- if (openSessions.length === 1) {
33
- session = openSessions[0];
32
+ const currentVersionSessions = openSessions.filter((candidate) => candidate.documentVersion === input.documentVersion);
33
+ if (currentVersionSessions.length === 1) {
34
+ session = currentVersionSessions[0];
34
35
  }
35
36
  else {
36
37
  session = deps.createSession({
@@ -40,7 +41,9 @@ export function createDocumentReviewCommandService(deps) {
40
41
  status: 'open',
41
42
  actorId: input.actorId,
42
43
  });
43
- sessionAction = 'created';
44
+ sessionAction = currentVersionSessions.length === 0 && openSessions.length > 0
45
+ ? 'created-for-current-version'
46
+ : 'created';
44
47
  }
45
48
  }
46
49
  const postedCommentIds = [];
@@ -28,6 +28,7 @@ export interface PersistedSyncWatermarks {
28
28
  taskRelationshipChangeKeys?: Map<string, string>;
29
29
  initiativeWatermarks: Map<string, string>;
30
30
  workstreamWatermarks: Map<string, string>;
31
+ planningIdentityWatermarks?: Map<string, string>;
31
32
  aiProfileWatermarks: Map<string, string>;
32
33
  aiProfileChangeKeys?: Map<string, string>;
33
34
  taskforceAgentWatermarks?: Map<string, string>;