@devilsdev/rag-pipeline-utils 2.6.1 → 2.7.0

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 (90) hide show
  1. package/BENCHMARKS.md +7 -1
  2. package/CHANGELOG.md +135 -0
  3. package/README.md +37 -24
  4. package/dist/index.cjs +4164 -1825
  5. package/dist/index.d.ts +265 -256
  6. package/dist/index.mjs +1 -1
  7. package/dist/types/cache/memory-cache.d.ts +4 -1
  8. package/dist/types/cache/redis-cache.d.ts +4 -1
  9. package/dist/types/cli/services/instrument.d.ts +14 -0
  10. package/dist/types/cli/services/rag-service.d.ts +140 -0
  11. package/dist/types/cli/shared/config-context.d.ts +9 -0
  12. package/dist/types/config/component-factory.d.ts +57 -0
  13. package/dist/types/config/enhanced-ragrc-schema.d.ts +648 -0
  14. package/dist/types/config/load-config.d.ts +18 -0
  15. package/dist/types/config/normalize-config.d.ts +9 -0
  16. package/dist/types/core/observability/event-logger.d.ts +211 -0
  17. package/dist/types/core/observability/metrics.d.ts +585 -0
  18. package/dist/types/core/performance/parallel-processor.d.ts +92 -0
  19. package/dist/types/core/plugin-registry.d.ts +5 -0
  20. package/dist/types/dag/core/execution-scheduler.d.ts +3 -1
  21. package/dist/types/dag/dag-engine.d.ts +15 -2
  22. package/dist/types/dev/dev-server.d.ts +136 -0
  23. package/dist/types/dev/hot-reload.d.ts +226 -0
  24. package/dist/types/ecosystem/plugin-analytics-dashboard.d.ts +141 -0
  25. package/dist/types/ecosystem/plugin-hub.d.ts +161 -0
  26. package/dist/types/ecosystem/plugin-installer.d.ts +40 -0
  27. package/dist/types/ecosystem/plugin-probe.d.ts +21 -0
  28. package/dist/types/ecosystem/plugin-scanner.d.ts +30 -0
  29. package/dist/types/ecosystem/tar-extract.d.ts +24 -0
  30. package/dist/types/enterprise/audit-logging.d.ts +217 -0
  31. package/dist/types/evaluate/compare.d.ts +140 -0
  32. package/dist/types/evaluate/dataset.d.ts +43 -0
  33. package/dist/types/evaluate/evaluator.d.ts +14 -0
  34. package/dist/types/evaluate/report.d.ts +56 -0
  35. package/dist/types/evaluate/synthetic.d.ts +64 -0
  36. package/dist/types/loader/csv-loader.d.ts +10 -0
  37. package/dist/types/loader/document-reader.d.ts +18 -0
  38. package/dist/types/loader/html-loader.d.ts +21 -0
  39. package/dist/types/loader/markdown-loader.d.ts +21 -0
  40. package/dist/types/retrieval/bm25-search.d.ts +4 -0
  41. package/dist/types/retrieval/file-vector-store.d.ts +4 -1
  42. package/dist/types/retrieval/hybrid-retriever.d.ts +4 -0
  43. package/dist/types/retrieval/pgvector-retriever.d.ts +123 -0
  44. package/dist/types/retrieval/qdrant-retriever.d.ts +106 -0
  45. package/dist/types/security/validator.d.ts +11 -1
  46. package/dist/types/testing.d.ts +2 -0
  47. package/dist/types/utils/batch-processor.d.ts +205 -0
  48. package/dist/types/utils/connection-pool.d.ts +158 -0
  49. package/dist/types/utils/error-formatter.d.ts +312 -0
  50. package/dist/types/utils/logger.d.ts +29 -4
  51. package/dist/types/utils/rate-limiter.d.ts +13 -8
  52. package/dist/types/utils/retry.d.ts +10 -0
  53. package/package.json +13 -3
  54. package/src/cache/memory-cache.js +4 -1
  55. package/src/cache/redis-cache.js +4 -1
  56. package/src/cli/enhanced-cli-commands.js +79 -0
  57. package/src/cli/handlers/ai-handler.js +2 -2
  58. package/src/cli/handlers/eval-handler.js +201 -0
  59. package/src/cli/handlers/generate-handler.js +103 -0
  60. package/src/cli/services/benchmark.js +2 -2
  61. package/src/cli/services/rag-service.js +59 -10
  62. package/src/cli/shared/cli-utils.js +40 -1
  63. package/src/config/component-factory.js +32 -0
  64. package/src/connectors/local-embedder.js +20 -13
  65. package/src/core/observability/event-logger.js +135 -1
  66. package/src/core/observability/metrics.js +223 -5
  67. package/src/core/performance/parallel-processor.js +2 -0
  68. package/src/core/plugin-registry.js +5 -1
  69. package/src/dag/core/execution-scheduler.js +2 -0
  70. package/src/dag/dag-engine.js +13 -0
  71. package/src/dev/dev-server.js +6 -0
  72. package/src/ecosystem/plugin-hub.js +4 -0
  73. package/src/enterprise/audit-logging.js +5 -0
  74. package/src/evaluate/compare.js +395 -0
  75. package/src/evaluate/dataset.js +207 -0
  76. package/src/evaluate/report.js +350 -0
  77. package/src/evaluate/synthetic.js +246 -0
  78. package/src/index.js +17 -0
  79. package/src/retrieval/bm25-search.js +4 -0
  80. package/src/retrieval/file-vector-store.js +4 -1
  81. package/src/retrieval/hybrid-retriever.js +4 -0
  82. package/src/retrieval/pgvector-retriever.js +420 -0
  83. package/src/retrieval/qdrant-retriever.js +361 -0
  84. package/src/security/validator.js +8 -0
  85. package/src/testing.js +2 -0
  86. package/src/utils/batch-processor.js +7 -3
  87. package/src/utils/error-formatter.js +48 -20
  88. package/src/utils/logger.js +31 -1
  89. package/src/utils/rate-limiter.js +9 -4
  90. package/src/utils/retry.js +10 -1
