@devilsdev/rag-pipeline-utils 2.4.2 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BENCHMARKS.md +338 -0
- package/CHANGELOG.md +131 -0
- package/README.md +7 -0
- package/SECURITY.md +80 -0
- package/SEMVER.md +184 -0
- package/package.json +7 -3
package/BENCHMARKS.md
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
# Benchmarks
|
|
2
|
+
|
|
3
|
+
This document describes **how we measure** performance in
|
|
4
|
+
`@devilsdev/rag-pipeline-utils` and **how you reproduce the numbers**
|
|
5
|
+
yourself. It deliberately does not publish a headline "N ops/sec" figure.
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
Benchmark numbers that are not reproducible are marketing, not engineering.
|
|
10
|
+
RAG pipelines are particularly sensitive to factors outside the framework:
|
|
11
|
+
embedding model choice, vector store, LLM provider and region, corpus
|
|
12
|
+
size, query distribution, and hardware. A single number hides all of
|
|
13
|
+
that.
|
|
14
|
+
|
|
15
|
+
Instead, we ship:
|
|
16
|
+
|
|
17
|
+
- A **deterministic, in-process benchmark suite** that measures framework
|
|
18
|
+
overhead — DAG execution, retry policies, logging, memory patterns.
|
|
19
|
+
These numbers are comparable across runs on the same hardware and
|
|
20
|
+
make regressions easy to catch.
|
|
21
|
+
- A **methodology and reference harness** that lets you benchmark your
|
|
22
|
+
own end-to-end pipeline with your actual provider, data, and hardware.
|
|
23
|
+
These are the only numbers that matter for your workload.
|
|
24
|
+
|
|
25
|
+
When you need a headline number for a decision, generate it on the
|
|
26
|
+
system you'll deploy to, with the providers you'll actually use.
|
|
27
|
+
|
|
28
|
+
## What the suite measures
|
|
29
|
+
|
|
30
|
+
The built-in suite (`scripts/benchmark.js`) exercises **framework
|
|
31
|
+
overhead only**. Every benchmark is in-process, network-free, and
|
|
32
|
+
deterministic up to GC and OS jitter.
|
|
33
|
+
|
|
34
|
+
| Category | What it measures | Why it matters |
|
|
35
|
+
| ----------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------------------ |
|
|
36
|
+
| **DAG execution** (5 / 10 / 25 / 50 nodes) | Linear chain of async nodes, cold and warm | Baseline overhead of the pipeline orchestrator |
|
|
37
|
+
| **Concurrent DAG** (1 / 2 / 5 / 10 parallelism) | Tree of 20 nodes with configurable concurrency | How well the engine scales intra-query parallelism |
|
|
38
|
+
| **Retry policies** (none / conservative / aggressive) | Simulated 30% failure rate, retries with jittered backoff | Cost of reliability guarantees on the happy path |
|
|
39
|
+
| **Structured logging** (JSON / console / correlated) | Single log call with contextual payload | Per-log-line overhead when observability is on |
|
|
40
|
+
| **Memory allocation** | Array + Map + Set construction and processing | Establishes a memory-pressure floor to compare against |
|
|
41
|
+
| **CPU intensive** | Fibonacci + JSON round-trip + string ops | Sanity check against the hosting CPU |
|
|
42
|
+
|
|
43
|
+
Each benchmark reports:
|
|
44
|
+
|
|
45
|
+
- `mean`, `median`, `min`, `max` latency (ms)
|
|
46
|
+
- `p95`, `p99` latency (ms)
|
|
47
|
+
- `standardDeviation` (ms)
|
|
48
|
+
- `throughput` (ops/sec)
|
|
49
|
+
- `memory.avgDeltaHeapUsed`, `memory.peakHeapUsed`
|
|
50
|
+
- `successRate` (%) and `errors` count
|
|
51
|
+
|
|
52
|
+
All measurements include a warmup phase (default 10 iterations) and use
|
|
53
|
+
`perf_hooks.performance.now()` for timing. If the Node process is
|
|
54
|
+
started with `--expose-gc`, the suite forces a GC before each run.
|
|
55
|
+
|
|
56
|
+
## What the suite does **not** measure
|
|
57
|
+
|
|
58
|
+
The built-in suite does not exercise:
|
|
59
|
+
|
|
60
|
+
- **Embedder throughput** — provider- and model-dependent
|
|
61
|
+
- **Retrieval latency** — vector store, index size, and network bound
|
|
62
|
+
- **LLM inference latency** — model, region, and token-count bound
|
|
63
|
+
- **End-to-end query latency** — dominated by the three above
|
|
64
|
+
- **Cost per query** — provider pricing + token usage
|
|
65
|
+
|
|
66
|
+
These are intentional omissions. Claiming a number here without
|
|
67
|
+
disclosing the full stack would be misleading. Use the
|
|
68
|
+
**end-to-end harness template** below to measure them against your
|
|
69
|
+
actual stack.
|
|
70
|
+
|
|
71
|
+
## Running the suite
|
|
72
|
+
|
|
73
|
+
Three presets ship in `package.json`:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# 20 iterations per benchmark — fast sanity check (~30s)
|
|
77
|
+
npm run benchmark:quick
|
|
78
|
+
|
|
79
|
+
# 100 iterations, verbose — default (~2 min)
|
|
80
|
+
npm run benchmark
|
|
81
|
+
|
|
82
|
+
# 500 iterations, verbose — release-gate quality (~8 min)
|
|
83
|
+
npm run benchmark:full
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Direct invocation:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
node scripts/benchmark.js \
|
|
90
|
+
--iterations 200 \
|
|
91
|
+
--output ./my-results \
|
|
92
|
+
--verbose
|
|
93
|
+
|
|
94
|
+
# With deterministic GC
|
|
95
|
+
node --expose-gc scripts/benchmark.js --iterations 200
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Results are written to `./benchmark-results/`:
|
|
99
|
+
|
|
100
|
+
- `latest.json` — most recent run
|
|
101
|
+
- `benchmark-<timestamp>.json` — archived run
|
|
102
|
+
|
|
103
|
+
A human-readable summary is printed to stdout on completion.
|
|
104
|
+
|
|
105
|
+
## Environment disclosure template
|
|
106
|
+
|
|
107
|
+
When sharing benchmark numbers (issue reports, blog posts, PR descriptions),
|
|
108
|
+
include the following so they're interpretable:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
Package: @devilsdev/rag-pipeline-utils@<version>
|
|
112
|
+
Node: <version> (v8 <version>)
|
|
113
|
+
OS: <distro/version>, kernel <version>
|
|
114
|
+
CPU: <model>, <cores> cores, <base/boost GHz>
|
|
115
|
+
Memory: <total GB>
|
|
116
|
+
Storage: <NVMe/SSD/HDD>, <filesystem>
|
|
117
|
+
Container: <bare-metal / Docker / K8s / Lambda / etc.>
|
|
118
|
+
Providers: embedder=<…>, retriever=<…>, llm=<…>
|
|
119
|
+
Corpus: <N documents, total tokens, chunk size>
|
|
120
|
+
Query set: <N queries, source>
|
|
121
|
+
Iterations: <N>, warmup: <N>
|
|
122
|
+
GC control: --expose-gc=<yes/no>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
The JSON report already captures `nodeVersion`, `platform`, `arch`,
|
|
126
|
+
`cpus`, `totalMemory`, and `loadAverage` automatically in its
|
|
127
|
+
`environment` block.
|
|
128
|
+
|
|
129
|
+
## Report schema
|
|
130
|
+
|
|
131
|
+
Each run produces a JSON document of the shape:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"timestamp": "2026-04-16T22:00:00.000Z",
|
|
136
|
+
"environment": {
|
|
137
|
+
"nodeVersion": "v20.x.x",
|
|
138
|
+
"platform": "linux",
|
|
139
|
+
"arch": "x64",
|
|
140
|
+
"cpus": 8,
|
|
141
|
+
"totalMemory": "16384MB",
|
|
142
|
+
"loadAverage": [0.12, 0.08, 0.05]
|
|
143
|
+
},
|
|
144
|
+
"benchmarks": {
|
|
145
|
+
"DAG execution (10 nodes)": {
|
|
146
|
+
"iterations": 100,
|
|
147
|
+
"errors": 0,
|
|
148
|
+
"successRate": 100,
|
|
149
|
+
"timing": {
|
|
150
|
+
"mean": 0.0,
|
|
151
|
+
"median": 0.0,
|
|
152
|
+
"min": 0.0,
|
|
153
|
+
"max": 0.0,
|
|
154
|
+
"p95": 0.0,
|
|
155
|
+
"p99": 0.0,
|
|
156
|
+
"standardDeviation": 0.0
|
|
157
|
+
},
|
|
158
|
+
"memory": {
|
|
159
|
+
"avgDeltaHeapUsed": "0KB",
|
|
160
|
+
"totalHeapDelta": "0KB",
|
|
161
|
+
"peakHeapUsed": "0KB"
|
|
162
|
+
},
|
|
163
|
+
"throughput": 0.0
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
"meta": {
|
|
167
|
+
"totalDuration": "0ms",
|
|
168
|
+
"totalBenchmarks": 0,
|
|
169
|
+
"completedAt": "2026-04-16T22:00:00.000Z"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The numeric fields are intentionally left at `0.0` in this schema —
|
|
175
|
+
fill them by running the suite.
|
|
176
|
+
|
|
177
|
+
## End-to-end benchmarking your pipeline
|
|
178
|
+
|
|
179
|
+
The harness below is the minimal template for honest end-to-end numbers.
|
|
180
|
+
Adapt it to your pipeline, provider mix, and query distribution.
|
|
181
|
+
|
|
182
|
+
```js
|
|
183
|
+
// scripts/e2e-benchmark.mjs
|
|
184
|
+
import { performance } from "node:perf_hooks";
|
|
185
|
+
import { writeFileSync } from "node:fs";
|
|
186
|
+
import { createRagPipeline } from "@devilsdev/rag-pipeline-utils";
|
|
187
|
+
|
|
188
|
+
const pipeline = createRagPipeline({
|
|
189
|
+
/* your real config — same as production */
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const queries = [
|
|
193
|
+
/* your real query set — at least 50 queries drawn from production logs */
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const WARMUP = 10;
|
|
197
|
+
const ITERATIONS = 100;
|
|
198
|
+
|
|
199
|
+
async function run(query) {
|
|
200
|
+
const t0 = performance.now();
|
|
201
|
+
const result = await pipeline.run({ query });
|
|
202
|
+
const t1 = performance.now();
|
|
203
|
+
return {
|
|
204
|
+
ms: t1 - t0,
|
|
205
|
+
retrievedCount: result.results?.length ?? 0,
|
|
206
|
+
answerChars: result.answer?.length ?? 0,
|
|
207
|
+
tokens: result.usage?.totalTokens ?? null,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Warmup
|
|
212
|
+
for (let i = 0; i < WARMUP; i++) {
|
|
213
|
+
await run(queries[i % queries.length]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Measured run
|
|
217
|
+
const samples = [];
|
|
218
|
+
for (let i = 0; i < ITERATIONS; i++) {
|
|
219
|
+
samples.push(await run(queries[i % queries.length]));
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const ms = samples.map((s) => s.ms).sort((a, b) => a - b);
|
|
223
|
+
const percentile = (p) => ms[Math.floor(ms.length * p)];
|
|
224
|
+
|
|
225
|
+
const report = {
|
|
226
|
+
timestamp: new Date().toISOString(),
|
|
227
|
+
iterations: ITERATIONS,
|
|
228
|
+
warmup: WARMUP,
|
|
229
|
+
latencyMs: {
|
|
230
|
+
mean: ms.reduce((a, b) => a + b, 0) / ms.length,
|
|
231
|
+
p50: percentile(0.5),
|
|
232
|
+
p95: percentile(0.95),
|
|
233
|
+
p99: percentile(0.99),
|
|
234
|
+
min: ms[0],
|
|
235
|
+
max: ms[ms.length - 1],
|
|
236
|
+
},
|
|
237
|
+
avgTokens: samples.reduce((a, b) => a + (b.tokens ?? 0), 0) / samples.length,
|
|
238
|
+
avgRetrieved:
|
|
239
|
+
samples.reduce((a, b) => a + b.retrievedCount, 0) / samples.length,
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
writeFileSync("e2e-benchmark.json", JSON.stringify(report, null, 2));
|
|
243
|
+
console.table(report.latencyMs);
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Run it the same way on every comparison — same corpus, same query set,
|
|
247
|
+
same providers, same hardware. Don't compare a warm run to a cold one.
|
|
248
|
+
|
|
249
|
+
## Interpreting results
|
|
250
|
+
|
|
251
|
+
### Timing percentiles
|
|
252
|
+
|
|
253
|
+
- **mean** is easy to move around by outliers; don't report it alone
|
|
254
|
+
- **p50** (median) is the "typical" experience
|
|
255
|
+
- **p95** is the tail a user will notice
|
|
256
|
+
- **p99** is where GC, cold caches, and network hiccups live — useful
|
|
257
|
+
for SLO design
|
|
258
|
+
- **standardDeviation** much larger than the mean signals high variance;
|
|
259
|
+
your benchmark is probably too short, too concurrent, or sharing a
|
|
260
|
+
noisy host
|
|
261
|
+
|
|
262
|
+
### Throughput
|
|
263
|
+
|
|
264
|
+
- Throughput is computed as `iterations / (mean_seconds)`. It's
|
|
265
|
+
single-process throughput with the harness's concurrency settings —
|
|
266
|
+
not a statement about your production service's throughput under a
|
|
267
|
+
real load mix.
|
|
268
|
+
- If you want realistic multi-tenant throughput numbers, build a
|
|
269
|
+
load-test harness (`autocannon`, `k6`, `artillery`) that hits the
|
|
270
|
+
HTTP surface you actually deploy, not the library directly.
|
|
271
|
+
|
|
272
|
+
### Memory
|
|
273
|
+
|
|
274
|
+
- `avgDeltaHeapUsed` is the _growth per iteration_. Trending up across
|
|
275
|
+
a long run means you have a leak.
|
|
276
|
+
- `peakHeapUsed` tells you the upper bound for right-sizing containers.
|
|
277
|
+
- On Windows or containerized Linux, RSS is not the same as heap used;
|
|
278
|
+
prefer platform metrics for capacity planning.
|
|
279
|
+
|
|
280
|
+
### Common pitfalls
|
|
281
|
+
|
|
282
|
+
1. **No warmup** — first-iteration numbers are dominated by JIT and
|
|
283
|
+
cold caches. Always discard a warmup window.
|
|
284
|
+
2. **Too few iterations** — 10 iterations on a ~1ms operation is mostly
|
|
285
|
+
noise. 100+ is a reasonable floor for framework benchmarks;
|
|
286
|
+
end-to-end benchmarks need enough iterations to cover your query
|
|
287
|
+
distribution.
|
|
288
|
+
3. **Correlated runs** — running the suite twice back-to-back on a
|
|
289
|
+
laptop will show the second run as faster because caches are warm.
|
|
290
|
+
For comparisons, use fresh processes and cold caches, or explicitly
|
|
291
|
+
measure warm paths.
|
|
292
|
+
4. **Shared hosts** — CI runners, personal machines with open browsers,
|
|
293
|
+
and containers on bin-packed hosts all have neighbors that will add
|
|
294
|
+
noise. Dedicated bare metal or bare VMs give the cleanest numbers.
|
|
295
|
+
5. **Stream-based workloads** — retrieval latency is not end-to-end
|
|
296
|
+
latency when the LLM streams tokens. Measure time-to-first-token
|
|
297
|
+
(TTFT) separately from total completion time.
|
|
298
|
+
|
|
299
|
+
## Regression testing in CI
|
|
300
|
+
|
|
301
|
+
The benchmark suite is deterministic enough to catch gross regressions
|
|
302
|
+
in CI. Recommended pattern:
|
|
303
|
+
|
|
304
|
+
1. Run `npm run benchmark:quick` on every PR against the default branch
|
|
305
|
+
2. Compare `latest.json` to the baseline in `main` using the keys in
|
|
306
|
+
`benchmarks.*.timing.mean`
|
|
307
|
+
3. Fail the gate if any benchmark's mean regresses by more than a
|
|
308
|
+
disclosed threshold (e.g. 25%)
|
|
309
|
+
|
|
310
|
+
This project does not yet gate on benchmark regressions in CI by default
|
|
311
|
+
— numbers on shared GitHub runners are too noisy to trust automatically.
|
|
312
|
+
If you run the suite on dedicated hardware as part of a release gate,
|
|
313
|
+
we'd welcome the workflow contribution.
|
|
314
|
+
|
|
315
|
+
## Contributing benchmark data
|
|
316
|
+
|
|
317
|
+
If you run the suite on a representative production-class host and want
|
|
318
|
+
to share the results:
|
|
319
|
+
|
|
320
|
+
1. Open a PR adding your report to `benchmark-results/community/` as
|
|
321
|
+
`<hostname-slug>-<date>.json`
|
|
322
|
+
2. Include the full environment disclosure block above in the PR
|
|
323
|
+
description
|
|
324
|
+
3. We will not average, normalize, or rank contributed numbers — they
|
|
325
|
+
remain raw data points for other users comparing against similar
|
|
326
|
+
hardware profiles
|
|
327
|
+
|
|
328
|
+
Community benchmark data is licensed under CC0 1.0 (public domain)
|
|
329
|
+
when contributed.
|
|
330
|
+
|
|
331
|
+
## See also
|
|
332
|
+
|
|
333
|
+
- [Performance guide](docs-site/docs/Performance.md) — optimization
|
|
334
|
+
strategies by component (embedding, retrieval, LLM, memory)
|
|
335
|
+
- [`scripts/benchmark.js`](scripts/benchmark.js) — the benchmark
|
|
336
|
+
harness source
|
|
337
|
+
- [SECURITY.md](SECURITY.md) — security hardening, not performance,
|
|
338
|
+
but often on the same reviewer checklist
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
|
|
5
|
+
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
6
|
+
and the [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) format.
|
|
7
|
+
|
|
8
|
+
Older history (pre-2.4.0) is preserved in the
|
|
9
|
+
[GitHub releases](https://github.com/DevilsDev/rag-pipeline-utils/releases)
|
|
10
|
+
page.
|
|
11
|
+
|
|
12
|
+
## [2.4.4] - 2026-04-16
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **`BENCHMARKS.md`** (root, ships in tarball) — methodology-first
|
|
17
|
+
benchmarks doc covering what we measure, what we don't, how to
|
|
18
|
+
run the suite, environment disclosure template, JSON report schema,
|
|
19
|
+
end-to-end harness template for benchmarking your own stack,
|
|
20
|
+
interpretation guide (percentiles, throughput, memory), common
|
|
21
|
+
pitfalls, and a CI regression pattern.
|
|
22
|
+
- **`SEMVER.md`** (root, ships in tarball) — API stability policy.
|
|
23
|
+
Defines public surface, what counts as breaking, deprecation
|
|
24
|
+
process (one-minor warning window minimum), supported runtimes,
|
|
25
|
+
TypeScript and ESM/CJS commitments.
|
|
26
|
+
- **`docs-site/docs/Security-Capabilities.md`** — capability matrix
|
|
27
|
+
distinguishing what's battle-tested (🟢) vs. recommended practice
|
|
28
|
+
(🟡) vs. example code requiring hardening (🟠) vs. out of scope
|
|
29
|
+
(🔴), across pre-retrieval, retrieval-time, and post-generation
|
|
30
|
+
guardrails plus supply-chain, auth, logging, input validation, and
|
|
31
|
+
data governance.
|
|
32
|
+
- **`docs-site/docs/Concepts-Core.md`**,
|
|
33
|
+
`Concepts-Connectors.md`, `Concepts-Evaluation.md`,
|
|
34
|
+
`Concepts-Guardrails.md` — four conceptual-module overviews mapped
|
|
35
|
+
to a future `rag-core` / `rag-connectors` / `rag-eval` /
|
|
36
|
+
`rag-guardrails` package boundary, so reviewers can reason about
|
|
37
|
+
blast radius without us splitting the codebase.
|
|
38
|
+
- **`docs-site/docs/Comparison.md`** — honest comparison vs.
|
|
39
|
+
LangChain.js and LlamaIndex.TS, including where we lose and a
|
|
40
|
+
decision framework. Currency dated to April 2026.
|
|
41
|
+
- **`examples/fastify-rag-demo/`** — runnable end-to-end RAG service:
|
|
42
|
+
Fastify 5 + OpenAI + in-memory retriever + 3-layer guardrails
|
|
43
|
+
- citations + evaluation. Ships with Dockerfile, Fly.io `fly.toml`,
|
|
44
|
+
Railway `railway.json`, ingest + smoke-test scripts, and a complete
|
|
45
|
+
README. ~150 lines of `server.js`.
|
|
46
|
+
- **`examples/README.md`** — index of runnable examples with
|
|
47
|
+
contribution guidance.
|
|
48
|
+
|
|
49
|
+
### Changed
|
|
50
|
+
|
|
51
|
+
- README "Documentation" section now links to BENCHMARKS, SECURITY,
|
|
52
|
+
CHANGELOG (added in 2.4.3) plus SEMVER, the Security Capabilities
|
|
53
|
+
matrix, the Comparison page, and the runnable demo.
|
|
54
|
+
- Sidebar adds two new categories: "Concepts" (4 pages) and a
|
|
55
|
+
Comparison page under Overview. Security-Capabilities slotted under
|
|
56
|
+
Enterprise.
|
|
57
|
+
|
|
58
|
+
## [2.4.3] - 2026-04-16
|
|
59
|
+
|
|
60
|
+
### Security
|
|
61
|
+
|
|
62
|
+
- **axios** upgraded from `1.8.4` → `1.15.0`, closing two critical advisories:
|
|
63
|
+
- [GHSA-fvcv-3m26-pcqx](https://github.com/advisories/GHSA-fvcv-3m26-pcqx) — unrestricted cloud metadata exfiltration via header injection chain
|
|
64
|
+
- [GHSA-3p68-rc4w-qgx5](https://github.com/advisories/GHSA-3p68-rc4w-qgx5) — SSRF via `NO_PROXY` hostname normalization bypass
|
|
65
|
+
- **follow-redirects** transitive patched for moderate auth-header leak on cross-domain redirects ([GHSA-r4q5-vmmm-2653](https://github.com/advisories/GHSA-r4q5-vmmm-2653))
|
|
66
|
+
- Supply-chain CI workflow now runs `npm audit` with `--omit=dev` and scopes the license allowlist to runtime deps — dev-only licenses no longer break the build, since they don't ship in the published tarball
|
|
67
|
+
- Added `Unlicense` and `CC-PDDC` to the license allowlist as legitimate public-domain dedications
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- `SECURITY.md` — responsible-disclosure policy with triage SLAs and safe-harbor language
|
|
72
|
+
- `CHANGELOG.md` — this file
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- `package.json` description updated to match the new positioning: _"Composable RAG for Node.js — with built-in evaluation, citations, guardrails, and observability."_ (previously the long "comprehensive enterprise-grade toolkit" line)
|
|
77
|
+
|
|
78
|
+
## [2.4.2] - 2026-04-16
|
|
79
|
+
|
|
80
|
+
### Changed
|
|
81
|
+
|
|
82
|
+
- **License: GPL-3.0 → MIT.** Removes adoption friction for commercial and closed-source consumers.
|
|
83
|
+
- README repositioned around three core primitives — `pipeline`, `plugin`, `connector` — instead of export counts. New sections: _Who This Is For_, _Use Cases_ (Document Q&A with citations / internal knowledge assistant with evaluation / enterprise service with guardrails).
|
|
84
|
+
- Docs-site homepage code example switched from CommonJS `require()` to ESM `import`, matching the README and the package's dual-mode export.
|
|
85
|
+
- Docs-site stat cards replaced unverified "<200ms retrieval latency" with verifiable "MIT License" + "3 Core Primitives".
|
|
86
|
+
- Kubernetes deployment examples in `docs-site/docs/Deployment-Kubernetes.md` bumped from `2.3.1` to `2.4.2` (6 occurrences).
|
|
87
|
+
- Algolia DocSearch facet filter and docs version label updated to `2.4.2`.
|
|
88
|
+
|
|
89
|
+
## [2.4.1] - 2026-04-15
|
|
90
|
+
|
|
91
|
+
### Changed
|
|
92
|
+
|
|
93
|
+
- Complete README rewrite for professional npm.js rendering — concise structure, ASCII architecture diagram (replaces Mermaid, which npm.js does not render), 21 keywords for discoverability.
|
|
94
|
+
- Additional internal files excluded from the published tarball (`src/cli/plugin-marketplace-commands.js`, example folders).
|
|
95
|
+
|
|
96
|
+
## [2.4.0] - 2026-04-14
|
|
97
|
+
|
|
98
|
+
First public release on the 2.4 line, introducing the v2.4 feature set.
|
|
99
|
+
|
|
100
|
+
### Added
|
|
101
|
+
|
|
102
|
+
- **GraphRAG** — knowledge-graph construction with entity/relationship extraction and graph traversal retrieval.
|
|
103
|
+
- **Streaming embeddings** — SSE and WebSocket adapters with backpressure control.
|
|
104
|
+
- **Advanced reranking** — cascaded reranker combining BM25, embedding similarity, and LLM scoring.
|
|
105
|
+
- **Performance dashboard** — bottleneck detection, execution tracing, token and cost tracking, budget enforcement.
|
|
106
|
+
- **MCP integration** — expose pipelines as Model Context Protocol tools.
|
|
107
|
+
- **3-layer guardrails** — pre-retrieval (prompt-injection detection, topic filtering), retrieval-time (minimum relevance thresholds), post-generation (PII detection, groundedness enforcement).
|
|
108
|
+
- **Agentic RAG** — query planning, iterative retrieval, self-critique via DAG execution.
|
|
109
|
+
- **Citation tracker** — per-sentence source attribution with hallucination detection and groundedness scoring.
|
|
110
|
+
- **RAG evaluation harness** — faithfulness, relevance, context precision/recall, groundedness metrics.
|
|
111
|
+
- **Hybrid retriever** — vector + BM25 with Reciprocal Rank Fusion.
|
|
112
|
+
- **Five chunking strategies** — sentence, fixed-size, recursive, semantic, structure-aware.
|
|
113
|
+
- **Seven provider connectors** — OpenAI, Anthropic, Cohere, Ollama, Local TF-IDF embedder, in-memory retriever, and a plugin registry for custom providers.
|
|
114
|
+
|
|
115
|
+
### Infrastructure
|
|
116
|
+
|
|
117
|
+
- ESLint auto-fixes across `src/` (174 violations resolved).
|
|
118
|
+
- Docs site published at <https://devilsdev.github.io/rag-pipeline-utils/> with versioned docs.
|
|
119
|
+
- Dual-module build (CJS + ESM) via esbuild; TypeScript declarations auto-generated.
|
|
120
|
+
- 2050+ tests (unit + integration + contract) with zero production vulnerabilities at release time.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
For release notes prior to v2.4.0, see
|
|
125
|
+
[github.com/DevilsDev/rag-pipeline-utils/releases](https://github.com/DevilsDev/rag-pipeline-utils/releases).
|
|
126
|
+
|
|
127
|
+
[2.4.4]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.4
|
|
128
|
+
[2.4.3]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.3
|
|
129
|
+
[2.4.2]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.2
|
|
130
|
+
[2.4.1]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.1
|
|
131
|
+
[2.4.0]: https://github.com/DevilsDev/rag-pipeline-utils/releases/tag/v2.4.0
|
package/README.md
CHANGED
|
@@ -157,6 +157,13 @@ import {
|
|
|
157
157
|
- **[Architecture](https://devilsdev.github.io/rag-pipeline-utils/docs/Architecture)** — plugin contracts, pipeline internals
|
|
158
158
|
- **[API reference](https://devilsdev.github.io/rag-pipeline-utils/docs/API-Reference)** — complete export index
|
|
159
159
|
- **[Examples](https://devilsdev.github.io/rag-pipeline-utils/docs/Examples)** — chatbot, Q&A, code search, support
|
|
160
|
+
- **[Comparison vs LangChain.js / LlamaIndex.TS](https://devilsdev.github.io/rag-pipeline-utils/docs/Comparison)** — honest decision framework
|
|
161
|
+
- **[Runnable demo](examples/fastify-rag-demo)** — Fastify + OpenAI + guardrails, deployable in one command
|
|
162
|
+
- **[Benchmarks & methodology](BENCHMARKS.md)** — how we measure, how you reproduce
|
|
163
|
+
- **[Security policy](SECURITY.md)** — responsible disclosure, supported versions
|
|
164
|
+
- **[Security capability matrix](https://devilsdev.github.io/rag-pipeline-utils/docs/Security-Capabilities)** — what's battle-tested vs. recommended vs. example
|
|
165
|
+
- **[API stability policy (SEMVER.md)](SEMVER.md)** — what counts as breaking, deprecation windows
|
|
166
|
+
- **[Changelog](CHANGELOG.md)** — release history
|
|
160
167
|
|
|
161
168
|
## Roadmap
|
|
162
169
|
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
Thank you for helping keep `@devilsdev/rag-pipeline-utils` and its users safe.
|
|
4
|
+
|
|
5
|
+
## Supported Versions
|
|
6
|
+
|
|
7
|
+
Only the latest minor release line receives security patches. When a new
|
|
8
|
+
minor version ships, the previous line receives one more patch window of
|
|
9
|
+
30 days before support ends.
|
|
10
|
+
|
|
11
|
+
| Version | Supported |
|
|
12
|
+
| ------- | ------------------ |
|
|
13
|
+
| 2.4.x | :white_check_mark: |
|
|
14
|
+
| 2.3.x | :x: |
|
|
15
|
+
| < 2.3 | :x: |
|
|
16
|
+
|
|
17
|
+
## Reporting a Vulnerability
|
|
18
|
+
|
|
19
|
+
**Please do not open a public GitHub issue for security vulnerabilities.**
|
|
20
|
+
|
|
21
|
+
Report privately via one of the following channels:
|
|
22
|
+
|
|
23
|
+
1. **GitHub private vulnerability reporting** (preferred) —
|
|
24
|
+
https://github.com/DevilsDev/rag-pipeline-utils/security/advisories/new
|
|
25
|
+
2. **Email** — open a draft security advisory on GitHub and tag
|
|
26
|
+
@DevilsDev maintainers; we'll respond within 72 hours.
|
|
27
|
+
|
|
28
|
+
Include, at minimum:
|
|
29
|
+
|
|
30
|
+
- A clear description of the issue and its potential impact
|
|
31
|
+
- Reproduction steps or a minimal proof-of-concept
|
|
32
|
+
- The affected version(s) and runtime environment (Node.js version, OS)
|
|
33
|
+
- Any suggested remediation if you have one
|
|
34
|
+
|
|
35
|
+
## What to Expect
|
|
36
|
+
|
|
37
|
+
| Stage | Target turnaround |
|
|
38
|
+
| --------------------------------------------- | ------------------------------------- |
|
|
39
|
+
| Initial acknowledgement | 72 hours |
|
|
40
|
+
| Triage + severity rating | 7 days |
|
|
41
|
+
| Patch release (for confirmed critical / high) | 14 days |
|
|
42
|
+
| Public disclosure | Coordinated with reporter after patch |
|
|
43
|
+
|
|
44
|
+
Confirmed vulnerabilities receive a CVE via GitHub Security Advisories and
|
|
45
|
+
are credited in the release notes unless the reporter requests otherwise.
|
|
46
|
+
|
|
47
|
+
## Scope
|
|
48
|
+
|
|
49
|
+
In scope:
|
|
50
|
+
|
|
51
|
+
- Source code in `src/`
|
|
52
|
+
- Published npm artifacts (`dist/`)
|
|
53
|
+
- Default plugin implementations (retrievers, embedders, LLM connectors,
|
|
54
|
+
rerankers, loaders)
|
|
55
|
+
- CLI (`bin/cli.js`)
|
|
56
|
+
|
|
57
|
+
Out of scope:
|
|
58
|
+
|
|
59
|
+
- Third-party dependencies — report upstream; we track via Dependabot
|
|
60
|
+
- Example/demo code in `docs-site/`
|
|
61
|
+
- Issues that require the attacker to already have full control of the
|
|
62
|
+
host environment running the pipeline
|
|
63
|
+
|
|
64
|
+
## Hardening Practices
|
|
65
|
+
|
|
66
|
+
This project applies the following controls to reduce supply-chain risk:
|
|
67
|
+
|
|
68
|
+
- **Pinned GitHub Actions** by commit SHA in all workflows
|
|
69
|
+
- **Dependabot** alerts on the default branch with automatic PRs for
|
|
70
|
+
patch-level bumps
|
|
71
|
+
- **npm audit** runs on every CI build (`--omit=dev`, fails on high+)
|
|
72
|
+
- **License allowlist** enforced for all runtime dependencies
|
|
73
|
+
- **SBOM generation** (`npm run sbom`) for release provenance
|
|
74
|
+
- **2FA-gated publishing** to npm via granular, scoped tokens
|
|
75
|
+
|
|
76
|
+
## Safe Harbor
|
|
77
|
+
|
|
78
|
+
Good-faith security research conducted under this policy is welcomed and
|
|
79
|
+
will not be pursued legally. Please give us a reasonable window to
|
|
80
|
+
remediate before any public disclosure.
|
package/SEMVER.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# API Stability Policy
|
|
2
|
+
|
|
3
|
+
This document defines what counts as a breaking change for
|
|
4
|
+
`@devilsdev/rag-pipeline-utils`, how long each release line is
|
|
5
|
+
supported, and the deprecation process for public API surface.
|
|
6
|
+
|
|
7
|
+
It is the contract you can plan against.
|
|
8
|
+
|
|
9
|
+
## Versioning
|
|
10
|
+
|
|
11
|
+
We follow [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html):
|
|
12
|
+
|
|
13
|
+
| Release | When it lands | What changes |
|
|
14
|
+
| ----------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
15
|
+
| **Patch** (2.4.x) | Bug fixes, security patches, docs, internal refactors | Nothing public-facing breaks. Safe to adopt without reading release notes. |
|
|
16
|
+
| **Minor** (2.x.0) | New features, additive API surface, new plugins, non-breaking behavior tweaks | Review the [CHANGELOG](CHANGELOG.md) before upgrading. Backward compatible. |
|
|
17
|
+
| **Major** (x.0.0) | Breaking changes to public API or required Node versions | Requires active migration. Each major ships with a migration guide. |
|
|
18
|
+
|
|
19
|
+
Pre-release versions (`x.y.z-rc.N`, `-beta.N`, `-alpha.N`) are for
|
|
20
|
+
testing. They have no stability guarantees and may change or disappear
|
|
21
|
+
before general availability.
|
|
22
|
+
|
|
23
|
+
## Public API surface
|
|
24
|
+
|
|
25
|
+
The **public API surface** — everything covered by SemVer — is
|
|
26
|
+
everything reachable from the package entry point:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
import { ... } from "@devilsdev/rag-pipeline-utils";
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Plus the CLI (`npx rag-pipeline …`) and the plugin contract schemas
|
|
33
|
+
in `contracts/`.
|
|
34
|
+
|
|
35
|
+
The following are **not** part of the public API surface and may
|
|
36
|
+
change in any release, including patches:
|
|
37
|
+
|
|
38
|
+
- Any import path with `/internal/` in it
|
|
39
|
+
- Default export behavior of submodules not documented in the
|
|
40
|
+
[API reference](https://devilsdev.github.io/rag-pipeline-utils/docs/API-Reference)
|
|
41
|
+
- Imports reaching into `dist/` or `src/` directly (e.g.
|
|
42
|
+
`@devilsdev/rag-pipeline-utils/src/core/dag/executor.js`)
|
|
43
|
+
- Behavior of items marked `@internal` in JSDoc
|
|
44
|
+
- Behavior marked **experimental** in release notes or JSDoc
|
|
45
|
+
- The on-disk format of internal caches, logs, or temporary files
|
|
46
|
+
- Exact wording of log messages and error `message` strings
|
|
47
|
+
- Node version support _below_ the documented minimum (see "Supported
|
|
48
|
+
runtime" below)
|
|
49
|
+
|
|
50
|
+
If you depend on any of the above, you accept that patch-level upgrades
|
|
51
|
+
may break your integration.
|
|
52
|
+
|
|
53
|
+
## Breaking changes
|
|
54
|
+
|
|
55
|
+
A **breaking change** is any change that would force a user of the
|
|
56
|
+
public API surface to modify their code, configuration, or deployment.
|
|
57
|
+
Concretely:
|
|
58
|
+
|
|
59
|
+
- Removing or renaming a public export
|
|
60
|
+
- Removing a method or property on a public class
|
|
61
|
+
- Changing the signature of a public method in a way existing callers
|
|
62
|
+
can't satisfy (added required parameter, removed optional parameter
|
|
63
|
+
type, etc.)
|
|
64
|
+
- Changing the shape of a public configuration object
|
|
65
|
+
- Tightening a type that was previously accepting
|
|
66
|
+
- Changing the default value of a public option when the new default
|
|
67
|
+
produces different behavior
|
|
68
|
+
- Throwing a new error class from a public method where callers
|
|
69
|
+
previously got a different class or a string
|
|
70
|
+
- Raising the minimum Node.js version
|
|
71
|
+
- Raising the minimum TypeScript version for typed consumers
|
|
72
|
+
- Removing support for a bundler or module format (ESM/CJS)
|
|
73
|
+
|
|
74
|
+
The following are **not** breaking changes (they ship in minors and
|
|
75
|
+
patches freely):
|
|
76
|
+
|
|
77
|
+
- Adding new exports, methods, or options
|
|
78
|
+
- Relaxing a type that was previously restrictive
|
|
79
|
+
- Widening an accepted input (e.g. accepting `Buffer` where we
|
|
80
|
+
previously only accepted `string`)
|
|
81
|
+
- Adding new optional parameters at the end of a signature
|
|
82
|
+
- Improving error messages or adding context to them
|
|
83
|
+
- Changing the shape of _logs_ (not errors)
|
|
84
|
+
- Performance improvements that don't change observable behavior
|
|
85
|
+
- Internal refactors invisible to the public API
|
|
86
|
+
|
|
87
|
+
## Deprecation process
|
|
88
|
+
|
|
89
|
+
When we need to remove public API surface, the removal is preceded by
|
|
90
|
+
at least **one minor release** with a deprecation warning.
|
|
91
|
+
|
|
92
|
+
Timeline:
|
|
93
|
+
|
|
94
|
+
1. **Minor X.Y.0** — API marked deprecated
|
|
95
|
+
- JSDoc `@deprecated` tag with migration guidance
|
|
96
|
+
- TypeScript `@deprecated` in type declarations (strikethrough in
|
|
97
|
+
IDEs)
|
|
98
|
+
- Runtime warning printed once per process when the API is called
|
|
99
|
+
(`util.deprecate` or equivalent)
|
|
100
|
+
- Documentation updated with the recommended replacement
|
|
101
|
+
- Mentioned in the [CHANGELOG](CHANGELOG.md)
|
|
102
|
+
2. **Minor X.Y.Z** and beyond — API still present, still warning
|
|
103
|
+
3. **Major (X+1).0.0** — API removed
|
|
104
|
+
|
|
105
|
+
The minimum one-minor window means a user running `npm update`
|
|
106
|
+
regularly will see deprecation warnings before the next major ships.
|
|
107
|
+
We will extend the window longer than one minor for widely-used API
|
|
108
|
+
surface.
|
|
109
|
+
|
|
110
|
+
## Supported runtime
|
|
111
|
+
|
|
112
|
+
The minimum supported Node.js version is declared in
|
|
113
|
+
[`package.json` `engines.node`](./package.json). We support Node LTS
|
|
114
|
+
versions that are in active maintenance at the time of each major
|
|
115
|
+
release.
|
|
116
|
+
|
|
117
|
+
Dropping support for a Node version is a **breaking change** and
|
|
118
|
+
lands only in major releases.
|
|
119
|
+
|
|
120
|
+
Current: **Node.js ≥ 18**. The next major release is planned to
|
|
121
|
+
require **Node.js ≥ 20** to track LTS support timelines.
|
|
122
|
+
|
|
123
|
+
## Supported release lines
|
|
124
|
+
|
|
125
|
+
See [SECURITY.md](SECURITY.md#supported-versions). In summary:
|
|
126
|
+
|
|
127
|
+
- **Latest minor** receives bug fixes and security patches
|
|
128
|
+
- **Previous minor** receives a 30-day security-only patch window
|
|
129
|
+
after a new minor ships
|
|
130
|
+
- **Older minors** are unsupported
|
|
131
|
+
|
|
132
|
+
The same matrix applies to non-security bug fixes.
|
|
133
|
+
|
|
134
|
+
## TypeScript
|
|
135
|
+
|
|
136
|
+
Type declarations ship in `dist/index.d.ts` and are considered part of
|
|
137
|
+
the public API surface. Breaking changes to _types_ that require
|
|
138
|
+
consumer code changes follow the same SemVer rules as runtime API.
|
|
139
|
+
|
|
140
|
+
Type-widening changes (making a type more permissive) are not breaking.
|
|
141
|
+
Type-narrowing changes (making a type more restrictive, causing
|
|
142
|
+
previously-compiling code to fail) are breaking.
|
|
143
|
+
|
|
144
|
+
We target the TypeScript version currently listed in
|
|
145
|
+
`package.json` `devDependencies`. Consumers using older TypeScript
|
|
146
|
+
versions may see type errors that are not regressions.
|
|
147
|
+
|
|
148
|
+
## ESM and CommonJS
|
|
149
|
+
|
|
150
|
+
The package ships **dual-module builds** — both ESM (`dist/index.mjs`)
|
|
151
|
+
and CommonJS (`dist/index.cjs`). `package.json` `exports` resolves the
|
|
152
|
+
correct entry point based on how the consumer imports it.
|
|
153
|
+
|
|
154
|
+
The ESM build is the primary development target. The CommonJS build
|
|
155
|
+
is a compatibility layer. When a feature can only be expressed in ESM
|
|
156
|
+
(e.g. top-level await, real dynamic imports), we ship it in ESM and
|
|
157
|
+
document the CJS limitation.
|
|
158
|
+
|
|
159
|
+
Dropping CommonJS support is a breaking change and will land only in
|
|
160
|
+
a major release, with a full minor of deprecation warnings first.
|
|
161
|
+
|
|
162
|
+
## What this means for you
|
|
163
|
+
|
|
164
|
+
If you are building on top of this package, you can:
|
|
165
|
+
|
|
166
|
+
- **Auto-merge patch updates** with confidence. Nothing public-facing
|
|
167
|
+
breaks.
|
|
168
|
+
- **Review minor updates** via the CHANGELOG before merging. No
|
|
169
|
+
required code changes, but new features may be worth adopting.
|
|
170
|
+
- **Plan for major updates.** Each major ships with a
|
|
171
|
+
`docs-site/docs/Migration.md` covering every breaking change and the
|
|
172
|
+
new call site.
|
|
173
|
+
|
|
174
|
+
If you find a case where a patch or minor change broke your
|
|
175
|
+
integration without a deprecation warning, open an issue — we treat
|
|
176
|
+
that as a bug against this policy.
|
|
177
|
+
|
|
178
|
+
## See also
|
|
179
|
+
|
|
180
|
+
- [SECURITY.md](SECURITY.md) — supported version windows and CVE
|
|
181
|
+
handling
|
|
182
|
+
- [CHANGELOG.md](CHANGELOG.md) — what actually changed per release
|
|
183
|
+
- [Migration guide](https://devilsdev.github.io/rag-pipeline-utils/docs/Migration)
|
|
184
|
+
— upgrade instructions between majors
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devilsdev/rag-pipeline-utils",
|
|
3
|
-
"version": "2.4.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.4.4",
|
|
4
|
+
"description": "Composable RAG for Node.js — with built-in evaluation, citations, guardrails, and observability.",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -151,7 +151,11 @@
|
|
|
151
151
|
"contracts/",
|
|
152
152
|
".ragrc.schema.json",
|
|
153
153
|
"README.md",
|
|
154
|
-
"LICENSE"
|
|
154
|
+
"LICENSE",
|
|
155
|
+
"SECURITY.md",
|
|
156
|
+
"CHANGELOG.md",
|
|
157
|
+
"BENCHMARKS.md",
|
|
158
|
+
"SEMVER.md"
|
|
155
159
|
],
|
|
156
160
|
"publishConfig": {
|
|
157
161
|
"access": "public"
|