@taskforcehq/taskforce 0.3.170 → 0.3.301
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 +71 -21
- package/dist/Taskforce.module.css +3394 -5981
- package/dist/TaskforceCore.CategoryFallback.test.js +5 -2
- package/dist/TaskforceCore.filter-persistence.test.js +402 -0
- package/dist/TaskforceCore.js +388 -71
- package/dist/TaskforceCore.routing.test.js +311 -0
- package/dist/TaskforceCore.test.js +3344 -615
- package/dist/TaskforceWidget.js +3 -2
- package/dist/__tests__/localizationCatalogs.test.js +48 -31
- package/dist/__tests__/workflowSimulation.test.js +2 -2
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.d.ts +60 -0
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.js +324 -0
- package/dist/annotatedAttachments/AnnotatedAttachmentSessionStore.test.js +278 -0
- package/dist/annotatedAttachments/payload.d.ts +2 -0
- package/dist/annotatedAttachments/payload.js +54 -0
- package/dist/annotatedAttachments/payload.test.js +67 -0
- package/dist/annotatedAttachments/service.d.ts +49 -0
- package/dist/annotatedAttachments/service.js +121 -0
- package/dist/annotatedAttachments/types.d.ts +86 -0
- package/dist/cli.js +74 -25
- package/dist/compat/deploymentCompat.d.ts +12 -0
- package/dist/compat/deploymentCompat.js +43 -0
- package/dist/compat/workspaceSyncCompat.d.ts +6 -0
- package/dist/compat/workspaceSyncCompat.js +79 -0
- package/dist/compat/workspaceSyncCompat.test.js +87 -0
- package/dist/components/features/AgentsModule.d.ts +5 -0
- package/dist/components/features/AgentsModule.js +131 -0
- package/dist/components/features/AgentsModule.test.js +102 -0
- package/dist/components/features/AnnotatedAttachmentWorkspace.d.ts +24 -0
- package/dist/components/features/AnnotatedAttachmentWorkspace.js +1942 -0
- package/dist/components/features/AnnotatedAttachmentWorkspace.test.js +2831 -0
- package/dist/components/features/DocumentGenerateModal.js +8 -16
- package/dist/components/features/DocumentIndex.d.ts +3 -4
- package/dist/components/features/DocumentIndex.js +22 -10
- package/dist/components/features/DocumentViewer.d.ts +6 -2
- package/dist/components/features/DocumentViewer.js +1000 -18
- package/dist/components/features/DocumentWorkspace.d.ts +40 -2
- package/dist/components/features/DocumentWorkspace.js +96 -16
- package/dist/components/features/DocumentWorkspace.test.js +1202 -0
- package/dist/components/features/InitiativesModule.d.ts +22 -0
- package/dist/components/features/InitiativesModule.js +33 -0
- package/dist/components/features/TaskSettings.d.ts +41 -32
- package/dist/components/features/TaskSettings.js +798 -313
- package/dist/components/features/TaskSettings.test.js +1221 -47
- package/dist/components/features/WorkflowsModule.d.ts +27 -0
- package/dist/components/features/WorkflowsModule.js +21 -0
- package/dist/components/features/documentWorkspaceFilters.d.ts +10 -0
- package/dist/components/features/documentWorkspaceFilters.js +11 -0
- package/dist/components/features/settings/CategoryManager.d.ts +2 -0
- package/dist/components/features/settings/CategoryManager.js +15 -8
- package/dist/components/features/settings/PriorityManager.d.ts +18 -0
- package/dist/components/features/settings/PriorityManager.js +51 -0
- package/dist/components/features/settings/TaxonomyEditor.d.ts +2 -1
- package/dist/components/features/settings/TaxonomyEditor.js +41 -18
- package/dist/components/features/settings/TaxonomyLibraryManager.d.ts +26 -0
- package/dist/components/features/settings/TaxonomyLibraryManager.js +301 -0
- package/dist/components/features/settings/TaxonomyLibraryManager.test.js +141 -0
- package/dist/components/features/settings/TaxonomyManager.d.ts +35 -12
- package/dist/components/features/settings/TaxonomyManager.js +59 -27
- package/dist/components/features/settings/TypeManager.d.ts +11 -0
- package/dist/components/features/settings/TypeManager.js +48 -11
- package/dist/components/features/settings/{WorkflowEditorPrototype.d.ts → WorkflowEditor.d.ts} +2 -2
- package/dist/components/features/settings/{WorkflowEditorPrototype.js → WorkflowEditor.js} +3 -3
- package/dist/components/task/TaskActionHeader.d.ts +12 -2
- package/dist/components/task/TaskActionHeader.js +64 -8
- package/dist/components/task/TaskActionHeader.test.js +73 -0
- package/dist/components/task/TaskCard.d.ts +14 -16
- package/dist/components/task/TaskCard.js +144 -174
- package/dist/components/task/TaskCard.test.js +416 -64
- package/dist/components/task/TaskContextUpload.d.ts +6 -5
- package/dist/components/task/TaskContextUpload.js +199 -64
- package/dist/components/task/TaskContextUpload.test.js +331 -14
- package/dist/components/task/TaskForm.d.ts +23 -29
- package/dist/components/task/TaskForm.js +348 -169
- package/dist/components/task/TaskForm.test.js +419 -23
- package/dist/components/task/TaskKanban.d.ts +20 -21
- package/dist/components/task/TaskKanban.js +176 -316
- package/dist/components/task/TaskKanban.planning-drop.test.js +93 -0
- package/dist/components/task/TaskList.d.ts +22 -11
- package/dist/components/task/TaskList.js +98 -12
- package/dist/components/task/TaskList.test.js +206 -7
- package/dist/components/task/TaskReferenceBadge.d.ts +12 -0
- package/dist/components/task/TaskReferenceBadge.js +5 -0
- package/dist/components/task/TaskStatusActions.d.ts +12 -0
- package/dist/components/task/TaskStatusActions.js +18 -0
- package/dist/components/task/TaskStatusActions.test.js +45 -0
- package/dist/components/ui/ImageReferenceBadge.d.ts +12 -0
- package/dist/components/ui/ImageReferenceBadge.js +5 -0
- package/dist/components/ui/LevelSelector.d.ts +2 -1
- package/dist/components/ui/LevelSelector.js +2 -2
- package/dist/components/ui/Markdown.d.ts +1 -2
- package/dist/components/ui/Markdown.js +2 -13
- package/dist/components/ui/Modal.d.ts +3 -2
- package/dist/components/ui/Modal.js +4 -3
- package/dist/components/ui/MultiSelectFilter.d.ts +3 -1
- package/dist/components/ui/MultiSelectFilter.js +2 -2
- package/dist/components/ui/ReferenceBadgeButton.d.ts +13 -0
- package/dist/components/ui/ReferenceBadgeButton.js +6 -0
- package/dist/components/ui/TaxonomyDropdown.d.ts +7 -1
- package/dist/components/ui/TaxonomyDropdown.js +58 -23
- package/dist/components/ui/TopNoticeLayer.d.ts +7 -0
- package/dist/components/ui/TopNoticeLayer.js +14 -0
- package/dist/components/ui/TopNoticeLayer.test.js +25 -0
- package/dist/components/views/AppShellHeader.d.ts +13 -0
- package/dist/components/views/AppShellHeader.js +19 -0
- package/dist/components/views/AppShellHeader.test.js +21 -0
- package/dist/components/views/PlanComparisonPage.d.ts +73 -0
- package/dist/components/views/PlanComparisonPage.js +196 -0
- package/dist/components/views/PlanComparisonPage.test.js +251 -0
- package/dist/components/views/PlansPage.d.ts +14 -0
- package/dist/components/views/PlansPage.js +355 -0
- package/dist/components/views/StandaloneLayout.d.ts +2 -2
- package/dist/components/views/StandaloneLayout.js +2227 -1188
- package/dist/components/views/WidgetView.d.ts +2 -2
- package/dist/components/views/WidgetView.js +149 -43
- package/dist/components/views/chrome/WorkspaceChromeSections.d.ts +57 -0
- package/dist/components/views/chrome/WorkspaceChromeSections.js +38 -0
- package/dist/components/views/chrome/WorkspaceChromeSections.test.js +54 -0
- package/dist/components/views/chrome/workspaceChrome.d.ts +31 -0
- package/dist/components/views/chrome/workspaceChrome.js +108 -0
- package/dist/components/views/chrome/workspaceChrome.test.js +52 -0
- package/dist/components/views/panels/DocumentFilterToolbar.d.ts +10 -0
- package/dist/components/views/panels/DocumentFilterToolbar.js +7 -0
- package/dist/components/views/panels/DocumentFilterToolbar.test.js +19 -0
- package/dist/components/views/panels/FilterToolbar.d.ts +68 -0
- package/dist/components/views/panels/FilterToolbar.js +21 -0
- package/dist/components/views/panels/FilterToolbar.test.d.ts +1 -0
- package/dist/components/views/panels/FilterToolbar.test.js +45 -0
- package/dist/components/views/panels/FilterToolbarControls.d.ts +47 -0
- package/dist/components/views/panels/FilterToolbarControls.js +61 -0
- package/dist/components/views/panels/PlanningDrawer.d.ts +115 -0
- package/dist/components/views/panels/PlanningDrawer.js +220 -0
- package/dist/components/views/panels/ScheduleSidebar.d.ts +52 -0
- package/dist/components/views/panels/ScheduleSidebar.js +127 -0
- package/dist/components/views/panels/scheduleUtils.d.ts +14 -0
- package/dist/components/views/panels/scheduleUtils.js +79 -0
- package/dist/components/views/teamManagementAccess.d.ts +6 -0
- package/dist/components/views/teamManagementAccess.js +18 -0
- package/dist/components/views/teamManagementAccess.test.d.ts +1 -0
- package/dist/components/views/teamManagementAccess.test.js +44 -0
- package/dist/config/clientDeployment.d.ts +2 -0
- package/dist/config/clientDeployment.js +13 -0
- package/dist/config/cloudEnvironment.d.ts +15 -0
- package/dist/config/cloudEnvironment.js +60 -0
- package/dist/config/deployment.d.ts +20 -0
- package/dist/config/deployment.js +67 -0
- package/dist/config/deployment.test.d.ts +1 -0
- package/dist/config/deployment.test.js +88 -0
- package/dist/config/envSchema.js +36 -8
- package/dist/config/envSchema.test.js +28 -0
- package/dist/core/AiProfileService.d.ts +66 -0
- package/dist/core/AiProfileService.js +320 -0
- package/dist/core/AiProfileService.test.d.ts +1 -0
- package/dist/core/AiProfileService.test.js +164 -0
- package/dist/core/AiProfiles.test.d.ts +1 -0
- package/dist/core/AiProfiles.test.js +449 -0
- package/dist/core/AttachmentLinkService.d.ts +15 -0
- package/dist/core/AttachmentLinkService.js +157 -0
- package/dist/core/AuthTokenService.d.ts +44 -0
- package/dist/core/AuthTokenService.js +207 -0
- package/dist/core/CreatedBy.test.js +134 -6
- package/dist/core/DeletedTaskLifecycleService.d.ts +33 -0
- package/dist/core/DeletedTaskLifecycleService.js +158 -0
- package/dist/core/DeletedTaskTrash.test.d.ts +1 -0
- package/dist/core/DeletedTaskTrash.test.js +104 -0
- package/dist/core/EntitlementsPolicy.test.js +78 -5
- package/dist/core/GlobalSettingsService.d.ts +16 -0
- package/dist/core/GlobalSettingsService.js +370 -0
- package/dist/core/JsonBackupRuntime.test.d.ts +1 -0
- package/dist/core/JsonBackupRuntime.test.js +155 -0
- package/dist/core/McpTokenService.d.ts +118 -0
- package/dist/core/McpTokenService.js +921 -0
- package/dist/core/PlanEntitlementService.d.ts +201 -0
- package/dist/core/PlanEntitlementService.js +1442 -0
- package/dist/core/PlanVersionPolicy.test.d.ts +1 -0
- package/dist/core/PlanVersionPolicy.test.js +178 -0
- package/dist/core/PlanningEntities.test.d.ts +1 -0
- package/dist/core/PlanningEntities.test.js +95 -0
- package/dist/core/ScheduleFields.test.js +15 -19
- package/dist/core/SignupMonetizationSettings.test.d.ts +1 -0
- package/dist/core/SignupMonetizationSettings.test.js +159 -0
- package/dist/core/Stats.test.d.ts +1 -0
- package/dist/core/Stats.test.js +36 -0
- package/dist/core/SyncReconciliationService.d.ts +93 -0
- package/dist/core/SyncReconciliationService.js +406 -0
- package/dist/core/SystemAdmin.test.js +578 -13
- package/dist/core/TaskActivityService.d.ts +21 -0
- package/dist/core/TaskActivityService.js +130 -0
- package/dist/core/TaskAttachmentsCanonical.test.d.ts +1 -0
- package/dist/core/TaskAttachmentsCanonical.test.js +306 -0
- package/dist/core/TaskAuditTimeline.test.d.ts +1 -0
- package/dist/core/TaskAuditTimeline.test.js +132 -0
- package/dist/core/TaskTaxonomyValidation.test.js +338 -15
- package/dist/core/Taskforce.d.ts +930 -183
- package/dist/core/Taskforce.ids.test.js +252 -0
- package/dist/core/Taskforce.js +3848 -2532
- package/dist/core/Taskforce.mcpAuth.test.d.ts +1 -0
- package/dist/core/Taskforce.mcpAuth.test.js +343 -0
- package/dist/core/Taskforce.realtimeMutation.test.js +57 -2
- package/dist/core/TaxonomySettingsService.d.ts +18 -0
- package/dist/core/TaxonomySettingsService.js +162 -0
- package/dist/core/WorkspaceDelete.test.js +32 -13
- package/dist/core/WorkspaceLifecycleService.d.ts +11 -0
- package/dist/core/WorkspaceLifecycleService.js +88 -0
- package/dist/core/WorkspacePermissions.test.js +95 -0
- package/dist/core/WorkspacePlanMode.test.js +114 -1
- package/dist/core/WorkspacePreferenceService.d.ts +41 -0
- package/dist/core/WorkspacePreferenceService.js +246 -0
- package/dist/core/WorkspaceSyncSettings.test.d.ts +1 -0
- package/dist/core/WorkspaceSyncSettings.test.js +65 -0
- package/dist/core/__tests__/TaskAttachmentsCanonical.test.d.ts +1 -0
- package/dist/core/__tests__/TaskAttachmentsCanonical.test.js +212 -0
- package/dist/core/shared.d.ts +36 -0
- package/dist/core/shared.js +128 -0
- package/dist/core/types.d.ts +614 -0
- package/dist/core/types.js +27 -0
- package/dist/documentReviews/DocumentReviewCommentStore.d.ts +56 -0
- package/dist/documentReviews/DocumentReviewCommentStore.js +230 -0
- package/dist/documentReviews/DocumentReviewSessionStore.d.ts +52 -0
- package/dist/documentReviews/DocumentReviewSessionStore.js +193 -0
- package/dist/documentReviews/DocumentReviewSessionStore.test.d.ts +1 -0
- package/dist/documentReviews/DocumentReviewSessionStore.test.js +127 -0
- package/dist/documentReviews/service.d.ts +68 -0
- package/dist/documentReviews/service.js +210 -0
- package/dist/documentReviews/types.d.ts +58 -0
- package/dist/documentReviews/types.js +1 -0
- package/dist/hooks/auth/useAuthGuardPolicy.d.ts +2 -0
- package/dist/hooks/auth/useAuthGuardPolicy.js +1 -0
- package/dist/hooks/tasks/useCurrentTaskRelations.d.ts +15 -0
- package/dist/hooks/tasks/useCurrentTaskRelations.js +37 -0
- package/dist/hooks/tasks/useTaskActions.d.ts +3 -0
- package/dist/hooks/tasks/useTaskActions.js +2 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.d.ts +65 -0
- package/dist/hooks/tasks/useTaskEditorNavigation.js +235 -0
- package/dist/hooks/tasks/useTaskFilters.d.ts +2 -0
- package/dist/hooks/tasks/useTaskFilters.js +2 -0
- package/dist/hooks/tasks/useTaskFormActions.d.ts +58 -0
- package/dist/hooks/tasks/useTaskFormActions.js +365 -0
- package/dist/hooks/tasks/useTaskRelationships.d.ts +16 -0
- package/dist/hooks/tasks/useTaskRelationships.js +64 -0
- package/dist/hooks/ui/useResourceExport.d.ts +19 -0
- package/dist/hooks/ui/useResourceExport.js +84 -0
- package/dist/hooks/ui/useSettingsModel.d.ts +203 -0
- package/dist/hooks/ui/useSettingsModel.js +125 -0
- package/dist/hooks/ui/useSettingsPersistence.d.ts +36 -0
- package/dist/hooks/ui/useSettingsPersistence.js +254 -0
- package/dist/hooks/ui/useSettingsTaxonomyManagement.d.ts +119 -0
- package/dist/hooks/ui/useSettingsTaxonomyManagement.js +536 -0
- package/dist/hooks/ui/useUiNotice.d.ts +1 -0
- package/dist/hooks/ui/useUiNotice.js +1 -0
- package/dist/hooks/ui/useWorkflowTemplates.d.ts +37 -0
- package/dist/hooks/ui/useWorkflowTemplates.js +111 -0
- package/dist/hooks/ui/useZenMode.d.ts +5 -0
- package/dist/hooks/ui/useZenMode.js +32 -0
- package/dist/hooks/useFilterSort.d.ts +60 -0
- package/dist/hooks/useFilterSort.js +362 -0
- package/dist/hooks/useFilterSort.test.d.ts +1 -0
- package/dist/hooks/useFilterSort.test.js +333 -0
- package/dist/hooks/useRealtimeSync.d.ts +1 -0
- package/dist/hooks/useRealtimeSync.js +24 -9
- package/dist/hooks/useRealtimeSync.test.js +28 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.d.ts +1 -0
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +34 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +65 -103
- package/dist/hooks/useSyncOrchestrator.js +1538 -670
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +700 -174
- package/dist/hooks/useTaskData.d.ts +35 -0
- package/dist/hooks/useTaskData.js +243 -0
- package/dist/hooks/useTaskData.test.d.ts +1 -0
- package/dist/hooks/useTaskData.test.js +180 -0
- package/dist/hooks/useTaskMutations.d.ts +46 -0
- package/dist/hooks/useTaskMutations.js +472 -0
- package/dist/hooks/useTaskMutations.test.d.ts +1 -0
- package/dist/hooks/useTaskMutations.test.js +80 -0
- package/dist/hooks/useTaskforce.contract.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.contract.test.js +7 -0
- package/dist/hooks/useTaskforce.d.ts +260 -295
- package/dist/hooks/useTaskforce.js +1954 -2623
- package/dist/hooks/useTaskforce.priority-filters.test.js +6 -11
- package/dist/hooks/useTaskforce.sync-behavior.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.sync-behavior.test.js +1120 -0
- package/dist/hooks/useUiNotice.d.ts +16 -0
- package/dist/hooks/useUiNotice.js +49 -0
- package/dist/hooks/useWorkspaceSyncController.d.ts +23 -46
- package/dist/hooks/useWorkspaceSyncController.js +280 -461
- package/dist/hooks/useWorkspaceSyncController.test.js +106 -199
- package/dist/hooks/workspace/useTaskforceApiRouting.d.ts +8 -0
- package/dist/hooks/workspace/useTaskforceApiRouting.js +91 -0
- package/dist/hooks/workspace/useTaskforceApiRouting.test.d.ts +1 -0
- package/dist/hooks/workspace/useTaskforceApiRouting.test.js +60 -0
- package/dist/hooks/workspace/useWorkspaceSyncController.d.ts +1 -0
- package/dist/hooks/workspace/useWorkspaceSyncController.js +1 -0
- package/dist/hooks/workspace/workspaceLocalState.d.ts +30 -0
- package/dist/hooks/workspace/workspaceLocalState.js +101 -0
- package/dist/localization/locales/en-US.d.ts +1 -8
- package/dist/localization/locales/en-US.js +4 -11
- package/dist/localization/locales/es-419.js +2 -9
- package/dist/localization/locales/pt-BR.js +2 -9
- package/dist/localization/localizationCatalogs.test.d.ts +1 -0
- package/dist/localization/localizationCatalogs.test.js +37 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +9 -15
- package/dist/mcp/clientIntegrations.d.ts +33 -0
- package/dist/mcp/clientIntegrations.js +199 -0
- package/dist/mcp/clientIntegrations.test.d.ts +1 -0
- package/dist/mcp/clientIntegrations.test.js +110 -0
- package/dist/mcp/index.d.ts +2 -0
- package/dist/mcp/index.js +2 -0
- package/dist/mcp/optionResolution.test.js +6 -2
- package/dist/mcp/runtime.d.ts +120 -0
- package/dist/mcp/runtime.js +5668 -0
- package/dist/mcp/runtime.test.d.ts +1 -0
- package/dist/mcp/runtime.test.js +3299 -0
- package/dist/mcp/server.js +2 -1793
- package/dist/mcp/structuredCommentValidation.test.d.ts +1 -0
- package/dist/{__tests__ → mcp}/structuredCommentValidation.test.js +1 -1
- package/dist/mcp/structuredDocValidation.js +1 -2
- package/dist/mcp/structuredDocValidation.test.d.ts +1 -0
- package/dist/{__tests__ → mcp}/structuredDocValidation.test.js +9 -4
- package/dist/mcp/toolRegistry.d.ts +570 -0
- package/dist/mcp/toolRegistry.js +90 -0
- package/dist/mcp/toolRegistry.test.d.ts +1 -0
- package/dist/mcp/toolRegistry.test.js +30 -0
- package/dist/migrations/billingSchemaParity.test.js +111 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
- package/dist/migrations/taskSchemaMigrations.js +681 -39
- package/dist/migrations/taskSchemaMigrations.test.d.ts +1 -0
- package/dist/migrations/taskSchemaMigrations.test.js +210 -0
- package/dist/plugins/vite.js +13 -7
- package/dist/public/apple-touch-icon.png +0 -0
- package/dist/public/archive/phoenix/apple-touch-icon.png +0 -0
- package/dist/public/archive/phoenix/favicon.ico +0 -0
- package/dist/public/archive/phoenix/site.webmanifest +1 -0
- package/dist/public/favicon-96x96.png +0 -0
- package/dist/public/favicon.ico +0 -0
- package/dist/public/favicon.svg +17 -0
- package/dist/public/site.webmanifest +21 -1
- package/dist/public/web-app-manifest-192x192.png +0 -0
- package/dist/public/web-app-manifest-512x512.png +0 -0
- package/dist/releaseVersion.test.d.ts +1 -0
- package/dist/{__tests__/releaseVersion.test.js → releaseVersion.test.js} +1 -1
- package/dist/resources/templates/WORKFLOW_V2_POLICY.md +1 -1
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +62 -52
- package/dist/resources/templates/workflows/collaborate.yaml +11 -5
- package/dist/resources/templates/workflows/do.yaml +8 -2
- package/dist/resources/templates/workflows/evaluate.yaml +13 -7
- package/dist/resources/templates/workflows/execute.yaml +40 -23
- package/dist/resources/templates/workflows/plan.yaml +15 -8
- package/dist/resources/templates/workflows/review.yaml +14 -8
- package/dist/runtime/appGateDefinitions.d.ts +32 -0
- package/dist/runtime/appGateDefinitions.js +32 -0
- package/dist/runtime/appGates.d.ts +29 -0
- package/dist/runtime/appGates.js +53 -0
- package/dist/runtime/appGates.test.d.ts +1 -0
- package/dist/runtime/appGates.test.js +42 -0
- package/dist/runtime/migrationFlags.d.ts +1 -0
- package/dist/runtime/migrationFlags.js +1 -0
- package/dist/server/annotatedAttachmentsRoutes.test.d.ts +1 -0
- package/dist/server/annotatedAttachmentsRoutes.test.js +473 -0
- package/dist/server/auth.js +14 -2
- package/dist/server/auth.test.js +21 -1
- package/dist/server/cors.js +11 -5
- package/dist/server/cors.test.js +6 -0
- package/dist/server/documentReviewRoutes.test.d.ts +1 -0
- package/dist/server/documentReviewRoutes.test.js +157 -0
- package/dist/server/index.cookieProxy.test.js +46 -1
- package/dist/server/index.d.ts +20 -0
- package/dist/server/index.js +168 -41
- package/dist/server/index.rateLimit.test.js +6 -0
- package/dist/server/index.test.js +133 -2
- package/dist/server/mockStripe.d.ts +72 -0
- package/dist/server/mockStripe.js +357 -0
- package/dist/server/realtimeSyncWs.js +4 -0
- package/dist/server/routes/admin.d.ts +114 -0
- package/dist/server/routes/admin.js +2226 -0
- package/dist/server/routes/annotatedAttachments.d.ts +24 -0
- package/dist/server/routes/annotatedAttachments.js +235 -0
- package/dist/server/routes/auth.d.ts +61 -0
- package/dist/server/routes/auth.js +1296 -0
- package/dist/server/{routes.billing.d.ts → routes/billing.d.ts} +3 -2
- package/dist/server/routes/billing.js +2001 -0
- package/dist/server/routes/billing.test.d.ts +1 -0
- package/dist/server/routes/billing.test.js +1631 -0
- package/dist/server/routes/documentReviews.d.ts +11 -0
- package/dist/server/routes/documentReviews.js +191 -0
- package/dist/server/routes/documents.d.ts +118 -0
- package/dist/server/routes/documents.js +1113 -0
- package/dist/server/routes/resources.d.ts +25 -0
- package/dist/server/routes/resources.js +225 -0
- package/dist/server/routes/shared.d.ts +35 -0
- package/dist/server/routes/shared.js +305 -0
- package/dist/server/routes/shared.test.d.ts +1 -0
- package/dist/server/routes/shared.test.js +32 -0
- package/dist/server/{routes.sync.d.ts → routes/sync.d.ts} +5 -5
- package/dist/server/routes/sync.integration.test.d.ts +1 -0
- package/dist/server/routes/sync.integration.test.js +2003 -0
- package/dist/server/routes/sync.js +3143 -0
- package/dist/server/routes/tasks.d.ts +72 -0
- package/dist/server/routes/tasks.js +1252 -0
- package/dist/server/routes/workspaces.d.ts +32 -0
- package/dist/server/routes/workspaces.js +307 -0
- package/dist/server/routes.d.ts +8 -9
- package/dist/server/routes.js +968 -4092
- package/dist/server/routes.test.js +9043 -2415
- package/dist/server/runtimeMode.d.ts +1 -1
- package/dist/server/runtimeMode.js +3 -18
- package/dist/server/runtimeMode.test.js +3 -3
- package/dist/server/securityHeaders.d.ts +1 -1
- package/dist/server/securityHeaders.js +65 -6
- package/dist/server/securityHeaders.test.js +40 -2
- package/dist/services/templateEngine.test.d.ts +1 -0
- package/dist/{__tests__ → services}/templateEngine.test.js +1 -1
- package/dist/services/templates.test.d.ts +1 -0
- package/dist/{__tests__ → services}/templates.test.js +1 -1
- package/dist/services/workflowDocumentFixtures.test.d.ts +1 -0
- package/dist/{__tests__ → services}/workflowDocumentFixtures.test.js +4 -4
- package/dist/services/workflowExportMatrix.test.d.ts +1 -0
- package/dist/{__tests__ → services}/workflowExportMatrix.test.js +1 -1
- package/dist/services/workflowExportSnapshots.test.d.ts +1 -0
- package/dist/services/workflowGeneration.test.d.ts +1 -0
- package/dist/services/workflowSimulation.test.d.ts +1 -0
- package/dist/services/workflowSimulation.test.js +113 -0
- package/dist/services/workflowV2Policy.test.d.ts +1 -0
- package/dist/{__tests__ → services}/workflowV2Policy.test.js +2 -2
- package/dist/shared/aiProfileSurfaceType.d.ts +9 -0
- package/dist/shared/aiProfileSurfaceType.js +49 -0
- package/dist/shared/customTaxonomyLibrary.d.ts +11 -0
- package/dist/shared/customTaxonomyLibrary.js +276 -0
- package/dist/shared/customTaxonomyLibrary.test.d.ts +1 -0
- package/dist/shared/customTaxonomyLibrary.test.js +20 -0
- package/dist/shared/taxonomyCatalog.d.ts +19 -0
- package/dist/shared/taxonomyCatalog.js +36 -0
- package/dist/shared/taxonomyDefaults.d.ts +29 -0
- package/dist/shared/taxonomyDefaults.js +26 -0
- package/dist/shared/taxonomyLibrary.d.ts +15 -0
- package/dist/shared/taxonomyLibrary.js +98 -0
- package/dist/shared/taxonomyLibrary.test.d.ts +1 -0
- package/dist/shared/taxonomyLibrary.test.js +26 -0
- package/dist/shared/taxonomyState.d.ts +36 -0
- package/dist/shared/taxonomyState.js +73 -0
- package/dist/shared/taxonomyState.test.d.ts +1 -0
- package/dist/shared/taxonomyState.test.js +71 -0
- package/dist/shared/workflowDefaults.d.ts +9 -0
- package/dist/shared/workflowDefaults.js +11 -0
- package/dist/storage/documentIntegrity.d.ts +2 -0
- package/dist/storage/documentIntegrity.js +34 -17
- package/dist/storage/documentPurge.d.ts +2 -1
- package/dist/storage/documentPurge.js +35 -8
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.js +2 -0
- package/dist/storage/objectStorage.d.ts +1 -1
- package/dist/storage/objectStorageClient.d.ts +6 -4
- package/dist/storage/objectStorageClient.js +77 -29
- package/dist/storage/objectStorageClient.test.d.ts +1 -0
- package/dist/storage/objectStorageClient.test.js +57 -0
- package/dist/storage/objectStorageConfig.js +3 -1
- package/dist/storage/objectStorageConfig.test.d.ts +1 -0
- package/dist/storage/objectStorageConfig.test.js +38 -0
- package/dist/storage/postgresAdapter.d.ts +5 -0
- package/dist/storage/postgresAdapter.js +2 -2
- package/dist/storage/postgresAdapter.test.d.ts +1 -0
- package/dist/storage/postgresAdapter.test.js +29 -0
- package/dist/storage/taskAssetStore.d.ts +7 -4
- package/dist/storage/taskAssetStore.js +65 -60
- package/dist/storage/workspaceAssetStore.d.ts +122 -0
- package/dist/storage/workspaceAssetStore.js +496 -0
- package/dist/storage/workspaceAssetStore.test.d.ts +1 -0
- package/dist/storage/workspaceAssetStore.test.js +501 -0
- package/dist/sync/cloudSyncApi.d.ts +33 -2
- package/dist/sync/cloudSyncApi.js +37 -15
- package/dist/sync/cloudSyncApi.test.js +60 -3
- package/dist/sync/index.d.ts +2 -0
- package/dist/sync/index.js +3 -0
- package/dist/sync/syncService.d.ts +25 -0
- package/dist/sync/syncService.js +184 -16
- package/dist/sync/syncService.test.js +289 -25
- package/dist/sync/workspaceRepair.d.ts +114 -0
- package/dist/sync/workspaceRepair.js +566 -0
- package/dist/sync/workspaceSyncModel.d.ts +230 -2
- package/dist/sync/workspaceSyncModel.js +456 -17
- package/dist/sync/workspaceSyncModel.test.js +642 -0
- package/dist/sync/workspaceSyncState.d.ts +12 -0
- package/dist/sync/workspaceSyncState.js +12 -0
- package/dist/sync/workspaceSyncSurface.d.ts +33 -0
- package/dist/sync/workspaceSyncSurface.js +74 -0
- package/dist/types.d.ts +143 -18
- package/dist/types.js +9 -24
- package/dist/ui/assets/AgentsModule-Bdq3T1Ts.js +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-BaS2VwIr.css +1 -0
- package/dist/ui/assets/AnnotatedAttachmentWorkspace-jKUVo-PJ.js +3 -0
- package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-DuQa-uIC.js +250 -0
- package/dist/ui/assets/InitiativesModule-C8Pi2VTk.js +1 -0
- package/dist/ui/assets/PlansPage-B6BDECSi.js +1 -0
- package/dist/ui/assets/PlansPage-BlVC_lRq.css +1 -0
- package/dist/ui/assets/TaskSettings-BwB9NtmJ.css +1 -0
- package/dist/ui/assets/TaskSettings-DUJgRTPU.js +8 -0
- package/dist/ui/assets/WorkflowsModule-b6TLuHwJ.js +5 -0
- package/dist/ui/assets/index-BiiF1cLQ.css +1 -0
- package/dist/ui/assets/index-xBWLPOEb.js +6 -0
- package/dist/ui/assets/vendor-dnd-DRzYolkg.js +5 -0
- package/dist/ui/assets/{vendor-icons-ZFG3SGwo.js → vendor-icons-QZyhEwgT.js} +1 -1
- package/dist/ui/assets/{vendor-markdown-CKYkQHfj.js → vendor-markdown-BUxTU7dS.js} +1 -1
- package/dist/ui/assets/vendor-react-CKJs5o3c.js +61 -0
- package/dist/ui/assets/vendor-router-BbWMxlnO.js +3 -0
- package/dist/ui/branding/logos/logo.png +0 -0
- package/dist/ui/branding/logos/logo_dark.svg +27 -0
- package/dist/ui/branding/logos/logo_favicon.svg +35 -0
- package/dist/ui/branding/logos/logo_light.svg +27 -0
- package/dist/ui/favicon/apple-touch-icon.png +0 -0
- package/dist/ui/favicon/archive/phoenix/apple-touch-icon.png +0 -0
- package/dist/ui/favicon/archive/phoenix/favicon.ico +0 -0
- package/dist/ui/favicon/archive/phoenix/site.webmanifest +1 -0
- package/dist/ui/favicon/favicon-96x96.png +0 -0
- package/dist/ui/favicon/favicon.ico +0 -0
- package/dist/ui/favicon/favicon.svg +17 -0
- package/dist/ui/favicon/site.webmanifest +21 -1
- package/dist/ui/favicon/web-app-manifest-192x192.png +0 -0
- package/dist/ui/favicon/web-app-manifest-512x512.png +0 -0
- package/dist/ui/index.html +10 -7
- package/dist/ui/product/screen_01.png +0 -0
- package/dist/ui/product/screen_02.png +0 -0
- package/dist/ui/product/screen_03.png +0 -0
- package/dist/utils/annotatedAttachments.d.ts +20 -0
- package/dist/utils/annotatedAttachments.js +74 -0
- package/dist/utils/annotatedAttachments.test.d.ts +1 -0
- package/dist/utils/annotatedAttachments.test.js +108 -0
- package/dist/utils/assignees.d.ts +26 -0
- package/dist/utils/assignees.js +132 -0
- package/dist/utils/canonicalAssetKind.d.ts +16 -0
- package/dist/utils/canonicalAssetKind.js +39 -0
- package/dist/utils/canonicalAssetKind.test.d.ts +1 -0
- package/dist/utils/canonicalAssetKind.test.js +24 -0
- package/dist/utils/coalescedRefresh.d.ts +5 -0
- package/dist/utils/coalescedRefresh.js +16 -0
- package/dist/utils/coalescedRefresh.test.d.ts +1 -0
- package/dist/utils/coalescedRefresh.test.js +30 -0
- package/dist/utils/constants.d.ts +16 -3
- package/dist/utils/constants.icons.test.js +2 -1
- package/dist/utils/constants.js +70 -13
- package/dist/utils/contextAssetEvents.d.ts +7 -0
- package/dist/utils/contextAssetEvents.js +6 -0
- package/dist/utils/contextFiles.d.ts +14 -3
- package/dist/utils/contextFiles.js +40 -8
- package/dist/utils/documentManagerApi.d.ts +6 -0
- package/dist/utils/documentManagerApi.js +19 -0
- package/dist/utils/documentNames.d.ts +24 -0
- package/dist/utils/documentNames.js +91 -0
- package/dist/utils/documentReferences.d.ts +9 -0
- package/dist/utils/documentReferences.js +11 -0
- package/dist/utils/entityReferences.d.ts +9 -0
- package/dist/utils/entityReferences.js +32 -0
- package/dist/utils/imageReferences.d.ts +9 -0
- package/dist/utils/imageReferences.js +11 -0
- package/dist/utils/planParser.d.ts +2 -2
- package/dist/utils/planParser.js +11 -11
- package/dist/utils/planParser.test.d.ts +1 -0
- package/dist/{__tests__ → utils}/planParser.test.js +22 -22
- package/dist/utils/planningReferences.d.ts +17 -0
- package/dist/utils/planningReferences.js +30 -0
- package/dist/utils/planningReferences.test.d.ts +1 -0
- package/dist/utils/planningReferences.test.js +17 -0
- package/dist/utils/taskActivity.d.ts +9 -0
- package/dist/utils/taskActivity.js +147 -0
- package/dist/utils/taskActivity.test.d.ts +1 -0
- package/dist/utils/taskActivity.test.js +34 -0
- package/dist/utils/taskDraftDefaults.d.ts +21 -0
- package/dist/utils/taskDraftDefaults.js +40 -0
- package/dist/utils/taskDraftDefaults.test.d.ts +1 -0
- package/dist/utils/taskDraftDefaults.test.js +34 -0
- package/dist/utils/taskNormalization.d.ts +25 -0
- package/dist/utils/taskNormalization.js +161 -0
- package/dist/utils/taskNormalization.test.d.ts +1 -0
- package/dist/utils/taskNormalization.test.js +158 -0
- package/dist/utils/taskReferences.d.ts +5 -0
- package/dist/utils/taskReferences.js +11 -0
- package/dist/utils/taskforceApiClient.d.ts +2 -0
- package/dist/utils/taskforceApiClient.js +101 -3
- package/dist/utils/taskforceApiClient.test.d.ts +1 -0
- package/dist/utils/taskforceApiClient.test.js +44 -0
- package/dist/utils/taxonomyFilterOptions.d.ts +2 -0
- package/dist/utils/taxonomyFilterOptions.js +17 -0
- package/dist/utils/taxonomyFormDefaults.d.ts +3 -0
- package/dist/utils/taxonomyFormDefaults.js +28 -0
- package/dist/utils/taxonomyFormDefaults.test.d.ts +1 -0
- package/dist/utils/taxonomyFormDefaults.test.js +63 -0
- package/dist/utils/taxonomyLifecycle.d.ts +3 -0
- package/dist/utils/taxonomyLifecycle.js +17 -0
- package/dist/utils/taxonomySorting.d.ts +7 -0
- package/dist/utils/taxonomySorting.js +74 -0
- package/dist/utils/theme.d.ts +15 -0
- package/dist/utils/theme.js +23 -0
- package/dist/utils/uiNotice.d.ts +7 -0
- package/dist/utils/uiNotice.js +6 -0
- package/dist/utils/uiNotice.test.d.ts +1 -0
- package/dist/utils/uiNotice.test.js +18 -0
- package/dist/utils/workspaceIdentity.d.ts +14 -0
- package/dist/utils/workspaceIdentity.js +21 -0
- package/dist/utils/workspaceIdentity.test.js +30 -1
- package/dist/utils/workspaceSyncPresentation.d.ts +20 -0
- package/dist/utils/workspaceSyncPresentation.js +21 -0
- package/dist/utils/workspaceSyncPresentation.test.d.ts +1 -0
- package/dist/utils/workspaceSyncPresentation.test.js +36 -0
- package/package.json +30 -23
- package/scripts/bootstrap-playwright-auth.mjs +155 -0
- package/scripts/check-compat-boundaries.mjs +41 -0
- package/scripts/check-env.ts +9 -2
- package/scripts/debug-login.mjs +32 -0
- package/scripts/deploy-prod.sh +41 -0
- package/scripts/deploy-staging.sh +23 -0
- package/scripts/migrate-planning-model.ts +233 -0
- package/scripts/migrate-task-data-assets.mjs +408 -0
- package/scripts/playwright-auth.sh +11 -0
- package/scripts/run-dev-proxy.sh +2 -0
- package/scripts/update-homebrew-formula.sh +2 -2
- package/scripts/with-esbuild.sh +11 -0
- package/src/resources/templates/WORKFLOW_V2_POLICY.md +1 -1
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +62 -52
- package/src/resources/templates/workflows/collaborate.yaml +11 -5
- package/src/resources/templates/workflows/do.yaml +8 -2
- package/src/resources/templates/workflows/evaluate.yaml +13 -7
- package/src/resources/templates/workflows/execute.yaml +40 -23
- package/src/resources/templates/workflows/plan.yaml +15 -8
- package/src/resources/templates/workflows/review.yaml +14 -8
- package/dist/TaskforceScreenshot.d.ts +0 -11
- package/dist/TaskforceScreenshot.js +0 -113
- package/dist/compat/priorityCompat.d.ts +0 -2
- package/dist/compat/priorityCompat.js +0 -24
- package/dist/components/features/settings/TaxonomyManager 2.d.ts +0 -52
- package/dist/components/features/settings/TaxonomyManager 2.js +0 -75
- package/dist/components/task/TaskKanban 2.d.ts +0 -76
- package/dist/components/task/TaskKanban 2.js +0 -1004
- package/dist/components/task/TaskScreenshotSection.d.ts +0 -15
- package/dist/components/task/TaskScreenshotSection.js +0 -22
- package/dist/components/views/StandaloneLayout 2.d.ts +0 -8
- package/dist/components/views/StandaloneLayout 2.js +0 -1660
- package/dist/core/InitiativeTemplates.test.js +0 -50
- package/dist/core/ParentLifecycle.test.js +0 -98
- package/dist/migrations/clientMigrations.d.ts +0 -9
- package/dist/migrations/clientMigrations.js +0 -74
- package/dist/migrations/flags.d.ts +0 -6
- package/dist/migrations/flags.js +0 -8
- package/dist/migrations/taskMigrations.d.ts +0 -71
- package/dist/migrations/taskMigrations.js +0 -236
- package/dist/migrations/taskMigrations.test.js +0 -34
- package/dist/server/routes.billing.js +0 -991
- package/dist/server/routes.billing.test.js +0 -387
- package/dist/server/routes.sync.integration.test.js +0 -470
- package/dist/server/routes.sync.js +0 -1141
- package/dist/soak/syncSoakHarness.d.ts +0 -6
- package/dist/soak/syncSoakHarness.js +0 -10
- package/dist/ui/assets/index-0W5vyCpn.css +0 -1
- package/dist/ui/assets/index-MCZuNNfn.js +0 -23
- package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
- package/dist/ui/assets/vendor-dnd-BI1K77C1.js +0 -5
- package/dist/ui/assets/vendor-react-DdIDsh7f.js +0 -9
- package/dist/ui/assets/vendor-router-BtiNU7Dl.js +0 -3
- package/dist/utils/taskHierarchy.d.ts +0 -4
- package/dist/utils/taskHierarchy.js +0 -69
- package/dist/utils/taskHierarchy.test.js +0 -38
- package/dist/utils/taskParenting.d.ts +0 -3
- package/dist/utils/taskParenting.js +0 -24
- package/dist/utils/taskParenting.test.js +0 -21
- package/dist/utils/taskRelations.d.ts +0 -6
- package/dist/utils/taskRelations.js +0 -24
- package/dist/utils/taskRelations.test.js +0 -34
- package/scripts/check-compat-boundaries.js +0 -48
- /package/dist/{__tests__/planParser.test.d.ts → TaskforceCore.filter-persistence.test.d.ts} +0 -0
- /package/dist/{__tests__/releaseVersion.test.d.ts → TaskforceCore.routing.test.d.ts} +0 -0
- /package/dist/{__tests__/structuredCommentValidation.test.d.ts → annotatedAttachments/AnnotatedAttachmentSessionStore.test.d.ts} +0 -0
- /package/dist/{__tests__/structuredDocValidation.test.d.ts → annotatedAttachments/payload.test.d.ts} +0 -0
- /package/dist/{__tests__/templateEngine.test.d.ts → annotatedAttachments/types.js} +0 -0
- /package/dist/{__tests__/templates.test.d.ts → compat/workspaceSyncCompat.test.d.ts} +0 -0
- /package/dist/{__tests__/workflowDocumentFixtures.test.d.ts → components/features/AgentsModule.test.d.ts} +0 -0
- /package/dist/{__tests__/workflowExportMatrix.test.d.ts → components/features/AnnotatedAttachmentWorkspace.test.d.ts} +0 -0
- /package/dist/{__tests__/workflowExportSnapshots.test.d.ts → components/features/DocumentWorkspace.test.d.ts} +0 -0
- /package/dist/{__tests__/workflowGeneration.test.d.ts → components/features/settings/TaxonomyLibraryManager.test.d.ts} +0 -0
- /package/dist/{__tests__/workflowV2Policy.test.d.ts → components/task/TaskActionHeader.test.d.ts} +0 -0
- /package/dist/{core/InitiativeTemplates.test.d.ts → components/task/TaskKanban.planning-drop.test.d.ts} +0 -0
- /package/dist/{core/ParentLifecycle.test.d.ts → components/task/TaskStatusActions.test.d.ts} +0 -0
- /package/dist/{migrations/taskMigrations.test.d.ts → components/ui/TopNoticeLayer.test.d.ts} +0 -0
- /package/dist/{server/routes.billing.test.d.ts → components/views/AppShellHeader.test.d.ts} +0 -0
- /package/dist/{server/routes.sync.integration.test.d.ts → components/views/PlanComparisonPage.test.d.ts} +0 -0
- /package/dist/{utils/taskHierarchy.test.d.ts → components/views/chrome/WorkspaceChromeSections.test.d.ts} +0 -0
- /package/dist/{utils/taskParenting.test.d.ts → components/views/chrome/workspaceChrome.test.d.ts} +0 -0
- /package/dist/{utils/taskRelations.test.d.ts → components/views/panels/DocumentFilterToolbar.test.d.ts} +0 -0
- /package/dist/public/{android-chrome-192x192.png → archive/phoenix/android-chrome-192x192.png} +0 -0
- /package/dist/public/{android-chrome-512x512.png → archive/phoenix/android-chrome-512x512.png} +0 -0
- /package/dist/public/{favicon-16x16.png → archive/phoenix/favicon-16x16.png} +0 -0
- /package/dist/public/{favicon-32x32.png → archive/phoenix/favicon-32x32.png} +0 -0
- /package/dist/public/{favicon.png → archive/phoenix/favicon.png} +0 -0
- /package/dist/{__tests__ → services}/workflowExportSnapshots.test.js +0 -0
- /package/dist/{__tests__ → services}/workflowGeneration.test.js +0 -0
- /package/dist/ui/favicon/{android-chrome-192x192.png → archive/phoenix/android-chrome-192x192.png} +0 -0
- /package/dist/ui/favicon/{android-chrome-512x512.png → archive/phoenix/android-chrome-512x512.png} +0 -0
- /package/dist/ui/favicon/{favicon-16x16.png → archive/phoenix/favicon-16x16.png} +0 -0
- /package/dist/ui/favicon/{favicon-32x32.png → archive/phoenix/favicon-32x32.png} +0 -0
- /package/dist/ui/favicon/{favicon.png → archive/phoenix/favicon.png} +0 -0
package/dist/mcp/server.js
CHANGED
|
@@ -1,1793 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { CallToolRequestSchema, ListResourceTemplatesRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, SubscribeRequestSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
-
import * as fs from 'fs';
|
|
5
|
-
import * as path from 'path';
|
|
6
|
-
import { TaskforceCore } from '../core/Taskforce.js'; // Note .js extension for ESM
|
|
7
|
-
import { COMPLEXITY_OPTIONS, resolveNumberOption, resolveStringOption, STATUS_OPTIONS } from './optionResolution.js';
|
|
8
|
-
import { validateStructuredDocForAttach } from './structuredDocValidation.js';
|
|
9
|
-
import { validateStructuredCommentForAdd } from './structuredCommentValidation.js';
|
|
10
|
-
import { resolveDatabaseConfigFromEnv } from '../storage/providerConfig.js';
|
|
11
|
-
// Initialize Core
|
|
12
|
-
// We need to find project root.
|
|
13
|
-
// In dev (tsx), we are in src/mcp/server.ts.
|
|
14
|
-
// In prod (dist), we are in dist/mcp/server.js.
|
|
15
|
-
// Project root is likely 2 levels up.
|
|
16
|
-
const PROJECT_ROOT = process.argv[2]
|
|
17
|
-
? path.resolve(process.argv[2])
|
|
18
|
-
: path.resolve(process.cwd());
|
|
19
|
-
const PROJECT_NAME = path.basename(PROJECT_ROOT);
|
|
20
|
-
console.error(`[Taskforce MCP] Starting for project: ${PROJECT_NAME} at ${PROJECT_ROOT}`);
|
|
21
|
-
const db = resolveDatabaseConfigFromEnv();
|
|
22
|
-
const tenantId = String(process.env.TASKFORCE_TENANT_ID || 'default').trim() || 'default';
|
|
23
|
-
const MCP_SERVER_VERSION = (() => {
|
|
24
|
-
try {
|
|
25
|
-
const packagePath = path.resolve(PROJECT_ROOT, 'package.json');
|
|
26
|
-
const raw = fs.readFileSync(packagePath, 'utf-8');
|
|
27
|
-
const parsed = JSON.parse(raw);
|
|
28
|
-
const version = String(parsed?.version || '').trim();
|
|
29
|
-
return version || '0.0.0-dev';
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
return '0.0.0-dev';
|
|
33
|
-
}
|
|
34
|
-
})();
|
|
35
|
-
const core = new TaskforceCore({
|
|
36
|
-
projectRoot: PROJECT_ROOT,
|
|
37
|
-
tenantId,
|
|
38
|
-
database: {
|
|
39
|
-
provider: db.provider,
|
|
40
|
-
connectionString: db.connectionString
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
const workspaceFromEnv = String(process.env.TASKFORCE_WORKSPACE_ID || '').trim();
|
|
44
|
-
let ACTIVE_WORKSPACE_ID = '';
|
|
45
|
-
const workspaceFromEnvValid = workspaceFromEnv && workspaceFromEnv.toLowerCase() !== 'default'
|
|
46
|
-
? workspaceFromEnv
|
|
47
|
-
: '';
|
|
48
|
-
if (workspaceFromEnv && !workspaceFromEnvValid) {
|
|
49
|
-
console.warn('[Taskforce MCP] Ignoring TASKFORCE_WORKSPACE_ID=default. Resolving non-default workspace automatically.');
|
|
50
|
-
}
|
|
51
|
-
if (workspaceFromEnvValid) {
|
|
52
|
-
if (!core.workspaceExists(workspaceFromEnv)) {
|
|
53
|
-
throw new Error(`[Taskforce MCP] Configured workspace not found for tenant ${tenantId}: ${workspaceFromEnv}`);
|
|
54
|
-
}
|
|
55
|
-
ACTIVE_WORKSPACE_ID = workspaceFromEnvValid;
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
const inferredWorkspaceId = core.resolvePreferredWorkspaceId({ allowDefault: false });
|
|
59
|
-
if (!inferredWorkspaceId) {
|
|
60
|
-
throw new Error('[Taskforce MCP] Unable to resolve workspace scope. Set TASKFORCE_WORKSPACE_ID explicitly.');
|
|
61
|
-
}
|
|
62
|
-
ACTIVE_WORKSPACE_ID = inferredWorkspaceId;
|
|
63
|
-
}
|
|
64
|
-
console.error(`[Taskforce MCP] Scope resolved: tenant=${tenantId} workspace=${ACTIVE_WORKSPACE_ID}`);
|
|
65
|
-
const server = new Server({
|
|
66
|
-
name: `taskforce-${PROJECT_NAME}`,
|
|
67
|
-
version: MCP_SERVER_VERSION,
|
|
68
|
-
}, {
|
|
69
|
-
capabilities: {
|
|
70
|
-
resources: {
|
|
71
|
-
subscribe: true,
|
|
72
|
-
listChanged: true,
|
|
73
|
-
},
|
|
74
|
-
tools: {},
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
/**
|
|
78
|
-
* Helpers
|
|
79
|
-
*/
|
|
80
|
-
function renderTaskTable(tasks) {
|
|
81
|
-
if (tasks.length === 0)
|
|
82
|
-
return "No tasks found.";
|
|
83
|
-
let table = "| ID | Title | Status | Assignee | Category | Priority |\n";
|
|
84
|
-
table += "|---|---|---|---|---|---|\n";
|
|
85
|
-
for (const task of tasks) {
|
|
86
|
-
table += `| \`${task.id}\` | ${task.title} | \`${task.status}\` | \`${task.assignee || 'unassigned'}\` | ${task.category} | ${task.priority} |\n`;
|
|
87
|
-
}
|
|
88
|
-
return table;
|
|
89
|
-
}
|
|
90
|
-
function isHttpUrl(value) {
|
|
91
|
-
return /^https?:\/\//i.test(value);
|
|
92
|
-
}
|
|
93
|
-
function isWithinRoot(filePath, root) {
|
|
94
|
-
const relative = path.relative(root, filePath);
|
|
95
|
-
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
|
|
96
|
-
}
|
|
97
|
-
function toPosixPath(filePath) {
|
|
98
|
-
return filePath.split(path.sep).join('/');
|
|
99
|
-
}
|
|
100
|
-
function sanitizeTaskIdForPath(taskIdRaw) {
|
|
101
|
-
const value = typeof taskIdRaw === 'string' ? taskIdRaw.trim() : '';
|
|
102
|
-
if (!value)
|
|
103
|
-
return '_unassigned';
|
|
104
|
-
return value.replace(/[^a-zA-Z0-9._-]/g, '-');
|
|
105
|
-
}
|
|
106
|
-
function sanitizeFilenameForPath(filenameRaw, fallback = 'attachment.txt') {
|
|
107
|
-
const value = typeof filenameRaw === 'string' ? filenameRaw.trim() : '';
|
|
108
|
-
const basename = path.basename(value || fallback);
|
|
109
|
-
const sanitized = basename
|
|
110
|
-
.replace(/[^a-zA-Z0-9._-]/g, '-')
|
|
111
|
-
.replace(/^\.+/, '');
|
|
112
|
-
return sanitized || fallback;
|
|
113
|
-
}
|
|
114
|
-
function nextAvailablePath(targetPath) {
|
|
115
|
-
if (!fs.existsSync(targetPath))
|
|
116
|
-
return targetPath;
|
|
117
|
-
const parsed = path.parse(targetPath);
|
|
118
|
-
let counter = 2;
|
|
119
|
-
while (true) {
|
|
120
|
-
const nextPath = path.join(parsed.dir, `${parsed.name}-${counter}${parsed.ext}`);
|
|
121
|
-
if (!fs.existsSync(nextPath))
|
|
122
|
-
return nextPath;
|
|
123
|
-
counter += 1;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
function buildRelationshipAuditComment(taskId, previousParentId, nextParentId) {
|
|
127
|
-
if (previousParentId === nextParentId)
|
|
128
|
-
return null;
|
|
129
|
-
if (!previousParentId && !nextParentId)
|
|
130
|
-
return null;
|
|
131
|
-
const timestamp = new Date().toISOString();
|
|
132
|
-
if (!previousParentId && nextParentId) {
|
|
133
|
-
return [
|
|
134
|
-
'## AI Relationship Audit',
|
|
135
|
-
'### Action',
|
|
136
|
-
'link-child',
|
|
137
|
-
'### Task',
|
|
138
|
-
taskId,
|
|
139
|
-
'### From Parent',
|
|
140
|
-
'none',
|
|
141
|
-
'### To Parent',
|
|
142
|
-
nextParentId,
|
|
143
|
-
'### Timestamp',
|
|
144
|
-
timestamp
|
|
145
|
-
].join('\n');
|
|
146
|
-
}
|
|
147
|
-
if (previousParentId && !nextParentId) {
|
|
148
|
-
return [
|
|
149
|
-
'## AI Relationship Audit',
|
|
150
|
-
'### Action',
|
|
151
|
-
'unlink-child',
|
|
152
|
-
'### Task',
|
|
153
|
-
taskId,
|
|
154
|
-
'### From Parent',
|
|
155
|
-
previousParentId,
|
|
156
|
-
'### To Parent',
|
|
157
|
-
'none',
|
|
158
|
-
'### Timestamp',
|
|
159
|
-
timestamp
|
|
160
|
-
].join('\n');
|
|
161
|
-
}
|
|
162
|
-
return [
|
|
163
|
-
'## AI Relationship Audit',
|
|
164
|
-
'### Action',
|
|
165
|
-
're-parent-child',
|
|
166
|
-
'### Task',
|
|
167
|
-
taskId,
|
|
168
|
-
'### From Parent',
|
|
169
|
-
previousParentId,
|
|
170
|
-
'### To Parent',
|
|
171
|
-
nextParentId,
|
|
172
|
-
'### Timestamp',
|
|
173
|
-
timestamp
|
|
174
|
-
].join('\n');
|
|
175
|
-
}
|
|
176
|
-
function buildBatchSummary(params) {
|
|
177
|
-
const failed = Math.max(0, params.total - params.succeeded);
|
|
178
|
-
return {
|
|
179
|
-
operation: params.operation,
|
|
180
|
-
total: params.total,
|
|
181
|
-
succeeded: params.succeeded,
|
|
182
|
-
failed,
|
|
183
|
-
partial: params.succeeded > 0 && failed > 0
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
function parseDateOnlyLocal(dateOnly) {
|
|
187
|
-
const match = String(dateOnly || '').trim().match(/^(\d{4})-(\d{2})-(\d{2})$/);
|
|
188
|
-
if (!match)
|
|
189
|
-
return null;
|
|
190
|
-
const date = new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));
|
|
191
|
-
if (Number.isNaN(date.getTime()))
|
|
192
|
-
return null;
|
|
193
|
-
return date;
|
|
194
|
-
}
|
|
195
|
-
function formatDateOnlyLocal(date) {
|
|
196
|
-
const y = date.getFullYear();
|
|
197
|
-
const m = String(date.getMonth() + 1).padStart(2, '0');
|
|
198
|
-
const d = String(date.getDate()).padStart(2, '0');
|
|
199
|
-
return `${y}-${m}-${d}`;
|
|
200
|
-
}
|
|
201
|
-
function addDaysDateOnly(dateOnly, days) {
|
|
202
|
-
const parsed = parseDateOnlyLocal(dateOnly);
|
|
203
|
-
if (!parsed)
|
|
204
|
-
return null;
|
|
205
|
-
const next = new Date(parsed);
|
|
206
|
-
next.setDate(parsed.getDate() + days);
|
|
207
|
-
return formatDateOnlyLocal(next);
|
|
208
|
-
}
|
|
209
|
-
function normalizeScheduleFieldAliases(input) {
|
|
210
|
-
const next = { ...input };
|
|
211
|
-
if (next.scheduledDate === undefined && next.scheduleDate !== undefined) {
|
|
212
|
-
next.scheduledDate = next.scheduleDate;
|
|
213
|
-
}
|
|
214
|
-
if (next.scheduledWeekKey === undefined && next.scheduleWeekKey !== undefined) {
|
|
215
|
-
next.scheduledWeekKey = next.scheduleWeekKey;
|
|
216
|
-
}
|
|
217
|
-
delete next.scheduleDate;
|
|
218
|
-
delete next.scheduleWeekKey;
|
|
219
|
-
return next;
|
|
220
|
-
}
|
|
221
|
-
const RESOURCE_URI_PREFIX = `taskforce://${PROJECT_NAME}`;
|
|
222
|
-
const RESOURCE_CONFIG_URI = `${RESOURCE_URI_PREFIX}/config`;
|
|
223
|
-
const RESOURCE_STATS_URI = `${RESOURCE_URI_PREFIX}/stats`;
|
|
224
|
-
const RESOURCE_TASKS_URI = `${RESOURCE_URI_PREFIX}/tasks`;
|
|
225
|
-
const RESOURCE_TASK_TEMPLATE_URI = `${RESOURCE_URI_PREFIX}/tasks/{id}`;
|
|
226
|
-
const resourceSubscriptions = new Set();
|
|
227
|
-
const ASSIGNEE_OPTIONS = [
|
|
228
|
-
{ value: 'unassigned', label: 'Unassigned' },
|
|
229
|
-
{ value: 'agent', label: 'Agent' },
|
|
230
|
-
{ value: 'user', label: 'User' }
|
|
231
|
-
];
|
|
232
|
-
function taskUriFor(id) {
|
|
233
|
-
return `${RESOURCE_URI_PREFIX}/tasks/${encodeURIComponent(id)}`;
|
|
234
|
-
}
|
|
235
|
-
function parseTaskIdFromUri(uri) {
|
|
236
|
-
if (!uri.startsWith(`${RESOURCE_URI_PREFIX}/tasks/`))
|
|
237
|
-
return null;
|
|
238
|
-
const encodedId = uri.slice(`${RESOURCE_URI_PREFIX}/tasks/`.length).trim();
|
|
239
|
-
if (!encodedId)
|
|
240
|
-
return null;
|
|
241
|
-
return decodeURIComponent(encodedId);
|
|
242
|
-
}
|
|
243
|
-
function isSupportedResourceUri(uri) {
|
|
244
|
-
return uri === RESOURCE_CONFIG_URI
|
|
245
|
-
|| uri === RESOURCE_STATS_URI
|
|
246
|
-
|| uri === RESOURCE_TASKS_URI
|
|
247
|
-
|| parseTaskIdFromUri(uri) !== null;
|
|
248
|
-
}
|
|
249
|
-
async function notifyResourceUpdatedIfSubscribed(uri) {
|
|
250
|
-
if (!resourceSubscriptions.has(uri))
|
|
251
|
-
return;
|
|
252
|
-
try {
|
|
253
|
-
await server.sendResourceUpdated({ uri });
|
|
254
|
-
}
|
|
255
|
-
catch (error) {
|
|
256
|
-
console.error(`[Taskforce MCP] Failed to send resources/updated for ${uri}: ${error.message}`);
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
async function notifyResourceMutation(options) {
|
|
260
|
-
const uris = new Set();
|
|
261
|
-
if (options.includeConfig)
|
|
262
|
-
uris.add(RESOURCE_CONFIG_URI);
|
|
263
|
-
if (options.includeStats)
|
|
264
|
-
uris.add(RESOURCE_STATS_URI);
|
|
265
|
-
if (options.includeTasks)
|
|
266
|
-
uris.add(RESOURCE_TASKS_URI);
|
|
267
|
-
for (const taskId of options.taskIds ?? []) {
|
|
268
|
-
if (taskId && typeof taskId === 'string') {
|
|
269
|
-
uris.add(taskUriFor(taskId));
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
for (const uri of uris) {
|
|
273
|
-
await notifyResourceUpdatedIfSubscribed(uri);
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
function buildConfigResourcePayload() {
|
|
277
|
-
return {
|
|
278
|
-
project: {
|
|
279
|
-
name: PROJECT_NAME,
|
|
280
|
-
root: PROJECT_ROOT,
|
|
281
|
-
},
|
|
282
|
-
categories: core.getCategories(),
|
|
283
|
-
types: core.getTypes(),
|
|
284
|
-
priorities: core.getPriorities(),
|
|
285
|
-
approaches: core.getApproaches(),
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
function buildTasksResourcePayload() {
|
|
289
|
-
const tasks = core.listTasks(ACTIVE_WORKSPACE_ID).tasks;
|
|
290
|
-
return {
|
|
291
|
-
total: tasks.length,
|
|
292
|
-
tasks,
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
296
|
-
return {
|
|
297
|
-
resources: [
|
|
298
|
-
{
|
|
299
|
-
uri: RESOURCE_CONFIG_URI,
|
|
300
|
-
name: `${PROJECT_NAME} Config`,
|
|
301
|
-
title: `${PROJECT_NAME} Project Configuration`,
|
|
302
|
-
description: "Resolved Taskforce categories, types, priorities, and approaches.",
|
|
303
|
-
mimeType: "application/json",
|
|
304
|
-
},
|
|
305
|
-
{
|
|
306
|
-
uri: RESOURCE_STATS_URI,
|
|
307
|
-
name: `${PROJECT_NAME} Stats`,
|
|
308
|
-
title: `${PROJECT_NAME} Task Statistics`,
|
|
309
|
-
description: "Current active and archived task counts by status and priority.",
|
|
310
|
-
mimeType: "application/json",
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
uri: RESOURCE_TASKS_URI,
|
|
314
|
-
name: `${PROJECT_NAME} Tasks`,
|
|
315
|
-
title: `${PROJECT_NAME} Active Task List`,
|
|
316
|
-
description: "All active tasks as JSON.",
|
|
317
|
-
mimeType: "application/json",
|
|
318
|
-
},
|
|
319
|
-
],
|
|
320
|
-
};
|
|
321
|
-
});
|
|
322
|
-
server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
|
|
323
|
-
return {
|
|
324
|
-
resourceTemplates: [
|
|
325
|
-
{
|
|
326
|
-
uriTemplate: RESOURCE_TASK_TEMPLATE_URI,
|
|
327
|
-
name: `${PROJECT_NAME} Task`,
|
|
328
|
-
title: `${PROJECT_NAME} Task By ID`,
|
|
329
|
-
description: "Read one task by ID. Example URI: " + taskUriFor("task-123"),
|
|
330
|
-
mimeType: "application/json",
|
|
331
|
-
},
|
|
332
|
-
],
|
|
333
|
-
};
|
|
334
|
-
});
|
|
335
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
336
|
-
const uri = request.params.uri;
|
|
337
|
-
if (uri === RESOURCE_CONFIG_URI) {
|
|
338
|
-
return {
|
|
339
|
-
contents: [
|
|
340
|
-
{
|
|
341
|
-
uri,
|
|
342
|
-
mimeType: "application/json",
|
|
343
|
-
text: JSON.stringify(buildConfigResourcePayload(), null, 2),
|
|
344
|
-
},
|
|
345
|
-
],
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
if (uri === RESOURCE_STATS_URI) {
|
|
349
|
-
return {
|
|
350
|
-
contents: [
|
|
351
|
-
{
|
|
352
|
-
uri,
|
|
353
|
-
mimeType: "application/json",
|
|
354
|
-
text: JSON.stringify(core.getStats(ACTIVE_WORKSPACE_ID), null, 2),
|
|
355
|
-
},
|
|
356
|
-
],
|
|
357
|
-
};
|
|
358
|
-
}
|
|
359
|
-
if (uri === RESOURCE_TASKS_URI) {
|
|
360
|
-
return {
|
|
361
|
-
contents: [
|
|
362
|
-
{
|
|
363
|
-
uri,
|
|
364
|
-
mimeType: "application/json",
|
|
365
|
-
text: JSON.stringify(buildTasksResourcePayload(), null, 2),
|
|
366
|
-
},
|
|
367
|
-
],
|
|
368
|
-
};
|
|
369
|
-
}
|
|
370
|
-
const taskId = parseTaskIdFromUri(uri);
|
|
371
|
-
if (taskId) {
|
|
372
|
-
const task = core.getTask(taskId, ACTIVE_WORKSPACE_ID);
|
|
373
|
-
if (!task) {
|
|
374
|
-
throw new Error(`Task not found for URI: ${uri}`);
|
|
375
|
-
}
|
|
376
|
-
return {
|
|
377
|
-
contents: [
|
|
378
|
-
{
|
|
379
|
-
uri,
|
|
380
|
-
mimeType: "application/json",
|
|
381
|
-
text: JSON.stringify(task, null, 2),
|
|
382
|
-
},
|
|
383
|
-
],
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
throw new Error(`Unknown resource URI: ${uri}`);
|
|
387
|
-
});
|
|
388
|
-
server.setRequestHandler(SubscribeRequestSchema, async (request) => {
|
|
389
|
-
const uri = request.params.uri;
|
|
390
|
-
if (!isSupportedResourceUri(uri)) {
|
|
391
|
-
throw new Error(`Unsupported resource URI for subscribe: ${uri}`);
|
|
392
|
-
}
|
|
393
|
-
resourceSubscriptions.add(uri);
|
|
394
|
-
return {};
|
|
395
|
-
});
|
|
396
|
-
server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
|
|
397
|
-
const uri = request.params.uri;
|
|
398
|
-
if (!isSupportedResourceUri(uri)) {
|
|
399
|
-
throw new Error(`Unsupported resource URI for unsubscribe: ${uri}`);
|
|
400
|
-
}
|
|
401
|
-
resourceSubscriptions.delete(uri);
|
|
402
|
-
return {};
|
|
403
|
-
});
|
|
404
|
-
/**
|
|
405
|
-
* Tool Definitions
|
|
406
|
-
*/
|
|
407
|
-
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
408
|
-
const priorities = core.getPriorities();
|
|
409
|
-
const approaches = core.getApproaches();
|
|
410
|
-
const types = core.getTypes();
|
|
411
|
-
const priorityDesc = "Priority level: " + priorities.map(p => `${p.value} (${p.label})`).join(', ');
|
|
412
|
-
const approachEnum = approaches.map(a => a.value);
|
|
413
|
-
const typeEnum = types.map(t => t.value);
|
|
414
|
-
const complexityDesc = "Complexity level: 1 (Tiny), 2 (Low), 3 (Medium), 4 (High), 5 (Epic)";
|
|
415
|
-
const optionPreflight = "Before setting category/type/priority/approach/status/complexity, call get_config to read current valid values. ";
|
|
416
|
-
const prefix = `[Project: ${PROJECT_NAME}] `;
|
|
417
|
-
const agentNote = " NOTE: Use this tool instead of editing files directly to ensure data integrity.";
|
|
418
|
-
return {
|
|
419
|
-
tools: [
|
|
420
|
-
{
|
|
421
|
-
name: "list_tasks",
|
|
422
|
-
description: prefix + "List all active task items." + agentNote,
|
|
423
|
-
inputSchema: {
|
|
424
|
-
type: "object",
|
|
425
|
-
properties: {
|
|
426
|
-
format: { type: "string", enum: ["markdown", "json"], description: "Toggle output format (default: markdown)" },
|
|
427
|
-
category: { type: "string", description: "Filter by category" },
|
|
428
|
-
status: { type: "string", enum: ["task", "on-hold", "in-progress", "review", "done", "cancelled"], description: "Filter by status" },
|
|
429
|
-
parentTaskId: { type: "string", description: "Filter by parent task ID (direct children only)." },
|
|
430
|
-
openOnly: { type: "boolean", description: "When true, only include open tasks (task, on-hold, in-progress, review)." },
|
|
431
|
-
assignee: { type: "string", enum: ["unassigned", "agent", "user"], description: "Filter by assignee" },
|
|
432
|
-
priority: { type: "number", description: "Filter by priority level" },
|
|
433
|
-
type: { type: "string", enum: typeEnum, description: "Filter by task type" },
|
|
434
|
-
sort: { type: "string", enum: ["priority", "created", "updated"], description: "Sort field (default: created)" },
|
|
435
|
-
order: { type: "string", enum: ["asc", "desc"], description: "Sort order (default: desc)" },
|
|
436
|
-
limit: { type: "number", description: "Max tasks to return" }
|
|
437
|
-
},
|
|
438
|
-
},
|
|
439
|
-
},
|
|
440
|
-
{
|
|
441
|
-
name: "search_tasks",
|
|
442
|
-
description: prefix + "Search for tasks (active and archived) by query string." + agentNote,
|
|
443
|
-
inputSchema: {
|
|
444
|
-
type: "object",
|
|
445
|
-
properties: {
|
|
446
|
-
query: { type: "string", description: "Search term (matches title, description, or ID)" },
|
|
447
|
-
scope: { type: "string", enum: ["all", "active", "archive"], description: "Search scope (default: all)" }
|
|
448
|
-
},
|
|
449
|
-
required: ["query"]
|
|
450
|
-
}
|
|
451
|
-
},
|
|
452
|
-
{
|
|
453
|
-
name: "get_task",
|
|
454
|
-
description: prefix + "Get a specific task item by ID (checks active and archive)" + agentNote,
|
|
455
|
-
inputSchema: {
|
|
456
|
-
type: "object",
|
|
457
|
-
properties: {
|
|
458
|
-
id: { type: "string" }
|
|
459
|
-
},
|
|
460
|
-
required: ["id"],
|
|
461
|
-
},
|
|
462
|
-
},
|
|
463
|
-
{
|
|
464
|
-
name: "get_schedule_board",
|
|
465
|
-
description: prefix + "Get schedule board state for a target week (backlog/expired/day columns)." + agentNote,
|
|
466
|
-
inputSchema: {
|
|
467
|
-
type: "object",
|
|
468
|
-
properties: {
|
|
469
|
-
week: { type: "string", description: "ISO week key (e.g., 2026-W08)" },
|
|
470
|
-
showWeekends: { type: "boolean", description: "Include Saturday/Sunday columns (default: false)" }
|
|
471
|
-
},
|
|
472
|
-
required: ["week"],
|
|
473
|
-
},
|
|
474
|
-
},
|
|
475
|
-
{
|
|
476
|
-
name: "schedule_task",
|
|
477
|
-
description: prefix + "Schedule a task to a date/order. Leaf-only validation and scheduling warnings are enforced." + agentNote,
|
|
478
|
-
inputSchema: {
|
|
479
|
-
type: "object",
|
|
480
|
-
properties: {
|
|
481
|
-
id: { type: "string" },
|
|
482
|
-
scheduledDate: { type: "string", description: "Date-only value (YYYY-MM-DD)" },
|
|
483
|
-
orderInDay: { type: "number", description: "Optional order index within the scheduled day" }
|
|
484
|
-
},
|
|
485
|
-
required: ["id", "scheduledDate"],
|
|
486
|
-
},
|
|
487
|
-
},
|
|
488
|
-
{
|
|
489
|
-
name: "unschedule_task",
|
|
490
|
-
description: prefix + "Move a task back to backlog by clearing schedule fields." + agentNote,
|
|
491
|
-
inputSchema: {
|
|
492
|
-
type: "object",
|
|
493
|
-
properties: {
|
|
494
|
-
id: { type: "string" }
|
|
495
|
-
},
|
|
496
|
-
required: ["id"],
|
|
497
|
-
},
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
name: "reorder_scheduled_tasks",
|
|
501
|
-
description: prefix + "Apply multiple schedule/date/order moves in one operation." + agentNote,
|
|
502
|
-
inputSchema: {
|
|
503
|
-
type: "object",
|
|
504
|
-
properties: {
|
|
505
|
-
moves: {
|
|
506
|
-
type: "array",
|
|
507
|
-
items: {
|
|
508
|
-
type: "object",
|
|
509
|
-
properties: {
|
|
510
|
-
id: { type: "string" },
|
|
511
|
-
scheduledDate: { type: ["string", "null"] },
|
|
512
|
-
orderInDay: { type: "number" }
|
|
513
|
-
},
|
|
514
|
-
required: ["id", "scheduledDate"]
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
},
|
|
518
|
-
required: ["moves"],
|
|
519
|
-
},
|
|
520
|
-
},
|
|
521
|
-
{
|
|
522
|
-
name: "bulk_carryover",
|
|
523
|
-
description: prefix + "Carry over unfinished scheduled tasks by day or week." + agentNote,
|
|
524
|
-
inputSchema: {
|
|
525
|
-
type: "object",
|
|
526
|
-
properties: {
|
|
527
|
-
fromWeek: { type: "string", description: "Source ISO week key (e.g., 2026-W08)" },
|
|
528
|
-
toWeek: { type: "string", description: "Target ISO week key (currently informational; date shift is mode-based)" },
|
|
529
|
-
mode: { type: "string", enum: ["day", "week"], description: "Shift scheduled dates by 1 day or 7 days" },
|
|
530
|
-
includeStatuses: {
|
|
531
|
-
type: "array",
|
|
532
|
-
items: { type: "string", enum: ["task", "on-hold", "in-progress", "review", "done", "cancelled"] },
|
|
533
|
-
description: "Statuses eligible for carryover (default: task,in-progress,review,on-hold)"
|
|
534
|
-
}
|
|
535
|
-
},
|
|
536
|
-
required: ["fromWeek", "toWeek", "mode"],
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
name: "set_schedule_preferences",
|
|
541
|
-
description: prefix + "Persist schedule preferences used by planning flows." + agentNote,
|
|
542
|
-
inputSchema: {
|
|
543
|
-
type: "object",
|
|
544
|
-
properties: {
|
|
545
|
-
showWeekends: { type: "boolean" },
|
|
546
|
-
isCalendarSidebarOpen: { type: "boolean" },
|
|
547
|
-
dailyCapacity: {
|
|
548
|
-
type: "object",
|
|
549
|
-
properties: {
|
|
550
|
-
monday: { type: "number" },
|
|
551
|
-
tuesday: { type: "number" },
|
|
552
|
-
wednesday: { type: "number" },
|
|
553
|
-
thursday: { type: "number" },
|
|
554
|
-
friday: { type: "number" },
|
|
555
|
-
saturday: { type: "number" },
|
|
556
|
-
sunday: { type: "number" }
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
},
|
|
560
|
-
},
|
|
561
|
-
},
|
|
562
|
-
{
|
|
563
|
-
name: "create_task",
|
|
564
|
-
description: prefix + "Create a new task item. " + optionPreflight + agentNote,
|
|
565
|
-
inputSchema: {
|
|
566
|
-
type: "object",
|
|
567
|
-
properties: {
|
|
568
|
-
title: { type: "string" },
|
|
569
|
-
description: { type: "string" },
|
|
570
|
-
category: { type: "string" },
|
|
571
|
-
type: { type: "string", enum: typeEnum },
|
|
572
|
-
priority: { type: "number", description: priorityDesc },
|
|
573
|
-
complexity: { type: "number", description: complexityDesc },
|
|
574
|
-
status: { type: "string", enum: ["task", "on-hold", "in-progress", "review"], description: "Initial status (default: task)" },
|
|
575
|
-
approach: { type: "string", enum: approachEnum },
|
|
576
|
-
assignee: { type: "string", enum: ["unassigned", "agent", "user"], description: "Task owner assignment" },
|
|
577
|
-
owner: { type: "string", enum: ["unassigned", "agent", "user"], description: "Alias for assignee (task owner assignment)" },
|
|
578
|
-
scheduledDate: { type: "string", description: "Optional schedule date in YYYY-MM-DD format" },
|
|
579
|
-
dueDate: { type: "string", description: "Optional due date in YYYY-MM-DD format" },
|
|
580
|
-
orderInDay: { type: "number", description: "Optional sort order within scheduledDate" },
|
|
581
|
-
parentTaskId: { type: "string", description: "Optional parent task ID. Empty/omitted means top-level task." },
|
|
582
|
-
childDisplayOrder: { type: "number", description: "Optional display-only child order index (lower comes first among siblings)." },
|
|
583
|
-
specialists: { type: "array", items: { type: "string" }, description: "List of specialist skill IDs to assign" }
|
|
584
|
-
},
|
|
585
|
-
required: ["title"],
|
|
586
|
-
},
|
|
587
|
-
},
|
|
588
|
-
{
|
|
589
|
-
name: "update_task",
|
|
590
|
-
description: prefix + "Update an existing task item. " + optionPreflight + "Status reflects workflow state (task/on-hold/in-progress/review/done/cancelled). Archiving moves tasks to history - use archive_task for that." + agentNote,
|
|
591
|
-
inputSchema: {
|
|
592
|
-
type: "object",
|
|
593
|
-
properties: {
|
|
594
|
-
id: { type: "string" },
|
|
595
|
-
title: { type: "string" },
|
|
596
|
-
description: { type: "string" },
|
|
597
|
-
category: { type: "string" },
|
|
598
|
-
type: { type: "string", enum: typeEnum },
|
|
599
|
-
priority: { type: "number", description: priorityDesc },
|
|
600
|
-
complexity: { type: "number", description: complexityDesc },
|
|
601
|
-
approach: { type: "string", enum: approachEnum },
|
|
602
|
-
assignee: { type: "string", enum: ["unassigned", "agent", "user"], description: "Task owner assignment" },
|
|
603
|
-
owner: { type: "string", enum: ["unassigned", "agent", "user"], description: "Alias for assignee (task owner assignment)" },
|
|
604
|
-
scheduledDate: { type: "string", description: "Set schedule date (YYYY-MM-DD)" },
|
|
605
|
-
dueDate: { type: "string", description: "Set due date (YYYY-MM-DD)" },
|
|
606
|
-
orderInDay: { type: "number", description: "Set order index within scheduledDate" },
|
|
607
|
-
status: { type: "string", enum: ["task", "on-hold", "in-progress", "review", "done", "cancelled"] },
|
|
608
|
-
parentTaskId: { type: "string", description: "Set to a parent task ID, or empty string to unlink." },
|
|
609
|
-
childDisplayOrder: { type: "number", description: "Optional display-only child order index (lower comes first among siblings)." },
|
|
610
|
-
specialists: { type: "array", items: { type: "string" }, description: "Update list of assigned specialists" },
|
|
611
|
-
canceledReason: { type: "string", description: "Reason for cancellation" }
|
|
612
|
-
},
|
|
613
|
-
required: ["id"],
|
|
614
|
-
},
|
|
615
|
-
},
|
|
616
|
-
{
|
|
617
|
-
name: "assign_task",
|
|
618
|
-
description: prefix + "Assign a task owner explicitly (user/agent/unassigned)." + agentNote,
|
|
619
|
-
inputSchema: {
|
|
620
|
-
type: "object",
|
|
621
|
-
properties: {
|
|
622
|
-
id: { type: "string" },
|
|
623
|
-
assignee: { type: "string", enum: ["unassigned", "agent", "user"] }
|
|
624
|
-
},
|
|
625
|
-
required: ["id", "assignee"],
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
{
|
|
629
|
-
name: "bulk_assign_tasks",
|
|
630
|
-
description: prefix + "Assign many tasks to one owner explicitly (user/agent/unassigned)." + agentNote,
|
|
631
|
-
inputSchema: {
|
|
632
|
-
type: "object",
|
|
633
|
-
properties: {
|
|
634
|
-
ids: { type: "array", items: { type: "string" } },
|
|
635
|
-
assignee: { type: "string", enum: ["unassigned", "agent", "user"] }
|
|
636
|
-
},
|
|
637
|
-
required: ["ids", "assignee"],
|
|
638
|
-
},
|
|
639
|
-
},
|
|
640
|
-
{
|
|
641
|
-
name: "archive_task",
|
|
642
|
-
description: prefix + "Archive a task item (moving to history). This is the preferred way to 'remove' completed or cancelled tasks." + agentNote,
|
|
643
|
-
inputSchema: {
|
|
644
|
-
type: "object",
|
|
645
|
-
properties: {
|
|
646
|
-
id: { type: "string" },
|
|
647
|
-
status: { type: "string", enum: ["done", "cancelled"], description: "Final status when archiving" },
|
|
648
|
-
reason: { type: "string", description: "Reason for cancellation" }
|
|
649
|
-
},
|
|
650
|
-
required: ["id", "status"],
|
|
651
|
-
},
|
|
652
|
-
},
|
|
653
|
-
{
|
|
654
|
-
name: "add_comment",
|
|
655
|
-
description: prefix + "Add a comment to a task item." + agentNote,
|
|
656
|
-
inputSchema: {
|
|
657
|
-
type: "object",
|
|
658
|
-
properties: {
|
|
659
|
-
id: { type: "string" },
|
|
660
|
-
text: { type: "string" },
|
|
661
|
-
author: { type: "string", description: "Comment author identity. Use 'user' for human comments, or AI identifiers such as 'ai', 'codex', 'antigravity', 'claude', etc." }
|
|
662
|
-
},
|
|
663
|
-
required: ["id", "text", "author"],
|
|
664
|
-
},
|
|
665
|
-
},
|
|
666
|
-
{
|
|
667
|
-
name: "attach_context_file",
|
|
668
|
-
description: prefix + "Attach a project file or URL to a task as context. Local files must be inside the project root." + agentNote,
|
|
669
|
-
inputSchema: {
|
|
670
|
-
type: "object",
|
|
671
|
-
properties: {
|
|
672
|
-
id: { type: "string", description: "Task ID" },
|
|
673
|
-
path: { type: "string", description: "File path (absolute or project-relative) or an http(s) URL" },
|
|
674
|
-
caption: { type: "string", description: "Optional label shown in task context" }
|
|
675
|
-
},
|
|
676
|
-
required: ["id", "path"],
|
|
677
|
-
},
|
|
678
|
-
},
|
|
679
|
-
{
|
|
680
|
-
name: "save_task_attachment",
|
|
681
|
-
description: prefix + "Save task-specific content or a copied file into .taskforce/task-data/{taskId}/attachments and attach it to the task." + agentNote,
|
|
682
|
-
inputSchema: {
|
|
683
|
-
type: "object",
|
|
684
|
-
properties: {
|
|
685
|
-
id: { type: "string", description: "Task ID" },
|
|
686
|
-
filename: { type: "string", description: "Target filename in the task attachments folder." },
|
|
687
|
-
content: { type: "string", description: "Text/markdown file content to save. Provide either content or sourcePath." },
|
|
688
|
-
sourcePath: { type: "string", description: "Project-relative or absolute source file path to copy. Provide either sourcePath or content." },
|
|
689
|
-
caption: { type: "string", description: "Optional label shown in task context" },
|
|
690
|
-
overwrite: { type: "boolean", description: "Overwrite the destination file when it already exists (default: false)." }
|
|
691
|
-
},
|
|
692
|
-
required: ["id", "filename"],
|
|
693
|
-
},
|
|
694
|
-
},
|
|
695
|
-
{
|
|
696
|
-
name: "list_archive",
|
|
697
|
-
description: prefix + "List all archived task items." + agentNote,
|
|
698
|
-
inputSchema: {
|
|
699
|
-
type: "object",
|
|
700
|
-
properties: {
|
|
701
|
-
format: { type: "string", enum: ["markdown", "json"], description: "Toggle output format (default: markdown)" }
|
|
702
|
-
},
|
|
703
|
-
},
|
|
704
|
-
},
|
|
705
|
-
{
|
|
706
|
-
name: "unarchive_task",
|
|
707
|
-
description: prefix + "Move a task from archive back to active." + agentNote,
|
|
708
|
-
inputSchema: {
|
|
709
|
-
type: "object",
|
|
710
|
-
properties: {
|
|
711
|
-
id: { type: "string" }
|
|
712
|
-
},
|
|
713
|
-
required: ["id"],
|
|
714
|
-
},
|
|
715
|
-
},
|
|
716
|
-
{
|
|
717
|
-
name: "bulk_archive",
|
|
718
|
-
description: prefix + "Archive multiple task items at once." + agentNote,
|
|
719
|
-
inputSchema: {
|
|
720
|
-
type: "object",
|
|
721
|
-
properties: {
|
|
722
|
-
ids: { type: "array", items: { type: "string" } },
|
|
723
|
-
status: { type: "string", enum: ["done", "cancelled"], description: "Status for all archived items (default: done)" }
|
|
724
|
-
},
|
|
725
|
-
required: ["ids"],
|
|
726
|
-
},
|
|
727
|
-
},
|
|
728
|
-
{
|
|
729
|
-
name: "get_config",
|
|
730
|
-
description: prefix + "Get full Taskforce configuration (types, priorities, approaches, categories)." + agentNote,
|
|
731
|
-
inputSchema: {
|
|
732
|
-
type: "object",
|
|
733
|
-
properties: {},
|
|
734
|
-
},
|
|
735
|
-
},
|
|
736
|
-
{
|
|
737
|
-
name: "update_categories",
|
|
738
|
-
description: prefix + "Update category definitions." + agentNote,
|
|
739
|
-
inputSchema: {
|
|
740
|
-
type: "object",
|
|
741
|
-
properties: {
|
|
742
|
-
categories: {
|
|
743
|
-
type: "array",
|
|
744
|
-
items: {
|
|
745
|
-
type: "object",
|
|
746
|
-
properties: {
|
|
747
|
-
value: { type: "string" },
|
|
748
|
-
label: { type: "string" },
|
|
749
|
-
icon: { type: "string" },
|
|
750
|
-
color: { type: "string" }
|
|
751
|
-
},
|
|
752
|
-
required: ["value", "label"]
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
},
|
|
756
|
-
required: ["categories"],
|
|
757
|
-
},
|
|
758
|
-
},
|
|
759
|
-
{
|
|
760
|
-
name: "update_types",
|
|
761
|
-
description: prefix + "Update task type definitions." + agentNote,
|
|
762
|
-
inputSchema: {
|
|
763
|
-
type: "object",
|
|
764
|
-
properties: {
|
|
765
|
-
types: {
|
|
766
|
-
type: "array",
|
|
767
|
-
items: {
|
|
768
|
-
type: "object",
|
|
769
|
-
properties: {
|
|
770
|
-
value: { type: "string" },
|
|
771
|
-
label: { type: "string" }
|
|
772
|
-
},
|
|
773
|
-
required: ["value", "label"]
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
},
|
|
777
|
-
required: ["types"],
|
|
778
|
-
},
|
|
779
|
-
},
|
|
780
|
-
{
|
|
781
|
-
name: "bulk_update_type",
|
|
782
|
-
description: prefix + "Change the type of multiple tasks." + agentNote,
|
|
783
|
-
inputSchema: {
|
|
784
|
-
type: "object",
|
|
785
|
-
properties: {
|
|
786
|
-
fromType: { type: "string" },
|
|
787
|
-
toType: { type: "string" }
|
|
788
|
-
},
|
|
789
|
-
required: ["fromType", "toType"],
|
|
790
|
-
},
|
|
791
|
-
},
|
|
792
|
-
{
|
|
793
|
-
name: "bulk_update_fields",
|
|
794
|
-
description: prefix + "Update specific fields for multiple tasks at once. Efficient for batch operations like reprioritizing or recategorizing. " + optionPreflight + agentNote,
|
|
795
|
-
inputSchema: {
|
|
796
|
-
type: "object",
|
|
797
|
-
properties: {
|
|
798
|
-
updates: {
|
|
799
|
-
type: "array",
|
|
800
|
-
items: {
|
|
801
|
-
type: "object",
|
|
802
|
-
properties: {
|
|
803
|
-
id: { type: "string" },
|
|
804
|
-
title: { type: "string" },
|
|
805
|
-
description: { type: "string" },
|
|
806
|
-
category: { type: "string" },
|
|
807
|
-
type: { type: "string", enum: typeEnum },
|
|
808
|
-
priority: { type: "number", description: priorityDesc },
|
|
809
|
-
complexity: { type: "number", description: complexityDesc },
|
|
810
|
-
approach: { type: "string", enum: approachEnum },
|
|
811
|
-
assignee: { type: "string", enum: ["unassigned", "agent", "user"] },
|
|
812
|
-
owner: { type: "string", enum: ["unassigned", "agent", "user"], description: "Alias for assignee" },
|
|
813
|
-
status: { type: "string", enum: ["task", "on-hold", "in-progress", "review", "done", "cancelled"] },
|
|
814
|
-
specialists: { type: "array", items: { type: "string" } }
|
|
815
|
-
},
|
|
816
|
-
required: ["id"]
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
},
|
|
820
|
-
required: ["updates"],
|
|
821
|
-
},
|
|
822
|
-
},
|
|
823
|
-
{
|
|
824
|
-
name: "list_skills",
|
|
825
|
-
description: prefix + "List available skills (also known as agents or specialists)." + agentNote,
|
|
826
|
-
inputSchema: {
|
|
827
|
-
type: "object",
|
|
828
|
-
properties: {},
|
|
829
|
-
},
|
|
830
|
-
},
|
|
831
|
-
{
|
|
832
|
-
name: "export_resources",
|
|
833
|
-
description: prefix + "Export templates (workflows/skills) to the project." + agentNote,
|
|
834
|
-
inputSchema: {
|
|
835
|
-
type: "object",
|
|
836
|
-
properties: {
|
|
837
|
-
type: { type: "string", enum: ["workflows", "skills"] },
|
|
838
|
-
path: { type: "string" },
|
|
839
|
-
variables: { type: "object", additionalProperties: { type: "string" } },
|
|
840
|
-
environment: { type: "string", enum: ["aider", "antigravity", "claude", "cline", "codex", "copilot", "cursor", "gemini", "windsurf"], description: "Target environment/IDE" }
|
|
841
|
-
},
|
|
842
|
-
required: ["type", "path"],
|
|
843
|
-
},
|
|
844
|
-
},
|
|
845
|
-
{
|
|
846
|
-
name: "get_paths",
|
|
847
|
-
description: prefix + "Get project and storage paths." + agentNote,
|
|
848
|
-
inputSchema: {
|
|
849
|
-
type: "object",
|
|
850
|
-
properties: {},
|
|
851
|
-
},
|
|
852
|
-
},
|
|
853
|
-
{
|
|
854
|
-
name: "update_priorities",
|
|
855
|
-
description: prefix + "Update priority level definitions." + agentNote,
|
|
856
|
-
inputSchema: {
|
|
857
|
-
type: "object",
|
|
858
|
-
properties: {
|
|
859
|
-
priorities: {
|
|
860
|
-
type: "array",
|
|
861
|
-
items: {
|
|
862
|
-
type: "object",
|
|
863
|
-
properties: {
|
|
864
|
-
value: { type: "number" },
|
|
865
|
-
label: { type: "string" },
|
|
866
|
-
color: { type: "string" },
|
|
867
|
-
icon: { type: "string" }
|
|
868
|
-
},
|
|
869
|
-
required: ["value", "label"]
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
},
|
|
873
|
-
required: ["priorities"],
|
|
874
|
-
},
|
|
875
|
-
},
|
|
876
|
-
{
|
|
877
|
-
name: "update_approaches",
|
|
878
|
-
description: prefix + "Update approach definitions." + agentNote,
|
|
879
|
-
inputSchema: {
|
|
880
|
-
type: "object",
|
|
881
|
-
properties: {
|
|
882
|
-
approaches: {
|
|
883
|
-
type: "array",
|
|
884
|
-
items: {
|
|
885
|
-
type: "object",
|
|
886
|
-
properties: {
|
|
887
|
-
value: { type: "string" },
|
|
888
|
-
label: { type: "string" },
|
|
889
|
-
color: { type: "string" },
|
|
890
|
-
icon: { type: "string" }
|
|
891
|
-
},
|
|
892
|
-
required: ["value", "label"]
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
},
|
|
896
|
-
required: ["approaches"],
|
|
897
|
-
},
|
|
898
|
-
},
|
|
899
|
-
{
|
|
900
|
-
name: "get_stats",
|
|
901
|
-
description: prefix + "Get task statistics for situational awareness (counts by status, priority, etc)." + agentNote,
|
|
902
|
-
inputSchema: {
|
|
903
|
-
type: "object",
|
|
904
|
-
properties: {},
|
|
905
|
-
},
|
|
906
|
-
}
|
|
907
|
-
],
|
|
908
|
-
};
|
|
909
|
-
});
|
|
910
|
-
/**
|
|
911
|
-
* Tool Execution
|
|
912
|
-
*/
|
|
913
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
914
|
-
const { name, arguments: args } = request.params;
|
|
915
|
-
try {
|
|
916
|
-
switch (name) {
|
|
917
|
-
case "list_tasks": {
|
|
918
|
-
const { format = "markdown", category, status, parentTaskId, openOnly = false, assignee, priority, type, sort = "created", order = "desc", limit } = args;
|
|
919
|
-
let data = core.listTasks(ACTIVE_WORKSPACE_ID);
|
|
920
|
-
let tasks = data.tasks;
|
|
921
|
-
const openStatuses = new Set(["task", "on-hold", "in-progress", "review"]);
|
|
922
|
-
// Filtering
|
|
923
|
-
if (category)
|
|
924
|
-
tasks = tasks.filter(t => t.category === category);
|
|
925
|
-
if (status)
|
|
926
|
-
tasks = tasks.filter(t => t.status === status);
|
|
927
|
-
if (parentTaskId !== undefined) {
|
|
928
|
-
const normalizedParentTaskId = String(parentTaskId || "").trim();
|
|
929
|
-
tasks = tasks.filter(t => (t.parentTaskId || "") === normalizedParentTaskId);
|
|
930
|
-
}
|
|
931
|
-
if (openOnly)
|
|
932
|
-
tasks = tasks.filter(t => openStatuses.has(t.status));
|
|
933
|
-
if (assignee)
|
|
934
|
-
tasks = tasks.filter(t => (t.assignee || 'unassigned') === assignee);
|
|
935
|
-
if (priority !== undefined)
|
|
936
|
-
tasks = tasks.filter(t => t.priority === Number(priority));
|
|
937
|
-
if (type)
|
|
938
|
-
tasks = tasks.filter(t => t.type === type);
|
|
939
|
-
// Sorting
|
|
940
|
-
tasks.sort((a, b) => {
|
|
941
|
-
let aVal, bVal;
|
|
942
|
-
if (sort === "priority") {
|
|
943
|
-
aVal = a.priority;
|
|
944
|
-
bVal = b.priority;
|
|
945
|
-
}
|
|
946
|
-
else if (sort === "updated") {
|
|
947
|
-
aVal = a.updatedAt || a.createdAt;
|
|
948
|
-
bVal = b.updatedAt || b.createdAt;
|
|
949
|
-
}
|
|
950
|
-
else {
|
|
951
|
-
aVal = a.createdAt;
|
|
952
|
-
bVal = b.createdAt;
|
|
953
|
-
}
|
|
954
|
-
const cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
|
|
955
|
-
return order === "asc" ? cmp : -cmp;
|
|
956
|
-
});
|
|
957
|
-
// Limiting
|
|
958
|
-
if (limit && limit > 0) {
|
|
959
|
-
tasks = tasks.slice(0, limit);
|
|
960
|
-
}
|
|
961
|
-
if (format === "json") {
|
|
962
|
-
return {
|
|
963
|
-
content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }],
|
|
964
|
-
};
|
|
965
|
-
}
|
|
966
|
-
return {
|
|
967
|
-
content: [{ type: "text", text: renderTaskTable(tasks) }],
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
case "search_tasks": {
|
|
971
|
-
const { query, scope = "all" } = args;
|
|
972
|
-
const results = core.searchTasks(query, scope, ACTIVE_WORKSPACE_ID);
|
|
973
|
-
return {
|
|
974
|
-
content: [{ type: "text", text: renderTaskTable(results) }],
|
|
975
|
-
};
|
|
976
|
-
}
|
|
977
|
-
case "get_task": {
|
|
978
|
-
const { id } = args;
|
|
979
|
-
const task = core.getTask(id, ACTIVE_WORKSPACE_ID);
|
|
980
|
-
if (!task) {
|
|
981
|
-
throw new Error(`Task ${id} not found`);
|
|
982
|
-
}
|
|
983
|
-
return {
|
|
984
|
-
content: [{ type: "text", text: JSON.stringify(task, null, 2) }],
|
|
985
|
-
};
|
|
986
|
-
}
|
|
987
|
-
case "get_schedule_board": {
|
|
988
|
-
const { week, showWeekends = false } = args;
|
|
989
|
-
if (!week || typeof week !== 'string') {
|
|
990
|
-
throw new Error('week is required');
|
|
991
|
-
}
|
|
992
|
-
const board = core.getScheduleBoard(week, Boolean(showWeekends), ACTIVE_WORKSPACE_ID);
|
|
993
|
-
return {
|
|
994
|
-
content: [{ type: "text", text: JSON.stringify(board, null, 2) }],
|
|
995
|
-
};
|
|
996
|
-
}
|
|
997
|
-
case "schedule_task": {
|
|
998
|
-
const { id, scheduledDate, orderInDay } = args;
|
|
999
|
-
if (!id || typeof id !== 'string')
|
|
1000
|
-
throw new Error('id is required');
|
|
1001
|
-
if (!scheduledDate || typeof scheduledDate !== 'string')
|
|
1002
|
-
throw new Error('scheduledDate is required');
|
|
1003
|
-
const result = core.updateTaskSchedule(id, { scheduledDate, orderInDay }, ACTIVE_WORKSPACE_ID);
|
|
1004
|
-
if (!result) {
|
|
1005
|
-
throw new Error(`Task ${id} not found`);
|
|
1006
|
-
}
|
|
1007
|
-
await notifyResourceMutation({
|
|
1008
|
-
taskIds: [id],
|
|
1009
|
-
includeTasks: true,
|
|
1010
|
-
includeStats: true,
|
|
1011
|
-
});
|
|
1012
|
-
return {
|
|
1013
|
-
content: [{
|
|
1014
|
-
type: "text",
|
|
1015
|
-
text: JSON.stringify({
|
|
1016
|
-
success: true,
|
|
1017
|
-
scheduling: {
|
|
1018
|
-
taskId: id,
|
|
1019
|
-
requestedDate: scheduledDate,
|
|
1020
|
-
persistedDate: result.task.scheduledDate,
|
|
1021
|
-
persistedWeekKey: result.task.scheduledWeekKey,
|
|
1022
|
-
persistedOrderInDay: result.task.orderInDay ?? null
|
|
1023
|
-
},
|
|
1024
|
-
warnings: result.warnings,
|
|
1025
|
-
task: result.task
|
|
1026
|
-
}, null, 2)
|
|
1027
|
-
}],
|
|
1028
|
-
};
|
|
1029
|
-
}
|
|
1030
|
-
case "unschedule_task": {
|
|
1031
|
-
const { id } = args;
|
|
1032
|
-
if (!id || typeof id !== 'string')
|
|
1033
|
-
throw new Error('id is required');
|
|
1034
|
-
const result = core.updateTaskSchedule(id, { scheduledDate: null, orderInDay: null }, ACTIVE_WORKSPACE_ID);
|
|
1035
|
-
if (!result) {
|
|
1036
|
-
throw new Error(`Task ${id} not found`);
|
|
1037
|
-
}
|
|
1038
|
-
await notifyResourceMutation({
|
|
1039
|
-
taskIds: [id],
|
|
1040
|
-
includeTasks: true,
|
|
1041
|
-
includeStats: true,
|
|
1042
|
-
});
|
|
1043
|
-
return {
|
|
1044
|
-
content: [{
|
|
1045
|
-
type: "text",
|
|
1046
|
-
text: JSON.stringify({
|
|
1047
|
-
success: true,
|
|
1048
|
-
scheduling: {
|
|
1049
|
-
taskId: id,
|
|
1050
|
-
requestedDate: null,
|
|
1051
|
-
persistedDate: result.task.scheduledDate,
|
|
1052
|
-
persistedWeekKey: result.task.scheduledWeekKey,
|
|
1053
|
-
persistedOrderInDay: result.task.orderInDay ?? null
|
|
1054
|
-
},
|
|
1055
|
-
warnings: result.warnings,
|
|
1056
|
-
task: result.task
|
|
1057
|
-
}, null, 2)
|
|
1058
|
-
}],
|
|
1059
|
-
};
|
|
1060
|
-
}
|
|
1061
|
-
case "reorder_scheduled_tasks": {
|
|
1062
|
-
const { moves } = args;
|
|
1063
|
-
if (!Array.isArray(moves)) {
|
|
1064
|
-
throw new Error('moves must be an array');
|
|
1065
|
-
}
|
|
1066
|
-
const result = core.reorderScheduledTasks(moves, ACTIVE_WORKSPACE_ID);
|
|
1067
|
-
await notifyResourceMutation({
|
|
1068
|
-
taskIds: moves.map((m) => m?.id).filter((id) => typeof id === 'string'),
|
|
1069
|
-
includeTasks: true,
|
|
1070
|
-
includeStats: true,
|
|
1071
|
-
});
|
|
1072
|
-
return {
|
|
1073
|
-
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
1074
|
-
};
|
|
1075
|
-
}
|
|
1076
|
-
case "bulk_carryover": {
|
|
1077
|
-
const { fromWeek, toWeek, mode, includeStatuses = ['task', 'in-progress', 'review', 'on-hold'] } = args;
|
|
1078
|
-
if (!fromWeek || typeof fromWeek !== 'string')
|
|
1079
|
-
throw new Error('fromWeek is required');
|
|
1080
|
-
if (!toWeek || typeof toWeek !== 'string')
|
|
1081
|
-
throw new Error('toWeek is required');
|
|
1082
|
-
if (mode !== 'day' && mode !== 'week')
|
|
1083
|
-
throw new Error('mode must be "day" or "week"');
|
|
1084
|
-
const shiftDays = mode === 'day' ? 1 : 7;
|
|
1085
|
-
const activeStatuses = Array.isArray(includeStatuses) ? includeStatuses.map((s) => String(s)) : [];
|
|
1086
|
-
const tasks = core.listTasks(ACTIVE_WORKSPACE_ID).tasks.filter((task) => {
|
|
1087
|
-
if (!task.scheduledDate)
|
|
1088
|
-
return false;
|
|
1089
|
-
if (task.scheduledWeekKey !== fromWeek)
|
|
1090
|
-
return false;
|
|
1091
|
-
if (task.status === 'done' || task.status === 'cancelled')
|
|
1092
|
-
return false;
|
|
1093
|
-
return activeStatuses.length === 0 || activeStatuses.includes(task.status);
|
|
1094
|
-
});
|
|
1095
|
-
const updates = [];
|
|
1096
|
-
for (const task of tasks) {
|
|
1097
|
-
const nextDate = addDaysDateOnly(String(task.scheduledDate), shiftDays);
|
|
1098
|
-
if (!nextDate)
|
|
1099
|
-
continue;
|
|
1100
|
-
core.updateTaskSchedule(task.id, { scheduledDate: nextDate, orderInDay: task.orderInDay ?? undefined }, ACTIVE_WORKSPACE_ID);
|
|
1101
|
-
updates.push({ id: task.id, from: String(task.scheduledDate), to: nextDate });
|
|
1102
|
-
}
|
|
1103
|
-
await notifyResourceMutation({
|
|
1104
|
-
taskIds: updates.map(u => u.id),
|
|
1105
|
-
includeTasks: true,
|
|
1106
|
-
includeStats: true,
|
|
1107
|
-
});
|
|
1108
|
-
return {
|
|
1109
|
-
content: [{
|
|
1110
|
-
type: "text",
|
|
1111
|
-
text: JSON.stringify({
|
|
1112
|
-
fromWeek,
|
|
1113
|
-
toWeek,
|
|
1114
|
-
mode,
|
|
1115
|
-
shiftedDays: shiftDays,
|
|
1116
|
-
moved: updates.length,
|
|
1117
|
-
updates
|
|
1118
|
-
}, null, 2)
|
|
1119
|
-
}],
|
|
1120
|
-
};
|
|
1121
|
-
}
|
|
1122
|
-
case "set_schedule_preferences": {
|
|
1123
|
-
const { showWeekends, isCalendarSidebarOpen, dailyCapacity } = args;
|
|
1124
|
-
const schedulePreferences = {
|
|
1125
|
-
...(typeof showWeekends === 'boolean' ? { showWeekends } : {}),
|
|
1126
|
-
...(typeof isCalendarSidebarOpen === 'boolean' ? { isCalendarSidebarOpen } : {}),
|
|
1127
|
-
...(dailyCapacity && typeof dailyCapacity === 'object' ? { dailyCapacity } : {})
|
|
1128
|
-
};
|
|
1129
|
-
core.updateGlobalSettings({ schedulePreferences });
|
|
1130
|
-
const updated = core.getGlobalSettings();
|
|
1131
|
-
await notifyResourceMutation({
|
|
1132
|
-
includeConfig: true,
|
|
1133
|
-
});
|
|
1134
|
-
return {
|
|
1135
|
-
content: [{
|
|
1136
|
-
type: "text",
|
|
1137
|
-
text: JSON.stringify({
|
|
1138
|
-
success: true,
|
|
1139
|
-
schedulePreferences: updated.schedulePreferences || {}
|
|
1140
|
-
}, null, 2)
|
|
1141
|
-
}],
|
|
1142
|
-
};
|
|
1143
|
-
}
|
|
1144
|
-
case "create_task": {
|
|
1145
|
-
const createArgs = normalizeScheduleFieldAliases(args);
|
|
1146
|
-
const createAssigneeInput = createArgs.assignee ?? createArgs.owner;
|
|
1147
|
-
const normalized = {
|
|
1148
|
-
category: resolveStringOption('category', createArgs.category, core.getCategories().map(c => ({ value: c.value, label: c.label }))),
|
|
1149
|
-
type: resolveStringOption('type', createArgs.type, core.getTypes().map(t => ({ value: t.value, label: t.label }))),
|
|
1150
|
-
priority: resolveNumberOption('priority', createArgs.priority, core.getPriorities().map(p => ({ value: p.value, label: p.label }))),
|
|
1151
|
-
approach: resolveStringOption('approach', createArgs.approach, core.getApproaches().map(a => ({ value: a.value, label: a.label }))),
|
|
1152
|
-
assignee: resolveStringOption('assignee', createAssigneeInput, [...ASSIGNEE_OPTIONS]),
|
|
1153
|
-
status: resolveStringOption('status', createArgs.status, STATUS_OPTIONS),
|
|
1154
|
-
complexity: resolveNumberOption('complexity', createArgs.complexity, COMPLEXITY_OPTIONS)
|
|
1155
|
-
};
|
|
1156
|
-
const task = core.createTask({
|
|
1157
|
-
...createArgs,
|
|
1158
|
-
...normalized,
|
|
1159
|
-
createdBy: 'AI Agent'
|
|
1160
|
-
}, { workspaceId: ACTIVE_WORKSPACE_ID });
|
|
1161
|
-
if (task?.id) {
|
|
1162
|
-
const nextParentId = typeof task.parentTaskId === 'string' && task.parentTaskId.trim().length > 0
|
|
1163
|
-
? task.parentTaskId.trim()
|
|
1164
|
-
: null;
|
|
1165
|
-
const auditComment = buildRelationshipAuditComment(task.id, null, nextParentId);
|
|
1166
|
-
if (auditComment) {
|
|
1167
|
-
core.addComment(task.id, auditComment, 'ai', ACTIVE_WORKSPACE_ID);
|
|
1168
|
-
}
|
|
1169
|
-
}
|
|
1170
|
-
await notifyResourceMutation({
|
|
1171
|
-
taskIds: task?.id ? [task.id] : [],
|
|
1172
|
-
includeTasks: true,
|
|
1173
|
-
includeStats: true,
|
|
1174
|
-
});
|
|
1175
|
-
return {
|
|
1176
|
-
content: [{ type: "text", text: JSON.stringify(task, null, 2) }],
|
|
1177
|
-
};
|
|
1178
|
-
}
|
|
1179
|
-
case "update_task": {
|
|
1180
|
-
const normalizedArgs = normalizeScheduleFieldAliases(args);
|
|
1181
|
-
const { id, status, category, priority, type, approach, assignee, owner, complexity, ...updates } = normalizedArgs;
|
|
1182
|
-
const existingTask = core.getTask(id, ACTIVE_WORKSPACE_ID);
|
|
1183
|
-
if (!existingTask) {
|
|
1184
|
-
throw new Error(`Task ${id} not found`);
|
|
1185
|
-
}
|
|
1186
|
-
// Safety Guard: Remove any fields that are set to our internal placeholder "%SAME%"
|
|
1187
|
-
Object.keys(updates).forEach(key => {
|
|
1188
|
-
const value = updates[key];
|
|
1189
|
-
if (typeof value === 'string' && (value === '%SAME%' || value === '%SAME% ')) {
|
|
1190
|
-
delete updates[key];
|
|
1191
|
-
}
|
|
1192
|
-
});
|
|
1193
|
-
// Explicitly protect ID from being updated via the updates object
|
|
1194
|
-
delete updates.id;
|
|
1195
|
-
delete updates.owner;
|
|
1196
|
-
const updateAssigneeInput = assignee ?? owner;
|
|
1197
|
-
const normalized = {
|
|
1198
|
-
category: resolveStringOption('category', category, core.getCategories().map(c => ({ value: c.value, label: c.label }))),
|
|
1199
|
-
type: resolveStringOption('type', type, core.getTypes().map(t => ({ value: t.value, label: t.label }))),
|
|
1200
|
-
priority: resolveNumberOption('priority', priority, core.getPriorities().map(p => ({ value: p.value, label: p.label }))),
|
|
1201
|
-
approach: resolveStringOption('approach', approach, core.getApproaches().map(a => ({ value: a.value, label: a.label }))),
|
|
1202
|
-
assignee: resolveStringOption('assignee', updateAssigneeInput, [...ASSIGNEE_OPTIONS]),
|
|
1203
|
-
status: resolveStringOption('status', status, STATUS_OPTIONS),
|
|
1204
|
-
complexity: resolveNumberOption('complexity', complexity, COMPLEXITY_OPTIONS)
|
|
1205
|
-
};
|
|
1206
|
-
const finalUpdates = {
|
|
1207
|
-
...updates,
|
|
1208
|
-
...(normalized.category !== undefined ? { category: normalized.category } : {}),
|
|
1209
|
-
...(normalized.type !== undefined ? { type: normalized.type } : {}),
|
|
1210
|
-
...(normalized.priority !== undefined ? { priority: normalized.priority } : {}),
|
|
1211
|
-
...(normalized.approach !== undefined ? { approach: normalized.approach } : {}),
|
|
1212
|
-
...(normalized.assignee !== undefined ? { assignee: normalized.assignee } : {}),
|
|
1213
|
-
...(normalized.complexity !== undefined ? { complexity: normalized.complexity } : {})
|
|
1214
|
-
};
|
|
1215
|
-
// If status is provided, update it. This NO LONGER auto-archives.
|
|
1216
|
-
if (normalized.status) {
|
|
1217
|
-
finalUpdates.status = normalized.status;
|
|
1218
|
-
}
|
|
1219
|
-
const updated = core.updateTask(id, finalUpdates, ACTIVE_WORKSPACE_ID);
|
|
1220
|
-
if (!updated) {
|
|
1221
|
-
throw new Error(`Task ${id} not found`);
|
|
1222
|
-
}
|
|
1223
|
-
const previousParentId = typeof existingTask.parentTaskId === 'string' && existingTask.parentTaskId.trim().length > 0
|
|
1224
|
-
? existingTask.parentTaskId.trim()
|
|
1225
|
-
: null;
|
|
1226
|
-
const nextParentId = typeof updated.parentTaskId === 'string' && updated.parentTaskId.trim().length > 0
|
|
1227
|
-
? updated.parentTaskId.trim()
|
|
1228
|
-
: null;
|
|
1229
|
-
const auditComment = buildRelationshipAuditComment(id, previousParentId, nextParentId);
|
|
1230
|
-
if (auditComment) {
|
|
1231
|
-
core.addComment(id, auditComment, 'ai', ACTIVE_WORKSPACE_ID);
|
|
1232
|
-
}
|
|
1233
|
-
await notifyResourceMutation({
|
|
1234
|
-
taskIds: [id],
|
|
1235
|
-
includeTasks: true,
|
|
1236
|
-
includeStats: true,
|
|
1237
|
-
});
|
|
1238
|
-
return {
|
|
1239
|
-
content: [{ type: "text", text: JSON.stringify(updated, null, 2) }],
|
|
1240
|
-
};
|
|
1241
|
-
}
|
|
1242
|
-
case "assign_task": {
|
|
1243
|
-
const { id, assignee } = args;
|
|
1244
|
-
if (!id || typeof id !== 'string')
|
|
1245
|
-
throw new Error('id is required');
|
|
1246
|
-
const resolvedAssignee = resolveStringOption('assignee', assignee, [...ASSIGNEE_OPTIONS]);
|
|
1247
|
-
if (!resolvedAssignee)
|
|
1248
|
-
throw new Error('assignee is required');
|
|
1249
|
-
const updated = core.updateTask(id, { assignee: resolvedAssignee }, ACTIVE_WORKSPACE_ID);
|
|
1250
|
-
if (!updated)
|
|
1251
|
-
throw new Error(`Task ${id} not found`);
|
|
1252
|
-
await notifyResourceMutation({
|
|
1253
|
-
taskIds: [id],
|
|
1254
|
-
includeTasks: true,
|
|
1255
|
-
includeStats: true,
|
|
1256
|
-
});
|
|
1257
|
-
return {
|
|
1258
|
-
content: [{ type: "text", text: JSON.stringify(updated, null, 2) }],
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
case "bulk_assign_tasks": {
|
|
1262
|
-
const { ids, assignee } = args;
|
|
1263
|
-
const list = Array.isArray(ids) ? ids : [];
|
|
1264
|
-
if (list.length === 0)
|
|
1265
|
-
throw new Error('ids array is required');
|
|
1266
|
-
const resolvedAssignee = resolveStringOption('assignee', assignee, [...ASSIGNEE_OPTIONS]);
|
|
1267
|
-
if (!resolvedAssignee)
|
|
1268
|
-
throw new Error('assignee is required');
|
|
1269
|
-
const updates = list.map((id) => ({ id, assignee: resolvedAssignee }));
|
|
1270
|
-
const preview = core.bulkUpdateFieldsPreview(updates, ACTIVE_WORKSPACE_ID);
|
|
1271
|
-
const changed = [];
|
|
1272
|
-
const errors = [];
|
|
1273
|
-
for (const skipped of preview.skipped) {
|
|
1274
|
-
if (skipped.statusCode >= 400) {
|
|
1275
|
-
errors.push({
|
|
1276
|
-
index: skipped.index,
|
|
1277
|
-
id: skipped.id,
|
|
1278
|
-
message: skipped.message,
|
|
1279
|
-
statusCode: skipped.statusCode,
|
|
1280
|
-
code: skipped.code
|
|
1281
|
-
});
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
for (const item of preview.toApply) {
|
|
1285
|
-
const updated = core.updateTask(item.id, item.fields, ACTIVE_WORKSPACE_ID);
|
|
1286
|
-
if (!updated) {
|
|
1287
|
-
errors.push({ index: item.index, id: item.id, message: 'Task not found', statusCode: 404, code: 'TASK_NOT_FOUND' });
|
|
1288
|
-
continue;
|
|
1289
|
-
}
|
|
1290
|
-
changed.push({ id: updated.id, assignee: updated.assignee || 'unassigned' });
|
|
1291
|
-
}
|
|
1292
|
-
const summary = buildBatchSummary({
|
|
1293
|
-
operation: 'bulk-assign-tasks',
|
|
1294
|
-
total: list.length,
|
|
1295
|
-
succeeded: changed.length
|
|
1296
|
-
});
|
|
1297
|
-
await notifyResourceMutation({
|
|
1298
|
-
taskIds: list.filter((id) => typeof id === 'string'),
|
|
1299
|
-
includeTasks: true,
|
|
1300
|
-
includeStats: true,
|
|
1301
|
-
});
|
|
1302
|
-
return {
|
|
1303
|
-
content: [{
|
|
1304
|
-
type: "text",
|
|
1305
|
-
text: JSON.stringify({
|
|
1306
|
-
success: errors.length === 0,
|
|
1307
|
-
summary,
|
|
1308
|
-
results: {
|
|
1309
|
-
assigned: changed,
|
|
1310
|
-
preflight: {
|
|
1311
|
-
deduped: preview.deduped,
|
|
1312
|
-
skipped_noop: preview.skipped.filter((s) => s.code === 'NO_CHANGES' || s.code === 'DUPLICATE_SUPERSEDED').length
|
|
1313
|
-
}
|
|
1314
|
-
},
|
|
1315
|
-
errors
|
|
1316
|
-
}, null, 2)
|
|
1317
|
-
}],
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1320
|
-
case "archive_task": {
|
|
1321
|
-
const { id, status, reason } = args;
|
|
1322
|
-
const isCancelled = status === 'cancelled';
|
|
1323
|
-
const task = core.archiveTask(id, isCancelled, reason, ACTIVE_WORKSPACE_ID);
|
|
1324
|
-
if (!task) {
|
|
1325
|
-
throw new Error(`Task ${id} not found`);
|
|
1326
|
-
}
|
|
1327
|
-
await notifyResourceMutation({
|
|
1328
|
-
taskIds: [id],
|
|
1329
|
-
includeTasks: true,
|
|
1330
|
-
includeStats: true,
|
|
1331
|
-
});
|
|
1332
|
-
return {
|
|
1333
|
-
content: [{ type: "text", text: `Task ${id} archived as ${status}` }],
|
|
1334
|
-
};
|
|
1335
|
-
}
|
|
1336
|
-
case "list_skills": {
|
|
1337
|
-
const skills = core.listSpecialists();
|
|
1338
|
-
return {
|
|
1339
|
-
content: [{ type: "text", text: JSON.stringify(skills, null, 2) }],
|
|
1340
|
-
};
|
|
1341
|
-
}
|
|
1342
|
-
case "get_config": {
|
|
1343
|
-
return {
|
|
1344
|
-
content: [{
|
|
1345
|
-
type: "text",
|
|
1346
|
-
text: JSON.stringify({
|
|
1347
|
-
categories: core.getCategories(),
|
|
1348
|
-
types: core.getTypes(),
|
|
1349
|
-
priorities: core.getPriorities(),
|
|
1350
|
-
approaches: core.getApproaches(),
|
|
1351
|
-
complexities: COMPLEXITY_OPTIONS
|
|
1352
|
-
}, null, 2)
|
|
1353
|
-
}],
|
|
1354
|
-
};
|
|
1355
|
-
}
|
|
1356
|
-
case "update_categories": {
|
|
1357
|
-
const { categories } = args;
|
|
1358
|
-
core.updateCategories(categories);
|
|
1359
|
-
await notifyResourceMutation({
|
|
1360
|
-
includeConfig: true,
|
|
1361
|
-
includeTasks: true,
|
|
1362
|
-
includeStats: true,
|
|
1363
|
-
});
|
|
1364
|
-
return {
|
|
1365
|
-
content: [{ type: "text", text: "Categories updated" }],
|
|
1366
|
-
};
|
|
1367
|
-
}
|
|
1368
|
-
case "add_comment": {
|
|
1369
|
-
const { id, text, author } = args;
|
|
1370
|
-
const validation = validateStructuredCommentForAdd(text);
|
|
1371
|
-
if (!validation.ok) {
|
|
1372
|
-
throw new Error(validation.message);
|
|
1373
|
-
}
|
|
1374
|
-
const updated = core.addComment(id, text, author, ACTIVE_WORKSPACE_ID);
|
|
1375
|
-
if (!updated) {
|
|
1376
|
-
throw new Error(`Task ${id} not found`);
|
|
1377
|
-
}
|
|
1378
|
-
await notifyResourceMutation({
|
|
1379
|
-
taskIds: [id],
|
|
1380
|
-
includeTasks: true,
|
|
1381
|
-
});
|
|
1382
|
-
return {
|
|
1383
|
-
content: [{ type: "text", text: `Comment added to ${id}` }],
|
|
1384
|
-
};
|
|
1385
|
-
}
|
|
1386
|
-
case "attach_context_file": {
|
|
1387
|
-
const { id, path: inputPath, caption } = args;
|
|
1388
|
-
if (!id)
|
|
1389
|
-
throw new Error("id is required");
|
|
1390
|
-
if (!inputPath || typeof inputPath !== 'string')
|
|
1391
|
-
throw new Error("path is required");
|
|
1392
|
-
const task = core.getTask(id, ACTIVE_WORKSPACE_ID);
|
|
1393
|
-
if (!task) {
|
|
1394
|
-
throw new Error(`Task ${id} not found`);
|
|
1395
|
-
}
|
|
1396
|
-
const trimmedPath = inputPath.trim();
|
|
1397
|
-
if (!trimmedPath)
|
|
1398
|
-
throw new Error("path cannot be empty");
|
|
1399
|
-
const now = new Date().toISOString();
|
|
1400
|
-
const safeCaption = typeof caption === 'string' && caption.trim().length > 0
|
|
1401
|
-
? caption.trim()
|
|
1402
|
-
: undefined;
|
|
1403
|
-
const { projectRoot } = core.getPaths();
|
|
1404
|
-
const attachment = (() => {
|
|
1405
|
-
if (isHttpUrl(trimmedPath)) {
|
|
1406
|
-
return {
|
|
1407
|
-
path: trimmedPath,
|
|
1408
|
-
caption: safeCaption || trimmedPath,
|
|
1409
|
-
timestamp: now
|
|
1410
|
-
};
|
|
1411
|
-
}
|
|
1412
|
-
const resolved = path.isAbsolute(trimmedPath)
|
|
1413
|
-
? path.resolve(trimmedPath)
|
|
1414
|
-
: path.resolve(projectRoot, trimmedPath);
|
|
1415
|
-
if (!fs.existsSync(resolved)) {
|
|
1416
|
-
throw new Error(`File not found: ${trimmedPath}`);
|
|
1417
|
-
}
|
|
1418
|
-
const real = fs.realpathSync(resolved);
|
|
1419
|
-
if (!isWithinRoot(real, projectRoot)) {
|
|
1420
|
-
throw new Error("Linked file must be within project root");
|
|
1421
|
-
}
|
|
1422
|
-
if (!fs.statSync(real).isFile()) {
|
|
1423
|
-
throw new Error(`Path is not a file: ${trimmedPath}`);
|
|
1424
|
-
}
|
|
1425
|
-
const relativePath = toPosixPath(path.relative(projectRoot, real));
|
|
1426
|
-
if (relativePath.endsWith('.md')) {
|
|
1427
|
-
const content = fs.readFileSync(real, 'utf8');
|
|
1428
|
-
const validation = validateStructuredDocForAttach(relativePath, content);
|
|
1429
|
-
if (!validation.ok) {
|
|
1430
|
-
throw new Error(validation.message);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
return {
|
|
1434
|
-
path: `/api/taskforce/context-link?path=${encodeURIComponent(relativePath)}`,
|
|
1435
|
-
fsPath: relativePath,
|
|
1436
|
-
caption: safeCaption || path.basename(real),
|
|
1437
|
-
timestamp: now
|
|
1438
|
-
};
|
|
1439
|
-
})();
|
|
1440
|
-
const existing = Array.isArray(task.attachments)
|
|
1441
|
-
? task.attachments
|
|
1442
|
-
: (Array.isArray(task.screenshots) ? task.screenshots : []);
|
|
1443
|
-
const duplicate = existing.some((item) => {
|
|
1444
|
-
if (typeof item === 'string') {
|
|
1445
|
-
return item === attachment.path || (!!attachment.fsPath && item === attachment.fsPath);
|
|
1446
|
-
}
|
|
1447
|
-
if (!item || typeof item !== 'object')
|
|
1448
|
-
return false;
|
|
1449
|
-
if (item.path === attachment.path)
|
|
1450
|
-
return true;
|
|
1451
|
-
if (attachment.fsPath && item.fsPath === attachment.fsPath)
|
|
1452
|
-
return true;
|
|
1453
|
-
return false;
|
|
1454
|
-
});
|
|
1455
|
-
if (duplicate) {
|
|
1456
|
-
return {
|
|
1457
|
-
content: [{ type: "text", text: `Context file already attached to ${id}` }],
|
|
1458
|
-
};
|
|
1459
|
-
}
|
|
1460
|
-
const updated = core.updateTask(id, {
|
|
1461
|
-
attachments: [...existing, attachment]
|
|
1462
|
-
}, ACTIVE_WORKSPACE_ID);
|
|
1463
|
-
if (!updated) {
|
|
1464
|
-
throw new Error(`Task ${id} not found`);
|
|
1465
|
-
}
|
|
1466
|
-
await notifyResourceMutation({
|
|
1467
|
-
taskIds: [id],
|
|
1468
|
-
includeTasks: true,
|
|
1469
|
-
});
|
|
1470
|
-
return {
|
|
1471
|
-
content: [{ type: "text", text: `Attached context file to ${id}\n${JSON.stringify(attachment, null, 2)}` }],
|
|
1472
|
-
};
|
|
1473
|
-
}
|
|
1474
|
-
case "save_task_attachment": {
|
|
1475
|
-
const { id, filename, content, sourcePath, caption, overwrite = false } = args;
|
|
1476
|
-
if (!id)
|
|
1477
|
-
throw new Error("id is required");
|
|
1478
|
-
if (!filename || typeof filename !== 'string')
|
|
1479
|
-
throw new Error("filename is required");
|
|
1480
|
-
const hasContent = typeof content === 'string';
|
|
1481
|
-
const hasSourcePath = typeof sourcePath === 'string' && sourcePath.trim().length > 0;
|
|
1482
|
-
if (hasContent === hasSourcePath) {
|
|
1483
|
-
throw new Error("Provide exactly one of: content or sourcePath");
|
|
1484
|
-
}
|
|
1485
|
-
const task = core.getTask(id, ACTIVE_WORKSPACE_ID);
|
|
1486
|
-
if (!task)
|
|
1487
|
-
throw new Error(`Task ${id} not found`);
|
|
1488
|
-
const now = new Date().toISOString();
|
|
1489
|
-
const safeCaption = typeof caption === 'string' && caption.trim().length > 0
|
|
1490
|
-
? caption.trim()
|
|
1491
|
-
: undefined;
|
|
1492
|
-
const { projectRoot, taskDataDir } = core.getPaths();
|
|
1493
|
-
const taskPathSegment = sanitizeTaskIdForPath(id);
|
|
1494
|
-
const attachmentsDir = path.join(taskDataDir, taskPathSegment, 'attachments');
|
|
1495
|
-
fs.mkdirSync(attachmentsDir, { recursive: true });
|
|
1496
|
-
let safeFilename = sanitizeFilenameForPath(filename);
|
|
1497
|
-
let destinationPath = path.join(attachmentsDir, safeFilename);
|
|
1498
|
-
if (!overwrite) {
|
|
1499
|
-
destinationPath = nextAvailablePath(destinationPath);
|
|
1500
|
-
safeFilename = path.basename(destinationPath);
|
|
1501
|
-
}
|
|
1502
|
-
if (hasContent) {
|
|
1503
|
-
fs.writeFileSync(destinationPath, content, 'utf8');
|
|
1504
|
-
}
|
|
1505
|
-
else {
|
|
1506
|
-
const trimmedSource = sourcePath.trim();
|
|
1507
|
-
const sourceResolved = path.isAbsolute(trimmedSource)
|
|
1508
|
-
? path.resolve(trimmedSource)
|
|
1509
|
-
: path.resolve(projectRoot, trimmedSource);
|
|
1510
|
-
if (!fs.existsSync(sourceResolved)) {
|
|
1511
|
-
throw new Error(`File not found: ${trimmedSource}`);
|
|
1512
|
-
}
|
|
1513
|
-
const sourceReal = fs.realpathSync(sourceResolved);
|
|
1514
|
-
if (!isWithinRoot(sourceReal, projectRoot)) {
|
|
1515
|
-
throw new Error("sourcePath must be within project root");
|
|
1516
|
-
}
|
|
1517
|
-
if (!fs.statSync(sourceReal).isFile()) {
|
|
1518
|
-
throw new Error(`Path is not a file: ${trimmedSource}`);
|
|
1519
|
-
}
|
|
1520
|
-
fs.copyFileSync(sourceReal, destinationPath);
|
|
1521
|
-
}
|
|
1522
|
-
const relativePath = toPosixPath(path.relative(projectRoot, destinationPath));
|
|
1523
|
-
if (relativePath.endsWith('.md')) {
|
|
1524
|
-
const fileContent = fs.readFileSync(destinationPath, 'utf8');
|
|
1525
|
-
const validation = validateStructuredDocForAttach(relativePath, fileContent);
|
|
1526
|
-
if (!validation.ok) {
|
|
1527
|
-
throw new Error(validation.message);
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
const attachment = {
|
|
1531
|
-
path: `/api/taskforce/context-link?path=${encodeURIComponent(relativePath)}`,
|
|
1532
|
-
fsPath: relativePath,
|
|
1533
|
-
caption: safeCaption || safeFilename,
|
|
1534
|
-
timestamp: now
|
|
1535
|
-
};
|
|
1536
|
-
const existing = Array.isArray(task.attachments)
|
|
1537
|
-
? task.attachments
|
|
1538
|
-
: (Array.isArray(task.screenshots) ? task.screenshots : []);
|
|
1539
|
-
const duplicate = existing.some((item) => {
|
|
1540
|
-
if (typeof item === 'string') {
|
|
1541
|
-
return item === attachment.path || item === attachment.fsPath;
|
|
1542
|
-
}
|
|
1543
|
-
if (!item || typeof item !== 'object')
|
|
1544
|
-
return false;
|
|
1545
|
-
if (item.path === attachment.path)
|
|
1546
|
-
return true;
|
|
1547
|
-
if (item.fsPath === attachment.fsPath)
|
|
1548
|
-
return true;
|
|
1549
|
-
return false;
|
|
1550
|
-
});
|
|
1551
|
-
if (duplicate) {
|
|
1552
|
-
return {
|
|
1553
|
-
content: [{ type: "text", text: `Task attachment saved for ${id}\n${JSON.stringify(attachment, null, 2)}\nAlready attached.` }],
|
|
1554
|
-
};
|
|
1555
|
-
}
|
|
1556
|
-
const updated = core.updateTask(id, {
|
|
1557
|
-
attachments: [...existing, attachment]
|
|
1558
|
-
}, ACTIVE_WORKSPACE_ID);
|
|
1559
|
-
if (!updated) {
|
|
1560
|
-
throw new Error(`Task ${id} not found`);
|
|
1561
|
-
}
|
|
1562
|
-
await notifyResourceMutation({
|
|
1563
|
-
taskIds: [id],
|
|
1564
|
-
includeTasks: true,
|
|
1565
|
-
});
|
|
1566
|
-
return {
|
|
1567
|
-
content: [{ type: "text", text: `Task attachment saved and attached to ${id}\n${JSON.stringify(attachment, null, 2)}` }],
|
|
1568
|
-
};
|
|
1569
|
-
}
|
|
1570
|
-
case "list_archive": {
|
|
1571
|
-
const { format = "markdown" } = args;
|
|
1572
|
-
const archive = core.listArchive(ACTIVE_WORKSPACE_ID);
|
|
1573
|
-
if (format === "json") {
|
|
1574
|
-
return {
|
|
1575
|
-
content: [{ type: "text", text: JSON.stringify(archive.archived, null, 2) }],
|
|
1576
|
-
};
|
|
1577
|
-
}
|
|
1578
|
-
return {
|
|
1579
|
-
content: [{ type: "text", text: renderTaskTable(archive.archived) }],
|
|
1580
|
-
};
|
|
1581
|
-
}
|
|
1582
|
-
case "unarchive_task": {
|
|
1583
|
-
const { id } = args;
|
|
1584
|
-
const task = core.unarchiveTask(id, ACTIVE_WORKSPACE_ID);
|
|
1585
|
-
if (!task) {
|
|
1586
|
-
throw new Error(`Task ${id} not found in archive`);
|
|
1587
|
-
}
|
|
1588
|
-
await notifyResourceMutation({
|
|
1589
|
-
taskIds: [id],
|
|
1590
|
-
includeTasks: true,
|
|
1591
|
-
includeStats: true,
|
|
1592
|
-
});
|
|
1593
|
-
return {
|
|
1594
|
-
content: [{ type: "text", text: `Task ${id} unarchived` }],
|
|
1595
|
-
};
|
|
1596
|
-
}
|
|
1597
|
-
case "bulk_archive": {
|
|
1598
|
-
const { ids, status = "done" } = args;
|
|
1599
|
-
const isCancellation = status === "cancelled";
|
|
1600
|
-
const list = Array.isArray(ids) ? ids : [];
|
|
1601
|
-
const archived = [];
|
|
1602
|
-
const errors = [];
|
|
1603
|
-
for (let i = 0; i < list.length; i++) {
|
|
1604
|
-
const id = list[i];
|
|
1605
|
-
try {
|
|
1606
|
-
const item = core.archiveTask(id, isCancellation, undefined, ACTIVE_WORKSPACE_ID);
|
|
1607
|
-
if (!item) {
|
|
1608
|
-
errors.push({ index: i, id, message: 'Task not found', statusCode: 404, code: 'TASK_NOT_FOUND' });
|
|
1609
|
-
continue;
|
|
1610
|
-
}
|
|
1611
|
-
archived.push(item);
|
|
1612
|
-
}
|
|
1613
|
-
catch (error) {
|
|
1614
|
-
errors.push({
|
|
1615
|
-
index: i,
|
|
1616
|
-
id,
|
|
1617
|
-
message: error?.message || 'Failed to archive task',
|
|
1618
|
-
statusCode: Number.isFinite(Number(error?.statusCode)) ? Number(error.statusCode) : 400,
|
|
1619
|
-
code: typeof error?.code === 'string' ? error.code : undefined
|
|
1620
|
-
});
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
const summary = buildBatchSummary({
|
|
1624
|
-
operation: 'bulk-archive',
|
|
1625
|
-
total: list.length,
|
|
1626
|
-
succeeded: archived.length
|
|
1627
|
-
});
|
|
1628
|
-
await notifyResourceMutation({
|
|
1629
|
-
taskIds: list,
|
|
1630
|
-
includeTasks: true,
|
|
1631
|
-
includeStats: true,
|
|
1632
|
-
});
|
|
1633
|
-
return {
|
|
1634
|
-
content: [{
|
|
1635
|
-
type: "text",
|
|
1636
|
-
text: JSON.stringify({
|
|
1637
|
-
success: errors.length === 0,
|
|
1638
|
-
summary,
|
|
1639
|
-
results: { archived },
|
|
1640
|
-
errors
|
|
1641
|
-
}, null, 2)
|
|
1642
|
-
}],
|
|
1643
|
-
};
|
|
1644
|
-
}
|
|
1645
|
-
case "update_types": {
|
|
1646
|
-
const { types } = args;
|
|
1647
|
-
core.updateTypes(types);
|
|
1648
|
-
await notifyResourceMutation({
|
|
1649
|
-
includeConfig: true,
|
|
1650
|
-
includeTasks: true,
|
|
1651
|
-
includeStats: true,
|
|
1652
|
-
});
|
|
1653
|
-
return {
|
|
1654
|
-
content: [{ type: "text", text: "Task types updated" }],
|
|
1655
|
-
};
|
|
1656
|
-
}
|
|
1657
|
-
case "bulk_update_type": {
|
|
1658
|
-
const { fromType, toType } = args;
|
|
1659
|
-
const count = core.bulkUpdateType(fromType, toType, ACTIVE_WORKSPACE_ID);
|
|
1660
|
-
await notifyResourceMutation({
|
|
1661
|
-
includeTasks: true,
|
|
1662
|
-
includeStats: true,
|
|
1663
|
-
});
|
|
1664
|
-
return {
|
|
1665
|
-
content: [{ type: "text", text: `Updated ${count} items from ${fromType} to ${toType}` }],
|
|
1666
|
-
};
|
|
1667
|
-
}
|
|
1668
|
-
case "bulk_update_fields": {
|
|
1669
|
-
const { updates } = args;
|
|
1670
|
-
const list = Array.isArray(updates) ? updates : [];
|
|
1671
|
-
// Validate all updates before applying
|
|
1672
|
-
for (const update of list) {
|
|
1673
|
-
const assigneeInput = update.assignee ?? update.owner;
|
|
1674
|
-
update.category = resolveStringOption('category', update.category, core.getCategories().map(c => ({ value: c.value, label: c.label })));
|
|
1675
|
-
update.type = resolveStringOption('type', update.type, core.getTypes().map(t => ({ value: t.value, label: t.label })));
|
|
1676
|
-
update.priority = resolveNumberOption('priority', update.priority, core.getPriorities().map(p => ({ value: p.value, label: p.label })));
|
|
1677
|
-
update.approach = resolveStringOption('approach', update.approach, core.getApproaches().map(a => ({ value: a.value, label: a.label })));
|
|
1678
|
-
update.assignee = resolveStringOption('assignee', assigneeInput, [...ASSIGNEE_OPTIONS]);
|
|
1679
|
-
delete update.owner;
|
|
1680
|
-
update.status = resolveStringOption('status', update.status, STATUS_OPTIONS);
|
|
1681
|
-
update.complexity = resolveNumberOption('complexity', update.complexity, COMPLEXITY_OPTIONS);
|
|
1682
|
-
}
|
|
1683
|
-
const preview = core.bulkUpdateFieldsPreview(list, ACTIVE_WORKSPACE_ID);
|
|
1684
|
-
const changed = [];
|
|
1685
|
-
const errors = [];
|
|
1686
|
-
for (const skipped of preview.skipped) {
|
|
1687
|
-
if (skipped.statusCode >= 400) {
|
|
1688
|
-
errors.push({
|
|
1689
|
-
index: skipped.index,
|
|
1690
|
-
id: skipped.id,
|
|
1691
|
-
message: skipped.message,
|
|
1692
|
-
statusCode: skipped.statusCode,
|
|
1693
|
-
code: skipped.code
|
|
1694
|
-
});
|
|
1695
|
-
}
|
|
1696
|
-
}
|
|
1697
|
-
for (const item of preview.toApply) {
|
|
1698
|
-
const updated = core.updateTask(item.id, item.fields, ACTIVE_WORKSPACE_ID);
|
|
1699
|
-
if (!updated) {
|
|
1700
|
-
errors.push({ index: item.index, id: item.id, message: 'Task not found', statusCode: 404, code: 'TASK_NOT_FOUND' });
|
|
1701
|
-
continue;
|
|
1702
|
-
}
|
|
1703
|
-
changed.push({ id: item.id, fields: item.changedFields });
|
|
1704
|
-
}
|
|
1705
|
-
const summary = buildBatchSummary({
|
|
1706
|
-
operation: 'bulk-update-fields',
|
|
1707
|
-
total: list.length,
|
|
1708
|
-
succeeded: changed.length
|
|
1709
|
-
});
|
|
1710
|
-
await notifyResourceMutation({
|
|
1711
|
-
includeTasks: true,
|
|
1712
|
-
includeStats: true,
|
|
1713
|
-
});
|
|
1714
|
-
return {
|
|
1715
|
-
content: [{
|
|
1716
|
-
type: "text",
|
|
1717
|
-
text: JSON.stringify({
|
|
1718
|
-
success: errors.length === 0,
|
|
1719
|
-
summary,
|
|
1720
|
-
results: {
|
|
1721
|
-
changes: changed,
|
|
1722
|
-
preflight: {
|
|
1723
|
-
deduped: preview.deduped,
|
|
1724
|
-
skipped_noop: preview.skipped.filter((s) => s.code === 'NO_CHANGES' || s.code === 'DUPLICATE_SUPERSEDED').length,
|
|
1725
|
-
by_field: preview.byField,
|
|
1726
|
-
priority_before: preview.priorityBefore,
|
|
1727
|
-
priority_after: preview.priorityAfter
|
|
1728
|
-
}
|
|
1729
|
-
},
|
|
1730
|
-
errors
|
|
1731
|
-
}, null, 2)
|
|
1732
|
-
}],
|
|
1733
|
-
};
|
|
1734
|
-
}
|
|
1735
|
-
case "export_resources": {
|
|
1736
|
-
const { type, path, variables, environment } = args;
|
|
1737
|
-
const count = core.exportResources(type, path, variables, environment);
|
|
1738
|
-
return {
|
|
1739
|
-
content: [{ type: "text", text: `Exported ${count} ${type} to ${path}` }],
|
|
1740
|
-
};
|
|
1741
|
-
}
|
|
1742
|
-
case "get_paths": {
|
|
1743
|
-
const paths = core.getPaths();
|
|
1744
|
-
return {
|
|
1745
|
-
content: [{ type: "text", text: JSON.stringify(paths, null, 2) }],
|
|
1746
|
-
};
|
|
1747
|
-
}
|
|
1748
|
-
case "update_priorities": {
|
|
1749
|
-
const { priorities } = args;
|
|
1750
|
-
core.updatePriorities(priorities);
|
|
1751
|
-
await notifyResourceMutation({
|
|
1752
|
-
includeConfig: true,
|
|
1753
|
-
includeTasks: true,
|
|
1754
|
-
includeStats: true,
|
|
1755
|
-
});
|
|
1756
|
-
return {
|
|
1757
|
-
content: [{ type: "text", text: "Priorities updated" }],
|
|
1758
|
-
};
|
|
1759
|
-
}
|
|
1760
|
-
case "update_approaches": {
|
|
1761
|
-
const { approaches } = args;
|
|
1762
|
-
core.updateApproaches(approaches);
|
|
1763
|
-
await notifyResourceMutation({
|
|
1764
|
-
includeConfig: true,
|
|
1765
|
-
includeTasks: true,
|
|
1766
|
-
includeStats: true,
|
|
1767
|
-
});
|
|
1768
|
-
return {
|
|
1769
|
-
content: [{ type: "text", text: "Approaches updated" }],
|
|
1770
|
-
};
|
|
1771
|
-
}
|
|
1772
|
-
case "get_stats": {
|
|
1773
|
-
const stats = core.getStats(ACTIVE_WORKSPACE_ID);
|
|
1774
|
-
return {
|
|
1775
|
-
content: [{ type: "text", text: JSON.stringify(stats, null, 2) }],
|
|
1776
|
-
};
|
|
1777
|
-
}
|
|
1778
|
-
default:
|
|
1779
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
catch (error) {
|
|
1783
|
-
return {
|
|
1784
|
-
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
1785
|
-
isError: true,
|
|
1786
|
-
};
|
|
1787
|
-
}
|
|
1788
|
-
});
|
|
1789
|
-
/**
|
|
1790
|
-
* Start Server
|
|
1791
|
-
*/
|
|
1792
|
-
const transport = new StdioServerTransport();
|
|
1793
|
-
await server.connect(transport);
|
|
1
|
+
import { startTaskforceMcpStdioServer } from './runtime.js';
|
|
2
|
+
await startTaskforceMcpStdioServer();
|