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
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* LLM Processor for content extraction
|
|
3
3
|
* Uses OpenRouter via OPENROUTER_API_KEY for AI-powered content filtering
|
|
4
|
+
* Implements robust retry logic and NEVER throws
|
|
4
5
|
*/
|
|
5
6
|
import OpenAI from 'openai';
|
|
6
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
|
+
]);
|
|
7
22
|
let llmClient = null;
|
|
8
23
|
export function createLLMProcessor() {
|
|
9
24
|
if (!getCapabilities().llmExtraction)
|
|
@@ -13,41 +28,176 @@ export function createLLMProcessor() {
|
|
|
13
28
|
baseURL: RESEARCH.BASE_URL,
|
|
14
29
|
apiKey: RESEARCH.API_KEY,
|
|
15
30
|
timeout: 120000,
|
|
31
|
+
maxRetries: 0, // We handle retries ourselves for more control
|
|
16
32
|
});
|
|
17
33
|
}
|
|
18
34
|
return llmClient;
|
|
19
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
|
+
*/
|
|
20
79
|
export async function processContentWithLLM(content, config, processor) {
|
|
21
|
-
|
|
80
|
+
// Early returns for invalid/skip conditions
|
|
81
|
+
if (!config.use_llm) {
|
|
22
82
|
return { content, processed: false };
|
|
23
83
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
+
},
|
|
34
94
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
+
};
|
|
38
144
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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;
|
|
44
163
|
}
|
|
45
|
-
return { content, processed: false, error: 'No content in response' };
|
|
46
164
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
+
/**
|
|
180
|
+
* Process multiple contents with LLM in parallel with rate limiting
|
|
181
|
+
* NEVER throws - always returns results array
|
|
182
|
+
*/
|
|
183
|
+
export async function processMultipleWithLLM(contents, config, processor, concurrency = 3) {
|
|
184
|
+
if (!config.use_llm || !processor || contents.length === 0) {
|
|
185
|
+
return contents.map(c => ({ content: c.content, processed: false, url: c.url }));
|
|
186
|
+
}
|
|
187
|
+
const results = [];
|
|
188
|
+
// Process in batches to avoid overwhelming the API
|
|
189
|
+
for (let i = 0; i < contents.length; i += concurrency) {
|
|
190
|
+
const batch = contents.slice(i, i + concurrency);
|
|
191
|
+
const batchResults = await Promise.all(batch.map(async ({ content, url }) => {
|
|
192
|
+
const result = await processContentWithLLM(content, config, processor);
|
|
193
|
+
return { ...result, url };
|
|
194
|
+
}));
|
|
195
|
+
results.push(...batchResults);
|
|
196
|
+
// Small delay between batches if more batches to process
|
|
197
|
+
if (i + concurrency < contents.length) {
|
|
198
|
+
await sleep(500);
|
|
199
|
+
}
|
|
51
200
|
}
|
|
201
|
+
return results;
|
|
52
202
|
}
|
|
53
203
|
//# sourceMappingURL=llm-processor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-processor.js","sourceRoot":"","sources":["../../src/services/llm-processor.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"llm-processor.js","sourceRoot":"","sources":["../../src/services/llm-processor.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/research.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Deep Research Tool Handler - Batch processing with dynamic token allocation
|
|
3
|
+
* Implements robust error handling that NEVER crashes
|
|
3
4
|
*/
|
|
4
5
|
import type { DeepResearchParams } from '../schemas/deep-research.js';
|
|
5
6
|
interface ResearchOptions {
|
|
6
7
|
sessionId?: string;
|
|
7
8
|
logger?: (level: 'info' | 'error' | 'debug', message: string, sessionId: string) => Promise<void>;
|
|
8
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Handle deep research request
|
|
12
|
+
* NEVER throws - always returns a valid response
|
|
13
|
+
*/
|
|
9
14
|
export declare function handleDeepResearch(params: DeepResearchParams, options?: ResearchOptions): Promise<{
|
|
10
15
|
content: string;
|
|
11
16
|
structuredContent: object;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../src/tools/research.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../src/tools/research.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAWtE,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnG;AAiDD;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CAoIzD"}
|
package/dist/tools/research.js
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Deep Research Tool Handler - Batch processing with dynamic token allocation
|
|
3
|
+
* Implements robust error handling that NEVER crashes
|
|
3
4
|
*/
|
|
4
5
|
import { ResearchClient } from '../clients/research.js';
|
|
5
6
|
import { FileAttachmentService } from '../services/file-attachment.js';
|
|
6
7
|
import { RESEARCH } from '../config/index.js';
|
|
7
|
-
import {
|
|
8
|
+
import { classifyError } from '../utils/errors.js';
|
|
8
9
|
// Constants
|
|
9
10
|
const TOTAL_TOKEN_BUDGET = 32000;
|
|
10
|
-
const MIN_QUESTIONS =
|
|
11
|
+
const MIN_QUESTIONS = 1; // Allow single question for flexibility
|
|
11
12
|
const MAX_QUESTIONS = 10;
|
|
12
13
|
function calculateTokenAllocation(questionCount) {
|
|
14
|
+
if (questionCount <= 0)
|
|
15
|
+
return TOTAL_TOKEN_BUDGET;
|
|
13
16
|
return Math.floor(TOTAL_TOKEN_BUDGET / questionCount);
|
|
14
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Safe logger wrapper - NEVER throws
|
|
20
|
+
*/
|
|
21
|
+
async function safeLog(logger, sessionId, level, message) {
|
|
22
|
+
if (!logger || !sessionId)
|
|
23
|
+
return;
|
|
24
|
+
try {
|
|
25
|
+
await logger(level, message, sessionId);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
console.error(`[Research Tool] Logger failed: ${message}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
15
31
|
const SYSTEM_PROMPT = `You are an expert research consultant. Provide evidence-based, multi-perspective analysis.
|
|
16
32
|
|
|
17
33
|
METHODOLOGY:
|
|
@@ -28,14 +44,18 @@ FORMAT (high info density):
|
|
|
28
44
|
- WHAT'S CHANGING: Recent developments
|
|
29
45
|
|
|
30
46
|
Be dense with insights, light on filler. Use examples and citations.`;
|
|
47
|
+
/**
|
|
48
|
+
* Handle deep research request
|
|
49
|
+
* NEVER throws - always returns a valid response
|
|
50
|
+
*/
|
|
31
51
|
export async function handleDeepResearch(params, options = {}) {
|
|
32
52
|
const { sessionId, logger } = options;
|
|
33
|
-
const questions = params.questions;
|
|
53
|
+
const questions = params.questions || [];
|
|
34
54
|
// Validation
|
|
35
55
|
if (questions.length < MIN_QUESTIONS) {
|
|
36
56
|
return {
|
|
37
|
-
content: `# ❌ Error\n\nMinimum ${MIN_QUESTIONS} research
|
|
38
|
-
structuredContent: { error: true, message: `Minimum ${MIN_QUESTIONS}
|
|
57
|
+
content: `# ❌ Error\n\nMinimum ${MIN_QUESTIONS} research question(s) required. Received: ${questions.length}`,
|
|
58
|
+
structuredContent: { error: true, message: `Minimum ${MIN_QUESTIONS} question(s) required` },
|
|
39
59
|
};
|
|
40
60
|
}
|
|
41
61
|
if (questions.length > MAX_QUESTIONS) {
|
|
@@ -45,21 +65,37 @@ export async function handleDeepResearch(params, options = {}) {
|
|
|
45
65
|
};
|
|
46
66
|
}
|
|
47
67
|
const tokensPerQuestion = calculateTokenAllocation(questions.length);
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
await safeLog(logger, sessionId, 'info', `Starting batch research: ${questions.length} questions, ${tokensPerQuestion.toLocaleString()} tokens/question`);
|
|
69
|
+
// Initialize client safely
|
|
70
|
+
let client;
|
|
71
|
+
try {
|
|
72
|
+
client = new ResearchClient();
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const err = classifyError(error);
|
|
76
|
+
return {
|
|
77
|
+
content: `# ❌ Error\n\nFailed to initialize research client: ${err.message}`,
|
|
78
|
+
structuredContent: { error: true, message: `Failed to initialize: ${err.message}` },
|
|
79
|
+
};
|
|
50
80
|
}
|
|
51
|
-
const client = new ResearchClient();
|
|
52
81
|
const fileService = new FileAttachmentService();
|
|
53
82
|
const results = [];
|
|
54
|
-
// Process all questions in parallel
|
|
83
|
+
// Process all questions in parallel - each handler NEVER throws
|
|
55
84
|
const researchPromises = questions.map(async (q, index) => {
|
|
56
85
|
try {
|
|
57
86
|
// Enhance question with file attachments if present
|
|
58
87
|
let enhancedQuestion = q.question;
|
|
59
88
|
if (q.file_attachments && q.file_attachments.length > 0) {
|
|
60
|
-
|
|
61
|
-
|
|
89
|
+
try {
|
|
90
|
+
const attachmentsMarkdown = await fileService.formatAttachments(q.file_attachments);
|
|
91
|
+
enhancedQuestion = q.question + attachmentsMarkdown;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// If attachment processing fails, continue with original question
|
|
95
|
+
console.error(`[Research] Failed to process attachments for question ${index + 1}`);
|
|
96
|
+
}
|
|
62
97
|
}
|
|
98
|
+
// ResearchClient.research() now returns error in response instead of throwing
|
|
63
99
|
const response = await client.research({
|
|
64
100
|
question: enhancedQuestion,
|
|
65
101
|
systemPrompt: SYSTEM_PROMPT,
|
|
@@ -67,20 +103,31 @@ export async function handleDeepResearch(params, options = {}) {
|
|
|
67
103
|
maxSearchResults: Math.min(RESEARCH.MAX_URLS, 20),
|
|
68
104
|
maxTokens: tokensPerQuestion,
|
|
69
105
|
});
|
|
106
|
+
// Check if response contains an error
|
|
107
|
+
if (response.error) {
|
|
108
|
+
return {
|
|
109
|
+
question: q.question,
|
|
110
|
+
content: response.content || '',
|
|
111
|
+
success: false,
|
|
112
|
+
error: response.error.message,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
70
115
|
return {
|
|
71
116
|
question: q.question,
|
|
72
|
-
content: response.content,
|
|
73
|
-
success:
|
|
117
|
+
content: response.content || '',
|
|
118
|
+
success: !!response.content,
|
|
74
119
|
tokensUsed: response.usage?.totalTokens,
|
|
120
|
+
error: response.content ? undefined : 'Empty response received',
|
|
75
121
|
};
|
|
76
122
|
}
|
|
77
123
|
catch (error) {
|
|
78
|
-
|
|
124
|
+
// This catch is a safety net - ResearchClient should not throw
|
|
125
|
+
const structuredError = classifyError(error);
|
|
79
126
|
return {
|
|
80
127
|
question: q.question,
|
|
81
128
|
content: '',
|
|
82
129
|
success: false,
|
|
83
|
-
error:
|
|
130
|
+
error: structuredError.message,
|
|
84
131
|
};
|
|
85
132
|
}
|
|
86
133
|
});
|
|
@@ -108,9 +155,7 @@ export async function handleDeepResearch(params, options = {}) {
|
|
|
108
155
|
}
|
|
109
156
|
markdown += `---\n\n`;
|
|
110
157
|
}
|
|
111
|
-
|
|
112
|
-
await logger('info', `Research completed: ${successful.length}/${questions.length} successful, ${totalTokens.toLocaleString()} tokens`, sessionId);
|
|
113
|
-
}
|
|
158
|
+
await safeLog(logger, sessionId, 'info', `Research completed: ${successful.length}/${questions.length} successful, ${totalTokens.toLocaleString()} tokens`);
|
|
114
159
|
return {
|
|
115
160
|
content: markdown.trim(),
|
|
116
161
|
structuredContent: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"research.js","sourceRoot":"","sources":["../../src/tools/research.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"research.js","sourceRoot":"","sources":["../../src/tools/research.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/scrape.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Scrape Links Tool Handler
|
|
3
|
+
* Implements robust error handling that NEVER crashes the MCP server
|
|
3
4
|
*/
|
|
4
5
|
import type { ScrapeLinksParams, ScrapeLinksOutput } from '../schemas/scrape-links.js';
|
|
5
6
|
interface ToolOptions {
|
|
6
7
|
sessionId?: string;
|
|
7
8
|
logger?: (level: 'info' | 'error' | 'debug', message: string, sessionId: string) => Promise<void>;
|
|
8
9
|
}
|
|
10
|
+
/**
|
|
11
|
+
* Handle scrape links request
|
|
12
|
+
* NEVER throws - always returns a valid response with content and metadata
|
|
13
|
+
*/
|
|
9
14
|
export declare function handleScrapeLinks(params: ScrapeLinksParams, options?: ToolOptions): Promise<{
|
|
10
15
|
content: string;
|
|
11
16
|
structuredContent: ScrapeLinksOutput;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrape.d.ts","sourceRoot":"","sources":["../../src/tools/scrape.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"scrape.d.ts","sourceRoot":"","sources":["../../src/tools/scrape.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAQvF,UAAU,WAAW;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnG;AA8BD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,iBAAiB,EACzB,OAAO,GAAE,WAAgB,GACxB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,iBAAiB,CAAA;CAAE,CAAC,CAoKpE"}
|