@taskforcehq/taskforce 0.3.305 → 0.3.307

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 (440) hide show
  1. package/README.md +0 -2
  2. package/dist/Taskforce.module.css +603 -107
  3. package/dist/TaskforceCore.js +216 -43
  4. package/dist/TaskforceCore.test.js +611 -28
  5. package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
  6. package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  7. package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
  8. package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
  9. package/dist/assets/fonts/Noir_medium.woff2 +0 -0
  10. package/dist/assets/fonts/Noir_regular.woff2 +0 -0
  11. package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
  12. package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
  13. package/dist/compat/workspaceSyncCompat.js +46 -2
  14. package/dist/compat/workspaceSyncCompat.test.js +38 -1
  15. package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
  16. package/dist/components/activity/EntityActivityTimeline.js +81 -0
  17. package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
  18. package/dist/components/context/ContextAttachmentManager.js +561 -0
  19. package/dist/components/features/AgentsModule.d.ts +14 -1
  20. package/dist/components/features/AgentsModule.js +366 -18
  21. package/dist/components/features/AgentsModule.test.js +507 -8
  22. package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
  23. package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
  24. package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
  25. package/dist/components/features/DocumentIndex.d.ts +2 -2
  26. package/dist/components/features/DocumentIndex.js +3 -4
  27. package/dist/components/features/DocumentViewer.d.ts +7 -1
  28. package/dist/components/features/DocumentViewer.js +62 -4
  29. package/dist/components/features/DocumentWorkspace.d.ts +10 -2
  30. package/dist/components/features/DocumentWorkspace.js +15 -4
  31. package/dist/components/features/DocumentWorkspace.test.js +51 -1
  32. package/dist/components/features/TaskSettings.d.ts +2 -0
  33. package/dist/components/features/TaskSettings.js +83 -78
  34. package/dist/components/features/TaskSettings.test.js +171 -82
  35. package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
  36. package/dist/components/task/TaskActionHeader.js +11 -5
  37. package/dist/components/task/TaskActionHeader.test.js +10 -0
  38. package/dist/components/task/TaskCard.js +24 -29
  39. package/dist/components/task/TaskCard.test.js +38 -3
  40. package/dist/components/task/TaskContextUpload.js +4 -526
  41. package/dist/components/task/TaskContextUpload.test.js +3 -3
  42. package/dist/components/task/TaskForm.js +61 -116
  43. package/dist/components/task/TaskForm.test.js +110 -8
  44. package/dist/components/task/TaskKanban.d.ts +2 -1
  45. package/dist/components/task/TaskKanban.js +94 -21
  46. package/dist/components/task/TaskKanban.test.js +36 -0
  47. package/dist/components/task/TaskList.js +5 -1
  48. package/dist/components/task/TaskList.test.js +4 -0
  49. package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
  50. package/dist/components/ui/EditableAvatarButton.js +18 -0
  51. package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
  52. package/dist/components/ui/HierarchyActionBadge.js +5 -0
  53. package/dist/components/views/AppShellHeader.d.ts +3 -1
  54. package/dist/components/views/AppShellHeader.js +27 -11
  55. package/dist/components/views/AppShellHeader.test.js +18 -1
  56. package/dist/components/views/PlanComparisonPage.d.ts +9 -1
  57. package/dist/components/views/PlanComparisonPage.js +78 -14
  58. package/dist/components/views/PlanComparisonPage.test.js +257 -0
  59. package/dist/components/views/PlansPage.js +127 -36
  60. package/dist/components/views/PlansPage.test.js +294 -12
  61. package/dist/components/views/StandaloneLayout.js +529 -592
  62. package/dist/components/views/WidgetView.js +10 -8
  63. package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
  64. package/dist/components/views/panels/PlanningDrawer.js +270 -55
  65. package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
  66. package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
  67. package/dist/components/views/planningScope.d.ts +20 -0
  68. package/dist/components/views/planningScope.js +25 -0
  69. package/dist/components/views/planningScope.test.d.ts +1 -0
  70. package/dist/components/views/planningScope.test.js +60 -0
  71. package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
  72. package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
  73. package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
  74. package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
  75. package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
  76. package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
  77. package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
  78. package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
  79. package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
  80. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
  81. package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
  82. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
  83. package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
  84. package/dist/config/envSchema.js +1 -0
  85. package/dist/core/AiProfileService.d.ts +46 -2
  86. package/dist/core/AiProfileService.js +1073 -82
  87. package/dist/core/AiProfileService.test.js +19 -1
  88. package/dist/core/AiProfiles.test.js +1249 -44
  89. package/dist/core/AttachmentLinkService.d.ts +3 -0
  90. package/dist/core/AttachmentLinkService.js +110 -23
  91. package/dist/core/AuthIdentityService.d.ts +107 -0
  92. package/dist/core/AuthIdentityService.js +284 -0
  93. package/dist/core/AuthTokenService.d.ts +4 -0
  94. package/dist/core/AuthTokenService.js +34 -6
  95. package/dist/core/AuthTokenService.test.js +3 -3
  96. package/dist/core/EntitlementsPolicy.test.js +2 -2
  97. package/dist/core/GlobalSettingsService.js +127 -6
  98. package/dist/core/McpTokenService.d.ts +12 -0
  99. package/dist/core/McpTokenService.js +44 -1
  100. package/dist/core/PlanEntitlementService.d.ts +23 -2
  101. package/dist/core/PlanEntitlementService.js +343 -57
  102. package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
  103. package/dist/core/PlanFeatureCatalog.test.js +84 -0
  104. package/dist/core/PlanVersionPolicy.test.js +35 -2
  105. package/dist/core/PlanningEntities.test.js +418 -4
  106. package/dist/core/SignupMonetizationSettings.test.js +199 -27
  107. package/dist/core/SyncReconciliationService.js +2 -65
  108. package/dist/core/SystemAdmin.test.js +42 -42
  109. package/dist/core/TaskActivityService.d.ts +28 -1
  110. package/dist/core/TaskActivityService.js +227 -46
  111. package/dist/core/TaskActivitySync.test.d.ts +1 -0
  112. package/dist/core/TaskActivitySync.test.js +90 -0
  113. package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
  114. package/dist/core/TaskAuditTimeline.test.js +96 -0
  115. package/dist/core/Taskforce.d.ts +415 -40
  116. package/dist/core/Taskforce.ids.test.js +58 -0
  117. package/dist/core/Taskforce.js +1543 -266
  118. package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
  119. package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
  120. package/dist/core/Taskforce.mcpAuth.test.js +109 -0
  121. package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
  122. package/dist/core/WorkspaceLifecycleService.js +0 -5
  123. package/dist/core/WorkspacePermissions.test.js +25 -1
  124. package/dist/core/WorkspacePlanMode.test.js +117 -16
  125. package/dist/core/shared.d.ts +1 -1
  126. package/dist/core/shared.js +5 -1
  127. package/dist/core/types.d.ts +75 -2
  128. package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
  129. package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
  130. package/dist/hooks/bootstrapTimeouts.js +8 -0
  131. package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
  132. package/dist/hooks/bootstrapTimeouts.test.js +12 -0
  133. package/dist/hooks/sync/bootstrap.js +2 -0
  134. package/dist/hooks/sync/controlPlane.d.ts +37 -0
  135. package/dist/hooks/sync/controlPlane.js +78 -0
  136. package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
  137. package/dist/hooks/sync/controlPlane.test.js +121 -0
  138. package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
  139. package/dist/hooks/sync/lifecyclePolicy.js +93 -0
  140. package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
  141. package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
  142. package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
  143. package/dist/hooks/sync/orchestratorShared.js +129 -48
  144. package/dist/hooks/sync/orchestratorShared.test.js +50 -1
  145. package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
  146. package/dist/hooks/sync/pullLifecycle.js +24 -0
  147. package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
  148. package/dist/hooks/sync/pullLifecycle.test.js +80 -0
  149. package/dist/hooks/sync/recovery.d.ts +16 -2
  150. package/dist/hooks/sync/recovery.js +179 -53
  151. package/dist/hooks/sync/recovery.test.d.ts +1 -0
  152. package/dist/hooks/sync/recovery.test.js +292 -0
  153. package/dist/hooks/sync/transfers.d.ts +16 -3
  154. package/dist/hooks/sync/transfers.js +210 -66
  155. package/dist/hooks/sync/transfers.test.d.ts +1 -0
  156. package/dist/hooks/sync/transfers.test.js +928 -0
  157. package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
  158. package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
  159. package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
  160. package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
  161. package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
  162. package/dist/hooks/sync/useSyncStatusActions.js +88 -0
  163. package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
  164. package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
  165. package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
  166. package/dist/hooks/sync/useSyncStatusControls.js +60 -0
  167. package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
  168. package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
  169. package/dist/hooks/useFilterSort.js +13 -13
  170. package/dist/hooks/useFilterSort.test.js +87 -1
  171. package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
  172. package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
  173. package/dist/hooks/useSyncOrchestrator.js +409 -183
  174. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
  175. package/dist/hooks/useTaskData.js +8 -3
  176. package/dist/hooks/useTaskData.test.js +45 -0
  177. package/dist/hooks/useTaskforce.d.ts +145 -52
  178. package/dist/hooks/useTaskforce.js +592 -253
  179. package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
  180. package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
  181. package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
  182. package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
  183. package/dist/hooks/useWorkspaceSyncController.js +13 -2
  184. package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
  185. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
  186. package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
  187. package/dist/localization/locales/en-US.d.ts +0 -1
  188. package/dist/localization/locales/en-US.js +0 -1
  189. package/dist/localization/locales/es-419.js +0 -1
  190. package/dist/localization/locales/pt-BR.js +0 -1
  191. package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
  192. package/dist/mcp/canonicalAssetHelpers.js +18 -10
  193. package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
  194. package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
  195. package/dist/mcp/clientIntegrations.d.ts +1 -0
  196. package/dist/mcp/clientIntegrations.js +25 -0
  197. package/dist/mcp/clientIntegrations.test.js +14 -3
  198. package/dist/mcp/clientProfileDefaults.js +3 -3
  199. package/dist/mcp/collaborationRegistrar.js +7 -7
  200. package/dist/mcp/documentAssetRegistrar.js +116 -10
  201. package/dist/mcp/runtime.d.ts +3 -0
  202. package/dist/mcp/runtime.js +1099 -185
  203. package/dist/mcp/runtime.test.js +1491 -140
  204. package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
  205. package/dist/mcp/taskPlanningRegistrar.js +48 -0
  206. package/dist/mcp/toolRegistry.d.ts +56 -0
  207. package/dist/mcp/toolRegistry.js +8 -0
  208. package/dist/mcp/toolRegistry.test.js +4 -0
  209. package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
  210. package/dist/migrations/taskSchemaMigrations.js +192 -61
  211. package/dist/migrations/taskSchemaMigrations.test.js +15 -0
  212. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  213. package/dist/resources/templates/workflows/collaborate.yaml +1 -1
  214. package/dist/resources/templates/workflows/evaluate.yaml +2 -2
  215. package/dist/resources/templates/workflows/plan.yaml +1 -1
  216. package/dist/resources/templates/workflows/review.yaml +2 -2
  217. package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
  218. package/dist/server/aiProfileAvatarAssets.js +319 -0
  219. package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
  220. package/dist/server/aiProfileAvatarAssets.test.js +213 -0
  221. package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
  222. package/dist/server/auth/providers/apple.d.ts +33 -0
  223. package/dist/server/auth/providers/apple.js +82 -0
  224. package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
  225. package/dist/server/auth/providers/appleClientSecret.js +65 -0
  226. package/dist/server/auth/providers/github.d.ts +26 -0
  227. package/dist/server/auth/providers/github.js +86 -0
  228. package/dist/server/auth/providers/google.d.ts +21 -0
  229. package/dist/server/auth/providers/google.js +56 -0
  230. package/dist/server/auth/providers/types.d.ts +21 -0
  231. package/dist/server/auth/providers/types.js +1 -0
  232. package/dist/server/auth.d.ts +2 -0
  233. package/dist/server/auth.js +6 -3
  234. package/dist/server/documentReviewRoutes.test.js +36 -3
  235. package/dist/server/index.cookieProxy.test.js +1 -0
  236. package/dist/server/index.d.ts +12 -0
  237. package/dist/server/index.js +124 -9
  238. package/dist/server/index.rateLimit.test.js +3 -0
  239. package/dist/server/index.test.js +111 -3
  240. package/dist/server/routes/admin.d.ts +3 -0
  241. package/dist/server/routes/admin.js +459 -28
  242. package/dist/server/routes/annotatedAttachments.js +51 -0
  243. package/dist/server/routes/auth.d.ts +26 -2
  244. package/dist/server/routes/auth.js +1170 -71
  245. package/dist/server/routes/authSupport.d.ts +5 -1
  246. package/dist/server/routes/authSupport.js +13 -2
  247. package/dist/server/routes/billing.js +372 -35
  248. package/dist/server/routes/billing.test.js +595 -12
  249. package/dist/server/routes/documents.d.ts +1 -0
  250. package/dist/server/routes/documents.js +182 -70
  251. package/dist/server/routes/shared.d.ts +28 -2
  252. package/dist/server/routes/shared.js +69 -14
  253. package/dist/server/routes/sync.integration.test.js +658 -39
  254. package/dist/server/routes/sync.js +74 -608
  255. package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
  256. package/dist/server/routes/syncAuxRoutes.js +91 -0
  257. package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
  258. package/dist/server/routes/syncAuxRoutes.test.js +158 -0
  259. package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
  260. package/dist/server/routes/syncPullApplyRoutes.js +204 -0
  261. package/dist/server/routes/syncPushRoutes.d.ts +24 -0
  262. package/dist/server/routes/syncPushRoutes.js +212 -0
  263. package/dist/server/routes/syncRouteGuards.d.ts +36 -0
  264. package/dist/server/routes/syncRouteGuards.js +67 -0
  265. package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
  266. package/dist/server/routes/syncRouteGuards.test.js +94 -0
  267. package/dist/server/routes/syncRouteTypes.d.ts +13 -0
  268. package/dist/server/routes/syncRouteTypes.js +1 -0
  269. package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
  270. package/dist/server/routes/syncSnapshotRoutes.js +182 -0
  271. package/dist/server/routes/tasks.js +55 -10
  272. package/dist/server/routes/workspaces.js +36 -5
  273. package/dist/server/routes.js +147 -11
  274. package/dist/server/routes.test.js +2704 -183
  275. package/dist/services/workflowExportSnapshots.test.js +2 -0
  276. package/dist/shared/aiProfileSeatScope.d.ts +5 -0
  277. package/dist/shared/aiProfileSeatScope.js +21 -0
  278. package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
  279. package/dist/shared/aiProfileSurfaceType.js +10 -8
  280. package/dist/shared/passwordPolicy.d.ts +13 -0
  281. package/dist/shared/passwordPolicy.js +84 -0
  282. package/dist/shared/passwordPolicy.test.d.ts +1 -0
  283. package/dist/shared/passwordPolicy.test.js +34 -0
  284. package/dist/storage/objectStorage.d.ts +1 -0
  285. package/dist/storage/objectStorage.js +2 -1
  286. package/dist/storage/objectStorageClient.d.ts +1 -0
  287. package/dist/storage/objectStorageClient.js +41 -8
  288. package/dist/storage/objectStorageClient.test.js +26 -1
  289. package/dist/storage/objectStorageConfig.js +3 -1
  290. package/dist/storage/objectStorageConfig.test.js +13 -1
  291. package/dist/storage/workspaceAssetStore.d.ts +15 -3
  292. package/dist/storage/workspaceAssetStore.js +132 -44
  293. package/dist/storage/workspaceAssetStore.test.js +93 -6
  294. package/dist/styles/fonts.css +70 -0
  295. package/dist/sync/collaborationSyncPayload.d.ts +6 -1
  296. package/dist/sync/collaborationSyncPayload.js +19 -11
  297. package/dist/sync/collaborationSyncPayload.test.js +14 -1
  298. package/dist/sync/collaborationSyncState.d.ts +3 -3
  299. package/dist/sync/collaborationSyncState.js +19 -12
  300. package/dist/sync/contentSyncPayload.d.ts +5 -1
  301. package/dist/sync/contentSyncPayload.js +9 -0
  302. package/dist/sync/contentSyncPayload.test.js +39 -0
  303. package/dist/sync/contentSyncState.d.ts +9 -9
  304. package/dist/sync/contentSyncState.js +248 -107
  305. package/dist/sync/planningSyncPayload.js +5 -0
  306. package/dist/sync/planningSyncPayload.test.js +24 -0
  307. package/dist/sync/syncApplyHandlers.d.ts +11 -4
  308. package/dist/sync/syncApplyHandlers.js +115 -42
  309. package/dist/sync/syncApplyHandlers.test.js +251 -4
  310. package/dist/sync/syncFieldSemantics.d.ts +12 -0
  311. package/dist/sync/syncFieldSemantics.js +55 -0
  312. package/dist/sync/syncResourceAdapters.d.ts +46 -0
  313. package/dist/sync/syncResourceAdapters.js +79 -0
  314. package/dist/sync/syncService.d.ts +6 -0
  315. package/dist/sync/syncService.js +65 -1
  316. package/dist/sync/syncService.test.js +96 -3
  317. package/dist/sync/taskSyncChangeKey.d.ts +2 -0
  318. package/dist/sync/taskSyncChangeKey.js +143 -0
  319. package/dist/sync/taskSyncPayload.js +3 -8
  320. package/dist/sync/workspacePullFeed.d.ts +4 -0
  321. package/dist/sync/workspacePullFeed.js +132 -72
  322. package/dist/sync/workspacePullFeed.test.js +92 -0
  323. package/dist/sync/workspaceRepair.js +5 -2
  324. package/dist/sync/workspaceSyncModel.d.ts +73 -6
  325. package/dist/sync/workspaceSyncModel.js +342 -73
  326. package/dist/sync/workspaceSyncModel.test.js +559 -14
  327. package/dist/sync/workspaceSyncState.d.ts +17 -0
  328. package/dist/sync/workspaceSyncState.js +2 -1
  329. package/dist/sync/workspaceSyncSurface.js +3 -8
  330. package/dist/types.d.ts +50 -2
  331. package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
  332. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
  333. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
  334. package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
  335. package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
  336. package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
  337. package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
  338. package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
  339. package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
  340. package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
  341. package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
  342. package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
  343. package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
  344. package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
  345. package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
  346. package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
  347. package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
  348. package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
  349. package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
  350. package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
  351. package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
  352. package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
  353. package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
  354. package/dist/ui/assets/index-607WPo_X.js +4 -0
  355. package/dist/ui/assets/index-CYyodXsg.css +1 -0
  356. package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
  357. package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
  358. package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
  359. package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
  360. package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
  361. package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
  362. package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
  363. package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
  364. package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
  365. package/dist/ui/fonts/Noir_medium.otf +0 -0
  366. package/dist/ui/fonts/Noir_medium.woff2 +0 -0
  367. package/dist/ui/fonts/Noir_regular.otf +0 -0
  368. package/dist/ui/fonts/Noir_regular.woff2 +0 -0
  369. package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
  370. package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
  371. package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
  372. package/dist/ui/index.html +3 -3
  373. package/dist/ui/product/agent manager.png +0 -0
  374. package/dist/ui/product/agent_manager_02.png +0 -0
  375. package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
  376. package/dist/utils/aiProfileEvents.d.ts +7 -0
  377. package/dist/utils/aiProfileEvents.js +6 -0
  378. package/dist/utils/assignees.d.ts +8 -0
  379. package/dist/utils/assignees.js +10 -1
  380. package/dist/utils/assignees.test.d.ts +1 -0
  381. package/dist/utils/assignees.test.js +25 -0
  382. package/dist/utils/avatarDisplay.d.ts +1 -0
  383. package/dist/utils/avatarDisplay.js +15 -0
  384. package/dist/utils/avatarUpload.d.ts +27 -0
  385. package/dist/utils/avatarUpload.js +132 -0
  386. package/dist/utils/avatarUpload.test.d.ts +1 -0
  387. package/dist/utils/avatarUpload.test.js +40 -0
  388. package/dist/utils/bootstrapTrace.d.ts +7 -0
  389. package/dist/utils/bootstrapTrace.js +29 -0
  390. package/dist/utils/commercialLifecyclePresentation.js +3 -0
  391. package/dist/utils/contextAssetEvents.d.ts +2 -0
  392. package/dist/utils/contextFiles.d.ts +3 -1
  393. package/dist/utils/contextFiles.js +2 -1
  394. package/dist/utils/syncEventDetails.d.ts +3 -0
  395. package/dist/utils/syncEventDetails.js +64 -0
  396. package/dist/utils/syncEventDetails.test.d.ts +1 -0
  397. package/dist/utils/syncEventDetails.test.js +23 -0
  398. package/dist/utils/syncEventPresentation.d.ts +15 -0
  399. package/dist/utils/syncEventPresentation.js +129 -0
  400. package/dist/utils/syncEventPresentation.test.d.ts +1 -0
  401. package/dist/utils/syncEventPresentation.test.js +64 -0
  402. package/dist/utils/syncStatusPresentation.d.ts +72 -0
  403. package/dist/utils/syncStatusPresentation.js +217 -0
  404. package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
  405. package/dist/utils/syncStatusPresentation.test.js +164 -0
  406. package/dist/utils/taskActivity.d.ts +9 -1
  407. package/dist/utils/taskActivity.js +290 -22
  408. package/dist/utils/taskActivity.test.js +141 -8
  409. package/dist/utils/taskSearch.d.ts +22 -0
  410. package/dist/utils/taskSearch.js +87 -0
  411. package/dist/utils/taskSearch.test.d.ts +1 -0
  412. package/dist/utils/taskSearch.test.js +69 -0
  413. package/dist/utils/taskUtils.js +10 -3
  414. package/dist/utils/taskUtils.test.d.ts +1 -0
  415. package/dist/utils/taskUtils.test.js +19 -0
  416. package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
  417. package/dist/utils/workspaceSyncPresentation.js +68 -2
  418. package/dist/utils/workspaceSyncPresentation.test.js +36 -1
  419. package/package.json +3 -2
  420. package/scripts/export-sqlite-to-postgres.mjs +7 -9
  421. package/scripts/run-e2e-realtime.sh +17 -3
  422. package/scripts/run-smoke.sh +17 -5
  423. package/scripts/run-soak.sh +17 -5
  424. package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
  425. package/src/resources/templates/workflows/collaborate.yaml +1 -1
  426. package/src/resources/templates/workflows/evaluate.yaml +2 -2
  427. package/src/resources/templates/workflows/plan.yaml +1 -1
  428. package/src/resources/templates/workflows/review.yaml +2 -2
  429. package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
  430. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
  431. package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
  432. package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
  433. package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
  434. package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
  435. package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
  436. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  437. package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
  438. package/dist/ui/assets/index-C2-OXZV7.css +0 -1
  439. package/dist/ui/assets/index-DcSI5F86.js +0 -6
  440. package/scripts/migrate-planning-model.ts +0 -233
