@hauptsache.net/clickup-mcp 1.1.0 → 1.2.0

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.
@@ -1,4 +1,3 @@
1
- import { ContentBlock } from "./types";
2
1
  import Fuse from 'fuse.js';
3
2
  /**
4
3
  * Checks if a string looks like a valid ClickUp task ID
@@ -7,24 +6,76 @@ import Fuse from 'fuse.js';
7
6
  export declare function isTaskId(str: string): boolean;
8
7
  /**
9
8
  * Get current authenticated user information from ClickUp API
10
- * Caches the result after first successful fetch to avoid repeated API calls during the session
9
+ * Caches the promise to prevent race conditions on concurrent calls
11
10
  */
12
11
  export declare function getCurrentUser(): Promise<any>;
13
- /**
14
- * Limits the number of images in the content array, replacing excess images with text placeholders
15
- * Prioritizes keeping the most recent images (assumes content is ordered with newest items last)
16
- *
17
- * @param content Array of content blocks that may contain images
18
- * @param maxImages Maximum number of images to keep
19
- * @returns Modified content array with limited images
20
- */
21
- export declare function limitImages(content: ContentBlock[], maxImages: number): ContentBlock[];
12
+ export { downloadImages } from "./image-processing";
22
13
  /**
23
14
  * Function to get space details, using a cache to avoid redundant fetches
24
15
  */
25
16
  export declare function getSpaceDetails(spaceId: string): Promise<any>;
26
17
  /**
27
18
  * Get or create a task search index with specified filters
19
+ * Caches promises to prevent race conditions on concurrent calls
28
20
  */
29
21
  export declare function getTaskSearchIndex(space_ids?: string[], list_ids?: string[], assignees?: string[]): Promise<Fuse<any> | null>;
22
+ /**
23
+ * Generate a ClickUp task URL from a task ID
24
+ */
25
+ export declare function generateTaskUrl(taskId: string): string;
26
+ /**
27
+ * Generate a ClickUp list URL from a list ID
28
+ */
29
+ export declare function generateListUrl(listId: string): string;
30
+ /**
31
+ * Generate a ClickUp space URL from a space ID
32
+ */
33
+ export declare function generateSpaceUrl(spaceId: string): string;
34
+ /**
35
+ * Generate a ClickUp folder URL from a folder ID
36
+ */
37
+ export declare function generateFolderUrl(folderId: string): string;
38
+ /**
39
+ * Format a ClickUp task link as markdown
40
+ */
41
+ export declare function formatTaskLink(taskId: string, taskName?: string): string;
42
+ /**
43
+ * Format a ClickUp list link as markdown
44
+ */
45
+ export declare function formatListLink(listId: string, listName?: string): string;
46
+ /**
47
+ * Format a ClickUp space link as markdown
48
+ */
49
+ export declare function formatSpaceLink(spaceId: string, spaceName?: string): string;
50
+ /**
51
+ * Extract task ID from a ClickUp URL
52
+ */
53
+ export declare function extractTaskIdFromUrl(url: string): string | null;
54
+ /**
55
+ * Validate if a string is a valid ClickUp URL
56
+ */
57
+ export declare function isClickUpUrl(url: string): boolean;
58
+ /**
59
+ * Format a prominent link section for responses
60
+ */
61
+ export declare function formatLinksSection(links: {
62
+ text: string;
63
+ url: string;
64
+ }[]): string;
65
+ /**
66
+ * Get or refresh the space search index
67
+ * Caches promise to prevent race conditions on concurrent calls
68
+ */
69
+ export declare function getSpaceSearchIndex(): Promise<Fuse<any> | null>;
70
+ /**
71
+ * Get lists and folders for a specific space with caching
72
+ */
73
+ export declare function getSpaceContent(spaceId: string): Promise<{
74
+ lists: any[];
75
+ folders: any[];
76
+ }>;
77
+ /**
78
+ * Gets all team members from ClickUp API with caching
79
+ */
80
+ export declare function getAllTeamMembers(): Promise<string[]>;
30
81
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,SAAS,CAAC;AAErC,OAAO,IAAI,MAAM,SAAS,CAAC;AAI3B;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAG7C;AAKD;;;GAGG;AACH,wBAAsB,cAAc,iBAiBnC;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,EAAE,CA8BtF;AAID;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA0B7D;AAKD;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,CAAC,EAAE,MAAM,EAAE,EACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,EACnB,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CA4B3B"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/shared/utils.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,SAAS,CAAC;AAI3B;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAG7C;AAKD;;;GAGG;AACH,wBAAsB,cAAc,iBA6BnC;AAGD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CA0B7D;AAKD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,CAAC,EAAE,MAAM,EAAE,EACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,EACnB,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CA+B3B;AAiED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAIxE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAI3E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG/D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG,MAAM,CAKjF;AAKD;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CA+CrE;AAKD;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IAAC,OAAO,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,CAgEhG;AAKD;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CA+C3D"}
@@ -3,11 +3,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.downloadImages = void 0;
6
7
  exports.isTaskId = isTaskId;
