@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.
Files changed (126) hide show
  1. package/dist/assets/{OAuthCallback-DE62cdTZ.js → OAuthCallback-D6y8tFfF.js} +1 -1
  2. package/dist/assets/{OAuthDebugCallback-CWjFdCIE.js → OAuthDebugCallback-DHegnqTa.js} +1 -1
  3. package/dist/assets/{index-PCQVSwHa.js → index-Cu02Ah3g.js} +4 -4
  4. package/dist/assets/{index-Df9Sx1jt.css → index-cHhcEXbr.css} +4 -0
  5. package/dist/index.html +2 -2
  6. package/lib/lib/assessment/coreTypes.d.ts +65 -0
  7. package/lib/lib/assessment/coreTypes.d.ts.map +1 -1
  8. package/lib/lib/assessment/extendedTypes.d.ts +127 -0
  9. package/lib/lib/assessment/extendedTypes.d.ts.map +1 -1
  10. package/lib/lib/assessment/resultTypes.d.ts +45 -0
  11. package/lib/lib/assessment/resultTypes.d.ts.map +1 -1
  12. package/lib/lib/moduleScoring.d.ts +2 -2
  13. package/lib/lib/moduleScoring.d.ts.map +1 -1
  14. package/lib/lib/moduleScoring.js +3 -2
  15. package/lib/services/assessment/AssessmentOrchestrator.d.ts +3 -7
  16. package/lib/services/assessment/AssessmentOrchestrator.d.ts.map +1 -1
  17. package/lib/services/assessment/AssessmentOrchestrator.js +13 -2
  18. package/lib/services/assessment/TestDataGenerator.d.ts +9 -1
  19. package/lib/services/assessment/TestDataGenerator.d.ts.map +1 -1
  20. package/lib/services/assessment/TestDataGenerator.js +32 -6
  21. package/lib/services/assessment/TestScenarioEngine.d.ts +9 -1
  22. package/lib/services/assessment/TestScenarioEngine.d.ts.map +1 -1
  23. package/lib/services/assessment/TestScenarioEngine.js +17 -14
  24. package/lib/services/assessment/config/annotationPatterns.d.ts +3 -1
  25. package/lib/services/assessment/config/annotationPatterns.d.ts.map +1 -1
  26. package/lib/services/assessment/config/annotationPatterns.js +5 -2
  27. package/lib/services/assessment/config/architecturePatterns.d.ts +101 -0
  28. package/lib/services/assessment/config/architecturePatterns.d.ts.map +1 -0
  29. package/lib/services/assessment/config/architecturePatterns.js +248 -0
  30. package/lib/services/assessment/config/performanceConfig.d.ts +122 -0
  31. package/lib/services/assessment/config/performanceConfig.d.ts.map +1 -0
  32. package/lib/services/assessment/config/performanceConfig.js +154 -0
  33. package/lib/services/assessment/config/sanitizationPatterns.d.ts +63 -0
  34. package/lib/services/assessment/config/sanitizationPatterns.d.ts.map +1 -0
  35. package/lib/services/assessment/config/sanitizationPatterns.js +223 -0
  36. package/lib/services/assessment/lib/claudeCodeBridge.d.ts +40 -3
  37. package/lib/services/assessment/lib/claudeCodeBridge.d.ts.map +1 -1
  38. package/lib/services/assessment/lib/claudeCodeBridge.js +149 -8
  39. package/lib/services/assessment/lib/concurrencyLimit.d.ts +6 -2
  40. package/lib/services/assessment/lib/concurrencyLimit.d.ts.map +1 -1
  41. package/lib/services/assessment/lib/concurrencyLimit.js +13 -6
  42. package/lib/services/assessment/lib/errors.d.ts +90 -0
  43. package/lib/services/assessment/lib/errors.d.ts.map +1 -0
  44. package/lib/services/assessment/lib/errors.js +136 -0
  45. package/lib/services/assessment/lib/timeoutUtils.d.ts +69 -0
  46. package/lib/services/assessment/lib/timeoutUtils.d.ts.map +1 -0
  47. package/lib/services/assessment/lib/timeoutUtils.js +103 -0
  48. package/lib/services/assessment/modules/BaseAssessor.d.ts +43 -8
  49. package/lib/services/assessment/modules/BaseAssessor.d.ts.map +1 -1
  50. package/lib/services/assessment/modules/BaseAssessor.js +103 -34
  51. package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts +38 -1
  52. package/lib/services/assessment/modules/DeveloperExperienceAssessor.d.ts.map +1 -1
  53. package/lib/services/assessment/modules/DeveloperExperienceAssessor.js +185 -19
  54. package/lib/services/assessment/modules/DocumentationAssessor.d.ts +5 -0
  55. package/lib/services/assessment/modules/DocumentationAssessor.d.ts.map +1 -1
  56. package/lib/services/assessment/modules/DocumentationAssessor.js +11 -0
  57. package/lib/services/assessment/modules/ErrorHandlingAssessor.js +1 -1
  58. package/lib/services/assessment/modules/FunctionalityAssessor.d.ts.map +1 -1
  59. package/lib/services/assessment/modules/FunctionalityAssessor.js +6 -3
  60. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts +3 -0
  61. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.d.ts.map +1 -1
  62. package/lib/services/assessment/modules/MCPSpecComplianceAssessor.js +14 -2
  63. package/lib/services/assessment/modules/ManifestValidationAssessor.d.ts.map +1 -1
  64. package/lib/services/assessment/modules/ManifestValidationAssessor.js +7 -2
  65. package/lib/services/assessment/modules/PromptAssessor.d.ts +1 -0
  66. package/lib/services/assessment/modules/PromptAssessor.d.ts.map +1 -1
  67. package/lib/services/assessment/modules/PromptAssessor.js +26 -16
  68. package/lib/services/assessment/modules/ProtocolComplianceAssessor.d.ts.map +1 -1
  69. package/lib/services/assessment/modules/ProtocolComplianceAssessor.js +6 -2
  70. package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts +5 -0
  71. package/lib/services/assessment/modules/ProtocolConformanceAssessor.d.ts.map +1 -1
  72. package/lib/services/assessment/modules/ProtocolConformanceAssessor.js +15 -0
  73. package/lib/services/assessment/modules/ResourceAssessor.d.ts.map +1 -1
  74. package/lib/services/assessment/modules/ResourceAssessor.js +8 -2
  75. package/lib/services/assessment/modules/SecurityAssessor.d.ts +3 -171
  76. package/lib/services/assessment/modules/SecurityAssessor.d.ts.map +1 -1
  77. package/lib/services/assessment/modules/SecurityAssessor.js +25 -1480
  78. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts +27 -28
  79. package/lib/services/assessment/modules/ToolAnnotationAssessor.d.ts.map +1 -1
  80. package/lib/services/assessment/modules/ToolAnnotationAssessor.js +340 -863
  81. package/lib/services/assessment/modules/UsabilityAssessor.d.ts +5 -0
  82. package/lib/services/assessment/modules/UsabilityAssessor.d.ts.map +1 -1
  83. package/lib/services/assessment/modules/UsabilityAssessor.js +11 -0
  84. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts +57 -0
  85. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.d.ts.map +1 -0
  86. package/lib/services/assessment/modules/annotations/AnnotationDeceptionDetector.js +176 -0
  87. package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts +67 -0
  88. package/lib/services/assessment/modules/annotations/ArchitectureDetector.d.ts.map +1 -0
  89. package/lib/services/assessment/modules/annotations/ArchitectureDetector.js +239 -0
  90. package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts +46 -0
  91. package/lib/services/assessment/modules/annotations/BehaviorInference.d.ts.map +1 -0
  92. package/lib/services/assessment/modules/annotations/BehaviorInference.js +394 -0
  93. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts +64 -0
  94. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.d.ts.map +1 -0
  95. package/lib/services/assessment/modules/annotations/DescriptionAnalyzer.js +304 -0
  96. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts +43 -0
  97. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.d.ts.map +1 -0
  98. package/lib/services/assessment/modules/annotations/DescriptionPoisoningDetector.js +276 -0
  99. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts +122 -0
  100. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.d.ts.map +1 -0
  101. package/lib/services/assessment/modules/annotations/SchemaAnalyzer.js +388 -0
  102. package/lib/services/assessment/modules/annotations/index.d.ts +13 -0
  103. package/lib/services/assessment/modules/annotations/index.d.ts.map +1 -0
  104. package/lib/services/assessment/modules/annotations/index.js +15 -0
  105. package/lib/services/assessment/modules/index.d.ts +10 -0
  106. package/lib/services/assessment/modules/index.d.ts.map +1 -1
  107. package/lib/services/assessment/modules/index.js +13 -0
  108. package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts +125 -0
  109. package/lib/services/assessment/modules/securityTests/SanitizationDetector.d.ts.map +1 -0
  110. package/lib/services/assessment/modules/securityTests/SanitizationDetector.js +345 -0
  111. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts +33 -0
  112. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.d.ts.map +1 -0
  113. package/lib/services/assessment/modules/securityTests/SecurityPayloadGenerator.js +128 -0
  114. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts +67 -0
  115. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.d.ts.map +1 -0
  116. package/lib/services/assessment/modules/securityTests/SecurityPayloadTester.js +372 -0
  117. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts +178 -0
  118. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.d.ts.map +1 -0
  119. package/lib/services/assessment/modules/securityTests/SecurityResponseAnalyzer.js +1207 -0
  120. package/lib/services/assessment/modules/securityTests/index.d.ts +8 -0
  121. package/lib/services/assessment/modules/securityTests/index.d.ts.map +1 -0
  122. package/lib/services/assessment/modules/securityTests/index.js +7 -0
  123. package/lib/services/assessment/tool-classifier-patterns.d.ts +1 -0
  124. package/lib/services/assessment/tool-classifier-patterns.d.ts.map +1 -1
  125. package/lib/services/assessment/tool-classifier-patterns.js +17 -0
  126. 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
- constructor(config) {
74
+ logger;
75
+ constructor(config, logger) {
54
76
  this.config = config;
55
- this.isAvailable = this.checkClaudeAvailability();
56
- if (!this.isAvailable) {
57
- console.warn("[ClaudeCodeBridge] Claude CLI not available - features will be disabled");
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
- checkClaudeAvailability() {
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 with retries
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
- const response = this.executeClaudeCommand(prompt);
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
- console.warn("[ClaudeCodeBridge] Failed to parse JSON response");
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 = 10000;
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;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,QAAQ,CAAC;AAE7C,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;AAEpE;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAuDzE"}
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 = 10000;
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
- console.warn(`[concurrencyLimit] Queue depth: ${queue.length} ` +
66
- `(threshold: ${QUEUE_WARNING_THRESHOLD}). ` +
67
- `Active: ${activeCount}/${concurrency}. ` +
68
- `This may indicate a slow/stalled server.`);
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"}