@taskforcehq/taskforce 0.3.324 → 0.3.326
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/dist/Taskforce.module.css +39 -0
- package/dist/components/features/TaskSettings.js +26 -9
- package/dist/components/task/TaskKanban.d.ts +2 -2
- package/dist/components/views/StandaloneLayout.js +22 -22
- package/dist/components/views/panels/PlanningDrawer.d.ts +2 -2
- package/dist/components/views/panels/PlanningDrawer.js +26 -12
- package/dist/components/views/planningScope.d.ts +4 -0
- package/dist/components/views/planningScope.js +5 -0
- package/dist/core/AiProfileService.js +6 -1
- package/dist/hooks/useTaskforce.js +74 -17
- package/dist/hooks/workspace/workspaceLocalState.d.ts +25 -0
- package/dist/hooks/workspace/workspaceLocalState.js +38 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +0 -10
- package/dist/mcp/clientIntegrations.d.ts +1 -1
- package/dist/mcp/clientIntegrations.js +50 -0
- package/dist/mcp/clientProfileDefaults.js +4 -0
- package/dist/mcp/collaborationRegistrar.js +3 -3
- package/dist/mcp/documentAssetRegistrar.js +24 -72
- package/dist/mcp/documentHelpers.d.ts +11 -4
- package/dist/mcp/documentHelpers.js +21 -17
- package/dist/mcp/runtime.d.ts +4 -0
- package/dist/mcp/runtime.js +466 -534
- package/dist/mcp/taskPlanningRegistrar.js +45 -81
- package/dist/mcp/toolProfiles.d.ts +7 -0
- package/dist/mcp/toolProfiles.js +36 -0
- package/dist/mcp/toolRegistry.d.ts +87 -609
- package/dist/mcp/toolRegistry.js +93 -88
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +10 -10
- package/dist/resources/templates/workflows/collaborate.yaml +2 -3
- package/dist/resources/templates/workflows/do.yaml +2 -3
- package/dist/resources/templates/workflows/evaluate.yaml +2 -3
- package/dist/resources/templates/workflows/execute.yaml +12 -15
- package/dist/resources/templates/workflows/plan.yaml +3 -4
- package/dist/resources/templates/workflows/review.yaml +2 -3
- package/dist/shared/taxonomyLibrary.js +1 -1
- package/dist/sync/cloudSyncApi.js +22 -3
- package/dist/types.js +1 -1
- package/dist/ui/assets/{AgentsModule-DvkbUHi0.js → AgentsModule-C4LcqhcZ.js} +1 -1
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-jhOhxqHT.js → AnnotatedAttachmentWorkspace-B-Dq22d2.js} +1 -1
- package/dist/ui/assets/{ContextAttachmentManager-BAmEyLHL.js → ContextAttachmentManager-DsXPTvi-.js} +1 -1
- package/dist/ui/assets/{DocumentWorkspace-X-CpD5OO.js → DocumentWorkspace-CxA1wO3U.js} +1 -1
- package/dist/ui/assets/{EntityActivityTimeline-DD33onAC.js → EntityActivityTimeline-B8nSe8l3.js} +1 -1
- package/dist/ui/assets/{InitiativesModule-5nDXtIjf.js → InitiativesModule-VY95v38E.js} +1 -1
- package/dist/ui/assets/{PlansPage-B8nDR1hQ.js → PlansPage-CQbKDv1a.js} +1 -1
- package/dist/ui/assets/{TaskContextUpload-DrGrXJHm.js → TaskContextUpload-DvDlNpHC.js} +1 -1
- package/dist/ui/assets/TaskSettings-CUWbYYtP.js +12 -0
- package/dist/ui/assets/{WorkflowsModule-DWCGhEWT.js → WorkflowsModule-CgM3Jako.js} +1 -1
- package/dist/ui/assets/documentReferences-Do9YjrS3.js +1 -0
- package/dist/ui/assets/index--mh3pktj.js +5 -0
- package/dist/ui/assets/index-BawaaEXS.css +1 -0
- package/dist/ui/index.html +2 -2
- package/dist/utils/theme.js +1 -1
- package/package.json +1 -1
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +10 -10
- package/src/resources/templates/workflows/collaborate.yaml +2 -3
- package/src/resources/templates/workflows/do.yaml +2 -3
- package/src/resources/templates/workflows/evaluate.yaml +2 -3
- package/src/resources/templates/workflows/execute.yaml +12 -15
- package/src/resources/templates/workflows/plan.yaml +3 -4
- package/src/resources/templates/workflows/review.yaml +2 -3
- package/dist/ui/assets/TaskSettings-BXVvZZwH.js +0 -9
- package/dist/ui/assets/documentReferences-Crup321p.js +0 -1
- package/dist/ui/assets/index-B9k24Aym.js +0 -5
- package/dist/ui/assets/index-DNeR5dYW.css +0 -1
|
@@ -62,7 +62,7 @@ import { useTaskFilters } from './tasks/useTaskFilters';
|
|
|
62
62
|
import { useTaskFormActions } from './tasks/useTaskFormActions';
|
|
63
63
|
import { useTaskRelationships } from './tasks/useTaskRelationships';
|
|
64
64
|
import { useTaskActions } from './tasks/useTaskActions';
|
|
65
|
-
import { clearPersistedWorkspaceId, logBootstrapDebug, persistRemoteUiState, readPersistedAppUiState, readPersistedWorkspaceId, writePersistedAppUiState, writePersistedWorkspaceId } from './workspace/workspaceLocalState';
|
|
65
|
+
import { areFilterTaxonomySignaturesEqual, buildFilterTaxonomySignature, clearPersistedWorkspaceId, logBootstrapDebug, persistRemoteUiState, readPersistedAppUiState, readPersistedWorkspaceId, writePersistedAppUiState, writePersistedWorkspaceId } from './workspace/workspaceLocalState';
|
|
66
66
|
import { useTaskforceApiRouting } from './workspace/useTaskforceApiRouting';
|
|
67
67
|
import { useTaskforceAuthBootstrap } from './auth/useTaskforceAuthBootstrap';
|
|
68
68
|
import { deriveAuthGuardPolicy } from './auth/useAuthGuardPolicy';
|
|
@@ -442,6 +442,7 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
442
442
|
const authSessionLastCheckedAtRef = useRef(0);
|
|
443
443
|
const authSessionLastResultRef = useRef(hasOptimisticLocalAuth);
|
|
444
444
|
const currentWorkspaceIdRef = useRef(currentWorkspaceId);
|
|
445
|
+
const pendingPersistedTaxonomyUiStateRef = useRef(null);
|
|
445
446
|
const explicitWorkspaceSelectionRef = useRef(null);
|
|
446
447
|
const workspaceTransitionEpochRef = useRef(0);
|
|
447
448
|
const bootstrapTraceSeedRef = useRef((() => {
|
|
@@ -1238,9 +1239,26 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
1238
1239
|
authRequiredForApiRef.current = authRequiredForApi;
|
|
1239
1240
|
isAuthenticatedRef.current = isAuthenticated;
|
|
1240
1241
|
}, [authSessionResolved, authRequiredForApi, isAuthenticated]);
|
|
1242
|
+
const currentFilterTaxonomySignature = useMemo(() => (referenceDataLoaded
|
|
1243
|
+
? buildFilterTaxonomySignature({
|
|
1244
|
+
categories: activeCategories,
|
|
1245
|
+
types: activeTypes,
|
|
1246
|
+
priorities,
|
|
1247
|
+
taxonomies
|
|
1248
|
+
})
|
|
1249
|
+
: null), [activeCategories, activeTypes, priorities, referenceDataLoaded, taxonomies]);
|
|
1241
1250
|
const applyPersistedUiState = useCallback((state, options) => {
|
|
1242
|
-
if (!state)
|
|
1251
|
+
if (!state) {
|
|
1252
|
+
pendingPersistedTaxonomyUiStateRef.current = null;
|
|
1243
1253
|
return;
|
|
1254
|
+
}
|
|
1255
|
+
const hasPersistedTaxonomyFilterState = Array.isArray(state.filterCategories)
|
|
1256
|
+
|| Array.isArray(state.filterPriorities)
|
|
1257
|
+
|| Array.isArray(state.filterTypes)
|
|
1258
|
+
|| (state.filterTaxonomies && typeof state.filterTaxonomies === 'object');
|
|
1259
|
+
if (!hasPersistedTaxonomyFilterState) {
|
|
1260
|
+
pendingPersistedTaxonomyUiStateRef.current = null;
|
|
1261
|
+
}
|
|
1244
1262
|
const hasPersistedFilterState = Array.isArray(state.filterCategories)
|
|
1245
1263
|
|| Array.isArray(state.filterPriorities)
|
|
1246
1264
|
|| Array.isArray(state.filterTypes)
|
|
@@ -1248,6 +1266,20 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
1248
1266
|
|| Array.isArray(state.filterAssignees)
|
|
1249
1267
|
|| typeof state.filterAssigneesAllSelected === 'boolean'
|
|
1250
1268
|
|| (state.filterTaxonomies && typeof state.filterTaxonomies === 'object');
|
|
1269
|
+
const canCompareTaxonomySignature = currentFilterTaxonomySignature !== null;
|
|
1270
|
+
if (hasPersistedTaxonomyFilterState && !canCompareTaxonomySignature) {
|
|
1271
|
+
pendingPersistedTaxonomyUiStateRef.current = {
|
|
1272
|
+
state,
|
|
1273
|
+
skipActiveWorkspaceModule: options?.skipActiveWorkspaceModule
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
const canApplyTaxonomyFilters = hasPersistedTaxonomyFilterState
|
|
1277
|
+
&& canCompareTaxonomySignature
|
|
1278
|
+
&& areFilterTaxonomySignaturesEqual(state.filterTaxonomySignature, currentFilterTaxonomySignature);
|
|
1279
|
+
const shouldResetTaxonomyFilters = hasPersistedTaxonomyFilterState
|
|
1280
|
+
&& canCompareTaxonomySignature
|
|
1281
|
+
&& !canApplyTaxonomyFilters;
|
|
1282
|
+
const taxonomyFiltersAreReady = !hasPersistedTaxonomyFilterState || canApplyTaxonomyFilters || shouldResetTaxonomyFilters;
|
|
1251
1283
|
if (!options?.skipActiveWorkspaceModule) {
|
|
1252
1284
|
if (typeof state.activeWorkspaceModule === 'string') {
|
|
1253
1285
|
setActiveWorkspaceModuleState(state.activeWorkspaceModule);
|
|
@@ -1264,28 +1296,39 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
1264
1296
|
setZenModeState(state.zenMode);
|
|
1265
1297
|
if (typeof state.searchQuery === 'string')
|
|
1266
1298
|
setSearchQuery(state.searchQuery);
|
|
1267
|
-
if (
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1299
|
+
if (canApplyTaxonomyFilters) {
|
|
1300
|
+
if (Array.isArray(state.filterCategories))
|
|
1301
|
+
setFilterCategories(state.filterCategories);
|
|
1302
|
+
if (Array.isArray(state.filterPriorities))
|
|
1303
|
+
setFilterPriorities(state.filterPriorities);
|
|
1304
|
+
if (Array.isArray(state.filterTypes))
|
|
1305
|
+
setFilterTypes(state.filterTypes);
|
|
1306
|
+
if (state.filterTaxonomies && typeof state.filterTaxonomies === 'object')
|
|
1307
|
+
setFilterTaxonomies(state.filterTaxonomies);
|
|
1308
|
+
}
|
|
1309
|
+
else if (shouldResetTaxonomyFilters) {
|
|
1310
|
+
setFilterCategories(activeCategories.map((category) => category.value));
|
|
1311
|
+
setFilterPriorities(priorities.map((priority) => priority.value));
|
|
1312
|
+
setFilterTypes(activeTypes.map((type) => type.value));
|
|
1313
|
+
setFilterTaxonomies({});
|
|
1314
|
+
}
|
|
1273
1315
|
if (Array.isArray(state.filterStatus))
|
|
1274
1316
|
setFilterStatus(state.filterStatus);
|
|
1275
1317
|
if (Array.isArray(state.filterAssignees))
|
|
1276
1318
|
setFilterAssignees(state.filterAssignees);
|
|
1277
1319
|
if (typeof state.filterAssigneesAllSelected === 'boolean')
|
|
1278
1320
|
setFilterAssigneesAllSelected(state.filterAssigneesAllSelected);
|
|
1279
|
-
if (state.filterTaxonomies && typeof state.filterTaxonomies === 'object')
|
|
1280
|
-
setFilterTaxonomies(state.filterTaxonomies);
|
|
1281
1321
|
if (state.sortBy === 'created' || state.sortBy === 'priority' || state.sortBy === 'updated' || state.sortBy === 'complexity')
|
|
1282
1322
|
setSortBy(state.sortBy);
|
|
1283
1323
|
if (state.sortOrder === 'asc' || state.sortOrder === 'desc')
|
|
1284
1324
|
setSortOrder(state.sortOrder);
|
|
1285
|
-
if (
|
|
1325
|
+
if (shouldResetTaxonomyFilters) {
|
|
1326
|
+
setHasInitedFilters(true);
|
|
1327
|
+
}
|
|
1328
|
+
else if (typeof state.hasInitedFilters === 'boolean' && taxonomyFiltersAreReady) {
|
|
1286
1329
|
setHasInitedFilters(state.hasInitedFilters);
|
|
1287
1330
|
}
|
|
1288
|
-
else if (hasPersistedFilterState) {
|
|
1331
|
+
else if (hasPersistedFilterState && taxonomyFiltersAreReady) {
|
|
1289
1332
|
setHasInitedFilters(true);
|
|
1290
1333
|
}
|
|
1291
1334
|
if (typeof state.showChecklist === 'boolean')
|
|
@@ -1295,7 +1338,16 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
1295
1338
|
if (typeof state.exportEnvironment === 'string' && state.exportEnvironment.trim().length > 0) {
|
|
1296
1339
|
setExportEnvironment(state.exportEnvironment.trim());
|
|
1297
1340
|
}
|
|
1298
|
-
}, []);
|
|
1341
|
+
}, [activeCategories, activeTypes, currentFilterTaxonomySignature, priorities]);
|
|
1342
|
+
useEffect(() => {
|
|
1343
|
+
if (!currentFilterTaxonomySignature || !pendingPersistedTaxonomyUiStateRef.current)
|
|
1344
|
+
return;
|
|
1345
|
+
const pending = pendingPersistedTaxonomyUiStateRef.current;
|
|
1346
|
+
pendingPersistedTaxonomyUiStateRef.current = null;
|
|
1347
|
+
applyPersistedUiState(pending.state, {
|
|
1348
|
+
skipActiveWorkspaceModule: pending.skipActiveWorkspaceModule
|
|
1349
|
+
});
|
|
1350
|
+
}, [applyPersistedUiState, currentFilterTaxonomySignature]);
|
|
1299
1351
|
const loadPersistedUiState = useCallback(async (workspaceIdOverride) => {
|
|
1300
1352
|
const targetWorkspaceId = String(workspaceIdOverride || currentWorkspaceIdRef.current || currentWorkspaceId || 'default').trim() || 'default';
|
|
1301
1353
|
const uiStateLoadKey = `${runtimeMode}:${workspaceUiStateScope}:${targetWorkspaceId}`;
|
|
@@ -1369,6 +1421,7 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
1369
1421
|
filterAssignees,
|
|
1370
1422
|
filterAssigneesAllSelected,
|
|
1371
1423
|
filterTaxonomies,
|
|
1424
|
+
...(currentFilterTaxonomySignature ? { filterTaxonomySignature: currentFilterTaxonomySignature } : {}),
|
|
1372
1425
|
sortBy,
|
|
1373
1426
|
sortOrder,
|
|
1374
1427
|
hasInitedFilters,
|
|
@@ -1404,6 +1457,7 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
1404
1457
|
filterAssignees,
|
|
1405
1458
|
filterAssigneesAllSelected,
|
|
1406
1459
|
filterTaxonomies,
|
|
1460
|
+
currentFilterTaxonomySignature,
|
|
1407
1461
|
sortBy,
|
|
1408
1462
|
sortOrder,
|
|
1409
1463
|
hasInitedFilters,
|
|
@@ -2557,6 +2611,9 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
2557
2611
|
setInitiatives((current) => upsertEntityById(current, data));
|
|
2558
2612
|
return data;
|
|
2559
2613
|
}, [fetchPlanningEntities]);
|
|
2614
|
+
const refreshPlanningEntitiesInBackground = useCallback(() => {
|
|
2615
|
+
void fetchPlanningEntities();
|
|
2616
|
+
}, [fetchPlanningEntities]);
|
|
2560
2617
|
const archiveInitiative = useCallback(async (id) => {
|
|
2561
2618
|
const res = await fetch(`/api/taskforce/initiative/${encodeURIComponent(id)}/archive`, {
|
|
2562
2619
|
method: 'POST',
|
|
@@ -2565,10 +2622,10 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
2565
2622
|
if (!res.ok) {
|
|
2566
2623
|
throw new Error(data?.error || `Failed to archive initiative (${res.status})`);
|
|
2567
2624
|
}
|
|
2568
|
-
await fetchPlanningEntities();
|
|
2569
2625
|
setInitiatives((current) => upsertEntityById(current, data));
|
|
2626
|
+
refreshPlanningEntitiesInBackground();
|
|
2570
2627
|
return data;
|
|
2571
|
-
}, [
|
|
2628
|
+
}, [refreshPlanningEntitiesInBackground]);
|
|
2572
2629
|
const unarchiveInitiative = useCallback(async (id) => {
|
|
2573
2630
|
const res = await fetch(`/api/taskforce/initiative/${encodeURIComponent(id)}/unarchive`, {
|
|
2574
2631
|
method: 'POST',
|
|
@@ -2577,10 +2634,10 @@ export function useTaskforce({ config = {}, initialTaskId, onTaskCountChange, on
|
|
|
2577
2634
|
if (!res.ok) {
|
|
2578
2635
|
throw new Error(data?.error || `Failed to unarchive initiative (${res.status})`);
|
|
2579
2636
|
}
|
|
2580
|
-
await fetchPlanningEntities();
|
|
2581
2637
|
setInitiatives((current) => upsertEntityById(current, data));
|
|
2638
|
+
refreshPlanningEntitiesInBackground();
|
|
2582
2639
|
return data;
|
|
2583
|
-
}, [
|
|
2640
|
+
}, [refreshPlanningEntitiesInBackground]);
|
|
2584
2641
|
const createWorkstream = useCallback(async (payload) => {
|
|
2585
2642
|
const res = await fetch('/api/taskforce/workstream', {
|
|
2586
2643
|
method: 'POST',
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { TaskAssignee } from '../../types';
|
|
2
2
|
import type { TaskSortKey } from '../../utils/taxonomySorting.js';
|
|
3
|
+
export interface FilterTaxonomySignature {
|
|
4
|
+
categories: string[];
|
|
5
|
+
types: string[];
|
|
6
|
+
priorities: string[];
|
|
7
|
+
taxonomies: Record<string, string[]>;
|
|
8
|
+
}
|
|
3
9
|
export interface PersistedUiState {
|
|
4
10
|
groupBy?: 'category' | 'type' | 'priority' | 'approach' | 'assignee' | 'status' | 'complexity' | 'schedule' | 'docs';
|
|
5
11
|
activeWorkspaceModule?: 'tasks' | 'docs' | 'annotate' | 'workflows' | 'agents';
|
|
@@ -13,6 +19,7 @@ export interface PersistedUiState {
|
|
|
13
19
|
filterAssignees?: TaskAssignee[];
|
|
14
20
|
filterAssigneesAllSelected?: boolean;
|
|
15
21
|
filterTaxonomies?: Record<string, (string | number)[]>;
|
|
22
|
+
filterTaxonomySignature?: FilterTaxonomySignature;
|
|
16
23
|
sortBy?: TaskSortKey;
|
|
17
24
|
sortOrder?: 'asc' | 'desc';
|
|
18
25
|
hasInitedFilters?: boolean;
|
|
@@ -28,6 +35,24 @@ type RemoteUiStatePersistResult = {
|
|
|
28
35
|
response?: Response;
|
|
29
36
|
payload?: any;
|
|
30
37
|
};
|
|
38
|
+
export declare function buildFilterTaxonomySignature(input: {
|
|
39
|
+
categories: Array<{
|
|
40
|
+
value?: unknown;
|
|
41
|
+
}>;
|
|
42
|
+
types: Array<{
|
|
43
|
+
value?: unknown;
|
|
44
|
+
}>;
|
|
45
|
+
priorities: Array<{
|
|
46
|
+
value?: unknown;
|
|
47
|
+
}>;
|
|
48
|
+
taxonomies?: Array<{
|
|
49
|
+
id?: unknown;
|
|
50
|
+
options?: Array<{
|
|
51
|
+
value?: unknown;
|
|
52
|
+
}>;
|
|
53
|
+
}>;
|
|
54
|
+
}): FilterTaxonomySignature | null;
|
|
55
|
+
export declare function areFilterTaxonomySignaturesEqual(left: FilterTaxonomySignature | null | undefined, right: FilterTaxonomySignature | null | undefined): boolean;
|
|
31
56
|
export declare function generateClientUuid(): string;
|
|
32
57
|
export declare function logBootstrapDebug(event: string, details?: Record<string, unknown>): void;
|
|
33
58
|
export declare function resetRemoteUiStatePersistCache(): void;
|
|
@@ -4,6 +4,44 @@ const APP_UI_STATE_STORAGE_KEY_PREFIX = 'taskforce.uiState.app.v1';
|
|
|
4
4
|
const BOOTSTRAP_DEBUG_LOG_KEY = 'taskforce.bootstrapDebug.v1';
|
|
5
5
|
const REMOTE_UI_STATE_FAILURE_RETRY_MS = 5000;
|
|
6
6
|
const remoteUiStatePersistCache = new Map();
|
|
7
|
+
function normalizeSignatureValues(values) {
|
|
8
|
+
return Array.from(new Set(values
|
|
9
|
+
.map((value) => String(value ?? '').trim())
|
|
10
|
+
.filter((value) => value.length > 0))).sort();
|
|
11
|
+
}
|
|
12
|
+
export function buildFilterTaxonomySignature(input) {
|
|
13
|
+
const categories = normalizeSignatureValues(input.categories.map((category) => category.value));
|
|
14
|
+
const types = normalizeSignatureValues(input.types.map((type) => type.value));
|
|
15
|
+
const priorities = normalizeSignatureValues(input.priorities.map((priority) => priority.value));
|
|
16
|
+
if (categories.length === 0 || types.length === 0 || priorities.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
const taxonomies = {};
|
|
19
|
+
(input.taxonomies || []).forEach((taxonomy) => {
|
|
20
|
+
const id = String(taxonomy.id ?? '').trim();
|
|
21
|
+
if (!id)
|
|
22
|
+
return;
|
|
23
|
+
taxonomies[id] = normalizeSignatureValues((taxonomy.options || []).map((option) => option.value));
|
|
24
|
+
});
|
|
25
|
+
return { categories, types, priorities, taxonomies };
|
|
26
|
+
}
|
|
27
|
+
function haveSameStringValues(left, right) {
|
|
28
|
+
return left.length === right.length && left.every((value, index) => value === right[index]);
|
|
29
|
+
}
|
|
30
|
+
export function areFilterTaxonomySignaturesEqual(left, right) {
|
|
31
|
+
if (!left || !right)
|
|
32
|
+
return false;
|
|
33
|
+
if (!haveSameStringValues(left.categories || [], right.categories || []))
|
|
34
|
+
return false;
|
|
35
|
+
if (!haveSameStringValues(left.types || [], right.types || []))
|
|
36
|
+
return false;
|
|
37
|
+
if (!haveSameStringValues(left.priorities || [], right.priorities || []))
|
|
38
|
+
return false;
|
|
39
|
+
const leftTaxonomyKeys = Object.keys(left.taxonomies || {}).sort();
|
|
40
|
+
const rightTaxonomyKeys = Object.keys(right.taxonomies || {}).sort();
|
|
41
|
+
if (!haveSameStringValues(leftTaxonomyKeys, rightTaxonomyKeys))
|
|
42
|
+
return false;
|
|
43
|
+
return leftTaxonomyKeys.every((key) => (haveSameStringValues(left.taxonomies[key] || [], right.taxonomies[key] || [])));
|
|
44
|
+
}
|
|
7
45
|
export function generateClientUuid() {
|
|
8
46
|
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
9
47
|
return crypto.randomUUID();
|
|
@@ -66,16 +66,6 @@ export function registerAdminWorkspaceTools(registerTool, executeTool) {
|
|
|
66
66
|
required: ['types'],
|
|
67
67
|
},
|
|
68
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
69
|
register('bulk_update_fields', (context) => ({
|
|
80
70
|
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
71
|
inputSchema: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AiProfileBootstrapConfig } from './aiProfileBootstrap.js';
|
|
2
|
-
export type McpClientId = 'general' | 'cursor' | 'cline' | 'vscode' | 'windsurf' | 'antigravity' | 'openclaw' | 'codex' | 'claude-code' | 'gemini-cli' | 'claude-desktop' | 'chatgpt-desktop';
|
|
2
|
+
export type McpClientId = 'general' | 'cursor' | 'cline' | 'vscode' | 'kiro' | 'windsurf' | 'antigravity' | 'openclaw' | 'codex' | 'grok' | 'claude-code' | 'gemini-cli' | 'claude-desktop' | 'chatgpt-desktop';
|
|
3
3
|
export interface McpClientOption {
|
|
4
4
|
id: McpClientId;
|
|
5
5
|
label: string;
|
|
@@ -4,10 +4,12 @@ const LOCAL_AI_PROFILE_DEFAULTS = {
|
|
|
4
4
|
cursor: { name: 'Cursor', icon: 'Bot', role: 'IDE coding assistant', provider: 'Cursor', model: 'Cursor', surfaceType: 'ide' },
|
|
5
5
|
cline: { name: 'Cline', icon: 'Bot', role: 'IDE coding assistant', provider: 'Cline', model: 'Cline', surfaceType: 'ide' },
|
|
6
6
|
vscode: { name: 'VS Code Copilot', icon: 'Bot', role: 'IDE coding assistant', provider: 'Microsoft', model: 'Copilot', surfaceType: 'ide' },
|
|
7
|
+
kiro: { name: 'Kiro', icon: 'Bot', role: 'IDE coding assistant', provider: 'Amazon', model: 'Kiro', surfaceType: 'ide' },
|
|
7
8
|
windsurf: { name: 'Windsurf', icon: 'Bot', role: 'IDE coding assistant', provider: 'Windsurf', model: 'Windsurf', surfaceType: 'ide' },
|
|
8
9
|
antigravity: { name: 'Antigravity', icon: 'Bot', role: 'Coding agent', provider: 'Google', model: 'Antigravity', surfaceType: 'coding_tool' },
|
|
9
10
|
openclaw: { name: 'OpenClaw', icon: 'Bot', role: 'AI agent', provider: 'OpenClaw', model: 'OpenClaw', surfaceType: 'agent' },
|
|
10
11
|
codex: { name: 'Codex', icon: 'Bot', role: 'Coding agent', provider: 'OpenAI', model: 'Codex', surfaceType: 'cli' },
|
|
12
|
+
grok: { name: 'Grok CLI', icon: 'Bot', role: 'Coding agent', provider: 'xAI', model: 'Grok CLI', surfaceType: 'cli' },
|
|
11
13
|
'claude-code': { name: 'Claude Code', icon: 'Bot', role: 'Coding agent', provider: 'Anthropic', model: 'Claude Code', surfaceType: 'cli' },
|
|
12
14
|
'gemini-cli': { name: 'Gemini CLI', icon: 'Bot', role: 'Coding agent', provider: 'Google', model: 'Gemini CLI', surfaceType: 'cli' },
|
|
13
15
|
'claude-desktop': { name: 'Claude Desktop', icon: 'Bot', role: 'Desktop AI collaborator', provider: 'Anthropic', model: 'Claude Desktop', surfaceType: 'chat_app' },
|
|
@@ -32,6 +34,8 @@ export const MCP_CLIENT_OPTIONS = [
|
|
|
32
34
|
{ id: 'codex', label: 'Codex' },
|
|
33
35
|
{ id: 'cursor', label: 'Cursor' },
|
|
34
36
|
{ id: 'gemini-cli', label: 'Gemini CLI' },
|
|
37
|
+
{ id: 'grok', label: 'Grok CLI' },
|
|
38
|
+
{ id: 'kiro', label: 'Kiro' },
|
|
35
39
|
{ id: 'openclaw', label: 'OpenClaw' },
|
|
36
40
|
{ id: 'vscode', label: 'VS Code / Copilot' },
|
|
37
41
|
{ id: 'windsurf', label: 'Windsurf' },
|
|
@@ -149,6 +153,18 @@ export function buildCloudMcpClientIntegration(input) {
|
|
|
149
153
|
instructionLabel: 'VS Code Configuration Instructions',
|
|
150
154
|
instructionText: buildConfigurationInstruction('Open .vscode/mcp.json or MCP: Open User Configuration and add this server under the servers object.')
|
|
151
155
|
};
|
|
156
|
+
case 'kiro':
|
|
157
|
+
return {
|
|
158
|
+
clientId,
|
|
159
|
+
kind: 'json',
|
|
160
|
+
rootKey: 'mcpServers',
|
|
161
|
+
serverConfig: {
|
|
162
|
+
url: endpoint,
|
|
163
|
+
headers
|
|
164
|
+
},
|
|
165
|
+
instructionLabel: 'Kiro Configuration Instructions',
|
|
166
|
+
instructionText: buildConfigurationInstruction('Open .kiro/settings/mcp.json in your workspace (or ~/.kiro/settings/mcp.json for user-level config) and add this server under mcpServers.')
|
|
167
|
+
};
|
|
152
168
|
case 'windsurf':
|
|
153
169
|
return {
|
|
154
170
|
clientId,
|
|
@@ -199,6 +215,18 @@ export function buildCloudMcpClientIntegration(input) {
|
|
|
199
215
|
instructionLabel: 'Codex Configuration Instructions',
|
|
200
216
|
instructionText: buildConfigurationInstruction('Open ~/.codex/config.toml and add this Codex MCP entry.')
|
|
201
217
|
};
|
|
218
|
+
case 'grok':
|
|
219
|
+
return {
|
|
220
|
+
clientId,
|
|
221
|
+
kind: 'text',
|
|
222
|
+
renderedText: [
|
|
223
|
+
`[mcp_servers.${serverId}]`,
|
|
224
|
+
`url = "${endpoint}"`,
|
|
225
|
+
`headers = { ${Object.entries(headers).map(([key, value]) => `${key} = "${value}"`).join(', ')} }`
|
|
226
|
+
].join('\n'),
|
|
227
|
+
instructionLabel: 'Grok CLI Configuration Instructions',
|
|
228
|
+
instructionText: buildConfigurationInstruction('Open ~/.grok/config.toml (or .grok/config.toml in your project for project-scoped config) and add this Grok CLI MCP entry.')
|
|
229
|
+
};
|
|
202
230
|
case 'claude-code':
|
|
203
231
|
return {
|
|
204
232
|
clientId,
|
|
@@ -288,6 +316,15 @@ export function buildLocalMcpClientIntegration(input) {
|
|
|
288
316
|
instructionLabel: 'VS Code Configuration Instructions',
|
|
289
317
|
instructionText: buildLocalConfigurationInstruction('Open .vscode/mcp.json or MCP: Open User Configuration and add this server under the servers object.')
|
|
290
318
|
};
|
|
319
|
+
case 'kiro':
|
|
320
|
+
return {
|
|
321
|
+
clientId,
|
|
322
|
+
kind: 'json',
|
|
323
|
+
rootKey: 'mcpServers',
|
|
324
|
+
serverConfig: baseStdioConfig,
|
|
325
|
+
instructionLabel: 'Kiro Configuration Instructions',
|
|
326
|
+
instructionText: buildLocalConfigurationInstruction('Open .kiro/settings/mcp.json in your workspace (or ~/.kiro/settings/mcp.json for user-level config) and add this server under mcpServers.')
|
|
327
|
+
};
|
|
291
328
|
case 'windsurf':
|
|
292
329
|
return {
|
|
293
330
|
clientId,
|
|
@@ -332,6 +369,19 @@ export function buildLocalMcpClientIntegration(input) {
|
|
|
332
369
|
instructionLabel: 'Codex Configuration Instructions',
|
|
333
370
|
instructionText: buildLocalConfigurationInstruction('Open ~/.codex/config.toml and add this local MCP entry.')
|
|
334
371
|
};
|
|
372
|
+
case 'grok':
|
|
373
|
+
return {
|
|
374
|
+
clientId,
|
|
375
|
+
kind: 'text',
|
|
376
|
+
renderedText: [
|
|
377
|
+
`[mcp_servers.${serverId}]`,
|
|
378
|
+
`command = ${formatTomlString(serverConfig.command)}`,
|
|
379
|
+
`args = ${formatTomlArray(serverConfig.args)}`,
|
|
380
|
+
...buildTomlEnvAssignment(serverConfig.env)
|
|
381
|
+
].join('\n'),
|
|
382
|
+
instructionLabel: 'Grok CLI Configuration Instructions',
|
|
383
|
+
instructionText: buildLocalConfigurationInstruction('Open ~/.grok/config.toml (or .grok/config.toml in your project for project-scoped config) and add this local Grok CLI MCP entry.')
|
|
384
|
+
};
|
|
335
385
|
case 'claude-code':
|
|
336
386
|
return {
|
|
337
387
|
clientId,
|
|
@@ -16,8 +16,12 @@ export function getDefaultAiProfileMetadataForClient(clientId) {
|
|
|
16
16
|
return { icon: 'MessageSquareMore', color: '#d97706', description: 'Claude Desktop connected through the Taskforce MCP connector.', role: 'AI Assistant', provider: 'Anthropic', model: 'Claude', surfaceType: 'chat_app' };
|
|
17
17
|
case 'gemini-cli':
|
|
18
18
|
return { icon: 'Gem', color: '#2563eb', description: 'Gemini CLI coding agent connected through MCP.', role: 'CLI Coding Agent', provider: 'Google', model: 'Gemini', surfaceType: 'cli' };
|
|
19
|
+
case 'grok':
|
|
20
|
+
return { icon: 'Sparkles', color: '#111827', description: 'Grok CLI coding agent connected through MCP.', role: 'CLI Coding Agent', provider: 'xAI', model: 'Grok CLI', surfaceType: 'cli' };
|
|
19
21
|
case 'vscode':
|
|
20
22
|
return { icon: 'Code2', color: '#2563eb', description: 'VS Code MCP-connected coding agent.', role: 'Coding Agent', provider: null, model: null, surfaceType: 'ide' };
|
|
23
|
+
case 'kiro':
|
|
24
|
+
return { icon: 'Bot', color: '#7c3aed', description: 'Kiro IDE-connected AI assistant.', role: 'IDE coding assistant', provider: 'Amazon', model: null, surfaceType: 'ide' };
|
|
21
25
|
case 'cline':
|
|
22
26
|
case 'windsurf':
|
|
23
27
|
case 'antigravity':
|
|
@@ -23,11 +23,11 @@ export function registerCollaborationTools(registerTool, executeTool) {
|
|
|
23
23
|
});
|
|
24
24
|
};
|
|
25
25
|
register('list_assignees', (context) => ({
|
|
26
|
-
description: context.describeTool('List eligible assignees for the active workspace. Returns human workspace members and AI profiles that can own tasks. Use this before create_task, update_task,
|
|
26
|
+
description: context.describeTool('List eligible assignees for the active workspace. Returns human workspace members and AI profiles that can own tasks. Use this before create_task, update_task, or bulk_update_fields when you need a valid assignee ID.'),
|
|
27
27
|
inputSchema: { properties: {} },
|
|
28
28
|
}));
|
|
29
29
|
register('get_current_profile', (context) => ({
|
|
30
|
-
description: context.describeTool('Inspect
|
|
30
|
+
description: context.describeTool('Inspect current AI identity for this call (ambient session, connection bootstrap, or explicit profileToken). Returns identityBound (true if this invocation has a resolved identity), bindingSource, profile, taskFilter, suggestedArgs, and guidance. Stateless/scheduled agents: call with profileToken if no ambient bind; use the returned suggestedArgs (with assignee) for list_tasks and pass profileToken on writes. Call before mutating or to decide on resolve_profile.'),
|
|
31
31
|
inputSchema: {
|
|
32
32
|
properties: {
|
|
33
33
|
profileToken: stringProperty('Optional AI profile token to inspect when no profile is currently bound in session state. Pass only a token previously issued to this AI identity.'),
|
|
@@ -35,7 +35,7 @@ export function registerCollaborationTools(registerTool, executeTool) {
|
|
|
35
35
|
},
|
|
36
36
|
}));
|
|
37
37
|
register('resolve_profile', (context) => ({
|
|
38
|
-
description: context.describeTool('Resolve or create
|
|
38
|
+
description: context.describeTool('Resolve or create this AI collaborator profile. For stateless agents (no ambient binding): call with name + surfaceType (and profileToken to re-use); the response includes created, profileToken, profile, *plus* identityBound, bindingSource, taskFilter, suggestedArgs, nextTool, guidance. Store profileToken privately only. Use suggestedArgs for list_tasks; pass profileToken on mutating calls. Never write profileToken to repos, tasks, logs, or docs.'),
|
|
39
39
|
inputSchema: {
|
|
40
40
|
properties: {
|
|
41
41
|
name: stringProperty('Display name for the AI collaborator.'),
|
|
@@ -31,44 +31,27 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
|
|
|
31
31
|
});
|
|
32
32
|
};
|
|
33
33
|
register('get_task_attachments', (context) => ({
|
|
34
|
-
description: context.describeTool('List attachment descriptors for one task.
|
|
34
|
+
description: context.describeTool('List attachment descriptors for one task. Pass attachmentId when you need one attachment body or download reference. For canonical documents, prefer get_document with includeContent=true for the document-focused workflow.'),
|
|
35
35
|
inputSchema: {
|
|
36
36
|
properties: {
|
|
37
37
|
taskId: stringProperty('Task ID or task reference such as T-123.'),
|
|
38
38
|
id: stringProperty('Alias for taskId. Task ID or task reference such as T-123.'),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
}));
|
|
42
|
-
register('read_task_attachment', (context) => ({
|
|
43
|
-
description: context.describeTool('Read one task attachment by attachmentId. Prefer this tool over opening attachment path URLs directly. For a canonical document attachment, this response also points toward the document-specific workflow.'),
|
|
44
|
-
inputSchema: {
|
|
45
|
-
properties: {
|
|
46
|
-
taskId: stringProperty('Task ID or task reference such as T-123.'),
|
|
47
|
-
attachmentId: stringProperty('Attachment descriptor id from get_task_attachments.'),
|
|
39
|
+
attachmentId: stringProperty('Optional attachment descriptor id to include content for one attachment.'),
|
|
40
|
+
format: stringProperty('Optional read format when attachmentId is provided. Use metadata for descriptors or download for a download URL.', ['text', 'metadata', 'download']),
|
|
48
41
|
maxChars: numberProperty('Optional max inline character count for readable text attachments.'),
|
|
49
42
|
},
|
|
50
|
-
required: ['taskId', 'attachmentId'],
|
|
51
43
|
},
|
|
52
44
|
}));
|
|
53
45
|
register('get_workstream_attachments', (context) => ({
|
|
54
|
-
description: context.describeTool('List attachment descriptors for one workstream.
|
|
46
|
+
description: context.describeTool('List attachment descriptors for one workstream. Pass attachmentId when you need one attachment body or download reference.'),
|
|
55
47
|
inputSchema: {
|
|
56
48
|
properties: {
|
|
57
49
|
id: stringProperty('Workstream ID or workstream reference such as WS-123.'),
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
},
|
|
61
|
-
}));
|
|
62
|
-
register('read_workstream_attachment', (context) => ({
|
|
63
|
-
description: context.describeTool('Read one workstream attachment by attachmentId. Prefer this tool over opening attachment path URLs directly.'),
|
|
64
|
-
inputSchema: {
|
|
65
|
-
properties: {
|
|
66
|
-
workstreamId: stringProperty('Workstream ID or workstream reference such as WS-123.'),
|
|
67
|
-
attachmentId: stringProperty('Attachment descriptor id from get_workstream_attachments.'),
|
|
68
|
-
format: stringProperty('Read format. Use metadata for descriptors or download for a download URL.', ['text', 'metadata', 'download']),
|
|
50
|
+
attachmentId: stringProperty('Optional attachment descriptor id to include content for one attachment.'),
|
|
51
|
+
format: stringProperty('Optional read format when attachmentId is provided. Use metadata for descriptors or download for a download URL.', ['text', 'metadata', 'download']),
|
|
69
52
|
maxChars: numberProperty('Optional max inline character count for readable text attachments.'),
|
|
70
53
|
},
|
|
71
|
-
required: ['
|
|
54
|
+
required: ['id'],
|
|
72
55
|
},
|
|
73
56
|
}));
|
|
74
57
|
register('save_workstream_attachment', (context) => ({
|
|
@@ -96,24 +79,15 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
|
|
|
96
79
|
},
|
|
97
80
|
}));
|
|
98
81
|
register('get_initiative_attachments', (context) => ({
|
|
99
|
-
description: context.describeTool('List attachment descriptors for one initiative.
|
|
82
|
+
description: context.describeTool('List attachment descriptors for one initiative. Pass attachmentId when you need one attachment body or download reference.'),
|
|
100
83
|
inputSchema: {
|
|
101
84
|
properties: {
|
|
102
85
|
id: stringProperty('Initiative ID or initiative reference such as IN-123.'),
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
},
|
|
106
|
-
}));
|
|
107
|
-
register('read_initiative_attachment', (context) => ({
|
|
108
|
-
description: context.describeTool('Read one initiative attachment by attachmentId. Prefer this tool over opening attachment path URLs directly.'),
|
|
109
|
-
inputSchema: {
|
|
110
|
-
properties: {
|
|
111
|
-
initiativeId: stringProperty('Initiative ID or initiative reference such as IN-123.'),
|
|
112
|
-
attachmentId: stringProperty('Attachment descriptor id from get_initiative_attachments.'),
|
|
113
|
-
format: stringProperty('Read format. Use metadata for descriptors or download for a download URL.', ['text', 'metadata', 'download']),
|
|
86
|
+
attachmentId: stringProperty('Optional attachment descriptor id to include content for one attachment.'),
|
|
87
|
+
format: stringProperty('Optional read format when attachmentId is provided. Use metadata for descriptors or download for a download URL.', ['text', 'metadata', 'download']),
|
|
114
88
|
maxChars: numberProperty('Optional max inline character count for readable text attachments.'),
|
|
115
89
|
},
|
|
116
|
-
required: ['
|
|
90
|
+
required: ['id'],
|
|
117
91
|
},
|
|
118
92
|
}));
|
|
119
93
|
register('save_initiative_attachment', (context) => ({
|
|
@@ -151,7 +125,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
|
|
|
151
125
|
},
|
|
152
126
|
}));
|
|
153
127
|
register('get_image', (context) => ({
|
|
154
|
-
description: context.describeTool('Get a single image by asset id or image reference such as I-123. Use this first when the user references an image, then use
|
|
128
|
+
description: context.describeTool('Get a single image by asset id or image reference such as I-123. Use this first when the user references an image, then use get_image_annotations for saved annotation sessions and payloads. When the image is being used for UI, placement, or visual correction feedback, read the saved annotation payload before making changes.'),
|
|
155
129
|
inputSchema: {
|
|
156
130
|
properties: {
|
|
157
131
|
id: stringProperty('Image asset id or image reference such as I-123.'),
|
|
@@ -160,7 +134,7 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
|
|
|
160
134
|
},
|
|
161
135
|
}));
|
|
162
136
|
register('search_documents', (context) => ({
|
|
163
|
-
description: context.describeTool('Search document assets by keyword, title, filename, caption, or D-123 reference. Use this before get_document when you only know a rough identifier. Search results guide the next step into get_document
|
|
137
|
+
description: context.describeTool('Search document assets by keyword, title, filename, caption, or D-123 reference. Use this before get_document when you only know a rough identifier. Search results guide the next step into get_document.'),
|
|
164
138
|
inputSchema: {
|
|
165
139
|
properties: {
|
|
166
140
|
query: stringProperty('Search term for document lookup, including D-123 references.'),
|
|
@@ -170,40 +144,26 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
|
|
|
170
144
|
},
|
|
171
145
|
}));
|
|
172
146
|
register('get_document', (context) => ({
|
|
173
|
-
description: context.describeTool('Get a single canonical document by asset id or document reference such as D-123.
|
|
147
|
+
description: context.describeTool('Get a single canonical document by asset id or document reference such as D-123. Pass includeContent=true when you need the document body for review or analysis.'),
|
|
174
148
|
inputSchema: {
|
|
175
149
|
properties: {
|
|
176
150
|
id: stringProperty('Document asset id or document reference such as D-123.'),
|
|
177
151
|
documentId: stringProperty('Alias for id. Document asset id or document reference such as D-123.'),
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}));
|
|
181
|
-
register('read_document_content', (context) => ({
|
|
182
|
-
description: context.describeTool('Read the canonical document body for one document. Use this when an AI needs to inspect what it is reviewing before adding review comments.'),
|
|
183
|
-
inputSchema: {
|
|
184
|
-
properties: {
|
|
185
|
-
documentId: stringProperty('Document asset id or document reference such as D-123.'),
|
|
152
|
+
includeContent: booleanProperty('When true, include bounded inline text content or a download reference for binary documents.'),
|
|
153
|
+
format: stringProperty('Optional read mode when including content.', ['metadata', 'text', 'content', 'full', 'download']),
|
|
186
154
|
maxChars: numberProperty('Optional max inline character count for readable documents.'),
|
|
187
155
|
},
|
|
188
|
-
required: ['documentId'],
|
|
189
156
|
},
|
|
190
157
|
}));
|
|
191
|
-
register('
|
|
192
|
-
description: context.describeTool('List saved annotation sessions for one image. Use this after get_image when
|
|
158
|
+
register('get_image_annotations', (context) => ({
|
|
159
|
+
description: context.describeTool('List saved annotation sessions for one image or task, and optionally include one session payload. Use this after get_image when an image reference such as I-123 is being used for UI, placement, or visual correction feedback. Pass sessionId when you need the authoritative payload for a specific saved session.'),
|
|
193
160
|
inputSchema: {
|
|
194
161
|
properties: {
|
|
195
162
|
imageId: stringProperty('Image asset id or image reference such as I-123.'),
|
|
163
|
+
imageAssetId: stringProperty('Alias for imageId. Image asset id or image reference such as I-123.'),
|
|
164
|
+
taskId: stringProperty('Optional task ID or task reference such as T-123 to narrow sessions linked to one task.'),
|
|
165
|
+
sessionId: stringProperty('Optional annotated attachment session id to include the structured payload for one session.'),
|
|
196
166
|
},
|
|
197
|
-
required: ['imageId'],
|
|
198
|
-
},
|
|
199
|
-
}));
|
|
200
|
-
register('read_annotated_attachment_payload', (context) => ({
|
|
201
|
-
description: context.describeTool('Read the structured payload for one annotated attachment session, including markers, geometry, and derived crop hints. Use this as the authoritative instruction source when I-123 is being used for UI placement or visual change requests.'),
|
|
202
|
-
inputSchema: {
|
|
203
|
-
properties: {
|
|
204
|
-
sessionId: stringProperty('Annotated attachment session id.'),
|
|
205
|
-
},
|
|
206
|
-
required: ['sessionId'],
|
|
207
167
|
},
|
|
208
168
|
}));
|
|
209
169
|
register('create_annotated_attachment_session', (context) => ({
|
|
@@ -320,22 +280,14 @@ export function registerDocumentAssetTools(registerTool, executeTool) {
|
|
|
320
280
|
required: ['sessionId', 'markerId'],
|
|
321
281
|
},
|
|
322
282
|
}));
|
|
323
|
-
register('
|
|
324
|
-
description: context.describeTool('List review sessions for one document such as D-123. Use
|
|
283
|
+
register('get_document_reviews', (context) => ({
|
|
284
|
+
description: context.describeTool('List review sessions for one document such as D-123, or fetch one review session by sessionId. Use get_document with includeContent=true when you need the document body before choosing a session.'),
|
|
325
285
|
inputSchema: {
|
|
326
286
|
properties: {
|
|
327
287
|
documentId: stringProperty('Document asset id or document reference such as D-123.'),
|
|
328
|
-
|
|
329
|
-
required: ['documentId'],
|
|
330
|
-
},
|
|
331
|
-
}));
|
|
332
|
-
register('get_document_review_session', (context) => ({
|
|
333
|
-
description: context.describeTool('Get one document review session with its comments and summary state.'),
|
|
334
|
-
inputSchema: {
|
|
335
|
-
properties: {
|
|
288
|
+
id: stringProperty('Alias for documentId. Document asset id or document reference such as D-123.'),
|
|
336
289
|
sessionId: stringProperty('Document review session id.'),
|
|
337
290
|
},
|
|
338
|
-
required: ['sessionId'],
|
|
339
291
|
},
|
|
340
292
|
}));
|
|
341
293
|
register('create_document_review_session', (context) => ({
|