@@ -1,31 +1,72 @@
1
1
  'use strict';
2
2
 
3
+ /**
4
+ * Event type names used by PipelineEventLogger. The logger also emits
5
+ * 'stage.end' and 'memory.warning', which have no entry here.
6
+ * @type {{PLUGIN_START: string, PLUGIN_END: string, PLUGIN_ERROR: string, STAGE_START: string, STAGE_ERROR: string}}
7
+ */
3
8
  const EventTypes = {
9
+ /** A plugin call started. */
4
10
  PLUGIN_START: 'plugin.start',
11
+ /** A plugin call finished. */
5
12
  PLUGIN_END: 'plugin.end',
13
+ /** A plugin call failed. */
6
14
  PLUGIN_ERROR: 'plugin.error',
15
+ /** A pipeline stage started. */
7
16
  STAGE_START: 'stage.start',
17
+ /** A pipeline stage failed. Not emitted by PipelineEventLogger itself. */
8
18
  STAGE_ERROR: 'stage.error',
9
19
  };
10
20
 
11
- const EventSeverity = { DEBUG: 'debug', INFO: 'info', ERROR: 'error' };
21
+ /**
22
+ * Severity levels used by PipelineEventLogger. Memory warnings use 'warn',
23
+ * which has no entry here.
24
+ * @type {{DEBUG: string, INFO: string, ERROR: string}}
25
+ */
26
+ const EventSeverity = {
27
+ /** Plugin start and end events. */
28
+ DEBUG: 'debug',
29
+ /** Stage events. */
30
+ INFO: 'info',
31
+ /** Plugin errors. */
32
+ ERROR: 'error',
33
+ };
12
34
 
