research-powerpack-mcp 3.0.14 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/clients/reddit.d.ts +9 -1
- package/dist/clients/reddit.d.ts.map +1 -1
- package/dist/clients/reddit.js +121 -41
- package/dist/clients/reddit.js.map +1 -1
- package/dist/clients/research.d.ts +16 -0
- package/dist/clients/research.d.ts.map +1 -1
- package/dist/clients/research.js +135 -31
- package/dist/clients/research.js.map +1 -1
- package/dist/clients/scraper.d.ts +27 -1
- package/dist/clients/scraper.d.ts.map +1 -1
- package/dist/clients/scraper.js +206 -101
- package/dist/clients/scraper.js.map +1 -1
- package/dist/clients/search.d.ts +15 -0
- package/dist/clients/search.d.ts.map +1 -1
- package/dist/clients/search.js +174 -52
- package/dist/clients/search.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -6
- package/dist/index.js.map +1 -1
- package/dist/services/llm-processor.d.ts +18 -0
- package/dist/services/llm-processor.d.ts.map +1 -1
- package/dist/services/llm-processor.js +174 -24
- package/dist/services/llm-processor.js.map +1 -1
- package/dist/tools/research.d.ts +5 -0
- package/dist/tools/research.d.ts.map +1 -1
- package/dist/tools/research.js +63 -18
- package/dist/tools/research.js.map +1 -1
- package/dist/tools/scrape.d.ts +5 -0
- package/dist/tools/scrape.d.ts.map +1 -1
- package/dist/tools/scrape.js +144 -81
- package/dist/tools/scrape.js.map +1 -1
- package/dist/utils/errors.d.ts +79 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +253 -22
- package/dist/utils/errors.js.map +1 -1
- package/package.json +1 -1
package/dist/tools/scrape.js
CHANGED
|
@@ -1,111 +1,174 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scrape Links Tool Handler
|
|
3
|
+
* Implements robust error handling that NEVER crashes the MCP server
|
|
3
4
|
*/
|
|
4
5
|
import { ScraperClient } from '../clients/scraper.js';
|
|
5
6
|
import { MarkdownCleaner } from '../services/markdown-cleaner.js';
|
|
6
7
|
import { createLLMProcessor, processContentWithLLM } from '../services/llm-processor.js';
|
|
7
8
|
import { removeMetaTags } from '../utils/markdown-formatter.js';
|
|
8
9
|
import { SCRAPER } from '../config/index.js';
|
|
10
|
+
import { classifyError } from '../utils/errors.js';
|
|
9
11
|
function calculateTokenAllocation(urlCount) {
|
|
12
|
+
if (urlCount <= 0)
|
|
13
|
+
return SCRAPER.MAX_TOKENS_BUDGET;
|
|
10
14
|
return Math.floor(SCRAPER.MAX_TOKENS_BUDGET / urlCount);
|
|
11
15
|
}
|
|
12
16
|
function enhanceExtractionInstruction(instruction) {
|
|
13
17
|
const base = instruction || 'Extract the main content and key information from this page.';
|
|
14
18
|
return `${base}\n\n${SCRAPER.EXTRACTION_SUFFIX}`;
|
|
15
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Safe logger wrapper - NEVER throws
|
|
22
|
+
*/
|
|
23
|
+
async function safeLog(logger, sessionId, level, message) {
|
|
24
|
+
if (!logger || !sessionId)
|
|
25
|
+
return;
|
|
26
|
+
try {
|
|
27
|
+
await logger(level, message, sessionId);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// Silently ignore logger errors - they should never crash the tool
|
|
31
|
+
console.error(`[Scrape Tool] Logger failed: ${message}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Handle scrape links request
|
|
36
|
+
* NEVER throws - always returns a valid response with content and metadata
|
|
37
|
+
*/
|
|
16
38
|
export async function handleScrapeLinks(params, options = {}) {
|
|
17
39
|
const { sessionId, logger } = options;
|
|
18
40
|
const startTime = Date.now();
|
|
41
|
+
// Helper to create error response
|
|
42
|
+
const createErrorResponse = (message, executionTime) => ({
|
|
43
|
+
content: `# ❌ Scraping Failed\n\n${message}`,
|
|
44
|
+
structuredContent: {
|
|
45
|
+
content: `# ❌ Scraping Failed\n\n${message}`,
|
|
46
|
+
metadata: {
|
|
47
|
+
total_urls: params.urls?.length || 0,
|
|
48
|
+
successful: 0,
|
|
49
|
+
failed: params.urls?.length || 0,
|
|
50
|
+
total_credits: 0,
|
|
51
|
+
execution_time_ms: executionTime,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
// Validate params
|
|
56
|
+
if (!params.urls || params.urls.length === 0) {
|
|
57
|
+
return createErrorResponse('No URLs provided', Date.now() - startTime);
|
|
58
|
+
}
|
|
59
|
+
// Filter out invalid URLs early
|
|
60
|
+
const validUrls = [];
|
|
61
|
+
const invalidUrls = [];
|
|
62
|
+
for (const url of params.urls) {
|
|
63
|
+
try {
|
|
64
|
+
new URL(url);
|
|
65
|
+
validUrls.push(url);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
invalidUrls.push(url);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (validUrls.length === 0) {
|
|
72
|
+
return createErrorResponse(`All ${params.urls.length} URLs are invalid`, Date.now() - startTime);
|
|
73
|
+
}
|
|
74
|
+
const tokensPerUrl = calculateTokenAllocation(validUrls.length);
|
|
75
|
+
const totalBatches = Math.ceil(validUrls.length / SCRAPER.BATCH_SIZE);
|
|
76
|
+
await safeLog(logger, sessionId, 'info', `Starting scrape: ${validUrls.length} URL(s), ${tokensPerUrl} tokens/URL, ${totalBatches} batch(es)`);
|
|
77
|
+
// Initialize clients safely
|
|
78
|
+
let client;
|
|
19
79
|
try {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
80
|
+
client = new ScraperClient();
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const err = classifyError(error);
|
|
84
|
+
return createErrorResponse(`Failed to initialize scraper: ${err.message}`, Date.now() - startTime);
|
|
85
|
+
}
|
|
86
|
+
const markdownCleaner = new MarkdownCleaner();
|
|
87
|
+
const llmProcessor = createLLMProcessor(); // Returns null if not configured
|
|
88
|
+
const enhancedInstruction = params.use_llm
|
|
89
|
+
? enhanceExtractionInstruction(params.what_to_extract)
|
|
90
|
+
: undefined;
|
|
91
|
+
// Scrape URLs - scrapeMultiple NEVER throws
|
|
92
|
+
const results = await client.scrapeMultiple(validUrls, { timeout: params.timeout });
|
|
93
|
+
await safeLog(logger, sessionId, 'info', `Scraping complete. Processing ${results.length} results...`);
|
|
94
|
+
let successful = 0;
|
|
95
|
+
let failed = 0;
|
|
96
|
+
let totalCredits = 0;
|
|
97
|
+
let llmErrors = 0;
|
|
98
|
+
const contents = [];
|
|
99
|
+
// Add invalid URLs to failed count
|
|
100
|
+
for (const invalidUrl of invalidUrls) {
|
|
101
|
+
failed++;
|
|
102
|
+
contents.push(`## ${invalidUrl}\n\n❌ Invalid URL format`);
|
|
103
|
+
}
|
|
104
|
+
// Process each result
|
|
105
|
+
for (let i = 0; i < results.length; i++) {
|
|
106
|
+
const result = results[i];
|
|
107
|
+
if (!result) {
|
|
108
|
+
failed++;
|
|
109
|
+
contents.push(`## Unknown URL\n\n❌ No result returned`);
|
|
110
|
+
continue;
|
|
24
111
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
await logger('info', `Scraping complete. Processing ${results.length} results...`, sessionId);
|
|
112
|
+
await safeLog(logger, sessionId, 'info', `[${i + 1}/${results.length}] Processing ${result.url}`);
|
|
113
|
+
// Check for errors in result
|
|
114
|
+
if (result.error || result.statusCode < 200 || result.statusCode >= 300) {
|
|
115
|
+
failed++;
|
|
116
|
+
const errorMsg = result.error?.message || result.content || `HTTP ${result.statusCode}`;
|
|
117
|
+
contents.push(`## ${result.url}\n\n❌ Failed to scrape: ${errorMsg}`);
|
|
118
|
+
await safeLog(logger, sessionId, 'error', `[${i + 1}/${results.length}] Failed: ${errorMsg}`);
|
|
119
|
+
continue;
|
|
34
120
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const llmResult = await processContentWithLLM(content, { use_llm: params.use_llm, what_to_extract: enhancedInstruction, max_tokens: tokensPerUrl }, llmProcessor);
|
|
55
|
-
content = llmResult.content;
|
|
56
|
-
if (sessionId && logger) {
|
|
57
|
-
await logger('info', `[${i + 1}/${results.length}] LLM processing ${llmResult.processed ? 'complete' : 'skipped'}`, sessionId);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
content = removeMetaTags(content);
|
|
61
|
-
contents.push(`## ${result.url}\n\n${content}`);
|
|
121
|
+
// Success case
|
|
122
|
+
successful++;
|
|
123
|
+
totalCredits += result.credits;
|
|
124
|
+
// Process content safely
|
|
125
|
+
let content;
|
|
126
|
+
try {
|
|
127
|
+
content = markdownCleaner.processContent(result.content);
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// If markdown cleaning fails, use raw content
|
|
131
|
+
content = result.content;
|
|
132
|
+
}
|
|
133
|
+
// Apply LLM extraction if enabled - processContentWithLLM NEVER throws
|
|
134
|
+
if (params.use_llm && llmProcessor) {
|
|
135
|
+
await safeLog(logger, sessionId, 'info', `[${i + 1}/${results.length}] Applying LLM extraction (${tokensPerUrl} tokens)...`);
|
|
136
|
+
const llmResult = await processContentWithLLM(content, { use_llm: params.use_llm, what_to_extract: enhancedInstruction, max_tokens: tokensPerUrl }, llmProcessor);
|
|
137
|
+
if (llmResult.processed) {
|
|
138
|
+
content = llmResult.content;
|
|
139
|
+
await safeLog(logger, sessionId, 'info', `[${i + 1}/${results.length}] LLM extraction complete`);
|
|
62
140
|
}
|
|
63
141
|
else {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
await logger('error', `[${i + 1}/${results.length}] Failed: ${result.statusCode}`, sessionId);
|
|
68
|
-
}
|
|
142
|
+
llmErrors++;
|
|
143
|
+
await safeLog(logger, sessionId, 'info', `[${i + 1}/${results.length}] LLM extraction skipped: ${llmResult.error || 'unknown reason'}`);
|
|
144
|
+
// Continue with original content - graceful degradation
|
|
69
145
|
}
|
|
70
146
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
147
|
+
// Remove meta tags safely
|
|
148
|
+
try {
|
|
149
|
+
content = removeMetaTags(content);
|
|
74
150
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const formattedContent = `# Scraped Content (${params.urls.length} URLs)\n\n${allocationHeader}\n${statusHeader}\n\n---\n\n${contents.join('\n\n---\n\n')}`;
|
|
78
|
-
const metadata = {
|
|
79
|
-
total_urls: params.urls.length,
|
|
80
|
-
successful,
|
|
81
|
-
failed,
|
|
82
|
-
total_credits: totalCredits,
|
|
83
|
-
execution_time_ms: executionTime,
|
|
84
|
-
tokens_per_url: tokensPerUrl,
|
|
85
|
-
total_token_budget: SCRAPER.MAX_TOKENS_BUDGET,
|
|
86
|
-
batches_processed: totalBatches,
|
|
87
|
-
};
|
|
88
|
-
return { content: formattedContent, structuredContent: { content: formattedContent, metadata } };
|
|
89
|
-
}
|
|
90
|
-
catch (error) {
|
|
91
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
92
|
-
if (sessionId && logger) {
|
|
93
|
-
await logger('error', errorMessage, sessionId);
|
|
151
|
+
catch {
|
|
152
|
+
// If this fails, just use the content as-is
|
|
94
153
|
}
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
content: `# ❌ Scraping Failed\n\n${errorMessage}`,
|
|
98
|
-
structuredContent: {
|
|
99
|
-
content: `# ❌ Scraping Failed\n\n${errorMessage}`,
|
|
100
|
-
metadata: {
|
|
101
|
-
total_urls: params.urls.length,
|
|
102
|
-
successful: 0,
|
|
103
|
-
failed: params.urls.length,
|
|
104
|
-
total_credits: 0,
|
|
105
|
-
execution_time_ms: executionTime,
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
};
|
|
154
|
+
contents.push(`## ${result.url}\n\n${content}`);
|
|
109
155
|
}
|
|
156
|
+
const executionTime = Date.now() - startTime;
|
|
157
|
+
await safeLog(logger, sessionId, 'info', `Completed: ${successful} successful, ${failed} failed, ${totalCredits} credits used`);
|
|
158
|
+
// Build response
|
|
159
|
+
const allocationHeader = `**Token Allocation:** ${tokensPerUrl.toLocaleString()} tokens/URL (${params.urls.length} URLs, ${SCRAPER.MAX_TOKENS_BUDGET.toLocaleString()} total budget)`;
|
|
160
|
+
const statusHeader = `**Status:** ✅ ${successful} successful | ❌ ${failed} failed | 📦 ${totalBatches} batch(es)${llmErrors > 0 ? ` | ⚠️ ${llmErrors} LLM extraction failures` : ''}`;
|
|
161
|
+
const formattedContent = `# Scraped Content (${params.urls.length} URLs)\n\n${allocationHeader}\n${statusHeader}\n\n---\n\n${contents.join('\n\n---\n\n')}`;
|
|
162
|
+
const metadata = {
|
|
163
|
+
total_urls: params.urls.length,
|
|
164
|
+
successful,
|
|
165
|
+
failed,
|
|
166
|
+
total_credits: totalCredits,
|
|
167
|
+
execution_time_ms: executionTime,
|
|
168
|
+
tokens_per_url: tokensPerUrl,
|
|
169
|
+
total_token_budget: SCRAPER.MAX_TOKENS_BUDGET,
|
|
170
|
+
batches_processed: totalBatches,
|
|
171
|
+
};
|
|
172
|
+
return { content: formattedContent, structuredContent: { content: formattedContent, metadata } };
|
|
110
173
|
}
|
|
111
174
|
//# sourceMappingURL=scrape.js.map
|
package/dist/tools/scrape.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrape.js","sourceRoot":"","sources":["../../src/tools/scrape.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"scrape.js","sourceRoot":"","sources":["../../src/tools/scrape.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAa,MAAM,oBAAoB,CAAC;AAO9D,SAAS,wBAAwB,CAAC,QAAgB;IAChD,IAAI,QAAQ,IAAI,CAAC;QAAE,OAAO,OAAO,CAAC,iBAAiB,CAAC;IACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,GAAG,QAAQ,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,4BAA4B,CAAC,WAA+B;IACnE,MAAM,IAAI,GAAG,WAAW,IAAI,8DAA8D,CAAC;IAC3F,OAAO,GAAG,IAAI,OAAO,OAAO,CAAC,iBAAiB,EAAE,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,OAAO,CACpB,MAA6B,EAC7B,SAA6B,EAC7B,KAAiC,EACjC,OAAe;IAEf,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS;QAAE,OAAO;IAClC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,mEAAmE;QACnE,OAAO,CAAC,KAAK,CAAC,gCAAgC,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAyB,EACzB,UAAuB,EAAE;IAEzB,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,kCAAkC;IAClC,MAAM,mBAAmB,GAAG,CAAC,OAAe,EAAE,aAAqB,EAA6D,EAAE,CAAC,CAAC;QAClI,OAAO,EAAE,0BAA0B,OAAO,EAAE;QAC5C,iBAAiB,EAAE;YACjB,OAAO,EAAE,0BAA0B,OAAO,EAAE;YAC5C,QAAQ,EAAE;gBACR,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;gBACpC,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;gBAChC,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,aAAa;aACjC;SACF;KACF,CAAC,CAAC;IAEH,kBAAkB;IAClB,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7C,OAAO,mBAAmB,CAAC,kBAAkB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IACzE,CAAC;IAED,gCAAgC;IAChC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YACb,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,mBAAmB,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,mBAAmB,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IACnG,CAAC;IAED,MAAM,YAAY,GAAG,wBAAwB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;IAEtE,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,oBAAoB,SAAS,CAAC,MAAM,YAAY,YAAY,gBAAgB,YAAY,YAAY,CAAC,CAAC;IAE/I,4BAA4B;IAC5B,IAAI,MAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,GAAG,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QACjC,OAAO,mBAAmB,CAAC,iCAAiC,GAAG,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;IACrG,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC9C,MAAM,YAAY,GAAG,kBAAkB,EAAE,CAAC,CAAC,iCAAiC;IAE5E,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO;QACxC,CAAC,CAAC,4BAA4B,CAAC,MAAM,CAAC,eAAe,CAAC;QACtD,CAAC,CAAC,SAAS,CAAC;IAEd,4CAA4C;IAC5C,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAEpF,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,iCAAiC,OAAO,CAAC,MAAM,aAAa,CAAC,CAAC;IAEvG,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,mCAAmC;IACnC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,EAAE,CAAC;QACT,QAAQ,CAAC,IAAI,CAAC,MAAM,UAAU,0BAA0B,CAAC,CAAC;IAC5D,CAAC;IAED,sBAAsB;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC;YACT,QAAQ,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;YACxD,SAAS;QACX,CAAC;QAED,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,gBAAgB,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC;QAElG,6BAA6B;QAC7B,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,GAAG,GAAG,IAAI,MAAM,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;YACxE,MAAM,EAAE,CAAC;YACT,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,IAAI,MAAM,CAAC,OAAO,IAAI,QAAQ,MAAM,CAAC,UAAU,EAAE,CAAC;YACxF,QAAQ,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,GAAG,2BAA2B,QAAQ,EAAE,CAAC,CAAC;YAErE,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,aAAa,QAAQ,EAAE,CAAC,CAAC;YAC9F,SAAS;QACX,CAAC;QAED,eAAe;QACf,UAAU,EAAE,CAAC;QACb,YAAY,IAAI,MAAM,CAAC,OAAO,CAAC;QAE/B,yBAAyB;QACzB,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,eAAe,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,8CAA8C;YAC9C,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC3B,CAAC;QAED,uEAAuE;QACvE,IAAI,MAAM,CAAC,OAAO,IAAI,YAAY,EAAE,CAAC;YACnC,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,8BAA8B,YAAY,aAAa,CAAC,CAAC;YAE7H,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAC3C,OAAO,EACP,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,UAAU,EAAE,YAAY,EAAE,EAC3F,YAAY,CACb,CAAC;YAEF,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;gBACxB,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;gBAC5B,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,2BAA2B,CAAC,CAAC;YACnG,CAAC;iBAAM,CAAC;gBACN,SAAS,EAAE,CAAC;gBACZ,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,6BAA6B,SAAS,CAAC,KAAK,IAAI,gBAAgB,EAAE,CAAC,CAAC;gBACxI,wDAAwD;YAC1D,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,IAAI,CAAC;YACH,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,4CAA4C;QAC9C,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,MAAM,MAAM,CAAC,GAAG,OAAO,OAAO,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAE7C,MAAM,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,UAAU,gBAAgB,MAAM,YAAY,YAAY,eAAe,CAAC,CAAC;IAEhI,iBAAiB;IACjB,MAAM,gBAAgB,GAAG,yBAAyB,YAAY,CAAC,cAAc,EAAE,gBAAgB,MAAM,CAAC,IAAI,CAAC,MAAM,UAAU,OAAO,CAAC,iBAAiB,CAAC,cAAc,EAAE,gBAAgB,CAAC;IACtL,MAAM,YAAY,GAAG,iBAAiB,UAAU,mBAAmB,MAAM,gBAAgB,YAAY,aAAa,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,0BAA0B,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACtL,MAAM,gBAAgB,GAAG,sBAAsB,MAAM,CAAC,IAAI,CAAC,MAAM,aAAa,gBAAgB,KAAK,YAAY,cAAc,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;IAE5J,MAAM,QAAQ,GAAG;QACf,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM;QAC9B,UAAU;QACV,MAAM;QACN,aAAa,EAAE,YAAY;QAC3B,iBAAiB,EAAE,aAAa;QAChC,cAAc,EAAE,YAAY;QAC5B,kBAAkB,EAAE,OAAO,CAAC,iBAAiB;QAC7C,iBAAiB,EAAE,YAAY;KAChC,CAAC;IAEF,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,EAAE,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,CAAC;AACnG,CAAC"}
|
package/dist/utils/errors.d.ts
CHANGED
|
@@ -1,5 +1,83 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Robust error handling utilities for MCP server
|
|
3
|
+
* Ensures the server NEVER crashes and always returns structured responses
|
|
4
|
+
*/
|
|
5
|
+
export declare const ErrorCode: {
|
|
6
|
+
readonly RATE_LIMITED: "RATE_LIMITED";
|
|
7
|
+
readonly TIMEOUT: "TIMEOUT";
|
|
8
|
+
readonly NETWORK_ERROR: "NETWORK_ERROR";
|
|
9
|
+
readonly SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE";
|
|
10
|
+
readonly AUTH_ERROR: "AUTH_ERROR";
|
|
11
|
+
readonly INVALID_INPUT: "INVALID_INPUT";
|
|
12
|
+
readonly NOT_FOUND: "NOT_FOUND";
|
|
13
|
+
readonly QUOTA_EXCEEDED: "QUOTA_EXCEEDED";
|
|
14
|
+
readonly INTERNAL_ERROR: "INTERNAL_ERROR";
|
|
15
|
+
readonly PARSE_ERROR: "PARSE_ERROR";
|
|
16
|
+
readonly UNKNOWN_ERROR: "UNKNOWN_ERROR";
|
|
17
|
+
};
|
|
18
|
+
export type ErrorCodeType = typeof ErrorCode[keyof typeof ErrorCode];
|
|
19
|
+
export interface StructuredError {
|
|
20
|
+
code: ErrorCodeType;
|
|
21
|
+
message: string;
|
|
22
|
+
retryable: boolean;
|
|
23
|
+
statusCode?: number;
|
|
24
|
+
cause?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RetryOptions {
|
|
27
|
+
maxRetries: number;
|
|
28
|
+
baseDelayMs: number;
|
|
29
|
+
maxDelayMs: number;
|
|
30
|
+
retryableStatuses: number[];
|
|
31
|
+
onRetry?: (attempt: number, error: StructuredError, delayMs: number) => void;
|
|
32
|
+
}
|
|
33
|
+
export declare const DEFAULT_RETRY_OPTIONS: RetryOptions;
|
|
34
|
+
/**
|
|
35
|
+
* Classify any error into a structured format
|
|
36
|
+
* NEVER throws - always returns a valid StructuredError
|
|
37
|
+
*/
|
|
38
|
+
export declare function classifyError(error: unknown): StructuredError;
|
|
39
|
+
/**
|
|
40
|
+
* Calculate delay with exponential backoff and jitter
|
|
41
|
+
*/
|
|
42
|
+
export declare function calculateBackoff(attempt: number, options: RetryOptions): number;
|
|
43
|
+
/**
|
|
44
|
+
* Sleep utility that respects abort signals
|
|
45
|
+
*/
|
|
46
|
+
export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Execute a function with retry logic
|
|
49
|
+
* NEVER throws on final failure - returns error result instead
|
|
50
|
+
*/
|
|
51
|
+
export declare function withRetry<T>(fn: (signal: AbortSignal) => Promise<T>, options?: Partial<RetryOptions>): Promise<{
|
|
52
|
+
success: true;
|
|
53
|
+
data: T;
|
|
54
|
+
} | {
|
|
55
|
+
success: false;
|
|
56
|
+
error: StructuredError;
|
|
57
|
+
attempts: number;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Wrap a fetch call with timeout via AbortController
|
|
61
|
+
*/
|
|
62
|
+
export declare function fetchWithTimeout(url: string, options?: RequestInit & {
|
|
63
|
+
timeoutMs?: number;
|
|
64
|
+
}): Promise<Response>;
|
|
65
|
+
/**
|
|
66
|
+
* Safely execute any function, NEVER throws
|
|
67
|
+
*/
|
|
68
|
+
export declare function safeExecute<T>(fn: () => Promise<T>, fallback: T): Promise<{
|
|
69
|
+
data: T;
|
|
70
|
+
error?: StructuredError;
|
|
71
|
+
}>;
|
|
72
|
+
/**
|
|
73
|
+
* Safely parse JSON, NEVER throws
|
|
74
|
+
*/
|
|
75
|
+
export declare function safeJsonParse<T>(text: string, fallback: T): {
|
|
76
|
+
data: T;
|
|
77
|
+
error?: string;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* @deprecated Use classifyError instead
|
|
3
81
|
*/
|
|
4
82
|
export declare function createSimpleError(error: unknown): {
|
|
5
83
|
message: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/utils/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,eAAO,MAAM,SAAS;;;;;;;;;;;;CAiBZ,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,OAAO,SAAS,CAAC,MAAM,OAAO,SAAS,CAAC,CAAC;AAMrE,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9E;AAED,eAAO,MAAM,qBAAqB,EAAE,YAKnC,CAAC;AAMF;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CA4F7D;AAyCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,MAAM,CAI/E;AAED;;GAEG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAcrE;AAED;;;GAGG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACvC,OAAO,GAAE,OAAO,CAAC,YAAY,CAAM,GAClC,OAAO,CAAC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAqCpG;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,WAAW,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,QAAQ,CAAC,CAcnB;AAMD;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EACjC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,QAAQ,EAAE,CAAC,GACV,OAAO,CAAC;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,eAAe,CAAA;CAAE,CAAC,CAO/C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAMvF;AAMD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAGnF"}
|