@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
package/dist/mcp/runtime.test.js
CHANGED
|
@@ -323,6 +323,7 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
323
323
|
const getTask = getTool(result, 'get_task');
|
|
324
324
|
const getPaths = getTool(result, 'get_paths');
|
|
325
325
|
const searchImages = getTool(result, 'search_images');
|
|
326
|
+
const getImage = getTool(result, 'get_image');
|
|
326
327
|
const getDocument = getTool(result, 'get_document');
|
|
327
328
|
const searchDocuments = getTool(result, 'search_documents');
|
|
328
329
|
const listAnnotatedAttachmentSessions = getTool(result, 'get_annotated_attachment_sessions');
|
|
@@ -341,10 +342,13 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
341
342
|
expect(getTask.description).toContain('Do not use this for image references like I-123 or document references like D-123.');
|
|
342
343
|
expect(getPaths.description).toContain('Get project and Taskforce storage paths.');
|
|
343
344
|
expect(searchImages.description).toContain('I-123 reference');
|
|
345
|
+
expect(getImage.description).toContain('placement, or visual correction feedback');
|
|
344
346
|
expect(getDocument.description).toContain('D-123');
|
|
345
347
|
expect(searchDocuments.description).toContain('D-123 reference');
|
|
346
348
|
expect(listAnnotatedAttachmentSessions.description).toContain('saved annotation sessions');
|
|
349
|
+
expect(listAnnotatedAttachmentSessions.description).toContain('inspect the saved session payload next');
|
|
347
350
|
expect(readAnnotatedAttachmentPayload.description).toContain('derived crop hints');
|
|
351
|
+
expect(readAnnotatedAttachmentPayload.description).toContain('authoritative instruction source');
|
|
348
352
|
expect(createAnnotatedAttachmentSession.description).toContain('before adding markers');
|
|
349
353
|
expect(deleteAnnotatedAttachmentSession.description).toContain('rather than deleting markers one by one');
|
|
350
354
|
expect(reviewImage.description).toContain('first-pass visual review');
|
|
@@ -400,6 +404,7 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
400
404
|
expect(getTask.description).toContain('Do not use this for image references like I-123 or document references like D-123.');
|
|
401
405
|
expect(searchImages.description).toContain('get_image');
|
|
402
406
|
expect(getImage.description).toContain('Use this first when the user references an image');
|
|
407
|
+
expect(getImage.description).toContain('read the saved annotation payload before making changes');
|
|
403
408
|
expect(searchDocuments.description).toContain('get_document');
|
|
404
409
|
expect(searchDocuments.description).toContain('read_document_content');
|
|
405
410
|
expect(getDocument.description).toContain('Use this first when the user references a document');
|
|
@@ -733,6 +738,63 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
733
738
|
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
734
739
|
}
|
|
735
740
|
});
|
|
741
|
+
it('creates a separate cloud profile and persists metadata when a same-name local profile already exists', async () => {
|
|
742
|
+
const projectRoot = createProjectRoot();
|
|
743
|
+
try {
|
|
744
|
+
const initial = parseToolJson(await callTool(projectRoot, 'local', 'resolve_profile', {
|
|
745
|
+
name: 'Automation Codex',
|
|
746
|
+
icon: 'Bot',
|
|
747
|
+
color: '#64748b'
|
|
748
|
+
}));
|
|
749
|
+
expect(initial.profile.description).toBeNull();
|
|
750
|
+
expect(initial.profile.role).toBeNull();
|
|
751
|
+
const currentProfile = parseToolJson(await callTool(projectRoot, 'cloud', 'get_current_profile', {}, {
|
|
752
|
+
workspaceId: 'workspace-1',
|
|
753
|
+
resolveProfile: false,
|
|
754
|
+
authAiProfileName: 'Automation Codex',
|
|
755
|
+
authAiProfileDescription: 'OpenAI Codex coding agent connected through MCP.',
|
|
756
|
+
authAiProfileRole: 'Coding Agent',
|
|
757
|
+
authAiProfileProvider: 'OpenAI',
|
|
758
|
+
authAiProfileModel: 'Codex',
|
|
759
|
+
authAiProfileSurfaceType: 'coding_tool'
|
|
760
|
+
}));
|
|
761
|
+
expect(currentProfile.profile).toEqual(expect.objectContaining({
|
|
762
|
+
name: 'Automation Codex',
|
|
763
|
+
description: 'OpenAI Codex coding agent connected through MCP.',
|
|
764
|
+
role: 'Coding Agent',
|
|
765
|
+
provider: 'OpenAI',
|
|
766
|
+
model: 'Codex',
|
|
767
|
+
surfaceType: 'coding_tool',
|
|
768
|
+
seatScope: 'cloud_metered'
|
|
769
|
+
}));
|
|
770
|
+
expect(currentProfile.profile.id).not.toBe(initial.profile.id);
|
|
771
|
+
const reloadedCore = new TaskforceCore({
|
|
772
|
+
projectRoot,
|
|
773
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
774
|
+
});
|
|
775
|
+
expect(reloadedCore.listAiProfiles('workspace-1')).toEqual(expect.arrayContaining([
|
|
776
|
+
expect.objectContaining({
|
|
777
|
+
id: initial.profile.id,
|
|
778
|
+
name: 'Automation Codex',
|
|
779
|
+
seatScope: 'local_unmetered'
|
|
780
|
+
}),
|
|
781
|
+
expect.objectContaining({
|
|
782
|
+
id: currentProfile.profile.id,
|
|
783
|
+
name: 'Automation Codex',
|
|
784
|
+
description: 'OpenAI Codex coding agent connected through MCP.',
|
|
785
|
+
role: 'Coding Agent',
|
|
786
|
+
provider: 'OpenAI',
|
|
787
|
+
model: 'Codex',
|
|
788
|
+
surfaceType: 'coding_tool',
|
|
789
|
+
seatScope: 'cloud_metered'
|
|
790
|
+
})
|
|
791
|
+
]));
|
|
792
|
+
reloadedCore.close();
|
|
793
|
+
}
|
|
794
|
+
finally {
|
|
795
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
796
|
+
}
|
|
797
|
+
});
|
|
736
798
|
it('allows mutating MCP tools in a fresh runtime when profileToken is passed', async () => {
|
|
737
799
|
const projectRoot = createProjectRoot();
|
|
738
800
|
try {
|
|
@@ -759,9 +821,12 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
759
821
|
it('allows mutating cloud MCP tools when the connection is configured with an AI profile token', async () => {
|
|
760
822
|
const projectRoot = createProjectRoot();
|
|
761
823
|
try {
|
|
762
|
-
const resolved = parseToolJson(await callTool(projectRoot, '
|
|
824
|
+
const resolved = parseToolJson(await callTool(projectRoot, 'cloud', 'resolve_profile', {
|
|
763
825
|
name: 'Automation Codex'
|
|
764
|
-
}, {
|
|
826
|
+
}, {
|
|
827
|
+
workspaceId: 'workspace-1',
|
|
828
|
+
resolveProfile: false
|
|
829
|
+
}));
|
|
765
830
|
const created = parseToolJson(await callTool(projectRoot, 'cloud', 'create_task', {
|
|
766
831
|
title: 'Configured token write'
|
|
767
832
|
}, {
|
|
@@ -816,6 +881,154 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
816
881
|
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
817
882
|
}
|
|
818
883
|
});
|
|
884
|
+
it('blocks cloud auto-bind when the configured AI profile has been retired by name until resolve_profile explicitly reactivates it', async () => {
|
|
885
|
+
const projectRoot = createProjectRoot();
|
|
886
|
+
try {
|
|
887
|
+
const core = new TaskforceCore({
|
|
888
|
+
projectRoot,
|
|
889
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
890
|
+
});
|
|
891
|
+
const resolved = core.resolveAiProfile({
|
|
892
|
+
workspaceId: 'workspace-1',
|
|
893
|
+
name: 'Automation Codex',
|
|
894
|
+
}, { trustedSeatScope: 'cloud_metered' });
|
|
895
|
+
core.archiveAiProfile({
|
|
896
|
+
workspaceId: 'workspace-1',
|
|
897
|
+
profileId: resolved.profile.id,
|
|
898
|
+
archivedBy: 'owner-1',
|
|
899
|
+
reason: 'manual_archive'
|
|
900
|
+
});
|
|
901
|
+
core.close();
|
|
902
|
+
const blocked = await callTool(projectRoot, 'cloud', 'create_task', {
|
|
903
|
+
title: 'Should stay retired'
|
|
904
|
+
}, {
|
|
905
|
+
workspaceId: 'workspace-1',
|
|
906
|
+
resolveProfile: false,
|
|
907
|
+
authAiProfileName: 'Automation Codex'
|
|
908
|
+
});
|
|
909
|
+
expect(blocked.isError).toBe(true);
|
|
910
|
+
const blockedPayload = parseToolJson(blocked);
|
|
911
|
+
expect(blockedPayload.code).toBe('AI_PROFILE_RETIRED');
|
|
912
|
+
expect(blockedPayload.error).toContain('has been retired from this workspace');
|
|
913
|
+
expect(blockedPayload.nextTool).toBe('resolve_profile');
|
|
914
|
+
const reactivated = parseToolJson(await callTool(projectRoot, 'cloud', 'resolve_profile', {
|
|
915
|
+
name: 'Automation Codex',
|
|
916
|
+
surfaceType: 'agent'
|
|
917
|
+
}, {
|
|
918
|
+
workspaceId: 'workspace-1',
|
|
919
|
+
resolveProfile: false,
|
|
920
|
+
authAiProfileName: 'Automation Codex'
|
|
921
|
+
}));
|
|
922
|
+
expect(reactivated.created).toBe(false);
|
|
923
|
+
expect(reactivated.profile.id).toBe(resolved.profile.id);
|
|
924
|
+
expect(reactivated.profile.archivedAt ?? null).toBeNull();
|
|
925
|
+
const created = parseToolJson(await callTool(projectRoot, 'cloud', 'create_task', {
|
|
926
|
+
title: 'Reactivated automation write'
|
|
927
|
+
}, {
|
|
928
|
+
workspaceId: 'workspace-1',
|
|
929
|
+
resolveProfile: false,
|
|
930
|
+
authAiProfileName: 'Automation Codex'
|
|
931
|
+
}));
|
|
932
|
+
expect(created.title).toBe('Reactivated automation write');
|
|
933
|
+
expect(created.createdBy).toBe(resolved.profile.id);
|
|
934
|
+
}
|
|
935
|
+
finally {
|
|
936
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
937
|
+
}
|
|
938
|
+
});
|
|
939
|
+
it('blocks cloud auto-bind when the configured AI profile token belongs to a retired profile', async () => {
|
|
940
|
+
const projectRoot = createProjectRoot();
|
|
941
|
+
try {
|
|
942
|
+
const core = new TaskforceCore({
|
|
943
|
+
projectRoot,
|
|
944
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
945
|
+
});
|
|
946
|
+
const resolved = core.resolveAiProfile({
|
|
947
|
+
workspaceId: 'workspace-1',
|
|
948
|
+
name: 'Automation Codex',
|
|
949
|
+
}, { trustedSeatScope: 'cloud_metered' });
|
|
950
|
+
core.archiveAiProfile({
|
|
951
|
+
workspaceId: 'workspace-1',
|
|
952
|
+
profileId: resolved.profile.id,
|
|
953
|
+
archivedBy: 'owner-1',
|
|
954
|
+
reason: 'manual_archive'
|
|
955
|
+
});
|
|
956
|
+
core.close();
|
|
957
|
+
const blocked = await callTool(projectRoot, 'cloud', 'create_task', {
|
|
958
|
+
title: 'Token should stay retired'
|
|
959
|
+
}, {
|
|
960
|
+
workspaceId: 'workspace-1',
|
|
961
|
+
resolveProfile: false,
|
|
962
|
+
authAiProfileToken: resolved.profile.profileToken,
|
|
963
|
+
authAiProfileName: 'Automation Codex'
|
|
964
|
+
});
|
|
965
|
+
expect(blocked.isError).toBe(true);
|
|
966
|
+
const blockedPayload = parseToolJson(blocked);
|
|
967
|
+
expect(blockedPayload.code).toBe('AI_PROFILE_RETIRED');
|
|
968
|
+
expect(blockedPayload.details).toEqual(expect.objectContaining({
|
|
969
|
+
profileId: resolved.profile.id,
|
|
970
|
+
profileToken: resolved.profile.profileToken,
|
|
971
|
+
archivedReason: 'manual_archive'
|
|
972
|
+
}));
|
|
973
|
+
}
|
|
974
|
+
finally {
|
|
975
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
976
|
+
}
|
|
977
|
+
});
|
|
978
|
+
it('blocks cloud auto-bind when the workspace has no remaining ai profile seats', async () => {
|
|
979
|
+
const projectRoot = createProjectRoot();
|
|
980
|
+
try {
|
|
981
|
+
const core = new TaskforceCore({
|
|
982
|
+
projectRoot,
|
|
983
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
984
|
+
});
|
|
985
|
+
core.upsertPlanCatalog({ planId: 'free', displayName: 'Free', status: 'active' });
|
|
986
|
+
core.ensureBootstrapUserAccess({
|
|
987
|
+
userId: 'owner-u1',
|
|
988
|
+
workspaceId: 'workspace-1',
|
|
989
|
+
role: 'owner',
|
|
990
|
+
email: 'owner@example.com'
|
|
991
|
+
});
|
|
992
|
+
core.updatePlanVersionFeatures({
|
|
993
|
+
planVersionId: 'free-v1',
|
|
994
|
+
features: [
|
|
995
|
+
{ featureKey: 'collaboration.ai_profiles', access: 'limited', config: { maxAiProfiles: 1 } }
|
|
996
|
+
]
|
|
997
|
+
});
|
|
998
|
+
core.updateAccountEntitlement({
|
|
999
|
+
accountId: 'owner-u1',
|
|
1000
|
+
planVersionId: 'free-v1',
|
|
1001
|
+
entitlementState: 'active',
|
|
1002
|
+
actorUserId: 'system-admin',
|
|
1003
|
+
actorRole: 'system_admin'
|
|
1004
|
+
});
|
|
1005
|
+
core.resolveAiProfile({
|
|
1006
|
+
workspaceId: 'workspace-1',
|
|
1007
|
+
name: 'Existing Automation Bot',
|
|
1008
|
+
}, { trustedSeatScope: 'cloud_metered' });
|
|
1009
|
+
core.close();
|
|
1010
|
+
const result = await callTool(projectRoot, 'cloud', 'create_task', {
|
|
1011
|
+
title: 'Blocked automation write'
|
|
1012
|
+
}, {
|
|
1013
|
+
workspaceId: 'workspace-1',
|
|
1014
|
+
resolveProfile: false,
|
|
1015
|
+
authAiProfileName: 'Automation Codex'
|
|
1016
|
+
});
|
|
1017
|
+
expect(result.isError).toBe(true);
|
|
1018
|
+
const payload = parseToolJson(result);
|
|
1019
|
+
expect(payload.code).toBe('AI_PROFILE_LIMIT_REACHED');
|
|
1020
|
+
expect(payload.error).toContain('No AI seats are available for this workspace');
|
|
1021
|
+
expect(payload.details).toEqual({
|
|
1022
|
+
workspaceId: 'workspace-1',
|
|
1023
|
+
limit: 1,
|
|
1024
|
+
used: 1,
|
|
1025
|
+
remaining: 0
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
finally {
|
|
1029
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
819
1032
|
it('rejects invalid profileToken values on mutating MCP tools', async () => {
|
|
820
1033
|
const projectRoot = createProjectRoot();
|
|
821
1034
|
try {
|
|
@@ -876,6 +1089,185 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
876
1089
|
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
877
1090
|
}
|
|
878
1091
|
});
|
|
1092
|
+
it('surfaces ai profile seat limits when an invalid per-call token falls back to a configured AI name', async () => {
|
|
1093
|
+
const projectRoot = createProjectRoot();
|
|
1094
|
+
try {
|
|
1095
|
+
const core = new TaskforceCore({
|
|
1096
|
+
projectRoot,
|
|
1097
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
1098
|
+
});
|
|
1099
|
+
core.upsertPlanCatalog({ planId: 'free', displayName: 'Free', status: 'active' });
|
|
1100
|
+
core.ensureBootstrapUserAccess({
|
|
1101
|
+
userId: 'owner-u1',
|
|
1102
|
+
workspaceId: 'workspace-1',
|
|
1103
|
+
role: 'owner',
|
|
1104
|
+
email: 'owner@example.com'
|
|
1105
|
+
});
|
|
1106
|
+
core.updatePlanVersionFeatures({
|
|
1107
|
+
planVersionId: 'free-v1',
|
|
1108
|
+
features: [
|
|
1109
|
+
{ featureKey: 'collaboration.ai_profiles', access: 'limited', config: { maxAiProfiles: 1 } }
|
|
1110
|
+
]
|
|
1111
|
+
});
|
|
1112
|
+
core.updateAccountEntitlement({
|
|
1113
|
+
accountId: 'owner-u1',
|
|
1114
|
+
planVersionId: 'free-v1',
|
|
1115
|
+
entitlementState: 'active',
|
|
1116
|
+
actorUserId: 'system-admin',
|
|
1117
|
+
actorRole: 'system_admin'
|
|
1118
|
+
});
|
|
1119
|
+
core.resolveAiProfile({
|
|
1120
|
+
workspaceId: 'workspace-1',
|
|
1121
|
+
name: 'Existing Automation Bot',
|
|
1122
|
+
}, { trustedSeatScope: 'cloud_metered' });
|
|
1123
|
+
core.close();
|
|
1124
|
+
const result = await callTool(projectRoot, 'cloud', 'create_task', {
|
|
1125
|
+
title: 'Recovered per-call token write',
|
|
1126
|
+
profileToken: 'tfp_invalid_token',
|
|
1127
|
+
}, {
|
|
1128
|
+
workspaceId: 'workspace-1',
|
|
1129
|
+
resolveProfile: false,
|
|
1130
|
+
authAiProfileName: 'Automation Codex'
|
|
1131
|
+
});
|
|
1132
|
+
expect(result.isError).toBe(true);
|
|
1133
|
+
const payload = parseToolJson(result);
|
|
1134
|
+
expect(payload.code).toBe('AI_PROFILE_LIMIT_REACHED');
|
|
1135
|
+
expect(payload.error).toContain('No AI seats are available for this workspace');
|
|
1136
|
+
expect(payload.details).toEqual({
|
|
1137
|
+
workspaceId: 'workspace-1',
|
|
1138
|
+
limit: 1,
|
|
1139
|
+
used: 1,
|
|
1140
|
+
remaining: 0
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
finally {
|
|
1144
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
it('keeps local MCP profile resolution unmetered even when cloud seats are full', async () => {
|
|
1148
|
+
const projectRoot = createProjectRoot();
|
|
1149
|
+
try {
|
|
1150
|
+
const core = new TaskforceCore({
|
|
1151
|
+
projectRoot,
|
|
1152
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
1153
|
+
});
|
|
1154
|
+
core.upsertPlanCatalog({ planId: 'free', displayName: 'Free', status: 'active' });
|
|
1155
|
+
core.ensureBootstrapUserAccess({
|
|
1156
|
+
userId: 'owner-u1',
|
|
1157
|
+
workspaceId: 'workspace-1',
|
|
1158
|
+
role: 'owner',
|
|
1159
|
+
email: 'owner@example.com'
|
|
1160
|
+
});
|
|
1161
|
+
core.updatePlanVersionFeatures({
|
|
1162
|
+
planVersionId: 'free-v1',
|
|
1163
|
+
features: [
|
|
1164
|
+
{ featureKey: 'collaboration.ai_profiles', access: 'limited', config: { maxAiProfiles: 1 } }
|
|
1165
|
+
]
|
|
1166
|
+
});
|
|
1167
|
+
core.updateAccountEntitlement({
|
|
1168
|
+
accountId: 'owner-u1',
|
|
1169
|
+
planVersionId: 'free-v1',
|
|
1170
|
+
entitlementState: 'active',
|
|
1171
|
+
actorUserId: 'system-admin',
|
|
1172
|
+
actorRole: 'system_admin'
|
|
1173
|
+
});
|
|
1174
|
+
core.resolveAiProfile({
|
|
1175
|
+
workspaceId: 'workspace-1',
|
|
1176
|
+
name: 'Existing Automation Bot',
|
|
1177
|
+
}, { trustedSeatScope: 'cloud_metered' });
|
|
1178
|
+
core.close();
|
|
1179
|
+
const payload = parseToolJson(await callTool(projectRoot, 'local', 'resolve_profile', {
|
|
1180
|
+
name: 'Local Codex'
|
|
1181
|
+
}, {
|
|
1182
|
+
workspaceId: 'workspace-1',
|
|
1183
|
+
resolveProfile: false
|
|
1184
|
+
}));
|
|
1185
|
+
expect(payload.created).toBe(true);
|
|
1186
|
+
expect(payload.profile.name).toBe('Local Codex');
|
|
1187
|
+
expect(payload.profile.seatScope).toBe('local_unmetered');
|
|
1188
|
+
}
|
|
1189
|
+
finally {
|
|
1190
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
it('derives profile seat scope from the MCP runtime instead of auth metadata', async () => {
|
|
1194
|
+
const projectRoot = createProjectRoot();
|
|
1195
|
+
try {
|
|
1196
|
+
const localRuntime = createTaskforceMcpServer({
|
|
1197
|
+
projectRoot,
|
|
1198
|
+
runtimeMode: 'local',
|
|
1199
|
+
workspaceId: 'workspace-1',
|
|
1200
|
+
logStartup: false,
|
|
1201
|
+
auth: {
|
|
1202
|
+
aiProfileSeatScope: 'cloud_metered',
|
|
1203
|
+
aiProfileName: 'Codex',
|
|
1204
|
+
aiProfileRole: 'Implementation',
|
|
1205
|
+
aiProfileProvider: 'OpenAI',
|
|
1206
|
+
aiProfileModel: 'gpt-5',
|
|
1207
|
+
aiProfileSurfaceType: 'coding_tool',
|
|
1208
|
+
}
|
|
1209
|
+
});
|
|
1210
|
+
const localPayload = parseToolJson(await callToolWithRuntime(localRuntime, 'resolve_profile', {
|
|
1211
|
+
name: 'Codex',
|
|
1212
|
+
surfaceType: 'coding_tool',
|
|
1213
|
+
}, {
|
|
1214
|
+
resolveProfile: false
|
|
1215
|
+
}));
|
|
1216
|
+
expect(localPayload.profile.seatScope).toBe('local_unmetered');
|
|
1217
|
+
const cloudRuntime = createTaskforceMcpServer({
|
|
1218
|
+
projectRoot,
|
|
1219
|
+
runtimeMode: 'cloud',
|
|
1220
|
+
workspaceId: 'workspace-1',
|
|
1221
|
+
logStartup: false,
|
|
1222
|
+
auth: {
|
|
1223
|
+
scopes: ['tasks:read', 'tasks:write', 'workspace:read'],
|
|
1224
|
+
userId: 'owner-1',
|
|
1225
|
+
actorType: 'oauth',
|
|
1226
|
+
aiProfileSeatScope: 'local_unmetered',
|
|
1227
|
+
aiProfileName: 'Cloud Codex',
|
|
1228
|
+
aiProfileSurfaceType: 'coding_tool',
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
const cloudPayload = parseToolJson(await callToolWithRuntime(cloudRuntime, 'resolve_profile', {
|
|
1232
|
+
name: 'Cloud Codex',
|
|
1233
|
+
surfaceType: 'coding_tool',
|
|
1234
|
+
}, {
|
|
1235
|
+
resolveProfile: false
|
|
1236
|
+
}));
|
|
1237
|
+
expect(cloudPayload.profile.seatScope).toBe('cloud_metered');
|
|
1238
|
+
}
|
|
1239
|
+
finally {
|
|
1240
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
it('creates a separate local MCP profile when a cloud profile with the same name already exists', async () => {
|
|
1244
|
+
const projectRoot = createProjectRoot();
|
|
1245
|
+
try {
|
|
1246
|
+
const core = new TaskforceCore({
|
|
1247
|
+
projectRoot,
|
|
1248
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
1249
|
+
});
|
|
1250
|
+
const cloud = core.resolveAiProfile({
|
|
1251
|
+
workspaceId: 'workspace-1',
|
|
1252
|
+
name: 'Codex',
|
|
1253
|
+
surfaceType: 'coding_tool'
|
|
1254
|
+
}, { trustedSeatScope: 'cloud_metered' });
|
|
1255
|
+
core.close();
|
|
1256
|
+
const payload = parseToolJson(await callTool(projectRoot, 'local', 'resolve_profile', {
|
|
1257
|
+
name: 'Codex',
|
|
1258
|
+
surfaceType: 'coding_tool'
|
|
1259
|
+
}, {
|
|
1260
|
+
workspaceId: 'workspace-1',
|
|
1261
|
+
resolveProfile: false
|
|
1262
|
+
}));
|
|
1263
|
+
expect(payload.created).toBe(true);
|
|
1264
|
+
expect(payload.profile.id).not.toBe(cloud.profile.id);
|
|
1265
|
+
expect(payload.profile.seatScope).toBe('local_unmetered');
|
|
1266
|
+
}
|
|
1267
|
+
finally {
|
|
1268
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
879
1271
|
it('claims unassigned tasks and marks them in progress through start_task', async () => {
|
|
880
1272
|
const projectRoot = createProjectRoot();
|
|
881
1273
|
try {
|
|
@@ -2486,6 +2878,52 @@ describe('Taskforce MCP tool descriptions', () => {
|
|
|
2486
2878
|
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
2487
2879
|
}
|
|
2488
2880
|
});
|
|
2881
|
+
it('accepts documented schedule helper arguments', async () => {
|
|
2882
|
+
const projectRoot = createProjectRoot();
|
|
2883
|
+
try {
|
|
2884
|
+
const core = new TaskforceCore({
|
|
2885
|
+
projectRoot,
|
|
2886
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
2887
|
+
});
|
|
2888
|
+
const first = core.createTask({ title: 'First documented schedule helper test' }, { workspaceId: 'workspace-1' });
|
|
2889
|
+
const second = core.createTask({ title: 'Second documented schedule helper test' }, { workspaceId: 'workspace-1' });
|
|
2890
|
+
core.close();
|
|
2891
|
+
const board = parseToolJson(await callTool(projectRoot, 'local', 'get_schedule_board', {}));
|
|
2892
|
+
expect(board.week).toMatch(/^\d{4}-W\d{2}$/);
|
|
2893
|
+
const scheduled = parseToolJson(await callTool(projectRoot, 'local', 'schedule_task', {
|
|
2894
|
+
taskId: first.referenceLabel,
|
|
2895
|
+
date: '2099-01-05',
|
|
2896
|
+
order: 3
|
|
2897
|
+
}));
|
|
2898
|
+
expect(scheduled.scheduling.persistedDate).toBe('2099-01-05');
|
|
2899
|
+
expect(scheduled.scheduling.persistedOrderInDay).toBe(3);
|
|
2900
|
+
await callTool(projectRoot, 'local', 'reorder_scheduled_tasks', {
|
|
2901
|
+
date: '2099-01-05',
|
|
2902
|
+
taskIds: [second.referenceLabel, first.referenceLabel]
|
|
2903
|
+
});
|
|
2904
|
+
await callTool(projectRoot, 'local', 'unschedule_task', {
|
|
2905
|
+
taskId: first.referenceLabel
|
|
2906
|
+
});
|
|
2907
|
+
const after = new TaskforceCore({
|
|
2908
|
+
projectRoot,
|
|
2909
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
2910
|
+
});
|
|
2911
|
+
try {
|
|
2912
|
+
const firstTask = after.getTask(first.id, 'workspace-1');
|
|
2913
|
+
const secondTask = after.getTask(second.id, 'workspace-1');
|
|
2914
|
+
expect(firstTask?.scheduledDate).toBeNull();
|
|
2915
|
+
expect(firstTask?.orderInDay).toBeNull();
|
|
2916
|
+
expect(secondTask?.scheduledDate).toBe('2099-01-05');
|
|
2917
|
+
expect(secondTask?.orderInDay).toBe(0);
|
|
2918
|
+
}
|
|
2919
|
+
finally {
|
|
2920
|
+
after.close();
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
finally {
|
|
2924
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
2925
|
+
}
|
|
2926
|
+
});
|
|
2489
2927
|
it('maps legacy agent assignee writes to unassigned even when a profile is resolved', async () => {
|
|
2490
2928
|
const projectRoot = createProjectRoot();
|
|
2491
2929
|
try {
|