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.
- package/README.md +635 -0
- package/dist/clients/reddit.d.ts +74 -0
- package/dist/clients/reddit.d.ts.map +1 -0
- package/dist/clients/reddit.js +305 -0
- package/dist/clients/reddit.js.map +1 -0
- package/dist/clients/research.d.ts +67 -0
- package/dist/clients/research.d.ts.map +1 -0
- package/dist/clients/research.js +252 -0
- package/dist/clients/research.js.map +1 -0
- package/dist/clients/scraper.d.ts +71 -0
- package/dist/clients/scraper.d.ts.map +1 -0
- package/dist/clients/scraper.js +321 -0
- package/dist/clients/scraper.js.map +1 -0
- package/dist/clients/search.d.ts +62 -0
- package/dist/clients/search.d.ts.map +1 -0
- package/dist/clients/search.js +219 -0
- package/dist/clients/search.js.map +1 -0
- package/dist/config/index.d.ts +62 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +142 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/loader.d.ts +40 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +305 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +81 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/yaml/tools.yaml +130 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +271 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/deep-research.d.ts +64 -0
- package/dist/schemas/deep-research.d.ts.map +1 -0
- package/dist/schemas/deep-research.js +224 -0
- package/dist/schemas/deep-research.js.map +1 -0
- package/dist/schemas/scrape-links.d.ts +32 -0
- package/dist/schemas/scrape-links.d.ts.map +1 -0
- package/dist/schemas/scrape-links.js +34 -0
- package/dist/schemas/scrape-links.js.map +1 -0
- package/dist/schemas/web-search.d.ts +22 -0
- package/dist/schemas/web-search.d.ts.map +1 -0
- package/dist/schemas/web-search.js +21 -0
- package/dist/schemas/web-search.js.map +1 -0
- package/dist/services/file-attachment.d.ts +30 -0
- package/dist/services/file-attachment.d.ts.map +1 -0
- package/dist/services/file-attachment.js +199 -0
- package/dist/services/file-attachment.js.map +1 -0
- package/dist/services/llm-processor.d.ts +27 -0
- package/dist/services/llm-processor.d.ts.map +1 -0
- package/dist/services/llm-processor.js +179 -0
- package/dist/services/llm-processor.js.map +1 -0
- package/dist/services/markdown-cleaner.d.ts +8 -0
- package/dist/services/markdown-cleaner.d.ts.map +1 -0
- package/dist/services/markdown-cleaner.js +44 -0
- package/dist/services/markdown-cleaner.js.map +1 -0
- package/dist/tools/definitions.d.ts +16 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +17 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/reddit.d.ts +14 -0
- package/dist/tools/reddit.d.ts.map +1 -0
- package/dist/tools/reddit.js +213 -0
- package/dist/tools/reddit.js.map +1 -0
- package/dist/tools/registry.d.ts +71 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +242 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/research.d.ts +14 -0
- package/dist/tools/research.d.ts.map +1 -0
- package/dist/tools/research.js +194 -0
- package/dist/tools/research.js.map +1 -0
- package/dist/tools/scrape.d.ts +14 -0
- package/dist/tools/scrape.d.ts.map +1 -0
- package/dist/tools/scrape.js +201 -0
- package/dist/tools/scrape.js.map +1 -0
- package/dist/tools/search.d.ts +10 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +137 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/utils.d.ts +105 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +159 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/utils/concurrency.d.ts +29 -0
- package/dist/utils/concurrency.d.ts.map +1 -0
- package/dist/utils/concurrency.js +73 -0
- package/dist/utils/concurrency.js.map +1 -0
- package/dist/utils/errors.d.ts +77 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +335 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/logger.d.ts +39 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +57 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/markdown-formatter.d.ts +5 -0
- package/dist/utils/markdown-formatter.d.ts.map +1 -0
- package/dist/utils/markdown-formatter.js +15 -0
- package/dist/utils/markdown-formatter.js.map +1 -0
- package/dist/utils/response.d.ts +88 -0
- package/dist/utils/response.d.ts.map +1 -0
- package/dist/utils/response.js +151 -0
- package/dist/utils/response.js.map +1 -0
- package/dist/utils/url-aggregator.d.ts +90 -0
- package/dist/utils/url-aggregator.d.ts.map +1 -0
- package/dist/utils/url-aggregator.js +502 -0
- package/dist/utils/url-aggregator.js.map +1 -0
- package/dist/version.d.ts +30 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +60 -0
- package/dist/version.js.map +1 -0
- package/dist/worker.d.ts +17 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +53 -0
- package/dist/worker.js.map +1 -0
- 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
|