7
8
  exports.getCurrentUser = getCurrentUser;
8
- exports.limitImages = limitImages;
9
9
  exports.getSpaceDetails = getSpaceDetails;
10
10
  exports.getTaskSearchIndex = getTaskSearchIndex;
11
+ exports.generateTaskUrl = generateTaskUrl;
12
+ exports.generateListUrl = generateListUrl;
13
+ exports.generateSpaceUrl = generateSpaceUrl;
14
+ exports.generateFolderUrl = generateFolderUrl;
15
+ exports.formatTaskLink = formatTaskLink;
16
+ exports.formatListLink = formatListLink;
17
+ exports.formatSpaceLink = formatSpaceLink;
18
+ exports.extractTaskIdFromUrl = extractTaskIdFromUrl;
19
+ exports.isClickUpUrl = isClickUpUrl;
20
+ exports.formatLinksSection = formatLinksSection;
21
+ exports.getSpaceSearchIndex = getSpaceSearchIndex;
22
+ exports.getSpaceContent = getSpaceContent;
23
+ exports.getAllTeamMembers = getAllTeamMembers;
11
24
  const config_1 = require("./config");
12
25
  const fuse_js_1 = __importDefault(require("fuse.js"));
13
26
  const GLOBAL_REFRESH_INTERVAL = 60000; // 60 seconds - that is the rate limit time frame
@@ -19,62 +32,39 @@ function isTaskId(str) {
19
32
  // Task IDs are 6-9 characters long and contain only alphanumeric characters
20
33
  return /^[a-z0-9]{6,9}$/i.test(str);
21
34
  }
22
- // Cache for current user info to avoid repeated API calls
23
- let cachedUserData = null;
35
+ // Cache for current user info to avoid repeated API calls and race conditions
36
+ let cachedUserPromise = null;
24
37
  /**
25
38
  * Get current authenticated user information from ClickUp API
26
- * Caches the result after first successful fetch to avoid repeated API calls during the session
39
+ * Caches the promise to prevent race conditions on concurrent calls
27
40
  */
