@hailer/mcp 0.0.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/.claude/commands/tool-builder.md +37 -0
- package/.claude/commands/ws-pull.md +44 -0
- package/.claude/settings.json +8 -0
- package/.claude/settings.local.json +49 -0
- package/.claude/skills/activity-api/SKILL.md +96 -0
- package/.claude/skills/activity-api/references/activity-endpoints.md +845 -0
- package/.claude/skills/add-app-member-skill/SKILL.md +977 -0
- package/.claude/skills/agent-building/SKILL.md +243 -0
- package/.claude/skills/agent-building/references/architecture-patterns.md +446 -0
- package/.claude/skills/agent-building/references/code-examples.md +587 -0
- package/.claude/skills/agent-building/references/implementation-guide.md +619 -0
- package/.claude/skills/app-api/SKILL.md +219 -0
- package/.claude/skills/app-api/references/app-endpoints.md +759 -0
- package/.claude/skills/building-hailer-apps-skill/SKILL.md +548 -0
- package/.claude/skills/create-app-skill/SKILL.md +1101 -0
- package/.claude/skills/create-insight-skill/SKILL.md +1317 -0
- package/.claude/skills/get-insight-data-skill/SKILL.md +1053 -0
- package/.claude/skills/hailer-api/SKILL.md +283 -0
- package/.claude/skills/hailer-api/references/activities.md +620 -0
- package/.claude/skills/hailer-api/references/authentication.md +216 -0
- package/.claude/skills/hailer-api/references/datasets.md +437 -0
- package/.claude/skills/hailer-api/references/files.md +301 -0
- package/.claude/skills/hailer-api/references/insights.md +469 -0
- package/.claude/skills/hailer-api/references/workflows.md +720 -0
- package/.claude/skills/hailer-api/references/workspaces-users.md +445 -0
- package/.claude/skills/insight-api/SKILL.md +185 -0
- package/.claude/skills/insight-api/references/insight-endpoints.md +514 -0
- package/.claude/skills/install-workflow-skill/SKILL.md +1056 -0
- package/.claude/skills/list-apps-skill/SKILL.md +1010 -0
- package/.claude/skills/list-workflows-minimal-skill/SKILL.md +992 -0
- package/.claude/skills/local-first-skill/SKILL.md +570 -0
- package/.claude/skills/mcp-tools/SKILL.md +419 -0
- package/.claude/skills/mcp-tools/references/api-endpoints.md +499 -0
- package/.claude/skills/mcp-tools/references/data-structures.md +554 -0
- package/.claude/skills/mcp-tools/references/implementation-patterns.md +717 -0
- package/.claude/skills/preview-insight-skill/SKILL.md +1290 -0
- package/.claude/skills/publish-hailer-app-skill/SKILL.md +453 -0
- package/.claude/skills/remove-app-member-skill/SKILL.md +671 -0
- package/.claude/skills/remove-app-skill/SKILL.md +985 -0
- package/.claude/skills/remove-insight-skill/SKILL.md +1011 -0
- package/.claude/skills/remove-workflow-skill/SKILL.md +920 -0
- package/.claude/skills/scaffold-hailer-app-skill/SKILL.md +1034 -0
- package/.claude/skills/skill-testing/README.md +137 -0
- package/.claude/skills/skill-testing/SKILL.md +348 -0
- package/.claude/skills/skill-testing/references/test-patterns.md +705 -0
- package/.claude/skills/skill-testing/references/testing-guide.md +603 -0
- package/.claude/skills/skill-testing/references/validation-checklist.md +537 -0
- package/.claude/skills/tool-builder/SKILL.md +328 -0
- package/.claude/skills/update-app-skill/SKILL.md +970 -0
- package/.claude/skills/update-workflow-field-skill/SKILL.md +1098 -0
- package/.env.example +81 -0
- package/.mcp.json +13 -0
- package/README.md +297 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.js +74 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +5 -0
- package/dist/client/adaptive-documentation-bot.d.ts +108 -0
- package/dist/client/adaptive-documentation-bot.js +475 -0
- package/dist/client/adaptive-documentation-types.d.ts +66 -0
- package/dist/client/adaptive-documentation-types.js +9 -0
- package/dist/client/agent-activity-bot.d.ts +51 -0
- package/dist/client/agent-activity-bot.js +166 -0
- package/dist/client/agent-tracker.d.ts +499 -0
- package/dist/client/agent-tracker.js +659 -0
- package/dist/client/description-updater.d.ts +56 -0
- package/dist/client/description-updater.js +259 -0
- package/dist/client/log-parser.d.ts +72 -0
- package/dist/client/log-parser.js +387 -0
- package/dist/client/mcp-client.d.ts +50 -0
- package/dist/client/mcp-client.js +532 -0
- package/dist/client/message-processor.d.ts +35 -0
- package/dist/client/message-processor.js +352 -0
- package/dist/client/multi-bot-manager.d.ts +24 -0
- package/dist/client/multi-bot-manager.js +74 -0
- package/dist/client/providers/anthropic-provider.d.ts +19 -0
- package/dist/client/providers/anthropic-provider.js +631 -0
- package/dist/client/providers/llm-provider.d.ts +47 -0
- package/dist/client/providers/llm-provider.js +367 -0
- package/dist/client/providers/openai-provider.d.ts +23 -0
- package/dist/client/providers/openai-provider.js +621 -0
- package/dist/client/simple-llm-caller.d.ts +19 -0
- package/dist/client/simple-llm-caller.js +100 -0
- package/dist/client/skill-generator.d.ts +81 -0
- package/dist/client/skill-generator.js +386 -0
- package/dist/client/test-adaptive-bot.d.ts +9 -0
- package/dist/client/test-adaptive-bot.js +82 -0
- package/dist/client/token-pricing.d.ts +38 -0
- package/dist/client/token-pricing.js +127 -0
- package/dist/client/token-tracker.d.ts +232 -0
- package/dist/client/token-tracker.js +457 -0
- package/dist/client/token-usage-bot.d.ts +53 -0
- package/dist/client/token-usage-bot.js +153 -0
- package/dist/client/tool-executor.d.ts +69 -0
- package/dist/client/tool-executor.js +159 -0
- package/dist/client/tool-schema-loader.d.ts +60 -0
- package/dist/client/tool-schema-loader.js +178 -0
- package/dist/client/types.d.ts +69 -0
- package/dist/client/types.js +7 -0
- package/dist/config.d.ts +162 -0
- package/dist/config.js +296 -0
- package/dist/core.d.ts +26 -0
- package/dist/core.js +147 -0
- package/dist/lib/context-manager.d.ts +111 -0
- package/dist/lib/context-manager.js +431 -0
- package/dist/lib/logger.d.ts +74 -0
- package/dist/lib/logger.js +277 -0
- package/dist/lib/materialize.d.ts +3 -0
- package/dist/lib/materialize.js +101 -0
- package/dist/lib/normalizedName.d.ts +7 -0
- package/dist/lib/normalizedName.js +48 -0
- package/dist/lib/prompt-length-manager.d.ts +81 -0
- package/dist/lib/prompt-length-manager.js +457 -0
- package/dist/lib/terminal-prompt.d.ts +9 -0
- package/dist/lib/terminal-prompt.js +108 -0
- package/dist/mcp/UserContextCache.d.ts +56 -0
- package/dist/mcp/UserContextCache.js +163 -0
- package/dist/mcp/auth.d.ts +2 -0
- package/dist/mcp/auth.js +29 -0
- package/dist/mcp/hailer-clients.d.ts +42 -0
- package/dist/mcp/hailer-clients.js +246 -0
- package/dist/mcp/signal-handler.d.ts +45 -0
- package/dist/mcp/signal-handler.js +317 -0
- package/dist/mcp/tool-registry.d.ts +100 -0
- package/dist/mcp/tool-registry.js +306 -0
- package/dist/mcp/tools/activity.d.ts +15 -0
- package/dist/mcp/tools/activity.js +955 -0
- package/dist/mcp/tools/app.d.ts +20 -0
- package/dist/mcp/tools/app.js +1488 -0
- package/dist/mcp/tools/discussion.d.ts +19 -0
- package/dist/mcp/tools/discussion.js +950 -0
- package/dist/mcp/tools/file.d.ts +15 -0
- package/dist/mcp/tools/file.js +119 -0
- package/dist/mcp/tools/insight.d.ts +17 -0
- package/dist/mcp/tools/insight.js +806 -0
- package/dist/mcp/tools/skill.d.ts +10 -0
- package/dist/mcp/tools/skill.js +279 -0
- package/dist/mcp/tools/user.d.ts +10 -0
- package/dist/mcp/tools/user.js +108 -0
- package/dist/mcp/tools/workflow-template.d.ts +19 -0
- package/dist/mcp/tools/workflow-template.js +822 -0
- package/dist/mcp/tools/workflow.d.ts +18 -0
- package/dist/mcp/tools/workflow.js +1362 -0
- package/dist/mcp/utils/api-errors.d.ts +45 -0
- package/dist/mcp/utils/api-errors.js +160 -0
- package/dist/mcp/utils/data-transformers.d.ts +102 -0
- package/dist/mcp/utils/data-transformers.js +194 -0
- package/dist/mcp/utils/file-upload.d.ts +33 -0
- package/dist/mcp/utils/file-upload.js +148 -0
- package/dist/mcp/utils/hailer-api-client.d.ts +120 -0
- package/dist/mcp/utils/hailer-api-client.js +323 -0
- package/dist/mcp/utils/index.d.ts +13 -0
- package/dist/mcp/utils/index.js +39 -0
- package/dist/mcp/utils/logger.d.ts +42 -0
- package/dist/mcp/utils/logger.js +103 -0
- package/dist/mcp/utils/types.d.ts +286 -0
- package/dist/mcp/utils/types.js +7 -0
- package/dist/mcp/workspace-cache.d.ts +42 -0
- package/dist/mcp/workspace-cache.js +97 -0
- package/dist/mcp-server.d.ts +42 -0
- package/dist/mcp-server.js +280 -0
- package/package.json +56 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Log Parser for Adaptive Documentation Bot
|
|
4
|
+
*
|
|
5
|
+
* Parses MCP server logs to extract tool call errors and LLM mistakes.
|
|
6
|
+
* Monitors both file-based logs and live log streams.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.LogParser = void 0;
|
|
43
|
+
const logger_1 = require("../lib/logger");
|
|
44
|
+
const fs = __importStar(require("fs/promises"));
|
|
45
|
+
const path = __importStar(require("path"));
|
|
46
|
+
const logger = (0, logger_1.createLogger)({ component: 'LogParser' });
|
|
47
|
+
class LogParser {
|
|
48
|
+
logPath;
|
|
49
|
+
statePath;
|
|
50
|
+
lastReadPosition = 0;
|
|
51
|
+
lastProcessedTimestamp = null;
|
|
52
|
+
seenErrors = new Set();
|
|
53
|
+
constructor(logPath) {
|
|
54
|
+
this.logPath = logPath || path.join(process.cwd(), 'logs', 'mcp-unified.json');
|
|
55
|
+
this.statePath = path.join(process.cwd(), 'logs', '.adaptive-bot-state.json');
|
|
56
|
+
// Load state synchronously on initialization to survive server restarts
|
|
57
|
+
this.loadStateSync();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Parse recent logs for tool call errors
|
|
61
|
+
* Returns only new errors since last parse
|
|
62
|
+
*/
|
|
63
|
+
async parseToolCallErrors(retries = 3) {
|
|
64
|
+
for (let attempt = 0; attempt < retries; attempt++) {
|
|
65
|
+
try {
|
|
66
|
+
// Check if log file exists
|
|
67
|
+
const exists = await this.fileExists(this.logPath);
|
|
68
|
+
if (!exists) {
|
|
69
|
+
logger.debug('Log file does not exist yet', { logPath: this.logPath });
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
const content = await fs.readFile(this.logPath, 'utf-8');
|
|
73
|
+
// Parse the entire JSON file
|
|
74
|
+
let logData;
|
|
75
|
+
try {
|
|
76
|
+
logData = JSON.parse(content);
|
|
77
|
+
}
|
|
78
|
+
catch (parseError) {
|
|
79
|
+
// Log file might be mid-write, retry after a short delay
|
|
80
|
+
if (attempt < retries - 1) {
|
|
81
|
+
const delay = 100 * (attempt + 1); // 100ms, 200ms, 300ms
|
|
82
|
+
logger.debug('Failed to parse logs (file may be mid-write, retrying)', {
|
|
83
|
+
attempt: attempt + 1,
|
|
84
|
+
retries,
|
|
85
|
+
delayMs: delay,
|
|
86
|
+
error: parseError instanceof Error ? parseError.message : String(parseError)
|
|
87
|
+
});
|
|
88
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
89
|
+
continue; // Retry
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Final attempt failed
|
|
93
|
+
logger.warn('Failed to parse logs after all retries', {
|
|
94
|
+
attempts: retries,
|
|
95
|
+
error: parseError instanceof Error ? parseError.message : String(parseError)
|
|
96
|
+
});
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!logData.entries || !Array.isArray(logData.entries)) {
|
|
101
|
+
logger.warn('Invalid log file format', { logPath: this.logPath });
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
const errors = [];
|
|
105
|
+
// Detect log rotation: if log has fewer entries than lastReadPosition,
|
|
106
|
+
// or if we have a timestamp and the earliest entry is after it, log rotated
|
|
107
|
+
const totalEntries = logData.entries.length;
|
|
108
|
+
let startPosition = this.lastReadPosition;
|
|
109
|
+
if (totalEntries < this.lastReadPosition) {
|
|
110
|
+
logger.info('Log rotation detected (fewer entries than last position)', {
|
|
111
|
+
totalEntries,
|
|
112
|
+
lastReadPosition: this.lastReadPosition
|
|
113
|
+
});
|
|
114
|
+
startPosition = 0;
|
|
115
|
+
}
|
|
116
|
+
else if (this.lastProcessedTimestamp && totalEntries > 0) {
|
|
117
|
+
const firstEntryTimestamp = logData.entries[0]?.timestamp;
|
|
118
|
+
if (firstEntryTimestamp && firstEntryTimestamp > this.lastProcessedTimestamp) {
|
|
119
|
+
logger.info('Log rotation detected (earliest entry newer than last processed)', {
|
|
120
|
+
firstEntryTimestamp,
|
|
121
|
+
lastProcessedTimestamp: this.lastProcessedTimestamp
|
|
122
|
+
});
|
|
123
|
+
startPosition = 0;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Process only new entries since startPosition
|
|
127
|
+
const entriesToProcess = logData.entries.slice(startPosition);
|
|
128
|
+
this.lastReadPosition = totalEntries;
|
|
129
|
+
// Update lastProcessedTimestamp to the newest entry we'll process
|
|
130
|
+
if (entriesToProcess.length > 0) {
|
|
131
|
+
const lastEntry = entriesToProcess[entriesToProcess.length - 1];
|
|
132
|
+
if (lastEntry?.timestamp) {
|
|
133
|
+
this.lastProcessedTimestamp = lastEntry.timestamp;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const entry of entriesToProcess) {
|
|
137
|
+
const error = this.parseLogEntry(entry);
|
|
138
|
+
if (error && !this.isDuplicate(error)) {
|
|
139
|
+
errors.push(error);
|
|
140
|
+
this.seenErrors.add(this.getErrorSignature(error));
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Save state after processing to survive server restarts
|
|
144
|
+
if (entriesToProcess.length > 0) {
|
|
145
|
+
await this.saveState();
|
|
146
|
+
}
|
|
147
|
+
if (errors.length > 0) {
|
|
148
|
+
logger.info('Parsed tool call errors from logs', {
|
|
149
|
+
errorCount: errors.length,
|
|
150
|
+
uniqueTools: new Set(errors.map(e => e.toolName)).size
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return errors;
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
logger.error('Failed to parse logs', error);
|
|
157
|
+
return [];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Should never reach here
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Parse a single log entry for error patterns
|
|
165
|
+
*/
|
|
166
|
+
parseLogEntry(logEntry) {
|
|
167
|
+
try {
|
|
168
|
+
if (!logEntry || !logEntry.message) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
// Pattern 1: Tool validation failed (from GlobalToolRegistry)
|
|
172
|
+
if (logEntry.message === 'Tool validation failed' && logEntry.context) {
|
|
173
|
+
return {
|
|
174
|
+
timestamp: new Date(logEntry.timestamp || Date.now()).getTime(),
|
|
175
|
+
toolName: logEntry.context.toolName,
|
|
176
|
+
errorMessage: logEntry.context.errors || 'Validation failed',
|
|
177
|
+
attemptedCall: JSON.parse(logEntry.context.receivedArgs || '{}'),
|
|
178
|
+
context: {
|
|
179
|
+
provider: logEntry.context.provider,
|
|
180
|
+
model: logEntry.context.model
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
// Pattern 2: Tool call failed
|
|
185
|
+
if (logEntry.message?.includes('Tool call failed') ||
|
|
186
|
+
logEntry.message?.includes('Failed to execute tool')) {
|
|
187
|
+
return this.extractToolCallError(logEntry);
|
|
188
|
+
}
|
|
189
|
+
// Pattern 3: General validation error
|
|
190
|
+
if (logEntry.message?.includes('validation') ||
|
|
191
|
+
logEntry.message?.includes('Invalid parameters')) {
|
|
192
|
+
return this.extractValidationError(logEntry);
|
|
193
|
+
}
|
|
194
|
+
// Pattern 4: Parameter missing/incorrect
|
|
195
|
+
if (logEntry.message?.includes('required') ||
|
|
196
|
+
logEntry.message?.includes('missing') ||
|
|
197
|
+
logEntry.message?.includes('must be provided')) {
|
|
198
|
+
return this.extractParameterError(logEntry);
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
// Not a parseable error entry
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Extract tool call error from JSON log entry
|
|
209
|
+
*/
|
|
210
|
+
extractToolCallError(logEntry) {
|
|
211
|
+
const toolName = logEntry.toolName ||
|
|
212
|
+
logEntry.tool ||
|
|
213
|
+
this.extractToolNameFromMessage(logEntry.message);
|
|
214
|
+
if (!toolName) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
timestamp: new Date(logEntry.timestamp || Date.now()).getTime(),
|
|
219
|
+
toolName,
|
|
220
|
+
errorMessage: logEntry.error || logEntry.message || 'Unknown error',
|
|
221
|
+
attemptedCall: logEntry.attemptedCall || logEntry.params || {},
|
|
222
|
+
actualParameters: logEntry.actualParameters,
|
|
223
|
+
context: {
|
|
224
|
+
conversationId: logEntry.conversationId || logEntry.discussionId,
|
|
225
|
+
userId: logEntry.userId,
|
|
226
|
+
provider: logEntry.provider,
|
|
227
|
+
model: logEntry.model
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Extract validation error
|
|
233
|
+
*/
|
|
234
|
+
extractValidationError(logEntry) {
|
|
235
|
+
const toolName = logEntry.toolName || this.extractToolNameFromMessage(logEntry.message);
|
|
236
|
+
if (!toolName) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
// Extract validation details if available
|
|
240
|
+
const validationDetails = logEntry.validationError || logEntry.details;
|
|
241
|
+
return {
|
|
242
|
+
timestamp: new Date(logEntry.timestamp || Date.now()).getTime(),
|
|
243
|
+
toolName,
|
|
244
|
+
errorMessage: `Validation error: ${logEntry.message}`,
|
|
245
|
+
attemptedCall: logEntry.params || validationDetails || {},
|
|
246
|
+
context: {
|
|
247
|
+
conversationId: logEntry.conversationId,
|
|
248
|
+
userId: logEntry.userId,
|
|
249
|
+
provider: logEntry.provider
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Extract parameter error
|
|
255
|
+
*/
|
|
256
|
+
extractParameterError(logEntry) {
|
|
257
|
+
const toolName = logEntry.toolName || this.extractToolNameFromMessage(logEntry.message);
|
|
258
|
+
if (!toolName) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
timestamp: new Date(logEntry.timestamp || Date.now()).getTime(),
|
|
263
|
+
toolName,
|
|
264
|
+
errorMessage: logEntry.message,
|
|
265
|
+
attemptedCall: logEntry.params || {},
|
|
266
|
+
context: {
|
|
267
|
+
conversationId: logEntry.conversationId,
|
|
268
|
+
userId: logEntry.userId
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Extract tool name from error message
|
|
274
|
+
*/
|
|
275
|
+
extractToolNameFromMessage(message) {
|
|
276
|
+
// Try to find tool name in common patterns
|
|
277
|
+
const patterns = [
|
|
278
|
+
/tool[:\s]+['"]?(\w+)['"]?/i,
|
|
279
|
+
/calling\s+['"]?(\w+)['"]?/i,
|
|
280
|
+
/execute\s+['"]?(\w+)['"]?/i,
|
|
281
|
+
/['"]?(\w+)['"]?\s+failed/i
|
|
282
|
+
];
|
|
283
|
+
for (const pattern of patterns) {
|
|
284
|
+
const match = message.match(pattern);
|
|
285
|
+
if (match) {
|
|
286
|
+
return match[1];
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Check if error is a duplicate
|
|
293
|
+
*/
|
|
294
|
+
isDuplicate(error) {
|
|
295
|
+
const signature = this.getErrorSignature(error);
|
|
296
|
+
return this.seenErrors.has(signature);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Generate unique signature for error deduplication
|
|
300
|
+
*/
|
|
301
|
+
getErrorSignature(error) {
|
|
302
|
+
return `${error.toolName}:${error.errorMessage}:${JSON.stringify(error.attemptedCall)}`;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Check if file exists
|
|
306
|
+
*/
|
|
307
|
+
async fileExists(filePath) {
|
|
308
|
+
try {
|
|
309
|
+
await fs.access(filePath);
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Reset parser state (useful for testing)
|
|
318
|
+
*/
|
|
319
|
+
reset() {
|
|
320
|
+
this.lastReadPosition = 0;
|
|
321
|
+
this.seenErrors.clear();
|
|
322
|
+
// Delete state file
|
|
323
|
+
try {
|
|
324
|
+
const fsSync = require('fs');
|
|
325
|
+
fsSync.unlinkSync(this.statePath);
|
|
326
|
+
logger.debug('Deleted parser state file');
|
|
327
|
+
}
|
|
328
|
+
catch (error) {
|
|
329
|
+
// File doesn't exist - that's fine
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get statistics about parsed errors
|
|
334
|
+
*/
|
|
335
|
+
getStats() {
|
|
336
|
+
return {
|
|
337
|
+
totalSeen: this.seenErrors.size,
|
|
338
|
+
uniqueErrors: this.seenErrors.size
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Load parser state from disk synchronously (called in constructor)
|
|
343
|
+
*/
|
|
344
|
+
loadStateSync() {
|
|
345
|
+
try {
|
|
346
|
+
const fsSync = require('fs');
|
|
347
|
+
const content = fsSync.readFileSync(this.statePath, 'utf-8');
|
|
348
|
+
const state = JSON.parse(content);
|
|
349
|
+
this.lastReadPosition = state.lastReadPosition || 0;
|
|
350
|
+
this.lastProcessedTimestamp = state.lastProcessedTimestamp || null;
|
|
351
|
+
this.seenErrors = new Set(state.seenErrors || []);
|
|
352
|
+
logger.info('Loaded parser state from previous session', {
|
|
353
|
+
lastReadPosition: this.lastReadPosition,
|
|
354
|
+
lastProcessedTimestamp: this.lastProcessedTimestamp,
|
|
355
|
+
seenErrorsCount: this.seenErrors.size
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
catch (error) {
|
|
359
|
+
// File doesn't exist or invalid - start fresh
|
|
360
|
+
logger.debug('No previous state found, starting fresh');
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Save parser state to disk
|
|
365
|
+
*/
|
|
366
|
+
async saveState() {
|
|
367
|
+
try {
|
|
368
|
+
const state = {
|
|
369
|
+
lastReadPosition: this.lastReadPosition,
|
|
370
|
+
lastProcessedTimestamp: this.lastProcessedTimestamp,
|
|
371
|
+
seenErrors: Array.from(this.seenErrors),
|
|
372
|
+
lastUpdated: new Date().toISOString()
|
|
373
|
+
};
|
|
374
|
+
await fs.writeFile(this.statePath, JSON.stringify(state, null, 2), 'utf-8');
|
|
375
|
+
logger.debug('Saved parser state', {
|
|
376
|
+
lastReadPosition: this.lastReadPosition,
|
|
377
|
+
lastProcessedTimestamp: this.lastProcessedTimestamp,
|
|
378
|
+
seenErrorsCount: this.seenErrors.size
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
catch (error) {
|
|
382
|
+
logger.error('Failed to save parser state', error);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
exports.LogParser = LogParser;
|
|
387
|
+
//# sourceMappingURL=log-parser.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main MCP Client
|
|
3
|
+
* Orchestrates signal handling, message processing, and LLM provider interaction
|
|
4
|
+
*/
|
|
5
|
+
import { AdaptiveDocumentationBot } from "./adaptive-documentation-bot";
|
|
6
|
+
import { McpClientConfig } from "./types";
|
|
7
|
+
export declare class McpClient {
|
|
8
|
+
private multiBotManager;
|
|
9
|
+
private messageProcessor;
|
|
10
|
+
private providers;
|
|
11
|
+
private config;
|
|
12
|
+
private isActive;
|
|
13
|
+
private processedMessages;
|
|
14
|
+
private activeSubscriptions;
|
|
15
|
+
private agentTracker;
|
|
16
|
+
private tokenTracker;
|
|
17
|
+
private tokenUsageBot;
|
|
18
|
+
private agentActivityBot;
|
|
19
|
+
private adaptiveDocBot?;
|
|
20
|
+
constructor(config: McpClientConfig);
|
|
21
|
+
initialize(): Promise<void>;
|
|
22
|
+
private initializeProviders;
|
|
23
|
+
start(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Get adaptive documentation bot instance (for error reporting)
|
|
26
|
+
*/
|
|
27
|
+
getAdaptiveBot(): AdaptiveDocumentationBot | undefined;
|
|
28
|
+
stop(): void;
|
|
29
|
+
private handleSignal;
|
|
30
|
+
private getFirstEnabledProvider;
|
|
31
|
+
private determineTriggerType;
|
|
32
|
+
private processMessage;
|
|
33
|
+
private handleResponse;
|
|
34
|
+
private postSuccessResponse;
|
|
35
|
+
private buildToolUsageSummary;
|
|
36
|
+
private postErrorResponse;
|
|
37
|
+
/** Shutdown the dependency: MultiBotManager */
|
|
38
|
+
shutdownMultiBotManager(): Promise<void>;
|
|
39
|
+
/** Shutdown the McpClient and MultiBotManager */
|
|
40
|
+
shutdown(): Promise<void>;
|
|
41
|
+
getStatus(): {
|
|
42
|
+
active: boolean;
|
|
43
|
+
providersCount: number;
|
|
44
|
+
enabledProviders: string[];
|
|
45
|
+
activeSubscriptions: number;
|
|
46
|
+
botClientsCount: number;
|
|
47
|
+
directMessagesEnabled: boolean;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=mcp-client.d.ts.map
|