@bryan-thompson/inspector-assessment-client 1.25.4 → 1.25.6
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/assets/{OAuthCallback-DE62cdTZ.js → OAuthCallback-D6y8tFfF.js} +1 -1
- package/dist/assets/{OAuthDebugCallback-CWjFdCIE.js → OAuthDebugCallback-DHegnqTa.js} +1 -1
- package/dist/assets/{index-PCQVSwHa.js → index-Cu02Ah3g.js} +4 -4
- package/dist/assets/{index-Df9Sx1jt.css → index-cHhcEXbr.css} +4 -0
- package/dist/index.html +2 -2
- package/lib/lib/assessment/coreTypes.d.ts +65 -0
- package/lib/lib/assessment/coreTypes.d.ts.map +1 -1
- package/lib/lib/assessment/extendedTypes.d.ts +127 -0
- package/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
- package/lib/lib/assessment/resultTypes.d.ts +45 -0
- package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
- package/lib/lib/moduleScoring.d.ts +2 -2
- package/lib/lib/moduleScoring.d.ts.map +1 -1
- package/lib/lib/moduleScoring.js +3 -2
- package/lib/services/assessment/AssessmentOrchestrator.d.ts +3 -7
- package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
- package/lib/services/assessment/AssessmentOrchestrator.js +13 -2
- package/lib/services/assessment/TestDataGenerator.d.ts +9 -1
- package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -1
- package/lib/services/assessment/TestDataGenerator.js +32 -6
- package/lib/services/assessment/TestScenarioEngine.d.ts +9 -1
- package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -1
- package/lib/services/assessment/TestScenarioEngine.js +17 -14
- package/lib/services/assessment/config/annotationPatterns.d.ts +3 -1
- package/lib/services/assessment/config/annotationPatterns.d.ts.map +1 -1
- package/lib/services/assessment/config/annotationPatterns.js +5 -2
- package/lib/services/assessment/config/architecturePatterns.d.ts +101 -0
- package/lib/services/assessment/config/architecturePatterns.d.ts.map +1 -0
- package/lib/services/assessment/config/architecturePatterns.js +248 -0
- package/lib/services/assessment/config/performanceConfig.d.ts +122 -0
- package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -0
- package/lib/services/assessment/config/performanceConfig.js +154 -0
- package/lib/services/assessment/config/sanitizationPatterns.d.ts +63 -0
- package/lib/services/assessment/config/sanitizationPatterns.d.ts.map +1 -0
- package/lib/services/assessment/config/sanitizationPatterns.js +223 -0
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts +40 -3
- package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -1
- package/lib/services/assessment/lib/claudeCodeBridge.js +149 -8
- package/lib/services/assessment/lib/concurrencyLimit.d.ts +6 -2
- package/lib/services/assessment/lib/concurrencyLimit.d.ts.map +1 -1
- package/lib/services/assessment/lib/concurrencyLimit.js +13 -6
- package/lib/services/assessment/lib/errors.d.ts +90 -0
- package/lib/services/assessment/lib/errors.d.ts.map +1 -0
- package/lib/services/assessment/lib/errors.js +136 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts +69 -0
- package/lib/services/assessment/lib/timeoutUtils.d.ts.map +1 -0
- package/lib/services/assessment/lib/timeoutUtils.js +103 -0
- package/lib/services/assessment/modules/BaseAssessor.d.ts +43 -8
- package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/BaseAssessor.js +103 -34
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts +38 -1
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +185 -19
- package/lib/services/assessment/modules/DocumentationAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/DocumentationAssessor.js +11 -0
- package/lib/services/assessment/modules/ErrorHandlingAssessor.js +1 -1
- package/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/FunctionalityAssessor.js +6 -3
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +3 -0
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +14 -2
- package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ManifestValidationAssessor.js +7 -2
- package/lib/services/assessment/modules/PromptAssessor.d.ts +1 -0
- package/lib/services/assessment/modules/PromptAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/PromptAssessor.js +26 -16
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +6 -2
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +15 -0
- package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ResourceAssessor.js +8 -2
- package/lib/services/assessment/modules/SecurityAssessor.d.ts +3 -171
- package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/SecurityAssessor.js +25 -1480
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +27 -28
- package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/ToolAnnotationAssessor.js +340 -863
- package/lib/services/assessment/modules/UsabilityAssessor.d.ts +5 -0
- package/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -1
- package/lib/services/assessment/modules/UsabilityAssessor.js +11 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts +57 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.js +176 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts +67 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/ArchitectureDetector.js +239 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts +46 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/BehaviorInference.js +394 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts +64 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.js +304 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts +43 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +276 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts +122 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/SchemaAnalyzer.js +388 -0
- package/lib/services/assessment/modules/annotations/index.d.ts +13 -0
- package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -0
- package/lib/services/assessment/modules/annotations/index.js +15 -0
- package/lib/services/assessment/modules/index.d.ts +10 -0
- package/lib/services/assessment/modules/index.d.ts.map +1 -1
- package/lib/services/assessment/modules/index.js +13 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts +125 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SanitizationDetector.js +345 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts +33 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +128 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts +67 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +372 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +178 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +1207 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts +8 -0
- package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -0
- package/lib/services/assessment/modules/securityTests/index.js +7 -0
- package/lib/services/assessment/tool-classifier-patterns.d.ts +1 -0
- package/lib/services/assessment/tool-classifier-patterns.d.ts.map +1 -1
- package/lib/services/assessment/tool-classifier-patterns.js +17 -0
- package/package.json +1 -1
|
@@ -43,6 +43,27 @@ export const FULL_CLAUDE_CODE_CONFIG = {
|
|
|
43
43
|
documentationQuality: true,
|
|
44
44
|
},
|
|
45
45
|
};
|
|
46
|
+
/**
|
|
47
|
+
* HTTP transport configuration using mcp-auditor as Claude API proxy
|
|
48
|
+
* Requires mcp-auditor server running on the specified baseUrl
|
|
49
|
+
*/
|
|
50
|
+
export const HTTP_CLAUDE_CODE_CONFIG = {
|
|
51
|
+
enabled: true,
|
|
52
|
+
transport: "http",
|
|
53
|
+
httpConfig: {
|
|
54
|
+
baseUrl: "http://localhost:8085",
|
|
55
|
+
},
|
|
56
|
+
timeout: 30000,
|
|
57
|
+
maxRetries: 2,
|
|
58
|
+
features: {
|
|
59
|
+
intelligentTestGeneration: true,
|
|
60
|
+
aupSemanticAnalysis: true,
|
|
61
|
+
behaviorInference: true,
|
|
62
|
+
annotationInference: true,
|
|
63
|
+
documentationAssessment: true,
|
|
64
|
+
documentationQuality: true,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
46
67
|
/**
|
|
47
68
|
* Claude Code Bridge
|
|
48
69
|
* Executes Claude CLI for intelligent analysis during MCP assessments
|
|
@@ -50,11 +71,16 @@ export const FULL_CLAUDE_CODE_CONFIG = {
|
|
|
50
71
|
export class ClaudeCodeBridge {
|
|
51
72
|
config;
|
|
52
73
|
isAvailable = false;
|
|
53
|
-
|
|
74
|
+
logger;
|
|
75
|
+
constructor(config, logger) {
|
|
54
76
|
this.config = config;
|
|
55
|
-
this.
|
|
56
|
-
|
|
57
|
-
|
|
77
|
+
this.logger = logger;
|
|
78
|
+
this.isAvailable = this.checkAvailability();
|
|
79
|
+
if (!this.isAvailable && this.config.transport !== "http") {
|
|
80
|
+
this.logger?.warn("Claude CLI not available - features will be disabled");
|
|
81
|
+
}
|
|
82
|
+
if (this.config.transport === "http") {
|
|
83
|
+
this.logger?.info(`Claude Code Bridge using HTTP transport: ${this.config.httpConfig?.baseUrl || "not configured"}`);
|
|
58
84
|
}
|
|
59
85
|
}
|
|
60
86
|
/**
|
|
@@ -72,10 +98,35 @@ export class ClaudeCodeBridge {
|
|
|
72
98
|
}
|
|
73
99
|
return this.config.features[feature] === true;
|
|
74
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Get the current transport type
|
|
103
|
+
*/
|
|
104
|
+
getTransport() {
|
|
105
|
+
return this.config.transport || "cli";
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Check availability based on transport type
|
|
109
|
+
* For CLI: checks if claude binary exists
|
|
110
|
+
* For HTTP: assumes available (validated on first request)
|
|
111
|
+
*/
|
|
112
|
+
checkAvailability() {
|
|
113
|
+
// HTTP transport: assume available, will fail on first request if not
|
|
114
|
+
// This is because we can't do async checks in constructor
|
|
115
|
+
if (this.config.transport === "http") {
|
|
116
|
+
// Validate httpConfig is present
|
|
117
|
+
if (!this.config.httpConfig?.baseUrl) {
|
|
118
|
+
this.logger?.warn("HTTP transport configured but baseUrl is missing - features will be disabled");
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
// CLI transport: check if claude binary exists
|
|
124
|
+
return this.checkCliAvailability();
|
|
125
|
+
}
|
|
75
126
|
/**
|
|
76
127
|
* Check if Claude CLI is available on the system
|
|
77
128
|
*/
|
|
78
|
-
|
|
129
|
+
checkCliAvailability() {
|
|
79
130
|
try {
|
|
80
131
|
execSync("which claude", { stdio: "pipe", timeout: 5000 });
|
|
81
132
|
return true;
|
|
@@ -84,6 +135,28 @@ export class ClaudeCodeBridge {
|
|
|
84
135
|
return false;
|
|
85
136
|
}
|
|
86
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Check HTTP endpoint health (async version for runtime checks)
|
|
140
|
+
* Can be called to verify HTTP transport is working
|
|
141
|
+
*/
|
|
142
|
+
async checkHttpHealth() {
|
|
143
|
+
if (this.config.transport !== "http" || !this.config.httpConfig?.baseUrl) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
try {
|
|
147
|
+
const controller = new AbortController();
|
|
148
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
149
|
+
const response = await fetch(`${this.config.httpConfig.baseUrl}/api/health`, {
|
|
150
|
+
method: "GET",
|
|
151
|
+
signal: controller.signal,
|
|
152
|
+
});
|
|
153
|
+
clearTimeout(timeoutId);
|
|
154
|
+
return response.ok;
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
87
160
|
/**
|
|
88
161
|
* Execute Claude CLI with a prompt
|
|
89
162
|
* Uses execFileSync to avoid shell injection vulnerabilities
|
|
@@ -116,13 +189,81 @@ export class ClaudeCodeBridge {
|
|
|
116
189
|
}
|
|
117
190
|
}
|
|
118
191
|
/**
|
|
119
|
-
* Execute
|
|
192
|
+
* Execute via HTTP transport using mcp-auditor's Claude API proxy
|
|
193
|
+
* Requires mcp-auditor server with /api/claude/messages endpoint
|
|
194
|
+
*/
|
|
195
|
+
async executeHttpCommand(prompt) {
|
|
196
|
+
const startTime = Date.now();
|
|
197
|
+
if (!this.config.httpConfig) {
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
output: "",
|
|
201
|
+
error: "HTTP transport configured but httpConfig is missing",
|
|
202
|
+
executionTimeMs: Date.now() - startTime,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const { baseUrl, apiKey, headers } = this.config.httpConfig;
|
|
206
|
+
const timeout = this.config.timeout || 30000;
|
|
207
|
+
try {
|
|
208
|
+
const controller = new AbortController();
|
|
209
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
210
|
+
const response = await fetch(`${baseUrl}/api/claude/messages`, {
|
|
211
|
+
method: "POST",
|
|
212
|
+
headers: {
|
|
213
|
+
"Content-Type": "application/json",
|
|
214
|
+
...(apiKey && { Authorization: `Bearer ${apiKey}` }),
|
|
215
|
+
...headers,
|
|
216
|
+
},
|
|
217
|
+
body: JSON.stringify({
|
|
218
|
+
messages: [{ role: "user", content: prompt }],
|
|
219
|
+
maxTokens: 4096,
|
|
220
|
+
stream: false,
|
|
221
|
+
}),
|
|
222
|
+
signal: controller.signal,
|
|
223
|
+
});
|
|
224
|
+
clearTimeout(timeoutId);
|
|
225
|
+
if (!response.ok) {
|
|
226
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
227
|
+
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
228
|
+
}
|
|
229
|
+
const data = (await response.json());
|
|
230
|
+
// Handle various response formats from the API
|
|
231
|
+
const output = data.content ||
|
|
232
|
+
data.text ||
|
|
233
|
+
data.message?.content ||
|
|
234
|
+
JSON.stringify(data);
|
|
235
|
+
return {
|
|
236
|
+
success: true,
|
|
237
|
+
output: typeof output === "string" ? output.trim() : JSON.stringify(output),
|
|
238
|
+
executionTimeMs: Date.now() - startTime,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
const errorMessage = error instanceof Error
|
|
243
|
+
? error.name === "AbortError"
|
|
244
|
+
? `Request timeout after ${timeout}ms`
|
|
245
|
+
: error.message
|
|
246
|
+
: String(error);
|
|
247
|
+
return {
|
|
248
|
+
success: false,
|
|
249
|
+
output: "",
|
|
250
|
+
error: errorMessage,
|
|
251
|
+
executionTimeMs: Date.now() - startTime,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Execute with retries - supports both CLI and HTTP transports
|
|
120
257
|
*/
|
|
121
258
|
async executeWithRetry(prompt) {
|
|
122
259
|
const maxRetries = this.config.maxRetries || 1;
|
|
260
|
+
const isHttpTransport = this.config.transport === "http";
|
|
123
261
|
let lastError = null;
|
|
124
262
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
125
|
-
|
|
263
|
+
// Use appropriate transport
|
|
264
|
+
const response = isHttpTransport
|
|
265
|
+
? await this.executeHttpCommand(prompt)
|
|
266
|
+
: this.executeClaudeCommand(prompt);
|
|
126
267
|
if (response.success) {
|
|
127
268
|
return response;
|
|
128
269
|
}
|
|
@@ -151,7 +292,7 @@ export class ClaudeCodeBridge {
|
|
|
151
292
|
return JSON.parse(jsonStr);
|
|
152
293
|
}
|
|
153
294
|
catch {
|
|
154
|
-
|
|
295
|
+
this.logger?.warn("Failed to parse JSON response");
|
|
155
296
|
return null;
|
|
156
297
|
}
|
|
157
298
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Simple concurrency limiter for parallel async operations
|
|
3
3
|
* Provides the same interface as p-limit but is CJS-compatible
|
|
4
4
|
*/
|
|
5
|
+
import { Logger } from "./logger.js";
|
|
5
6
|
/**
|
|
6
7
|
* Warning threshold for queue depth monitoring.
|
|
7
8
|
* If queue exceeds this size, a warning is emitted to help diagnose
|
|
@@ -12,14 +13,17 @@
|
|
|
12
13
|
*
|
|
13
14
|
* Threshold of 10,000 provides ~146% headroom to accommodate larger
|
|
14
15
|
* tool sets while catching true runaway scenarios.
|
|
16
|
+
*
|
|
17
|
+
* @see PerformanceConfig.queueWarningThreshold (Issue #37)
|
|
15
18
|
*/
|
|
16
|
-
export declare const QUEUE_WARNING_THRESHOLD
|
|
19
|
+
export declare const QUEUE_WARNING_THRESHOLD: number;
|
|
17
20
|
export type LimitFunction = <T>(fn: () => Promise<T>) => Promise<T>;
|
|
18
21
|
/**
|
|
19
22
|
* Creates a concurrency limiter that allows only a specified number
|
|
20
23
|
* of async operations to run simultaneously
|
|
21
24
|
*
|
|
22
25
|
* @param concurrency - Maximum number of concurrent operations
|
|
26
|
+
* @param logger - Optional logger instance for queue depth warnings
|
|
23
27
|
* @returns A function that wraps async operations with the concurrency limit
|
|
24
28
|
*
|
|
25
29
|
* @example
|
|
@@ -28,5 +32,5 @@ export type LimitFunction = <T>(fn: () => Promise<T>) => Promise<T>;
|
|
|
28
32
|
* items.map(item => limit(() => processItem(item)))
|
|
29
33
|
* );
|
|
30
34
|
*/
|
|
31
|
-
export declare function createConcurrencyLimit(concurrency: number): LimitFunction;
|
|
35
|
+
export declare function createConcurrencyLimit(concurrency: number, logger?: Logger): LimitFunction;
|
|
32
36
|
//# sourceMappingURL=concurrencyLimit.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"concurrencyLimit.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/lib/concurrencyLimit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH
|
|
1
|
+
{"version":3,"file":"concurrencyLimit.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/lib/concurrencyLimit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,QACc,CAAC;AAEnD,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAEpE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,aAAa,CAwDf"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Simple concurrency limiter for parallel async operations
|
|
3
3
|
* Provides the same interface as p-limit but is CJS-compatible
|
|
4
4
|
*/
|
|
5
|
+
import { DEFAULT_PERFORMANCE_CONFIG } from "../config/performanceConfig.js";
|
|
5
6
|
/**
|
|
6
7
|
* Warning threshold for queue depth monitoring.
|
|
7
8
|
* If queue exceeds this size, a warning is emitted to help diagnose
|
|
@@ -12,13 +13,16 @@
|
|
|
12
13
|
*
|
|
13
14
|
* Threshold of 10,000 provides ~146% headroom to accommodate larger
|
|
14
15
|
* tool sets while catching true runaway scenarios.
|
|
16
|
+
*
|
|
17
|
+
* @see PerformanceConfig.queueWarningThreshold (Issue #37)
|
|
15
18
|
*/
|
|
16
|
-
export const QUEUE_WARNING_THRESHOLD =
|
|
19
|
+
export const QUEUE_WARNING_THRESHOLD = DEFAULT_PERFORMANCE_CONFIG.queueWarningThreshold;
|
|
17
20
|
/**
|
|
18
21
|
* Creates a concurrency limiter that allows only a specified number
|
|
19
22
|
* of async operations to run simultaneously
|
|
20
23
|
*
|
|
21
24
|
* @param concurrency - Maximum number of concurrent operations
|
|
25
|
+
* @param logger - Optional logger instance for queue depth warnings
|
|
22
26
|
* @returns A function that wraps async operations with the concurrency limit
|
|
23
27
|
*
|
|
24
28
|
* @example
|
|
@@ -27,7 +31,7 @@ export const QUEUE_WARNING_THRESHOLD = 10000;
|
|
|
27
31
|
* items.map(item => limit(() => processItem(item)))
|
|
28
32
|
* );
|
|
29
33
|
*/
|
|
30
|
-
export function createConcurrencyLimit(concurrency) {
|
|
34
|
+
export function createConcurrencyLimit(concurrency, logger) {
|
|
31
35
|
if (concurrency < 1) {
|
|
32
36
|
throw new Error("Concurrency must be at least 1");
|
|
33
37
|
}
|
|
@@ -62,10 +66,13 @@ export function createConcurrencyLimit(concurrency) {
|
|
|
62
66
|
// Only warn once per limiter instance to avoid log spam
|
|
63
67
|
if (queue.length > QUEUE_WARNING_THRESHOLD && !hasWarned) {
|
|
64
68
|
hasWarned = true;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
logger?.warn("Queue depth exceeded threshold", {
|
|
70
|
+
queueDepth: queue.length,
|
|
71
|
+
threshold: QUEUE_WARNING_THRESHOLD,
|
|
72
|
+
activeCount,
|
|
73
|
+
concurrency,
|
|
74
|
+
message: "This may indicate a slow/stalled server",
|
|
75
|
+
});
|
|
69
76
|
}
|
|
70
77
|
next();
|
|
71
78
|
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assessment Error Types
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized error handling across all assessment modules.
|
|
5
|
+
* See docs/ERROR_HANDLING_CONVENTIONS.md for usage guidelines.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Error categories for classification and debugging
|
|
9
|
+
*/
|
|
10
|
+
export declare enum ErrorCategory {
|
|
11
|
+
/** Network connectivity issues (ECONNREFUSED, DNS failures, etc.) */
|
|
12
|
+
CONNECTION = "CONNECTION",
|
|
13
|
+
/** MCP protocol violations or unexpected responses */
|
|
14
|
+
PROTOCOL = "PROTOCOL",
|
|
15
|
+
/** Input validation failures (invalid parameters, missing fields) */
|
|
16
|
+
VALIDATION = "VALIDATION",
|
|
17
|
+
/** Operation exceeded time limit */
|
|
18
|
+
TIMEOUT = "TIMEOUT",
|
|
19
|
+
/** JSON or data parsing failures */
|
|
20
|
+
PARSE = "PARSE",
|
|
21
|
+
/** Unclassified errors */
|
|
22
|
+
UNKNOWN = "UNKNOWN"
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Custom error class for assessment operations
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* throw new AssessmentError(
|
|
29
|
+
* 'Failed to connect to MCP server',
|
|
30
|
+
* ErrorCategory.CONNECTION,
|
|
31
|
+
* false, // not recoverable
|
|
32
|
+
* { url: 'http://localhost:3000', attempt: 3 }
|
|
33
|
+
* );
|
|
34
|
+
*/
|
|
35
|
+
export declare class AssessmentError extends Error {
|
|
36
|
+
readonly code: ErrorCategory;
|
|
37
|
+
readonly recoverable: boolean;
|
|
38
|
+
readonly context?: Record<string, unknown>;
|
|
39
|
+
constructor(message: string, code: ErrorCategory, recoverable?: boolean, context?: Record<string, unknown>);
|
|
40
|
+
/**
|
|
41
|
+
* Create a structured object for serialization
|
|
42
|
+
*/
|
|
43
|
+
toJSON(): ErrorInfo;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Structured error information for result objects
|
|
47
|
+
*/
|
|
48
|
+
export interface ErrorInfo {
|
|
49
|
+
/** Human-readable error message */
|
|
50
|
+
message: string;
|
|
51
|
+
/** Error category for classification */
|
|
52
|
+
code: ErrorCategory;
|
|
53
|
+
/** Whether the operation can be retried */
|
|
54
|
+
recoverable: boolean;
|
|
55
|
+
/** Stack trace (optional, for debugging) */
|
|
56
|
+
stack?: string;
|
|
57
|
+
/** Additional context about the error */
|
|
58
|
+
context?: Record<string, unknown>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Interface for result objects that may contain errors
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* interface ToolTestResult extends ErrorResult {
|
|
65
|
+
* toolName: string;
|
|
66
|
+
* passed: boolean;
|
|
67
|
+
* }
|
|
68
|
+
*/
|
|
69
|
+
export interface ErrorResult {
|
|
70
|
+
error?: ErrorInfo;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Type guard to check if a value is an AssessmentError
|
|
74
|
+
*/
|
|
75
|
+
export declare function isAssessmentError(error: unknown): error is AssessmentError;
|
|
76
|
+
/**
|
|
77
|
+
* Categorize an error based on its message content
|
|
78
|
+
*
|
|
79
|
+
* @param error - The error to categorize
|
|
80
|
+
* @returns The appropriate ErrorCategory
|
|
81
|
+
*/
|
|
82
|
+
export declare function categorizeError(error: unknown): ErrorCategory;
|
|
83
|
+
/**
|
|
84
|
+
* Extract error message from various error types
|
|
85
|
+
*
|
|
86
|
+
* @param error - The error to extract message from
|
|
87
|
+
* @returns A string error message
|
|
88
|
+
*/
|
|
89
|
+
export declare function extractErrorMessage(error: unknown): string;
|
|
90
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/lib/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,oBAAY,aAAa;IACvB,qEAAqE;IACrE,UAAU,eAAe;IACzB,sDAAsD;IACtD,QAAQ,aAAa;IACrB,qEAAqE;IACrE,UAAU,eAAe;IACzB,oCAAoC;IACpC,OAAO,YAAY;IACnB,oCAAoC;IACpC,KAAK,UAAU;IACf,0BAA0B;IAC1B,OAAO,YAAY;CACpB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,eAAgB,SAAQ,KAAK;aAGtB,IAAI,EAAE,aAAa;aACnB,WAAW,EAAE,OAAO;aACpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAHjD,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,aAAa,EACnB,WAAW,GAAE,OAAc,EAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAUnD;;OAEG;IACH,MAAM,IAAI,SAAS;CASpB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,mCAAmC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,IAAI,EAAE,aAAa,CAAC;IACpB,2CAA2C;IAC3C,WAAW,EAAE,OAAO,CAAC;IACrB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAsC7D;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwB1D"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assessment Error Types
|
|
3
|
+
*
|
|
4
|
+
* Provides standardized error handling across all assessment modules.
|
|
5
|
+
* See docs/ERROR_HANDLING_CONVENTIONS.md for usage guidelines.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Error categories for classification and debugging
|
|
9
|
+
*/
|
|
10
|
+
export var ErrorCategory;
|
|
11
|
+
(function (ErrorCategory) {
|
|
12
|
+
/** Network connectivity issues (ECONNREFUSED, DNS failures, etc.) */
|
|
13
|
+
ErrorCategory["CONNECTION"] = "CONNECTION";
|
|
14
|
+
/** MCP protocol violations or unexpected responses */
|
|
15
|
+
ErrorCategory["PROTOCOL"] = "PROTOCOL";
|
|
16
|
+
/** Input validation failures (invalid parameters, missing fields) */
|
|
17
|
+
ErrorCategory["VALIDATION"] = "VALIDATION";
|
|
18
|
+
/** Operation exceeded time limit */
|
|
19
|
+
ErrorCategory["TIMEOUT"] = "TIMEOUT";
|
|
20
|
+
/** JSON or data parsing failures */
|
|
21
|
+
ErrorCategory["PARSE"] = "PARSE";
|
|
22
|
+
/** Unclassified errors */
|
|
23
|
+
ErrorCategory["UNKNOWN"] = "UNKNOWN";
|
|
24
|
+
})(ErrorCategory || (ErrorCategory = {}));
|
|
25
|
+
/**
|
|
26
|
+
* Custom error class for assessment operations
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* throw new AssessmentError(
|
|
30
|
+
* 'Failed to connect to MCP server',
|
|
31
|
+
* ErrorCategory.CONNECTION,
|
|
32
|
+
* false, // not recoverable
|
|
33
|
+
* { url: 'http://localhost:3000', attempt: 3 }
|
|
34
|
+
* );
|
|
35
|
+
*/
|
|
36
|
+
export class AssessmentError extends Error {
|
|
37
|
+
code;
|
|
38
|
+
recoverable;
|
|
39
|
+
context;
|
|
40
|
+
constructor(message, code, recoverable = true, context) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.code = code;
|
|
43
|
+
this.recoverable = recoverable;
|
|
44
|
+
this.context = context;
|
|
45
|
+
this.name = "AssessmentError";
|
|
46
|
+
// Maintains proper stack trace in V8 environments
|
|
47
|
+
if (Error.captureStackTrace) {
|
|
48
|
+
Error.captureStackTrace(this, AssessmentError);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a structured object for serialization
|
|
53
|
+
*/
|
|
54
|
+
toJSON() {
|
|
55
|
+
return {
|
|
56
|
+
message: this.message,
|
|
57
|
+
code: this.code,
|
|
58
|
+
recoverable: this.recoverable,
|
|
59
|
+
stack: this.stack,
|
|
60
|
+
context: this.context,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Type guard to check if a value is an AssessmentError
|
|
66
|
+
*/
|
|
67
|
+
export function isAssessmentError(error) {
|
|
68
|
+
return error instanceof AssessmentError;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Categorize an error based on its message content
|
|
72
|
+
*
|
|
73
|
+
* @param error - The error to categorize
|
|
74
|
+
* @returns The appropriate ErrorCategory
|
|
75
|
+
*/
|
|
76
|
+
export function categorizeError(error) {
|
|
77
|
+
const message = extractErrorMessage(error).toLowerCase();
|
|
78
|
+
if (message.includes("timeout") || message.includes("timed out")) {
|
|
79
|
+
return ErrorCategory.TIMEOUT;
|
|
80
|
+
}
|
|
81
|
+
if (message.includes("connection") ||
|
|
82
|
+
message.includes("econnrefused") ||
|
|
83
|
+
message.includes("enotfound") ||
|
|
84
|
+
message.includes("network")) {
|
|
85
|
+
return ErrorCategory.CONNECTION;
|
|
86
|
+
}
|
|
87
|
+
if (message.includes("parse") ||
|
|
88
|
+
message.includes("json") ||
|
|
89
|
+
message.includes("syntax")) {
|
|
90
|
+
return ErrorCategory.PARSE;
|
|
91
|
+
}
|
|
92
|
+
if (message.includes("protocol") ||
|
|
93
|
+
message.includes("mcp") ||
|
|
94
|
+
message.includes("invalid response")) {
|
|
95
|
+
return ErrorCategory.PROTOCOL;
|
|
96
|
+
}
|
|
97
|
+
if (message.includes("invalid") ||
|
|
98
|
+
message.includes("required") ||
|
|
99
|
+
message.includes("missing") ||
|
|
100
|
+
message.includes("validation")) {
|
|
101
|
+
return ErrorCategory.VALIDATION;
|
|
102
|
+
}
|
|
103
|
+
return ErrorCategory.UNKNOWN;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extract error message from various error types
|
|
107
|
+
*
|
|
108
|
+
* @param error - The error to extract message from
|
|
109
|
+
* @returns A string error message
|
|
110
|
+
*/
|
|
111
|
+
export function extractErrorMessage(error) {
|
|
112
|
+
if (typeof error === "string") {
|
|
113
|
+
return error;
|
|
114
|
+
}
|
|
115
|
+
if (error instanceof Error) {
|
|
116
|
+
return error.message;
|
|
117
|
+
}
|
|
118
|
+
if (error && typeof error === "object") {
|
|
119
|
+
const err = error;
|
|
120
|
+
if (typeof err.message === "string") {
|
|
121
|
+
return err.message;
|
|
122
|
+
}
|
|
123
|
+
if (typeof err.error === "string") {
|
|
124
|
+
return err.error;
|
|
125
|
+
}
|
|
126
|
+
if (err.error && typeof err.error === "object") {
|
|
127
|
+
return extractErrorMessage(err.error);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
return JSON.stringify(error);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return String(error);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeout Utilities for Assessment Operations
|
|
3
|
+
*
|
|
4
|
+
* Provides AbortController-based timeout handling with proper cleanup.
|
|
5
|
+
* Fixes GitHub issue #38: Promise.race patterns that leave timers hanging.
|
|
6
|
+
*
|
|
7
|
+
* Key improvements over basic Promise.race:
|
|
8
|
+
* 1. Clears setTimeout when operation completes (prevents timer leaks)
|
|
9
|
+
* 2. Uses AbortController for signal-based cancellation
|
|
10
|
+
* 3. Provides consistent error messages
|
|
11
|
+
*/
|
|
12
|
+
export interface TimeoutOptions {
|
|
13
|
+
/** Timeout in milliseconds */
|
|
14
|
+
timeoutMs: number;
|
|
15
|
+
/** Optional custom error message for timeout */
|
|
16
|
+
errorMessage?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Execute a promise with timeout and proper cleanup.
|
|
20
|
+
*
|
|
21
|
+
* This function wraps any promise with a timeout, ensuring the timer
|
|
22
|
+
* is always cleaned up whether the operation succeeds, fails, or times out.
|
|
23
|
+
*
|
|
24
|
+
* @param promise - The promise to execute
|
|
25
|
+
* @param options - Timeout configuration
|
|
26
|
+
* @returns The result of the promise
|
|
27
|
+
* @throws Error if operation times out
|
|
28
|
+
*
|
|
29
|
+
* @example Basic usage
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const result = await executeWithTimeout(
|
|
32
|
+
* callTool(tool.name, params),
|
|
33
|
+
* { timeoutMs: 5000 }
|
|
34
|
+
* );
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @example With custom error message
|
|
38
|
+
* ```typescript
|
|
39
|
+
* const result = await executeWithTimeout(
|
|
40
|
+
* fetchData(),
|
|
41
|
+
* { timeoutMs: 10000, errorMessage: "Data fetch timed out" }
|
|
42
|
+
* );
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function executeWithTimeout<T>(promise: Promise<T>, options: TimeoutOptions): Promise<T>;
|
|
46
|
+
/**
|
|
47
|
+
* Execute an async function with timeout and AbortSignal support.
|
|
48
|
+
*
|
|
49
|
+
* This variant accepts a function that receives an AbortSignal, enabling
|
|
50
|
+
* cancellation of fetch requests and other abortable operations.
|
|
51
|
+
*
|
|
52
|
+
* @param fn - Function that accepts an AbortSignal and returns a Promise
|
|
53
|
+
* @param options - Timeout configuration
|
|
54
|
+
* @returns The result of the function
|
|
55
|
+
* @throws Error if operation times out
|
|
56
|
+
*
|
|
57
|
+
* @example With fetch
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const data = await executeWithTimeoutAndSignal(
|
|
60
|
+
* async (signal) => {
|
|
61
|
+
* const response = await fetch(url, { signal });
|
|
62
|
+
* return response.json();
|
|
63
|
+
* },
|
|
64
|
+
* { timeoutMs: 5000 }
|
|
65
|
+
* );
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export declare function executeWithTimeoutAndSignal<T>(fn: (signal: AbortSignal) => Promise<T>, options: TimeoutOptions): Promise<T>;
|
|
69
|
+
//# sourceMappingURL=timeoutUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeoutUtils.d.ts","sourceRoot":"","sources":["../../../../src/services/assessment/lib/timeoutUtils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,cAAc;IAC7B,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,CAAC,CAAC,CA2BZ;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,2BAA2B,CAAC,CAAC,EACjD,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,EACvC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,CAAC,CAAC,CAqBZ"}
|