28
41
  async function getCurrentUser() {
29
- // Return cached data if available
30
- if (cachedUserData) {
31
- return cachedUserData;
42
+ // Return cached promise if available
43
+ if (cachedUserPromise) {
44
+ return cachedUserPromise;
32
45
  }
33
- const userResponse = await fetch("https://api.clickup.com/api/v2/user", {
34
- headers: { Authorization: config_1.CONFIG.apiKey },
35
- });
36
- if (!userResponse.ok) {
37
- throw new Error(`Error fetching user info: ${userResponse.status} ${userResponse.statusText}`);
38
- }
39
- // Cache the result for future calls
40
- cachedUserData = await userResponse.json();
41
- return cachedUserData;
42
- }
43
- /**
44
- * Limits the number of images in the content array, replacing excess images with text placeholders
45
- * Prioritizes keeping the most recent images (assumes content is ordered with newest items last)
46
- *
47
- * @param content Array of content blocks that may contain images
48
- * @param maxImages Maximum number of images to keep
49
- * @returns Modified content array with limited images
50
- */
51
- function limitImages(content, maxImages) {
52
- // Count how many images we have
53
- const imageIndices = [];
54
- // Find all image blocks
55
- content.forEach((block, index) => {
56
- if (block.type === "image") {
57
- imageIndices.push(index);
58
- }
59
- });
60
- // If we have fewer images than the limit, return the original content
61
- if (imageIndices.length <= maxImages) {
62
- return content;
63
- }
64
- // Determine which images to keep (the most recent ones)
65
- // We want to keep the last 'maxImages' images
66
- const imagesToRemove = imageIndices.slice(0, imageIndices.length - maxImages);
67
- // Create a new content array with excess images replaced by text
68
- return content.map((block, index) => {
69
- if (block.type === "image" && imagesToRemove.includes(index)) {
70
- return {
71
- type: "text",
72
- text: "[Image removed due to size limitations. Only the most recent images are shown.]",
73
- };
46
+ // Create the fetch promise
47
+ const fetchPromise = (async () => {
48
+ const userResponse = await fetch("https://api.clickup.com/api/v2/user", {
49
+ headers: { Authorization: config_1.CONFIG.apiKey },
50
+ });
51
+ if (!userResponse.ok) {
52
+ throw new Error(`Error fetching user info: ${userResponse.status} ${userResponse.statusText}`);
74
53
  }
75
- return block;
76
- });
54
+ return await userResponse.json();
55
+ })();
56
+ // Cache the promise
57
+ cachedUserPromise = fetchPromise;
58
+ // Auto-cleanup after 60 seconds
59
+ setTimeout(() => {
60
+ cachedUserPromise = null;
61
+ console.error(`Auto-cleaned user data cache`);
62
+ }, GLOBAL_REFRESH_INTERVAL);
63
+ return fetchPromise;
77
64
  }
65
+ // Re-export image processing functions for backward compatibility
66
+ var image_processing_1 = require("./image-processing");
67
+ Object.defineProperty(exports, "downloadImages", { enumerable: true, get: function () { return image_processing_1.downloadImages; } });
78
68
  const spaceCache = new Map(); // Global cache for space details promises
79
69
  /**
80
70
  * Function to get space details, using a cache to avoid redundant fetches
@@ -101,10 +91,11 @@ function getSpaceDetails(spaceId) {
101
91
  spaceCache.set(spaceId, fetchPromise);
102
92
  return fetchPromise;
103
93
  }
104
- // Task search index management
94
+ // Task search index management - cache promises to prevent race conditions
105
95
  const taskIndices = new Map();
106
96
  /**
107
97
  * Get or create a task search index with specified filters
98
+ * Caches promises to prevent race conditions on concurrent calls
108
99
  */
109
100
  async function getTaskSearchIndex(space_ids, list_ids, assignees) {
110
101
  // Create cache key from sorted filter arrays
@@ -113,23 +104,26 @@ async function getTaskSearchIndex(space_ids, list_ids, assignees) {
113
104
  list_ids: list_ids?.sort(),
114
105
  assignees: assignees?.sort()
115
106
  });
116
- // Check for existing valid index
117
- const cachedIndex = taskIndices.get(key);
118
- if (cachedIndex) {
119
- return cachedIndex;
107
+ // Check for existing valid index promise
108
+ const cachedPromise = taskIndices.get(key);
109
+ if (cachedPromise) {
110
+ return cachedPromise;
120
111
  }
121
- // Fetch tasks with specified filters
122
- console.error(`Refreshing task index for filters: ${key}`);
123
- const tasks = await fetchTasks(space_ids, list_ids, assignees);
124
- const index = createFuseIndex(tasks);
125
- // Store with auto-cleanup
126
- taskIndices.set(key, index);
112
+ // Create the fetch promise
113
+ const fetchPromise = (async () => {
114
+ console.error(`Refreshing task index for filters: ${key}`);
115
+ const tasks = await fetchTasks(space_ids, list_ids, assignees);
116
+ const index = createFuseIndex(tasks);
117
+ console.error(`Task index created with ${tasks.length} tasks`);
118
+ return index;
119
+ })();
120
+ // Store promise with auto-cleanup
121
+ taskIndices.set(key, fetchPromise);
127
122
  setTimeout(() => {
128
123
  taskIndices.delete(key);
129
124
  console.error(`Auto-cleaned index for filters: ${key}`);
130
125
  }, GLOBAL_REFRESH_INTERVAL);
131
- console.error(`Task index created with ${tasks.length} tasks`);
132
- return index;
126
+ return fetchPromise;
133
127
  }
134
128
  /**
135
129
  * Fetch tasks using team endpoint with dynamic filters
@@ -183,3 +177,227 @@ function createFuseIndex(tasks) {
183
177
  minMatchCharLength: 2,
184
178
  });
185
179
  }
180
+ // ===== LINK UTILITIES =====
181
+ /**
182
+ * Generate a ClickUp task URL from a task ID
183
+ */
184
+ function generateTaskUrl(taskId) {
185
+ return `https://app.clickup.com/t/${taskId}`;
186
+ }
187
+ /**
188
+ * Generate a ClickUp list URL from a list ID
189
+ */
190
+ function generateListUrl(listId) {
191
+ return `https://app.clickup.com/v/l/${listId}`;
192
+ }
193
+ /**
194
+ * Generate a ClickUp space URL from a space ID
195
+ */
196
+ function generateSpaceUrl(spaceId) {
197
+ return `https://app.clickup.com/v/s/${spaceId}`;
198
+ }
199
+ /**
200
+ * Generate a ClickUp folder URL from a folder ID
201
+ */
202
+ function generateFolderUrl(folderId) {
203
+ return `https://app.clickup.com/v/f/${folderId}`;
204
+ }
205
+ /**
206
+ * Format a ClickUp task link as markdown
207
+ */
208
+ function formatTaskLink(taskId, taskName) {
209
+ const url = generateTaskUrl(taskId);
210
+ const displayText = taskName ? `${taskName} (${taskId})` : taskId;
211
+ return `[${displayText}](${url})`;
212
+ }
213
+ /**
214
+ * Format a ClickUp list link as markdown
215
+ */
216
+ function formatListLink(listId, listName) {
217
+ const url = generateListUrl(listId);
218
+ const displayText = listName ? `${listName} (${listId})` : listId;
219
+ return `[${displayText}](${url})`;
220
+ }
221
+ /**
222
+ * Format a ClickUp space link as markdown
223
+ */
224
+ function formatSpaceLink(spaceId, spaceName) {
225
+ const url = generateSpaceUrl(spaceId);
226
+ const displayText = spaceName ? `${spaceName} (${spaceId})` : spaceId;
227
+ return `[${displayText}](${url})`;
228
+ }
229
+ /**
230
+ * Extract task ID from a ClickUp URL
231
+ */
232
+ function extractTaskIdFromUrl(url) {
233
+ const match = url.match(/https?:\/\/app\.clickup\.com\/t\/([a-z0-9]{6,9})/i);
234
+ return match ? match[1] : null;
235
+ }
236
+ /**
237
+ * Validate if a string is a valid ClickUp URL
238
+ */
239
+ function isClickUpUrl(url) {
240
+ return /^https?:\/\/app\.clickup\.com\//.test(url);
241
+ }
242
+ /**
243
+ * Format a prominent link section for responses
244
+ */
245
+ function formatLinksSection(links) {
246
+ if (links.length === 0)
247
+ return '';
248
+ const linkLines = links.map(link => `🔗 [${link.text}](${link.url})`);
249
+ return `\n\n**📌 Quick Links:**\n${linkLines.join('\n')}`;
250
+ }
251
+ // Space search index cache - cache promise to prevent race conditions
252
+ let spaceSearchIndexPromise = null;
253
+ /**
254
+ * Get or refresh the space search index
255
+ * Caches promise to prevent race conditions on concurrent calls
256
+ */
257
+ async function getSpaceSearchIndex() {
258
+ // Return cached promise if available
259
+ if (spaceSearchIndexPromise) {
260
+ return spaceSearchIndexPromise;
261
+ }
262
+ // Create the fetch promise
263
+ const fetchPromise = (async () => {
264
+ try {
265
+ const url = `https://api.clickup.com/api/v2/team/${config_1.CONFIG.teamId}/space`;
266
+ const response = await fetch(url, {
267
+ headers: { Authorization: config_1.CONFIG.apiKey },
268
+ });
269
+ if (!response.ok) {
270
+ throw new Error(`Error fetching spaces: ${response.status} ${response.statusText}`);
271
+ }
272
+ const data = await response.json();
273
+ const spacesData = data.spaces || [];
274
+ // Create Fuse search index
275
+ return new fuse_js_1.default(spacesData, {
276
+ keys: [
277
+ { name: 'name', weight: 0.7 },
278
+ { name: 'id', weight: 0.6 }
279
+ ],
280
+ includeScore: true,
281
+ threshold: 0.4,
282
+ minMatchCharLength: 1,
283
+ });
284
+ }
285
+ catch (error) {
286
+ console.error('Error creating space search index:', error);
287
+ return null;
288
+ }
289
+ })();
290
+ // Cache the promise
291
+ spaceSearchIndexPromise = fetchPromise;
292
+ // Auto-cleanup after 60 seconds
293
+ setTimeout(() => {
294
+ spaceSearchIndexPromise = null;
295
+ console.error('Auto-cleaned space search index');
296
+ }, GLOBAL_REFRESH_INTERVAL);
297
+ return fetchPromise;
298
+ }
299
+ const listCache = new Map(); // Cache for space lists/folders
300
+ /**
301
+ * Get lists and folders for a specific space with caching
302
+ */
303
+ async function getSpaceContent(spaceId) {
304
+ const cacheKey = `space-content-${spaceId}`;
305
+ // Check cache first
306
+ const cachedContent = listCache.get(cacheKey);
307
+ if (cachedContent) {
308
+ return cachedContent;
309
+ }
310
+ // Fetch content with parallel requests
311
+ const fetchPromise = (async () => {
312
+ try {
313
+ const [foldersResponse, listsResponse] = await Promise.all([
314
+ fetch(`https://api.clickup.com/api/v2/space/${spaceId}/folder`, {
315
+ headers: { Authorization: config_1.CONFIG.apiKey },
316
+ }),
317
+ fetch(`https://api.clickup.com/api/v2/space/${spaceId}/list`, {
318
+ headers: { Authorization: config_1.CONFIG.apiKey },
319
+ })
320
+ ]);
321
+ const folders = foldersResponse.ok ?
322
+ (await foldersResponse.json()).folders || [] : [];
323
+ const lists = listsResponse.ok ?
324
+ (await listsResponse.json()).lists || [] : [];
325
+ // For each folder, also fetch its lists
326
+ const folderListPromises = folders.map(async (folder) => {
327
+ try {
328
+ const folderListResponse = await fetch(`https://api.clickup.com/api/v2/folder/${folder.id}/list`, { headers: { Authorization: config_1.CONFIG.apiKey } });
329
+ if (folderListResponse.ok) {
330
+ const folderListData = await folderListResponse.json();
331
+ folder.lists = folderListData.lists || [];
332
+ }
333
+ return folder;
334
+ }
335
+ catch (error) {
336
+ console.error(`Error fetching lists for folder ${folder.id}:`, error);
337
+ folder.lists = [];
338
+ return folder;
339
+ }
340
+ });
341
+ const foldersWithLists = await Promise.all(folderListPromises);
342
+ return { lists, folders: foldersWithLists };
343
+ }
344
+ catch (error) {
345
+ console.error(`Error fetching space content for ${spaceId}:`, error);
346
+ return { lists: [], folders: [] };
347
+ }
348
+ })();
349
+ // Cache the promise
350
+ listCache.set(cacheKey, fetchPromise);
351
+ // Auto-cleanup after 60 seconds
352
+ setTimeout(() => {
353
+ listCache.delete(cacheKey);
354
+ console.error(`Auto-cleaned space content cache for ${spaceId}`);
355
+ }, GLOBAL_REFRESH_INTERVAL);
356
+ return fetchPromise;
357
+ }
358
+ // Cache for team members to avoid repeated API calls and race conditions
359
+ let cachedTeamMembersPromise = null;
360
+ /**
361
+ * Gets all team members from ClickUp API with caching
362
+ */
363
+ async function getAllTeamMembers() {
364
+ // Return cached promise if available
365
+ if (cachedTeamMembersPromise) {
366
+ return cachedTeamMembersPromise;
367
+ }
368
+ // Create the fetch promise
369
+ const fetchPromise = (async () => {
370
+ try {
371
+ const response = await fetch(`https://api.clickup.com/api/v2/team`, {
372
+ headers: { Authorization: config_1.CONFIG.apiKey },
373
+ });
374
+ if (!response.ok) {
375
+ console.error(`Error fetching teams: ${response.status} ${response.statusText}`);
376
+ return [];
377
+ }
378
+ const data = await response.json();
379
+ if (!data.teams || !Array.isArray(data.teams)) {
380
+ return [];
381
+ }
382
+ // Find the team that matches our configured team ID and extract all user IDs
383
+ const currentTeam = data.teams.find((team) => team.id === config_1.CONFIG.teamId);
384
+ if (!currentTeam || !currentTeam.members || !Array.isArray(currentTeam.members)) {
385
+ console.error(`Team ${config_1.CONFIG.teamId} not found or has no members`);
386
+ return [];
387
+ }
388
+ return currentTeam.members.map((member) => member.user?.id).filter(Boolean);
389
+ }
390
+ catch (error) {
391
+ console.error('Error fetching team members:', error);
392
+ return [];
393
+ }
394
+ })();
395
+ // Cache the promise
396
+ cachedTeamMembersPromise = fetchPromise;
397
+ // Auto-cleanup after 60 seconds
398
+ setTimeout(() => {
399
+ cachedTeamMembersPromise = null;
400
+ console.error(`Auto-cleaned team members cache`);
401
+ }, GLOBAL_REFRESH_INTERVAL);
402
+ return fetchPromise;
403
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"list-tools.d.ts","sourceRoot":"","sources":["../../src/tools/list-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,QA4OtD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,QAuEvD"}
1
+ {"version":3,"file":"list-tools.d.ts","sourceRoot":"","sources":["../../src/tools/list-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,QA+GtD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,QAyEvD"}