@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
@@ -8,6 +8,7 @@ import { MCP_CLIENT_OPTIONS, buildCloudMcpClientIntegration, buildLocalMcpClient
8
8
  import { resolveTaskforceMcpBaseUrlFromBaseUrl } from '../../config/cloudEnvironment';
9
9
  import { TaxonomyManager } from './settings/TaxonomyManager';
10
10
  import { normalizeTaskforceApplicationBaseUrl } from '../../shared/taskDeepLinks.js';
11
+ import { TaskCard } from '../task/TaskCard';
11
12
  const THEME_ICON_MAP = {
12
13
  sun: Sun,
13
14
  wind: Wind,
@@ -15,19 +16,39 @@ const THEME_ICON_MAP = {
15
16
  sparkles: Sparkles,
16
17
  };
17
18
  const DEFAULT_MCP_TOKEN_SCOPES = ['tasks:read', 'tasks:write', 'workspace:read'];
19
+ const DEFAULT_MCP_TOOL_PROFILE_OPTIONS = [
20
+ { id: 'default', label: 'Standard', toolCount: 58 },
21
+ { id: 'extended', label: 'All cloud tools', toolCount: 85 },
22
+ ];
18
23
  const MCP_CONFIG_CODE_COLORS = {
19
24
  key: '#93c5fd',
20
25
  token: '#c084fc',
21
26
  punctuation: '#cbd5e1',
22
27
  text: '#f8fafc'
23
28
  };
29
+ const TASK_CARD_PREVIEW_INITIATIVE = {
30
+ id: 'task-card-settings-preview-initiative',
31
+ referenceNumber: 29,
32
+ referenceLabel: 'IN-29',
33
+ title: 'Task Experience',
34
+ description: null,
35
+ createdAt: '2026-08-14T12:00:00.000Z',
36
+ };
37
+ const TASK_CARD_PREVIEW_WORKSTREAM = {
38
+ id: 'task-card-settings-preview-workstream',
39
+ referenceNumber: 749,
40
+ referenceLabel: 'WS-749',
41
+ initiativeId: TASK_CARD_PREVIEW_INITIATIVE.id,
42
+ title: 'Task Card Polish',
43
+ description: null,
44
+ createdAt: '2026-08-14T12:00:00.000Z',
45
+ };
24
46
  export function TaskSettings(props) {
25
47
  const { settingsModel, onSectionChange, renderMode = 'full' } = props;
26
48
  const isMcpOnly = renderMode === 'mcp-only';
27
- const { currentTheme, globalTheme, themeUseGlobalDefault, keyShortcut, jsonBackupEnabled, globalJsonBackupEnabled, globalWeekStartsOn, locale = 'en-US', supportedLocales = ['en-US', 'es-419', 'pt-BR'], jsonBackupUseGlobalDefault, manualComplexityEnabled, checklistDropdownEnabled = true, showTaskCardStatusLabel = false, initialSection, onThemeChange, onSaveTheme, onSaveGlobalTheme, onResetProjectToGlobal, onKeyShortcutChange, onJsonBackupEnabledChange, onSaveGlobalJsonBackupEnabled, onSaveGlobalWeekStartsOn, onSaveLocale, onManualComplexityEnabledChange, onChecklistDropdownEnabledChange, onShowTaskCardStatusLabelChange, onSaveSettings, onShowFolderBrowserChange, onBrowserTargetChange, onFetchFolders, categories, pathValidation, taxonomyDisplayLabels, onUpdateCategory, onRemoveCategory, onSaveCategory, onAddPath, onRemovePath, onUpdateCategoryIcon, onUpdateCategoryColor, types, onSaveType, onRemoveType, onUpdateType, taxonomies, onUpdateTaxonomies, priorities, onUpdatePriorities, onAnalyzeSystemTaxonomyPack, onApplySystemTaxonomyPack, onUpdateTaxonomyDisplayLabels, projectRoot, projectName, mcpHostRoot, serverHostRoot, mcpScriptPath, tenantId, workspaceId, runtimeMode = 'local', cloudAuthBaseUrl = '', cloudMcpBaseUrl = '', fetchCloudAuthApi, checkLocalMcpCliHealth, getLocalUpdateStatus, workspaceSwitchingEnabled = false, currentWorkspaceRole = 'member', currentWorkspaceName = '', onDeleteWorkspace, onMcpHostRootChange, onOpenCloudAuth, isAuthenticated = false, setupState = null, buildInfo = null, onSaveSetupMode, onSaveWorkspaceProfile, initiativeTemplates = [], onRefreshInitiativeTemplates, onCreateInitiativeFromTemplate } = settingsModel;
49
+ const { currentTheme, globalTheme, themeUseGlobalDefault, keyShortcut, jsonBackupEnabled, globalJsonBackupEnabled, globalWeekStartsOn, locale = 'en-US', supportedLocales = ['en-US', 'es-419', 'pt-BR'], jsonBackupUseGlobalDefault, manualComplexityEnabled, checklistDropdownEnabled = true, showTaskCardStatusLabel = false, showTaskCardDescription = true, showTaskCardAttachments = true, showTaskCardChecklistProgress = true, showTaskCardLatestActivity = true, tintTaskCardActivityBackground = false, initialSection, onThemeChange, onSaveTheme, onSaveGlobalTheme, onUseGlobalThemeDefault, onKeyShortcutChange, onJsonBackupEnabledChange, onSaveGlobalJsonBackupEnabled, onUseGlobalJsonBackupDefault, onSaveGlobalWeekStartsOn, onSaveLocale, onManualComplexityEnabledChange, onChecklistDropdownEnabledChange, onShowTaskCardStatusLabelChange, onShowTaskCardDescriptionChange, onShowTaskCardAttachmentsChange, onShowTaskCardChecklistProgressChange, onShowTaskCardLatestActivityChange, onTintTaskCardActivityBackgroundChange, onSaveSettings, onShowFolderBrowserChange, onBrowserTargetChange, onFetchFolders, categories, pathValidation, taxonomyDisplayLabels, onUpdateCategory, onRemoveCategory, onSaveCategory, onAddPath, onRemovePath, onUpdateCategoryIcon, onUpdateCategoryColor, types, onSaveType, onRemoveType, onUpdateType, taxonomies, onUpdateTaxonomies, priorities, onUpdatePriorities, onAnalyzeSystemTaxonomyPack, onApplySystemTaxonomyPack, onUpdateTaxonomyDisplayLabels, projectRoot, projectName, mcpHostRoot, serverHostRoot, mcpScriptPath, tenantId, workspaceId, runtimeMode = 'local', cloudAuthBaseUrl = '', cloudMcpBaseUrl = '', fetchCloudAuthApi, checkLocalMcpCliHealth, getLocalUpdateStatus, workspaceSwitchingEnabled = false, currentWorkspaceRole = 'member', currentWorkspaceName = '', onDeleteWorkspace, onMcpHostRootChange, onOpenCloudAuth, isAuthenticated = false, setupState = null, buildInfo = null, onSaveSetupMode, onSaveWorkspaceProfile, initiativeTemplates = [], onRefreshInitiativeTemplates, onCreateInitiativeFromTemplate } = settingsModel;
28
50
  const showJsonBackupSettings = runtimeMode !== 'cloud';
29
51
  const [settingsFeedback, setSettingsFeedback] = useState(null);
30
- const [setupMode, setSetupMode] = useState(() => setupState?.mode === 'operations' ? 'operations' : 'core');
31
52
  const [workspaceDisplayName, setWorkspaceDisplayName] = useState(() => String(setupState?.workspace?.name || '').trim());
32
53
  const [workspaceDescription, setWorkspaceDescription] = useState(() => String(setupState?.workspace?.description || ''));
33
54
  const [selectedInitiativeTemplateId, setSelectedInitiativeTemplateId] = useState('');
@@ -38,6 +59,53 @@ export function TaskSettings(props) {
38
59
  const [generalScopeTab, setGeneralScopeTab] = useState(() => {
39
60
  return 'project';
40
61
  });
62
+ const taskCardPreviewTask = useMemo(() => ({
63
+ id: 'task-card-settings-preview',
64
+ referenceNumber: 1590,
65
+ referenceLabel: 'T-1590',
66
+ title: 'Polish Task card appearance',
67
+ description: 'Make card preferences easy to understand at a glance.',
68
+ category: categories.find((option) => !option.disabled)?.value || 'general',
69
+ type: types[0]?.value || 'feature',
70
+ priority: priorities.find((option) => Number(option.value) === 2)?.value ?? priorities[0]?.value ?? 2,
71
+ complexity: 3,
72
+ status: 'in-progress',
73
+ workstreamId: TASK_CARD_PREVIEW_WORKSTREAM.id,
74
+ createdAt: '2026-08-14T12:00:00.000Z',
75
+ attachments: [{
76
+ path: '/task-card-preview.md',
77
+ displayName: 'task-card-style-guide.md',
78
+ originalFilename: 'task-card-style-guide.md',
79
+ linkRole: 'attachment',
80
+ }],
81
+ commentCount: 2,
82
+ checklistCount: 3,
83
+ completedChecklistCount: 1,
84
+ latestActivity: {
85
+ id: 'task-card-settings-preview-activity',
86
+ type: 'event',
87
+ timestamp: '2026-08-14T12:30:00.000Z',
88
+ event: {
89
+ action: 'task-status-changed',
90
+ actor: 'Cardsmith',
91
+ actorType: 'ai',
92
+ actorProfile: {
93
+ id: 'task-card-settings-preview-actor',
94
+ kind: 'ai',
95
+ label: 'Cardsmith',
96
+ username: 'cardsmith',
97
+ icon: 'Bot',
98
+ color: 'violet-500',
99
+ isNamed: true,
100
+ },
101
+ details: {
102
+ changes: {
103
+ status: { from: 'task', to: 'in-progress' },
104
+ },
105
+ },
106
+ },
107
+ },
108
+ }), [categories, priorities, types]);
41
109
  useEffect(() => {
42
110
  if (initiativeTemplates.length > 0 && !selectedInitiativeTemplateId) {
43
111
  setSelectedInitiativeTemplateId(initiativeTemplates[0].id);
@@ -49,13 +117,31 @@ export function TaskSettings(props) {
49
117
  const timer = setTimeout(() => setSettingsFeedback(null), 2500);
50
118
  return () => clearTimeout(timer);
51
119
  }, [settingsFeedback]);
52
- useEffect(() => {
53
- setSetupMode(setupState?.mode === 'operations' ? 'operations' : 'core');
54
- }, [setupState?.mode]);
120
+ const reportTaskCardPreferenceResult = (success, errorMessage) => {
121
+ setSettingsFeedback(success ? null : { type: 'error', message: errorMessage });
122
+ };
55
123
  useEffect(() => {
56
124
  setWorkspaceDisplayName(String(setupState?.workspace?.name || '').trim());
57
125
  setWorkspaceDescription(String(setupState?.workspace?.description || ''));
58
126
  }, [setupState?.workspace?.name, setupState?.workspace?.description]);
127
+ const resolvedWorkspaceId = String(workspaceId || setupState?.workspaceId || setupState?.workspace?.id || '').trim();
128
+ const handleCopyWorkspaceId = async () => {
129
+ if (!resolvedWorkspaceId) {
130
+ setSettingsFeedback({ type: 'error', message: 'Workspace ID is unavailable.' });
131
+ return;
132
+ }
133
+ if (!navigator.clipboard?.writeText) {
134
+ setSettingsFeedback({ type: 'error', message: 'Clipboard copy is unavailable in this browser.' });
135
+ return;
136
+ }
137
+ try {
138
+ await navigator.clipboard.writeText(resolvedWorkspaceId);
139
+ setSettingsFeedback({ type: 'success', message: 'Workspace ID copied.' });
140
+ }
141
+ catch {
142
+ setSettingsFeedback({ type: 'error', message: 'Failed to copy workspace ID.' });
143
+ }
144
+ };
59
145
  const handleThemeChange = async (theme) => {
60
146
  onThemeChange(theme);
61
147
  const success = await onSaveTheme(theme);
@@ -86,33 +172,42 @@ export function TaskSettings(props) {
86
172
  const [mcpTokensLoading, setMcpTokensLoading] = useState(false);
87
173
  const [mcpTokensError, setMcpTokensError] = useState(null);
88
174
  const [mcpActionBusyId, setMcpActionBusyId] = useState(null);
175
+ const [selectedMcpClient, setSelectedMcpClient] = useState('general');
176
+ const selectedMcpClientLabel = useMemo(() => {
177
+ const label = MCP_CLIENT_OPTIONS.find((option) => option.id === selectedMcpClient)?.label || 'General';
178
+ return selectedMcpClient === 'general' ? 'General MCP' : label;
179
+ }, [selectedMcpClient]);
89
180
  const defaultTokenName = useMemo(() => {
90
- const label = String(currentWorkspaceName
181
+ const workspaceLabel = String(currentWorkspaceName
91
182
  || setupState?.workspace?.name
92
183
  || projectName
93
184
  || workspaceId
94
- || 'Taskforce Workspace').trim();
95
- return `${label} MCP`;
96
- }, [currentWorkspaceName, setupState?.workspace?.name, projectName, workspaceId]);
185
+ || 'Taskforce Workspace').trim() || 'Taskforce Workspace';
186
+ return `${selectedMcpClientLabel} — ${workspaceLabel}`;
187
+ }, [currentWorkspaceName, setupState?.workspace?.name, projectName, selectedMcpClientLabel, workspaceId]);
97
188
  const [newTokenName, setNewTokenName] = useState(defaultTokenName);
189
+ const [tokenNameCustomized, setTokenNameCustomized] = useState(false);
98
190
  const [newTokenExpiresAt, setNewTokenExpiresAt] = useState('');
99
191
  const [mcpTokenIssueNotice, setMcpTokenIssueNotice] = useState(null);
100
192
  const [mcpConfigNotice, setMcpConfigNotice] = useState(null);
101
193
  const [mcpTokenListNotice, setMcpTokenListNotice] = useState(null);
102
194
  const [generatedTokenValue, setGeneratedTokenValue] = useState(null);
103
- const [selectedMcpClient, setSelectedMcpClient] = useState('general');
104
195
  const [mcpConnectionBusy, setMcpConnectionBusy] = useState(false);
105
196
  const [mcpConnectionResult, setMcpConnectionResult] = useState(null);
106
197
  const [mcpConnectorGrants, setMcpConnectorGrants] = useState([]);
107
198
  const [mcpConnectorsLoading, setMcpConnectorsLoading] = useState(false);
108
199
  const [mcpConnectorsError, setMcpConnectorsError] = useState(null);
109
200
  const [mcpConnectorBusyId, setMcpConnectorBusyId] = useState(null);
201
+ const [mcpToolProfileOptions, setMcpToolProfileOptions] = useState(DEFAULT_MCP_TOOL_PROFILE_OPTIONS);
202
+ const [mcpProfileNotice, setMcpProfileNotice] = useState(null);
203
+ const canManageMcpToolProfiles = currentWorkspaceRole === 'owner' || currentWorkspaceRole === 'admin';
110
204
  useEffect(() => {
111
205
  setSelectedMcpMode(defaultMcpMode);
112
206
  }, [defaultMcpMode]);
113
207
  useEffect(() => {
114
- setNewTokenName((current) => current.trim().length > 0 ? current : defaultTokenName);
115
- }, [defaultTokenName]);
208
+ if (!tokenNameCustomized)
209
+ setNewTokenName(defaultTokenName);
210
+ }, [defaultTokenName, tokenNameCustomized]);
116
211
  useEffect(() => {
117
212
  if (!mcpTokenIssueNotice)
118
213
  return;
@@ -508,6 +603,8 @@ export function TaskSettings(props) {
508
603
  return;
509
604
  }
510
605
  setMcpTokens(Array.isArray(payload?.items) ? payload.items : []);
606
+ if (Array.isArray(payload?.profileOptions))
607
+ setMcpToolProfileOptions(payload.profileOptions);
511
608
  }
512
609
  catch {
513
610
  setMcpTokensError('Failed to load MCP tokens.');
@@ -532,6 +629,8 @@ export function TaskSettings(props) {
532
629
  return;
533
630
  }
534
631
  setMcpConnectorGrants(Array.isArray(payload?.items) ? payload.items : []);
632
+ if (Array.isArray(payload?.profileOptions))
633
+ setMcpToolProfileOptions(payload.profileOptions);
535
634
  }
536
635
  catch {
537
636
  setMcpConnectorsError('Failed to load MCP connectors.');
@@ -567,7 +666,7 @@ export function TaskSettings(props) {
567
666
  }
568
667
  setGeneratedTokenValue(String(payload?.token || ''));
569
668
  setMcpConnectionResult(null);
570
- setNewTokenName(defaultTokenName);
669
+ setTokenNameCustomized(false);
571
670
  setNewTokenExpiresAt('');
572
671
  setMcpTokens((current) => {
573
672
  const next = payload?.record ? [payload.record, ...current.filter((item) => item.id !== payload.record.id)] : current;
@@ -701,6 +800,8 @@ export function TaskSettings(props) {
701
800
  workspaceName: typeof result?.workspaceName === 'string' ? String(result.workspaceName) : '',
702
801
  workspaceId: typeof result?.workspaceId === 'string' ? String(result.workspaceId) : '',
703
802
  endpoint: typeof result?.endpoint === 'string' ? String(result.endpoint) : cloudMcpEndpoint,
803
+ toolProfile: result?.toolProfile === 'extended' ? 'extended' : 'default',
804
+ toolCount: Number.isFinite(result?.toolCount) ? Number(result.toolCount) : undefined,
704
805
  });
705
806
  }
706
807
  catch {
@@ -743,6 +844,40 @@ export function TaskSettings(props) {
743
844
  setMcpConnectorBusyId(null);
744
845
  }
745
846
  };
847
+ const handleMcpToolProfileChange = async (kind, id, toolProfile) => {
848
+ const busyId = `profile:${kind}:${id}`;
849
+ setMcpActionBusyId(busyId);
850
+ setMcpConnectorBusyId(busyId);
851
+ setMcpProfileNotice(null);
852
+ try {
853
+ const res = await fetchCloudAuthApi(`/api/taskforce/settings/mcp/${kind}/${encodeURIComponent(id)}/tool-profile`, {
854
+ method: 'PATCH',
855
+ credentials: 'include',
856
+ headers: { 'Content-Type': 'application/json' },
857
+ body: JSON.stringify({ toolProfile }),
858
+ });
859
+ const payload = await res.json().catch(() => ({}));
860
+ if (!res.ok) {
861
+ setMcpProfileNotice({ type: 'error', message: String(payload?.error || 'Failed to change MCP tool access.') });
862
+ return;
863
+ }
864
+ const record = payload?.record;
865
+ if (kind === 'tokens') {
866
+ setMcpTokens((current) => current.map((item) => item.id === record?.id ? record : item));
867
+ }
868
+ else {
869
+ setMcpConnectorGrants((current) => current.map((item) => item.id === record?.id ? record : item));
870
+ }
871
+ setMcpProfileNotice({ type: 'success', message: 'Tool access updated. Restart or reconnect the client, then refresh its MCP tools. In ChatGPT, refresh actions, review additions, enable the intended actions, and publish.' });
872
+ }
873
+ catch {
874
+ setMcpProfileNotice({ type: 'error', message: 'Failed to change MCP tool access.' });
875
+ }
876
+ finally {
877
+ setMcpActionBusyId(null);
878
+ setMcpConnectorBusyId(null);
879
+ }
880
+ };
746
881
  useEffect(() => {
747
882
  if (!canUseCloudMcp)
748
883
  return;
@@ -831,7 +966,13 @@ export function TaskSettings(props) {
831
966
  setActiveTab(tab);
832
967
  onSectionChange?.(section);
833
968
  };
834
- const renderProjectThemeControls = () => (_jsxs("div", { className: styles.settingGroup, children: [_jsx("h3", { className: `${styles.settingTitle} tf-heading-section`, children: "Theme" }), _jsx("div", { className: styles.buttonGrid, children: TASKFORCE_THEME_OPTIONS.map((themeOption) => renderThemeButton(themeOption, currentTheme, handleThemeChange)) })] }));
969
+ const renderProjectThemeControls = () => (_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.settingTitleRow, children: [_jsx("h3", { className: `${styles.settingTitle} tf-heading-section`, children: "Theme" }), !themeUseGlobalDefault && (_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: async () => {
970
+ const success = await onUseGlobalThemeDefault();
971
+ setSettingsFeedback({
972
+ type: success ? 'success' : 'error',
973
+ message: success ? 'Using global theme default.' : 'Failed to use global theme default.'
974
+ });
975
+ }, children: "Use global theme" }))] }), _jsx("div", { className: styles.buttonGrid, children: TASKFORCE_THEME_OPTIONS.map((themeOption) => renderThemeButton(themeOption, currentTheme, handleThemeChange)) })] }));
835
976
  const renderGlobalThemeControls = () => (_jsxs("div", { className: styles.settingGroup, children: [_jsx("h3", { className: `${styles.settingTitle} tf-heading-section`, children: "Theme Defaults" }), _jsx("div", { className: styles.buttonGrid, children: TASKFORCE_THEME_OPTIONS.map((themeOption) => renderThemeButton(themeOption, globalTheme, async (theme) => {
836
977
  const success = await onSaveGlobalTheme(theme);
837
978
  setSettingsFeedback({
@@ -848,30 +989,27 @@ export function TaskSettings(props) {
848
989
  message: success ? 'Checklist dropdown setting saved.' : 'Failed to save checklist dropdown setting.'
849
990
  });
850
991
  }, disabled: !onChecklistDropdownEnabledChange }), _jsx("span", { children: "Enable checklist dropdown in task form" })] })] }));
851
- return (_jsx("div", { className: `${styles.settingsTab} ${isMcpOnly ? styles.settingsTabMcpOnly : ''}`.trim(), children: _jsxs("div", { className: `${styles.settingsLayout} ${isMcpOnly ? styles.settingsLayoutMcpOnly : ''}`.trim(), children: [!isMcpOnly && (_jsxs("aside", { className: styles.settingsSidebar, children: [_jsx("div", { className: styles.settingsSidebarHeader, children: "Sections" }), _jsxs("div", { className: `${styles.settingsSidebarNav} tf-scrollbar tf-scrollbar--track-transparent tf-scrollbar--compact`, children: [settingsNavItems.filter((item) => item.key === 'general').map((item) => (_jsxs("button", { className: `${styles.settingsSidebarBtn} ${activeTab === item.key ? styles.settingsSidebarBtnActive : ''}`, onClick: () => selectTab(item.key, item.section), children: [item.icon, _jsx("span", { children: item.label })] }, item.key))), _jsxs("div", { className: styles.settingsSidebarGroup, children: [_jsxs("button", { className: `${styles.settingsSidebarBtn} ${styles.settingsSidebarGroupBtn} ${(activeTab === 'appearanceApplication' || activeTab === 'appearanceTaskCards' || activeTab === 'appearanceTaskForms') ? styles.settingsSidebarBtnActive : ''}`, onClick: () => setAppearanceExpanded((current) => !current), "aria-expanded": appearanceExpanded, "aria-controls": "settings-appearance-nav", children: [_jsx(Sparkles, { size: 14 }), _jsx("span", { className: styles.settingsSidebarGroupLabel, children: "Appearance" }), _jsx("span", { className: styles.settingsSidebarGroupChevron, children: appearanceExpanded ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 }) })] }), appearanceExpanded && (_jsx("div", { id: "settings-appearance-nav", className: styles.settingsSidebarSubnav, children: appearanceNavItems.map((item) => (_jsx("button", { className: `${styles.settingsSidebarSubBtn} ${activeTab === item.key ? styles.settingsSidebarBtnActive : ''}`, onClick: () => selectTab(item.key, item.section), children: _jsx("span", { children: item.label }) }, item.key))) }))] }), settingsNavItems.filter((item) => item.key !== 'general').map((item) => (_jsxs("button", { className: `${styles.settingsSidebarBtn} ${activeTab === item.key ? styles.settingsSidebarBtnActive : ''}`, onClick: () => selectTab(item.key, item.section), children: [item.icon, _jsx("span", { children: item.label })] }, item.key)))] })] })), _jsxs("div", { className: styles.settingsContent, children: [settingsFeedback && (_jsxs("div", { className: `${styles.settingsToast} ${settingsFeedback.type === 'success' ? styles.settingsToastSuccess : styles.settingsToastError}`, children: [settingsFeedback.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), _jsx("span", { children: settingsFeedback.message })] })), activeTab === 'general' && (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: `${styles.settingsTabs} tf-scrollbar tf-scrollbar--track-transparent tf-scrollbar--compact`, children: [_jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'project' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('project'), children: "Project" }), _jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'global' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('global'), children: "Global" })] }), generalScopeTab === 'project' && (_jsx("div", { className: styles.pathInputGroup, style: { justifyContent: 'flex-end' }, children: _jsx("button", { onClick: async () => {
852
- const confirmed = window.confirm('Reset project Theme and Backups to global defaults?');
853
- if (!confirmed)
854
- return;
855
- const success = await onResetProjectToGlobal();
856
- setSettingsFeedback({
857
- type: success ? 'success' : 'error',
858
- message: success ? 'Project settings reset to global.' : 'Failed to reset project settings.'
859
- });
860
- }, className: styles.copyBtn, children: "Reset to Global" }) }))] }), generalScopeTab === 'project' && (_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.pathInputGroup, children: [_jsxs("label", { className: styles.label, style: { minWidth: '110px' }, children: [setupMode === 'operations' ? 'Mission' : 'Project', " name:"] }), _jsx("input", { className: styles.input, type: "text", value: workspaceDisplayName, onChange: (event) => setWorkspaceDisplayName(event.target.value), placeholder: setupMode === 'operations' ? 'Mission name' : 'Project name' })] }), _jsxs("div", { className: styles.pathInputGroup, children: [_jsx("label", { className: styles.label, style: { minWidth: '110px' }, children: "Description:" }), _jsx("textarea", { className: styles.textarea, value: workspaceDescription, onChange: (event) => setWorkspaceDescription(event.target.value), placeholder: setupMode === 'operations' ? 'Mission description (optional)' : 'Project description (optional)', rows: 3 })] }), _jsx("div", { className: styles.pathInputGroup, style: { justifyContent: 'flex-end' }, children: _jsx("button", { onClick: async () => {
861
- if (!onSaveWorkspaceProfile)
862
- return;
863
- const result = await onSaveWorkspaceProfile({
864
- workspaceId: setupState?.workspaceId,
865
- name: workspaceDisplayName,
866
- description: workspaceDescription
867
- });
868
- setSettingsFeedback({
869
- type: result.success ? 'success' : 'error',
870
- message: result.success
871
- ? `${setupMode === 'operations' ? 'Mission' : 'Project'} profile saved.`
872
- : (result.error || 'Failed to save workspace profile.')
873
- });
874
- }, className: styles.copyBtn, disabled: !onSaveWorkspaceProfile, children: "Save" }) })] })), generalScopeTab === 'project' && (_jsx("div", { className: styles.settingGroup, children: showJsonBackupSettings && (_jsxs(_Fragment, { children: [_jsx("h3", { className: styles.settingTitle, children: "Backup" }), _jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: jsonBackupEnabled, onChange: async (e) => {
992
+ return (_jsx("div", { className: `${styles.settingsTab} ${isMcpOnly ? styles.settingsTabMcpOnly : ''}`.trim(), children: _jsxs("div", { className: `${styles.settingsLayout} ${isMcpOnly ? styles.settingsLayoutMcpOnly : ''}`.trim(), children: [!isMcpOnly && (_jsxs("aside", { className: styles.settingsSidebar, children: [_jsx("div", { className: styles.settingsSidebarHeader, children: "Sections" }), _jsxs("div", { className: `${styles.settingsSidebarNav} tf-scrollbar tf-scrollbar--track-transparent tf-scrollbar--compact`, children: [settingsNavItems.filter((item) => item.key === 'general').map((item) => (_jsxs("button", { className: `${styles.settingsSidebarBtn} ${activeTab === item.key ? styles.settingsSidebarBtnActive : ''}`, onClick: () => selectTab(item.key, item.section), children: [item.icon, _jsx("span", { children: item.label })] }, item.key))), _jsxs("div", { className: styles.settingsSidebarGroup, children: [_jsxs("button", { className: `${styles.settingsSidebarBtn} ${styles.settingsSidebarGroupBtn} ${(activeTab === 'appearanceApplication' || activeTab === 'appearanceTaskCards' || activeTab === 'appearanceTaskForms') ? styles.settingsSidebarBtnActive : ''}`, onClick: () => setAppearanceExpanded((current) => !current), "aria-expanded": appearanceExpanded, "aria-controls": "settings-appearance-nav", children: [_jsx(Sparkles, { size: 14 }), _jsx("span", { className: styles.settingsSidebarGroupLabel, children: "Appearance" }), _jsx("span", { className: styles.settingsSidebarGroupChevron, children: appearanceExpanded ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 }) })] }), appearanceExpanded && (_jsx("div", { id: "settings-appearance-nav", className: styles.settingsSidebarSubnav, children: appearanceNavItems.map((item) => (_jsx("button", { className: `${styles.settingsSidebarSubBtn} ${activeTab === item.key ? styles.settingsSidebarBtnActive : ''}`, onClick: () => selectTab(item.key, item.section), children: _jsx("span", { children: item.label }) }, item.key))) }))] }), settingsNavItems.filter((item) => item.key !== 'general').map((item) => (_jsxs("button", { className: `${styles.settingsSidebarBtn} ${activeTab === item.key ? styles.settingsSidebarBtnActive : ''}`, onClick: () => selectTab(item.key, item.section), children: [item.icon, _jsx("span", { children: item.label })] }, item.key)))] })] })), _jsxs("div", { className: styles.settingsContent, children: [settingsFeedback && (_jsxs("div", { className: `${styles.settingsToast} ${settingsFeedback.type === 'success' ? styles.settingsToastSuccess : styles.settingsToastError}`, role: settingsFeedback.type === 'success' ? 'status' : 'alert', "aria-live": settingsFeedback.type === 'success' ? 'polite' : 'assertive', children: [settingsFeedback.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), _jsx("span", { children: settingsFeedback.message })] })), activeTab === 'general' && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.settingGroup, children: _jsxs("div", { className: `${styles.settingsTabs} tf-scrollbar tf-scrollbar--track-transparent tf-scrollbar--compact`, children: [_jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'project' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('project'), children: "Project" }), _jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'global' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('global'), children: "Global" })] }) }), generalScopeTab === 'project' && (_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.workspaceIdentity, children: [_jsx("span", { className: styles.label, children: "Workspace ID:" }), _jsxs("div", { className: styles.workspaceIdentityValueRow, children: [_jsx("code", { className: styles.workspaceIdentityValue, children: resolvedWorkspaceId || 'Unavailable' }), _jsx("button", { type: "button", className: "tf-control-icon tf-control-icon-compact", onClick: () => { void handleCopyWorkspaceId(); }, disabled: !resolvedWorkspaceId, "aria-label": "Copy workspace ID", title: "Copy workspace ID", children: _jsx(Copy, { size: 14, "aria-hidden": "true" }) })] })] }), _jsxs("div", { className: styles.workspaceProfileForm, children: [_jsx("label", { htmlFor: "workspace-name", className: styles.label, children: "Workspace name:" }), _jsx("input", { id: "workspace-name", className: styles.input, type: "text", value: workspaceDisplayName, onChange: (event) => setWorkspaceDisplayName(event.target.value), placeholder: "Workspace name" }), _jsx("label", { htmlFor: "workspace-description", className: `${styles.label} ${styles.workspaceProfileTextareaLabel}`, children: "Description:" }), _jsx("textarea", { id: "workspace-description", className: styles.textarea, value: workspaceDescription, onChange: (event) => setWorkspaceDescription(event.target.value), placeholder: "Describe this workspace (optional)", rows: 3 }), _jsx("div", { className: styles.workspaceProfileActions, children: _jsx("button", { type: "button", onClick: async () => {
993
+ if (!onSaveWorkspaceProfile)
994
+ return;
995
+ const result = await onSaveWorkspaceProfile({
996
+ workspaceId: setupState?.workspaceId,
997
+ name: workspaceDisplayName,
998
+ description: workspaceDescription
999
+ });
1000
+ setSettingsFeedback({
1001
+ type: result.success ? 'success' : 'error',
1002
+ message: result.success
1003
+ ? 'Workspace profile saved.'
1004
+ : (result.error || 'Failed to save workspace profile.')
1005
+ });
1006
+ }, className: "tf-button-primary tf-button-compact", disabled: !onSaveWorkspaceProfile, children: "Save" }) })] })] })), generalScopeTab === 'project' && (_jsx("div", { className: styles.settingGroup, children: showJsonBackupSettings && (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.settingTitleRow, children: [_jsx("h3", { className: styles.settingTitle, children: "Backup" }), !jsonBackupUseGlobalDefault && (_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: async () => {
1007
+ const success = await onUseGlobalJsonBackupDefault();
1008
+ setSettingsFeedback({
1009
+ type: success ? 'success' : 'error',
1010
+ message: success ? 'Using global backup default.' : 'Failed to use global backup default.'
1011
+ });
1012
+ }, children: "Use global backup" }))] }), _jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: jsonBackupEnabled, onChange: async (e) => {
875
1013
  const success = await onJsonBackupEnabledChange(e.target.checked);
876
1014
  setSettingsFeedback({
877
1015
  type: success ? 'success' : 'error',
@@ -907,7 +1045,7 @@ export function TaskSettings(props) {
907
1045
  type: success ? 'success' : 'error',
908
1046
  message: success ? 'Global shortcut saved.' : 'Failed to save global shortcut.'
909
1047
  });
910
- }, className: `${styles.saveSettingsBtn} ${styles.saveSettingsBtnWrapper}`, children: "Save" })] }), _jsxs("p", { className: styles.settingHelper, children: ["Supported modifiers: Alt, Option, Ctrl, Shift, Meta (Cmd). Example: ", _jsx("code", { children: "Alt+T" }), " or ", _jsx("code", { children: "Ctrl+Shift+L" }), "."] })] })] })), generalScopeTab === 'project' && runtimeMode === 'cloud' && (_jsxs("div", { className: styles.settingGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Danger Zone" }), !workspaceSwitchingEnabled ? (_jsx("p", { className: styles.settingHelper, children: "Workspace deletion is available in cloud runtime only." })) : !isAuthenticated ? (_jsx("p", { className: styles.settingHelper, children: "Sign in to manage workspace deletion." })) : currentWorkspaceRole !== 'owner' ? (_jsx("p", { className: styles.settingHelper, children: "Only workspace owners can delete a workspace." })) : (_jsx("div", { className: styles.pathInputGroup, children: _jsxs("button", { className: styles.destructiveBtn, onClick: async () => {
1048
+ }, className: `${styles.saveSettingsBtn} ${styles.saveSettingsBtnWrapper}`, children: "Save" })] }), _jsxs("p", { className: styles.settingHelper, children: ["Supported modifiers: Alt, Option, Ctrl, Shift, Meta (Cmd). Example: ", _jsx("code", { children: "Alt+T" }), " or ", _jsx("code", { children: "Ctrl+Shift+L" }), "."] })] })] })), generalScopeTab === 'project' && runtimeMode === 'cloud' && (_jsxs("div", { className: styles.settingGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Danger Zone" }), !workspaceSwitchingEnabled ? (_jsx("p", { className: styles.settingHelper, children: "Workspace deletion is available in cloud runtime only." })) : !isAuthenticated ? (_jsx("p", { className: styles.settingHelper, children: "Sign in to manage workspace deletion." })) : currentWorkspaceRole !== 'owner' ? (_jsx("p", { className: styles.settingHelper, children: "Only workspace owners can delete a workspace." })) : (_jsx("div", { className: styles.pathInputGroup, children: _jsxs("button", { className: "tf-button-destructive tf-button-compact", onClick: async () => {
911
1049
  if (!onDeleteWorkspace)
912
1050
  return;
913
1051
  const normalizedWorkspaceId = String(workspaceId || '').trim();
@@ -944,15 +1082,37 @@ export function TaskSettings(props) {
944
1082
  ? `Workspace deleted with ${warningCount} cleanup warning(s).`
945
1083
  : 'Workspace deleted.'
946
1084
  });
947
- }, disabled: !onDeleteWorkspace, children: [_jsx(Trash2, { size: 14, style: { marginRight: 8 } }), "Delete Workspace"] }) }))] }))] })), activeTab === 'appearanceApplication' && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.settingGroup, children: _jsxs("div", { className: `${styles.settingsTabs} tf-scrollbar tf-scrollbar--track-transparent tf-scrollbar--compact`, children: [_jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'project' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('project'), children: "Project" }), _jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'global' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('global'), children: "Global" })] }) }), generalScopeTab === 'project' ? renderProjectThemeControls() : renderGlobalThemeControls()] })), activeTab === 'appearanceTaskCards' && (_jsxs("div", { className: styles.settingGroup, children: [_jsx("h3", { className: `${styles.settingTitle} tf-heading-section`, children: "Task Cards" }), _jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: showTaskCardStatusLabel, onChange: async (e) => {
948
- if (!onShowTaskCardStatusLabelChange)
949
- return;
950
- const success = await onShowTaskCardStatusLabelChange(e.target.checked);
951
- setSettingsFeedback({
952
- type: success ? 'success' : 'error',
953
- message: success ? 'Task card status label setting saved.' : 'Failed to save task card status label setting.'
954
- });
955
- }, disabled: !onShowTaskCardStatusLabelChange }), _jsx("span", { children: "Show status label" })] })] })), activeTab === 'appearanceTaskForms' && renderTaskFormsControls(), activeTab === 'initiatives' && (_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.settingTitleRow, children: [_jsx("h3", { className: styles.settingTitle, children: "Initiative Templates" }), _jsx("button", { className: styles.copyBtn, onClick: () => { void onRefreshInitiativeTemplates?.(); }, children: "Refresh" })] }), _jsx("p", { className: `${styles.settingsHint} ${styles.marginBottom12}`, children: "Create launch, migration, or incident initiatives from reusable templates." }), _jsxs("div", { className: styles.exportItem, children: [_jsx("label", { className: styles.label, children: "Template" }), _jsx("select", { className: styles.input, value: selectedInitiativeTemplateId, onChange: (e) => {
1085
+ }, disabled: !onDeleteWorkspace, children: [_jsx(Trash2, { size: 14, "aria-hidden": "true" }), "Delete Workspace"] }) }))] }))] })), activeTab === 'appearanceApplication' && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.settingGroup, children: _jsxs("div", { className: `${styles.settingsTabs} tf-scrollbar tf-scrollbar--track-transparent tf-scrollbar--compact`, children: [_jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'project' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('project'), children: "Project" }), _jsx("button", { className: `${styles.settingsTabBtn} ${generalScopeTab === 'global' ? styles.settingsTabBtnActive : ''}`, onClick: () => setGeneralScopeTab('global'), children: "Global" })] }) }), generalScopeTab === 'project' ? renderProjectThemeControls() : renderGlobalThemeControls()] })), activeTab === 'appearanceTaskCards' && (_jsxs("div", { className: styles.taskCardSettingsLayout, children: [_jsxs("div", { className: styles.settingGroup, children: [_jsx("h3", { className: `${styles.settingTitle} tf-heading-section`, children: "Task Cards" }), _jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: showTaskCardStatusLabel, onChange: async (e) => {
1086
+ if (!onShowTaskCardStatusLabelChange)
1087
+ return;
1088
+ const success = await onShowTaskCardStatusLabelChange(e.target.checked);
1089
+ reportTaskCardPreferenceResult(success, 'Failed to save task card status label setting.');
1090
+ }, disabled: !onShowTaskCardStatusLabelChange }), _jsx("span", { children: "Show status label" })] }), _jsxs("div", { className: styles.taskCardSettingWithHelp, children: [_jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: runtimeMode !== 'cloud' && showTaskCardDescription, onChange: async (e) => {
1091
+ if (!onShowTaskCardDescriptionChange)
1092
+ return;
1093
+ const success = await onShowTaskCardDescriptionChange(e.target.checked);
1094
+ reportTaskCardPreferenceResult(success, 'Failed to save task card description setting.');
1095
+ }, disabled: runtimeMode === 'cloud' || !onShowTaskCardDescriptionChange, "aria-describedby": runtimeMode === 'cloud' ? 'task-card-description-cloud-help' : undefined }), _jsx("span", { children: "Show description" })] }), runtimeMode === 'cloud' && (_jsx("span", { id: "task-card-description-cloud-help", className: styles.taskCardSettingHelp, children: "Unavailable in cloud to keep task collections fast." }))] }), _jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: showTaskCardAttachments, onChange: async (e) => {
1096
+ if (!onShowTaskCardAttachmentsChange)
1097
+ return;
1098
+ const success = await onShowTaskCardAttachmentsChange(e.target.checked);
1099
+ reportTaskCardPreferenceResult(success, 'Failed to save task card attachments setting.');
1100
+ }, disabled: !onShowTaskCardAttachmentsChange }), _jsx("span", { children: "Show attachments" })] }), _jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: showTaskCardChecklistProgress, onChange: async (e) => {
1101
+ if (!onShowTaskCardChecklistProgressChange)
1102
+ return;
1103
+ const success = await onShowTaskCardChecklistProgressChange(e.target.checked);
1104
+ reportTaskCardPreferenceResult(success, 'Failed to save task card checklist progress setting.');
1105
+ }, disabled: !onShowTaskCardChecklistProgressChange }), _jsx("span", { children: "Show checklist progress" })] }), _jsxs("label", { className: styles.archiveToggle, children: [_jsx("input", { type: "checkbox", checked: showTaskCardLatestActivity, onChange: async (e) => {
1106
+ if (!onShowTaskCardLatestActivityChange)
1107
+ return;
1108
+ const success = await onShowTaskCardLatestActivityChange(e.target.checked);
1109
+ reportTaskCardPreferenceResult(success, 'Failed to save task card latest activity setting.');
1110
+ }, disabled: !onShowTaskCardLatestActivityChange }), _jsx("span", { children: "Show latest activity" })] }), _jsxs("label", { className: `${styles.archiveToggle} ${styles.taskCardDependentSetting}`, children: [_jsx("input", { type: "checkbox", checked: tintTaskCardActivityBackground, onChange: async (e) => {
1111
+ if (!onTintTaskCardActivityBackgroundChange)
1112
+ return;
1113
+ const success = await onTintTaskCardActivityBackgroundChange(e.target.checked);
1114
+ reportTaskCardPreferenceResult(success, 'Failed to save task card activity background setting.');
1115
+ }, disabled: !showTaskCardLatestActivity || !onTintTaskCardActivityBackgroundChange }), _jsx("span", { children: "Tint latest activity background" })] })] }), _jsxs("section", { className: styles.taskCardSettingsPreview, "aria-labelledby": "task-card-preview-title", children: [_jsx("h3", { id: "task-card-preview-title", className: `${styles.settingTitle} tf-heading-section`, children: "Preview" }), _jsx("div", { className: styles.taskCardSettingsPreviewFrame, inert: true, children: _jsx(TaskCard, { task: taskCardPreviewTask, categories: categories, types: types, priorities: priorities, taxonomies: taxonomies, taskInitiative: TASK_CARD_PREVIEW_INITIATIVE, taskWorkstream: TASK_CARD_PREVIEW_WORKSTREAM, showStatusLabel: showTaskCardStatusLabel, showDescription: runtimeMode !== 'cloud' && showTaskCardDescription, showAttachments: showTaskCardAttachments, showChecklistProgress: showTaskCardChecklistProgress, showLatestActivity: showTaskCardLatestActivity, tintActivityBackground: tintTaskCardActivityBackground }) })] })] })), activeTab === 'appearanceTaskForms' && renderTaskFormsControls(), activeTab === 'initiatives' && (_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.settingTitleRow, children: [_jsx("h3", { className: styles.settingTitle, children: "Initiative Templates" }), _jsx("button", { className: styles.copyBtn, onClick: () => { void onRefreshInitiativeTemplates?.(); }, children: "Refresh" })] }), _jsx("p", { className: `${styles.settingsHint} ${styles.marginBottom12}`, children: "Create launch, migration, or incident initiatives from reusable templates." }), _jsxs("div", { className: styles.exportItem, children: [_jsx("label", { className: styles.label, children: "Template" }), _jsx("select", { className: styles.input, value: selectedInitiativeTemplateId, onChange: (e) => {
956
1116
  const nextId = e.target.value;
957
1117
  setSelectedInitiativeTemplateId(nextId);
958
1118
  }, children: initiativeTemplates.map(template => (_jsx("option", { value: template.id, children: template.name }, template.id))) })] }), _jsxs("div", { className: `${styles.exportItem} ${styles.marginTop12}`, children: [_jsx("label", { className: styles.label, children: "Initiative Title" }), _jsx("input", { className: styles.input, placeholder: "Enter initiative title", value: initiativeTitle, onChange: (e) => setInitiativeTitle(e.target.value) })] }), _jsxs("button", { className: `${styles.secondaryHeaderBtn} ${styles.marginTop12}`, disabled: isCreatingInitiative || !selectedInitiativeTemplateId || !initiativeTitle.trim() || !onCreateInitiativeFromTemplate, onClick: async () => {
@@ -984,22 +1144,25 @@ export function TaskSettings(props) {
984
1144
  ? new Date(selectedConnectorGrant.lastUsedAt).toLocaleString()
985
1145
  : 'not yet'] })] })] })) : ('No active connector authorization for this workspace yet.') }), _jsx("div", { className: styles.settingDescription, style: { marginTop: '12px' }, children: "Use the server URL above in your client, then finish the OAuth authorization flow from the Integrations tab." }), _jsx("div", { style: { display: 'flex', justifyContent: 'flex-end', width: '100%', marginTop: '12px' }, children: _jsx("button", { className: styles.copyBtn, onClick: () => setActiveTab('integrations'), children: "Open Integrations" }) })] }), _jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.codeBlockWrapperCustom} ${styles.marginTop12}`, style: { minHeight: '260px' }, children: [_jsxs("div", { className: styles.codeHeader, children: [_jsx("span", { className: styles.codeLabel, children: "Cloud MCP Configuration" }), _jsxs("div", { className: styles.codeHeaderActions, children: [_jsx("select", { className: styles.settingInput, value: selectedMcpClient, onChange: (e) => setSelectedMcpClient(e.target.value), "aria-label": "MCP client", style: { width: 'auto', minWidth: '170px', padding: '6px 12px', fontSize: '12px', borderRadius: '8px' }, children: MCP_CLIENT_OPTIONS.map((option) => (_jsx("option", { value: option.id, disabled: option.disabled, children: option.label }, option.id))) }), _jsx("button", { className: `${styles.copyBtn} ${copiedConfig === 'full' ? styles.copyBtnActive : ''}`, onClick: handleCopyCloudMcpConfig, title: "Copy full configuration file", children: copiedConfig === 'full' ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }) })] })] }), _jsx("pre", { className: styles.settingsCodeBlock, children: _jsx("code", { children: cloudMcpServerConfig
986
1146
  ? renderMcpConfigBlock(cloudMcpServerId, cloudMcpServerConfig, cloudClientIntegration.rootKey || 'mcpServers', cloudClientIntegration.wrapperKeys || [])
987
- : renderTextConfigBlock(cloudClientIntegration.renderedText || '') }) })] }), mcpConfigNotice && (_jsxs("div", { className: `${mcpConfigNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpConfigNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpConfigNotice.message] })), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("span", { className: styles.codeLabel, children: cloudClientIntegration.instructionLabel }) }), _jsxs("div", { style: { padding: '16px 20px' }, children: [_jsx("div", { className: styles.settingDescription, children: cloudClientIntegration.instructionText }), renderCodexTrustGuidance(), renderMcpProfilePrompt()] })] })] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: _jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Cloud MCP" }), _jsx("span", { className: styles.settingDescription, children: "Cloud MCP connects agents to Taskforce through the hosted MCP endpoint. Use this for remote MCP clients or tools that cannot access your local Taskforce install." })] }) }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.codeBlockWrapperCustom} ${styles.marginTop16}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("div", { className: styles.settingLabelGroup, style: { gap: '2px' }, children: _jsx("span", { className: styles.codeLabel, children: "Generate Token" }) }) }), _jsx("div", { className: styles.mcpTokenCardBody, children: _jsxs("div", { className: styles.mcpTokenFormGrid, children: [_jsxs("div", { className: styles.settingsItem, style: { gap: '6px' }, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Token Name" }) }), _jsx("input", { type: "text", className: styles.settingInput, placeholder: "Enter a recognizable token name", value: newTokenName, onChange: (e) => setNewTokenName(e.target.value) })] }), _jsxs("div", { className: styles.settingsItem, style: { gap: '6px' }, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Expiry (Optional)" }) }), _jsx("input", { type: "date", className: `${styles.settingInput} ${styles.taskFormDateInput}`, value: newTokenExpiresAt, onChange: (e) => setNewTokenExpiresAt(e.target.value) })] })] }) }), _jsxs("div", { className: styles.mcpTokenOutputWrap, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Full Token" }) }), _jsx("input", { type: "text", className: `${styles.settingInput} ${styles.mcpTokenValueInput}`, placeholder: "Generate a token to populate the full secret", value: generatedTokenValue || '', onChange: (e) => {
1147
+ : renderTextConfigBlock(cloudClientIntegration.renderedText || '') }) })] }), mcpConfigNotice && (_jsxs("div", { className: `${mcpConfigNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpConfigNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpConfigNotice.message] })), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("span", { className: styles.codeLabel, children: cloudClientIntegration.instructionLabel }) }), _jsxs("div", { style: { padding: '16px 20px' }, children: [_jsx("div", { className: styles.settingDescription, children: cloudClientIntegration.instructionText }), renderCodexTrustGuidance(), renderMcpProfilePrompt()] })] })] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: _jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Cloud MCP" }), _jsx("span", { className: styles.settingDescription, children: "Cloud MCP connects agents to Taskforce through the hosted MCP endpoint. Use this for remote MCP clients or tools that cannot access your local Taskforce install." })] }) }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.codeBlockWrapperCustom} ${styles.marginTop16}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("div", { className: styles.settingLabelGroup, style: { gap: '2px' }, children: _jsx("span", { className: styles.codeLabel, children: "Generate Token" }) }) }), _jsx("div", { className: styles.mcpTokenCardBody, children: _jsxs("div", { className: styles.mcpTokenFormGrid, children: [_jsxs("div", { className: styles.settingsItem, style: { gap: '6px' }, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Token Name" }) }), _jsx("input", { type: "text", className: styles.settingInput, placeholder: "Enter a recognizable token name", value: newTokenName, onChange: (e) => {
1148
+ setTokenNameCustomized(true);
1149
+ setNewTokenName(e.target.value);
1150
+ } })] }), _jsxs("div", { className: styles.settingsItem, style: { gap: '6px' }, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Expiry (Optional)" }) }), _jsx("input", { type: "date", className: `${styles.settingInput} ${styles.taskFormDateInput}`, value: newTokenExpiresAt, onChange: (e) => setNewTokenExpiresAt(e.target.value) })] })] }) }), _jsxs("div", { className: styles.mcpTokenOutputWrap, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Full Token" }) }), _jsx("input", { type: "text", className: `${styles.settingInput} ${styles.mcpTokenValueInput}`, placeholder: "Generate a token to populate the full secret", value: generatedTokenValue || '', onChange: (e) => {
988
1151
  setGeneratedTokenValue(e.target.value);
989
1152
  setMcpConnectionResult(null);
990
- } })] }), _jsxs("div", { className: styles.mcpTokenActionRow, children: [_jsxs("button", { className: styles.copyBtn, onClick: () => void handleTestMcpConnection(), disabled: !currentMcpTokenValue || mcpConnectionBusy, title: "Test Token", "aria-label": "Test Token", children: [mcpConnectionBusy ? _jsx(Loader2, { size: 14, className: styles.spinIcon }) : _jsx(Zap, { size: 14 }), _jsx("span", { children: "TEST TOKEN" })] }), _jsxs("button", { className: `${styles.copyBtn} ${copiedConfig === 'token' ? styles.copyBtnActive : ''}`, onClick: () => currentMcpTokenValue && copyToClipboard(currentMcpTokenValue, 'token'), disabled: !currentMcpTokenValue, title: "Copy Token", "aria-label": "Copy Token", children: [copiedConfig === 'token' ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }), _jsx("span", { children: "COPY TOKEN" })] }), _jsxs("button", { className: styles.copyBtn, onClick: () => void handleCreateMcpToken(), disabled: mcpActionBusyId === 'create', title: "Generate Token", "aria-label": "Generate Token", children: [mcpActionBusyId === 'create' ? _jsx(Loader2, { size: 14, className: styles.spinIcon }) : _jsx(Zap, { size: 14 }), _jsx("span", { children: "GENERATE TOKEN" })] })] }), mcpTokenIssueNotice && (_jsxs("div", { className: `${mcpTokenIssueNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpTokenIssueNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpTokenIssueNotice.message] })), mcpConnectionResult && (_jsxs("div", { className: `${mcpConnectionResult.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpConnectionResult.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), _jsxs("div", { children: [_jsx("div", { children: mcpConnectionResult.message }), mcpConnectionResult.type === 'success' && (mcpConnectionResult.workspaceName || mcpConnectionResult.workspaceId) && (_jsxs("div", { className: styles.settingHelper, children: ["Workspace: ", mcpConnectionResult.workspaceName || mcpConnectionResult.workspaceId, mcpConnectionResult.workspaceId ? ` (${mcpConnectionResult.workspaceId})` : ''] })), mcpConnectionResult.type === 'success' && Array.isArray(mcpConnectionResult.scopes) && mcpConnectionResult.scopes.length > 0 && (_jsxs("div", { className: styles.settingHelper, children: ["Granted scopes: ", mcpConnectionResult.scopes.join(', ')] })), mcpConnectionResult.endpoint && (_jsxs("div", { className: styles.settingHelper, children: ["Endpoint: ", mcpConnectionResult.endpoint] })), mcpConnectionResult.type === 'error' && mcpConnectionResult.errorCode && (_jsxs("div", { className: styles.settingHelper, children: ["Error code: ", mcpConnectionResult.errorCode] })), mcpConnectionResult.type === 'error' && mcpConnectionResult.followup && (_jsx("div", { className: styles.settingHelper, children: mcpConnectionResult.followup }))] })] }))] }), _jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.codeBlockWrapperCustom} ${styles.marginTop12}`, style: { minHeight: '260px' }, children: [_jsxs("div", { className: styles.codeHeader, children: [_jsx("span", { className: styles.codeLabel, children: "Cloud MCP Configuration" }), _jsxs("div", { className: styles.codeHeaderActions, children: [_jsx("select", { className: styles.settingInput, value: selectedMcpClient, onChange: (e) => setSelectedMcpClient(e.target.value), "aria-label": "MCP client", style: { width: 'auto', minWidth: '170px', padding: '6px 12px', fontSize: '12px', borderRadius: '8px' }, children: MCP_CLIENT_OPTIONS.map((option) => (_jsx("option", { value: option.id, disabled: option.disabled, children: option.label }, option.id))) }), _jsx("button", { className: `${styles.copyBtn} ${copiedConfig === 'full' ? styles.copyBtnActive : ''}`, onClick: handleCopyCloudMcpConfig, title: "Copy full configuration file", children: copiedConfig === 'full' ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }) })] })] }), _jsx("pre", { className: styles.settingsCodeBlock, children: _jsx("code", { children: cloudMcpServerConfig
1153
+ } })] }), _jsxs("div", { className: styles.mcpTokenActionRow, children: [_jsxs("button", { className: styles.copyBtn, onClick: () => void handleTestMcpConnection(), disabled: !currentMcpTokenValue || mcpConnectionBusy, title: "Test Token", "aria-label": "Test Token", children: [mcpConnectionBusy ? _jsx(Loader2, { size: 14, className: styles.spinIcon }) : _jsx(Zap, { size: 14 }), _jsx("span", { children: "TEST TOKEN" })] }), _jsxs("button", { className: `${styles.copyBtn} ${copiedConfig === 'token' ? styles.copyBtnActive : ''}`, onClick: () => currentMcpTokenValue && copyToClipboard(currentMcpTokenValue, 'token'), disabled: !currentMcpTokenValue, title: "Copy Token", "aria-label": "Copy Token", children: [copiedConfig === 'token' ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }), _jsx("span", { children: "COPY TOKEN" })] }), _jsxs("button", { className: styles.copyBtn, onClick: () => void handleCreateMcpToken(), disabled: mcpActionBusyId === 'create', title: "Generate Token", "aria-label": "Generate Token", children: [mcpActionBusyId === 'create' ? _jsx(Loader2, { size: 14, className: styles.spinIcon }) : _jsx(Zap, { size: 14 }), _jsx("span", { children: "GENERATE TOKEN" })] })] }), mcpTokenIssueNotice && (_jsxs("div", { className: `${mcpTokenIssueNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpTokenIssueNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpTokenIssueNotice.message] })), mcpConnectionResult && (_jsxs("div", { className: `${mcpConnectionResult.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpConnectionResult.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), _jsxs("div", { children: [_jsx("div", { children: mcpConnectionResult.message }), mcpConnectionResult.type === 'success' && (mcpConnectionResult.workspaceName || mcpConnectionResult.workspaceId) && (_jsxs("div", { className: styles.settingHelper, children: ["Workspace: ", mcpConnectionResult.workspaceName || mcpConnectionResult.workspaceId, mcpConnectionResult.workspaceId ? ` (${mcpConnectionResult.workspaceId})` : ''] })), mcpConnectionResult.type === 'success' && Array.isArray(mcpConnectionResult.scopes) && mcpConnectionResult.scopes.length > 0 && (_jsxs("div", { className: styles.settingHelper, children: ["Granted scopes: ", mcpConnectionResult.scopes.join(', ')] })), mcpConnectionResult.type === 'success' && mcpConnectionResult.toolProfile && (_jsxs("div", { className: styles.settingHelper, children: ["Tool access: ", mcpConnectionResult.toolProfile === 'extended' ? 'All cloud tools' : 'Standard', typeof mcpConnectionResult.toolCount === 'number' ? ` · ${mcpConnectionResult.toolCount} tools` : ''] })), mcpConnectionResult.endpoint && (_jsxs("div", { className: styles.settingHelper, children: ["Endpoint: ", mcpConnectionResult.endpoint] })), mcpConnectionResult.type === 'error' && mcpConnectionResult.errorCode && (_jsxs("div", { className: styles.settingHelper, children: ["Error code: ", mcpConnectionResult.errorCode] })), mcpConnectionResult.type === 'error' && mcpConnectionResult.followup && (_jsx("div", { className: styles.settingHelper, children: mcpConnectionResult.followup }))] })] }))] }), _jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.codeBlockWrapperCustom} ${styles.marginTop12}`, style: { minHeight: '260px' }, children: [_jsxs("div", { className: styles.codeHeader, children: [_jsx("span", { className: styles.codeLabel, children: "Cloud MCP Configuration" }), _jsxs("div", { className: styles.codeHeaderActions, children: [_jsx("select", { className: styles.settingInput, value: selectedMcpClient, onChange: (e) => setSelectedMcpClient(e.target.value), "aria-label": "MCP client", style: { width: 'auto', minWidth: '170px', padding: '6px 12px', fontSize: '12px', borderRadius: '8px' }, children: MCP_CLIENT_OPTIONS.map((option) => (_jsx("option", { value: option.id, disabled: option.disabled, children: option.label }, option.id))) }), _jsx("button", { className: `${styles.copyBtn} ${copiedConfig === 'full' ? styles.copyBtnActive : ''}`, onClick: handleCopyCloudMcpConfig, title: "Copy full configuration file", children: copiedConfig === 'full' ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }) })] })] }), _jsx("pre", { className: styles.settingsCodeBlock, children: _jsx("code", { children: cloudMcpServerConfig
991
1154
  ? renderMcpConfigBlock(cloudMcpServerId, cloudMcpServerConfig, cloudClientIntegration.rootKey || 'mcpServers', cloudClientIntegration.wrapperKeys || [])
992
1155
  : renderTextConfigBlock(cloudClientIntegration.renderedText || '') }) })] }), mcpConfigNotice && (_jsxs("div", { className: `${mcpConfigNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpConfigNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpConfigNotice.message] })), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("span", { className: styles.codeLabel, children: cloudClientIntegration.instructionLabel }) }), _jsxs("div", { style: { padding: '16px 20px' }, children: [_jsx("div", { className: styles.settingDescription, children: cloudClientIntegration.instructionText }), renderCodexTrustGuidance(), renderMcpProfilePrompt()] })] })] }), _jsxs("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: [_jsxs("div", { className: styles.toggleHeading, onClick: () => setShowMcpTokensList((prev) => !prev), onKeyDown: (e) => {
993
1156
  if (e.key === 'Enter' || e.key === ' ') {
994
1157
  e.preventDefault();
995
1158
  setShowMcpTokensList((prev) => !prev);
996
1159
  }
997
- }, role: "button", tabIndex: 0, title: showMcpTokensList ? 'Hide workspace tokens' : 'Show workspace tokens', children: [_jsx("label", { className: styles.label, children: "Your Tokens" }), showMcpTokensList ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 })] }), showMcpTokensList && (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles.settingDescription} ${styles.marginTop12}`, children: "Manage tokens created for this workspace." }), mcpTokenListNotice && (_jsxs("div", { className: `${mcpTokenListNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpTokenListNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpTokenListNotice.message] })), mcpTokensLoading ? (_jsx("p", { className: styles.settingHelper, children: "Loading tokens\u2026" })) : mcpTokensError ? (_jsxs("div", { className: styles.errorMessage, children: [_jsx(AlertTriangle, { size: 14 }), mcpTokensError] })) : mcpTokens.length === 0 ? (_jsx("p", { className: styles.settingHelper, children: "No MCP tokens yet." })) : (_jsx("div", { className: styles.settingGroup, children: sortedMcpTokens.map((token) => (_jsxs("div", { className: `${styles.settingsItem} ${styles.marginTop12}`, style: {
1160
+ }, role: "button", tabIndex: 0, title: showMcpTokensList ? 'Hide workspace tokens' : 'Show workspace tokens', children: [_jsx("label", { className: styles.label, children: "Your Tokens" }), showMcpTokensList ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 })] }), showMcpTokensList && (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles.settingDescription} ${styles.marginTop12}`, children: "Manage tokens created for this workspace." }), mcpTokenListNotice && (_jsxs("div", { className: `${mcpTokenListNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpTokenListNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpTokenListNotice.message] })), mcpProfileNotice && (_jsxs("div", { className: `${mcpProfileNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpProfileNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpProfileNotice.message] })), mcpTokensLoading ? (_jsx("p", { className: styles.settingHelper, children: "Loading tokens\u2026" })) : mcpTokensError ? (_jsxs("div", { className: styles.errorMessage, children: [_jsx(AlertTriangle, { size: 14 }), mcpTokensError] })) : mcpTokens.length === 0 ? (_jsx("p", { className: styles.settingHelper, children: "No MCP tokens yet." })) : (_jsx("div", { className: styles.settingGroup, children: sortedMcpTokens.map((token) => (_jsxs("div", { className: `${styles.settingsItem} ${styles.marginTop12}`, style: {
998
1161
  padding: '14px 16px',
999
1162
  borderRadius: '12px',
1000
1163
  border: '1px solid var(--border-primary, rgba(255, 255, 255, 0.1))',
1001
1164
  background: 'rgba(255, 255, 255, 0.03)'
1002
- }, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsxs("div", { className: styles.labelGroupFlex, children: [_jsx("label", { className: styles.settingLabel, children: token.name }), _jsx("span", { className: `${styles.configBadge} ${token.status === 'revoked' ? styles.configBadgeRevoked : token.status === 'expired' ? styles.configBadgeExpired : styles.configBadgeActive}`, children: token.status })] }), _jsx("span", { className: styles.settingDescription, style: { fontFamily: '"JetBrains Mono", "Fira Code", monospace' }, children: token.tokenPrefix }), _jsxs("span", { className: styles.settingDescription, children: ["Scopes: ", token.scopes.join(', ')] }), _jsxs("span", { className: styles.settingDescription, children: ["Created ", new Date(token.createdAt).toLocaleDateString(), token.lastUsedAt ? ` · Last used ${new Date(token.lastUsedAt).toLocaleString()}` : ' · Never used'] })] }), _jsxs("div", { style: { display: 'flex', gap: '8px', flexWrap: 'wrap', justifyContent: 'flex-end' }, children: [token.status === 'active' && (_jsx("button", { className: styles.copyBtn, onClick: () => void handleMcpTokenAction(token.id, 'regenerate'), disabled: mcpActionBusyId === `regenerate:${token.id}`, children: "Regenerate" })), token.status === 'active' && (_jsx("button", { className: styles.copyBtn, onClick: () => void handleMcpTokenAction(token.id, 'revoke'), disabled: mcpActionBusyId === `revoke:${token.id}`, children: "Revoke" })), token.status !== 'active' && (_jsx("button", { className: styles.copyBtn, onClick: () => void handleMcpTokenAction(token.id, 'delete'), disabled: mcpActionBusyId === `delete:${token.id}`, children: "Delete" }))] })] }, token.id))) }))] }))] })] })) })), showLocalMcp && (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: _jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Local MCP" }), _jsx("span", { className: styles.settingDescription, children: "Local MCP connects through your local Taskforce install and does not require a cloud access token. Use this for Codex, Claude Code CLI, Gemini CLI, and similar local MCP clients." })] }) }), useGlobalMcp && localMcpHealth.status === 'host-unverified' && (_jsxs("div", { className: `${styles.mcpHealthCompactAlert} ${styles.marginTop12}`, role: "status", children: [_jsx(AlertTriangle, { size: 17, "aria-hidden": "true" }), _jsxs("div", { className: styles.mcpHealthCompactBody, children: [_jsx("strong", { children: "Global MCP cannot be checked on this host" }), _jsxs("span", { children: ["This project uses host path mapping. Verify ", _jsx("code", { children: "taskforce --version" }), " in the host environment, or use Local / npx."] })] }), _jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => setUseGlobalMcp(false), children: "Use Local / npx" })] })), useGlobalMcp && globalCliMismatch && (_jsxs("div", { className: `${styles.mcpHealthUpdateRow} ${styles.marginTop12}`, role: "status", children: [_jsx("div", { className: styles.mcpHealthUpdateIcon, children: _jsx(AlertTriangle, { size: 17, "aria-hidden": "true" }) }), _jsxs("div", { className: styles.mcpHealthCompactBody, children: [_jsx("strong", { children: "Global MCP update available" }), _jsxs("span", { children: [globalCliMismatch.cliVersion || 'Unknown version', " installed", ' · ', globalCliMismatch.appVersion, " expected"] })] }), _jsxs("button", { type: "button", className: `tf-button-secondary tf-button-compact ${styles.mcpHealthStableAction}`, onClick: () => setGlobalCliDialogOpen(true), disabled: localMcpHealthChecking, "aria-busy": localMcpHealthChecking, children: [localMcpHealthChecking && (_jsx(Loader2, { className: styles.spinner, size: 14, "aria-hidden": "true" })), "Review update"] })] })), useGlobalMcp && globalCliUnavailable && (_jsxs("div", { className: `${styles.mcpHealthBlockingAlert} ${styles.marginTop12}`, role: "alert", children: [_jsx(AlertTriangle, { size: 18, "aria-hidden": "true" }), _jsxs("div", { className: styles.mcpHealthCompactBody, children: [_jsx("strong", { children: "Global MCP is unavailable" }), _jsx("span", { children: globalCliUnavailable.message })] }), _jsxs("div", { className: styles.mcpHealthCompactActions, children: [_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => setUseGlobalMcp(false), children: "Use Local / npx" }), _jsxs("button", { type: "button", className: `tf-button-secondary tf-button-compact ${styles.mcpHealthStableAction}`, onClick: () => setLocalMcpHealthRetry((value) => value + 1), disabled: localMcpHealthChecking, "aria-busy": localMcpHealthChecking, "aria-label": localMcpHealthChecking ? 'Checking Global MCP' : 'Check again', children: [localMcpHealthChecking && (_jsx(Loader2, { className: styles.spinner, size: 14, "aria-hidden": "true" })), "Check again"] })] })] })), mcpConfigNotice?.type === 'error' && !globalCliDialogOpen && (_jsxs("div", { className: `${styles.mcpHealthCopyError} ${styles.marginTop12}`, role: "alert", children: [_jsx(AlertTriangle, { size: 14, "aria-hidden": "true" }), mcpConfigNotice.message] })), _jsx(Modal, { isOpen: globalCliDialogOpen && Boolean(globalCliMismatch), onClose: () => setGlobalCliDialogOpen(false), title: "Update Global MCP", size: "md", theme: currentTheme, children: globalCliMismatch && (_jsxs("div", { className: styles.mcpUpdateDialog, children: [_jsx("p", { className: styles.mcpUpdateDialogIntro, children: "Your Global MCP CLI is usable, but it does not match this Taskforce app. Update it, then restart any running MCP clients." }), _jsxs("dl", { className: styles.mcpUpdateVersionGrid, children: [_jsxs("div", { children: [_jsx("dt", { children: "Installed CLI" }), _jsx("dd", { children: globalCliMismatch.cliVersion || 'Unknown' })] }), _jsxs("div", { children: [_jsx("dt", { children: "Expected by app" }), _jsx("dd", { children: globalCliMismatch.appVersion })] }), _jsxs("div", { children: [_jsx("dt", { children: "Installation channel" }), _jsx("dd", { children: globalCliUpdateStatus.status === 'loading'
1165
+ }, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsxs("div", { className: styles.labelGroupFlex, children: [_jsx("label", { className: styles.settingLabel, children: token.name }), _jsx("span", { className: `${styles.configBadge} ${token.status === 'revoked' ? styles.configBadgeRevoked : token.status === 'expired' ? styles.configBadgeExpired : styles.configBadgeActive}`, children: token.status })] }), _jsx("span", { className: styles.settingDescription, style: { fontFamily: '"JetBrains Mono", "Fira Code", monospace' }, children: token.tokenPrefix }), _jsxs("span", { className: styles.settingDescription, children: ["Scopes: ", token.scopes.join(', ')] }), _jsxs("span", { className: styles.settingDescription, children: ["Tool access: ", (token.toolProfile || 'default') === 'extended' ? 'All cloud tools' : 'Standard', " \u00B7 up to ", mcpToolProfileOptions.find((option) => option.id === (token.toolProfile || 'default'))?.toolCount ?? 58, " tools; granted scopes still apply"] }), _jsxs("span", { className: styles.settingDescription, children: ["Created ", new Date(token.createdAt).toLocaleDateString(), token.lastUsedAt ? ` · Last used ${new Date(token.lastUsedAt).toLocaleString()}` : ' · Never used'] })] }), _jsxs("div", { style: { display: 'flex', gap: '8px', flexWrap: 'wrap', justifyContent: 'flex-end' }, children: [token.status === 'active' && (_jsx("select", { className: styles.settingInput, "aria-label": `Tool access for ${token.name}`, value: token.toolProfile || 'default', onChange: (event) => void handleMcpToolProfileChange('tokens', token.id, event.target.value), disabled: !canManageMcpToolProfiles || mcpActionBusyId === `profile:tokens:${token.id}`, title: canManageMcpToolProfiles ? 'Change cloud MCP tool access' : 'Workspace owner or admin required', style: { width: 'auto', minWidth: '170px' }, children: mcpToolProfileOptions.map((option) => (_jsxs("option", { value: option.id, children: [option.label, " \u00B7 ", option.toolCount] }, option.id))) })), token.status === 'active' && (_jsx("button", { className: styles.copyBtn, onClick: () => void handleMcpTokenAction(token.id, 'regenerate'), disabled: mcpActionBusyId === `regenerate:${token.id}`, children: "Regenerate" })), token.status === 'active' && (_jsx("button", { className: styles.copyBtn, onClick: () => void handleMcpTokenAction(token.id, 'revoke'), disabled: mcpActionBusyId === `revoke:${token.id}`, children: "Revoke" })), token.status !== 'active' && (_jsx("button", { className: styles.copyBtn, onClick: () => void handleMcpTokenAction(token.id, 'delete'), disabled: mcpActionBusyId === `delete:${token.id}`, children: "Delete" }))] })] }, token.id))) }))] }))] })] })) })), showLocalMcp && (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: _jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Local MCP" }), _jsx("span", { className: styles.settingDescription, children: "Local MCP connects through your local Taskforce install and does not require a cloud access token. Use this for Codex, Claude Code CLI, Gemini CLI, and similar local MCP clients." })] }) }), useGlobalMcp && localMcpHealth.status === 'host-unverified' && (_jsxs("div", { className: `${styles.mcpHealthCompactAlert} ${styles.marginTop12}`, role: "status", children: [_jsx(AlertTriangle, { size: 17, "aria-hidden": "true" }), _jsxs("div", { className: styles.mcpHealthCompactBody, children: [_jsx("strong", { children: "Global MCP cannot be checked on this host" }), _jsxs("span", { children: ["This project uses host path mapping. Verify ", _jsx("code", { children: "taskforce --version" }), " in the host environment, or use Local / npx."] })] }), _jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => setUseGlobalMcp(false), children: "Use Local / npx" })] })), useGlobalMcp && globalCliMismatch && (_jsxs("div", { className: `${styles.mcpHealthUpdateRow} ${styles.marginTop12}`, role: "status", children: [_jsx("div", { className: styles.mcpHealthUpdateIcon, children: _jsx(AlertTriangle, { size: 17, "aria-hidden": "true" }) }), _jsxs("div", { className: styles.mcpHealthCompactBody, children: [_jsx("strong", { children: "Global MCP update available" }), _jsxs("span", { children: [globalCliMismatch.cliVersion || 'Unknown version', " installed", ' · ', globalCliMismatch.appVersion, " expected"] })] }), _jsxs("button", { type: "button", className: `tf-button-secondary tf-button-compact ${styles.mcpHealthStableAction}`, onClick: () => setGlobalCliDialogOpen(true), disabled: localMcpHealthChecking, "aria-busy": localMcpHealthChecking, children: [localMcpHealthChecking && (_jsx(Loader2, { className: styles.spinner, size: 14, "aria-hidden": "true" })), "Review update"] })] })), useGlobalMcp && globalCliUnavailable && (_jsxs("div", { className: `${styles.mcpHealthBlockingAlert} ${styles.marginTop12}`, role: "alert", children: [_jsx(AlertTriangle, { size: 18, "aria-hidden": "true" }), _jsxs("div", { className: styles.mcpHealthCompactBody, children: [_jsx("strong", { children: "Global MCP is unavailable" }), _jsx("span", { children: globalCliUnavailable.message })] }), _jsxs("div", { className: styles.mcpHealthCompactActions, children: [_jsx("button", { type: "button", className: "tf-button-secondary tf-button-compact", onClick: () => setUseGlobalMcp(false), children: "Use Local / npx" }), _jsxs("button", { type: "button", className: `tf-button-secondary tf-button-compact ${styles.mcpHealthStableAction}`, onClick: () => setLocalMcpHealthRetry((value) => value + 1), disabled: localMcpHealthChecking, "aria-busy": localMcpHealthChecking, "aria-label": localMcpHealthChecking ? 'Checking Global MCP' : 'Check again', children: [localMcpHealthChecking && (_jsx(Loader2, { className: styles.spinner, size: 14, "aria-hidden": "true" })), "Check again"] })] })] })), mcpConfigNotice?.type === 'error' && !globalCliDialogOpen && (_jsxs("div", { className: `${styles.mcpHealthCopyError} ${styles.marginTop12}`, role: "alert", children: [_jsx(AlertTriangle, { size: 14, "aria-hidden": "true" }), mcpConfigNotice.message] })), _jsx(Modal, { isOpen: globalCliDialogOpen && Boolean(globalCliMismatch), onClose: () => setGlobalCliDialogOpen(false), title: "Update Global MCP", size: "md", theme: currentTheme, children: globalCliMismatch && (_jsxs("div", { className: styles.mcpUpdateDialog, children: [_jsx("p", { className: styles.mcpUpdateDialogIntro, children: "Your Global MCP CLI is usable, but it does not match this Taskforce app. Update it, then restart any running MCP clients." }), _jsxs("dl", { className: styles.mcpUpdateVersionGrid, children: [_jsxs("div", { children: [_jsx("dt", { children: "Installed CLI" }), _jsx("dd", { children: globalCliMismatch.cliVersion || 'Unknown' })] }), _jsxs("div", { children: [_jsx("dt", { children: "Expected by app" }), _jsx("dd", { children: globalCliMismatch.appVersion })] }), _jsxs("div", { children: [_jsx("dt", { children: "Installation channel" }), _jsx("dd", { children: globalCliUpdateStatus.status === 'loading'
1003
1166
  ? 'Detecting…'
1004
1167
  : updateChannelLabel })] })] }), globalCliUpdateStatus.status === 'loading' && (_jsxs("div", { className: styles.mcpUpdateLoading, role: "status", "aria-live": "polite", children: [_jsx(Loader2, { className: styles.spinner, size: 15, "aria-hidden": "true" }), "Detecting the package manager\u2026"] })), globalCliUpdateStatus.status === 'error' && (_jsxs("div", { className: styles.mcpUpdateNotice, role: "status", children: [_jsx(AlertTriangle, { size: 16, "aria-hidden": "true" }), _jsxs("span", { children: [globalCliUpdateStatus.message, " Check again, or update using the package manager you originally used."] })] })), globalCliUpdateCommands.length > 0 && globalCliUpdateStatus.status !== 'loading' && (_jsxs("div", { className: styles.mcpUpdateCommands, children: [_jsx("span", { className: styles.mcpUpdateSectionLabel, children: updateTarget?.channel === 'unknown'
1005
1168
  || updateTarget?.channel === 'conflicting'
@@ -1015,7 +1178,7 @@ export function TaskSettings(props) {
1015
1178
  e.preventDefault();
1016
1179
  setShowAdvancedMcp((prev) => !prev);
1017
1180
  }
1018
- }, role: "button", tabIndex: 0, title: "Show advanced MCP install options", children: [_jsx("label", { className: styles.label, children: "Advanced" }), showAdvancedMcp ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 })] }) }), showAdvancedMcp && (_jsxs("div", { className: `${styles.settingGroup} ${styles.marginTop12}`, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Advanced Installation Mode" }), _jsx("span", { className: styles.settingDescription, children: "Global mode is recommended. Local / npx is intended for Taskforce development workflows." })] }), _jsxs("div", { className: styles.buttonGrid, children: [_jsx("button", { className: `${styles.themeBtn} ${useGlobalMcp ? styles.activeTheme : ''}`, onClick: () => setUseGlobalMcp(true), children: "Global" }), _jsx("button", { className: `${styles.themeBtn} ${!useGlobalMcp ? styles.activeTheme : ''}`, onClick: () => setUseGlobalMcp(false), children: "Local / npx (Dev)" })] }), _jsxs("div", { className: `${styles.settingsItem} ${styles.marginTop16}`, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsxs("div", { className: styles.labelGroupFlex, children: [_jsx("label", { className: styles.settingLabel, children: "MCP Path Mapping (Host Root)" }), serverHostRoot && !mcpHostRoot && (_jsx("span", { className: styles.configBadge, children: "Server Configured" }))] }), _jsx("span", { className: styles.settingDescription, children: "If running in Docker, WSL, or Remote Dev, provide the absolute path to this project as seen by your host OS." })] }), _jsx("div", { className: styles.pathInputWrapper, children: _jsx("input", { type: "text", className: styles.settingInput, placeholder: serverHostRoot || "/Users/username/Projects/my-project or C:\\Projects\\my-project", value: mcpHostRoot || '', onChange: (e) => onMcpHostRootChange?.(e.target.value) }) })] })] }))] }))] })), activeTab === 'integrations' && (_jsxs("div", { className: styles.settingsGroup, children: [_jsx("div", { className: styles.settingGroup, children: _jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Integrations" }), _jsx("span", { className: styles.settingDescription, children: "Manage OAuth-based app connectors separately from MCP tokens and local client setup." })] }) }), _jsxs("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: [[
1181
+ }, role: "button", tabIndex: 0, title: "Show advanced MCP install options", children: [_jsx("label", { className: styles.label, children: "Advanced" }), showAdvancedMcp ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 })] }) }), showAdvancedMcp && (_jsxs("div", { className: `${styles.settingGroup} ${styles.marginTop12}`, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Advanced Installation Mode" }), _jsx("span", { className: styles.settingDescription, children: "Global mode is recommended. Local / npx is intended for Taskforce development workflows." })] }), _jsxs("div", { className: styles.buttonGrid, children: [_jsx("button", { className: `${styles.themeBtn} ${useGlobalMcp ? styles.activeTheme : ''}`, onClick: () => setUseGlobalMcp(true), children: "Global" }), _jsx("button", { className: `${styles.themeBtn} ${!useGlobalMcp ? styles.activeTheme : ''}`, onClick: () => setUseGlobalMcp(false), children: "Local / npx (Dev)" })] }), _jsxs("div", { className: `${styles.settingsItem} ${styles.marginTop16}`, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsxs("div", { className: styles.labelGroupFlex, children: [_jsx("label", { className: styles.settingLabel, children: "MCP Path Mapping (Host Root)" }), serverHostRoot && !mcpHostRoot && (_jsx("span", { className: styles.configBadge, children: "Server Configured" }))] }), _jsx("span", { className: styles.settingDescription, children: "If running in Docker, WSL, or Remote Dev, provide the absolute path to this project as seen by your host OS." })] }), _jsx("div", { className: styles.pathInputWrapper, children: _jsx("input", { type: "text", className: styles.settingInput, placeholder: serverHostRoot || "/Users/username/Projects/my-project or C:\\Projects\\my-project", value: mcpHostRoot || '', onChange: (e) => onMcpHostRootChange?.(e.target.value) }) })] })] }))] }))] })), activeTab === 'integrations' && (_jsxs("div", { className: styles.settingsGroup, children: [_jsx("div", { className: styles.settingGroup, children: _jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "Integrations" }), _jsx("span", { className: styles.settingDescription, children: "Manage OAuth-based app connectors separately from MCP tokens and local client setup." })] }) }), _jsxs("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: [mcpProfileNotice && (_jsxs("div", { className: `${mcpProfileNotice.type === 'success' ? styles.successMessage : styles.errorMessage} ${styles.marginTop12}`, children: [mcpProfileNotice.type === 'success' ? _jsx(Check, { size: 14 }) : _jsx(AlertTriangle, { size: 14 }), mcpProfileNotice.message] })), [
1019
1182
  {
1020
1183
  key: 'chatgpt',
1021
1184
  label: 'ChatGPT Connector',
@@ -1069,6 +1232,6 @@ export function TaskSettings(props) {
1069
1232
  borderRadius: '14px',
1070
1233
  border: '1px solid var(--border-primary, rgba(255, 255, 255, 0.1))',
1071
1234
  background: 'rgba(255, 255, 255, 0.03)'
1072
- }, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsxs("div", { className: styles.labelGroupFlex, children: [_jsx("label", { className: styles.settingLabel, children: item.label }), _jsx("span", { className: `${styles.configBadge} ${connector && !comingSoon ? styles.configBadgeActive : styles.configBadgeRevoked}`, children: comingSoon ? 'coming soon' : (connector ? 'connected' : 'not connected') })] }), _jsx("span", { className: styles.settingDescription, children: item.description }), !comingSoon && (_jsx("span", { className: styles.settingDescription, style: { fontFamily: '"JetBrains Mono", "Fira Code", monospace' }, children: cloudMcpEndpoint })), comingSoon ? null : connector ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: styles.settingDescription, children: ["Authorized workspace: ", currentWorkspaceName || connector.workspaceId] }), _jsxs("span", { className: styles.settingDescription, children: ["Granted scopes: ", connector.scopes.join(', ')] }), _jsxs("span", { className: styles.settingDescription, children: ["Connected ", new Date(connector.createdAt).toLocaleString(), connector.lastUsedAt ? ` · Last used ${new Date(connector.lastUsedAt).toLocaleString()}` : ' · Never used'] })] })) : (_jsx("span", { className: styles.settingDescription, children: item.emptyMessage }))] }), _jsx("div", { style: { display: 'flex', justifyContent: 'flex-end', gap: '8px', flexWrap: 'wrap' }, children: connector && !comingSoon && (_jsxs("button", { className: styles.copyBtn, onClick: () => void handleDisconnectConnector(connector.id), disabled: mcpConnectorBusyId === connector.id, children: [mcpConnectorBusyId === connector.id ? _jsx(Loader2, { size: 14, className: styles.spinIcon }) : _jsx(Trash2, { size: 14 }), "Disconnect"] })) })] }, item.key));
1235
+ }, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsxs("div", { className: styles.labelGroupFlex, children: [_jsx("label", { className: styles.settingLabel, children: item.label }), _jsx("span", { className: `${styles.configBadge} ${connector && !comingSoon ? styles.configBadgeActive : styles.configBadgeRevoked}`, children: comingSoon ? 'coming soon' : (connector ? 'connected' : 'not connected') })] }), _jsx("span", { className: styles.settingDescription, children: item.description }), !comingSoon && (_jsx("span", { className: styles.settingDescription, style: { fontFamily: '"JetBrains Mono", "Fira Code", monospace' }, children: cloudMcpEndpoint })), comingSoon ? null : connector ? (_jsxs(_Fragment, { children: [_jsxs("span", { className: styles.settingDescription, children: ["Authorized workspace: ", currentWorkspaceName || connector.workspaceId] }), _jsxs("span", { className: styles.settingDescription, children: ["Granted scopes: ", connector.scopes.join(', ')] }), _jsxs("span", { className: styles.settingDescription, children: ["Tool access: ", (connector.toolProfile || 'default') === 'extended' ? 'All cloud tools' : 'Standard', " \u00B7 up to ", mcpToolProfileOptions.find((option) => option.id === (connector.toolProfile || 'default'))?.toolCount ?? 58, " tools; granted scopes still apply"] }), _jsxs("span", { className: styles.settingDescription, children: ["Connected ", new Date(connector.createdAt).toLocaleString(), connector.lastUsedAt ? ` · Last used ${new Date(connector.lastUsedAt).toLocaleString()}` : ' · Never used'] })] })) : (_jsx("span", { className: styles.settingDescription, children: item.emptyMessage }))] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'flex-end', gap: '8px', flexWrap: 'wrap' }, children: [connector && !comingSoon && (_jsx("select", { className: styles.settingInput, "aria-label": `Tool access for ${item.label}`, value: connector.toolProfile || 'default', onChange: (event) => void handleMcpToolProfileChange('connectors', connector.id, event.target.value), disabled: !canManageMcpToolProfiles || mcpConnectorBusyId === `profile:connectors:${connector.id}`, title: canManageMcpToolProfiles ? 'Change cloud MCP tool access' : 'Workspace owner or admin required', style: { width: 'auto', minWidth: '170px' }, children: mcpToolProfileOptions.map((option) => (_jsxs("option", { value: option.id, children: [option.label, " \u00B7 ", option.toolCount] }, option.id))) })), connector && !comingSoon && (_jsxs("button", { className: styles.copyBtn, onClick: () => void handleDisconnectConnector(connector.id), disabled: mcpConnectorBusyId === connector.id, children: [mcpConnectorBusyId === connector.id ? _jsx(Loader2, { size: 14, className: styles.spinIcon }) : _jsx(Trash2, { size: 14 }), "Disconnect"] }))] })] }, item.key));
1073
1236
  }), mcpConnectorsLoading && (_jsx("p", { className: `${styles.settingHelper} ${styles.marginTop12}`, children: "Loading connector grants\u2026" })), mcpConnectorsError && (_jsxs("div", { className: `${styles.errorMessage} ${styles.marginTop12}`, children: [_jsx(AlertTriangle, { size: 14 }), mcpConnectorsError] }))] })] }))] })] }) }));
1074
1237
  }