35
+ /**
36
+ * In-memory log of pipeline events (plugin and stage lifecycle, memory
37
+ * warnings, custom events) tagged with a session id. A session is started
38
+ * on the first event if startSession was not called.
39
+ */
13
40
  class PipelineEventLogger {
14
41
  constructor() {
15
42
  this._events = [];
16
43
  this._sessionId = null;
17
44
  }
18
45
 
46
+ /**
47
+ * Start a new session with a fresh id and start time. Existing events are kept.
48
+ * @returns {string} The new session id
49
+ */
19
50
  startSession() {
20
51
  this._sessionId = `session_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`;
21
52
  this._sessionStartTime = new Date().toISOString();
22
53
  return this._sessionId;
23
54
  }
24
55
 
56
+ /**
57
+ * Current time as an ISO 8601 string.
58
+ * @returns {string}
59
+ */
25
60
  nowISO() {
26
61
  return new Date().toISOString();
27
62
  }
28
63
 
64
+ /**
65
+ * Describe a value's size: length for arrays and strings, key count for
66
+ * objects, type only for null and primitives.
67
+ * @param {*} v - Value to describe
68
+ * @returns {{type: string, length?: number, keys?: number}}
69
+ */
29
70
  getInputSize(v) {
30
71
  if (Array.isArray(v)) return { type: 'array', length: v.length };
31
72
  if (typeof v === 'string') return { type: 'string', length: v.length };
@@ -34,10 +75,24 @@ class PipelineEventLogger {
34
75
  return { type: 'object', keys: Object.keys(v).length };
35
76
  return { type: typeof v };
36
77
  }
78
+ /**
79
+ * Same as getInputSize.
80
+ * @param {*} v - Value to describe
81
+ * @returns {{type: string, length?: number, keys?: number}}
82
+ */
37
83
  getResultSize(v) {
38
84
  return this.getInputSize(v);
39
85
  }
40
86
 
87
+ /**
88
+ * Record a debug-level plugin.start event with the input size and process info.
89
+ * @param {Object} event
90
+ * @param {string} event.pluginType - Plugin type, such as embedder or retriever
91
+ * @param {string} event.pluginName - Plugin name
92
+ * @param {*} [event.input] - Plugin input; only its size is recorded
93
+ * @param {Object<string, *>} [event.context={}] - Extra metadata
94
+ * @returns {void}
95
+ */
41
96
  logPluginStart({ pluginType, pluginName, input, context = {} }) {
42
97
  this._events.push({
43
98
  timestamp: this.nowISO(),
@@ -58,6 +113,18 @@ class PipelineEventLogger {
58
113
  });
59
114
  }
60
115
 
116
+ /**
117
+ * Record a debug-level plugin.end event. When the result is an array, or
118
+ * has a vectors array, its length is recorded as resultSize.vectorCount.
119
+ * @param {Object} event
120
+ * @param {string} event.pluginType - Plugin type
121
+ * @param {string} event.pluginName - Plugin name
122
+ * @param {number} [event.duration] - Duration in milliseconds
123
+ * @param {*} [event.result] - Plugin result; only its length is recorded
124
+ * @param {string} [event.status='success'] - Outcome
125
+ * @param {Object<string, *>} [event.context={}] - Extra metadata
126
+ * @returns {void}
127
+ */
61
128
  logPluginEnd({
62
129
  pluginType,
63
130
  pluginName,
@@ -92,6 +159,16 @@ class PipelineEventLogger {
92
159
  });
93
160
  }
94
161
 
162
+ /**
163
+ * Record an error-level plugin.error event with the error's name, message and code.
164
+ * @param {Object} event
165
+ * @param {string} event.pluginType - Plugin type
166
+ * @param {string} event.pluginName - Plugin name
167
+ * @param {number} [event.duration] - Duration in milliseconds
168
+ * @param {Error & {code?: string}} [event.error] - The error thrown
169
+ * @param {Object<string, *>} [event.context={}] - Extra metadata
170
+ * @returns {void}
171
+ */
95
172
  logPluginError({ pluginType, pluginName, duration, error, context = {} }) {
96
173
  this._events.push({
97
174
  timestamp: this.nowISO(),
@@ -116,6 +193,11 @@ class PipelineEventLogger {
116
193
  });
117
194
  }
118
195
 
196
+ /**
197
+ * Record an info-level stage.start event.
198
+ * @param {string} stage - Stage name
199
+ * @returns {void}
200
+ */
119
201
  logStageStart(stage) {
120
202
  this._events.push({
121
203
  timestamp: this.nowISO(),
@@ -132,6 +214,14 @@ class PipelineEventLogger {
132
214
  });
133
215
  }
134
216
 
217
+ /**
218
+ * Record a warn-level memory.warning event. usagePercentage is heapUsed
219
+ * (or rss if heapUsed is missing) in MB as a percentage of threshold.
220
+ * @param {Object} event
221
+ * @param {{heapUsed?: number, rss?: number}} event.memoryUsage - Memory figures in bytes, as from process.memoryUsage()
222
+ * @param {number} [event.threshold=512] - Threshold in MB
223
+ * @returns {void}
224
+ */
135
225
  logMemoryWarning({ memoryUsage, threshold = 512 }) {
136
226
  const usedBytes =
137
227
  typeof memoryUsage?.heapUsed === 'number'
@@ -152,6 +242,17 @@ class PipelineEventLogger {
152
242
  });
153
243
  }
154
244
 
245
+ /**
246
+ * Recorded events, oldest first, optionally filtered.
247
+ * @param {Object} [filters]
248
+ * @param {string} [filters.eventType]
249
+ * @param {string} [filters.severity]
250
+ * @param {string} [filters.pluginType]
251
+ * @param {string|number|Date} [filters.since] - Only events at or after this time
252
+ * @param {string|number|Date} [filters.until] - Only events at or before this time
253
+ * @param {number} [filters.limit] - Keep only the most recent `limit` events
254
+ * @returns {Object[]}
255
+ */
155
256
  getEventHistory({
156
257
  eventType,
157
258
  severity,
@@ -181,6 +282,11 @@ class PipelineEventLogger {
181
282
  return list;
182
283
  }
183
284
 
285
+ /**
286
+ * Serialize the session id and the events matching the filters.
287
+ * @param {Object} [filters] - Same filters as getEventHistory
288
+ * @returns {string} JSON string with sessionId, eventCount and events
289
+ */
184
290
  exportEvents(filters) {
185
291
  const filtered = this.getEventHistory(filters);
186
292
  return JSON.stringify({
@@ -190,6 +296,14 @@ class PipelineEventLogger {
190
296
  });
191
297
  }
192
298
 
299
+ /**
300
+ * Record an event of any type.
301
+ * @param {string} eventType - Event type
302
+ * @param {string} severity - Severity level
303
+ * @param {Object<string, *>} [metadata={}] - Event metadata
304
+ * @param {string} [message] - Message; defaults to 'Event: ' plus the event type
305
+ * @returns {this}
306
+ */
193
307
  logEvent(eventType, severity, metadata = {}, message) {
194
308
  this._events.push({
195
309
  timestamp: this.nowISO(),
@@ -202,11 +316,22 @@ class PipelineEventLogger {
202
316
  return this;
203
317
  }
204
318
 
319
+ /**
320
+ * Remove all recorded events. The session id is kept.
321
+ * @returns {this}
322
+ */
205
323
  clearHistory() {
206
324
  this._events = [];
207
325
  return this;
208
326
  }
209
327
 
328
+ /**
329
+ * Record an info-level stage.end event.
330
+ * @param {string} stage - Stage name
331
+ * @param {number} duration - Duration in milliseconds
332
+ * @param {Object<string, *>} [metadata={}] - Extra metadata merged into the event metadata
333
+ * @returns {this}
334
+ */
210
335
  logStageEnd(stage, duration, metadata = {}) {
211
336
  this._events.push({
212
337
  timestamp: this.nowISO(),
@@ -224,10 +349,19 @@ class PipelineEventLogger {
224
349
  return this;
225
350
  }
226
351
 
352
+ /**
353
+ * Current session id. Starts a session if none is active.
354
+ * @returns {string}
355
+ */
227
356
  get sessionId() {
228
357
  return this._sessionId || this.startSession();
229
358
  }
230
359
 
360
+ /**
361
+ * Session id, total event count, session start time and the distinct event
362
+ * types recorded. Starts a session if none is active.
363
+ * @returns {{sessionId: string, totalEvents: number, startTime: string, eventTypes: string[]}}
364
+ */
231
365
  getSessionStats() {
232
366
  return {
233
367
  sessionId: this.sessionId,
@@ -5,8 +5,13 @@ const MetricType = {
5
5
  GAUGE: 'gauge',
6
6
  };
7
7
 
8
- /** Counter */
8
+ /** Monotonic counter that only goes up until reset. */
9
9
  class Counter {
10
+ /**
11
+ * @param {string} name - Metric name
12
+ * @param {string} [description=''] - Human-readable description
13
+ * @param {Object<string, string>} [labels={}] - Static labels attached to the metric
14
+ */
10
15
  constructor(name, description = '', labels = {}) {
11
16
  this._type = MetricType.COUNTER;
12
17
  this.name = name;
@@ -14,14 +19,28 @@ class Counter {
14
19
  this.labels = labels || {};
15
20
  this.value = 0;
16
21
  }
22
+ /**
23
+ * Add to the counter.
24
+ * @param {number} [n=1] - Amount to add
25
+ * @returns {void}
26
+ * @throws {Error} If n is negative
27
+ */
17
28
  inc(n = 1) {
18
29
  if (n < 0)
19
30
  throw new Error('Counter can only be incremented by non-negative values');
20
31
  this.value += n;
21
32
  }
33
+ /**
34
+ * Set the value back to 0.
35
+ * @returns {void}
36
+ */
22
37
  reset() {
23
38
  this.value = 0;
24
39
  }
40
+ /**
41
+ * Snapshot of the metric with the current time as timestamp.
42
+ * @returns {{name: string, description: string, type: string, value: number, labels: Object<string, string>, timestamp: string}}
43
+ */
25
44
  toJSON() {
26
45
  return {
27
46
  name: this.name,
@@ -34,8 +53,13 @@ class Counter {
34
53
  }
35
54
  }
36
55
 
37
- /** Gauge */
56
+ /** Gauge holding a value that can be set, raised or lowered. */
38
57
  class Gauge {
58
+ /**
59
+ * @param {string} name - Metric name
60
+ * @param {string} [description=''] - Human-readable description
61
+ * @param {Object<string, string>} [labels={}] - Static labels attached to the metric
62
+ */
39
63
  constructor(name, description = '', labels = {}) {
40
64
  this._type = MetricType.GAUGE;
41
65
  this.name = name;
@@ -43,18 +67,41 @@ class Gauge {
43
67
  this.labels = labels || {};
44
68
  this.value = 0;
45
69
  }
70
+ /**
71
+ * Set the value.
72
+ * @param {number} v - New value
73
+ * @returns {void}
74
+ */
46
75
  set(v) {
47
76
  this.value = v;
48
77
  }
78
+ /**
79
+ * Add to the value.
80
+ * @param {number} [n=1] - Amount to add
81
+ * @returns {void}
82
+ */
49
83
  inc(n = 1) {
50
84
  this.value += n;
51
85
  }
86
+ /**
87
+ * Subtract from the value.
88
+ * @param {number} [n=1] - Amount to subtract
89
+ * @returns {void}
90
+ */
52
91
  dec(n = 1) {
53
92
  this.value -= n;
54
93
  }
94
+ /**
95
+ * Set the value back to 0.
96
+ * @returns {void}
97
+ */
55
98
  reset() {
56
99
  this.value = 0;
57
100
  }
101
+ /**
102
+ * Snapshot of the metric with the current time as timestamp.
103
+ * @returns {{name: string, description: string, type: string, value: number, labels: Object<string, string>, timestamp: string}}
104
+ */
58
105
  toJSON() {
59
106
  return {
60
107
  name: this.name,
@@ -67,8 +114,17 @@ class Gauge {
67
114
  }
68
115
  }
69
116
 
70
- /** Histogram with cumulative bucketCounts and raw observations for stats/percentiles */
117
+ /**
118
+ * Histogram with cumulative bucket counts. It also keeps every observed value
119
+ * in memory to compute percentiles and standard deviation.
120
+ */
71
121
  class Histogram {
122
+ /**
123
+ * @param {string} name - Metric name
124
+ * @param {string} [description=''] - Human-readable description
125
+ * @param {Object<string, string>} [labels={}] - Static labels attached to the metric
126
+ * @param {number[]} [buckets] - Bucket upper bounds, sorted ascending on construction. A +Inf bucket is added.
127
+ */
72
128
  constructor(
73
129
  name,
74
130
  description = '',
@@ -88,6 +144,11 @@ class Histogram {
88
144
  this._obs = [];
89
145
  }
90
146
 
147
+ /**
148
+ * Record a value. Non-numbers and NaN are ignored.
149
+ * @param {number} v - Observed value
150
+ * @returns {void}
151
+ */
91
152
  observe(v) {
92
153
  if (typeof v !== 'number' || Number.isNaN(v)) return;
93
154
  this._obs.push(v);
@@ -105,6 +166,12 @@ class Histogram {
105
166
  this.bucketCounts[i] += 1;
106
167
  }
107
168
 
169
+ /**
170
+ * Percentiles of the observed values by the nearest-rank method. Returns 0
171
+ * for each percentile when nothing has been observed.
172
+ * @param {number[]} [percentiles=[50, 95, 99]] - Percentiles to compute, 0-100
173
+ * @returns {Object<number, number>} Value for each requested percentile
174
+ */
108
175
  getPercentiles(percentiles = [50, 95, 99]) {
109
176
  if (this._obs.length === 0)
110
177
  return Object.fromEntries(percentiles.map((p) => [p, 0]));
@@ -121,6 +188,11 @@ class Histogram {
121
188
  return out;
122
189
  }
123
190
 
191
+ /**
192
+ * Mean, population standard deviation, min, max, count and sum of the
193
+ * observed values. With no observations, min is Infinity and max is -Infinity.
194
+ * @returns {{mean: number, stdDev: number, min: number, max: number, count: number, sum: number}}
195
+ */
124
196
  getStatistics() {
125
197
  if (this.count === 0) {
126
198
  return {
@@ -147,6 +219,10 @@ class Histogram {
147
219
  };
148
220
  }
149
221
 
222
+ /**
223
+ * Clear all bucket counts, statistics and stored observations.
224
+ * @returns {void}
225
+ */
150
226
  reset() {
151
227
  this.bucketCounts.fill(0);
152
228
  this.sum = 0;
@@ -155,6 +231,10 @@ class Histogram {
155
231
  this.max = -Infinity;
156
232
  this._obs = [];
157
233
  }
234
+ /**
235
+ * Cumulative count per bucket bound (plus '+Inf') together with getStatistics().
236
+ * @returns {{buckets: Object<string, number>, mean: number, stdDev: number, min: number, max: number, count: number, sum: number}}
237
+ */
158
238
  export() {
159
239
  // Map bucket value -> cumulative count
160
240
  const bucketsObj = {};
@@ -164,6 +244,11 @@ class Histogram {
164
244
  const stats = this.getStatistics();
165
245
  return { buckets: bucketsObj, ...stats };
166
246
  }
247
+ /**
248
+ * Snapshot of the histogram with the current time as timestamp. Does not
249
+ * include min, max or percentiles.
250
+ * @returns {{name: string, description: string, type: string, count: number, sum: number, buckets: number[], bucketCounts: number[], labels: Object<string, string>, timestamp: string}}
251
+ */
167
252
  toJSON() {
168
253
  return {
169
254
  name: this.name,
@@ -179,11 +264,17 @@ class Histogram {
179
264
  }
180
265
  }
181
266
 
182
- /** Metrics registry (simple) */
267
+ /** Registry of Counter, Histogram and Gauge instances keyed by name. */
183
268
  class MetricsRegistry {
184
269
  constructor() {
185
270
  this._metrics = new Map(); // name -> metric instance
186
271
  }
272
+ /**
273
+ * Add a metric under its name.
274
+ * @param {Counter|Histogram|Gauge} metric - Metric to register
275
+ * @returns {void}
276
+ * @throws {Error} If a metric with the same name is already registered
277
+ */
187
278
  register(metric) {
188
279
  if (this._metrics.has(metric.name)) {
189
280
  throw new Error(
@@ -192,15 +283,36 @@ class MetricsRegistry {
192
283
  }
193
284
  this._metrics.set(metric.name, metric);
194
285
  }
286
+ /**
287
+ * Look up a metric by name.
288
+ * @param {string} name - Metric name
289
+ * @returns {Counter|Histogram|Gauge|undefined} The metric, or undefined if not registered
290
+ */
195
291
  getMetric(name) {
196
292
  return this._metrics.get(name);
197
293
  }
294
+ /**
295
+ * All registered metrics in registration order.
296
+ * @returns {Array<Counter|Histogram|Gauge>}
297
+ */
198
298
  getAllMetrics() {
199
299
  return Array.from(this._metrics.values());
200
300
  }
301
+ /**
302
+ * Remove every registered metric.
303
+ * @returns {void}
304
+ */
201
305
  clear() {
202
306
  this._metrics.clear();
203
307
  }
308
+ /**
309
+ * Return the metric registered under name, or create and register a Counter.
310
+ * An existing metric is returned as is, even if it is not a Counter.
311
+ * @param {string} name - Metric name
312
+ * @param {string} [description] - Description for a new counter
313
+ * @param {Object<string, string>} [labels={}] - Labels for a new counter
314
+ * @returns {Counter}
315
+ */
204
316
  getOrCreateCounter(name, description, labels = {}) {
205
317
  if (this._metrics.has(name)) {
206
318
  return this._metrics.get(name);
@@ -209,6 +321,15 @@ class MetricsRegistry {
209
321
  this.register(counter);
210
322
  return counter;
211
323
  }
324
+ /**
325
+ * Return the metric registered under name, or create and register a
326
+ * Histogram. An existing metric is returned as is, even if it is not a Histogram.
327
+ * @param {string} name - Metric name
328
+ * @param {string} [description] - Description for a new histogram
329
+ * @param {Object<string, string>} [labels={}] - Labels for a new histogram
330
+ * @param {number[]} [buckets] - Bucket bounds for a new histogram
331
+ * @returns {Histogram}
332
+ */
212
333
  getOrCreateHistogram(name, description, labels = {}, buckets) {
213
334
  if (this._metrics.has(name)) {
214
335
  return this._metrics.get(name);
@@ -217,6 +338,14 @@ class MetricsRegistry {
217
338
  this.register(histogram);
218
339
  return histogram;
219
340
  }
341
+ /**
342
+ * Return the metric registered under name, or create and register a Gauge.
343
+ * An existing metric is returned as is, even if it is not a Gauge.
344
+ * @param {string} name - Metric name
345
+ * @param {string} [description] - Description for a new gauge
346
+ * @param {Object<string, string>} [labels={}] - Labels for a new gauge
347
+ * @returns {Gauge}
348
+ */
220
349
  getOrCreateGauge(name, description, labels = {}) {
221
350
  if (this._metrics.has(name)) {
222
351
  return this._metrics.get(name);
@@ -225,6 +354,10 @@ class MetricsRegistry {
225
354
  this.register(gauge);
226
355
  return gauge;
227
356
  }
357
+ /**
358
+ * Serialize all metrics (their toJSON output) with a timestamp.
359
+ * @returns {string} JSON string with timestamp and metrics fields
360
+ */
228
361
  exportMetrics() {
229
362
  return JSON.stringify({
230
363
  timestamp: new Date().toISOString(),
@@ -233,7 +366,10 @@ class MetricsRegistry {
233
366
  }
234
367
  }
235
368
 
236
- /** Pipeline-level convenience aggregator used by tests */
369
+ /**
370
+ * In-memory totals for pipeline operations: embedding, retrieval and LLM
371
+ * calls, errors, operation counts, concurrency, backpressure and heap usage.
372
+ */
237
373
  class PipelineMetrics {
238
374
  constructor() {
239
375
  this.counters = {
@@ -279,6 +415,14 @@ class PipelineMetrics {
279
415
  this.concurrency = { maxConcurrency: 0, concurrencyValues: [] };
280
416
  }
281
417
 
418
+ /**
419
+ * Record one embedding call.
420
+ * @param {string} provider - Provider name (unused)
421
+ * @param {number} duration - Duration in milliseconds
422
+ * @param {number} tokens - Tokens embedded
423
+ * @param {number} batches - Batches sent
424
+ * @returns {void}
425
+ */
282
426
  recordEmbedding(provider, duration, tokens, batches) {
283
427
  this.embedding.operations++;
284
428
  this.embedding.totalDuration += duration;
@@ -287,6 +431,13 @@ class PipelineMetrics {
287
431
  this.embedding.durations.push(duration);
288
432
  }
289
433
 
434
+ /**
435
+ * Record one retrieval call.
436
+ * @param {string} provider - Provider name (unused)
437
+ * @param {number} duration - Duration in milliseconds
438
+ * @param {number} results - Number of results returned
439
+ * @returns {void}
440
+ */
290
441
  recordRetrieval(provider, duration, results) {
291
442
  this.retrieval.operations++;
292
443
  this.retrieval.totalDuration += duration;
@@ -294,6 +445,15 @@ class PipelineMetrics {
294
445
  this.retrieval.durations.push(duration);
295
446
  }
296
447
 
448
+ /**
449
+ * Record one LLM call.
450
+ * @param {string} provider - Provider name (unused)
451
+ * @param {number} duration - Duration in milliseconds
452
+ * @param {number} inputTokens - Prompt tokens
453
+ * @param {number} outputTokens - Completion tokens
454
+ * @param {boolean} [streaming] - Whether the call streamed its output
455
+ * @returns {void}
456
+ */
297
457
  recordLLM(provider, duration, inputTokens, outputTokens, streaming) {
298
458
  this.llm.operations++;
299
459
  this.llm.totalDuration += duration;
@@ -305,6 +465,11 @@ class PipelineMetrics {
305
465
  this.llm.outputTokens.push(outputTokens);
306
466
  }
307
467
 
468
+ /**
469
+ * Store heapUsed and heapTotal from process.memoryUsage() and the used
470
+ * percentage, rounded.
471
+ * @returns {void}
472
+ */
308
473
  recordMemoryUsage() {
309
474
  const memUsage = process.memoryUsage();
310
475
  this.memory.heapUsed = memUsage.heapUsed;
@@ -314,6 +479,15 @@ class PipelineMetrics {
314
479
  );
315
480
  }
316
481
 
482
+ /**
483
+ * Count an error by type and by component. Only the types 'plugin' and
484
+ * 'stage' are counted by type; other types are counted only by component.
485
+ * @param {string} type - Error type, 'plugin' or 'stage'
486
+ * @param {string} [component] - Plugin or component name
487
+ * @param {string} [provider] - Provider name (unused)
488
+ * @param {Error} [error] - The error (unused)
489
+ * @returns {void}
490
+ */
317
491
  recordError(type, component, provider, error) {
318
492
  if (type && type in this.errorsByType) this.errorsByType[type]++;
319
493
  if (component)
@@ -321,11 +495,28 @@ class PipelineMetrics {
321
495
  (this.errorsByPlugin[component] || 0) + 1;
322
496
  }
323
497
 
498
+ /**
499
+ * Count an operation as started and active.
500
+ * @param {string} [type] - Operation type (unused)
501
+ * @param {string} [component] - Component name (unused)
502
+ * @param {string} [provider] - Provider name (unused)
503
+ * @returns {void}
504
+ */
324
505
  recordOperationStart(type, component, provider) {
325
506
  this.counters.operationsTotal.inc(1);
326
507
  this.counters.operationsActive.inc(1);
327
508
  }
328
509
 
510
+ /**
511
+ * Mark an active operation as finished. A status of 'error' or 'failed'
512
+ * counts as failed; any other status counts as successful.
513
+ * @param {string} [type] - Operation type (unused)
514
+ * @param {string} [component] - Component name (unused)
515
+ * @param {string} [provider] - Provider name (unused)
516
+ * @param {number} [duration] - Duration in milliseconds (unused)
517
+ * @param {string} [status] - Outcome of the operation
518
+ * @returns {void}
519
+ */
329
520
  recordOperationEnd(type, component, provider, duration, status) {
330
521
  this.counters.operationsActive.value = Math.max(
331
522
  0,
@@ -336,6 +527,12 @@ class PipelineMetrics {
336
527
  else this.counters.operationsSuccessful.inc(1);
337
528
  }
338
529
 
530
+ /**
531
+ * Record a concurrency sample. Keeps the highest max seen and every average.
532
+ * @param {number} maxConcurrency - Peak concurrency in the sample
533
+ * @param {number} avgConcurrency - Average concurrency in the sample
534
+ * @returns {void}
535
+ */
339
536
  recordConcurrency(maxConcurrency, avgConcurrency) {
340
537
  this.concurrency.maxConcurrency = Math.max(
341
538
  this.concurrency.maxConcurrency,
@@ -344,6 +541,13 @@ class PipelineMetrics {
344
541
  this.concurrency.concurrencyValues.push(avgConcurrency);
345
542
  }
346
543
 
544
+ /**
545
+ * Count a backpressure event and keep the buffer size as a sample.
546
+ * @param {string} action - 'applied' or 'released'; other values are not counted
547
+ * @param {number} [bufferSize] - Buffer size at the time of the event
548
+ * @param {number} [threshold] - Backpressure threshold (unused)
549
+ * @returns {void}
550
+ */
347
551
  recordBackpressure(action, bufferSize, threshold) {
348
552
  if (action === 'applied') this.backpressureApplied++;
349
553
  if (action === 'released') this.backpressureReleased++;
@@ -351,6 +555,11 @@ class PipelineMetrics {
351
555
  this.backpressureSamples.push(bufferSize);
352
556
  }
353
557
 
558
+ /**
559
+ * Totals and averages for every recorded category. Averages are 0 when
560
+ * nothing was recorded.
561
+ * @returns Summary grouped by embedding, retrieval, llm, memory, errors, operations, concurrency and backpressure
562
+ */
354
563
  getSummary() {
355
564
  const backpressureMean = this.backpressureSamples.length
356
565
  ? this.backpressureSamples.reduce((a, b) => a + b, 0) /
@@ -426,6 +635,10 @@ class PipelineMetrics {
426
635
  };
427
636
  }
428
637
 
638
+ /**
639
+ * getSummary() plus the raw recorded values, with a timestamp.
640
+ * @returns Object with timestamp, summary and rawMetrics
641
+ */
429
642
  exportMetrics() {
430
643
  return {
431
644
  timestamp: new Date().toISOString(),
@@ -447,6 +660,10 @@ class PipelineMetrics {
447
660
  };
448
661
  }
449
662
 
663
+ /**
664
+ * Reset every counter, total and sample to its initial value.
665
+ * @returns {void}
666
+ */
450
667
  clearMetrics() {
451
668
  this.counters.operationsTotal.reset();
452
669
  this.counters.operationsSuccessful.reset();
@@ -485,6 +702,7 @@ class PipelineMetrics {
485
702
  }
486
703
  }
487
704
 
705
+ /** Shared PipelineMetrics instance. */
488
706
  const pipelineMetrics = new PipelineMetrics();
489
707
 
490
708
  module.exports = {