mcp-researchpowerpack 3.6.9

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.
Files changed (119) hide show
  1. package/README.md +635 -0
  2. package/dist/clients/reddit.d.ts +74 -0
  3. package/dist/clients/reddit.d.ts.map +1 -0
  4. package/dist/clients/reddit.js +305 -0
  5. package/dist/clients/reddit.js.map +1 -0
  6. package/dist/clients/research.d.ts +67 -0
  7. package/dist/clients/research.d.ts.map +1 -0
  8. package/dist/clients/research.js +252 -0
  9. package/dist/clients/research.js.map +1 -0
  10. package/dist/clients/scraper.d.ts +71 -0
  11. package/dist/clients/scraper.d.ts.map +1 -0
  12. package/dist/clients/scraper.js +321 -0
  13. package/dist/clients/scraper.js.map +1 -0
  14. package/dist/clients/search.d.ts +62 -0
  15. package/dist/clients/search.d.ts.map +1 -0
  16. package/dist/clients/search.js +219 -0
  17. package/dist/clients/search.js.map +1 -0
  18. package/dist/config/index.d.ts +62 -0
  19. package/dist/config/index.d.ts.map +1 -0
  20. package/dist/config/index.js +142 -0
  21. package/dist/config/index.js.map +1 -0
  22. package/dist/config/loader.d.ts +40 -0
  23. package/dist/config/loader.d.ts.map +1 -0
  24. package/dist/config/loader.js +305 -0
  25. package/dist/config/loader.js.map +1 -0
  26. package/dist/config/types.d.ts +81 -0
  27. package/dist/config/types.d.ts.map +1 -0
  28. package/dist/config/types.js +6 -0
  29. package/dist/config/types.js.map +1 -0
  30. package/dist/config/yaml/tools.yaml +130 -0
  31. package/dist/index.d.ts +7 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +271 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/schemas/deep-research.d.ts +64 -0
  36. package/dist/schemas/deep-research.d.ts.map +1 -0
  37. package/dist/schemas/deep-research.js +224 -0
  38. package/dist/schemas/deep-research.js.map +1 -0
  39. package/dist/schemas/scrape-links.d.ts +32 -0
  40. package/dist/schemas/scrape-links.d.ts.map +1 -0
  41. package/dist/schemas/scrape-links.js +34 -0
  42. package/dist/schemas/scrape-links.js.map +1 -0
  43. package/dist/schemas/web-search.d.ts +22 -0
  44. package/dist/schemas/web-search.d.ts.map +1 -0
  45. package/dist/schemas/web-search.js +21 -0
  46. package/dist/schemas/web-search.js.map +1 -0
  47. package/dist/services/file-attachment.d.ts +30 -0
  48. package/dist/services/file-attachment.d.ts.map +1 -0
  49. package/dist/services/file-attachment.js +199 -0
  50. package/dist/services/file-attachment.js.map +1 -0
  51. package/dist/services/llm-processor.d.ts +27 -0
  52. package/dist/services/llm-processor.d.ts.map +1 -0
  53. package/dist/services/llm-processor.js +179 -0
  54. package/dist/services/llm-processor.js.map +1 -0
  55. package/dist/services/markdown-cleaner.d.ts +8 -0
  56. package/dist/services/markdown-cleaner.d.ts.map +1 -0
  57. package/dist/services/markdown-cleaner.js +44 -0
  58. package/dist/services/markdown-cleaner.js.map +1 -0
  59. package/dist/tools/definitions.d.ts +16 -0
  60. package/dist/tools/definitions.d.ts.map +1 -0
  61. package/dist/tools/definitions.js +17 -0
  62. package/dist/tools/definitions.js.map +1 -0
  63. package/dist/tools/reddit.d.ts +14 -0
  64. package/dist/tools/reddit.d.ts.map +1 -0
  65. package/dist/tools/reddit.js +213 -0
  66. package/dist/tools/reddit.js.map +1 -0
  67. package/dist/tools/registry.d.ts +71 -0
  68. package/dist/tools/registry.d.ts.map +1 -0
  69. package/dist/tools/registry.js +242 -0
  70. package/dist/tools/registry.js.map +1 -0
  71. package/dist/tools/research.d.ts +14 -0
  72. package/dist/tools/research.d.ts.map +1 -0
  73. package/dist/tools/research.js +194 -0
  74. package/dist/tools/research.js.map +1 -0
  75. package/dist/tools/scrape.d.ts +14 -0
  76. package/dist/tools/scrape.d.ts.map +1 -0
  77. package/dist/tools/scrape.js +201 -0
  78. package/dist/tools/scrape.js.map +1 -0
  79. package/dist/tools/search.d.ts +10 -0
  80. package/dist/tools/search.d.ts.map +1 -0
  81. package/dist/tools/search.js +137 -0
  82. package/dist/tools/search.js.map +1 -0
  83. package/dist/tools/utils.d.ts +105 -0
  84. package/dist/tools/utils.d.ts.map +1 -0
  85. package/dist/tools/utils.js +159 -0
  86. package/dist/tools/utils.js.map +1 -0
  87. package/dist/utils/concurrency.d.ts +29 -0
  88. package/dist/utils/concurrency.d.ts.map +1 -0
  89. package/dist/utils/concurrency.js +73 -0
  90. package/dist/utils/concurrency.js.map +1 -0
  91. package/dist/utils/errors.d.ts +77 -0
  92. package/dist/utils/errors.d.ts.map +1 -0
  93. package/dist/utils/errors.js +335 -0
  94. package/dist/utils/errors.js.map +1 -0
  95. package/dist/utils/logger.d.ts +39 -0
  96. package/dist/utils/logger.d.ts.map +1 -0
  97. package/dist/utils/logger.js +57 -0
  98. package/dist/utils/logger.js.map +1 -0
  99. package/dist/utils/markdown-formatter.d.ts +5 -0
  100. package/dist/utils/markdown-formatter.d.ts.map +1 -0
  101. package/dist/utils/markdown-formatter.js +15 -0
  102. package/dist/utils/markdown-formatter.js.map +1 -0
  103. package/dist/utils/response.d.ts +88 -0
  104. package/dist/utils/response.d.ts.map +1 -0
  105. package/dist/utils/response.js +151 -0
  106. package/dist/utils/response.js.map +1 -0
  107. package/dist/utils/url-aggregator.d.ts +90 -0
  108. package/dist/utils/url-aggregator.d.ts.map +1 -0
  109. package/dist/utils/url-aggregator.js +502 -0
  110. package/dist/utils/url-aggregator.js.map +1 -0
  111. package/dist/version.d.ts +30 -0
  112. package/dist/version.d.ts.map +1 -0
  113. package/dist/version.js +60 -0
  114. package/dist/version.js.map +1 -0
  115. package/dist/worker.d.ts +17 -0
  116. package/dist/worker.d.ts.map +1 -0
  117. package/dist/worker.js +53 -0
  118. package/dist/worker.js.map +1 -0
  119. package/package.json +73 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrape-links.js","sourceRoot":"","sources":["../../src/schemas/scrape-links.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sCAAsC;AACtC,MAAM,SAAS,GAAG,CAAC;KAChB,MAAM,CAAC,EAAE,cAAc,EAAE,+BAA+B,EAAE,CAAC;KAC3D,GAAG,CAAC,EAAE,OAAO,EAAE,kCAAkC,EAAE,CAAC;KACpD,MAAM,CACL,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAC9D,EAAE,OAAO,EAAE,yDAAyD,EAAE,CACvE,CAAC;AAEJ,qCAAqC;AACrC,MAAM,sBAAsB,GAAG;IAC7B,IAAI,EAAE,CAAC;SACJ,KAAK,CAAC,SAAS,EAAE;QAChB,cAAc,EAAE,sCAAsC;QACtD,kBAAkB,EAAE,qCAAqC;KAC1D,CAAC;SACD,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,0CAA0C,EAAE,CAAC;SAC/D,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,mDAAmD,EAAE,CAAC;SACzE,QAAQ,CAAC,sOAAsO,CAAC;IACnP,OAAO,EAAE,CAAC;SACP,MAAM,CAAC,EAAE,kBAAkB,EAAE,wCAAwC,EAAE,CAAC;SACxE,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,kDAAkD,EAAE,CAAC;SACvE,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,iDAAiD,EAAE,CAAC;SACxE,OAAO,CAAC,EAAE,CAAC;SACX,QAAQ,CAAC,iCAAiC,CAAC;IAC9C,OAAO,EAAE,CAAC;SACP,OAAO,CAAC,EAAE,kBAAkB,EAAE,yCAAyC,EAAE,CAAC;SAC1E,OAAO,CAAC,KAAK,CAAC;SACd,QAAQ,CAAC,2EAA2E,CAAC;IACxF,eAAe,EAAE,CAAC;SACf,MAAM,EAAE;SACR,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,sEAAsE,EAAE,CAAC;SAC9F,QAAQ,EAAE;SACV,QAAQ,CAAC,0GAA0G,CAAC;CACxH,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { z } from 'zod';
