@taskforcehq/taskforce 0.3.303 → 0.3.305
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -247
- package/dist/Taskforce.module.css +102 -5
- package/dist/TaskforceCore.js +635 -238
- package/dist/TaskforceCore.test.js +2243 -495
- package/dist/annotatedAttachments/service.d.ts +1 -1
- package/dist/annotatedAttachments/types.d.ts +1 -1
- package/dist/compat/workspaceSyncCompat.js +6 -0
- package/dist/components/features/AgentsModule.js +1 -1
- package/dist/components/features/AgentsModule.test.js +1 -1
- package/dist/components/features/DocumentIndex.d.ts +1 -1
- package/dist/components/features/DocumentIndex.js +1 -1
- package/dist/components/features/DocumentViewer.d.ts +1 -1
- package/dist/components/features/DocumentViewer.js +32 -9
- package/dist/components/features/DocumentWorkspace.d.ts +5 -22
- package/dist/components/features/DocumentWorkspace.js +12 -155
- package/dist/components/features/DocumentWorkspace.test.js +193 -6
- package/dist/components/features/TaskSettings.js +87 -41
- package/dist/components/features/TaskSettings.test.js +180 -40
- package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
- package/dist/components/features/documentWorkspaceModel.js +57 -0
- package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
- package/dist/components/features/useDocumentWorkspaceController.js +113 -0
- package/dist/components/task/TaskActionHeader.d.ts +2 -1
- package/dist/components/task/TaskActionHeader.js +3 -3
- package/dist/components/task/TaskActionHeader.test.js +8 -0
- package/dist/components/task/TaskCard.js +16 -1
- package/dist/components/task/TaskCard.test.js +31 -0
- package/dist/components/task/TaskForm.d.ts +9 -8
- package/dist/components/task/TaskForm.js +374 -219
- package/dist/components/task/TaskForm.test.js +482 -361
- package/dist/components/task/TaskKanban.d.ts +1 -1
- package/dist/components/task/TaskKanban.js +33 -161
- package/dist/components/task/TaskStatusActions.d.ts +6 -1
- package/dist/components/task/TaskStatusActions.js +8 -3
- package/dist/components/task/TaskStatusActions.test.js +9 -0
- package/dist/components/task/taskKanbanDropRules.d.ts +58 -0
- package/dist/components/task/taskKanbanDropRules.js +187 -0
- package/dist/components/task/taskKanbanDropRules.test.d.ts +1 -0
- package/dist/components/task/taskKanbanDropRules.test.js +114 -0
- package/dist/components/ui/Modal.d.ts +1 -1
- package/dist/components/ui/Modal.js +1 -0
- package/dist/components/views/AppShellHeader.js +5 -1
- package/dist/components/views/AppShellHeader.test.js +4 -0
- package/dist/components/views/PlanComparisonPage.d.ts +3 -2
- package/dist/components/views/PlanComparisonPage.js +9 -10
- package/dist/components/views/PlanComparisonPage.test.js +55 -41
- package/dist/components/views/PlansPage.d.ts +5 -1
- package/dist/components/views/PlansPage.js +150 -81
- package/dist/components/views/PlansPage.test.js +367 -41
- package/dist/components/views/StandaloneLayout.js +135 -54
- package/dist/components/views/WidgetView.js +11 -2
- package/dist/components/views/panels/FilterToolbar.test.js +6 -4
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +2 -14
- package/dist/components/views/standalone/modals/AccountHubModal.js +12 -14
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +24 -1
- package/dist/components/views/standalone/modals/SyncStatusModal.js +1 -1
- package/dist/config/envSchema.js +1 -1
- package/dist/core/AiProfileService.d.ts +6 -1
- package/dist/core/AiProfileService.js +161 -16
- package/dist/core/AiProfileService.test.js +3 -1
- package/dist/core/AiProfiles.test.js +200 -0
- package/dist/core/AuthTokenService.test.d.ts +1 -0
- package/dist/core/AuthTokenService.test.js +78 -0
- package/dist/core/DeletedTaskLifecycleService.d.ts +2 -1
- package/dist/core/EntitlementsPolicy.test.js +75 -13
- package/dist/core/PlanEntitlementService.d.ts +9 -1
- package/dist/core/PlanEntitlementService.js +144 -19
- package/dist/core/PlanVersionPolicy.test.js +19 -26
- package/dist/core/SignupMonetizationSettings.test.js +75 -15
- package/dist/core/SystemAdmin.test.js +212 -56
- package/dist/core/TaskActivityService.d.ts +4 -1
- package/dist/core/TaskActivityService.js +45 -0
- package/dist/core/TaskAuditTimeline.test.js +52 -1
- package/dist/core/TaskTaxonomyValidation.test.js +53 -0
- package/dist/core/Taskforce.d.ts +18 -11
- package/dist/core/Taskforce.js +93 -12
- package/dist/core/WorkspacePlanMode.test.js +73 -8
- package/dist/core/shared.d.ts +2 -0
- package/dist/core/shared.js +11 -0
- package/dist/documentReviews/service.d.ts +1 -1
- package/dist/documentReviews/types.d.ts +1 -1
- package/dist/hooks/auth/useTaskforceAuthBootstrap.d.ts +48 -0
- package/dist/hooks/auth/useTaskforceAuthBootstrap.js +219 -0
- package/dist/hooks/sync/auth.d.ts +37 -0
- package/dist/hooks/sync/auth.js +63 -0
- package/dist/hooks/sync/bootstrap.d.ts +34 -0
- package/dist/hooks/sync/bootstrap.js +52 -0
- package/dist/hooks/sync/orchestratorShared.d.ts +36 -0
- package/dist/hooks/sync/orchestratorShared.js +209 -0
- package/dist/hooks/sync/orchestratorShared.test.d.ts +1 -0
- package/dist/hooks/sync/orchestratorShared.test.js +49 -0
- package/dist/hooks/sync/realtime.d.ts +25 -0
- package/dist/hooks/sync/realtime.js +60 -0
- package/dist/hooks/sync/recovery.d.ts +69 -0
- package/dist/hooks/sync/recovery.js +118 -0
- package/dist/hooks/sync/transfers.d.ts +123 -0
- package/dist/hooks/sync/transfers.js +435 -0
- package/dist/hooks/sync/useDataVersionRefresh.d.ts +16 -0
- package/dist/hooks/sync/useDataVersionRefresh.js +73 -0
- package/dist/hooks/ui/useResourceExport.d.ts +3 -1
- package/dist/hooks/ui/useResourceExport.js +5 -2
- package/dist/hooks/ui/useWorkflowTemplates.js +11 -6
- package/dist/hooks/useRealtimeSync.js +2 -1
- package/dist/hooks/useSyncOrchestrator.aiProfiles.test.js +8 -0
- package/dist/hooks/useSyncOrchestrator.context-assets.test.d.ts +1 -0
- package/dist/hooks/useSyncOrchestrator.context-assets.test.js +228 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +12 -8
- package/dist/hooks/useSyncOrchestrator.js +388 -879
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +641 -6
- package/dist/hooks/useTaskMutations.d.ts +2 -1
- package/dist/hooks/useTaskMutations.js +57 -7
- package/dist/hooks/useTaskMutations.test.js +176 -0
- package/dist/hooks/useTaskforce.d.ts +13 -4
- package/dist/hooks/useTaskforce.js +302 -817
- package/dist/hooks/useTaskforce.sync-behavior.test.js +78 -0
- package/dist/hooks/useWorkspaceSyncController.d.ts +4 -1
- package/dist/hooks/useWorkspaceSyncController.js +33 -11
- package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
- package/dist/hooks/workspace/useTaskforceApiRouting.test.js +17 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.d.ts +166 -0
- package/dist/hooks/workspace/useTaskforceWorkspaceBootstrap.js +434 -0
- package/dist/hooks/workspace/workspaceLocalState.d.ts +19 -0
- package/dist/hooks/workspace/workspaceLocalState.js +100 -0
- package/dist/hooks/workspace/workspaceLocalState.test.d.ts +1 -0
- package/dist/hooks/workspace/workspaceLocalState.test.js +59 -0
- package/dist/localization/locales/en-US.js +2 -2
- package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
- package/dist/mcp/canonicalAssetHelpers.d.ts +70 -0
- package/dist/mcp/canonicalAssetHelpers.js +259 -0
- package/dist/mcp/clientIntegrations.d.ts +12 -1
- package/dist/mcp/clientIntegrations.js +161 -6
- package/dist/mcp/clientIntegrations.test.js +76 -4
- package/dist/mcp/collaborationRegistrar.d.ts +2 -0
- package/dist/mcp/collaborationRegistrar.js +71 -0
- package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
- package/dist/mcp/documentAssetRegistrar.js +346 -0
- package/dist/mcp/documentHelpers.d.ts +100 -0
- package/dist/mcp/documentHelpers.js +161 -0
- package/dist/mcp/runtime.js +2455 -3925
- package/dist/mcp/runtime.test.js +240 -8
- package/dist/mcp/taskAttachmentHelpers.d.ts +41 -0
- package/dist/mcp/taskAttachmentHelpers.js +60 -0
- package/dist/mcp/taskAttachmentTypes.d.ts +37 -0
- package/dist/mcp/taskAttachmentTypes.js +1 -0
- package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
- package/dist/mcp/taskPlanningRegistrar.js +418 -0
- package/dist/mcp/toolCatalog.d.ts +35 -0
- package/dist/mcp/toolCatalog.js +3 -0
- package/dist/plugins/vite.js +1 -1
- package/dist/runtime/appGateDefinitions.d.ts +1 -1
- package/dist/runtime/appGateDefinitions.js +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +46 -3
- package/dist/server/index.test.js +12 -1
- package/dist/server/routes/admin.d.ts +1 -5
- package/dist/server/routes/admin.js +151 -80
- package/dist/server/routes/annotatedAttachments.d.ts +1 -1
- package/dist/server/routes/annotatedAttachments.js +1 -1
- package/dist/server/routes/auth.d.ts +1 -4
- package/dist/server/routes/auth.js +59 -64
- package/dist/server/routes/authSupport.d.ts +30 -0
- package/dist/server/routes/authSupport.js +81 -0
- package/dist/server/routes/billing.d.ts +1 -1
- package/dist/server/routes/billing.js +122 -255
- package/dist/server/routes/billing.test.js +257 -86
- package/dist/server/routes/documentReviews.d.ts +1 -1
- package/dist/server/routes/documentReviews.js +1 -1
- package/dist/server/routes/documents.d.ts +4 -2
- package/dist/server/routes/documents.js +73 -7
- package/dist/server/routes/primitives.d.ts +11 -0
- package/dist/server/routes/primitives.js +73 -0
- package/dist/server/routes/resources.d.ts +1 -1
- package/dist/server/routes/resources.js +1 -1
- package/dist/server/routes/shared.d.ts +31 -1
- package/dist/server/routes/shared.js +26 -0
- package/dist/server/routes/sync.d.ts +1 -1
- package/dist/server/routes/sync.integration.test.js +20 -0
- package/dist/server/routes/sync.js +111 -238
- package/dist/server/routes/tasks.d.ts +1 -1
- package/dist/server/routes/tasks.js +50 -8
- package/dist/server/routes/workspaces.d.ts +1 -1
- package/dist/server/routes/workspaces.js +1 -1
- package/dist/server/routes.d.ts +2 -9
- package/dist/server/routes.js +84 -181
- package/dist/server/routes.test.js +912 -32
- package/dist/shared/taskActor.d.ts +10 -0
- package/dist/shared/taskActor.js +1 -0
- package/dist/sync/collaborationSyncPayload.js +4 -0
- package/dist/sync/collaborationSyncPayload.test.js +8 -0
- package/dist/sync/collaborationSyncState.d.ts +3 -1
- package/dist/sync/collaborationSyncState.js +19 -0
- package/dist/sync/contentSyncState.js +28 -17
- package/dist/sync/syncApplyHandlers.d.ts +87 -1
- package/dist/sync/syncApplyHandlers.js +370 -8
- package/dist/sync/syncApplyHandlers.test.d.ts +1 -0
- package/dist/sync/syncApplyHandlers.test.js +379 -0
- package/dist/sync/syncService.d.ts +9 -1
- package/dist/sync/syncService.js +44 -2
- package/dist/sync/syncService.test.js +62 -0
- package/dist/sync/workspacePullFeed.d.ts +1 -0
- package/dist/sync/workspacePullFeed.js +66 -59
- package/dist/sync/workspacePullFeed.test.js +72 -4
- package/dist/sync/workspaceSyncModel.d.ts +25 -1
- package/dist/sync/workspaceSyncModel.js +77 -3
- package/dist/sync/workspaceSyncModel.test.js +153 -0
- package/dist/sync/workspaceSyncState.d.ts +2 -0
- package/dist/sync/workspaceSyncState.js +1 -0
- package/dist/types.d.ts +2 -10
- package/dist/ui/assets/AgentsModule-N2MnQBZk.js +1 -0
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-C_TmXZwA.js → AnnotatedAttachmentWorkspace-BG6P_GVW.js} +1 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +252 -0
- package/dist/ui/assets/{InitiativesModule-4-Rh2K2n.js → InitiativesModule-Dhm7M8e7.js} +1 -1
- package/dist/ui/assets/{PlansPage-BlVC_lRq.css → PlansPage-C2dd2n1X.css} +1 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +1 -0
- package/dist/ui/assets/TaskSettings-ln0aF7xc.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-CGk9s3NJ.js → WorkflowsModule-BcS4afRn.js} +1 -1
- package/dist/ui/assets/index-C2-OXZV7.css +1 -0
- package/dist/ui/assets/index-DcSI5F86.js +6 -0
- package/dist/ui/assets/{vendor-icons-pWocEipT.js → vendor-icons-BSUaRwF8.js} +1 -1
- package/dist/ui/index.html +4 -4
- package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
- package/dist/utils/commercialLifecyclePresentation.js +196 -0
- package/dist/utils/taskActivity.js +4 -0
- package/dist/utils/taskActivity.test.js +25 -1
- package/package.json +10 -1
- package/scripts/check-cloud-mcp.mjs +83 -0
- package/scripts/playwright-auth.sh +9 -1
- package/scripts/run-billing-performance-smoke.sh +24 -0
- package/dist/ui/assets/AgentsModule-CpsTmrIW.js +0 -1
- package/dist/ui/assets/DocumentWorkspace-C3GyzrWm.js +0 -250
- package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
- package/dist/ui/assets/PlansPage-BP7AYOqr.js +0 -1
- package/dist/ui/assets/TaskSettings-BOC5F6Ag.js +0 -8
- package/dist/ui/assets/index-CLIMgR6g.js +0 -6
- package/dist/ui/assets/index-DneETxcu.css +0 -1
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { bindDomainTool } from './toolCatalog.js';
|
|
2
|
+
function stringProperty(description, enumValues) {
|
|
3
|
+
return enumValues ? { type: 'string', description, enum: enumValues } : { type: 'string', description };
|
|
4
|
+
}
|
|
5
|
+
function numberProperty(description) {
|
|
6
|
+
return { type: 'number', description };
|
|
7
|
+
}
|
|
8
|
+
function booleanProperty(description) {
|
|
9
|
+
return { type: 'boolean', description };
|
|
10
|
+
}
|
|
11
|
+
function arrayProperty(description, items) {
|
|
12
|
+
return { type: 'array', description, items };
|
|
13
|
+
}
|
|
14
|
+
export function registerAdminWorkspaceTools(registerTool, executeTool) {
|
|
15
|
+
const register = (name, buildDescriptor) => {
|
|
16
|
+
registerTool({
|
|
17
|
+
name,
|
|
18
|
+
buildDescriptor: (context) => {
|
|
19
|
+
const descriptor = buildDescriptor(context);
|
|
20
|
+
return {
|
|
21
|
+
name,
|
|
22
|
+
description: descriptor.description,
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: descriptor.inputSchema.properties,
|
|
26
|
+
...(descriptor.inputSchema.required ? { required: descriptor.inputSchema.required } : {}),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
handler: bindDomainTool(executeTool, name),
|
|
31
|
+
});
|
|
32
|
+
};
|
|
33
|
+
register('get_config', (context) => ({
|
|
34
|
+
description: context.describeTool('Get the active workspace taxonomy and planning configuration. Call this at the start of a session or before create_task/update_task when you need valid category, type, priority, approach, status, or complexity values.'),
|
|
35
|
+
inputSchema: { properties: {} },
|
|
36
|
+
}));
|
|
37
|
+
register('update_categories', (context) => ({
|
|
38
|
+
description: context.describeTool('Replace the workspace category taxonomy. This is session-only and updates the active categories used by task fields and validation.'),
|
|
39
|
+
inputSchema: {
|
|
40
|
+
properties: {
|
|
41
|
+
categories: arrayProperty('Ordered category definitions to save.', {
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
value: { type: 'string' },
|
|
45
|
+
label: { type: 'string' },
|
|
46
|
+
aliases: { type: 'array', items: { type: 'string' } },
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
required: ['categories'],
|
|
51
|
+
},
|
|
52
|
+
}));
|
|
53
|
+
register('update_types', (context) => ({
|
|
54
|
+
description: context.describeTool('Replace the workspace task type taxonomy. This is session-only and updates the active task type definitions used by validation and task editing flows.'),
|
|
55
|
+
inputSchema: {
|
|
56
|
+
properties: {
|
|
57
|
+
types: arrayProperty('Ordered task type definitions to save.', {
|
|
58
|
+
type: 'object',
|
|
59
|
+
properties: {
|
|
60
|
+
value: { type: 'string' },
|
|
61
|
+
label: { type: 'string' },
|
|
62
|
+
aliases: { type: 'array', items: { type: 'string' } },
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
},
|
|
66
|
+
required: ['types'],
|
|
67
|
+
},
|
|
68
|
+
}));
|
|
69
|
+
register('bulk_update_type', (context) => ({
|
|
70
|
+
description: context.describeTool('Bulk-update tasks from one task type to another. Use get_config first to confirm the current valid type values.'),
|
|
71
|
+
inputSchema: {
|
|
72
|
+
properties: {
|
|
73
|
+
fromType: stringProperty('Current task type value to replace.', context.typeEnum),
|
|
74
|
+
toType: stringProperty('Replacement task type value.', context.typeEnum),
|
|
75
|
+
},
|
|
76
|
+
required: ['fromType', 'toType'],
|
|
77
|
+
},
|
|
78
|
+
}));
|
|
79
|
+
register('bulk_update_fields', (context) => ({
|
|
80
|
+
description: context.describeTool('Apply field updates to multiple tasks in one request. Use get_config first to confirm valid taxonomy values before calling this tool.'),
|
|
81
|
+
inputSchema: {
|
|
82
|
+
properties: {
|
|
83
|
+
updates: arrayProperty('List of per-task field updates.', {
|
|
84
|
+
type: 'object',
|
|
85
|
+
properties: {
|
|
86
|
+
id: { type: 'string', description: 'Task ID or task reference such as T-123.' },
|
|
87
|
+
title: { type: 'string' },
|
|
88
|
+
description: { type: 'string' },
|
|
89
|
+
category: { type: 'string' },
|
|
90
|
+
type: { type: 'string' },
|
|
91
|
+
priority: { type: 'number', description: context.priorityDesc },
|
|
92
|
+
approach: { type: 'string', enum: context.approachEnum },
|
|
93
|
+
assignee: { type: 'string', description: `${context.assigneeHint} Call list_assignees to inspect the current eligible IDs.` },
|
|
94
|
+
owner: { type: 'string', description: `${context.assigneeHint} Alias for assignee.` },
|
|
95
|
+
status: { type: 'string', enum: ['task', 'on-hold', 'in-progress', 'review', 'done', 'cancelled'] },
|
|
96
|
+
complexity: { type: 'number', description: context.complexityDesc },
|
|
97
|
+
},
|
|
98
|
+
required: ['id'],
|
|
99
|
+
}),
|
|
100
|
+
},
|
|
101
|
+
required: ['updates'],
|
|
102
|
+
},
|
|
103
|
+
}));
|
|
104
|
+
register('export_resources', (context) => ({
|
|
105
|
+
description: context.describeTool('Export Taskforce resources to files on disk. Local-only utility for generating external artifacts from workspace data.'),
|
|
106
|
+
inputSchema: {
|
|
107
|
+
properties: {
|
|
108
|
+
type: stringProperty('Resource export type.'),
|
|
109
|
+
path: stringProperty('Destination path for the export output.'),
|
|
110
|
+
variables: { type: 'object', description: 'Optional template variables for the export job.' },
|
|
111
|
+
environment: stringProperty('Optional environment name to include in the export context.'),
|
|
112
|
+
},
|
|
113
|
+
required: ['type', 'path'],
|
|
114
|
+
},
|
|
115
|
+
}));
|
|
116
|
+
register('get_paths', (context) => ({
|
|
117
|
+
description: context.describeTool('Get project and Taskforce storage paths. Local-only utility for discovering the project root, Taskforce data root, and related filesystem locations.'),
|
|
118
|
+
inputSchema: { properties: {} },
|
|
119
|
+
}));
|
|
120
|
+
register('update_priorities', (context) => ({
|
|
121
|
+
description: context.describeTool('Replace the workspace priority options. This is session-only and updates the valid priority taxonomy used by task editing flows.'),
|
|
122
|
+
inputSchema: {
|
|
123
|
+
properties: {
|
|
124
|
+
priorities: arrayProperty('Ordered priority definitions to save.', {
|
|
125
|
+
type: 'object',
|
|
126
|
+
properties: {
|
|
127
|
+
value: { type: 'number' },
|
|
128
|
+
label: { type: 'string' },
|
|
129
|
+
},
|
|
130
|
+
}),
|
|
131
|
+
},
|
|
132
|
+
required: ['priorities'],
|
|
133
|
+
},
|
|
134
|
+
}));
|
|
135
|
+
register('update_approaches', (context) => ({
|
|
136
|
+
description: context.describeTool('Replace the active approach options. This is session-only and updates the valid approach taxonomy used by task editing flows.'),
|
|
137
|
+
inputSchema: {
|
|
138
|
+
properties: {
|
|
139
|
+
approaches: arrayProperty('Ordered approach definitions to save.', {
|
|
140
|
+
type: 'object',
|
|
141
|
+
properties: {
|
|
142
|
+
value: { type: 'string' },
|
|
143
|
+
label: { type: 'string' },
|
|
144
|
+
},
|
|
145
|
+
}),
|
|
146
|
+
},
|
|
147
|
+
required: ['approaches'],
|
|
148
|
+
},
|
|
149
|
+
}));
|
|
150
|
+
register('get_stats', (context) => ({
|
|
151
|
+
description: context.describeTool('Get task counts by status and priority for situational awareness. Call this at the start of a session to understand the current workload before listing or modifying tasks. Returns active totals (by status and priority) and archived totals.'),
|
|
152
|
+
inputSchema: { properties: {} },
|
|
153
|
+
}));
|
|
154
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { WorkspaceAssetEntry, WorkspaceAssetKind, WorkspaceAssetLinkRole, WorkspaceAssetScanStatus, WorkspaceAssetStore } from '../storage/workspaceAssetStore.js';
|
|
2
|
+
import type { McpTaskAttachmentDescriptor, TaskAttachmentRecord } from './taskAttachmentTypes.js';
|
|
3
|
+
export interface CanonicalAssetHelpersDeps {
|
|
4
|
+
activeWorkspaceId: string;
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
basePath: string;
|
|
7
|
+
workspaceAssetStore: WorkspaceAssetStore | null;
|
|
8
|
+
objectStorageClient: {
|
|
9
|
+
getObject(storageKey: string): Promise<{
|
|
10
|
+
body: Buffer;
|
|
11
|
+
} | null>;
|
|
12
|
+
} | null;
|
|
13
|
+
sanitizeFilenameForPath: (filenameRaw: unknown, fallback?: string) => string;
|
|
14
|
+
sanitizeDisplayName: (valueRaw: unknown, fallback: string) => string;
|
|
15
|
+
toPosixPath: (filePath: string) => string;
|
|
16
|
+
inferMimeTypeFromPath: (filePath: string) => string;
|
|
17
|
+
inferAssetKind: (filePath: string, mimeType: string) => WorkspaceAssetKind;
|
|
18
|
+
buildCanonicalWorkspaceAssetRelativePath: (params: {
|
|
19
|
+
workspaceIdRaw: unknown;
|
|
20
|
+
kind: WorkspaceAssetKind;
|
|
21
|
+
filename: string;
|
|
22
|
+
now?: Date;
|
|
23
|
+
}) => {
|
|
24
|
+
relativePath: string;
|
|
25
|
+
assetId: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export declare function createCanonicalAssetHelpers(deps: CanonicalAssetHelpersDeps): {
|
|
29
|
+
normalizeAttachmentStorageKey: (pathValue: unknown, fsPathValue: unknown) => string | null;
|
|
30
|
+
buildSyntheticAttachmentId: (taskId: string, attachment: TaskAttachmentRecord) => string;
|
|
31
|
+
getAttachmentAssetRecord: (attachment: TaskAttachmentRecord) => WorkspaceAssetEntry | null;
|
|
32
|
+
buildAttachmentDownloadUrl: (attachment: McpTaskAttachmentDescriptor) => string;
|
|
33
|
+
buildDocumentDownloadUrl: (asset: WorkspaceAssetEntry) => string;
|
|
34
|
+
readCanonicalAttachmentBuffer: (taskId: string, attachment: McpTaskAttachmentDescriptor) => Promise<Buffer>;
|
|
35
|
+
readCanonicalDocumentBuffer: (asset: WorkspaceAssetEntry) => Promise<Buffer>;
|
|
36
|
+
toTaskAttachmentRecord: (attachment: string | TaskAttachmentRecord) => TaskAttachmentRecord;
|
|
37
|
+
resolveAttachmentLogicalFilename: (attachmentInput: string | TaskAttachmentRecord, assetOverride?: ReturnType<(attachment: TaskAttachmentRecord) => WorkspaceAssetEntry | null> | null) => string;
|
|
38
|
+
resolveCanonicalOverwriteTarget: (task: {
|
|
39
|
+
id: string;
|
|
40
|
+
attachments?: Array<string | TaskAttachmentRecord> | null;
|
|
41
|
+
}, filenameRaw: unknown, describeTaskAttachment: (taskId: string, attachmentInput: string | TaskAttachmentRecord) => McpTaskAttachmentDescriptor) => null | {
|
|
42
|
+
index: number;
|
|
43
|
+
attachment: TaskAttachmentRecord;
|
|
44
|
+
asset: NonNullable<ReturnType<(attachment: TaskAttachmentRecord) => WorkspaceAssetEntry | null>>;
|
|
45
|
+
descriptor: McpTaskAttachmentDescriptor;
|
|
46
|
+
relativePath: string;
|
|
47
|
+
absolutePath: string;
|
|
48
|
+
logicalFilename: string;
|
|
49
|
+
};
|
|
50
|
+
ensureCanonicalTaskAttachment: (relativePathRaw: string, taskIdRaw: string, captionRaw: string | undefined, timestampRaw: string | undefined, role: WorkspaceAssetLinkRole, options?: {
|
|
51
|
+
originalFilename?: string;
|
|
52
|
+
logicalName?: string;
|
|
53
|
+
assetId?: string;
|
|
54
|
+
documentId?: string | null;
|
|
55
|
+
createdAt?: string;
|
|
56
|
+
createdByUserId?: string | null;
|
|
57
|
+
scanStatus?: WorkspaceAssetScanStatus;
|
|
58
|
+
scanEngine?: string | null;
|
|
59
|
+
scanDetails?: string | null;
|
|
60
|
+
}) => WorkspaceAssetEntry | null;
|
|
61
|
+
buildCanonicalWorkspaceAssetRelativePath: (params: {
|
|
62
|
+
workspaceIdRaw: unknown;
|
|
63
|
+
kind: WorkspaceAssetKind;
|
|
64
|
+
filename: string;
|
|
65
|
+
now?: Date;
|
|
66
|
+
}) => {
|
|
67
|
+
relativePath: string;
|
|
68
|
+
assetId: string;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
4
|
+
export function createCanonicalAssetHelpers(deps) {
|
|
5
|
+
const normalizeAttachmentStorageKey = (pathValue, fsPathValue) => {
|
|
6
|
+
const fsPathRaw = String(fsPathValue || '').trim().replace(/\\/g, '/');
|
|
7
|
+
if (fsPathRaw) {
|
|
8
|
+
return fsPathRaw.replace(/^\.taskforce\//, '').trim() || null;
|
|
9
|
+
}
|
|
10
|
+
const pathRaw = String(pathValue || '').trim();
|
|
11
|
+
if (!pathRaw)
|
|
12
|
+
return null;
|
|
13
|
+
if (/^https?:\/\//i.test(pathRaw))
|
|
14
|
+
return pathRaw;
|
|
15
|
+
if (pathRaw.startsWith('/api/taskforce/context/')) {
|
|
16
|
+
return decodeURIComponent(pathRaw.slice('/api/taskforce/context/'.length)).trim() || null;
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
};
|
|
20
|
+
const buildSyntheticAttachmentId = (taskId, attachment) => {
|
|
21
|
+
const stableSource = [
|
|
22
|
+
taskId,
|
|
23
|
+
String(attachment.path || '').trim(),
|
|
24
|
+
String(attachment.fsPath || '').trim(),
|
|
25
|
+
String(attachment.caption || '').trim(),
|
|
26
|
+
].join('::');
|
|
27
|
+
return `attachment-${createHash('sha256').update(stableSource).digest('hex').slice(0, 24)}`;
|
|
28
|
+
};
|
|
29
|
+
const getAttachmentAssetRecord = (attachment) => {
|
|
30
|
+
if (!deps.workspaceAssetStore)
|
|
31
|
+
return null;
|
|
32
|
+
const assetId = String(attachment.assetId || '').trim();
|
|
33
|
+
if (assetId) {
|
|
34
|
+
const byId = deps.workspaceAssetStore.get(assetId, deps.activeWorkspaceId);
|
|
35
|
+
if (byId && !byId.deletedAt)
|
|
36
|
+
return byId;
|
|
37
|
+
}
|
|
38
|
+
const storageKey = normalizeAttachmentStorageKey(attachment.path, attachment.fsPath);
|
|
39
|
+
if (!storageKey || /^https?:\/\//i.test(storageKey))
|
|
40
|
+
return null;
|
|
41
|
+
const byStorageKey = deps.workspaceAssetStore.getByStorageKey(storageKey, deps.activeWorkspaceId);
|
|
42
|
+
if (byStorageKey && !byStorageKey.deletedAt)
|
|
43
|
+
return byStorageKey;
|
|
44
|
+
return null;
|
|
45
|
+
};
|
|
46
|
+
const buildAttachmentDownloadUrl = (attachment) => {
|
|
47
|
+
if (attachment.source === 'external')
|
|
48
|
+
return attachment.path;
|
|
49
|
+
const safeName = encodeURIComponent(String(attachment.caption || attachment.displayName || attachment.originalFilename || path.basename(attachment.fsPath || attachment.path) || 'download').trim());
|
|
50
|
+
const joiner = attachment.path.includes('?') ? '&' : '?';
|
|
51
|
+
return `${attachment.path}${joiner}download=1&filename=${safeName}`;
|
|
52
|
+
};
|
|
53
|
+
const buildDocumentDownloadUrl = (asset) => {
|
|
54
|
+
const safeName = deps.sanitizeFilenameForPath(asset.originalFilename
|
|
55
|
+
|| asset.logicalName
|
|
56
|
+
|| path.basename(String(asset.storageKey || '').trim())
|
|
57
|
+
|| 'document.txt', 'document.txt');
|
|
58
|
+
return `/api/taskforce/documents/${encodeURIComponent(String(asset.assetId || '').trim())}/content?download=1&filename=${encodeURIComponent(safeName)}`;
|
|
59
|
+
};
|
|
60
|
+
const describeAttachmentStorageContext = (attachment, storageKey) => {
|
|
61
|
+
const parts = [
|
|
62
|
+
`attachmentId=${attachment.attachmentId}`,
|
|
63
|
+
`assetId=${String(attachment.assetId || 'unknown')}`,
|
|
64
|
+
`storageKey=${storageKey || 'unknown'}`
|
|
65
|
+
];
|
|
66
|
+
return parts.join(', ');
|
|
67
|
+
};
|
|
68
|
+
const readCanonicalAttachmentBuffer = async (taskId, attachment) => {
|
|
69
|
+
const assetId = String(attachment.assetId || '').trim();
|
|
70
|
+
const asset = assetId && deps.workspaceAssetStore
|
|
71
|
+
? deps.workspaceAssetStore.get(assetId, deps.activeWorkspaceId)
|
|
72
|
+
: null;
|
|
73
|
+
if (!asset || asset.deletedAt) {
|
|
74
|
+
throw new Error(`Attachment ${attachment.attachmentId} not found on task ${taskId}`);
|
|
75
|
+
}
|
|
76
|
+
if (asset.scanStatus === 'infected') {
|
|
77
|
+
throw new Error('Attachment is quarantined');
|
|
78
|
+
}
|
|
79
|
+
if (asset.scanStatus === 'pending') {
|
|
80
|
+
throw new Error('Attachment scan pending');
|
|
81
|
+
}
|
|
82
|
+
if (asset.storageProvider === 'r2') {
|
|
83
|
+
const attachmentContext = describeAttachmentStorageContext(attachment, asset.storageKey);
|
|
84
|
+
if (!deps.objectStorageClient) {
|
|
85
|
+
throw new Error(`Attachment read failed from R2 because object storage is not configured in this MCP runtime (${attachmentContext})`);
|
|
86
|
+
}
|
|
87
|
+
let object;
|
|
88
|
+
try {
|
|
89
|
+
object = await deps.objectStorageClient.getObject(asset.storageKey);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
const message = error instanceof Error ? String(error.message || '').trim() : String(error || '').trim();
|
|
93
|
+
throw new Error(`Attachment read failed from R2 (${attachmentContext}): ${message || 'Unknown object storage error'}`);
|
|
94
|
+
}
|
|
95
|
+
if (!object) {
|
|
96
|
+
throw new Error(`Attachment ${attachment.attachmentId} not found on task ${taskId}`);
|
|
97
|
+
}
|
|
98
|
+
return object.body;
|
|
99
|
+
}
|
|
100
|
+
const resolvedPath = path.resolve(deps.basePath, asset.storageKey);
|
|
101
|
+
if (!resolvedPath.startsWith(path.resolve(deps.basePath))) {
|
|
102
|
+
throw new Error(`Attachment ${attachment.attachmentId} not found on task ${taskId}`);
|
|
103
|
+
}
|
|
104
|
+
if (!fs.existsSync(resolvedPath) || !fs.statSync(resolvedPath).isFile()) {
|
|
105
|
+
throw new Error(`Attachment ${attachment.attachmentId} not found on task ${taskId}`);
|
|
106
|
+
}
|
|
107
|
+
return fs.readFileSync(resolvedPath);
|
|
108
|
+
};
|
|
109
|
+
const readCanonicalDocumentBuffer = async (asset) => {
|
|
110
|
+
if (asset.deletedAt || asset.kind !== 'document') {
|
|
111
|
+
throw new Error(`Document ${asset.assetId} not found in workspace ${deps.activeWorkspaceId}.`);
|
|
112
|
+
}
|
|
113
|
+
if (asset.scanStatus === 'infected') {
|
|
114
|
+
throw new Error('Document is quarantined');
|
|
115
|
+
}
|
|
116
|
+
if (asset.scanStatus === 'pending') {
|
|
117
|
+
throw new Error('Document scan pending');
|
|
118
|
+
}
|
|
119
|
+
if (asset.storageProvider === 'r2') {
|
|
120
|
+
if (!deps.objectStorageClient) {
|
|
121
|
+
throw new Error(`Document read failed from R2 because object storage is not configured in this MCP runtime (assetId=${asset.assetId}, storageKey=${asset.storageKey || 'unknown'})`);
|
|
122
|
+
}
|
|
123
|
+
let object;
|
|
124
|
+
try {
|
|
125
|
+
object = await deps.objectStorageClient.getObject(asset.storageKey);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
const message = error instanceof Error ? String(error.message || '').trim() : String(error || '').trim();
|
|
129
|
+
throw new Error(`Document read failed from R2 (assetId=${asset.assetId}, storageKey=${asset.storageKey || 'unknown'}): ${message || 'Unknown object storage error'}`);
|
|
130
|
+
}
|
|
131
|
+
if (!object) {
|
|
132
|
+
throw new Error(`Document ${asset.assetId} not found in workspace ${deps.activeWorkspaceId}.`);
|
|
133
|
+
}
|
|
134
|
+
return object.body;
|
|
135
|
+
}
|
|
136
|
+
const resolvedPath = path.resolve(deps.basePath, asset.storageKey);
|
|
137
|
+
if (!resolvedPath.startsWith(path.resolve(deps.basePath))) {
|
|
138
|
+
throw new Error(`Document ${asset.assetId} not found in workspace ${deps.activeWorkspaceId}.`);
|
|
139
|
+
}
|
|
140
|
+
if (!fs.existsSync(resolvedPath) || !fs.statSync(resolvedPath).isFile()) {
|
|
141
|
+
throw new Error(`Document ${asset.assetId} not found in workspace ${deps.activeWorkspaceId}.`);
|
|
142
|
+
}
|
|
143
|
+
return fs.readFileSync(resolvedPath);
|
|
144
|
+
};
|
|
145
|
+
const toTaskAttachmentRecord = (attachment) => {
|
|
146
|
+
if (typeof attachment === 'string') {
|
|
147
|
+
return { path: attachment };
|
|
148
|
+
}
|
|
149
|
+
return attachment;
|
|
150
|
+
};
|
|
151
|
+
const resolveAttachmentLogicalFilename = (attachmentInput, assetOverride) => {
|
|
152
|
+
const attachment = toTaskAttachmentRecord(attachmentInput);
|
|
153
|
+
const asset = assetOverride ?? getAttachmentAssetRecord(attachment);
|
|
154
|
+
const candidate = String(attachment.originalFilename
|
|
155
|
+
|| asset?.originalFilename
|
|
156
|
+
|| attachment.displayName
|
|
157
|
+
|| asset?.logicalName
|
|
158
|
+
|| '').trim();
|
|
159
|
+
if (candidate) {
|
|
160
|
+
return deps.sanitizeFilenameForPath(candidate);
|
|
161
|
+
}
|
|
162
|
+
const storageKey = normalizeAttachmentStorageKey(attachment.path, attachment.fsPath);
|
|
163
|
+
return deps.sanitizeFilenameForPath(storageKey ? path.basename(storageKey) : '', 'attachment.txt');
|
|
164
|
+
};
|
|
165
|
+
const resolveCanonicalOverwriteTarget = (task, filenameRaw, describeTaskAttachment) => {
|
|
166
|
+
const requestedFilename = deps.sanitizeFilenameForPath(filenameRaw);
|
|
167
|
+
const existingAttachments = Array.isArray(task.attachments) ? task.attachments : [];
|
|
168
|
+
for (let index = 0; index < existingAttachments.length; index++) {
|
|
169
|
+
const attachment = toTaskAttachmentRecord(existingAttachments[index]);
|
|
170
|
+
const asset = getAttachmentAssetRecord(attachment);
|
|
171
|
+
if (!asset || asset.deletedAt || asset.storageProvider === 'external')
|
|
172
|
+
continue;
|
|
173
|
+
const descriptor = describeTaskAttachment(task.id, attachment);
|
|
174
|
+
if (descriptor.source !== 'canonical')
|
|
175
|
+
continue;
|
|
176
|
+
const logicalFilename = resolveAttachmentLogicalFilename(attachment, asset);
|
|
177
|
+
if (logicalFilename !== requestedFilename)
|
|
178
|
+
continue;
|
|
179
|
+
const relativePath = deps.toPosixPath(path.relative(deps.projectRoot, path.resolve(deps.basePath, asset.storageKey)));
|
|
180
|
+
return {
|
|
181
|
+
index,
|
|
182
|
+
attachment,
|
|
183
|
+
asset,
|
|
184
|
+
descriptor,
|
|
185
|
+
relativePath,
|
|
186
|
+
absolutePath: path.resolve(deps.basePath, asset.storageKey),
|
|
187
|
+
logicalFilename,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
};
|
|
192
|
+
const ensureCanonicalTaskAttachment = (relativePathRaw, taskIdRaw, captionRaw, timestampRaw, role, options) => {
|
|
193
|
+
if (!deps.workspaceAssetStore)
|
|
194
|
+
return null;
|
|
195
|
+
const relativePath = String(relativePathRaw || '').trim();
|
|
196
|
+
const taskId = String(taskIdRaw || '').trim();
|
|
197
|
+
if (!relativePath || !taskId)
|
|
198
|
+
return null;
|
|
199
|
+
const absolutePath = path.resolve(deps.projectRoot, relativePath);
|
|
200
|
+
if (!fs.existsSync(absolutePath) || !fs.statSync(absolutePath).isFile())
|
|
201
|
+
return null;
|
|
202
|
+
const storageKey = relativePath.replace(/^\.taskforce\//, '').trim() || relativePath;
|
|
203
|
+
const buffer = fs.readFileSync(absolutePath);
|
|
204
|
+
const stats = fs.statSync(absolutePath);
|
|
205
|
+
const mimeType = deps.inferMimeTypeFromPath(relativePath);
|
|
206
|
+
const kind = deps.inferAssetKind(relativePath, mimeType);
|
|
207
|
+
const timestamp = String(timestampRaw || new Date().toISOString()).trim() || new Date().toISOString();
|
|
208
|
+
const existing = deps.workspaceAssetStore.getByStorageKey(storageKey, deps.activeWorkspaceId);
|
|
209
|
+
const originalFilename = deps.sanitizeFilenameForPath(options?.originalFilename || existing?.originalFilename || path.basename(relativePath));
|
|
210
|
+
const logicalName = deps.sanitizeDisplayName(options?.logicalName || existing?.logicalName || originalFilename, originalFilename);
|
|
211
|
+
const asset = deps.workspaceAssetStore.upsertAsset({
|
|
212
|
+
assetId: options?.assetId || existing?.assetId || `asset-${randomUUID().replace(/-/g, '')}`,
|
|
213
|
+
workspaceId: deps.activeWorkspaceId,
|
|
214
|
+
kind,
|
|
215
|
+
logicalName,
|
|
216
|
+
originalFilename,
|
|
217
|
+
mimeType,
|
|
218
|
+
storageProvider: 'local',
|
|
219
|
+
storageKey,
|
|
220
|
+
contentSha256: createHash('sha256').update(buffer).digest('hex'),
|
|
221
|
+
sizeBytes: stats.size,
|
|
222
|
+
documentId: kind === 'document' ? (options?.documentId || existing?.documentId || `doc-${randomUUID().replace(/-/g, '')}`) : null,
|
|
223
|
+
version: kind === 'document' ? Math.max(1, Number(existing?.version || 0) + 1) : null,
|
|
224
|
+
isLatest: true,
|
|
225
|
+
scanStatus: options?.scanStatus || existing?.scanStatus || 'clean',
|
|
226
|
+
scanEngine: options?.scanEngine !== undefined ? options.scanEngine : (existing?.scanEngine || null),
|
|
227
|
+
scanDetails: options?.scanDetails !== undefined ? options.scanDetails : (existing?.scanDetails || null),
|
|
228
|
+
createdByUserId: options?.createdByUserId !== undefined ? options.createdByUserId : (existing?.createdByUserId || null),
|
|
229
|
+
createdAt: options?.createdAt || existing?.createdAt || timestamp,
|
|
230
|
+
updatedAt: timestamp,
|
|
231
|
+
deletedAt: null,
|
|
232
|
+
purgeAfter: null
|
|
233
|
+
});
|
|
234
|
+
deps.workspaceAssetStore.upsertLink({
|
|
235
|
+
workspaceId: deps.activeWorkspaceId,
|
|
236
|
+
assetId: asset.assetId,
|
|
237
|
+
taskId,
|
|
238
|
+
role,
|
|
239
|
+
displayName: kind === 'document' ? null : (captionRaw || null),
|
|
240
|
+
updatedAt: timestamp,
|
|
241
|
+
deletedAt: null
|
|
242
|
+
});
|
|
243
|
+
return asset;
|
|
244
|
+
};
|
|
245
|
+
return {
|
|
246
|
+
normalizeAttachmentStorageKey,
|
|
247
|
+
buildSyntheticAttachmentId,
|
|
248
|
+
getAttachmentAssetRecord,
|
|
249
|
+
buildAttachmentDownloadUrl,
|
|
250
|
+
buildDocumentDownloadUrl,
|
|
251
|
+
readCanonicalAttachmentBuffer,
|
|
252
|
+
readCanonicalDocumentBuffer,
|
|
253
|
+
toTaskAttachmentRecord,
|
|
254
|
+
resolveAttachmentLogicalFilename,
|
|
255
|
+
resolveCanonicalOverwriteTarget,
|
|
256
|
+
ensureCanonicalTaskAttachment,
|
|
257
|
+
buildCanonicalWorkspaceAssetRelativePath: deps.buildCanonicalWorkspaceAssetRelativePath,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AiProfileBootstrapConfig } from './aiProfileBootstrap.js';
|
|
2
|
-
export type McpClientId = 'cursor' | 'cline' | 'vscode' | 'windsurf' | 'antigravity' | 'openclaw' | 'codex' | 'claude-code' | 'gemini-cli' | 'claude-desktop' | 'chatgpt-desktop';
|
|
2
|
+
export type McpClientId = 'general' | 'cursor' | 'cline' | 'vscode' | 'windsurf' | 'antigravity' | 'openclaw' | 'codex' | 'claude-code' | 'gemini-cli' | 'claude-desktop' | 'chatgpt-desktop';
|
|
3
3
|
export interface McpClientOption {
|
|
4
4
|
id: McpClientId;
|
|
5
5
|
label: string;
|
|
@@ -11,6 +11,16 @@ export interface BuildCloudMcpClientConfigInput extends AiProfileBootstrapConfig
|
|
|
11
11
|
tokenValue: string;
|
|
12
12
|
serverId: string;
|
|
13
13
|
}
|
|
14
|
+
export interface LocalMcpServerConfig {
|
|
15
|
+
command: string;
|
|
16
|
+
args: string[];
|
|
17
|
+
env?: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
export interface BuildLocalMcpClientConfigInput {
|
|
20
|
+
clientId: McpClientId;
|
|
21
|
+
serverId: string;
|
|
22
|
+
serverConfig: LocalMcpServerConfig;
|
|
23
|
+
}
|
|
14
24
|
export interface CloudMcpClientIntegration {
|
|
15
25
|
clientId: McpClientId;
|
|
16
26
|
kind: 'json' | 'text';
|
|
@@ -25,3 +35,4 @@ export declare const MCP_CLIENT_OPTIONS: McpClientOption[];
|
|
|
25
35
|
export declare function sanitizeMcpId(value: string, fallback: string): string;
|
|
26
36
|
export declare function buildCloudMcpServerId(workspaceName?: string | null, projectName?: string | null): string;
|
|
27
37
|
export declare function buildCloudMcpClientIntegration(input: BuildCloudMcpClientConfigInput): CloudMcpClientIntegration;
|
|
38
|
+
export declare function buildLocalMcpClientIntegration(input: BuildLocalMcpClientConfigInput): CloudMcpClientIntegration;
|