driftdetect-mcp 0.4.0 → 0.4.2

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 (140) hide show
  1. package/dist/bin/server.d.ts +12 -2
  2. package/dist/bin/server.d.ts.map +1 -1
  3. package/dist/bin/server.js +25 -5
  4. package/dist/bin/server.js.map +1 -1
  5. package/dist/enterprise-server.d.ts +78 -0
  6. package/dist/enterprise-server.d.ts.map +1 -0
  7. package/dist/enterprise-server.js +201 -0
  8. package/dist/enterprise-server.js.map +1 -0
  9. package/dist/index.d.ts +15 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +17 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/infrastructure/cache.d.ts +86 -0
  14. package/dist/infrastructure/cache.d.ts.map +1 -0
  15. package/dist/infrastructure/cache.js +271 -0
  16. package/dist/infrastructure/cache.js.map +1 -0
  17. package/dist/infrastructure/cursor-manager.d.ts +86 -0
  18. package/dist/infrastructure/cursor-manager.d.ts.map +1 -0
  19. package/dist/infrastructure/cursor-manager.js +175 -0
  20. package/dist/infrastructure/cursor-manager.js.map +1 -0
  21. package/dist/infrastructure/error-handler.d.ts +82 -0
  22. package/dist/infrastructure/error-handler.d.ts.map +1 -0
  23. package/dist/infrastructure/error-handler.js +226 -0
  24. package/dist/infrastructure/error-handler.js.map +1 -0
  25. package/dist/infrastructure/index.d.ts +19 -0
  26. package/dist/infrastructure/index.d.ts.map +1 -0
  27. package/dist/infrastructure/index.js +26 -0
  28. package/dist/infrastructure/index.js.map +1 -0
  29. package/dist/infrastructure/metrics.d.ts +104 -0
  30. package/dist/infrastructure/metrics.d.ts.map +1 -0
  31. package/dist/infrastructure/metrics.js +291 -0
  32. package/dist/infrastructure/metrics.js.map +1 -0
  33. package/dist/infrastructure/rate-limiter.d.ts +59 -0
  34. package/dist/infrastructure/rate-limiter.d.ts.map +1 -0
  35. package/dist/infrastructure/rate-limiter.js +132 -0
  36. package/dist/infrastructure/rate-limiter.js.map +1 -0
  37. package/dist/infrastructure/response-builder.d.ts +104 -0
  38. package/dist/infrastructure/response-builder.d.ts.map +1 -0
  39. package/dist/infrastructure/response-builder.js +207 -0
  40. package/dist/infrastructure/response-builder.js.map +1 -0
  41. package/dist/infrastructure/token-estimator.d.ts +48 -0
  42. package/dist/infrastructure/token-estimator.d.ts.map +1 -0
  43. package/dist/infrastructure/token-estimator.js +131 -0
  44. package/dist/infrastructure/token-estimator.js.map +1 -0
  45. package/dist/server.d.ts.map +1 -1
  46. package/dist/server.js +1074 -17
  47. package/dist/server.js.map +1 -1
  48. package/dist/tools/detail/code-examples.d.ts +33 -0
  49. package/dist/tools/detail/code-examples.d.ts.map +1 -0
  50. package/dist/tools/detail/code-examples.js +126 -0
  51. package/dist/tools/detail/code-examples.js.map +1 -0
  52. package/dist/tools/detail/dna-check.d.ts +32 -0
  53. package/dist/tools/detail/dna-check.d.ts.map +1 -0
  54. package/dist/tools/detail/dna-check.js +231 -0
  55. package/dist/tools/detail/dna-check.js.map +1 -0
  56. package/dist/tools/detail/dna-profile.d.ts +37 -0
  57. package/dist/tools/detail/dna-profile.d.ts.map +1 -0
  58. package/dist/tools/detail/dna-profile.js +101 -0
  59. package/dist/tools/detail/dna-profile.js.map +1 -0
  60. package/dist/tools/detail/file-patterns.d.ts +39 -0
  61. package/dist/tools/detail/file-patterns.d.ts.map +1 -0
  62. package/dist/tools/detail/file-patterns.js +103 -0
  63. package/dist/tools/detail/file-patterns.js.map +1 -0
  64. package/dist/tools/detail/files-list.d.ts +30 -0
  65. package/dist/tools/detail/files-list.d.ts.map +1 -0
  66. package/dist/tools/detail/files-list.js +99 -0
  67. package/dist/tools/detail/files-list.js.map +1 -0
  68. package/dist/tools/detail/impact-analysis.d.ts +53 -0
  69. package/dist/tools/detail/impact-analysis.d.ts.map +1 -0
  70. package/dist/tools/detail/impact-analysis.js +130 -0
  71. package/dist/tools/detail/impact-analysis.js.map +1 -0
  72. package/dist/tools/detail/index.d.ts +23 -0
  73. package/dist/tools/detail/index.d.ts.map +1 -0
  74. package/dist/tools/detail/index.js +200 -0
  75. package/dist/tools/detail/index.js.map +1 -0
  76. package/dist/tools/detail/pattern-get.d.ts +45 -0
  77. package/dist/tools/detail/pattern-get.d.ts.map +1 -0
  78. package/dist/tools/detail/pattern-get.js +87 -0
  79. package/dist/tools/detail/pattern-get.js.map +1 -0
  80. package/dist/tools/detail/reachability.d.ts +60 -0
  81. package/dist/tools/detail/reachability.d.ts.map +1 -0
  82. package/dist/tools/detail/reachability.js +168 -0
  83. package/dist/tools/detail/reachability.js.map +1 -0
  84. package/dist/tools/discovery/capabilities.d.ts +28 -0
  85. package/dist/tools/discovery/capabilities.d.ts.map +1 -0
  86. package/dist/tools/discovery/capabilities.js +112 -0
  87. package/dist/tools/discovery/capabilities.js.map +1 -0
  88. package/dist/tools/discovery/index.d.ts +13 -0
  89. package/dist/tools/discovery/index.d.ts.map +1 -0
  90. package/dist/tools/discovery/index.js +30 -0
  91. package/dist/tools/discovery/index.js.map +1 -0
  92. package/dist/tools/discovery/projects.d.ts +26 -0
  93. package/dist/tools/discovery/projects.d.ts.map +1 -0
  94. package/dist/tools/discovery/projects.js +210 -0
  95. package/dist/tools/discovery/projects.js.map +1 -0
  96. package/dist/tools/discovery/status.d.ts +42 -0
  97. package/dist/tools/discovery/status.d.ts.map +1 -0
  98. package/dist/tools/discovery/status.js +157 -0
  99. package/dist/tools/discovery/status.js.map +1 -0
  100. package/dist/tools/exploration/contracts-list.d.ts +35 -0
  101. package/dist/tools/exploration/contracts-list.d.ts.map +1 -0
  102. package/dist/tools/exploration/contracts-list.js +106 -0
  103. package/dist/tools/exploration/contracts-list.js.map +1 -0
  104. package/dist/tools/exploration/files-list.d.ts +29 -0
  105. package/dist/tools/exploration/files-list.d.ts.map +1 -0
  106. package/dist/tools/exploration/files-list.js +94 -0
  107. package/dist/tools/exploration/files-list.js.map +1 -0
  108. package/dist/tools/exploration/index.d.ts +17 -0
  109. package/dist/tools/exploration/index.d.ts.map +1 -0
  110. package/dist/tools/exploration/index.js +126 -0
  111. package/dist/tools/exploration/index.js.map +1 -0
  112. package/dist/tools/exploration/patterns-list.d.ts +40 -0
  113. package/dist/tools/exploration/patterns-list.d.ts.map +1 -0
  114. package/dist/tools/exploration/patterns-list.js +172 -0
  115. package/dist/tools/exploration/patterns-list.js.map +1 -0
  116. package/dist/tools/exploration/security-summary.d.ts +49 -0
  117. package/dist/tools/exploration/security-summary.d.ts.map +1 -0
  118. package/dist/tools/exploration/security-summary.js +111 -0
  119. package/dist/tools/exploration/security-summary.js.map +1 -0
  120. package/dist/tools/exploration/trends.d.ts +49 -0
  121. package/dist/tools/exploration/trends.d.ts.map +1 -0
  122. package/dist/tools/exploration/trends.js +147 -0
  123. package/dist/tools/exploration/trends.js.map +1 -0
  124. package/dist/tools/index.d.ts +13 -0
  125. package/dist/tools/index.d.ts.map +1 -0
  126. package/dist/tools/index.js +13 -0
  127. package/dist/tools/index.js.map +1 -0
  128. package/dist/tools/orchestration/context.d.ts +72 -0
  129. package/dist/tools/orchestration/context.d.ts.map +1 -0
  130. package/dist/tools/orchestration/context.js +499 -0
  131. package/dist/tools/orchestration/context.js.map +1 -0
  132. package/dist/tools/orchestration/index.d.ts +11 -0
  133. package/dist/tools/orchestration/index.d.ts.map +1 -0
  134. package/dist/tools/orchestration/index.js +56 -0
  135. package/dist/tools/orchestration/index.js.map +1 -0
  136. package/dist/tools/registry.d.ts +41 -0
  137. package/dist/tools/registry.d.ts.map +1 -0
  138. package/dist/tools/registry.js +64 -0
  139. package/dist/tools/registry.js.map +1 -0
  140. package/package.json +3 -3
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Enterprise Error Handler
3
+ *
4
+ * Provides structured error responses with:
5
+ * - Consistent error codes
6
+ * - Recovery suggestions for AI
7
+ * - Request tracking
8
+ */
9
+ export var DriftErrorCode;
10
+ (function (DriftErrorCode) {
11
+ // Client errors (4xx equivalent)
12
+ DriftErrorCode["INVALID_ARGUMENT"] = "INVALID_ARGUMENT";
13
+ DriftErrorCode["PATTERN_NOT_FOUND"] = "PATTERN_NOT_FOUND";
14
+ DriftErrorCode["FILE_NOT_FOUND"] = "FILE_NOT_FOUND";
15
+ DriftErrorCode["INVALID_CURSOR"] = "INVALID_CURSOR";
16
+ DriftErrorCode["INVALID_CATEGORY"] = "INVALID_CATEGORY";
17
+ DriftErrorCode["MISSING_REQUIRED_PARAM"] = "MISSING_REQUIRED_PARAM";
18
+ // Server errors (5xx equivalent)
19
+ DriftErrorCode["SCAN_REQUIRED"] = "SCAN_REQUIRED";
20
+ DriftErrorCode["STORE_UNAVAILABLE"] = "STORE_UNAVAILABLE";
21
+ DriftErrorCode["ANALYSIS_FAILED"] = "ANALYSIS_FAILED";
22
+ DriftErrorCode["INTERNAL_ERROR"] = "INTERNAL_ERROR";
23
+ // Rate limiting
24
+ DriftErrorCode["RATE_LIMITED"] = "RATE_LIMITED";
25
+ // Resource errors
26
+ DriftErrorCode["CALLGRAPH_NOT_BUILT"] = "CALLGRAPH_NOT_BUILT";
27
+ DriftErrorCode["DNA_NOT_ANALYZED"] = "DNA_NOT_ANALYZED";
28
+ })(DriftErrorCode || (DriftErrorCode = {}));
29
+ export class DriftError extends Error {
30
+ code;
31
+ details;
32
+ recovery;
33
+ constructor(errorDetails) {
34
+ super(errorDetails.message);
35
+ this.name = 'DriftError';
36
+ this.code = errorDetails.code;
37
+ this.details = errorDetails.details;
38
+ this.recovery = errorDetails.recovery;
39
+ }
40
+ /**
41
+ * Convert to MCP error response format
42
+ */
43
+ toMCPResponse(requestId) {
44
+ const errorResponse = {
45
+ error: {
46
+ code: this.code,
47
+ message: this.message,
48
+ details: this.details,
49
+ recovery: this.recovery,
50
+ },
51
+ meta: {
52
+ requestId: requestId || `err_${Date.now().toString(36)}`,
53
+ timestamp: new Date().toISOString(),
54
+ },
55
+ };
56
+ return {
57
+ content: [{
58
+ type: 'text',
59
+ text: JSON.stringify(errorResponse, null, 2),
60
+ }],
61
+ isError: true,
62
+ };
63
+ }
64
+ }
65
+ /**
66
+ * Error factory functions for common errors
67
+ */
68
+ export const Errors = {
69
+ invalidArgument(param, reason, suggestion) {
70
+ return new DriftError({
71
+ code: DriftErrorCode.INVALID_ARGUMENT,
72
+ message: `Invalid argument '${param}': ${reason}`,
73
+ details: { param, reason },
74
+ recovery: suggestion ? { suggestion } : undefined,
75
+ });
76
+ },
77
+ missingRequired(param) {
78
+ return new DriftError({
79
+ code: DriftErrorCode.MISSING_REQUIRED_PARAM,
80
+ message: `Missing required parameter: ${param}`,
81
+ details: { param },
82
+ recovery: {
83
+ suggestion: `Provide the '${param}' parameter`,
84
+ },
85
+ });
86
+ },
87
+ missingParameter(param) {
88
+ return this.missingRequired(param);
89
+ },
90
+ notFound(type, id) {
91
+ if (type === 'pattern') {
92
+ return this.patternNotFound(id);
93
+ }
94
+ if (type === 'file') {
95
+ return this.fileNotFound(id);
96
+ }
97
+ return new DriftError({
98
+ code: DriftErrorCode.FILE_NOT_FOUND,
99
+ message: `${type} not found: ${id}`,
100
+ details: { type, id },
101
+ recovery: {
102
+ suggestion: `Check that the ${type} exists`,
103
+ },
104
+ });
105
+ },
106
+ invalidParameter(param, reason) {
107
+ return this.invalidArgument(param, reason);
108
+ },
109
+ patternNotFound(patternId) {
110
+ return new DriftError({
111
+ code: DriftErrorCode.PATTERN_NOT_FOUND,
112
+ message: `Pattern not found: ${patternId}`,
113
+ details: { patternId },
114
+ recovery: {
115
+ suggestion: 'Use drift_patterns_list to find valid pattern IDs',
116
+ alternativeTools: ['drift_patterns_list', 'drift_status'],
117
+ },
118
+ });
119
+ },
120
+ fileNotFound(path) {
121
+ return new DriftError({
122
+ code: DriftErrorCode.FILE_NOT_FOUND,
123
+ message: `File not found: ${path}`,
124
+ details: { path },
125
+ recovery: {
126
+ suggestion: 'Check the file path is relative to project root',
127
+ alternativeTools: ['drift_files_list'],
128
+ },
129
+ });
130
+ },
131
+ invalidCursor() {
132
+ return new DriftError({
133
+ code: DriftErrorCode.INVALID_CURSOR,
134
+ message: 'Invalid or expired pagination cursor',
135
+ recovery: {
136
+ suggestion: 'Start pagination from the beginning without a cursor',
137
+ },
138
+ });
139
+ },
140
+ invalidCategory(category, validCategories) {
141
+ return new DriftError({
142
+ code: DriftErrorCode.INVALID_CATEGORY,
143
+ message: `Invalid category: ${category}`,
144
+ details: {
145
+ provided: category,
146
+ valid: validCategories,
147
+ },
148
+ recovery: {
149
+ suggestion: `Use one of: ${validCategories.join(', ')}`,
150
+ },
151
+ });
152
+ },
153
+ scanRequired() {
154
+ return new DriftError({
155
+ code: DriftErrorCode.SCAN_REQUIRED,
156
+ message: 'No pattern data found. The codebase needs to be scanned first.',
157
+ recovery: {
158
+ suggestion: "Run 'drift scan' in the project root to analyze patterns",
159
+ command: 'drift scan',
160
+ alternativeTools: ['drift_status'],
161
+ },
162
+ });
163
+ },
164
+ callgraphNotBuilt() {
165
+ return new DriftError({
166
+ code: DriftErrorCode.CALLGRAPH_NOT_BUILT,
167
+ message: 'Call graph has not been built yet.',
168
+ recovery: {
169
+ suggestion: "Use drift_callgraph with action='build' first",
170
+ alternativeTools: ['drift_callgraph'],
171
+ },
172
+ });
173
+ },
174
+ dnaNotAnalyzed() {
175
+ return new DriftError({
176
+ code: DriftErrorCode.DNA_NOT_ANALYZED,
177
+ message: 'Styling DNA has not been analyzed yet.',
178
+ recovery: {
179
+ suggestion: "Run 'drift dna scan' to analyze styling patterns",
180
+ command: 'drift dna scan',
181
+ },
182
+ });
183
+ },
184
+ rateLimited(retryAfterMs) {
185
+ return new DriftError({
186
+ code: DriftErrorCode.RATE_LIMITED,
187
+ message: 'Rate limit exceeded. Please wait before making more requests.',
188
+ recovery: {
189
+ suggestion: 'Wait before retrying',
190
+ retryAfterMs,
191
+ },
192
+ });
193
+ },
194
+ internal(message, details) {
195
+ return new DriftError({
196
+ code: DriftErrorCode.INTERNAL_ERROR,
197
+ message: `Internal error: ${message}`,
198
+ details,
199
+ recovery: {
200
+ suggestion: 'This is an unexpected error. Please report it if it persists.',
201
+ },
202
+ });
203
+ },
204
+ custom(code, message, alternativeTools) {
205
+ return new DriftError({
206
+ code: code,
207
+ message,
208
+ recovery: alternativeTools ? {
209
+ suggestion: message,
210
+ alternativeTools,
211
+ } : undefined,
212
+ });
213
+ },
214
+ };
215
+ /**
216
+ * Error handler middleware
217
+ */
218
+ export function handleError(error, requestId) {
219
+ if (error instanceof DriftError) {
220
+ return error.toMCPResponse(requestId);
221
+ }
222
+ // Convert unknown errors to DriftError
223
+ const message = error instanceof Error ? error.message : String(error);
224
+ return Errors.internal(message).toMCPResponse(requestId);
225
+ }
226
+ //# sourceMappingURL=error-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/infrastructure/error-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Enterprise MCP Infrastructure
3
+ *
4
+ * Core infrastructure components for building enterprise-grade MCP servers:
5
+ * - Response building with token budgets
6
+ * - Cursor-based pagination
7
+ * - Structured error handling
8
+ * - Caching with invalidation
9
+ * - Rate limiting
10
+ * - Metrics collection
11
+ */
12
+ export { ResponseBuilder, createResponseBuilder, type MCPResponse, type MCPResponseMeta, type PaginationInfo, type ResponseHints, type ResponseBuilderConfig, } from './response-builder.js';
13
+ export { TokenEstimator, tokenEstimator, type TokenEstimate, } from './token-estimator.js';
14
+ export { CursorManager, cursorManager, createCursor, parseCursor, type CursorData, type CursorConfig, } from './cursor-manager.js';
15
+ export { DriftError, DriftErrorCode, Errors, handleError, type DriftErrorDetails, type RecoveryHint, } from './error-handler.js';
16
+ export { ResponseCache, createCache, type CachedResponse, type CacheConfig, } from './cache.js';
17
+ export { RateLimiter, rateLimiter, type RateLimitConfig, } from './rate-limiter.js';
18
+ export { MetricsCollector, metrics, type Metric, type MetricLabels, type HistogramBuckets, } from './metrics.js';
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/infrastructure/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,cAAc,EACd,KAAK,aAAa,GACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAW,EACX,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EACL,UAAU,EACV,cAAc,EACd,MAAM,EACN,WAAW,EACX,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,aAAa,EACb,WAAW,EACX,KAAK,cAAc,EACnB,KAAK,WAAW,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,WAAW,EACX,WAAW,EACX,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,gBAAgB,EAChB,OAAO,EACP,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,gBAAgB,GACtB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Enterprise MCP Infrastructure
3
+ *
4
+ * Core infrastructure components for building enterprise-grade MCP servers:
5
+ * - Response building with token budgets
6
+ * - Cursor-based pagination
7
+ * - Structured error handling
8
+ * - Caching with invalidation
9
+ * - Rate limiting
10
+ * - Metrics collection
11
+ */
12
+ // Response Building
13
+ export { ResponseBuilder, createResponseBuilder, } from './response-builder.js';
14
+ // Token Estimation
15
+ export { TokenEstimator, tokenEstimator, } from './token-estimator.js';
16
+ // Cursor Pagination
17
+ export { CursorManager, cursorManager, createCursor, parseCursor, } from './cursor-manager.js';
18
+ // Error Handling
19
+ export { DriftError, DriftErrorCode, Errors, handleError, } from './error-handler.js';
20
+ // Caching
21
+ export { ResponseCache, createCache, } from './cache.js';
22
+ // Rate Limiting
23
+ export { RateLimiter, rateLimiter, } from './rate-limiter.js';
24
+ // Metrics
25
+ export { MetricsCollector, metrics, } from './metrics.js';
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/infrastructure/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,oBAAoB;AACpB,OAAO,EACL,eAAe,EACf,qBAAqB,GAMtB,MAAM,uBAAuB,CAAC;AAE/B,mBAAmB;AACnB,OAAO,EACL,cAAc,EACd,cAAc,GAEf,MAAM,sBAAsB,CAAC;AAE9B,oBAAoB;AACpB,OAAO,EACL,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAW,GAGZ,MAAM,qBAAqB,CAAC;AAE7B,iBAAiB;AACjB,OAAO,EACL,UAAU,EACV,cAAc,EACd,MAAM,EACN,WAAW,GAGZ,MAAM,oBAAoB,CAAC;AAE5B,UAAU;AACV,OAAO,EACL,aAAa,EACb,WAAW,GAGZ,MAAM,YAAY,CAAC;AAEpB,gBAAgB;AAChB,OAAO,EACL,WAAW,EACX,WAAW,GAEZ,MAAM,mBAAmB,CAAC;AAE3B,UAAU;AACV,OAAO,EACL,gBAAgB,EAChB,OAAO,GAIR,MAAM,cAAc,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Metrics Collector
3
+ *
4
+ * Collects operational metrics for observability:
5
+ * - Request counts and durations
6
+ * - Cache hit/miss rates
7
+ * - Token usage estimates
8
+ * - Error rates
9
+ */
10
+ export interface MetricLabels {
11
+ tool?: string;
12
+ success?: string;
13
+ cached?: string;
14
+ errorCode?: string;
15
+ }
16
+ export interface Metric {
17
+ name: string;
18
+ type: 'counter' | 'gauge' | 'histogram';
19
+ value: number;
20
+ labels: MetricLabels;
21
+ timestamp: number;
22
+ }
23
+ export interface HistogramBuckets {
24
+ le_10: number;
25
+ le_50: number;
26
+ le_100: number;
27
+ le_250: number;
28
+ le_500: number;
29
+ le_1000: number;
30
+ le_2500: number;
31
+ le_5000: number;
32
+ le_inf: number;
33
+ sum: number;
34
+ count: number;
35
+ }
36
+ export declare class MetricsCollector {
37
+ private counters;
38
+ private gauges;
39
+ private histograms;
40
+ private metrics;
41
+ private maxMetrics;
42
+ /**
43
+ * Increment a counter
44
+ */
45
+ increment(name: string, labels?: MetricLabels, value?: number): void;
46
+ /**
47
+ * Set a gauge value
48
+ */
49
+ gauge(name: string, value: number, labels?: MetricLabels): void;
50
+ /**
51
+ * Record a histogram observation
52
+ */
53
+ observe(name: string, value: number, labels?: MetricLabels): void;
54
+ /**
55
+ * Record a request
56
+ */
57
+ recordRequest(tool: string, durationMs: number, success: boolean, cached?: boolean): void;
58
+ /**
59
+ * Record an error
60
+ */
61
+ recordError(tool: string, errorCode: string): void;
62
+ /**
63
+ * Record token estimate
64
+ */
65
+ recordTokens(tool: string, tokens: number): void;
66
+ /**
67
+ * Record patterns queried
68
+ */
69
+ recordPatternsQueried(count: number, tool: string): void;
70
+ /**
71
+ * Get all metrics
72
+ */
73
+ getMetrics(): Metric[];
74
+ /**
75
+ * Get summary statistics
76
+ */
77
+ getSummary(): {
78
+ totalRequests: number;
79
+ totalErrors: number;
80
+ cacheHitRate: number;
81
+ avgDurationMs: number;
82
+ avgTokens: number;
83
+ requestsByTool: Record<string, number>;
84
+ };
85
+ /**
86
+ * Export metrics in Prometheus format
87
+ */
88
+ toPrometheus(): string;
89
+ /**
90
+ * Clear all metrics
91
+ */
92
+ clear(): void;
93
+ private makeKey;
94
+ private parseKey;
95
+ private formatLabels;
96
+ private addLabel;
97
+ private createEmptyBuckets;
98
+ private recordMetric;
99
+ }
100
+ /**
101
+ * Singleton instance for convenience
102
+ */
103
+ export declare const metrics: MetricsCollector;
104
+ //# sourceMappingURL=metrics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/infrastructure/metrics.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,WAAW,CAAC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAkC;IAClD,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,UAAU,CAA4C;IAC9D,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,UAAU,CAAiB;IAEnC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,YAAiB,EAAE,KAAK,GAAE,MAAU,GAAG,IAAI;IAc3E;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,YAAiB,GAAG,IAAI;IAanE;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,YAAiB,GAAG,IAAI;IAiCrE;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,IAAI;IAgBhG;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI;IAIlD;;OAEG;IACH,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIhD;;OAEG;IACH,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxD;;OAEG;IACH,UAAU,IAAI,MAAM,EAAE;IAItB;;OAEG;IACH,UAAU,IAAI;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACxC;IA2DD;;OAEG;IACH,YAAY,IAAI,MAAM;IAsCtB;;OAEG;IACH,KAAK,IAAI,IAAI;IASb,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,QAAQ;IAqBhB,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,QAAQ;IAOhB,OAAO,CAAC,kBAAkB;IAgB1B,OAAO,CAAC,YAAY;CAQrB;AAED;;GAEG;AACH,eAAO,MAAM,OAAO,kBAAyB,CAAC"}
@@ -0,0 +1,291 @@
1
+ /**
2
+ * Metrics Collector
3
+ *
4
+ * Collects operational metrics for observability:
5
+ * - Request counts and durations
6
+ * - Cache hit/miss rates
7
+ * - Token usage estimates
8
+ * - Error rates
9
+ */
10
+ export class MetricsCollector {
11
+ counters = new Map();
12
+ gauges = new Map();
13
+ histograms = new Map();
14
+ metrics = [];
15
+ maxMetrics = 10000;
16
+ /**
17
+ * Increment a counter
18
+ */
19
+ increment(name, labels = {}, value = 1) {
20
+ const key = this.makeKey(name, labels);
21
+ const current = this.counters.get(key) ?? 0;
22
+ this.counters.set(key, current + value);
23
+ this.recordMetric({
24
+ name,
25
+ type: 'counter',
26
+ value: current + value,
27
+ labels,
28
+ timestamp: Date.now(),
29
+ });
30
+ }
31
+ /**
32
+ * Set a gauge value
33
+ */
34
+ gauge(name, value, labels = {}) {
35
+ const key = this.makeKey(name, labels);
36
+ this.gauges.set(key, value);
37
+ this.recordMetric({
38
+ name,
39
+ type: 'gauge',
40
+ value,
41
+ labels,
42
+ timestamp: Date.now(),
43
+ });
44
+ }
45
+ /**
46
+ * Record a histogram observation
47
+ */
48
+ observe(name, value, labels = {}) {
49
+ const key = this.makeKey(name, labels);
50
+ let buckets = this.histograms.get(key);
51
+ if (!buckets) {
52
+ buckets = this.createEmptyBuckets();
53
+ this.histograms.set(key, buckets);
54
+ }
55
+ // Update buckets
56
+ if (value <= 10)
57
+ buckets.le_10++;
58
+ if (value <= 50)
59
+ buckets.le_50++;
60
+ if (value <= 100)
61
+ buckets.le_100++;
62
+ if (value <= 250)
63
+ buckets.le_250++;
64
+ if (value <= 500)
65
+ buckets.le_500++;
66
+ if (value <= 1000)
67
+ buckets.le_1000++;
68
+ if (value <= 2500)
69
+ buckets.le_2500++;
70
+ if (value <= 5000)
71
+ buckets.le_5000++;
72
+ buckets.le_inf++;
73
+ buckets.sum += value;
74
+ buckets.count++;
75
+ this.recordMetric({
76
+ name,
77
+ type: 'histogram',
78
+ value,
79
+ labels,
80
+ timestamp: Date.now(),
81
+ });
82
+ }
83
+ // Convenience methods for common metrics
84
+ /**
85
+ * Record a request
86
+ */
87
+ recordRequest(tool, durationMs, success, cached = false) {
88
+ this.increment('drift_mcp_requests_total', {
89
+ tool,
90
+ success: String(success),
91
+ cached: String(cached),
92
+ });
93
+ this.observe('drift_mcp_request_duration_ms', durationMs, { tool });
94
+ if (cached) {
95
+ this.increment('drift_mcp_cache_hits_total', { tool });
96
+ }
97
+ else {
98
+ this.increment('drift_mcp_cache_misses_total', { tool });
99
+ }
100
+ }
101
+ /**
102
+ * Record an error
103
+ */
104
+ recordError(tool, errorCode) {
105
+ this.increment('drift_mcp_errors_total', { tool, errorCode });
106
+ }
107
+ /**
108
+ * Record token estimate
109
+ */
110
+ recordTokens(tool, tokens) {
111
+ this.observe('drift_mcp_response_tokens', tokens, { tool });
112
+ }
113
+ /**
114
+ * Record patterns queried
115
+ */
116
+ recordPatternsQueried(count, tool) {
117
+ this.increment('drift_mcp_patterns_queried_total', { tool }, count);
118
+ }
119
+ /**
120
+ * Get all metrics
121
+ */
122
+ getMetrics() {
123
+ return [...this.metrics];
124
+ }
125
+ /**
126
+ * Get summary statistics
127
+ */
128
+ getSummary() {
129
+ let totalRequests = 0;
130
+ let totalErrors = 0;
131
+ let cacheHits = 0;
132
+ let cacheMisses = 0;
133
+ const requestsByTool = {};
134
+ // Count requests
135
+ for (const [key, value] of this.counters) {
136
+ if (key.startsWith('drift_mcp_requests_total')) {
137
+ totalRequests += value;
138
+ // Extract tool from key
139
+ const toolMatch = key.match(/tool:(\w+)/);
140
+ if (toolMatch) {
141
+ const tool = toolMatch[1];
142
+ requestsByTool[tool] = (requestsByTool[tool] ?? 0) + value;
143
+ }
144
+ }
145
+ if (key.startsWith('drift_mcp_errors_total')) {
146
+ totalErrors += value;
147
+ }
148
+ if (key.startsWith('drift_mcp_cache_hits_total')) {
149
+ cacheHits += value;
150
+ }
151
+ if (key.startsWith('drift_mcp_cache_misses_total')) {
152
+ cacheMisses += value;
153
+ }
154
+ }
155
+ // Calculate averages from histograms
156
+ let totalDuration = 0;
157
+ let durationCount = 0;
158
+ let totalTokens = 0;
159
+ let tokenCount = 0;
160
+ for (const [key, buckets] of this.histograms) {
161
+ if (key.startsWith('drift_mcp_request_duration_ms')) {
162
+ totalDuration += buckets.sum;
163
+ durationCount += buckets.count;
164
+ }
165
+ if (key.startsWith('drift_mcp_response_tokens')) {
166
+ totalTokens += buckets.sum;
167
+ tokenCount += buckets.count;
168
+ }
169
+ }
170
+ return {
171
+ totalRequests,
172
+ totalErrors,
173
+ cacheHitRate: cacheHits + cacheMisses > 0
174
+ ? cacheHits / (cacheHits + cacheMisses)
175
+ : 0,
176
+ avgDurationMs: durationCount > 0 ? totalDuration / durationCount : 0,
177
+ avgTokens: tokenCount > 0 ? totalTokens / tokenCount : 0,
178
+ requestsByTool,
179
+ };
180
+ }
181
+ /**
182
+ * Export metrics in Prometheus format
183
+ */
184
+ toPrometheus() {
185
+ const lines = [];
186
+ // Counters
187
+ for (const [key, value] of this.counters) {
188
+ const { name, labels } = this.parseKey(key);
189
+ const labelStr = this.formatLabels(labels);
190
+ lines.push(`${name}${labelStr} ${value}`);
191
+ }
192
+ // Gauges
193
+ for (const [key, value] of this.gauges) {
194
+ const { name, labels } = this.parseKey(key);
195
+ const labelStr = this.formatLabels(labels);
196
+ lines.push(`${name}${labelStr} ${value}`);
197
+ }
198
+ // Histograms
199
+ for (const [key, buckets] of this.histograms) {
200
+ const { name, labels } = this.parseKey(key);
201
+ const labelStr = this.formatLabels(labels);
202
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '10')} ${buckets.le_10}`);
203
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '50')} ${buckets.le_50}`);
204
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '100')} ${buckets.le_100}`);
205
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '250')} ${buckets.le_250}`);
206
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '500')} ${buckets.le_500}`);
207
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '1000')} ${buckets.le_1000}`);
208
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '2500')} ${buckets.le_2500}`);
209
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '5000')} ${buckets.le_5000}`);
210
+ lines.push(`${name}_bucket${this.addLabel(labelStr, 'le', '+Inf')} ${buckets.le_inf}`);
211
+ lines.push(`${name}_sum${labelStr} ${buckets.sum}`);
212
+ lines.push(`${name}_count${labelStr} ${buckets.count}`);
213
+ }
214
+ return lines.join('\n');
215
+ }
216
+ /**
217
+ * Clear all metrics
218
+ */
219
+ clear() {
220
+ this.counters.clear();
221
+ this.gauges.clear();
222
+ this.histograms.clear();
223
+ this.metrics = [];
224
+ }
225
+ // Private methods
226
+ makeKey(name, labels) {
227
+ const labelParts = Object.entries(labels)
228
+ .filter(([, v]) => v !== undefined)
229
+ .sort(([a], [b]) => a.localeCompare(b))
230
+ .map(([k, v]) => `${k}:${v}`);
231
+ return labelParts.length > 0
232
+ ? `${name}{${labelParts.join(',')}}`
233
+ : name;
234
+ }
235
+ parseKey(key) {
236
+ const match = key.match(/^([^{]+)(?:\{(.+)\})?$/);
237
+ if (!match) {
238
+ return { name: key, labels: {} };
239
+ }
240
+ const name = match[1];
241
+ const labels = {};
242
+ if (match[2]) {
243
+ for (const part of match[2].split(',')) {
244
+ const [k, v] = part.split(':');
245
+ if (k && v) {
246
+ labels[k] = v;
247
+ }
248
+ }
249
+ }
250
+ return { name, labels };
251
+ }
252
+ formatLabels(labels) {
253
+ const parts = Object.entries(labels)
254
+ .filter(([, v]) => v !== undefined)
255
+ .map(([k, v]) => `${k}="${v}"`);
256
+ return parts.length > 0 ? `{${parts.join(',')}}` : '';
257
+ }
258
+ addLabel(labelStr, key, value) {
259
+ if (labelStr === '') {
260
+ return `{${key}="${value}"}`;
261
+ }
262
+ return labelStr.replace('}', `,${key}="${value}"}`);
263
+ }
264
+ createEmptyBuckets() {
265
+ return {
266
+ le_10: 0,
267
+ le_50: 0,
268
+ le_100: 0,
269
+ le_250: 0,
270
+ le_500: 0,
271
+ le_1000: 0,
272
+ le_2500: 0,
273
+ le_5000: 0,
274
+ le_inf: 0,
275
+ sum: 0,
276
+ count: 0,
277
+ };
278
+ }
279
+ recordMetric(metric) {
280
+ this.metrics.push(metric);
281
+ // Trim old metrics if over limit
282
+ if (this.metrics.length > this.maxMetrics) {
283
+ this.metrics = this.metrics.slice(-this.maxMetrics / 2);
284
+ }
285
+ }
286
+ }
287
+ /**
288
+ * Singleton instance for convenience
289
+ */
290
+ export const metrics = new MetricsCollector();
291
+ //# sourceMappingURL=metrics.js.map