2
+ export declare const webSearchParamsSchema: z.ZodObject<{
3
+ keywords: z.ZodArray<z.ZodEffects<z.ZodString, string, string>, "many">;
4
+ }, "strip", z.ZodTypeAny, {
5
+ keywords: string[];
6
+ }, {
7
+ keywords: string[];
8
+ }>;
9
+ export type WebSearchParams = z.infer<typeof webSearchParamsSchema>;
10
+ export interface WebSearchOutput {
11
+ content: string;
12
+ metadata: {
13
+ total_keywords: number;
14
+ total_results: number;
15
+ execution_time_ms: number;
16
+ total_unique_urls?: number;
17
+ consensus_url_count?: number;
18
+ frequency_threshold?: number;
19
+ errorCode?: string;
20
+ };
21
+ }
22
+ //# sourceMappingURL=web-search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.d.ts","sourceRoot":"","sources":["../../src/schemas/web-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA0BxB,eAAO,MAAM,qBAAqB;;;;;;EAAiC,CAAC;AACpE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAGpE,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE;QACR,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ // Keyword schema with validation
3
+ const keywordSchema = z
4
+ .string({ required_error: 'web_search: Keyword is required' })
5
+ .min(1, { message: 'web_search: Keyword cannot be empty' })
6
+ .max(500, { message: 'web_search: Keyword too long (max 500 characters)' })
7
+ .refine(k => k.trim().length > 0, { message: 'web_search: Keyword cannot be whitespace only' });
8
+ // Input schema for web_search tool
9
+ const keywordsSchema = z
10
+ .array(keywordSchema, {
11
+ required_error: 'web_search: Keywords array is required',
12
+ invalid_type_error: 'web_search: Keywords must be an array'
13
+ })
14
+ .min(3, { message: 'web_search: MINIMUM 3 keywords required. Add more diverse keywords covering different perspectives.' })
15
+ .max(100, { message: 'web_search: Maximum 100 keywords allowed per request' })
16
+ .describe('Array of search keywords (MINIMUM 3, RECOMMENDED 5-7, MAX 100). Each keyword runs as a separate Google search in parallel. Use diverse keywords covering different angles for comprehensive results.');
17
+ const webSearchParamsShape = {
18
+ keywords: keywordsSchema,
19
+ };
20
+ export const webSearchParamsSchema = z.object(webSearchParamsShape);
21
+ //# sourceMappingURL=web-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-search.js","sourceRoot":"","sources":["../../src/schemas/web-search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,iCAAiC;AACjC,MAAM,aAAa,GAAG,CAAC;KACpB,MAAM,CAAC,EAAE,cAAc,EAAE,iCAAiC,EAAE,CAAC;KAC7D,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC;KAC1D,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,mDAAmD,EAAE,CAAC;KAC1E,MAAM,CACL,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EACxB,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAC7D,CAAC;AAEJ,mCAAmC;AACnC,MAAM,cAAc,GAAG,CAAC;KACrB,KAAK,CAAC,aAAa,EAAE;IACpB,cAAc,EAAE,wCAAwC;IACxD,kBAAkB,EAAE,uCAAuC;CAC5D,CAAC;KACD,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,qGAAqG,EAAE,CAAC;KAC1H,GAAG,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,sDAAsD,EAAE,CAAC;KAC7E,QAAQ,CAAC,sMAAsM,CAAC,CAAC;AAEpN,MAAM,oBAAoB,GAAG;IAC3B,QAAQ,EAAE,cAAc;CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * File attachment service for reading and formatting file contents
3
+ */
4
+ interface FileAttachment {
5
+ path: string;
6
+ start_line?: number | undefined;
7
+ end_line?: number | undefined;
8
+ description?: string | undefined;
9
+ }
10
+ export declare class FileAttachmentService {
11
+ /**
12
+ * Format multiple file attachments into a markdown section
13
+ */
14
+ formatAttachments(attachments: FileAttachment[]): Promise<string>;
15
+ /**
16
+ * Format a single file attachment
17
+ */
18
+ private formatSingleFile;
19
+ /**
20
+ * Format code block with line numbers and smart truncation
21
+ */
22
+ private formatCodeBlock;
23
+ /**
24
+ * Validate line range and return corrected values
25
+ */
26
+ private validateLineRange;
27
+ private detectLanguage;
28
+ }
29
+ export {};
30
+ //# sourceMappingURL=file-attachment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-attachment.d.ts","sourceRoot":"","sources":["../../src/services/file-attachment.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC;AASD,qBAAa,qBAAqB;IAChC;;OAEG;IACG,iBAAiB,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAiBvE;;OAEG;YACW,gBAAgB;IAsE9B;;OAEG;IACH,OAAO,CAAC,eAAe;IAiCvB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAoEzB,OAAO,CAAC,cAAc;CAcvB"}
@@ -0,0 +1,199 @@
1
+ /**
2
+ * File attachment service for reading and formatting file contents
3
+ */
4
+ import { access, readFile } from 'node:fs/promises';
5
+ import { extname } from 'node:path';
6
+ import { pMap } from '../utils/concurrency.js';
7
+ export class FileAttachmentService {
8
+ /**
9
+ * Format multiple file attachments into a markdown section
10
+ */
11
+ async formatAttachments(attachments) {
12
+ if (!attachments || attachments.length === 0) {
13
+ return '';
14
+ }
15
+ const results = await pMap(attachments, (attachment) => this.formatSingleFile(attachment), 5);
16
+ // Build the attachments section
17
+ const parts = ['\n\n---\n\n# 📎 ATTACHED FILES\n\n'];
18
+ parts.push(`*${results.length} file${results.length > 1 ? 's' : ''} attached for context*\n\n`);
19
+ for (const result of results) {
20
+ parts.push(result.content);
21
+ parts.push('\n\n');
22
+ }
23
+ return parts.join('');
24
+ }
25
+ /**
26
+ * Format a single file attachment
27
+ */
28
+ async formatSingleFile(attachment) {
29
+ const { path, start_line, end_line, description } = attachment;
30
+ // Check if file exists
31
+ try {
32
+ await access(path);
33
+ }
34
+ catch {
35
+ return {
36
+ success: false,
37
+ path,
38
+ content: `## ❌ ${path}\n\n**FILE NOT FOUND**\n${description ? `\n*Description:* ${description}\n` : ''}`,
39
+ error: 'File not found',
40
+ };
41
+ }
42
+ try {
43
+ // Read file content
44
+ const content = await readFile(path, 'utf-8');
45
+ const lines = content.split('\n');
46
+ const language = this.detectLanguage(path);
47
+ // Validate line ranges
48
+ const validatedRange = this.validateLineRange(start_line, end_line, lines.length);
49
+ if (!validatedRange.valid) {
50
+ return {
51
+ success: false,
52
+ path,
53
+ content: `## ⚠️ ${path}\n\n**INVALID LINE RANGE**: ${validatedRange.error}\n${description ? `\n*Description:* ${description}\n` : ''}`,
54
+ error: validatedRange.error,
55
+ };
56
+ }
57
+ // Extract relevant lines
58
+ const startIdx = validatedRange.start - 1;
59
+ const endIdx = validatedRange.end - 1;
60
+ const selectedLines = lines.slice(startIdx, endIdx + 1);
61
+ // Build formatted output
62
+ let formatted = `## 📄 ${path}\n\n`;
63
+ // Add metadata
64
+ const isPartial = start_line !== undefined || end_line !== undefined;
65
+ formatted += `**Language:** ${language} | `;
66
+ formatted += `**Lines:** ${isPartial ? `${validatedRange.start}-${validatedRange.end}` : lines.length} | `;
67
+ formatted += `**Size:** ${(content.length / 1024).toFixed(2)} KB\n`;
68
+ if (description) {
69
+ formatted += `\n*${description}*\n`;
70
+ }
71
+ formatted += '\n';
72
+ // Add file content with line numbers
73
+ formatted += this.formatCodeBlock(selectedLines, language, startIdx);
74
+ return {
75
+ success: true,
76
+ path,
77
+ content: formatted,
78
+ };
79
+ }
80
+ catch (error) {
81
+ return {
82
+ success: false,
83
+ path,
84
+ content: `## ❌ ${path}\n\n**ERROR READING FILE**: ${error instanceof Error ? error.message : String(error)}\n${description ? `\n*Description:* ${description}\n` : ''}`,
85
+ error: error instanceof Error ? error.message : String(error),
86
+ };
87
+ }
88
+ }
89
+ /**
90
+ * Format code block with line numbers and smart truncation
91
+ */
92
+ formatCodeBlock(lines, language, startIdx) {
93
+ const parts = [`\`\`\`${language.toLowerCase()}\n`];
94
+ // Smart truncation for very large files (keep first 500 lines + last 100 lines)
95
+ if (lines.length > 600) {
96
+ // First 500 lines
97
+ const firstLines = lines.slice(0, 500);
98
+ for (let idx = 0; idx < firstLines.length; idx++) {
99
+ const lineNumber = startIdx + idx + 1;
100
+ parts.push(`${lineNumber.toString().padStart(4, ' ')}: ${firstLines[idx]}\n`);
101
+ }
102
+ // Truncation marker
103
+ parts.push(`\n... [${lines.length - 600} lines truncated for brevity] ...\n\n`);
104
+ // Last 100 lines
105
+ const lastLines = lines.slice(-100);
106
+ for (let idx = 0; idx < lastLines.length; idx++) {
107
+ const lineNumber = startIdx + lines.length - 100 + idx + 1;
108
+ parts.push(`${lineNumber.toString().padStart(4, ' ')}: ${lastLines[idx]}\n`);
109
+ }
110
+ }
111
+ else {
112
+ // Show all lines with numbers
113
+ for (let idx = 0; idx < lines.length; idx++) {
114
+ const lineNumber = startIdx + idx + 1;
115
+ parts.push(`${lineNumber.toString().padStart(4, ' ')}: ${lines[idx]}\n`);
116
+ }
117
+ }
118
+ parts.push('```');
119
+ return parts.join('');
120
+ }
121
+ /**
122
+ * Validate line range and return corrected values
123
+ */
124
+ validateLineRange(start_line, end_line, totalLines) {
125
+ // No range specified - return full file
126
+ if (start_line === undefined && end_line === undefined) {
127
+ return { valid: true, start: 1, end: totalLines };
128
+ }
129
+ // Only start_line specified
130
+ if (start_line !== undefined && end_line === undefined) {
131
+ if (start_line < 1 || start_line > totalLines) {
132
+ return {
133
+ valid: false,
134
+ start: 1,
135
+ end: totalLines,
136
+ error: `start_line ${start_line} out of range (1-${totalLines})`,
137
+ };
138
+ }
139
+ return { valid: true, start: start_line, end: totalLines };
140
+ }
141
+ // Only end_line specified
142
+ if (start_line === undefined && end_line !== undefined) {
143
+ if (end_line < 1 || end_line > totalLines) {
144
+ return {
145
+ valid: false,
146
+ start: 1,
147
+ end: totalLines,
148
+ error: `end_line ${end_line} out of range (1-${totalLines})`,
149
+ };
150
+ }
151
+ return { valid: true, start: 1, end: end_line };
152
+ }
153
+ // Both specified
154
+ if (start_line !== undefined && end_line !== undefined) {
155
+ if (start_line < 1 || start_line > totalLines) {
156
+ return {
157
+ valid: false,
158
+ start: 1,
159
+ end: totalLines,
160
+ error: `start_line ${start_line} out of range (1-${totalLines})`,
161
+ };
162
+ }
163
+ if (end_line < 1 || end_line > totalLines) {
164
+ return {
165
+ valid: false,
166
+ start: 1,
167
+ end: totalLines,
168
+ error: `end_line ${end_line} out of range (1-${totalLines})`,
169
+ };
170
+ }
171
+ if (start_line > end_line) {
172
+ return {
173
+ valid: false,
174
+ start: 1,
175
+ end: totalLines,
176
+ error: `start_line ${start_line} cannot be greater than end_line ${end_line}`,
177
+ };
178
+ }
179
+ return { valid: true, start: start_line, end: end_line };
180
+ }
181
+ return { valid: true, start: 1, end: totalLines };
182
+ }
183
+ detectLanguage(filePath) {
184
+ const ext = extname(filePath).toLowerCase();
185
+ const map = {
186
+ '.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript',
187
+ '.ts': 'typescript', '.tsx': 'typescript',
188
+ '.py': 'python', '.go': 'go', '.rs': 'rust', '.rb': 'ruby',
189
+ '.java': 'java', '.c': 'c', '.cpp': 'cpp', '.h': 'c',
190
+ '.json': 'json', '.yaml': 'yaml', '.yml': 'yaml', '.toml': 'toml',
191
+ '.md': 'markdown', '.html': 'html', '.css': 'css', '.sql': 'sql',
192
+ '.sh': 'bash', '.xml': 'xml',
193
+ };
194
+ if (filePath.endsWith('Dockerfile'))
195
+ return 'dockerfile';
196
+ return map[ext] || 'text';
197
+ }
198
+ }
199
+ //# sourceMappingURL=file-attachment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-attachment.js","sourceRoot":"","sources":["../../src/services/file-attachment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * LLM Processor for content extraction
3
+ * Uses OpenRouter via OPENROUTER_API_KEY for AI-powered content filtering
4
+ * Implements robust retry logic and NEVER throws
5
+ */
6
+ import OpenAI from 'openai';
7
+ import { type StructuredError } from '../utils/errors.js';
8
+ interface ProcessingConfig {
9
+ use_llm: boolean;
10
+ what_to_extract: string | undefined;
11
+ max_tokens?: number;
12
+ }
13
+ interface LLMResult {
14
+ content: string;
15
+ processed: boolean;
16
+ error?: string;
17
+ errorDetails?: StructuredError;
18
+ }
19
+ export declare function createLLMProcessor(): OpenAI | null;
20
+ /**
21
+ * Process content with LLM extraction
22
+ * NEVER throws - always returns a valid LLMResult
23
+ * Implements retry logic with exponential backoff for transient failures
24
+ */
25
+ export declare function processContentWithLLM(content: string, config: ProcessingConfig, processor?: OpenAI | null): Promise<LLMResult>;
26
+ export {};
27
+ //# sourceMappingURL=llm-processor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-processor.d.ts","sourceRoot":"","sources":["../../src/services/llm-processor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAE5B,UAAU,gBAAgB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,SAAS;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,eAAe,CAAC;CAChC;AAmBD,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAYlD;AAqDD;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,EACxB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GACxB,OAAO,CAAC,SAAS,CAAC,CAkHpB"}
@@ -0,0 +1,179 @@
1
+ /**
2
+ * LLM Processor for content extraction
3
+ * Uses OpenRouter via OPENROUTER_API_KEY for AI-powered content filtering
4
+ * Implements robust retry logic and NEVER throws
5
+ */
6
+ import OpenAI from 'openai';
7
+ import { RESEARCH, LLM_EXTRACTION, getCapabilities } from '../config/index.js';
8
+ import { classifyError, sleep, ErrorCode, } from '../utils/errors.js';
9
+ // LLM-specific retry configuration
10
+ const LLM_RETRY_CONFIG = {
11
+ maxRetries: 3,
12
+ baseDelayMs: 2000,
13
+ maxDelayMs: 30000,
14
+ };
15
+ // OpenRouter/OpenAI specific retryable error codes (using Set for type-safe lookup)
16
+ const RETRYABLE_LLM_ERROR_CODES = new Set([
17
+ 'rate_limit_exceeded',
18
+ 'server_error',
19
+ 'timeout',
20
+ 'service_unavailable',
21
+ ]);
22
+ let llmClient = null;
23
+ export function createLLMProcessor() {
24
+ if (!getCapabilities().llmExtraction)
25
+ return null;
26
+ if (!llmClient) {
27
+ llmClient = new OpenAI({
28
+ baseURL: RESEARCH.BASE_URL,
29
+ apiKey: RESEARCH.API_KEY,
30
+ timeout: 120000,
31
+ maxRetries: 0, // We handle retries ourselves for more control
32
+ });
33
+ }
34
+ return llmClient;
35
+ }
36
+ /**
37
+ * Check if an LLM error is retryable
38
+ */
39
+ function isRetryableLLMError(error) {
40
+ if (!error)
41
+ return false;
42
+ const err = error;
43
+ // Check HTTP status codes
44
+ const status = err.status;
45
+ if (status === 429 || status === 500 || status === 502 || status === 503 || status === 504) {
46
+ return true;
47
+ }
48
+ // Check error codes from OpenAI/OpenRouter
49
+ const errorCode = err.code || err.error?.code || err.error?.type;
50
+ if (errorCode && RETRYABLE_LLM_ERROR_CODES.has(errorCode)) {
51
+ return true;
52
+ }
53
+ // Check message for common patterns
54
+ const message = (err.message || '').toLowerCase();
55
+ if (message.includes('rate limit') ||
56
+ message.includes('timeout') ||
57
+ message.includes('timed out') ||
58
+ message.includes('service unavailable') ||
59
+ message.includes('server error') ||
60
+ message.includes('connection') ||
61
+ message.includes('econnreset')) {
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+ /**
67
+ * Calculate backoff delay with jitter for LLM retries
68
+ */
69
+ function calculateLLMBackoff(attempt) {
70
+ const exponentialDelay = LLM_RETRY_CONFIG.baseDelayMs * Math.pow(2, attempt);
71
+ const jitter = Math.random() * 0.3 * exponentialDelay;
72
+ return Math.min(exponentialDelay + jitter, LLM_RETRY_CONFIG.maxDelayMs);
73
+ }
74
+ /**
75
+ * Process content with LLM extraction
76
+ * NEVER throws - always returns a valid LLMResult
77
+ * Implements retry logic with exponential backoff for transient failures
78
+ */
79
+ export async function processContentWithLLM(content, config, processor) {
80
+ // Early returns for invalid/skip conditions
81
+ if (!config.use_llm) {
82
+ return { content, processed: false };
83
+ }
84
+ if (!processor) {
85
+ return {
86
+ content,
87
+ processed: false,
88
+ error: 'LLM processor not available (OPENROUTER_API_KEY not set)',
89
+ errorDetails: {
90
+ code: ErrorCode.AUTH_ERROR,
91
+ message: 'LLM processor not available',
92
+ retryable: false,
93
+ },
94
+ };
95
+ }
96
+ if (!content?.trim()) {
97
+ return { content: content || '', processed: false, error: 'Empty content provided' };
98
+ }
99
+ // Truncate extremely long content to avoid token limits
100
+ const maxInputChars = 100000; // ~25k tokens
101
+ const truncatedContent = content.length > maxInputChars
102
+ ? content.substring(0, maxInputChars) + '\n\n[Content truncated due to length]'
103
+ : content;
104
+ const prompt = config.what_to_extract
105
+ ? `Extract and clean the following content. Focus on: ${config.what_to_extract}\n\nContent:\n${truncatedContent}`
106
+ : `Clean and extract the main content from the following text, removing navigation, ads, and irrelevant elements:\n\n${truncatedContent}`;
107
+ // Build request body
108
+ const requestBody = {
109
+ model: LLM_EXTRACTION.MODEL,
110
+ messages: [{ role: 'user', content: prompt }],
111
+ max_tokens: config.max_tokens || LLM_EXTRACTION.MAX_TOKENS,
112
+ };
113
+ if (LLM_EXTRACTION.ENABLE_REASONING) {
114
+ requestBody.reasoning = { enabled: true };
115
+ }
116
+ let lastError;
117
+ // Retry loop
118
+ for (let attempt = 0; attempt <= LLM_RETRY_CONFIG.maxRetries; attempt++) {
119
+ try {
120
+ if (attempt === 0) {
121
+ console.error(`[LLM Processor] Starting extraction with ${LLM_EXTRACTION.MODEL}`);
122
+ }
123
+ else {
124
+ console.error(`[LLM Processor] Retry attempt ${attempt}/${LLM_RETRY_CONFIG.maxRetries}`);
125
+ }
126
+ const response = await processor.chat.completions.create(requestBody);
127
+ const result = response.choices?.[0]?.message?.content;
128
+ if (result && result.trim()) {
129
+ console.error(`[LLM Processor] Successfully extracted ${result.length} characters`);
130
+ return { content: result, processed: true };
131
+ }
132
+ // Empty response - not retryable
133
+ console.error('[LLM Processor] Received empty response from LLM');
134
+ return {
135
+ content,
136
+ processed: false,
137
+ error: 'LLM returned empty response',
138
+ errorDetails: {
139
+ code: ErrorCode.INTERNAL_ERROR,
140
+ message: 'LLM returned empty response',
141
+ retryable: false,
142
+ },
143
+ };
144
+ }
145
+ catch (err) {
146
+ lastError = classifyError(err);
147
+ // Log the error
148
+ const errDetails = err;
149
+ console.error(`[LLM Processor] Error (attempt ${attempt + 1}): ${lastError.message}`, {
150
+ status: errDetails.status,
151
+ code: errDetails.code,
152
+ retryable: isRetryableLLMError(err),
153
+ });
154
+ // Check if we should retry
155
+ if (isRetryableLLMError(err) && attempt < LLM_RETRY_CONFIG.maxRetries) {
156
+ const delayMs = calculateLLMBackoff(attempt);
157
+ console.error(`[LLM Processor] Retrying in ${delayMs}ms...`);
158
+ await sleep(delayMs);
159
+ continue;
160
+ }
161
+ // Non-retryable or max retries reached
162
+ break;
163
+ }
164
+ }
165
+ // All attempts failed - return original content with error info
166
+ const errorMessage = lastError?.message || 'Unknown LLM error';
167
+ console.error(`[LLM Processor] All attempts failed: ${errorMessage}. Returning original content.`);
168
+ return {
169
+ content, // Return original content as fallback
170
+ processed: false,
171
+ error: `LLM extraction failed: ${errorMessage}`,
172
+ errorDetails: lastError || {
173
+ code: ErrorCode.UNKNOWN_ERROR,
174
+ message: errorMessage,
175
+ retryable: false,
176
+ },
177
+ };
178
+ }
179
+ //# sourceMappingURL=llm-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-processor.js","sourceRoot":"","sources":["../../src/services/llm-processor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare class MarkdownCleaner {
2
+ /**
3
+ * Process HTML content and convert to clean Markdown
4
+ * NEVER throws - returns original content on any error for graceful degradation
5
+ */
6
+ processContent(htmlContent: string): string;
7
+ }
8
+ //# sourceMappingURL=markdown-cleaner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-cleaner.d.ts","sourceRoot":"","sources":["../../src/services/markdown-cleaner.ts"],"names":[],"mappings":"AAcA,qBAAa,eAAe;IAC1B;;;OAGG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;CAmC5C"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Markdown cleaner service using Turndown for HTML to Markdown conversion
3
+ */
4
+ import TurndownService from 'turndown';
5
+ const turndown = new TurndownService({
6
+ headingStyle: 'atx',
7
+ codeBlockStyle: 'fenced',
8
+ bulletListMarker: '-',
9
+ });
10
+ // Remove script, style, nav, footer, aside elements
11
+ turndown.remove(['script', 'style', 'nav', 'footer', 'aside', 'noscript']);
12
+ export class MarkdownCleaner {
13
+ /**
14
+ * Process HTML content and convert to clean Markdown
15
+ * NEVER throws - returns original content on any error for graceful degradation
16
+ */
17
+ processContent(htmlContent) {
18
+ try {
19
+ // Handle null/undefined/non-string inputs gracefully
20
+ if (!htmlContent || typeof htmlContent !== 'string') {
21
+ return htmlContent || '';
22
+ }
23
+ // If already markdown (no HTML tags), return as-is
24
+ if (!htmlContent.includes('<')) {
25
+ return htmlContent.trim();
26
+ }
27
+ // Remove HTML comments before conversion
28
+ let content = htmlContent.replace(/<!--[\s\S]*?-->/g, '');
29
+ // Convert HTML to Markdown using Turndown
30
+ content = turndown.turndown(content);
31
+ // Clean up whitespace
32
+ content = content.replace(/\n{3,}/g, '\n\n');
33
+ content = content.trim();
34
+ return content;
35
+ }
36
+ catch (error) {
37
+ // Log error but don't crash - return original content for graceful degradation
38
+ console.error('[MarkdownCleaner] processContent failed:', error instanceof Error ? error.message : String(error), '| Content length:', htmlContent?.length ?? 0);
39
+ // Return original content if conversion fails
40
+ return htmlContent || '';
41
+ }
42
+ }
43
+ }
44
+ //# sourceMappingURL=markdown-cleaner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"markdown-cleaner.js","sourceRoot":"","sources":["../../src/services/markdown-cleaner.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,eAAe,MAAM,UAAU,CAAC;AAEvC,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC;IACnC,YAAY,EAAE,KAAK;IACnB,cAAc,EAAE,QAAQ;IACxB,gBAAgB,EAAE,GAAG;CACtB,CAAC,CAAC;AAEH,oDAAoD;AACpD,QAAQ,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC;AAE3E,MAAM,OAAO,eAAe;IAC1B;;;OAGG;IACH,cAAc,CAAC,WAAmB;QAChC,IAAI,CAAC;YACH,qDAAqD;YACrD,IAAI,CAAC,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;gBACpD,OAAO,WAAW,IAAI,EAAE,CAAC;YAC3B,CAAC;YAED,mDAAmD;YACnD,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/B,OAAO,WAAW,CAAC,IAAI,EAAE,CAAC;YAC5B,CAAC;YAED,yCAAyC;YACzC,IAAI,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;YAE1D,0CAA0C;YAC1C,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAErC,sBAAsB;YACtB,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC7C,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAEzB,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,+EAA+E;YAC/E,OAAO,CAAC,KAAK,CACX,0CAA0C,EAC1C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACtD,mBAAmB,EACnB,WAAW,EAAE,MAAM,IAAI,CAAC,CACzB,CAAC;YACF,8CAA8C;YAC9C,OAAO,WAAW,IAAI,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * MCP Tool Definitions
3
+ * Generated from YAML configuration for consistency
4
+ */
5
+ /**
6
+ * TOOLS array is now loaded from src/config/yaml/tools.yaml
7
+ * This provides a single source of truth for all tool metadata
8
+ *
9
+ * Benefits:
10
+ * - Descriptions defined once in YAML
11
+ * - Easy to update without touching TypeScript
12
+ * - Consistent format across all tools
13
+ * - Validation rules co-located with descriptions
14
+ */
15
+ export declare const TOOLS: import("../config/types.js").McpTool[];
16
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;;GASG;AACH,eAAO,MAAM,KAAK,wCAAqB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * MCP Tool Definitions
3
+ * Generated from YAML configuration for consistency
4
+ */
5
+ import { generateMcpTools } from '../config/loader.js';
6
+ /**
7
+ * TOOLS array is now loaded from src/config/yaml/tools.yaml
8
+ * This provides a single source of truth for all tool metadata
9
+ *
10
+ * Benefits:
11
+ * - Descriptions defined once in YAML
12
+ * - Easy to update without touching TypeScript
13
+ * - Consistent format across all tools
14
+ * - Validation rules co-located with descriptions
15
+ */
16
+ export const TOOLS = generateMcpTools();
17
+ //# sourceMappingURL=definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Reddit Tools - Search and Fetch
3
+ * NEVER throws - always returns structured response for graceful degradation
4
+ */
5
+ export declare function handleSearchReddit(queries: string[], apiKey: string, dateAfter?: string): Promise<string>;
6
+ interface GetRedditPostsOptions {
7
+ fetchComments?: boolean;
8
+ maxCommentsOverride?: number;
9
+ use_llm?: boolean;
10
+ what_to_extract?: string;
11
+ }
12
+ export declare function handleGetRedditPosts(urls: string[], clientId: string, clientSecret: string, maxComments?: number, options?: GetRedditPostsOptions): Promise<string>;
13
+ export {};
14
+ //# sourceMappingURL=reddit.d.ts.map