@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.
- package/README.md +0 -2
- package/dist/Taskforce.module.css +603 -107
- package/dist/TaskforceCore.js +216 -43
- package/dist/TaskforceCore.test.js +611 -28
- package/dist/assets/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/assets/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/assets/fonts/Noir_medium.woff2 +0 -0
- package/dist/assets/fonts/Noir_regular.woff2 +0 -0
- package/dist/assets/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/assets/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/compat/workspaceSyncCompat.js +46 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/activity/EntityActivityTimeline.d.ts +34 -0
- package/dist/components/activity/EntityActivityTimeline.js +81 -0
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +561 -0
- package/dist/components/features/AgentsModule.d.ts +14 -1
- package/dist/components/features/AgentsModule.js +366 -18
- package/dist/components/features/AgentsModule.test.js +507 -8
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +3 -1
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +118 -4
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +52 -0
- package/dist/components/features/DocumentIndex.d.ts +2 -2
- package/dist/components/features/DocumentIndex.js +3 -4
- package/dist/components/features/DocumentViewer.d.ts +7 -1
- package/dist/components/features/DocumentViewer.js +62 -4
- package/dist/components/features/DocumentWorkspace.d.ts +10 -2
- package/dist/components/features/DocumentWorkspace.js +15 -4
- package/dist/components/features/DocumentWorkspace.test.js +51 -1
- package/dist/components/features/TaskSettings.d.ts +2 -0
- package/dist/components/features/TaskSettings.js +83 -78
- package/dist/components/features/TaskSettings.test.js +171 -82
- package/dist/components/features/documentWorkspaceModel.d.ts +1 -1
- package/dist/components/task/TaskActionHeader.js +11 -5
- package/dist/components/task/TaskActionHeader.test.js +10 -0
- package/dist/components/task/TaskCard.js +24 -29
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskContextUpload.test.js +3 -3
- package/dist/components/task/TaskForm.js +61 -116
- package/dist/components/task/TaskForm.test.js +110 -8
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +94 -21
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/task/TaskList.js +5 -1
- package/dist/components/task/TaskList.test.js +4 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/ui/HierarchyActionBadge.d.ts +10 -0
- package/dist/components/ui/HierarchyActionBadge.js +5 -0
- package/dist/components/views/AppShellHeader.d.ts +3 -1
- package/dist/components/views/AppShellHeader.js +27 -11
- package/dist/components/views/AppShellHeader.test.js +18 -1
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +78 -14
- package/dist/components/views/PlanComparisonPage.test.js +257 -0
- package/dist/components/views/PlansPage.js +127 -36
- package/dist/components/views/PlansPage.test.js +294 -12
- package/dist/components/views/StandaloneLayout.js +529 -592
- package/dist/components/views/WidgetView.js +10 -8
- package/dist/components/views/panels/PlanningDrawer.d.ts +25 -5
- package/dist/components/views/panels/PlanningDrawer.js +270 -55
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +529 -0
- package/dist/components/views/planningScope.d.ts +20 -0
- package/dist/components/views/planningScope.js +25 -0
- package/dist/components/views/planningScope.test.d.ts +1 -0
- package/dist/components/views/planningScope.test.js +60 -0
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +26 -1
- package/dist/components/views/standalone/modals/AccountHubModal.js +76 -2
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +20 -3
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.d.ts +20 -0
- package/dist/components/views/standalone/modals/AvatarImageManagerModal.js +127 -0
- package/dist/components/views/standalone/modals/EditProfileModal.d.ts +2 -9
- package/dist/components/views/standalone/modals/EditProfileModal.js +3 -2
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.js +6 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.d.ts +1 -0
- package/dist/components/views/standalone/modals/SyncEnableWarningModal.test.js +24 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +2 -1
- package/dist/components/views/standalone/modals/SyncStatusModal.js +2 -2
- package/dist/config/envSchema.js +1 -0
- package/dist/core/AiProfileService.d.ts +46 -2
- package/dist/core/AiProfileService.js +1073 -82
- package/dist/core/AiProfileService.test.js +19 -1
- package/dist/core/AiProfiles.test.js +1249 -44
- package/dist/core/AttachmentLinkService.d.ts +3 -0
- package/dist/core/AttachmentLinkService.js +110 -23
- package/dist/core/AuthIdentityService.d.ts +107 -0
- package/dist/core/AuthIdentityService.js +284 -0
- package/dist/core/AuthTokenService.d.ts +4 -0
- package/dist/core/AuthTokenService.js +34 -6
- package/dist/core/AuthTokenService.test.js +3 -3
- package/dist/core/EntitlementsPolicy.test.js +2 -2
- package/dist/core/GlobalSettingsService.js +127 -6
- package/dist/core/McpTokenService.d.ts +12 -0
- package/dist/core/McpTokenService.js +44 -1
- package/dist/core/PlanEntitlementService.d.ts +23 -2
- package/dist/core/PlanEntitlementService.js +343 -57
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +35 -2
- package/dist/core/PlanningEntities.test.js +418 -4
- package/dist/core/SignupMonetizationSettings.test.js +199 -27
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +42 -42
- package/dist/core/TaskActivityService.d.ts +28 -1
- package/dist/core/TaskActivityService.js +227 -46
- package/dist/core/TaskActivitySync.test.d.ts +1 -0
- package/dist/core/TaskActivitySync.test.js +90 -0
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskAuditTimeline.test.js +96 -0
- package/dist/core/Taskforce.d.ts +415 -40
- package/dist/core/Taskforce.ids.test.js +58 -0
- package/dist/core/Taskforce.js +1543 -266
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -0
- package/dist/core/Taskforce.mcpAuth.test.js +109 -0
- package/dist/core/UserProfileAvatarDrafts.test.js +30 -3
- package/dist/core/WorkspaceLifecycleService.js +0 -5
- package/dist/core/WorkspacePermissions.test.js +25 -1
- package/dist/core/WorkspacePlanMode.test.js +117 -16
- package/dist/core/shared.d.ts +1 -1
- package/dist/core/shared.js +5 -1
- package/dist/core/types.d.ts +75 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +28 -2
- package/dist/hooks/bootstrapTimeouts.d.ts +4 -0
- package/dist/hooks/bootstrapTimeouts.js +8 -0
- package/dist/hooks/bootstrapTimeouts.test.d.ts +1 -0
- package/dist/hooks/bootstrapTimeouts.test.js +12 -0
- package/dist/hooks/sync/bootstrap.js +2 -0
- package/dist/hooks/sync/controlPlane.d.ts +37 -0
- package/dist/hooks/sync/controlPlane.js +78 -0
- package/dist/hooks/sync/controlPlane.test.d.ts +1 -0
- package/dist/hooks/sync/controlPlane.test.js +121 -0
- package/dist/hooks/sync/lifecyclePolicy.d.ts +45 -0
- package/dist/hooks/sync/lifecyclePolicy.js +93 -0
- package/dist/hooks/sync/lifecyclePolicy.test.d.ts +1 -0
- package/dist/hooks/sync/lifecyclePolicy.test.js +124 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +13 -4
- package/dist/hooks/sync/orchestratorShared.js +129 -48
- package/dist/hooks/sync/orchestratorShared.test.js +50 -1
- package/dist/hooks/sync/pullLifecycle.d.ts +31 -0
- package/dist/hooks/sync/pullLifecycle.js +24 -0
- package/dist/hooks/sync/pullLifecycle.test.d.ts +1 -0
- package/dist/hooks/sync/pullLifecycle.test.js +80 -0
- package/dist/hooks/sync/recovery.d.ts +16 -2
- package/dist/hooks/sync/recovery.js +179 -53
- package/dist/hooks/sync/recovery.test.d.ts +1 -0
- package/dist/hooks/sync/recovery.test.js +292 -0
- package/dist/hooks/sync/transfers.d.ts +16 -3
- package/dist/hooks/sync/transfers.js +210 -66
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +928 -0
- package/dist/hooks/sync/useRecentSyncEvents.d.ts +21 -0
- package/dist/hooks/sync/useRecentSyncEvents.js +92 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.d.ts +1 -0
- package/dist/hooks/sync/useRecentSyncEvents.test.js +124 -0
- package/dist/hooks/sync/useSyncStatusActions.d.ts +30 -0
- package/dist/hooks/sync/useSyncStatusActions.js +88 -0
- package/dist/hooks/sync/useSyncStatusActions.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusActions.test.js +133 -0
- package/dist/hooks/sync/useSyncStatusControls.d.ts +25 -0
- package/dist/hooks/sync/useSyncStatusControls.js +60 -0
- package/dist/hooks/sync/useSyncStatusControls.test.d.ts +1 -0
- package/dist/hooks/sync/useSyncStatusControls.test.js +88 -0
- package/dist/hooks/useFilterSort.js +13 -13
- package/dist/hooks/useFilterSort.test.js +87 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +9 -2
- package/dist/hooks/useSyncOrchestrator.js +409 -183
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +407 -0
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskforce.d.ts +145 -52
- package/dist/hooks/useTaskforce.js +592 -253
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +246 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2468 -201
- package/dist/hooks/useWorkspaceSyncController.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.js +13 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +48 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +328 -40
- package/dist/localization/locales/en-US.d.ts +0 -1
- package/dist/localization/locales/en-US.js +0 -1
- package/dist/localization/locales/es-419.js +0 -1
- package/dist/localization/locales/pt-BR.js +0 -1
- package/dist/mcp/canonicalAssetHelpers.d.ts +16 -4
- package/dist/mcp/canonicalAssetHelpers.js +18 -10
- package/dist/mcp/canonicalAssetHelpers.test.d.ts +1 -0
- package/dist/mcp/canonicalAssetHelpers.test.js +67 -0
- package/dist/mcp/clientIntegrations.d.ts +1 -0
- package/dist/mcp/clientIntegrations.js +25 -0
- package/dist/mcp/clientIntegrations.test.js +14 -3
- package/dist/mcp/clientProfileDefaults.js +3 -3
- package/dist/mcp/collaborationRegistrar.js +7 -7
- package/dist/mcp/documentAssetRegistrar.js +116 -10
- package/dist/mcp/runtime.d.ts +3 -0
- package/dist/mcp/runtime.js +1099 -185
- package/dist/mcp/runtime.test.js +1491 -140
- package/dist/mcp/taskAttachmentTypes.d.ts +1 -1
- package/dist/mcp/taskPlanningRegistrar.js +48 -0
- package/dist/mcp/toolRegistry.d.ts +56 -0
- package/dist/mcp/toolRegistry.js +8 -0
- package/dist/mcp/toolRegistry.test.js +4 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +192 -61
- package/dist/migrations/taskSchemaMigrations.test.js +15 -0
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/dist/resources/templates/workflows/collaborate.yaml +1 -1
- package/dist/resources/templates/workflows/evaluate.yaml +2 -2
- package/dist/resources/templates/workflows/plan.yaml +1 -1
- package/dist/resources/templates/workflows/review.yaml +2 -2
- package/dist/server/aiProfileAvatarAssets.d.ts +49 -0
- package/dist/server/aiProfileAvatarAssets.js +319 -0
- package/dist/server/aiProfileAvatarAssets.test.d.ts +1 -0
- package/dist/server/aiProfileAvatarAssets.test.js +213 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +69 -10
- package/dist/server/auth/providers/apple.d.ts +33 -0
- package/dist/server/auth/providers/apple.js +82 -0
- package/dist/server/auth/providers/appleClientSecret.d.ts +37 -0
- package/dist/server/auth/providers/appleClientSecret.js +65 -0
- package/dist/server/auth/providers/github.d.ts +26 -0
- package/dist/server/auth/providers/github.js +86 -0
- package/dist/server/auth/providers/google.d.ts +21 -0
- package/dist/server/auth/providers/google.js +56 -0
- package/dist/server/auth/providers/types.d.ts +21 -0
- package/dist/server/auth/providers/types.js +1 -0
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/auth.js +6 -3
- package/dist/server/documentReviewRoutes.test.js +36 -3
- package/dist/server/index.cookieProxy.test.js +1 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +124 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +111 -3
- package/dist/server/routes/admin.d.ts +3 -0
- package/dist/server/routes/admin.js +459 -28
- package/dist/server/routes/annotatedAttachments.js +51 -0
- package/dist/server/routes/auth.d.ts +26 -2
- package/dist/server/routes/auth.js +1170 -71
- package/dist/server/routes/authSupport.d.ts +5 -1
- package/dist/server/routes/authSupport.js +13 -2
- package/dist/server/routes/billing.js +372 -35
- package/dist/server/routes/billing.test.js +595 -12
- package/dist/server/routes/documents.d.ts +1 -0
- package/dist/server/routes/documents.js +182 -70
- package/dist/server/routes/shared.d.ts +28 -2
- package/dist/server/routes/shared.js +69 -14
- package/dist/server/routes/sync.integration.test.js +658 -39
- package/dist/server/routes/sync.js +74 -608
- package/dist/server/routes/syncAuxRoutes.d.ts +15 -0
- package/dist/server/routes/syncAuxRoutes.js +91 -0
- package/dist/server/routes/syncAuxRoutes.test.d.ts +1 -0
- package/dist/server/routes/syncAuxRoutes.test.js +158 -0
- package/dist/server/routes/syncPullApplyRoutes.d.ts +36 -0
- package/dist/server/routes/syncPullApplyRoutes.js +204 -0
- package/dist/server/routes/syncPushRoutes.d.ts +24 -0
- package/dist/server/routes/syncPushRoutes.js +212 -0
- package/dist/server/routes/syncRouteGuards.d.ts +36 -0
- package/dist/server/routes/syncRouteGuards.js +67 -0
- package/dist/server/routes/syncRouteGuards.test.d.ts +1 -0
- package/dist/server/routes/syncRouteGuards.test.js +94 -0
- package/dist/server/routes/syncRouteTypes.d.ts +13 -0
- package/dist/server/routes/syncRouteTypes.js +1 -0
- package/dist/server/routes/syncSnapshotRoutes.d.ts +66 -0
- package/dist/server/routes/syncSnapshotRoutes.js +182 -0
- package/dist/server/routes/tasks.js +55 -10
- package/dist/server/routes/workspaces.js +36 -5
- package/dist/server/routes.js +147 -11
- package/dist/server/routes.test.js +2704 -183
- package/dist/services/workflowExportSnapshots.test.js +2 -0
- package/dist/shared/aiProfileSeatScope.d.ts +5 -0
- package/dist/shared/aiProfileSeatScope.js +21 -0
- package/dist/shared/aiProfileSurfaceType.d.ts +1 -1
- package/dist/shared/aiProfileSurfaceType.js +10 -8
- package/dist/shared/passwordPolicy.d.ts +13 -0
- package/dist/shared/passwordPolicy.js +84 -0
- package/dist/shared/passwordPolicy.test.d.ts +1 -0
- package/dist/shared/passwordPolicy.test.js +34 -0
- package/dist/storage/objectStorage.d.ts +1 -0
- package/dist/storage/objectStorage.js +2 -1
- package/dist/storage/objectStorageClient.d.ts +1 -0
- package/dist/storage/objectStorageClient.js +41 -8
- package/dist/storage/objectStorageClient.test.js +26 -1
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.js +13 -1
- package/dist/storage/workspaceAssetStore.d.ts +15 -3
- package/dist/storage/workspaceAssetStore.js +132 -44
- package/dist/storage/workspaceAssetStore.test.js +93 -6
- package/dist/styles/fonts.css +70 -0
- package/dist/sync/collaborationSyncPayload.d.ts +6 -1
- package/dist/sync/collaborationSyncPayload.js +19 -11
- package/dist/sync/collaborationSyncPayload.test.js +14 -1
- package/dist/sync/collaborationSyncState.d.ts +3 -3
- package/dist/sync/collaborationSyncState.js +19 -12
- package/dist/sync/contentSyncPayload.d.ts +5 -1
- package/dist/sync/contentSyncPayload.js +9 -0
- package/dist/sync/contentSyncPayload.test.js +39 -0
- package/dist/sync/contentSyncState.d.ts +9 -9
- package/dist/sync/contentSyncState.js +248 -107
- package/dist/sync/planningSyncPayload.js +5 -0
- package/dist/sync/planningSyncPayload.test.js +24 -0
- package/dist/sync/syncApplyHandlers.d.ts +11 -4
- package/dist/sync/syncApplyHandlers.js +115 -42
- package/dist/sync/syncApplyHandlers.test.js +251 -4
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +46 -0
- package/dist/sync/syncResourceAdapters.js +79 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +65 -1
- package/dist/sync/syncService.test.js +96 -3
- package/dist/sync/taskSyncChangeKey.d.ts +2 -0
- package/dist/sync/taskSyncChangeKey.js +143 -0
- package/dist/sync/taskSyncPayload.js +3 -8
- package/dist/sync/workspacePullFeed.d.ts +4 -0
- package/dist/sync/workspacePullFeed.js +132 -72
- package/dist/sync/workspacePullFeed.test.js +92 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +73 -6
- package/dist/sync/workspaceSyncModel.js +342 -73
- package/dist/sync/workspaceSyncModel.test.js +559 -14
- package/dist/sync/workspaceSyncState.d.ts +17 -0
- package/dist/sync/workspaceSyncState.js +2 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +50 -2
- package/dist/ui/assets/AgentsModule-2y82_3DO.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BTLZZCiQ.js +3 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BVKew-mH.css +1 -0
- package/dist/ui/assets/ContextAttachmentManager-D2epuNnG.js +3 -0
- package/dist/ui/assets/CourierPrime-Bold-BuLj_dpw.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-BoldItalic-BrK2pUkZ.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Italic-DFUZK5Ey.woff2 +0 -0
- package/dist/ui/assets/CourierPrime-Regular-BsKphzVf.woff2 +0 -0
- package/dist/ui/assets/DocumentWorkspace-D4rJKXzd.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-sVa-3Do6.js +252 -0
- package/dist/ui/assets/EntityActivityTimeline-DyqvvhuF.css +1 -0
- package/dist/ui/assets/EntityActivityTimeline-Zods27y_.js +1 -0
- package/dist/ui/assets/{InitiativesModule-Dhm7M8e7.js → InitiativesModule-D4XseTwW.js} +1 -1
- package/dist/ui/assets/Noir_medium-bxQwKGzB.woff2 +0 -0
- package/dist/ui/assets/Noir_regular-ojf2kxlG.woff2 +0 -0
- package/dist/ui/assets/PlansPage-D5AcbO0L.js +1 -0
- package/dist/ui/assets/PlansPage-Dvqsz5zc.css +1 -0
- package/dist/ui/assets/RussoOne-Regular-Cu_qq_qC.woff2 +0 -0
- package/dist/ui/assets/SpecialElite-Regular-Di6gSvAS.woff2 +0 -0
- package/dist/ui/assets/TaskContextUpload-uC5qx4Bv.js +1 -0
- package/dist/ui/assets/TaskSettings-CqvPAsTv.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-BcS4afRn.js → WorkflowsModule-oOA9bcdK.js} +4 -4
- package/dist/ui/assets/documentReferences-DPZuTgHh.js +1 -0
- package/dist/ui/assets/index-607WPo_X.js +4 -0
- package/dist/ui/assets/index-CYyodXsg.css +1 -0
- package/dist/ui/assets/{vendor-icons-BSUaRwF8.js → vendor-icons-B32hGuF2.js} +1 -1
- package/dist/ui/fonts/CourierPrime-Bold.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Bold.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-BoldItalic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Italic.woff2 +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.ttf +0 -0
- package/dist/ui/fonts/CourierPrime-Regular.woff2 +0 -0
- package/dist/ui/fonts/Noir_medium.otf +0 -0
- package/dist/ui/fonts/Noir_medium.woff2 +0 -0
- package/dist/ui/fonts/Noir_regular.otf +0 -0
- package/dist/ui/fonts/Noir_regular.woff2 +0 -0
- package/dist/ui/fonts/RussoOne-Regular.woff2 +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.ttf +0 -0
- package/dist/ui/fonts/SpecialElite-Regular.woff2 +0 -0
- package/dist/ui/index.html +3 -3
- package/dist/ui/product/agent manager.png +0 -0
- package/dist/ui/product/agent_manager_02.png +0 -0
- package/dist/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/aiProfileEvents.d.ts +7 -0
- package/dist/utils/aiProfileEvents.js +6 -0
- package/dist/utils/assignees.d.ts +8 -0
- package/dist/utils/assignees.js +10 -1
- package/dist/utils/assignees.test.d.ts +1 -0
- package/dist/utils/assignees.test.js +25 -0
- package/dist/utils/avatarDisplay.d.ts +1 -0
- package/dist/utils/avatarDisplay.js +15 -0
- package/dist/utils/avatarUpload.d.ts +27 -0
- package/dist/utils/avatarUpload.js +132 -0
- package/dist/utils/avatarUpload.test.d.ts +1 -0
- package/dist/utils/avatarUpload.test.js +40 -0
- package/dist/utils/bootstrapTrace.d.ts +7 -0
- package/dist/utils/bootstrapTrace.js +29 -0
- package/dist/utils/commercialLifecyclePresentation.js +3 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- package/dist/utils/contextFiles.d.ts +3 -1
- package/dist/utils/contextFiles.js +2 -1
- package/dist/utils/syncEventDetails.d.ts +3 -0
- package/dist/utils/syncEventDetails.js +64 -0
- package/dist/utils/syncEventDetails.test.d.ts +1 -0
- package/dist/utils/syncEventDetails.test.js +23 -0
- package/dist/utils/syncEventPresentation.d.ts +15 -0
- package/dist/utils/syncEventPresentation.js +129 -0
- package/dist/utils/syncEventPresentation.test.d.ts +1 -0
- package/dist/utils/syncEventPresentation.test.js +64 -0
- package/dist/utils/syncStatusPresentation.d.ts +72 -0
- package/dist/utils/syncStatusPresentation.js +217 -0
- package/dist/utils/syncStatusPresentation.test.d.ts +1 -0
- package/dist/utils/syncStatusPresentation.test.js +164 -0
- package/dist/utils/taskActivity.d.ts +9 -1
- package/dist/utils/taskActivity.js +290 -22
- package/dist/utils/taskActivity.test.js +141 -8
- package/dist/utils/taskSearch.d.ts +22 -0
- package/dist/utils/taskSearch.js +87 -0
- package/dist/utils/taskSearch.test.d.ts +1 -0
- package/dist/utils/taskSearch.test.js +69 -0
- package/dist/utils/taskUtils.js +10 -3
- package/dist/utils/taskUtils.test.d.ts +1 -0
- package/dist/utils/taskUtils.test.js +19 -0
- package/dist/utils/workspaceSyncPresentation.d.ts +4 -0
- package/dist/utils/workspaceSyncPresentation.js +68 -2
- package/dist/utils/workspaceSyncPresentation.test.js +36 -1
- package/package.json +3 -2
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- package/scripts/run-e2e-realtime.sh +17 -3
- package/scripts/run-smoke.sh +17 -5
- package/scripts/run-soak.sh +17 -5
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +6 -6
- package/src/resources/templates/workflows/collaborate.yaml +1 -1
- package/src/resources/templates/workflows/evaluate.yaml +2 -2
- package/src/resources/templates/workflows/plan.yaml +1 -1
- package/src/resources/templates/workflows/review.yaml +2 -2
- package/dist/ui/assets/AgentsModule-N2MnQBZk.js +0 -1
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BG6P_GVW.js +0 -3
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +0 -1
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +0 -252
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/TaskSettings-ln0aF7xc.js +0 -9
- package/dist/ui/assets/index-C2-OXZV7.css +0 -1
- package/dist/ui/assets/index-DcSI5F86.js +0 -6
- 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
|
|
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 [
|
|
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 (!
|
|
188
|
+
if (!mcpTokenIssueNotice)
|
|
190
189
|
return;
|
|
191
|
-
const timer = setTimeout(() =>
|
|
190
|
+
const timer = setTimeout(() => setMcpTokenIssueNotice(null), 3500);
|
|
192
191
|
return () => clearTimeout(timer);
|
|
193
|
-
}, [
|
|
192
|
+
}, [mcpTokenIssueNotice]);
|
|
194
193
|
useEffect(() => {
|
|
195
|
-
if (!
|
|
194
|
+
if (!mcpConfigNotice)
|
|
196
195
|
return;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}, [
|
|
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
|
|
215
|
+
const showMcpModeToggle = localMcpEnabled;
|
|
211
216
|
const showCloudMcp = runtimeMode === 'cloud' || selectedMcpMode === 'cloud';
|
|
212
|
-
const showLocalMcp = runtimeMode !== 'cloud' &&
|
|
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
|
|
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 && !
|
|
292
|
-
|
|
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 (!
|
|
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 (!
|
|
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
|
-
|
|
449
|
+
setMcpTokenIssueNotice({ type: 'error', message: 'Token name is required.' });
|
|
437
450
|
return;
|
|
438
451
|
}
|
|
439
452
|
setMcpActionBusyId('create');
|
|
440
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
492
|
+
setMcpTokenListNotice(null);
|
|
475
493
|
try {
|
|
476
|
-
const
|
|
477
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
537
|
+
const trimmedToken = currentMcpTokenValue;
|
|
509
538
|
if (!trimmedToken) {
|
|
510
539
|
setMcpConnectionResult({
|
|
511
540
|
type: 'error',
|
|
512
|
-
message: '
|
|
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 (!
|
|
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,
|
|
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 }) }),
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
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 }) }),
|
|
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
|
|
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 }) }),
|
|
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);
|