@hauptsache.net/clickup-mcp 1.2.0 → 1.3.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.
@@ -0,0 +1,485 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerDocumentToolsRead = registerDocumentToolsRead;
4
+ exports.registerDocumentToolsWrite = registerDocumentToolsWrite;
5
+ const zod_1 = require("zod");
6
+ const config_1 = require("../shared/config");
7
+ const utils_1 = require("../shared/utils");
8
+ /**
9
+ * Helper function to recursively extract all pages from nested page structure
10
+ */
11
+ function extractAllPages(pageGroup) {
12
+ const allPages = [];
13
+ // Add the page itself
14
+ allPages.push({
15
+ id: pageGroup.id,
16
+ name: pageGroup.name,
17
+ doc_id: pageGroup.doc_id,
18
+ parent_page_id: pageGroup.parent_page_id || null
19
+ });
20
+ // Recursively add nested pages
21
+ if (pageGroup.pages && Array.isArray(pageGroup.pages)) {
22
+ pageGroup.pages.forEach((nestedPage) => {
23
+ allPages.push(...extractAllPages(nestedPage));
24
+ });
25
+ }
26
+ return allPages;
27
+ }
28
+ /**
29
+ * Helper function to display page hierarchy with proper indentation
30
+ */
31
+ function displayPageHierarchy(pageGroup, currentPageId, depth = 0) {
32
+ const result = [];
33
+ const indent = ' '.repeat(depth); // 2 spaces per level
34
+ const isCurrentPage = pageGroup.id === currentPageId;
35
+ const prefix = isCurrentPage ? '▶️ ' : ' ';
36
+ const pageIndicator = isCurrentPage ? ' ← **Currently viewing**' : '';
37
+ // Display this page
38
+ result.push(`${indent}${prefix}${pageGroup.name} (${pageGroup.id})${pageIndicator}`);
39
+ // Recursively display nested pages
40
+ if (pageGroup.pages && Array.isArray(pageGroup.pages)) {
41
+ pageGroup.pages.forEach((nestedPage) => {
42
+ result.push(...displayPageHierarchy(nestedPage, currentPageId, depth + 1));
43
+ });
44
+ }
45
+ return result;
46
+ }
47
+ function registerDocumentToolsRead(server) {
48
+ server.tool("readDocument", [
49
+ "Get a ClickUp document with page structure and content.",
50
+ "Always use the document URL when referencing documents in conversations or sharing with others.",
51
+ "The response provides complete document metadata, page structure, and requested page content.",
52
+ `Document URLs look like this: ${(0, utils_1.generateDocumentUrl)('doc_id', 'page_id')}`,
53
+ ].join("\n"), {
54
+ doc_id: zod_1.z
55
+ .string()
56
+ .min(1)
57
+ .describe("The document ID to read"),
58
+ page: zod_1.z
59
+ .string()
60
+ .optional()
61
+ .describe("Optional specific page ID or name to read (defaults to first page)")
62
+ }, async ({ doc_id, page }) => {
63
+ try {
64
+ // First get the document details and page structure
65
+ const [docResponse, pagesResponse] = await Promise.all([
66
+ fetch(`https://api.clickup.com/api/v3/workspaces/${config_1.CONFIG.teamId}/docs/${doc_id}`, {
67
+ headers: { Authorization: config_1.CONFIG.apiKey },
68
+ }),
69
+ fetch(`https://api.clickup.com/api/v3/workspaces/${config_1.CONFIG.teamId}/docs/${doc_id}/pageListing`, {
70
+ headers: { Authorization: config_1.CONFIG.apiKey },
71
+ })
72
+ ]);
73
+ if (!docResponse.ok) {
74
+ throw new Error(`Error fetching document: ${docResponse.status} ${docResponse.statusText}`);
75
+ }
76
+ if (!pagesResponse.ok) {
77
+ throw new Error(`Error fetching pages: ${pagesResponse.status} ${pagesResponse.statusText}`);
78
+ }
79
+ const docData = await docResponse.json();
80
+ const pagesData = await pagesResponse.json();
81
+ const doc = docData; // Document data is flat
82
+ // Extract all pages while preserving hierarchy for display
83
+ const pages = [];
84
+ const hierarchicalPages = pagesData; // Keep original structure for hierarchy display
85
+ // Extract flat list of pages for searching and navigation
86
+ pagesData.forEach((pageGroup) => {
87
+ pages.push(...extractAllPages(pageGroup));
88
+ });
89
+ if (pages.length === 0) {
90
+ return {
91
+ content: [{
92
+ type: "text",
93
+ text: `📄 **Document: ${doc.name}** (doc_id: ${doc_id})
94
+ 📎 Document URL: ${(0, utils_1.generateDocumentUrl)(doc_id)}
95
+
96
+ ⚠️ This document exists but has no pages yet.
97
+
98
+ **Next steps:**
99
+ - Use \`writeDocument\` with parent_type="doc" and parent_id="${doc_id}" to add the first page
100
+ - Example: writeDocument(parent_type="doc", parent_id="${doc_id}", page_name="Introduction", content="Your content here")`
101
+ }],
102
+ };
103
+ }
104
+ // Determine which page to read
105
+ let targetPage = null;
106
+ if (page) {
107
+ // Look for page by ID first, then by name
108
+ targetPage = pages.find((p) => p.id === page || p.name === page);
109
+ if (!targetPage) {
110
+ return {
111
+ content: [{
112
+ type: "text",
113
+ text: `Page "${page}" not found in document "${doc.name}". Available pages: ${pages.map((p) => `"${p.name}" (${p.id})`).join(', ')}`
114
+ }],
115
+ };
116
+ }
117
+ }
118
+ else {
119
+ // Default to first page
120
+ targetPage = pages[0];
121
+ }
122
+ // Get the specific page content
123
+ const pageResponse = await fetch(`https://api.clickup.com/api/v3/workspaces/${config_1.CONFIG.teamId}/docs/${doc_id}/pages/${targetPage.id}`, {
124
+ headers: { Authorization: config_1.CONFIG.apiKey },
125
+ });
126
+ if (!pageResponse.ok) {
127
+ throw new Error(`Error fetching page content: ${pageResponse.status} ${pageResponse.statusText}`);
128
+ }
129
+ const pageData = await pageResponse.json();
130
+ const pageContent = pageData; // Page data is flat
131
+ // Build the response
132
+ const result = [];
133
+ // Document header with metadata
134
+ result.push(`doc_id: ${doc.id}`);
135
+ result.push(`Document Title: ${doc.name}`);
136
+ result.push(`Document URL: ${(0, utils_1.generateDocumentUrl)(doc_id)}`);
137
+ result.push(`Current page_id: ${targetPage.id}`);
138
+ result.push(`Current Page Title: ${pageContent.name}`);
139
+ result.push(`Current Page URL: ${(0, utils_1.generateDocumentUrl)(doc_id, targetPage.id)}`);
140
+ // Page structure overview with hierarchy
141
+ result.push('Page Structure:');
142
+ hierarchicalPages.forEach((pageGroup) => {
143
+ result.push(...displayPageHierarchy(pageGroup, targetPage.id));
144
+ });
145
+ // Current page content
146
+ if (pageContent.content && pageContent.content.trim()) {
147
+ result.push(`Page Content:`);
148
+ return {
149
+ content: [
150
+ { type: "text", text: result.join('\n') },
151
+ { type: "text", text: pageContent.content },
152
+ ],
153
+ };
154
+ }
155
+ else {
156
+ result.push('*This page is empty.*');
157
+ result.push('');
158
+ result.push('**💡 To add content to this page:**');
159
+ result.push(`Use \`writeDocument\` with page_id="${targetPage.id}" and your content.`);
160
+ result.push(`Example: writeDocument(page_id="${targetPage.id}", content="Your content here")`);
161
+ return {
162
+ content: [
163
+ { type: "text", text: result.join('\n') },
164
+ ],
165
+ };
166
+ }
167
+ }
168
+ catch (error) {
169
+ console.error('Error reading document:', error);
170
+ return {
171
+ content: [
172
+ {
173
+ type: "text",
174
+ text: `Error reading document ${doc_id}: ${error instanceof Error ? error.message : 'Unknown error'}`,
175
+ },
176
+ ],
177
+ };
178
+ }
179
+ });
180
+ // Dynamically construct the searchDocuments description
181
+ const searchDocumentsDescriptionBase = [
182
+ "Search documents by name and space with fuzzy matching and support for multiple search terms (OR logic).",
183
+ "This can be a great knowledge based for general project information. Consider searching for documents and for tasks at the same time.",
184
+ "Can filter by specific space_ids. If no search terms provided, returns most recently updated documents."
185
+ ];
186
+ if (config_1.CONFIG.primaryLanguageHint && config_1.CONFIG.primaryLanguageHint.toLowerCase() !== 'en') {
187
+ searchDocumentsDescriptionBase.push(`For optimal results, as your ClickUp documents may be primarily in '${config_1.CONFIG.primaryLanguageHint}', consider providing search terms in English and '${config_1.CONFIG.primaryLanguageHint}'.`);
188
+ }
189
+ searchDocumentsDescriptionBase.push("Always reference documents by their URLs when discussing search results or suggesting actions.");
190
+ searchDocumentsDescriptionBase.push("You'll get document overview with space context - use readDocument to get full content.");
191
+ server.tool("searchDocuments", searchDocumentsDescriptionBase.join("\n"), {
192
+ terms: zod_1.z
193
+ .array(zod_1.z.string())
194
+ .optional()
195
+ .describe("Array of search terms to match against document names and spaces. If not provided, returns most recent documents."),
196
+ space_ids: zod_1.z
197
+ .array(zod_1.z.string())
198
+ .optional()
199
+ .describe("Filter documents to specific space IDs")
200
+ }, async ({ terms, space_ids }) => {
201
+ try {
202
+ // Get the document search index
203
+ const searchIndex = await (0, utils_1.getDocumentSearchIndex)(space_ids);
204
+ if (!searchIndex) {
205
+ return {
206
+ content: [
207
+ {
208
+ type: "text",
209
+ text: "Unable to create document search index.",
210
+ },
211
+ ],
212
+ };
213
+ }
214
+ let results;
215
+ if (terms && terms.length > 0) {
216
+ // Perform multi-term search
217
+ results = await (0, utils_1.performMultiTermSearch)(searchIndex, terms);
218
+ }
219
+ else {
220
+ // Return all documents sorted by creation date (most recent first)
221
+ const allResults = searchIndex._docs || [];
222
+ results = allResults
223
+ .sort((a, b) => new Date(b.date_created || 0).getTime() - new Date(a.date_created || 0).getTime());
224
+ }
225
+ // Limit results to prevent overwhelming the LLM
226
+ const limitedResults = results.slice(0, 50);
227
+ if (limitedResults.length === 0) {
228
+ const searchTermsText = terms && terms.length > 0 ? ` for terms: ${terms.join(", ")}` : "";
229
+ const spaceFilterText = space_ids && space_ids.length > 0 ? ` in spaces: ${space_ids.join(", ")}` : "";
230
+ return {
231
+ content: [
232
+ {
233
+ type: "text",
234
+ text: [
235
+ `No documents found${searchTermsText}${spaceFilterText}.`,
236
+ `The content of documents is not searched, so ask the user for more details if needed.`,
237
+ ].join("\n"),
238
+ },
239
+ ],
240
+ };
241
+ }
242
+ // Format results
243
+ const responseLines = [
244
+ `Found ${limitedResults.length} document${limitedResults.length === 1 ? "" : "s"}:`
245
+ ];
246
+ limitedResults.forEach((doc, index) => {
247
+ const docUrl = (0, utils_1.generateDocumentUrl)(doc.id);
248
+ const createdDate = doc.date_created ? new Date(+doc.date_created).toLocaleDateString() : 'Unknown';
249
+ const meta = [`doc_id ${doc.id}`];
250
+ // Show parent information
251
+ if (doc.parent_info) {
252
+ meta.push(doc.parent_info);
253
+ }
254
+ meta.push(`Created: ${createdDate}`);
255
+ responseLines.push(`- ${doc.name} (${meta.join(', ')}) ${docUrl}`);
256
+ });
257
+ responseLines.push("", "Use `readDocument` with a document ID to view full content and page structure.");
258
+ return {
259
+ content: [
260
+ {
261
+ type: "text",
262
+ text: responseLines.join("\n"),
263
+ },
264
+ ],
265
+ };
266
+ }
267
+ catch (error) {
268
+ console.error('Error searching documents:', error);
269
+ return {
270
+ content: [
271
+ {
272
+ type: "text",
273
+ text: `Error searching documents: ${error instanceof Error ? error.message : 'Unknown error'}`,
274
+ },
275
+ ],
276
+ };
277
+ }
278
+ });
279
+ }
280
+ function registerDocumentToolsWrite(server) {
281
+ server.tool("writeDocument", [
282
+ "Universal tool for document and page operations with smart document creation.",
283
+ "Create new documents by using parent_type 'space' or 'list'.",
284
+ "Create pages in existing documents by using parent_type 'doc'.",
285
+ "Create sub-pages by using parent_type 'page'.",
286
+ "Update existing pages by providing page_id.",
287
+ "Always reference documents by their URLs when creating or updating."
288
+ ].join("\n"), {
289
+ page_id: zod_1.z
290
+ .string()
291
+ .optional()
292
+ .describe("Optional page ID to update (if provided, updates existing page; if not, creates new page/document)"),
293
+ parent_type: zod_1.z
294
+ .enum(["space", "list", "doc", "page"])
295
+ .optional()
296
+ .describe("Type of parent when creating new content (required if page_id not provided)"),
297
+ parent_id: zod_1.z
298
+ .string()
299
+ .optional()
300
+ .describe("ID of parent (space, list, document, or page) when creating new content (required if page_id not provided)"),
301
+ page_name: zod_1.z
302
+ .string()
303
+ .optional()
304
+ .describe("Name for the page (required for new pages, optional for updates to rename)"),
305
+ content: zod_1.z
306
+ .string()
307
+ .optional()
308
+ .describe("Page content in markdown format (optional for updates)"),
309
+ append: zod_1.z
310
+ .boolean()
311
+ .optional()
312
+ .describe("Whether to append content to existing page content (default: false - replaces content)")
313
+ }, async ({ page_id, parent_type, parent_id, page_name, content, append = false }) => {
314
+ try {
315
+ // Validate input parameters
316
+ if (!page_id && (!parent_type || !parent_id)) {
317
+ return {
318
+ content: [{
319
+ type: "text",
320
+ text: "Error: Either page_id (for updates) or both parent_type and parent_id (for creation) must be provided."
321
+ }],
322
+ };
323
+ }
324
+ if (!page_id && !page_name) {
325
+ return {
326
+ content: [{
327
+ type: "text",
328
+ text: "Error: page_name is required when creating new pages."
329
+ }],
330
+ };
331
+ }
332
+ // Case 1: Update existing page
333
+ if (page_id) {
334
+ const requestBody = {};
335
+ if (page_name) {
336
+ requestBody.name = page_name;
337
+ }
338
+ if (content !== undefined) {
339
+ requestBody.content = content;
340
+ // Use native append mode from ClickUp API
341
+ requestBody.content_edit_mode = append ? 'append' : 'replace';
342
+ }
343
+ const response = await fetch(`https://api.clickup.com/api/v3/docs/pages/${page_id}`, {
344
+ method: 'PUT',
345
+ headers: {
346
+ Authorization: config_1.CONFIG.apiKey,
347
+ 'Content-Type': 'application/json',
348
+ },
349
+ body: JSON.stringify(requestBody),
350
+ });
351
+ if (!response.ok) {
352
+ throw new Error(`Error updating page: ${response.status} ${response.statusText}`);
353
+ }
354
+ const data = await response.json();
355
+ const updatedPage = data.page;
356
+ return {
357
+ content: [{
358
+ type: "text",
359
+ text: `✅ Successfully updated page "${updatedPage.name}" (${page_id})\n\nPage URL: ${(0, utils_1.generateDocumentUrl)(updatedPage.doc_id, page_id)}`
360
+ }],
361
+ };
362
+ }
363
+ // Case 2: Create new content
364
+ let docId;
365
+ if (parent_type === "space" || parent_type === "list") {
366
+ // Create new document first, then create first page manually
367
+ const docRequestBody = {
368
+ name: page_name, // Document name matches first page name
369
+ create_page: false, // Don't auto-create page, we'll create it manually for better control
370
+ parent: {
371
+ id: parent_id,
372
+ type: parent_type === "space" ? 4 : parent_type === "list" ? 6 : 7 // 4=Space, 6=List, 7=Workspace
373
+ }
374
+ };
375
+ const docResponse = await fetch(`https://api.clickup.com/api/v3/workspaces/${config_1.CONFIG.teamId}/docs`, {
376
+ method: 'POST',
377
+ headers: {
378
+ Authorization: config_1.CONFIG.apiKey,
379
+ 'Content-Type': 'application/json',
380
+ },
381
+ body: JSON.stringify(docRequestBody),
382
+ });
383
+ if (!docResponse.ok) {
384
+ throw new Error(`Error creating document: ${docResponse.status} ${docResponse.statusText}`);
385
+ }
386
+ const docData = await docResponse.json();
387
+ docId = docData.id;
388
+ // Create the first page manually for better control
389
+ const pageRequestBody = {
390
+ name: page_name,
391
+ content: content || '',
392
+ };
393
+ const pageResponse = await fetch(`https://api.clickup.com/api/v3/workspaces/${config_1.CONFIG.teamId}/docs/${docId}/pages`, {
394
+ method: 'POST',
395
+ headers: {
396
+ Authorization: config_1.CONFIG.apiKey,
397
+ 'Content-Type': 'application/json',
398
+ },
399
+ body: JSON.stringify(pageRequestBody),
400
+ });
401
+ if (!pageResponse.ok) {
402
+ throw new Error(`Error creating first page: ${pageResponse.status} ${pageResponse.statusText}`);
403
+ }
404
+ const pageData = await pageResponse.json();
405
+ const firstPage = pageData.page || pageData;
406
+ return {
407
+ content: [{
408
+ type: "text",
409
+ text: `✅ Successfully created new document "${page_name}" with first page\n\nDocument URL: ${(0, utils_1.generateDocumentUrl)(docId)}\nFirst Page URL: ${(0, utils_1.generateDocumentUrl)(docId, firstPage.id)}`
410
+ }],
411
+ };
412
+ }
413
+ else if (parent_type === "doc") {
414
+ // Create new page in existing document
415
+ docId = parent_id;
416
+ const pageRequestBody = {
417
+ name: page_name,
418
+ content: content || '',
419
+ };
420
+ const response = await fetch(`https://api.clickup.com/api/v3/workspaces/${config_1.CONFIG.teamId}/docs/${docId}/pages`, {
421
+ method: 'POST',
422
+ headers: {
423
+ Authorization: config_1.CONFIG.apiKey,
424
+ 'Content-Type': 'application/json',
425
+ },
426
+ body: JSON.stringify(pageRequestBody),
427
+ });
428
+ if (!response.ok) {
429
+ throw new Error(`Error creating page: ${response.status} ${response.statusText}`);
430
+ }
431
+ const data = await response.json();
432
+ const newPage = data.page;
433
+ return {
434
+ content: [{
435
+ type: "text",
436
+ text: `✅ Successfully created page "${newPage.name}" (${newPage.id}) in document\n\nPage URL: ${(0, utils_1.generateDocumentUrl)(docId, newPage.id)}`
437
+ }],
438
+ };
439
+ }
440
+ else if (parent_type === "page") {
441
+ // Create sub-page under existing page
442
+ const pageRequestBody = {
443
+ name: page_name,
444
+ content: content || '',
445
+ parent_page_id: parent_id
446
+ };
447
+ // For sub-pages, we need to get the doc_id from the parent page first
448
+ // This is a limitation we'll need to handle - for now, use a generic endpoint
449
+ const response = await fetch(`https://api.clickup.com/api/v3/docs/pages`, {
450
+ method: 'POST',
451
+ headers: {
452
+ Authorization: config_1.CONFIG.apiKey,
453
+ 'Content-Type': 'application/json',
454
+ },
455
+ body: JSON.stringify(pageRequestBody),
456
+ });
457
+ if (!response.ok) {
458
+ throw new Error(`Error creating sub-page: ${response.status} ${response.statusText}`);
459
+ }
460
+ const data = await response.json();
461
+ const newPage = data.page;
462
+ return {
463
+ content: [{
464
+ type: "text",
465
+ text: `✅ Successfully created sub-page "${newPage.name}" (${newPage.id}) under parent page ${parent_id}\n\nPage URL: ${(0, utils_1.generateDocumentUrl)(newPage.doc_id, newPage.id)}`
466
+ }],
467
+ };
468
+ }
469
+ return {
470
+ content: [{ type: "text", text: "Error: Invalid parent_type specified." }],
471
+ };
472
+ }
473
+ catch (error) {
474
+ console.error('Error in writeDocument:', error);
475
+ return {
476
+ content: [
477
+ {
478
+ type: "text",
479
+ text: `Error in document/page operation: ${error instanceof Error ? error.message : 'Unknown error'}`,
480
+ },
481
+ ],
482
+ };
483
+ }
484
+ });
485
+ }
@@ -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;AAMpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,QA+GtD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,QAyEvD"}
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,QA+GtD;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,QAyEvD"}
@@ -1 +1 @@
1
- {"version":3,"file":"search-tools.d.ts","sourceRoot":"","sources":["../../src/tools/search-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AASlE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,QA8MnE"}
1
+ {"version":3,"file":"search-tools.d.ts","sourceRoot":"","sources":["../../src/tools/search-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,yCAAyC,CAAC;AASlE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,QAuLnE"}
@@ -9,7 +9,7 @@ const MAX_SEARCH_RESULTS = 50;
9
9
  function registerSearchTools(server, userData) {
10
10
  // Dynamically construct the searchTasks description
11
11
  const searchTasksDescriptionBase = [
12
- "Searches tasks (sometimes called Tickets or Cards) by name, content, assignees, and ID (case insensitive) with fuzzy matching and support for multiple search terms (OR logic).",
12
+ "Searches tasks (sometimes called Tickets or Cards) by name, content, assignees, and ID with fuzzy matching and support for multiple search terms (OR logic).",
13
13
  "Can filter by multiple list_ids, space_ids, todo status, or tasks assigned to the current user. If no search terms provided, returns most recently updated tasks.",
14
14
  "Can also be used to find tasks for the current user by providing the assigned_to_me flag."
15
15
  ];
@@ -94,37 +94,15 @@ function registerSearchTools(server, userData) {
94
94
  content: await Promise.all(resultTasks.map((task) => (0, task_tools_1.generateTaskMetadata)(task, timeEntries))),
95
95
  };
96
96
  }
97
- // Filter valid search terms
98
- const validTerms = terms.filter(term => term && term.trim().length > 0);
99
- if (validTerms.length === 0) {
100
- return {
101
- content: [
102
- {
103
- type: "text",
104
- text: "No valid search terms provided.",
105
- },
106
- ],
107
- };
108
- }
97
+ // Create a results map to track unique tasks with scores
109
98
  const uniqueResults = new Map();
110
- // Search with each term
111
- validTerms.forEach(term => {
112
- const results = searchIndex.search(term.toLowerCase());
113
- results.forEach(result => {
114
- if (result.item && typeof result.item.id === 'string') {
115
- const currentScore = result.score ?? 1;
116
- const existing = uniqueResults.get(result.item.id);
117
- if (!existing || currentScore < existing.score) {
118
- uniqueResults.set(result.item.id, {
119
- item: result.item,
120
- score: currentScore
121
- });
122
- }
123
- }
124
- });
99
+ // Perform multi-term search with aggressive boosting
100
+ const searchResults = await (0, utils_1.performMultiTermSearch)(searchIndex, terms);
101
+ searchResults.forEach(task => {
102
+ uniqueResults.set(task.id, { item: task, score: 0.1 }); // Give search results a good score
125
103
  });
126
104
  // Task ID Fallback Logic
127
- const potentialTaskIds = validTerms.filter(utils_1.isTaskId);
105
+ const potentialTaskIds = terms.filter(utils_1.isTaskId);
128
106
  const foundTaskIdsByFuse = new Set(Array.from(uniqueResults.keys()).map(id => id.toLowerCase()));
129
107
  const taskIdsToFetchDirectly = potentialTaskIds.filter(id => {
130
108
  const lowerId = id.toLowerCase();
@@ -1 +1 @@
1
- {"version":3,"file":"space-tools.d.ts","sourceRoot":"","sources":["../../src/tools/space-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QAqNnD"}
1
+ {"version":3,"file":"space-tools.d.ts","sourceRoot":"","sources":["../../src/tools/space-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QAiNnD"}