@@ -3,7 +3,7 @@ import React, { useEffect, useMemo, useState } from 'react';
3
3
  import { Sun, Moon, Sparkles, Keyboard, FileText, Check, AlertTriangle, Loader2, Settings, Layers, Box, Copy, Trash2, Terminal, Bot, Codepen, Command, Wind, Github, Zap, ChevronDown, ChevronRight, Plug } from 'lucide-react';
4
4
  import styles from '../../Taskforce.module.css';
5
5
  import { TASKFORCE_THEME_OPTIONS } from '../../utils/theme';
6
- import { MCP_CLIENT_OPTIONS, buildCloudMcpClientIntegration, buildLocalMcpClientIntegration, buildCloudMcpServerId, sanitizeMcpId } from '../../mcp/clientIntegrations';
6
+ import { MCP_CLIENT_OPTIONS, buildCloudMcpClientIntegration, buildLocalMcpClientIntegration, buildCloudMcpServerId, buildLocalAiProfileEnv, sanitizeMcpId } from '../../mcp/clientIntegrations';
7
7
  import { resolveTaskforceMcpBaseUrlFromBaseUrl } from '../../config/cloudEnvironment';
8
8
  import { TaxonomyManager } from './settings/TaxonomyManager';
9
9
  const THEME_ICON_MAP = {
@@ -14,8 +14,9 @@ const THEME_ICON_MAP = {
14
14
  };
15
15
  const DEFAULT_MCP_TOKEN_SCOPES = ['tasks:read', 'tasks:write', 'workspace:read'];
16
16
  export function TaskSettings(props) {
17
- const { settingsModel, onSectionChange } = props;
18
- const { currentTheme, globalTheme, themeUseGlobalDefault, keyShortcut, jsonBackupEnabled, globalJsonBackupEnabled, globalWeekStartsOn, locale = 'en-US', supportedLocales = ['en-US', 'es-419', 'pt-BR'], jsonBackupUseGlobalDefault, manualComplexityEnabled, checklistDropdownEnabled = true, showTaskCardStatusLabel = true, exportWorkflowsPath, exportingResource, exportResult, initialSection, onThemeChange, onSaveTheme, onSaveGlobalTheme, onResetProjectToGlobal, onKeyShortcutChange, onJsonBackupEnabledChange, onSaveGlobalJsonBackupEnabled, onSaveGlobalWeekStartsOn, onSaveLocale, onManualComplexityEnabledChange, onChecklistDropdownEnabledChange, onShowTaskCardStatusLabelChange, onSaveSettings, onExportWorkflowsPathChange, 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, workspaceSwitchingEnabled = false, currentWorkspaceRole = 'member', currentWorkspaceName = '', onDeleteWorkspace, onMcpHostRootChange, isAuthenticated = false, exportEnvironment, setupState = null, buildInfo = null, onExportEnvironmentChange, onSaveSetupMode, onSaveWorkspaceProfile, availableWorkflows = [], onExportWorkflows, initiativeTemplates = [], onRefreshInitiativeTemplates, onCreateInitiativeFromTemplate, onRefreshWorkflows } = settingsModel;
17
+ const { settingsModel, onSectionChange, renderMode = 'full' } = props;
18
+ const isMcpOnly = renderMode === 'mcp-only';
19
+ const { currentTheme, globalTheme, themeUseGlobalDefault, keyShortcut, jsonBackupEnabled, globalJsonBackupEnabled, globalWeekStartsOn, locale = 'en-US', supportedLocales = ['en-US', 'es-419', 'pt-BR'], jsonBackupUseGlobalDefault, manualComplexityEnabled, checklistDropdownEnabled = true, showTaskCardStatusLabel = true, exportWorkflowsPath, exportingResource, exportResult, initialSection, onThemeChange, onSaveTheme, onSaveGlobalTheme, onResetProjectToGlobal, onKeyShortcutChange, onJsonBackupEnabledChange, onSaveGlobalJsonBackupEnabled, onSaveGlobalWeekStartsOn, onSaveLocale, onManualComplexityEnabledChange, onChecklistDropdownEnabledChange, onShowTaskCardStatusLabelChange, onSaveSettings, onExportWorkflowsPathChange, 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, workspaceSwitchingEnabled = false, currentWorkspaceRole = 'member', currentWorkspaceName = '', onDeleteWorkspace, onMcpHostRootChange, onOpenCloudAuth, isAuthenticated = false, exportEnvironment, setupState = null, buildInfo = null, onExportEnvironmentChange, onSaveSetupMode, onSaveWorkspaceProfile, availableWorkflows = [], onExportWorkflows, initiativeTemplates = [], onRefreshInitiativeTemplates, onCreateInitiativeFromTemplate, onRefreshWorkflows } = settingsModel;
19
20
  const showJsonBackupSettings = runtimeMode !== 'cloud';
20
21
  // Workflow Selection State
21
22
  const [selectedWorkflows, setSelectedWorkflows] = useState([]);
@@ -39,7 +40,7 @@ export function TaskSettings(props) {
39
40
  const [selectedInitiativeTemplateId, setSelectedInitiativeTemplateId] = useState('');
40
41
  const [initiativeTitle, setInitiativeTitle] = useState('');
41
42
  const [isCreatingInitiative, setIsCreatingInitiative] = useState(false);
42
- const [activeTab, setActiveTab] = useState('general');
43
+ const [activeTab, setActiveTab] = useState(() => isMcpOnly ? 'mcp' : 'general');
43
44
  const [appearanceExpanded, setAppearanceExpanded] = useState(true);
44
45
  const [generalScopeTab, setGeneralScopeTab] = useState(() => {
45
46
  return 'project';
@@ -64,7 +65,6 @@ export function TaskSettings(props) {
64
65
  ? data.assignees.filter((a) => a.kind === 'agent').map((a) => ({
65
66
  id: String(a.value || ''),
66
67
  name: String(a.label || ''),
67
- profileToken: typeof a.profileToken === 'string' ? a.profileToken : null,
68
68
  username: String(a.username || a.value || ''),
69
69
  icon: String(a.icon || 'Bot'),
70
70
  color: String(a.color || '#6B7280'),
@@ -145,7 +145,6 @@ export function TaskSettings(props) {
145
145
  const Icon = THEME_ICON_MAP[themeOption.icon];
146
146
  return (_jsxs("button", { className: `${styles.themeBtn} tf-button-tile ${activeTheme === themeOption.id ? styles.activeTheme : ''}`, onClick: () => { void onSelect(themeOption.id); }, children: [_jsx(Icon, { size: 20 }), " ", themeOption.label] }, themeOption.id));
147
147
  };
148
- const cloudMcpAvailable = runtimeMode === 'cloud' || isAuthenticated;
149
148
  const defaultMcpMode = runtimeMode === 'cloud'
150
149
  ? 'cloud'
151
150
  : 'local';
@@ -153,7 +152,6 @@ export function TaskSettings(props) {
153
152
  const [copiedConfig, setCopiedConfig] = useState(false);
154
153
  const [useGlobalMcp, setUseGlobalMcp] = useState(true);
155
154
  const [showAdvancedMcp, setShowAdvancedMcp] = useState(false);
156
- const [showMcpConnectionTest, setShowMcpConnectionTest] = useState(false);
157
155
  const [showMcpTokensList, setShowMcpTokensList] = useState(true);
158
156
  const [mcpTokens, setMcpTokens] = useState([]);
159
157
  const [mcpTokensLoading, setMcpTokensLoading] = useState(false);
@@ -169,10 +167,11 @@ export function TaskSettings(props) {
169
167
  }, [currentWorkspaceName, setupState?.workspace?.name, projectName, workspaceId]);
170
168
  const [newTokenName, setNewTokenName] = useState(defaultTokenName);
171
169
  const [newTokenExpiresAt, setNewTokenExpiresAt] = useState('');
172
- const [mcpTokenNotice, setMcpTokenNotice] = useState(null);
170
+ const [mcpTokenIssueNotice, setMcpTokenIssueNotice] = useState(null);
171
+ const [mcpConfigNotice, setMcpConfigNotice] = useState(null);
172
+ const [mcpTokenListNotice, setMcpTokenListNotice] = useState(null);
173
173
  const [generatedTokenValue, setGeneratedTokenValue] = useState(null);
174
174
  const [selectedMcpClient, setSelectedMcpClient] = useState('general');
175
- const [mcpConnectionToken, setMcpConnectionToken] = useState('');
176
175
  const [mcpConnectionBusy, setMcpConnectionBusy] = useState(false);
177
176
  const [mcpConnectionResult, setMcpConnectionResult] = useState(null);
178
177
  const [mcpConnectorGrants, setMcpConnectorGrants] = useState([]);
@@ -186,17 +185,23 @@ export function TaskSettings(props) {
186
185
  setNewTokenName((current) => current.trim().length > 0 ? current : defaultTokenName);
187
186
  }, [defaultTokenName]);
188
187
  useEffect(() => {
189
- if (!mcpTokenNotice)
188
+ if (!mcpTokenIssueNotice)
190
189
  return;
191
- const timer = setTimeout(() => setMcpTokenNotice(null), 3500);
190
+ const timer = setTimeout(() => setMcpTokenIssueNotice(null), 3500);
192
191
  return () => clearTimeout(timer);
193
- }, [mcpTokenNotice]);
192
+ }, [mcpTokenIssueNotice]);
194
193
  useEffect(() => {
195
- if (!generatedTokenValue)
194
+ if (!mcpConfigNotice)
196
195
  return;
197
- setMcpConnectionToken(generatedTokenValue);
198
- setMcpConnectionResult(null);
199
- }, [generatedTokenValue]);
196
+ const timer = setTimeout(() => setMcpConfigNotice(null), 3500);
197
+ return () => clearTimeout(timer);
198
+ }, [mcpConfigNotice]);
199
+ useEffect(() => {
200
+ if (!mcpTokenListNotice)
201
+ return;
202
+ const timer = setTimeout(() => setMcpTokenListNotice(null), 3500);
203
+ return () => clearTimeout(timer);
204
+ }, [mcpTokenListNotice]);
200
205
  const cloudMcpEndpoint = useMemo(() => {
201
206
  const inferredMcpBase = resolveTaskforceMcpBaseUrlFromBaseUrl(cloudMcpBaseUrl || cloudAuthBaseUrl || '');
202
207
  const configuredBase = String(inferredMcpBase || cloudMcpBaseUrl || cloudAuthBaseUrl || '').trim().replace(/\/+$/, '');
@@ -207,9 +212,10 @@ export function TaskSettings(props) {
207
212
  return `${window.location.origin.replace(/\/+$/, '')}/mcp`;
208
213
  }, [cloudMcpBaseUrl, cloudAuthBaseUrl]);
209
214
  const localMcpEnabled = runtimeMode !== 'cloud';
210
- const showMcpModeToggle = localMcpEnabled && cloudMcpAvailable;
215
+ const showMcpModeToggle = localMcpEnabled;
211
216
  const showCloudMcp = runtimeMode === 'cloud' || selectedMcpMode === 'cloud';
212
- const showLocalMcp = runtimeMode !== 'cloud' && (!cloudMcpAvailable || selectedMcpMode === 'local');
217
+ const showLocalMcp = runtimeMode !== 'cloud' && selectedMcpMode === 'local';
218
+ const canUseCloudMcp = isAuthenticated;
213
219
  const sortedMcpTokens = useMemo(() => {
214
220
  const statusRank = {
215
221
  active: 0,
@@ -224,7 +230,8 @@ export function TaskSettings(props) {
224
230
  });
225
231
  }, [mcpTokens]);
226
232
  const cloudMcpServerId = useMemo(() => buildCloudMcpServerId(currentWorkspaceName || null, projectName || null), [currentWorkspaceName, projectName]);
227
- const cloudMcpTokenValue = generatedTokenValue || '<<GENERATE_TOKEN>>';
233
+ const currentMcpTokenValue = generatedTokenValue?.trim() || '';
234
+ const cloudMcpTokenValue = currentMcpTokenValue || '<<GENERATE_TOKEN>>';
228
235
  // Launch decision: keep generated Cloud MCP config identity-neutral for shared connections.
229
236
  const cloudClientIntegration = useMemo(() => buildCloudMcpClientIntegration({
230
237
  clientId: selectedMcpClient,
@@ -241,6 +248,7 @@ export function TaskSettings(props) {
241
248
  ? cloudClientIntegration.serverConfig ?? null
242
249
  : null;
243
250
  const selectedMcpClientUsesOAuth = selectedMcpClient === 'chatgpt-desktop' || selectedMcpClient === 'claude-desktop';
251
+ const agentRegistrationPrompt = 'Resolve your profile with Taskforce.';
244
252
  const activeChatGptConnector = useMemo(() => mcpConnectorGrants.find((grant) => grant.provider === 'chatgpt' && grant.status === 'active') || null, [mcpConnectorGrants]);
245
253
  const activeClaudeConnector = useMemo(() => mcpConnectorGrants.find((grant) => grant.provider === 'claude' && grant.status === 'active') || null, [mcpConnectorGrants]);
246
254
  const selectedConnectorGrant = selectedMcpClient === 'chatgpt-desktop'
@@ -287,14 +295,17 @@ export function TaskSettings(props) {
287
295
  setCopiedConfig(mode);
288
296
  setTimeout(() => setCopiedConfig(false), 2000);
289
297
  };
298
+ const renderMcpProfilePrompt = () => (_jsxs("div", { className: styles.mcpRegistrationHint, children: [_jsx("span", { children: "Once the MCP is configured, prompt your agent:" }), _jsx("button", { type: "button", className: styles.mcpRegistrationPrompt, onClick: () => copyToClipboard(agentRegistrationPrompt, 'registration'), title: copiedConfig === 'registration' ? 'Copied' : 'Copy prompt', children: agentRegistrationPrompt })] }));
299
+ const renderCloudMcpAuthRequired = () => (_jsxs("div", { className: `${styles.mcpAuthRequiredCard} ${styles.marginTop16}`, children: [_jsx("div", { className: styles.mcpAuthRequiredIcon, children: _jsx(Plug, { size: 20 }) }), _jsxs("div", { className: styles.mcpAuthRequiredBody, children: [_jsx("h3", { className: styles.settingTitle, children: "Sign in to use Cloud MCP" }), _jsx("p", { className: styles.settingDescription, children: "Cloud MCP connects remote agents through your Taskforce cloud account. Register or sign in to generate cloud MCP tokens, copy client configuration, and connect hosted MCP agents to this workspace." }), onOpenCloudAuth && (_jsxs("div", { className: styles.mcpAuthRequiredActions, children: [_jsx("button", { type: "button", className: styles.copyBtn, onClick: () => onOpenCloudAuth('login'), children: "Sign In" }), _jsx("button", { type: "button", className: styles.copyBtn, onClick: () => onOpenCloudAuth('register'), children: "Register" })] }))] })] }));
290
300
  const handleCopyCloudMcpConfig = () => {
291
- if (!selectedMcpClientUsesOAuth && !generatedTokenValue) {
292
- setMcpTokenNotice({
301
+ if (!selectedMcpClientUsesOAuth && !currentMcpTokenValue) {
302
+ setMcpConfigNotice({
293
303
  type: 'error',
294
304
  message: 'Generate a token before copying the Cloud MCP configuration.'
295
305
  });
296
306
  return;
297
307
  }
308
+ setMcpConfigNotice(null);
298
309
  copyToClipboard(cloudMcpFullConfig, 'full');
299
310
  };
300
311
  const buildMcpServerConfig = () => {
@@ -321,7 +332,8 @@ export function TaskSettings(props) {
321
332
  : 'your-workspace-id';
322
333
  const env = {
323
334
  TASKFORCE_TENANT_ID: resolvedTenantId,
324
- TASKFORCE_WORKSPACE_ID: resolvedWorkspaceId
335
+ TASKFORCE_WORKSPACE_ID: resolvedWorkspaceId,
336
+ ...buildLocalAiProfileEnv(selectedMcpClient)
325
337
  };
326
338
  const serverConfig = useGlobalMcp
327
339
  ? {
@@ -350,6 +362,7 @@ export function TaskSettings(props) {
350
362
  tenantId,
351
363
  workspaceId,
352
364
  setupState?.workspaceId,
365
+ selectedMcpClient,
353
366
  useGlobalMcp
354
367
  ]);
355
368
  const localClientIntegration = useMemo(() => buildLocalMcpClientIntegration({
@@ -383,7 +396,7 @@ export function TaskSettings(props) {
383
396
  copyToClipboard(toCopy, mode);
384
397
  };
385
398
  const loadMcpTokens = async () => {
386
- if (!cloudMcpAvailable)
399
+ if (!canUseCloudMcp)
387
400
  return;
388
401
  setMcpTokensLoading(true);
389
402
  setMcpTokensError(null);
@@ -407,7 +420,7 @@ export function TaskSettings(props) {
407
420
  }
408
421
  };
409
422
  const loadMcpConnectors = async () => {
410
- if (!cloudMcpAvailable)
423
+ if (!canUseCloudMcp)
411
424
  return;
412
425
  setMcpConnectorsLoading(true);
413
426
  setMcpConnectorsError(null);
@@ -433,11 +446,12 @@ export function TaskSettings(props) {
433
446
  const handleCreateMcpToken = async () => {
434
447
  const trimmedName = newTokenName.trim();
435
448
  if (!trimmedName) {
436
- setMcpTokenNotice({ type: 'error', message: 'Token name is required.' });
449
+ setMcpTokenIssueNotice({ type: 'error', message: 'Token name is required.' });
437
450
  return;
438
451
  }
439
452
  setMcpActionBusyId('create');
440
- setMcpTokenNotice(null);
453
+ setMcpTokenIssueNotice(null);
454
+ setMcpConnectionResult(null);
441
455
  try {
442
456
  const res = await fetchCloudAuthApi('/api/taskforce/settings/mcp/tokens', {
443
457
  method: 'POST',
@@ -451,10 +465,11 @@ export function TaskSettings(props) {
451
465
  });
452
466
  const payload = await res.json().catch(() => ({}));
453
467
  if (!res.ok) {
454
- setMcpTokenNotice({ type: 'error', message: String(payload?.error || 'Failed to create token.') });
468
+ setMcpTokenIssueNotice({ type: 'error', message: String(payload?.error || 'Failed to create token.') });
455
469
  return;
456
470
  }
457
471
  setGeneratedTokenValue(String(payload?.token || ''));
472
+ setMcpConnectionResult(null);
458
473
  setNewTokenName(defaultTokenName);
459
474
  setNewTokenExpiresAt('');
460
475
  setMcpTokens((current) => {
@@ -463,31 +478,45 @@ export function TaskSettings(props) {
463
478
  });
464
479
  }
465
480
  catch {
466
- setMcpTokenNotice({ type: 'error', message: 'Failed to create token.' });
481
+ setMcpTokenIssueNotice({ type: 'error', message: 'Failed to create token.' });
467
482
  }
468
483
  finally {
469
484
  setMcpActionBusyId(null);
470
485
  }
471
486
  };
472
487
  const handleMcpTokenAction = async (tokenId, action) => {
488
+ if (action === 'delete' && !window.confirm('Delete this token record? This does not affect active tokens.')) {
489
+ return;
490
+ }
473
491
  setMcpActionBusyId(`${action}:${tokenId}`);
474
- setMcpTokenNotice(null);
492
+ setMcpTokenListNotice(null);
475
493
  try {
476
- const res = await fetchCloudAuthApi(`/api/taskforce/settings/mcp/tokens/${encodeURIComponent(tokenId)}/${action}`, {
477
- method: 'POST',
494
+ const path = action === 'delete'
495
+ ? `/api/taskforce/settings/mcp/tokens/${encodeURIComponent(tokenId)}`
496
+ : `/api/taskforce/settings/mcp/tokens/${encodeURIComponent(tokenId)}/${action}`;
497
+ const res = await fetchCloudAuthApi(path, {
498
+ method: action === 'delete' ? 'DELETE' : 'POST',
478
499
  credentials: 'include'
479
500
  });
480
501
  const payload = await res.json().catch(() => ({}));
481
502
  if (!res.ok) {
482
- setMcpTokenNotice({ type: 'error', message: String(payload?.error || `Failed to ${action} token.`) });
503
+ setMcpTokenListNotice({ type: 'error', message: String(payload?.error || `Failed to ${action} token.`) });
483
504
  return;
484
505
  }
485
506
  if (action === 'regenerate') {
486
507
  setGeneratedTokenValue(String(payload?.token || ''));
487
- setMcpTokenNotice({ type: 'success', message: 'Token regenerated. Copy the new value now.' });
508
+ setMcpConnectionResult(null);
509
+ setMcpTokenListNotice({ type: 'success', message: 'Token regenerated. Copy the new value from the Full Token field.' });
510
+ }
511
+ else if (action === 'delete') {
512
+ setMcpTokenListNotice({ type: 'success', message: 'Token deleted.' });
488
513
  }
489
514
  else {
490
- setMcpTokenNotice({ type: 'success', message: 'Token revoked.' });
515
+ setMcpTokenListNotice({ type: 'success', message: 'Token revoked.' });
516
+ }
517
+ if (action === 'delete') {
518
+ setMcpTokens((current) => current.filter((item) => item.id !== tokenId));
519
+ return;
491
520
  }
492
521
  const nextRecord = payload?.record || null;
493
522
  if (nextRecord?.id) {
@@ -498,18 +527,18 @@ export function TaskSettings(props) {
498
527
  }
499
528
  }
500
529
  catch {
501
- setMcpTokenNotice({ type: 'error', message: `Failed to ${action} token.` });
530
+ setMcpTokenListNotice({ type: 'error', message: `Failed to ${action} token.` });
502
531
  }
503
532
  finally {
504
533
  setMcpActionBusyId(null);
505
534
  }
506
535
  };
507
536
  const handleTestMcpConnection = async () => {
508
- const trimmedToken = mcpConnectionToken.trim();
537
+ const trimmedToken = currentMcpTokenValue;
509
538
  if (!trimmedToken) {
510
539
  setMcpConnectionResult({
511
540
  type: 'error',
512
- message: 'Paste a token to test the MCP connection.'
541
+ message: 'Generate or paste a full token before testing the MCP connection.'
513
542
  });
514
543
  return;
515
544
  }
@@ -618,7 +647,7 @@ export function TaskSettings(props) {
618
647
  }
619
648
  };
620
649
  useEffect(() => {
621
- if (!cloudMcpAvailable)
650
+ if (!canUseCloudMcp)
622
651
  return;
623
652
  if (activeTab === 'mcp' && showCloudMcp) {
624
653
  void loadMcpTokens();
@@ -628,7 +657,7 @@ export function TaskSettings(props) {
628
657
  if (activeTab === 'integrations') {
629
658
  void loadMcpConnectors();
630
659
  }
631
- }, [activeTab, showCloudMcp, cloudMcpAvailable]);
660
+ }, [activeTab, showCloudMcp, canUseCloudMcp]);
632
661
  useEffect(() => {
633
662
  if (activeTab === 'initiatives' && initiativeTemplates.length === 0) {
634
663
  onRefreshInitiativeTemplates?.();
@@ -677,6 +706,9 @@ export function TaskSettings(props) {
677
706
  else if (initialSection === 'agents') {
678
707
  setActiveTab('agents');
679
708
  }
709
+ else if (initialSection === 'mcp') {
710
+ setActiveTab(isMcpOnly ? 'mcp' : 'general');
711
+ }
680
712
  else if (initialSection === 'integrations') {
681
713
  setActiveTab('integrations');
682
714
  }
@@ -684,7 +716,7 @@ export function TaskSettings(props) {
684
716
  setActiveTab(initialSection);
685
717
  }
686
718
  }
687
- }, [initialSection]);
719
+ }, [initialSection, isMcpOnly]);
688
720
  useEffect(() => {
689
721
  if (activeTab === 'appearanceApplication' || activeTab === 'appearanceTaskCards' || activeTab === 'appearanceTaskForms') {
690
722
  setAppearanceExpanded(true);
@@ -708,8 +740,7 @@ export function TaskSettings(props) {
708
740
  const settingsNavItems = [
709
741
  { key: 'general', label: 'General', icon: _jsx(Settings, { size: 14 }), section: 'general' },
710
742
  { key: 'taxonomy', label: 'Taxonomy', icon: _jsx(Layers, { size: 14 }), section: 'taxonomy' },
711
- { key: 'integrations', label: 'Integrations', icon: _jsx(Plug, { size: 14 }), section: 'integrations' },
712
- { key: 'mcp', label: 'MCP', icon: _jsx(Box, { size: 14 }), section: 'mcp' }
743
+ { key: 'integrations', label: 'Integrations', icon: _jsx(Plug, { size: 14 }), section: 'integrations' }
713
744
  ];
714
745
  const appearanceNavItems = [
715
746
  { key: 'appearanceApplication', label: 'Application', section: 'appearance-application' },
@@ -737,7 +768,7 @@ export function TaskSettings(props) {
737
768
  message: success ? 'Checklist dropdown setting saved.' : 'Failed to save checklist dropdown setting.'
738
769
  });
739
770
  }, disabled: !onChecklistDropdownEnabledChange }), _jsx("span", { children: "Enable checklist dropdown in task form" })] })] }));
740
- return (_jsx("div", { className: styles.settingsTab, children: _jsxs("div", { className: styles.settingsLayout, children: [_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 () => {
771
+ 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 () => {
741
772
  const confirmed = window.confirm('Reset project Theme and Backups to global defaults?');
742
773
  if (!confirmed)
743
774
  return;
@@ -882,56 +913,30 @@ export function TaskSettings(props) {
882
913
  });
883
914
  }, initialTab: (initialSection === 'categories' || initialSection === 'types' || initialSection === 'priorities')
884
915
  ? initialSection
885
- : undefined })] })), activeTab === 'mcp' && (_jsxs("div", { className: styles.settingsGroup, children: [showMcpModeToggle && (_jsxs("div", { className: styles.settingsTabs, children: [_jsx("button", { className: `${styles.settingsTabBtn} ${selectedMcpMode === 'local' ? styles.settingsTabBtnActive : ''}`, onClick: () => setSelectedMcpMode('local'), children: "Local MCP" }), _jsx("button", { className: `${styles.settingsTabBtn} ${selectedMcpMode === 'cloud' ? styles.settingsTabBtnActive : ''}`, onClick: () => setSelectedMcpMode('cloud'), children: "Cloud MCP" })] })), showCloudMcp && (_jsx(_Fragment, { children: selectedMcpClientUsesOAuth ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "OAuth Connector Setup" }), _jsx("span", { className: styles.settingDescription, children: selectedMcpClient === 'chatgpt-desktop'
916
+ : undefined })] })), activeTab === 'mcp' && (_jsxs("div", { className: styles.settingsGroup, children: [showMcpModeToggle && (_jsxs("div", { className: styles.settingsTabs, children: [_jsx("button", { className: `${styles.settingsTabBtn} ${selectedMcpMode === 'local' ? styles.settingsTabBtnActive : ''}`, onClick: () => setSelectedMcpMode('local'), children: "Local MCP" }), _jsx("button", { className: `${styles.settingsTabBtn} ${selectedMcpMode === 'cloud' ? styles.settingsTabBtnActive : ''}`, onClick: () => setSelectedMcpMode('cloud'), children: "Cloud MCP" })] })), showCloudMcp && !canUseCloudMcp && (_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." })] }) }), renderCloudMcpAuthRequired()] })), showCloudMcp && canUseCloudMcp && (_jsx(_Fragment, { children: selectedMcpClientUsesOAuth ? (_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.settingGroup, children: [_jsxs("div", { className: styles.settingLabelGroup, children: [_jsx("h3", { className: styles.settingTitle, children: "OAuth Connector Setup" }), _jsx("span", { className: styles.settingDescription, children: selectedMcpClient === 'chatgpt-desktop'
886
917
  ? 'ChatGPT Desktop uses the Taskforce OAuth connector flow instead of a personal MCP token.'
887
918
  : 'Claude Desktop uses the Taskforce OAuth connector flow instead of a personal MCP token.' })] }), _jsx("div", { className: `${selectedConnectorGrant ? styles.successMessage : styles.settingHelper} ${styles.marginTop12}`, children: selectedConnectorGrant ? (_jsxs(_Fragment, { children: [_jsx(Check, { size: 14 }), _jsxs("div", { children: [_jsx("div", { children: "Connector already authorized for this workspace." }), _jsxs("div", { className: styles.settingHelper, children: ["Last used ", selectedConnectorGrant.lastUsedAt
888
919
  ? new Date(selectedConnectorGrant.lastUsedAt).toLocaleString()
889
920
  : '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.codeBlock, children: _jsx("code", { children: cloudMcpServerConfig
890
921
  ? renderMcpConfigBlock(cloudMcpServerId, cloudMcpServerConfig, cloudClientIntegration.rootKey || 'mcpServers', cloudClientIntegration.wrapperKeys || [])
891
- : renderTextConfigBlock(cloudClientIntegration.renderedText || '') }) })] }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("span", { className: styles.codeLabel, children: cloudClientIntegration.instructionLabel }) }), _jsx("div", { style: { padding: '16px 20px' }, children: _jsx("div", { className: styles.settingDescription, children: cloudClientIntegration.instructionText }) })] })] })] })) : (_jsxs(_Fragment, { children: [_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: "Cursor on MacBook", 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) })] })] }) }), (() => {
892
- const tokenBarError = mcpTokenNotice?.type === 'error'
893
- ? mcpTokenNotice.message
894
- : null;
895
- const displayedGeneratedToken = tokenBarError
896
- || (copiedConfig === 'token'
897
- ? 'Copied to clipboard'
898
- : (generatedTokenValue || ''));
899
- return (_jsxs("div", { className: styles.mcpTokenOutputWrap, style: { cursor: generatedTokenValue ? 'pointer' : 'default' }, onClick: () => generatedTokenValue && copyToClipboard(generatedTokenValue, 'token'), role: generatedTokenValue ? 'button' : undefined, tabIndex: generatedTokenValue ? 0 : -1, onKeyDown: (e) => {
900
- if (!generatedTokenValue)
901
- return;
902
- if (e.key === 'Enter' || e.key === ' ') {
903
- e.preventDefault();
904
- copyToClipboard(generatedTokenValue, 'token');
905
- }
906
- }, title: generatedTokenValue ? (copiedConfig === 'token' ? 'Token copied' : 'Click to copy token') : undefined, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Token" }) }), _jsx("div", { className: styles.mcpTokenValueField, style: {
907
- color: tokenBarError ? 'var(--status-danger-strong, #f87171)' : undefined,
908
- }, children: _jsx("span", { className: styles.mcpTokenValueText, children: _jsx("code", { children: displayedGeneratedToken }) }) })] }));
909
- })(), _jsx("div", { className: styles.mcpTokenActionRow, children: _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" })] }) })] }), _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.codeBlock, children: _jsx("code", { children: cloudMcpServerConfig
922
+ : 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 }), 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: "Cursor on MacBook", 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) => {
923
+ setGeneratedTokenValue(e.target.value);
924
+ setMcpConnectionResult(null);
925
+ } })] }), _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.codeBlock, children: _jsx("code", { children: cloudMcpServerConfig
910
926
  ? renderMcpConfigBlock(cloudMcpServerId, cloudMcpServerConfig, cloudClientIntegration.rootKey || 'mcpServers', cloudClientIntegration.wrapperKeys || [])
911
- : renderTextConfigBlock(cloudClientIntegration.renderedText || '') }) })] }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("span", { className: styles.codeLabel, children: cloudClientIntegration.instructionLabel }) }), _jsx("div", { style: { padding: '16px 20px' }, children: _jsx("div", { className: styles.settingDescription, children: cloudClientIntegration.instructionText }) })] })] }), _jsxs("div", { className: styles.settingGroup, children: [_jsxs("div", { className: styles.toggleHeading, onClick: () => setShowMcpConnectionTest((prev) => !prev), onKeyDown: (e) => {
912
- if (e.key === 'Enter' || e.key === ' ') {
913
- e.preventDefault();
914
- setShowMcpConnectionTest((prev) => !prev);
915
- }
916
- }, role: "button", tabIndex: 0, title: showMcpConnectionTest ? 'Hide connection test' : 'Show connection test', children: [_jsx("label", { className: styles.label, children: "Test Connection" }), showMcpConnectionTest ? _jsx(ChevronDown, { size: 14 }) : _jsx(ChevronRight, { size: 14 })] }), showMcpConnectionTest && (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles.settingDescription} ${styles.marginTop12}`, children: "Validate that a token works for this workspace before you paste it into your MCP client." }), _jsxs("div", { className: `${styles.settingsItem} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.settingLabelGroup, children: _jsx("span", { className: styles.settingDescription, children: "Token to Test" }) }), _jsx("input", { type: "text", className: styles.settingInput, placeholder: "tfmcp_xxxxx_replace-me", value: mcpConnectionToken, onChange: (e) => {
917
- setMcpConnectionToken(e.target.value);
918
- setMcpConnectionResult(null);
919
- } })] }), _jsxs("div", { className: styles.marginTop12, style: { display: 'flex', gap: '8px', flexWrap: 'wrap', justifyContent: 'flex-end' }, children: [generatedTokenValue && (_jsx("button", { className: styles.copyBtn, onClick: () => {
920
- setMcpConnectionToken(generatedTokenValue);
921
- setMcpConnectionResult(null);
922
- }, children: "Use Generated Token" })), _jsxs("button", { className: styles.copyBtn, onClick: () => void handleTestMcpConnection(), disabled: mcpConnectionBusy, children: [mcpConnectionBusy ? _jsx(Loader2, { size: 14, className: styles.spinIcon }) : _jsx(Zap, { size: 14 }), "Test Connection"] })] }), 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} ${styles.marginTop16}`, children: [_jsxs("div", { className: styles.toggleHeading, onClick: () => setShowMcpTokensList((prev) => !prev), onKeyDown: (e) => {
927
+ : 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 }), renderMcpProfilePrompt()] })] })] }), _jsxs("div", { className: `${styles.settingGroup} ${styles.marginTop16}`, children: [_jsxs("div", { className: styles.toggleHeading, onClick: () => setShowMcpTokensList((prev) => !prev), onKeyDown: (e) => {
923
928
  if (e.key === 'Enter' || e.key === ' ') {
924
929
  e.preventDefault();
925
930
  setShowMcpTokensList((prev) => !prev);
926
931
  }
927
- }, 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." }), 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: {
932
+ }, 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: {
928
933
  padding: '14px 16px',
929
934
  borderRadius: '12px',
930
935
  border: '1px solid var(--border-primary, rgba(255, 255, 255, 0.1))',
931
936
  background: 'rgba(255, 255, 255, 0.03)'
932
- }, 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 !== 'revoked' && (_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.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 runs over stdio and does not require a cloud token. Use this for Codex, Claude Code CLI, Gemini CLI, and similar local MCP clients." })] }) }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.codeBlockWrapperCustom}`, children: [_jsxs("div", { className: styles.codeHeader, children: [_jsx("span", { className: styles.codeLabel, children: "Local 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: () => handleCopyConfig('full'), title: "Copy full configuration file", children: copiedConfig === 'full' ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }) })] })] }), _jsx("pre", { className: styles.codeBlock, children: _jsx("code", { children: localMcpServerConfig
937
+ }, 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." })] }) }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.codeBlockWrapperCustom}`, children: [_jsxs("div", { className: styles.codeHeader, children: [_jsx("span", { className: styles.codeLabel, children: "Local 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: () => handleCopyConfig('full'), title: "Copy full configuration file", children: copiedConfig === 'full' ? _jsx(Check, { size: 14 }) : _jsx(Copy, { size: 14 }) })] })] }), _jsx("pre", { className: styles.codeBlock, children: _jsx("code", { children: localMcpServerConfig
933
938
  ? renderMcpConfigBlock(localMcpServer.serverId, localMcpServerConfig, localClientIntegration.rootKey || 'mcpServers', localClientIntegration.wrapperKeys || [])
934
- : renderTextConfigBlock(localClientIntegration.renderedText || '') }) })] }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("span", { className: styles.codeLabel, children: localClientIntegration.instructionLabel }) }), _jsx("div", { style: { padding: '16px 20px' }, children: _jsx("div", { className: styles.settingDescription, children: localClientIntegration.instructionText }) })] }), _jsx("div", { className: `${styles.settingGroup} ${styles.marginTop12}`, children: _jsxs("div", { className: styles.toggleHeading, onClick: () => setShowAdvancedMcp((prev) => !prev), onKeyDown: (e) => {
939
+ : renderTextConfigBlock(localClientIntegration.renderedText || '') }) })] }), _jsxs("div", { className: `${styles.codeBlockWrapper} ${styles.marginTop12}`, children: [_jsx("div", { className: styles.codeHeader, children: _jsx("span", { className: styles.codeLabel, children: localClientIntegration.instructionLabel }) }), _jsxs("div", { style: { padding: '16px 20px' }, children: [_jsx("div", { className: styles.settingDescription, children: localClientIntegration.instructionText }), renderMcpProfilePrompt()] })] }), _jsx("div", { className: `${styles.settingGroup} ${styles.marginTop12}`, children: _jsxs("div", { className: styles.toggleHeading, onClick: () => setShowAdvancedMcp((prev) => !prev), onKeyDown: (e) => {
935
940
  if (e.key === 'Enter' || e.key === ' ') {
936
941
  e.preventDefault();
937
942
  setShowAdvancedMcp((prev) => !prev);