@taskforcehq/taskforce 0.3.304 → 0.3.306
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 +140 -247
- package/dist/Taskforce.module.css +295 -89
- package/dist/TaskforceCore.js +378 -111
- package/dist/TaskforceCore.test.js +1221 -107
- 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 +52 -2
- package/dist/compat/workspaceSyncCompat.test.js +38 -1
- package/dist/components/context/ContextAttachmentManager.d.ts +14 -0
- package/dist/components/context/ContextAttachmentManager.js +549 -0
- package/dist/components/features/AgentsModule.d.ts +10 -1
- package/dist/components/features/AgentsModule.js +260 -15
- package/dist/components/features/AgentsModule.test.js +255 -5
- package/dist/components/features/DocumentIndex.d.ts +1 -1
- package/dist/components/features/DocumentIndex.js +1 -1
- package/dist/components/features/DocumentViewer.d.ts +6 -2
- package/dist/components/features/DocumentViewer.js +90 -10
- package/dist/components/features/DocumentWorkspace.d.ts +5 -22
- package/dist/components/features/DocumentWorkspace.js +12 -155
- package/dist/components/features/DocumentWorkspace.test.js +226 -6
- package/dist/components/features/TaskSettings.js +29 -3
- package/dist/components/features/TaskSettings.test.js +42 -1
- package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
- package/dist/components/features/documentWorkspaceModel.js +57 -0
- package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
- package/dist/components/features/useDocumentWorkspaceController.js +113 -0
- package/dist/components/task/TaskCard.js +19 -28
- package/dist/components/task/TaskCard.test.js +38 -3
- package/dist/components/task/TaskContextUpload.js +4 -526
- package/dist/components/task/TaskForm.d.ts +8 -8
- package/dist/components/task/TaskForm.js +362 -230
- package/dist/components/task/TaskForm.test.js +558 -381
- package/dist/components/task/TaskKanban.d.ts +2 -1
- package/dist/components/task/TaskKanban.js +96 -14
- package/dist/components/task/TaskKanban.test.js +36 -0
- package/dist/components/ui/EditableAvatarButton.d.ts +18 -0
- package/dist/components/ui/EditableAvatarButton.js +18 -0
- package/dist/components/views/PlanComparisonPage.d.ts +9 -1
- package/dist/components/views/PlanComparisonPage.js +70 -17
- package/dist/components/views/PlanComparisonPage.test.js +289 -41
- package/dist/components/views/PlansPage.js +239 -106
- package/dist/components/views/PlansPage.test.js +593 -42
- package/dist/components/views/StandaloneLayout.js +310 -554
- package/dist/components/views/panels/FilterToolbar.test.js +6 -4
- package/dist/components/views/panels/PlanningDrawer.d.ts +8 -1
- package/dist/components/views/panels/PlanningDrawer.js +18 -11
- package/dist/components/views/panels/PlanningDrawer.test.d.ts +1 -0
- package/dist/components/views/panels/PlanningDrawer.test.js +141 -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 +27 -14
- package/dist/components/views/standalone/modals/AccountHubModal.js +87 -15
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +42 -2
- 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 -1
- package/dist/core/AiProfileService.d.ts +45 -3
- package/dist/core/AiProfileService.js +774 -63
- package/dist/core/AiProfileService.test.js +22 -2
- package/dist/core/AiProfiles.test.js +761 -2
- package/dist/core/AttachmentLinkService.js +57 -15
- 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.d.ts +1 -0
- package/dist/core/AuthTokenService.test.js +78 -0
- package/dist/core/EntitlementsPolicy.test.js +77 -15
- package/dist/core/GlobalSettingsService.js +115 -6
- package/dist/core/PlanEntitlementService.d.ts +30 -3
- package/dist/core/PlanEntitlementService.js +454 -93
- package/dist/core/PlanFeatureCatalog.test.d.ts +1 -0
- package/dist/core/PlanFeatureCatalog.test.js +84 -0
- package/dist/core/PlanVersionPolicy.test.js +54 -28
- package/dist/core/PlanningEntities.test.js +52 -0
- package/dist/core/SignupMonetizationSettings.test.js +241 -44
- package/dist/core/SyncReconciliationService.js +2 -65
- package/dist/core/SystemAdmin.test.js +244 -88
- package/dist/core/TaskAttachmentsCanonical.test.js +51 -1
- package/dist/core/TaskTaxonomyValidation.test.js +53 -0
- package/dist/core/Taskforce.d.ts +228 -14
- package/dist/core/Taskforce.js +814 -201
- package/dist/core/Taskforce.listTasksSlim.test.d.ts +1 -0
- package/dist/core/Taskforce.listTasksSlim.test.js +91 -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 +128 -27
- package/dist/core/shared.d.ts +3 -1
- package/dist/core/shared.js +16 -1
- package/dist/core/types.d.ts +68 -2
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +26 -1
- package/dist/hooks/sync/auth.js +3 -1
- 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 +10 -1
- package/dist/hooks/sync/orchestratorShared.js +68 -47
- 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 +171 -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 +186 -65
- package/dist/hooks/sync/transfers.test.d.ts +1 -0
- package/dist/hooks/sync/transfers.test.js +396 -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/useSyncOrchestrator.aiProfiles.test.js +12 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +16 -6
- package/dist/hooks/useSyncOrchestrator.js +424 -175
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +487 -10
- package/dist/hooks/useTaskData.js +8 -3
- package/dist/hooks/useTaskData.test.js +45 -0
- package/dist/hooks/useTaskMutations.d.ts +2 -1
- package/dist/hooks/useTaskMutations.js +12 -1
- package/dist/hooks/useTaskMutations.test.js +30 -1
- package/dist/hooks/useTaskforce.d.ts +65 -4
- package/dist/hooks/useTaskforce.js +564 -243
- package/dist/hooks/useTaskforce.runtime-routing.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.runtime-routing.test.js +152 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +2454 -208
- package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
- package/dist/hooks/useWorkspaceSyncController.js +17 -2
- package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +16 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +316 -35
- 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/adminWorkspaceRegistrar.d.ts +2 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
- package/dist/mcp/collaborationRegistrar.d.ts +2 -0
- package/dist/mcp/collaborationRegistrar.js +71 -0
- package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
- package/dist/mcp/documentAssetRegistrar.js +346 -0
- package/dist/mcp/runtime.d.ts +2 -0
- package/dist/mcp/runtime.js +2433 -3534
- package/dist/mcp/runtime.test.js +440 -2
- package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
- package/dist/mcp/taskPlanningRegistrar.js +418 -0
- package/dist/mcp/toolCatalog.d.ts +35 -0
- package/dist/mcp/toolCatalog.js +3 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +1 -1
- package/dist/migrations/taskSchemaMigrations.js +171 -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/annotatedAttachmentsRoutes.test.js +3 -3
- 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 +120 -9
- package/dist/server/index.rateLimit.test.js +3 -0
- package/dist/server/index.test.js +106 -3
- package/dist/server/routes/admin.d.ts +4 -5
- package/dist/server/routes/admin.js +410 -80
- package/dist/server/routes/annotatedAttachments.d.ts +1 -1
- package/dist/server/routes/annotatedAttachments.js +1 -1
- package/dist/server/routes/auth.d.ts +16 -6
- package/dist/server/routes/auth.js +1015 -118
- package/dist/server/routes/authSupport.d.ts +30 -0
- package/dist/server/routes/authSupport.js +81 -0
- package/dist/server/routes/billing.d.ts +1 -1
- package/dist/server/routes/billing.js +276 -34
- package/dist/server/routes/billing.test.js +760 -52
- package/dist/server/routes/documentReviews.d.ts +1 -1
- package/dist/server/routes/documentReviews.js +1 -1
- package/dist/server/routes/documents.d.ts +5 -2
- package/dist/server/routes/documents.js +242 -74
- package/dist/server/routes/primitives.d.ts +11 -0
- package/dist/server/routes/primitives.js +73 -0
- package/dist/server/routes/resources.d.ts +1 -1
- package/dist/server/routes/resources.js +1 -1
- package/dist/server/routes/shared.d.ts +29 -3
- package/dist/server/routes/shared.js +69 -4
- package/dist/server/routes/sync.d.ts +1 -1
- package/dist/server/routes/sync.integration.test.js +437 -39
- package/dist/server/routes/sync.js +62 -606
- 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 +180 -0
- package/dist/server/routes/tasks.d.ts +1 -1
- package/dist/server/routes/tasks.js +44 -2
- package/dist/server/routes/workspaces.d.ts +1 -1
- package/dist/server/routes/workspaces.js +37 -6
- package/dist/server/routes.d.ts +2 -9
- package/dist/server/routes.js +136 -165
- package/dist/server/routes.test.js +2457 -162
- 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/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/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 +17 -11
- package/dist/sync/collaborationSyncPayload.test.js +13 -1
- package/dist/sync/contentSyncState.d.ts +4 -8
- package/dist/sync/contentSyncState.js +33 -77
- package/dist/sync/syncApplyHandlers.d.ts +7 -0
- package/dist/sync/syncApplyHandlers.js +28 -13
- package/dist/sync/syncApplyHandlers.test.js +72 -3
- package/dist/sync/syncFieldSemantics.d.ts +12 -0
- package/dist/sync/syncFieldSemantics.js +55 -0
- package/dist/sync/syncResourceAdapters.d.ts +44 -0
- package/dist/sync/syncResourceAdapters.js +77 -0
- package/dist/sync/syncService.d.ts +6 -0
- package/dist/sync/syncService.js +60 -0
- package/dist/sync/syncService.test.js +71 -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.js +4 -3
- package/dist/sync/workspacePullFeed.test.js +43 -0
- package/dist/sync/workspaceRepair.js +5 -2
- package/dist/sync/workspaceSyncModel.d.ts +48 -0
- package/dist/sync/workspaceSyncModel.js +195 -31
- package/dist/sync/workspaceSyncModel.test.js +325 -12
- package/dist/sync/workspaceSyncState.d.ts +19 -0
- package/dist/sync/workspaceSyncState.js +3 -1
- package/dist/sync/workspaceSyncSurface.js +3 -8
- package/dist/types.d.ts +17 -0
- package/dist/ui/assets/AgentsModule-DrLawwNl.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BlS-cqnl.js → AnnotatedAttachmentWorkspace-Z9_whf7F.js} +1 -1
- 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-B03MaSkw.js +252 -0
- package/dist/ui/assets/DocumentWorkspace-Dhdso07p.css +1 -0
- package/dist/ui/assets/{InitiativesModule-BjR6iBf9.js → InitiativesModule-9E6ParrY.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-CvfnMiWq.css +1 -0
- package/dist/ui/assets/PlansPage-DRXscYxH.js +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/TaskSettings-DZX4jk7e.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-DnFqdUME.js → WorkflowsModule-BA7jcEpH.js} +1 -1
- package/dist/ui/assets/index-9eT8e0Lu.css +1 -0
- package/dist/ui/assets/index-C6k75jr8.js +6 -0
- package/dist/ui/assets/{vendor-icons-I7ZwG1z_.js → vendor-icons-DuEd_65c.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/utils/accountProfileSummaryCache.d.ts +5 -0
- package/dist/utils/assignees.d.ts +2 -0
- package/dist/utils/assignees.js +2 -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.d.ts +19 -0
- package/dist/utils/commercialLifecyclePresentation.js +199 -0
- package/dist/utils/contextAssetEvents.d.ts +2 -0
- 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 +2 -0
- package/dist/utils/taskActivity.js +228 -22
- package/dist/utils/taskActivity.test.js +119 -8
- 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 +10 -2
- package/scripts/check-cloud-mcp.mjs +83 -0
- package/scripts/export-sqlite-to-postgres.mjs +7 -9
- package/scripts/playwright-auth.sh +5 -1
- package/scripts/run-billing-performance-smoke.sh +24 -0
- 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-BLWVbuKP.js +0 -1
- package/dist/ui/assets/DocumentWorkspace-BH_6DF6x.js +0 -250
- package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
- package/dist/ui/assets/PlansPage-C2dd2n1X.css +0 -1
- package/dist/ui/assets/PlansPage-CSDQ4sLa.js +0 -1
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/TaskSettings-CEDy34Jo.js +0 -9
- package/dist/ui/assets/index-DXUdtH1B.js +0 -6
- package/dist/ui/assets/index-Ii0B0rTO.css +0 -1
- package/scripts/migrate-planning-model.ts +0 -233
|
@@ -1,12 +1,78 @@
|
|
|
1
|
+
function resolveBlockedReasonPresentation(reason) {
|
|
2
|
+
switch (reason) {
|
|
3
|
+
case 'auth-required':
|
|
4
|
+
return {
|
|
5
|
+
summary: 'Sync is paused until you sign in again.',
|
|
6
|
+
recommendedAction: 'Sign in, then press Sync to retry.'
|
|
7
|
+
};
|
|
8
|
+
case 'attach-cloud':
|
|
9
|
+
return {
|
|
10
|
+
summary: 'This workspace still needs its first cloud pull before local pushes can run.',
|
|
11
|
+
recommendedAction: 'Keep this window open for the first cloud pull. If it seems stuck, press Repair.'
|
|
12
|
+
};
|
|
13
|
+
case 'provision-local':
|
|
14
|
+
return {
|
|
15
|
+
summary: 'This workspace is still doing its first cloud upload before normal pulls can run.',
|
|
16
|
+
recommendedAction: 'Keep this window open until the first cloud upload finishes.'
|
|
17
|
+
};
|
|
18
|
+
case 'repair-active':
|
|
19
|
+
return {
|
|
20
|
+
summary: 'Repair is already running for this workspace.',
|
|
21
|
+
recommendedAction: 'Wait for repair to finish before retrying sync.'
|
|
22
|
+
};
|
|
23
|
+
case 'retry-pending':
|
|
24
|
+
return {
|
|
25
|
+
summary: 'Sync hit a temporary problem and is waiting for its scheduled retry.',
|
|
26
|
+
recommendedAction: 'Wait for the automatic retry, or press Sync to retry now.'
|
|
27
|
+
};
|
|
28
|
+
case 'push-in-flight':
|
|
29
|
+
case 'pull-in-flight':
|
|
30
|
+
return {
|
|
31
|
+
summary: 'A sync request is already running for this workspace.',
|
|
32
|
+
recommendedAction: 'Wait for the current sync request to finish.'
|
|
33
|
+
};
|
|
34
|
+
case 'lease-held':
|
|
35
|
+
return {
|
|
36
|
+
summary: 'Another local window is already syncing this workspace.',
|
|
37
|
+
recommendedAction: 'Use a single local window for sync, or close the other syncing window.'
|
|
38
|
+
};
|
|
39
|
+
case 'invalid-workspace':
|
|
40
|
+
return {
|
|
41
|
+
summary: 'Workspace setup is required before sync can run.',
|
|
42
|
+
recommendedAction: 'Open or create a named workspace before retrying sync.'
|
|
43
|
+
};
|
|
44
|
+
case 'cloud-auth-unconfigured':
|
|
45
|
+
return {
|
|
46
|
+
summary: 'Cloud sync is unavailable because cloud authentication is not configured.',
|
|
47
|
+
recommendedAction: 'Configure cloud authentication before turning on sync.'
|
|
48
|
+
};
|
|
49
|
+
case 'runtime-not-local':
|
|
50
|
+
return {
|
|
51
|
+
summary: 'Workspace sync controls are only available in the local runtime.',
|
|
52
|
+
recommendedAction: 'Open this workspace in the local app to manage sync.'
|
|
53
|
+
};
|
|
54
|
+
case 'sync-disabled':
|
|
55
|
+
return {
|
|
56
|
+
summary: 'Workspace sync is currently turned off.',
|
|
57
|
+
recommendedAction: 'Turn on sync when you are ready to connect this workspace to cloud.'
|
|
58
|
+
};
|
|
59
|
+
default:
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
1
63
|
export function resolveHeaderWorkspaceSyncPresentation(input) {
|
|
2
64
|
const actionable = input.runtimeMode === 'local' && input.isAuthenticated;
|
|
3
65
|
if (actionable) {
|
|
66
|
+
const blockedReasonPresentation = resolveBlockedReasonPresentation(input.retryBlockedReason
|
|
67
|
+
|| input.pullBlockedReason
|
|
68
|
+
|| input.pushBlockedReason
|
|
69
|
+
|| null);
|
|
4
70
|
return {
|
|
5
71
|
actionable,
|
|
6
72
|
status: input.workspaceSyncStatus,
|
|
7
73
|
syncEnabledLabel: input.workspaceCloudSyncEnabled ? 'yes' : 'no',
|
|
8
|
-
summary: input.workspaceSyncSummary,
|
|
9
|
-
recommendedAction: input.workspaceSyncRecommendedAction,
|
|
74
|
+
summary: blockedReasonPresentation?.summary || input.workspaceSyncSummary,
|
|
75
|
+
recommendedAction: blockedReasonPresentation?.recommendedAction || input.workspaceSyncRecommendedAction,
|
|
10
76
|
lastError: input.workspaceSyncError
|
|
11
77
|
};
|
|
12
78
|
}
|
|
@@ -25,7 +25,10 @@ describe('resolveHeaderWorkspaceSyncPresentation', () => {
|
|
|
25
25
|
workspaceCloudSyncEnabled: true,
|
|
26
26
|
workspaceSyncSummary: 'Sync needs attention before it can continue.',
|
|
27
27
|
workspaceSyncRecommendedAction: 'Press Sync to retry.',
|
|
28
|
-
workspaceSyncError: 'Retry later'
|
|
28
|
+
workspaceSyncError: 'Retry later',
|
|
29
|
+
pushBlockedReason: null,
|
|
30
|
+
pullBlockedReason: null,
|
|
31
|
+
retryBlockedReason: null
|
|
29
32
|
});
|
|
30
33
|
expect(result.actionable).toBe(true);
|
|
31
34
|
expect(result.status).toBe('attention');
|
|
@@ -33,4 +36,36 @@ describe('resolveHeaderWorkspaceSyncPresentation', () => {
|
|
|
33
36
|
expect(result.summary).toBe('Sync needs attention before it can continue.');
|
|
34
37
|
expect(result.lastError).toBe('Retry later');
|
|
35
38
|
});
|
|
39
|
+
it('surfaces the highest-priority blocked sync reason in the visible summary', () => {
|
|
40
|
+
const result = resolveHeaderWorkspaceSyncPresentation({
|
|
41
|
+
runtimeMode: 'local',
|
|
42
|
+
isAuthenticated: true,
|
|
43
|
+
workspaceSyncStatus: 'attention',
|
|
44
|
+
workspaceCloudSyncEnabled: true,
|
|
45
|
+
workspaceSyncSummary: 'Sync needs attention before it can continue.',
|
|
46
|
+
workspaceSyncRecommendedAction: 'Press Sync to retry.',
|
|
47
|
+
workspaceSyncError: 'Retry later',
|
|
48
|
+
pushBlockedReason: 'attach-cloud',
|
|
49
|
+
pullBlockedReason: 'retry-pending',
|
|
50
|
+
retryBlockedReason: 'auth-required'
|
|
51
|
+
});
|
|
52
|
+
expect(result.summary).toBe('Sync is paused until you sign in again.');
|
|
53
|
+
expect(result.recommendedAction).toBe('Sign in, then press Sync to retry.');
|
|
54
|
+
});
|
|
55
|
+
it('explains when another local window holds the sync lease', () => {
|
|
56
|
+
const result = resolveHeaderWorkspaceSyncPresentation({
|
|
57
|
+
runtimeMode: 'local',
|
|
58
|
+
isAuthenticated: true,
|
|
59
|
+
workspaceSyncStatus: 'attention',
|
|
60
|
+
workspaceCloudSyncEnabled: true,
|
|
61
|
+
workspaceSyncSummary: 'Sync needs attention before it can continue.',
|
|
62
|
+
workspaceSyncRecommendedAction: 'Press Sync to retry.',
|
|
63
|
+
workspaceSyncError: 'Retry later',
|
|
64
|
+
pushBlockedReason: 'lease-held',
|
|
65
|
+
pullBlockedReason: null,
|
|
66
|
+
retryBlockedReason: null
|
|
67
|
+
});
|
|
68
|
+
expect(result.summary).toBe('Another local window is already syncing this workspace.');
|
|
69
|
+
expect(result.recommendedAction).toBe('Use a single local window for sync, or close the other syncing window.');
|
|
70
|
+
});
|
|
36
71
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taskforcehq/taskforce",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.306",
|
|
4
4
|
"description": "Mission Command center for AI-powered task management (beta - under active development)",
|
|
5
5
|
"author": "Taskforce HQ <hello@taskforcehq.ai> (https://taskforcehq.ai)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"build:ui": "npm run build:app",
|
|
55
55
|
"check:deploy-preflight": "npm run build",
|
|
56
56
|
"hooks:install": "git config core.hooksPath .githooks",
|
|
57
|
-
"build": "shx rm -rf dist && tsc && shx cp src/Taskforce.module.css dist/Taskforce.module.css && shx mkdir -p dist/resources && shx cp -r src/resources/* dist/resources/ && shx rm -f dist/resources/templates/workflows/release.yaml && shx mkdir -p dist/public && shx cp -r src/assets/images/* dist/public/ && shx cp -r src/assets/favicon/* dist/public/ && shx chmod +x dist/cli.js && npm run build:ui",
|
|
57
|
+
"build": "shx rm -rf dist && tsc && shx cp src/Taskforce.module.css dist/Taskforce.module.css && shx mkdir -p dist/styles && shx cp src/styles/fonts.css dist/styles/fonts.css && shx mkdir -p dist/assets/fonts && shx cp src/assets/fonts/*.woff2 dist/assets/fonts/ && shx mkdir -p dist/resources && shx cp -r src/resources/* dist/resources/ && shx rm -f dist/resources/templates/workflows/release.yaml && shx mkdir -p dist/public && shx cp -r src/assets/images/* dist/public/ && shx cp -r src/assets/favicon/* dist/public/ && shx chmod +x dist/cli.js && npm run build:ui",
|
|
58
58
|
"mcp": "node dist/mcp/server.js",
|
|
59
59
|
"gen:workflows": "node scripts/generate-workflow-templates.mjs",
|
|
60
60
|
"check:workflows": "node scripts/generate-workflow-templates.mjs --check",
|
|
@@ -76,6 +76,12 @@
|
|
|
76
76
|
"test:e2e:realtime:attachments": "npm run test:e2e:realtime -- tests/e2e/attachment-sync.spec.ts",
|
|
77
77
|
"test:e2e:realtime:multiclient": "npm run test:e2e:realtime -- tests/e2e/realtime-multiclient.spec.ts",
|
|
78
78
|
"test:e2e:realtime:reconnect": "npm run test:e2e:realtime -- tests/e2e/realtime-reconnect.spec.ts",
|
|
79
|
+
"test:e2e:onboarding": "npx playwright test -c playwright.e2e.config.ts tests/e2e/auth-runtime.spec.ts tests/e2e/billing-runtime.spec.ts",
|
|
80
|
+
"test:billing:deterministic": "npx vitest run src/server/routes/billing.test.ts src/components/views/PlansPage.test.tsx src/components/views/PlanComparisonPage.test.tsx src/migrations/billingSchemaParity.test.ts",
|
|
81
|
+
"test:billing:runtime:mock": "npx playwright test -c playwright.e2e.config.ts tests/e2e/billing-runtime.spec.ts",
|
|
82
|
+
"test:billing:local": "npm run test:billing:deterministic && npm run test:billing:runtime:mock",
|
|
83
|
+
"test:billing:performance:smoke": "sh scripts/run-billing-performance-smoke.sh",
|
|
84
|
+
"test:billing:performance:smoke:live": "TASKFORCE_BILLING_ENABLE_LIVE_PURCHASE=1 sh scripts/run-billing-performance-smoke.sh",
|
|
79
85
|
"playwright:auth:bootstrap": "node scripts/bootstrap-playwright-auth.mjs",
|
|
80
86
|
"playwright:auth": "sh scripts/playwright-auth.sh",
|
|
81
87
|
"playwright:interactive": "playwright test -c playwright.interactive.config.ts tests/e2e/interactive.smoke.spec.ts",
|
|
@@ -83,6 +89,7 @@
|
|
|
83
89
|
"qa:open": "node scripts/qa-open.mjs",
|
|
84
90
|
"check:env": "node --import tsx scripts/check-env.ts --target=server --strict=true",
|
|
85
91
|
"check:env:soak": "node --import tsx scripts/check-env.ts --target=soak --strict=true",
|
|
92
|
+
"check:mcp-smoke": "node scripts/check-cloud-mcp.mjs",
|
|
86
93
|
"check:compat": "node scripts/check-compat-boundaries.mjs",
|
|
87
94
|
"gen:env-example": "node --import tsx scripts/generate-env-example.ts",
|
|
88
95
|
"check:sync-smoke-preflight": "node --import tsx src/soak/preflight.cli.ts",
|
|
@@ -104,6 +111,7 @@
|
|
|
104
111
|
"js-yaml": "^4.1.1",
|
|
105
112
|
"nodemailer": "^6.10.1",
|
|
106
113
|
"pg": "^8.18.0",
|
|
114
|
+
"react-avatar-editor": "^15.1.0",
|
|
107
115
|
"rehype-sanitize": "^6.0.0",
|
|
108
116
|
"stripe": "^20.3.1",
|
|
109
117
|
"ws": "^8.18.0"
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const DEFAULT_ENDPOINTS = {
|
|
4
|
+
production: 'https://mcp.taskforcehq.ai/mcp',
|
|
5
|
+
staging: 'https://staging-mcp.taskforcehq.ai/mcp',
|
|
6
|
+
performance: 'https://performance-mcp.taskforcehq.ai/mcp'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const REQUEST_TIMEOUT_MS = 10000;
|
|
10
|
+
|
|
11
|
+
function normalizeTargets(argv) {
|
|
12
|
+
const values = argv.length > 0 ? argv : Object.keys(DEFAULT_ENDPOINTS);
|
|
13
|
+
return values.map((value) => {
|
|
14
|
+
const normalized = String(value || '').trim().toLowerCase();
|
|
15
|
+
if (DEFAULT_ENDPOINTS[normalized]) {
|
|
16
|
+
return {
|
|
17
|
+
label: normalized,
|
|
18
|
+
url: DEFAULT_ENDPOINTS[normalized]
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
label: normalized || 'custom',
|
|
23
|
+
url: String(value || '').trim()
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function checkEndpoint(target) {
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetch(target.url, {
|
|
33
|
+
method: 'GET',
|
|
34
|
+
headers: {
|
|
35
|
+
Accept: 'application/json'
|
|
36
|
+
},
|
|
37
|
+
signal: controller.signal
|
|
38
|
+
});
|
|
39
|
+
const contentType = String(response.headers.get('content-type') || '');
|
|
40
|
+
const responseText = await response.text();
|
|
41
|
+
let payload = null;
|
|
42
|
+
try {
|
|
43
|
+
payload = responseText ? JSON.parse(responseText) : null;
|
|
44
|
+
} catch {
|
|
45
|
+
payload = null;
|
|
46
|
+
}
|
|
47
|
+
const message = typeof payload?.error?.message === 'string'
|
|
48
|
+
? payload.error.message.trim()
|
|
49
|
+
: '';
|
|
50
|
+
|
|
51
|
+
if (response.status !== 401) {
|
|
52
|
+
throw new Error(`expected HTTP 401 but received ${response.status}`);
|
|
53
|
+
}
|
|
54
|
+
if (!contentType.includes('application/json')) {
|
|
55
|
+
throw new Error(`expected application/json response but received ${contentType || 'unknown content-type'}`);
|
|
56
|
+
}
|
|
57
|
+
if (message !== 'Unauthorized.') {
|
|
58
|
+
throw new Error(`expected MCP Unauthorized. payload but received message=${JSON.stringify(message || responseText.slice(0, 200))}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
console.log(`[mcp-smoke] ${target.label} ok ${target.url} -> 401 Unauthorized.`);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
64
|
+
throw new Error(`[mcp-smoke] ${target.label} failed ${target.url}: ${message}`);
|
|
65
|
+
} finally {
|
|
66
|
+
clearTimeout(timeout);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function main() {
|
|
71
|
+
const targets = normalizeTargets(process.argv.slice(2));
|
|
72
|
+
for (const target of targets) {
|
|
73
|
+
if (!target.url) {
|
|
74
|
+
throw new Error(`[mcp-smoke] ${target.label} has no URL to check.`);
|
|
75
|
+
}
|
|
76
|
+
await checkEndpoint(target);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
main().catch((error) => {
|
|
81
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
82
|
+
process.exitCode = 1;
|
|
83
|
+
});
|
|
@@ -49,19 +49,19 @@ lines.push('');
|
|
|
49
49
|
|
|
50
50
|
for (const t of tasks) {
|
|
51
51
|
lines.push(`INSERT INTO tasks (
|
|
52
|
-
id, tenant_id, title, description, status, priority, complexity, type, category,
|
|
52
|
+
id, tenant_id, workspace_id, title, description, status, priority, complexity, type, category,
|
|
53
53
|
approach, created_at, updated_at, completed_at, canceled_reason,
|
|
54
54
|
is_archived, specialists, taxonomies, created_by,
|
|
55
|
-
scheduled_date, due_date, scheduled_week_key, order_in_day
|
|
56
|
-
parent_task_id, child_display_order
|
|
55
|
+
scheduled_date, due_date, scheduled_week_key, order_in_day
|
|
57
56
|
) VALUES (
|
|
58
|
-
${sqlString(t.id)}, ${sqlString(t.tenant_id || 'default')}, ${sqlString(t.title)}, ${sqlString(t.description)}, ${sqlString(t.status)}, ${sqlNumber(t.priority)}, ${sqlNumber(t.complexity)}, ${sqlString(t.type)}, ${sqlString(t.category)},
|
|
57
|
+
${sqlString(t.id)}, ${sqlString(t.tenant_id || 'default')}, ${sqlString(t.workspace_id || 'default')}, ${sqlString(t.title)}, ${sqlString(t.description)}, ${sqlString(t.status)}, ${sqlNumber(t.priority)}, ${sqlNumber(t.complexity)}, ${sqlString(t.type)}, ${sqlString(t.category)},
|
|
59
58
|
${sqlString(t.approach)}, ${sqlString(t.created_at)}, ${sqlString(t.updated_at)}, ${sqlString(t.completed_at)}, ${sqlString(t.canceled_reason)},
|
|
60
59
|
${sqlBool(t.is_archived)}, ${sqlString(t.specialists)}, ${sqlString(t.taxonomies)}, ${sqlString(t.created_by)},
|
|
61
|
-
${sqlString(t.scheduled_date)}, ${sqlString(t.due_date)}, ${sqlString(t.scheduled_week_key)}, ${sqlNumber(t.order_in_day)}
|
|
62
|
-
${sqlString(t.parent_task_id)}, ${sqlNumber(t.child_display_order)}
|
|
60
|
+
${sqlString(t.scheduled_date)}, ${sqlString(t.due_date)}, ${sqlString(t.scheduled_week_key)}, ${sqlNumber(t.order_in_day)}
|
|
63
61
|
)
|
|
64
62
|
ON CONFLICT (id) DO UPDATE SET
|
|
63
|
+
tenant_id = EXCLUDED.tenant_id,
|
|
64
|
+
workspace_id = EXCLUDED.workspace_id,
|
|
65
65
|
title = EXCLUDED.title,
|
|
66
66
|
description = EXCLUDED.description,
|
|
67
67
|
status = EXCLUDED.status,
|
|
@@ -81,9 +81,7 @@ ON CONFLICT (id) DO UPDATE SET
|
|
|
81
81
|
scheduled_date = EXCLUDED.scheduled_date,
|
|
82
82
|
due_date = EXCLUDED.due_date,
|
|
83
83
|
scheduled_week_key = EXCLUDED.scheduled_week_key,
|
|
84
|
-
order_in_day = EXCLUDED.order_in_day
|
|
85
|
-
parent_task_id = EXCLUDED.parent_task_id,
|
|
86
|
-
child_display_order = EXCLUDED.child_display_order;`);
|
|
84
|
+
order_in_day = EXCLUDED.order_in_day;`);
|
|
87
85
|
}
|
|
88
86
|
|
|
89
87
|
for (const c of comments) {
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
|
-
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE
|
|
4
|
+
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
|
|
5
5
|
REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
|
|
6
6
|
|
|
7
7
|
if [ -f "$LOCAL_ENV_FILE" ]; then
|
|
8
|
+
set -a
|
|
8
9
|
# shellcheck disable=SC1090
|
|
9
10
|
. "$LOCAL_ENV_FILE"
|
|
11
|
+
set +a
|
|
10
12
|
elif [ -f "$REPO_E2E_ENV_FILE" ]; then
|
|
13
|
+
set -a
|
|
11
14
|
# shellcheck disable=SC1090
|
|
12
15
|
. "$REPO_E2E_ENV_FILE"
|
|
16
|
+
set +a
|
|
13
17
|
fi
|
|
14
18
|
|
|
15
19
|
exec node scripts/bootstrap-playwright-auth.mjs "$@"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
set -eu
|
|
3
|
+
|
|
4
|
+
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
|
|
5
|
+
REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
|
|
6
|
+
|
|
7
|
+
if [ -f "$LOCAL_ENV_FILE" ]; then
|
|
8
|
+
set -a
|
|
9
|
+
# shellcheck disable=SC1090
|
|
10
|
+
. "$LOCAL_ENV_FILE"
|
|
11
|
+
set +a
|
|
12
|
+
elif [ -f "$REPO_E2E_ENV_FILE" ]; then
|
|
13
|
+
set -a
|
|
14
|
+
# shellcheck disable=SC1090
|
|
15
|
+
. "$REPO_E2E_ENV_FILE"
|
|
16
|
+
set +a
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL="${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
|
|
20
|
+
export TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
|
|
21
|
+
export TASKFORCE_PLAYWRIGHT_BASE_URL="${TASKFORCE_PLAYWRIGHT_BASE_URL:-$TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL}"
|
|
22
|
+
|
|
23
|
+
node scripts/bootstrap-playwright-auth.mjs
|
|
24
|
+
exec npx playwright test -c playwright.interactive.config.ts tests/e2e/billing-performance.smoke.spec.ts "$@"
|
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
|
|
5
|
+
REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
|
|
6
|
+
|
|
7
|
+
if [ -f "$LOCAL_ENV_FILE" ]; then
|
|
8
|
+
set -a
|
|
9
|
+
# shellcheck disable=SC1090
|
|
10
|
+
. "$LOCAL_ENV_FILE"
|
|
11
|
+
set +a
|
|
12
|
+
elif [ -f "$REPO_E2E_ENV_FILE" ]; then
|
|
5
13
|
set -a
|
|
6
|
-
|
|
14
|
+
# shellcheck disable=SC1090
|
|
15
|
+
. "$REPO_E2E_ENV_FILE"
|
|
7
16
|
set +a
|
|
8
17
|
fi
|
|
9
18
|
|
|
10
19
|
# Mirror soak defaults so realtime e2e runs are plug-compatible with existing env setup.
|
|
11
20
|
export SYNC_SOAK_LOCAL_BASE_URL="${SYNC_SOAK_LOCAL_BASE_URL:-http://localhost:5174}"
|
|
12
|
-
export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
|
|
21
|
+
export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}}"
|
|
13
22
|
export SYNC_SOAK_WORKSPACE_ID="${SYNC_SOAK_WORKSPACE_ID:-test-smoke}"
|
|
23
|
+
export SYNC_SOAK_EMAIL="${SYNC_SOAK_EMAIL:-${TASKFORCE_E2E_EMAIL:-}}"
|
|
24
|
+
export SYNC_SOAK_PASSWORD="${SYNC_SOAK_PASSWORD:-${TASKFORCE_E2E_PASSWORD:-}}"
|
|
25
|
+
PLAYWRIGHT_AUTH_STORAGE_STATE="${PLAYWRIGHT_AUTH_STORAGE_STATE:-${TASKFORCE_PLAYWRIGHT_STORAGE_STATE:-}}"
|
|
26
|
+
unset TASKFORCE_E2E_EMAIL TASKFORCE_E2E_PASSWORD TASKFORCE_PLAYWRIGHT_STORAGE_STATE TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
|
|
14
27
|
|
|
15
28
|
node --import tsx scripts/check-env.ts --target=soak --strict=true
|
|
29
|
+
export PLAYWRIGHT_AUTH_STORAGE_STATE
|
|
16
30
|
npx playwright test -c playwright.e2e.config.ts "$@"
|
package/scripts/run-smoke.sh
CHANGED
|
@@ -1,22 +1,34 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
|
|
5
|
+
REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
|
|
6
|
+
|
|
7
|
+
if [ -f "$LOCAL_ENV_FILE" ]; then
|
|
8
|
+
set -a
|
|
9
|
+
# shellcheck disable=SC1090
|
|
10
|
+
. "$LOCAL_ENV_FILE"
|
|
11
|
+
set +a
|
|
12
|
+
elif [ -f "$REPO_E2E_ENV_FILE" ]; then
|
|
5
13
|
set -a
|
|
6
|
-
|
|
14
|
+
# shellcheck disable=SC1090
|
|
15
|
+
. "$REPO_E2E_ENV_FILE"
|
|
7
16
|
set +a
|
|
8
17
|
fi
|
|
9
18
|
|
|
10
19
|
# Provide safe defaults for non-secret settings; allow caller/.env.e2e overrides.
|
|
11
20
|
export SYNC_SOAK_LOCAL_BASE_URL="${SYNC_SOAK_LOCAL_BASE_URL:-http://localhost:5174}"
|
|
12
|
-
export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
|
|
21
|
+
export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}}"
|
|
13
22
|
export SYNC_SOAK_WORKSPACE_ID="${SYNC_SOAK_WORKSPACE_ID:-test-smoke}"
|
|
23
|
+
export SYNC_SOAK_EMAIL="${SYNC_SOAK_EMAIL:-${TASKFORCE_E2E_EMAIL:-}}"
|
|
24
|
+
export SYNC_SOAK_PASSWORD="${SYNC_SOAK_PASSWORD:-${TASKFORCE_E2E_PASSWORD:-}}"
|
|
25
|
+
unset TASKFORCE_E2E_EMAIL TASKFORCE_E2E_PASSWORD TASKFORCE_PLAYWRIGHT_STORAGE_STATE TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
|
|
14
26
|
|
|
15
27
|
node --import tsx scripts/check-env.ts --target=soak --strict=true
|
|
16
28
|
|
|
17
|
-
# Shared credentials are required and
|
|
29
|
+
# Shared credentials are required and may come from the local Playwright auth env file or repo .env.e2e.
|
|
18
30
|
if [ -z "${SYNC_SOAK_ACCOUNTS_JSON:-}" ] && { [ -z "${SYNC_SOAK_EMAIL:-}" ] || [ -z "${SYNC_SOAK_PASSWORD:-}" ]; }; then
|
|
19
|
-
echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in env
|
|
31
|
+
echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in $TASKFORCE_PLAYWRIGHT_ENV_FILE or .env.e2e." >&2
|
|
20
32
|
exit 1
|
|
21
33
|
fi
|
|
22
34
|
|
package/scripts/run-soak.sh
CHANGED
|
@@ -1,23 +1,35 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
LOCAL_ENV_FILE="${TASKFORCE_PLAYWRIGHT_ENV_FILE:-$HOME/.codex/taskforce-playwright.env}"
|
|
5
|
+
REPO_E2E_ENV_FILE="${TASKFORCE_PLAYWRIGHT_REPO_E2E_ENV_FILE:-.env.e2e}"
|
|
6
|
+
|
|
7
|
+
if [ -f "$LOCAL_ENV_FILE" ]; then
|
|
8
|
+
set -a
|
|
9
|
+
# shellcheck disable=SC1090
|
|
10
|
+
. "$LOCAL_ENV_FILE"
|
|
11
|
+
set +a
|
|
12
|
+
elif [ -f "$REPO_E2E_ENV_FILE" ]; then
|
|
5
13
|
set -a
|
|
6
|
-
|
|
14
|
+
# shellcheck disable=SC1090
|
|
15
|
+
. "$REPO_E2E_ENV_FILE"
|
|
7
16
|
set +a
|
|
8
17
|
fi
|
|
9
18
|
|
|
10
19
|
# Provide safe defaults for non-secret settings; allow caller/.env.e2e overrides.
|
|
11
20
|
# Soak runs target the dedicated performance cloud by default.
|
|
12
21
|
export SYNC_SOAK_LOCAL_BASE_URL="${SYNC_SOAK_LOCAL_BASE_URL:-http://localhost:5174}"
|
|
13
|
-
export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}"
|
|
22
|
+
export SYNC_SOAK_CLOUD_BASE_URL="${SYNC_SOAK_CLOUD_BASE_URL:-${TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL:-https://performance-app.taskforcehq.ai}}"
|
|
14
23
|
export SYNC_SOAK_WORKSPACE_ID="${SYNC_SOAK_WORKSPACE_ID:-test-smoke}"
|
|
24
|
+
export SYNC_SOAK_EMAIL="${SYNC_SOAK_EMAIL:-${TASKFORCE_E2E_EMAIL:-}}"
|
|
25
|
+
export SYNC_SOAK_PASSWORD="${SYNC_SOAK_PASSWORD:-${TASKFORCE_E2E_PASSWORD:-}}"
|
|
26
|
+
unset TASKFORCE_E2E_EMAIL TASKFORCE_E2E_PASSWORD TASKFORCE_PLAYWRIGHT_STORAGE_STATE TASKFORCE_PLAYWRIGHT_CLOUD_BASE_URL
|
|
15
27
|
|
|
16
28
|
node --import tsx scripts/check-env.ts --target=soak --strict=true
|
|
17
29
|
|
|
18
|
-
# Shared credentials are required and
|
|
30
|
+
# Shared credentials are required and may come from the local Playwright auth env file or repo .env.e2e.
|
|
19
31
|
if [ -z "${SYNC_SOAK_ACCOUNTS_JSON:-}" ] && { [ -z "${SYNC_SOAK_EMAIL:-}" ] || [ -z "${SYNC_SOAK_PASSWORD:-}" ]; }; then
|
|
20
|
-
echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in env
|
|
32
|
+
echo "Missing credentials. Set SYNC_SOAK_ACCOUNTS_JSON or SYNC_SOAK_EMAIL+SYNC_SOAK_PASSWORD in $TASKFORCE_PLAYWRIGHT_ENV_FILE or .env.e2e." >&2
|
|
21
33
|
exit 1
|
|
22
34
|
fi
|
|
23
35
|
|
|
@@ -284,7 +284,7 @@ export const workflowDocs = [
|
|
|
284
284
|
' - `### Next Action`',
|
|
285
285
|
'6. Ask whether to save as `{artifacts.implementationPlan.path}`.',
|
|
286
286
|
'7. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "implementation-plan.md"`.',
|
|
287
|
-
' - Use `{{MCP_PREFIX}}link_task_context` only for
|
|
287
|
+
' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
|
|
288
288
|
'8. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
|
|
289
289
|
'9. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
|
|
290
290
|
'10. Print `prompts.handoffPrompt` and stop.'
|
|
@@ -358,7 +358,7 @@ export const workflowDocs = [
|
|
|
358
358
|
' - `### Next Step`',
|
|
359
359
|
'4. Ask whether to save as `{artifacts.collaborationBlueprint.path}`.',
|
|
360
360
|
'5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "collaboration-blueprint.md"`.',
|
|
361
|
-
' - Use `{{MCP_PREFIX}}link_task_context` only for
|
|
361
|
+
' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
|
|
362
362
|
'6. Ask concise clarification questions only if required fields above are missing.',
|
|
363
363
|
'7. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
|
|
364
364
|
'8. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
|
|
@@ -435,14 +435,14 @@ export const workflowDocs = [
|
|
|
435
435
|
' - `### Next Step`',
|
|
436
436
|
'4. Ask whether to save as `{artifacts.evaluationReport.path}`.',
|
|
437
437
|
'5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "evaluation.md"`.',
|
|
438
|
-
' - Use `{{MCP_PREFIX}}link_task_context` only for
|
|
438
|
+
' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
|
|
439
439
|
'6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
|
|
440
440
|
'',
|
|
441
441
|
'## 3. Optional Report Artifact',
|
|
442
442
|
'',
|
|
443
443
|
'1. Use report files only when user opts in.',
|
|
444
444
|
'2. Save to `task attachment "evaluation.md"` and attach to task context when approved.',
|
|
445
|
-
' - If the document
|
|
445
|
+
' - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.',
|
|
446
446
|
'3. Stop.'
|
|
447
447
|
].join('\n')
|
|
448
448
|
}
|
|
@@ -513,7 +513,7 @@ export const workflowDocs = [
|
|
|
513
513
|
' - `### Next Status`',
|
|
514
514
|
'3. Ask whether to save as `{artifacts.reviewReport.path}`.',
|
|
515
515
|
'4. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "review.md"`.',
|
|
516
|
-
' - Use `{{MCP_PREFIX}}link_task_context` only for
|
|
516
|
+
' - Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.',
|
|
517
517
|
'5. Keep status within allowed statuses (`task`, `on-hold`, `in-progress`, `review`, `done`) unless user explicitly instructs otherwise.',
|
|
518
518
|
' - If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.',
|
|
519
519
|
'6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.',
|
|
@@ -522,7 +522,7 @@ export const workflowDocs = [
|
|
|
522
522
|
'',
|
|
523
523
|
'1. Use report files only when user opts in.',
|
|
524
524
|
'2. Save to `task attachment "review.md"` and attach to task context when approved.',
|
|
525
|
-
' - If the document
|
|
525
|
+
' - If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.',
|
|
526
526
|
'3. Stop.'
|
|
527
527
|
].join('\n')
|
|
528
528
|
}
|
|
@@ -102,7 +102,7 @@ content:
|
|
|
102
102
|
- `### Next Step`
|
|
103
103
|
4. Ask whether to save as `{artifacts.collaborationBlueprint.path}`.
|
|
104
104
|
5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "collaboration-blueprint.md"`.
|
|
105
|
-
- Use `{{MCP_PREFIX}}link_task_context` only for
|
|
105
|
+
- Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
|
|
106
106
|
6. Ask concise clarification questions only if required fields above are missing.
|
|
107
107
|
7. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
|
|
108
108
|
8. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
|
|
@@ -106,12 +106,12 @@ content:
|
|
|
106
106
|
- `### Next Step`
|
|
107
107
|
4. Ask whether to save as `{artifacts.evaluationReport.path}`.
|
|
108
108
|
5. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "evaluation.md"`.
|
|
109
|
-
- Use `{{MCP_PREFIX}}link_task_context` only for
|
|
109
|
+
- Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
|
|
110
110
|
6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
|
|
111
111
|
|
|
112
112
|
## 3. Optional Report Artifact
|
|
113
113
|
|
|
114
114
|
1. Use report files only when user opts in.
|
|
115
115
|
2. Save to `task attachment "evaluation.md"` and attach to task context when approved.
|
|
116
|
-
- If the document
|
|
116
|
+
- If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.
|
|
117
117
|
3. Stop.
|
|
@@ -113,7 +113,7 @@ content:
|
|
|
113
113
|
- `### Next Action`
|
|
114
114
|
6. Ask whether to save as `{artifacts.implementationPlan.path}`.
|
|
115
115
|
7. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "implementation-plan.md"`.
|
|
116
|
-
- Use `{{MCP_PREFIX}}link_task_context` only for
|
|
116
|
+
- Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
|
|
117
117
|
8. If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
|
|
118
118
|
9. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
|
|
119
119
|
10. Print `prompts.handoffPrompt` and stop.
|
|
@@ -102,7 +102,7 @@ content:
|
|
|
102
102
|
- `### Next Status`
|
|
103
103
|
3. Ask whether to save as `{artifacts.reviewReport.path}`.
|
|
104
104
|
4. If user confirms, persist task-specific content via `{{MCP_PREFIX}}save_task_attachment` using `filename: "review.md"`.
|
|
105
|
-
- Use `{{MCP_PREFIX}}link_task_context` only for
|
|
105
|
+
- Use `{{MCP_PREFIX}}link_task_context` only for external http(s) URLs that should stay as references.
|
|
106
106
|
5. Keep status within allowed statuses (`task`, `on-hold`, `in-progress`, `review`, `done`) unless user explicitly instructs otherwise.
|
|
107
107
|
- If setting status to `task` or `on-hold`, add explicit comment justification using `{{MCP_PREFIX}}add_comment`.
|
|
108
108
|
6. Never set `cancelled`, and never call `{{MCP_PREFIX}}archive_task`, unless explicitly instructed by the user.
|
|
@@ -111,5 +111,5 @@ content:
|
|
|
111
111
|
|
|
112
112
|
1. Use report files only when user opts in.
|
|
113
113
|
2. Save to `task attachment "review.md"` and attach to task context when approved.
|
|
114
|
-
- If the document
|
|
114
|
+
- If the document should become a shared durable document, save it through the canonical document/document-manager flow instead of a raw `docs/` file.
|
|
115
115
|
3. Stop.
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,j as e}from"./vendor-react-CKJs5o3c.js";import{p as T,u as C,v as w,w as S,t as s,x as M}from"./index-DXUdtH1B.js";import{h as L,B as A,k as I,aa as B,aI as H,aJ as D,b as R}from"./vendor-icons-I7ZwG1z_.js";import"./vendor-markdown-BUxTU7dS.js";import"./vendor-dnd-DRzYolkg.js";import"./vendor-router-BbWMxlnO.js";function F({workspaceId:h}){const[x,k]=n.useState([]),[j,y]=n.useState(!1),[c,P]=n.useState(null),[p,m]=n.useState(null),[d,g]=n.useState(null),N=n.useCallback(async()=>{if(h){y(!0);try{const a=await(await fetch(`/api/taskforce/workspace/assignee-options?workspaceId=${encodeURIComponent(h)}`,{credentials:"include"})).json().catch(()=>({})),t=Array.isArray(a?.assignees)?a.assignees.filter(i=>i.kind==="agent").map(i=>({id:String(i.value||""),name:String(i.label||i.value||"Unknown Agent"),username:String(i.username||i.value||""),icon:String(i.icon||"Bot"),color:String(i.color||"#6B7280"),kind:String(i.kind||"agent"),description:typeof i.description=="string"?i.description:null,role:typeof i.role=="string"?i.role:null,provider:typeof i.provider=="string"?i.provider:null,model:typeof i.model=="string"?i.model:null,surfaceType:T(i.surfaceType),createdAt:String(i.createdAt||""),updatedAt:String(i.updatedAt||i.createdAt||""),lastActiveAt:typeof i.lastActiveAt=="string"?i.lastActiveAt:null})):[];k(t)}finally{y(!1)}}},[h]);n.useEffect(()=>{N()},[N]);const f=n.useMemo(()=>{const r=new Map;for(const a of x){const t=C(a.surfaceType);r.has(t)||r.set(t,new Map);const i=r.get(t),v=a.name.toLowerCase();i.has(v)||i.set(v,[]),i.get(v).push(a)}return w.map(a=>({section:a,label:S(a),groups:Array.from(r.get(a)?.entries()||[]).map(([t,i])=>({groupId:`${a}:${t}`,section:a,sectionLabel:S(a),profiles:i,primaryProfile:i[0]}))})).filter(a=>a.groups.length>0)},[x]),o=n.useMemo(()=>f.flatMap(r=>r.groups),[f]),l=n.useMemo(()=>o.find(r=>r.groupId===d)||o[0]||null,[o,d]);n.useEffect(()=>{if(!o.length){d!==null&&g(null);return}(!d||!o.some(r=>r.groupId===d))&&g(o[0].groupId)},[o,d]);const b=async(r,a)=>{m(null);try{const t=await fetch("/api/taskforce/workspace/ai-profiles/merge",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({keepId:r,mergeId:a})}),i=await t.json().catch(()=>({}));if(!t.ok){m({type:"error",message:String(i?.error||"Failed to merge AI profiles.")});return}P(null),m({type:"success",message:"AI profiles merged."}),await N()}catch{m({type:"error",message:"Failed to merge AI profiles."})}},u=r=>{const a=String(r||"").trim();if(!a)return"Unknown";const t=Date.parse(a);return Number.isFinite(t)?new Date(t).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"}):a};return e.jsx("div",{className:`${s.standalonePage} ${s.standaloneContent}`,style:{overflow:"auto"},children:e.jsx("div",{className:s.settingsContent,style:{maxWidth:1080,margin:"0 auto",width:"100%"},children:e.jsx("div",{className:s.settingGroup,children:e.jsxs("div",{children:[e.jsx("h4",{className:s.settingSubTitle,children:"Registered AI Profiles"}),e.jsx("p",{className:`${s.settingsHint} ${s.marginBottom12}`,children:"AI agents register profiles when connecting via MCP. Merge duplicates created when a token was lost."}),j&&e.jsxs("div",{className:s.settingsHint,children:[e.jsx(L,{size:13,className:s.spinner})," Loading profiles…"]}),!j&&x.length===0&&e.jsx("div",{className:s.settingsHint,children:"No AI profiles registered yet."}),!j&&f.length>0&&e.jsxs("div",{className:s.aiProfilesExplorer,children:[e.jsx("div",{className:s.aiProfilesListPane,children:e.jsx("div",{className:s.aiProfilesList,children:f.map(r=>e.jsxs("div",{className:s.aiProfilesSection,children:[e.jsx("div",{className:s.aiProfilesSectionHeader,children:r.label}),r.groups.map(a=>{const t=l?.groupId===a.groupId,i=a.primaryProfile;return e.jsxs("button",{type:"button",className:`${s.aiProfileGroup} ${a.profiles.length>1?s.aiProfileGroupDuplicate:""} ${t?s.aiProfileGroupSelected:""}`,onClick:()=>g(a.groupId),"aria-pressed":t,children:[e.jsxs("div",{className:s.aiProfileGroupHeader,children:[e.jsx(A,{size:13,style:{color:i.color}}),e.jsx("span",{className:s.aiProfileName,children:i.name}),a.profiles.length>1&&e.jsxs("span",{className:s.aiProfileDuplicateBadge,children:[e.jsx(I,{size:11})," ",a.profiles.length," duplicates"]})]}),e.jsxs("div",{className:s.settingsHint,style:{marginTop:6},children:["@",i.username]}),(i.surfaceType||i.role||i.provider||i.model)&&e.jsxs("div",{className:s.aiProfileMetaRow,children:[i.surfaceType&&e.jsx("span",{className:s.aiProfileSurfaceBadge,children:M(i.surfaceType)}),i.role&&e.jsx("span",{children:i.role}),i.provider&&e.jsx("span",{children:i.provider}),i.model&&e.jsx("span",{children:i.model})]}),i.description&&e.jsx("div",{className:s.settingsHint,style:{marginTop:4},children:i.description})]},a.groupId)})]},r.section))})}),l&&e.jsx("div",{className:s.aiProfileDetailPane,children:e.jsxs("div",{className:s.aiProfileDetailCard,children:[e.jsxs("div",{className:s.aiProfileDetailHero,children:[e.jsx("div",{className:s.aiProfileDetailIcon,style:{color:l.primaryProfile.color},children:e.jsx(A,{size:18})}),e.jsxs("div",{className:s.aiProfileDetailHeading,children:[e.jsx("div",{className:s.aiProfileDetailTitleRow,children:e.jsx("h5",{className:s.aiProfileDetailTitle,children:l.primaryProfile.name})}),e.jsxs("div",{className:s.aiProfileDetailMetaRow,children:[e.jsxs("span",{className:s.aiProfileDetailHandle,children:["@",l.primaryProfile.username]}),e.jsx("span",{className:s.aiProfileDetailSectionBadge,children:l.sectionLabel}),l.profiles.length>1&&e.jsxs("span",{className:s.aiProfileDetailLinkedCount,children:[l.profiles.length," linked"]})]})]})]}),l.primaryProfile.description&&e.jsx("div",{className:s.aiProfileDetailDescription,children:l.primaryProfile.description}),e.jsxs("div",{className:s.aiProfileDetailGrid,children:[e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(B,{size:12})," Role"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:l.primaryProfile.role||"Not set"})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(H,{size:12})," Provider"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:[l.primaryProfile.provider,l.primaryProfile.model].filter(Boolean).join(" · ")||"Not set"})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(D,{size:12})," Last active"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:u(l.primaryProfile.lastActiveAt)})]}),e.jsxs("div",{className:s.aiProfileDetailStat,children:[e.jsxs("span",{className:s.aiProfileDetailStatLabel,children:[e.jsx(D,{size:12})," Updated"]}),e.jsx("span",{className:s.aiProfileDetailStatValue,children:u(l.primaryProfile.updatedAt)})]})]}),e.jsxs("div",{className:s.aiProfileInstanceSection,children:[e.jsxs("div",{className:s.aiProfileInstanceSectionHeader,children:[e.jsx("span",{children:"Profile instances"}),e.jsx("span",{className:s.settingsHint,children:"Choose a keeper here if duplicates need to be merged."})]}),e.jsx("div",{className:s.aiProfileInstanceList,children:l.profiles.map(r=>e.jsxs("div",{className:s.aiProfileInstanceCard,children:[e.jsxs("div",{className:s.aiProfileInstanceTopRow,children:[e.jsxs("div",{children:[e.jsxs("div",{className:s.aiProfileInstanceName,children:["@",r.username]}),e.jsx("div",{className:s.aiProfileIdChip,children:r.id})]}),l.profiles.length>1&&c?.keepId===r.id&&e.jsx("span",{className:s.aiProfileKeepBadge,children:"Keeping"})]}),e.jsxs("div",{className:s.aiProfileInstanceMeta,children:[e.jsxs("span",{children:["Created ",u(r.createdAt)]}),e.jsxs("span",{children:["Updated ",u(r.updatedAt)]})]}),l.profiles.length>1&&c?.keepId!==r.id&&e.jsx("button",{className:s.secondaryHeaderBtn,title:"Keep this profile, merge others into it",onClick:()=>{const a=l.profiles.find(t=>t.id!==r.id)?.id;a&&P({keepId:r.id,mergeId:a})},children:"Keep this"})]},r.id))}),c&&l.profiles.some(r=>r.id===c.keepId)&&e.jsxs("div",{className:s.aiProfileMergeActions,children:[e.jsx("button",{className:s.dangerBtn,onClick:()=>{b(c.keepId,c.mergeId)},children:"Merge duplicates"}),e.jsx("button",{className:s.secondaryHeaderBtn,onClick:()=>P(null),children:"Cancel"})]})]})]})})]}),p&&e.jsxs("div",{className:`${p.type==="success"?s.successMessage:s.errorMessage} ${s.marginTop12}`,children:[p.type==="success"?e.jsx(R,{size:14}):e.jsx(I,{size:14}),p.message]})]})})})})}export{F as AgentsModule};
|