@devilsdev/rag-pipeline-utils 1.0.0 ā 2.0.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.
- package/.codecov.yml +21 -0
- package/.dockerignore +14 -14
- package/.eslintignore +5 -0
- package/.eslintrc.json +21 -0
- package/.github/workflows/ci.yml +64 -42
- package/.husky/pre-commit +5 -0
- package/CHANGELOG.md +46 -0
- package/Dockerfile +22 -22
- package/LICENSE +674 -674
- package/README.md +117 -116
- package/__tests__/fixtures/.ragrc.json +8 -0
- package/__tests__/fixtures/invalid-ragrc.json +4 -0
- package/__tests__/fixtures/sample-eval-dataset.json +14 -14
- package/__tests__/fixtures/sample.pdf +1 -0
- package/__tests__/fixtures/src/mocks/openai-embedder.js +16 -0
- package/__tests__/fixtures/src/mocks/openai-llm.js +9 -0
- package/__tests__/fixtures/src/mocks/pdf-loader.js +17 -0
- package/__tests__/fixtures/src/mocks/pinecone-retriever.js +26 -0
- package/__tests__/fixtures/valid-ragrc.json +16 -0
- package/__tests__/integration/cli/config-flow.test.js +98 -44
- package/__tests__/integration/config/load-config.test.js +67 -52
- package/__tests__/unit/config/validate-schema.test.js +121 -0
- package/__tests__/unit/core/plugin-registry.test.js +55 -55
- package/__tests__/unit/reranker/llm-reranker.test.js +18 -42
- package/__tests__/unit/reranker/reranker.enriched.test.js +19 -0
- package/__tests__/unit/reranker/reranker.fallback.test.js +15 -0
- package/__tests__/unit/reranker/reranker.snapshot.test.js +15 -17
- package/__tests__/unit/reranker/reranker.structured-output.test.js +17 -0
- package/bin/cli.js +62 -168
- package/docs-site/docs/Architecture.md +76 -76
- package/docs-site/docs/CLI.md +69 -69
- package/docs-site/docs/Evaluation.md +61 -61
- package/docs-site/docs/FAQ.md +50 -50
- package/docs-site/docs/Plugins.md +61 -61
- package/docs-site/docs/Usage.md +72 -72
- package/jest.config.js +20 -13
- package/package.json +20 -3
- package/plugin.config.json +14 -0
- package/public/src/App.jsx +57 -57
- package/release.config.js +36 -23
- package/scripts/banner-injector.js +89 -0
- package/scripts/ci-runner.js +51 -0
- package/scripts/repair-fixtures.js +30 -0
- package/scripts/setup.js +31 -0
- package/scripts/test-global-setup.js +18 -0
- package/scripts/verify-fixture-mocks.js +45 -0
- package/scripts/verify-fixtures.js +36 -0
- package/server.js +31 -31
- package/src/config/load-config.js +33 -35
- package/src/config/load-plugin-config.js +56 -0
- package/src/config/validate-plugin-schema.js +28 -0
- package/src/config/validate-schema.js +107 -49
- package/src/core/create-pipeline.js +96 -82
- package/src/core/plugin-contracts.js +21 -0
- package/src/core/plugin-registry.js +48 -61
- package/src/dag/dag-engine.js +69 -69
- package/src/evaluate/evaluator.js +44 -44
- package/src/evaluate/scoring.js +73 -73
- package/src/loader/csv-loader.js +30 -30
- package/src/loader/directory-loader.js +37 -37
- package/src/loader/html-loader.js +57 -57
- package/src/loader/markdown-loader.js +58 -58
- package/src/mocks/openai-embedder.js +30 -0
- package/src/mocks/openai-llm.js +18 -0
- package/src/mocks/pdf-loader.js +17 -0
- package/src/mocks/pinecone-retriever.js +25 -0
- package/src/reranker/llm-reranker.js +34 -49
- package/src/utils/ci/diagnostic-reporter.js +36 -0
- package/src/utils/logger.js +29 -29
- package/src/utils/retry.js +42 -42
- package/src/utils/validate-plugin-contract.js +36 -0
- package/.github/workflows/release.yml +0 -21
package/docs-site/docs/Usage.md
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
# Usage
|
|
2
|
-
|
|
3
|
-
This guide covers how to use `@yourorg/rag-pipeline-utils` programmatically via API and through the CLI.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## š¦ Installation
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npm install @yourorg/rag-pipeline-utils
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## š§ Programmatic API
|
|
16
|
-
|
|
17
|
-
Import and instantiate a RAG pipeline:
|
|
18
|
-
|
|
19
|
-
```js
|
|
20
|
-
import { createRagPipeline } from '@yourorg/rag-pipeline-utils';
|
|
21
|
-
|
|
22
|
-
const pipeline = createRagPipeline({
|
|
23
|
-
loader: 'markdown',
|
|
24
|
-
embedder: 'openai',
|
|
25
|
-
retriever: 'pinecone',
|
|
26
|
-
llm: 'openai-gpt-4',
|
|
27
|
-
useReranker: true
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const answer = await pipeline.query("What is retrieval-augmented generation?");
|
|
31
|
-
console.log(answer);
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## š Pipeline Methods
|
|
37
|
-
|
|
38
|
-
- `pipeline.ingest(path: string)` ā Load, chunk, embed, and store vectors
|
|
39
|
-
- `pipeline.query(prompt: string)` ā Retrieve context, rerank (optional), and call LLM
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
|
-
## š§© Plugin Configuration
|
|
44
|
-
|
|
45
|
-
You can customize the pipeline by registering plugins:
|
|
46
|
-
|
|
47
|
-
```js
|
|
48
|
-
registry.register('loader', 'custom', new MyCustomLoader());
|
|
49
|
-
registry.register('retriever', 'opensearch', new MyOpenSearchRetriever());
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## āļø Configuration via `.ragrc.json`
|
|
55
|
-
|
|
56
|
-
Create a JSON file at your root:
|
|
57
|
-
|
|
58
|
-
```json
|
|
59
|
-
{
|
|
60
|
-
"loader": "directory",
|
|
61
|
-
"embedder": "openai",
|
|
62
|
-
"retriever": "pinecone",
|
|
63
|
-
"llm": "openai-gpt-4",
|
|
64
|
-
"useReranker": true
|
|
65
|
-
}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Used automatically when no CLI args are passed.
|
|
69
|
-
|
|
70
|
-
---
|
|
71
|
-
|
|
72
|
-
Next ā [CLI](./CLI.md)
|
|
1
|
+
# Usage
|
|
2
|
+
|
|
3
|
+
This guide covers how to use `@yourorg/rag-pipeline-utils` programmatically via API and through the CLI.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## š¦ Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @yourorg/rag-pipeline-utils
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## š§ Programmatic API
|
|
16
|
+
|
|
17
|
+
Import and instantiate a RAG pipeline:
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { createRagPipeline } from '@yourorg/rag-pipeline-utils';
|
|
21
|
+
|
|
22
|
+
const pipeline = createRagPipeline({
|
|
23
|
+
loader: 'markdown',
|
|
24
|
+
embedder: 'openai',
|
|
25
|
+
retriever: 'pinecone',
|
|
26
|
+
llm: 'openai-gpt-4',
|
|
27
|
+
useReranker: true
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const answer = await pipeline.query("What is retrieval-augmented generation?");
|
|
31
|
+
console.log(answer);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## š Pipeline Methods
|
|
37
|
+
|
|
38
|
+
- `pipeline.ingest(path: string)` ā Load, chunk, embed, and store vectors
|
|
39
|
+
- `pipeline.query(prompt: string)` ā Retrieve context, rerank (optional), and call LLM
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## š§© Plugin Configuration
|
|
44
|
+
|
|
45
|
+
You can customize the pipeline by registering plugins:
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
registry.register('loader', 'custom', new MyCustomLoader());
|
|
49
|
+
registry.register('retriever', 'opensearch', new MyOpenSearchRetriever());
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## āļø Configuration via `.ragrc.json`
|
|
55
|
+
|
|
56
|
+
Create a JSON file at your root:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"loader": "directory",
|
|
61
|
+
"embedder": "openai",
|
|
62
|
+
"retriever": "pinecone",
|
|
63
|
+
"llm": "openai-gpt-4",
|
|
64
|
+
"useReranker": true
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Used automatically when no CLI args are passed.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
Next ā [CLI](./CLI.md)
|
package/jest.config.js
CHANGED
|
@@ -1,14 +1,21 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version: 0.1.0
|
|
3
|
-
* Path: /jest.config.js
|
|
4
|
-
* Description: Jest configuration for native ESM test support
|
|
5
|
-
* Author: Ali Kahwaji
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Version: 0.1.0
|
|
3
|
+
* Path: /jest.config.js
|
|
4
|
+
* Description: Jest configuration for native ESM test support
|
|
5
|
+
* Author: Ali Kahwaji
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// jest.config.js
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
verbose: true,
|
|
12
|
+
testEnvironment: 'node',
|
|
13
|
+
transform: {},
|
|
14
|
+
collectCoverage: true,
|
|
15
|
+
coverageDirectory: 'coverage',
|
|
16
|
+
moduleFileExtensions: ['js', 'json'],
|
|
17
|
+
testMatch: ['**/__tests__/**/*.test.js'],
|
|
18
|
+
roots: ['<rootDir>/__tests__'],
|
|
19
|
+
};
|
|
20
|
+
|
|
14
21
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devilsdev/rag-pipeline-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A modular toolkit for building RAG (Retrieval-Augmented Generation) pipelines in Node.js",
|
|
5
5
|
"main": "src/core/create-pipeline.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,10 +8,22 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"scripts": {
|
|
11
|
-
"
|
|
11
|
+
"validate-fixtures": "node ./scripts/verify-fixtures.js",
|
|
12
|
+
"setup": "node ./scripts/setup.js",
|
|
13
|
+
"test": "node ./scripts/setup.js && cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage",
|
|
12
14
|
"test:watch": "jest --watch",
|
|
13
15
|
"lint": "eslint .",
|
|
14
|
-
"prepare": "husky install"
|
|
16
|
+
"prepare": "husky install",
|
|
17
|
+
"lint-staged": "lint-staged",
|
|
18
|
+
"postinstall": "husky install",
|
|
19
|
+
"verify:mocks": "node scripts/verify-fixture-mocks.js",
|
|
20
|
+
"ci": "node scripts/ci-runner.js"
|
|
21
|
+
},
|
|
22
|
+
"lint-staged": {
|
|
23
|
+
"**/*.{js,ts}": [
|
|
24
|
+
"npm run lint",
|
|
25
|
+
"npm run validate-fixtures"
|
|
26
|
+
]
|
|
15
27
|
},
|
|
16
28
|
"repository": {
|
|
17
29
|
"type": "git",
|
|
@@ -37,21 +49,26 @@
|
|
|
37
49
|
},
|
|
38
50
|
"devDependencies": {
|
|
39
51
|
"@semantic-release/changelog": "^6.0.3",
|
|
52
|
+
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
40
53
|
"@semantic-release/git": "^10.0.1",
|
|
41
54
|
"@semantic-release/github": "^9.2.6",
|
|
42
55
|
"@semantic-release/npm": "^11.0.3",
|
|
56
|
+
"@semantic-release/release-notes-generator": "^14.0.3",
|
|
43
57
|
"@types/jest": "^29.5.14",
|
|
58
|
+
"codecov": "^3.8.2",
|
|
44
59
|
"cross-env": "^7.0.3",
|
|
45
60
|
"esbuild": "^0.25.2",
|
|
46
61
|
"eslint": "^8.57.1",
|
|
47
62
|
"husky": "^8.0.3",
|
|
48
63
|
"jest": "^29.7.0",
|
|
64
|
+
"lint-staged": "^15.5.1",
|
|
49
65
|
"prettier": "^3.5.3",
|
|
50
66
|
"rimraf": "^6.0.1",
|
|
51
67
|
"semantic-release": "^21.1.2",
|
|
52
68
|
"ts-jest": "^29.3.2"
|
|
53
69
|
},
|
|
54
70
|
"dependencies": {
|
|
71
|
+
"ajv": "^8.17.1",
|
|
55
72
|
"axios": "^1.8.4",
|
|
56
73
|
"chalk": "^5.4.1",
|
|
57
74
|
"commander": "^13.1.0",
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"loader": {
|
|
3
|
+
"pdf": "./src/mocks/pdf-loader.js"
|
|
4
|
+
},
|
|
5
|
+
"embedder": {
|
|
6
|
+
"openai": "./src/mocks/openai-embedder.js"
|
|
7
|
+
},
|
|
8
|
+
"retriever": {
|
|
9
|
+
"pinecone": "./src/mocks/pinecone-retriever.js"
|
|
10
|
+
},
|
|
11
|
+
"llm": {
|
|
12
|
+
"openai-gpt-4": "./src/mocks/openai-llm.js"
|
|
13
|
+
}
|
|
14
|
+
}
|
package/public/src/App.jsx
CHANGED
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version: 0.1.0
|
|
3
|
-
* Path: /public/src/App.jsx
|
|
4
|
-
* Description: Evaluation results dashboard UI
|
|
5
|
-
* Author: Ali Kahwaji
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useEffect, useState } from 'react';
|
|
9
|
-
|
|
10
|
-
export default function App() {
|
|
11
|
-
const [results, setResults] = useState([]);
|
|
12
|
-
const [summary, setSummary] = useState({ passRate: 0, avgBLEU: 0, avgROUGE: 0 });
|
|
13
|
-
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
fetch('/results/sample-eval.json')
|
|
16
|
-
.then(res => res.json())
|
|
17
|
-
.then(data => {
|
|
18
|
-
setResults(data);
|
|
19
|
-
|
|
20
|
-
const total = data.length;
|
|
21
|
-
const passCount = data.filter(r => r.success).length;
|
|
22
|
-
const avgBLEU = data.reduce((s, r) => s + r.scores.bleu, 0) / total;
|
|
23
|
-
const avgROUGE = data.reduce((s, r) => s + r.scores.rouge, 0) / total;
|
|
24
|
-
|
|
25
|
-
setSummary({
|
|
26
|
-
passRate: (passCount / total * 100).toFixed(1),
|
|
27
|
-
avgBLEU: avgBLEU.toFixed(2),
|
|
28
|
-
avgROUGE: avgROUGE.toFixed(2)
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
}, []);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<main className="max-w-6xl mx-auto p-6">
|
|
35
|
-
<h1 className="text-3xl font-bold mb-4">RAG Evaluation Dashboard</h1>
|
|
36
|
-
|
|
37
|
-
<div className="mb-6 p-4 border rounded shadow bg-white">
|
|
38
|
-
<h2 className="text-xl font-semibold mb-2">Summary</h2>
|
|
39
|
-
<p> Pass Rate: <strong>{summary.passRate}%</strong></p>
|
|
40
|
-
<p> Avg BLEU: <strong>{summary.avgBLEU}</strong></p>
|
|
41
|
-
<p> Avg ROUGE: <strong>{summary.avgROUGE}</strong></p>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
{results.map((res, i) => (
|
|
45
|
-
<div key={i} className="mb-4 p-4 border-l-4 rounded bg-white shadow border-l-gray-300">
|
|
46
|
-
<h3 className="font-bold text-lg">Prompt {i + 1}</h3>
|
|
47
|
-
<p className="mt-2"><strong>Prompt:</strong> {res.prompt}</p>
|
|
48
|
-
<p><strong>Expected:</strong> {res.expected}</p>
|
|
49
|
-
<p><strong>Actual:</strong> {res.actual}</p>
|
|
50
|
-
<p> BLEU: <strong>{res.scores.bleu.toFixed(2)}</strong></p>
|
|
51
|
-
<p> ROUGE: <strong>{res.scores.rouge.toFixed(2)}</strong></p>
|
|
52
|
-
<p>Pass: <strong className={res.success ? 'text-green-600' : 'text-red-600'}>{res.success ? 'Yes' : 'No'}</strong></p>
|
|
53
|
-
</div>
|
|
54
|
-
))}
|
|
55
|
-
</main>
|
|
56
|
-
);
|
|
57
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Version: 0.1.0
|
|
3
|
+
* Path: /public/src/App.jsx
|
|
4
|
+
* Description: Evaluation results dashboard UI
|
|
5
|
+
* Author: Ali Kahwaji
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useEffect, useState } from 'react';
|
|
9
|
+
|
|
10
|
+
export default function App() {
|
|
11
|
+
const [results, setResults] = useState([]);
|
|
12
|
+
const [summary, setSummary] = useState({ passRate: 0, avgBLEU: 0, avgROUGE: 0 });
|
|
13
|
+
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
fetch('/results/sample-eval.json')
|
|
16
|
+
.then(res => res.json())
|
|
17
|
+
.then(data => {
|
|
18
|
+
setResults(data);
|
|
19
|
+
|
|
20
|
+
const total = data.length;
|
|
21
|
+
const passCount = data.filter(r => r.success).length;
|
|
22
|
+
const avgBLEU = data.reduce((s, r) => s + r.scores.bleu, 0) / total;
|
|
23
|
+
const avgROUGE = data.reduce((s, r) => s + r.scores.rouge, 0) / total;
|
|
24
|
+
|
|
25
|
+
setSummary({
|
|
26
|
+
passRate: (passCount / total * 100).toFixed(1),
|
|
27
|
+
avgBLEU: avgBLEU.toFixed(2),
|
|
28
|
+
avgROUGE: avgROUGE.toFixed(2)
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}, []);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<main className="max-w-6xl mx-auto p-6">
|
|
35
|
+
<h1 className="text-3xl font-bold mb-4">RAG Evaluation Dashboard</h1>
|
|
36
|
+
|
|
37
|
+
<div className="mb-6 p-4 border rounded shadow bg-white">
|
|
38
|
+
<h2 className="text-xl font-semibold mb-2">Summary</h2>
|
|
39
|
+
<p> Pass Rate: <strong>{summary.passRate}%</strong></p>
|
|
40
|
+
<p> Avg BLEU: <strong>{summary.avgBLEU}</strong></p>
|
|
41
|
+
<p> Avg ROUGE: <strong>{summary.avgROUGE}</strong></p>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
{results.map((res, i) => (
|
|
45
|
+
<div key={i} className="mb-4 p-4 border-l-4 rounded bg-white shadow border-l-gray-300">
|
|
46
|
+
<h3 className="font-bold text-lg">Prompt {i + 1}</h3>
|
|
47
|
+
<p className="mt-2"><strong>Prompt:</strong> {res.prompt}</p>
|
|
48
|
+
<p><strong>Expected:</strong> {res.expected}</p>
|
|
49
|
+
<p><strong>Actual:</strong> {res.actual}</p>
|
|
50
|
+
<p> BLEU: <strong>{res.scores.bleu.toFixed(2)}</strong></p>
|
|
51
|
+
<p> ROUGE: <strong>{res.scores.rouge.toFixed(2)}</strong></p>
|
|
52
|
+
<p>Pass: <strong className={res.success ? 'text-green-600' : 'text-red-600'}>{res.success ? 'Yes' : 'No'}</strong></p>
|
|
53
|
+
</div>
|
|
54
|
+
))}
|
|
55
|
+
</main>
|
|
56
|
+
);
|
|
57
|
+
}
|
package/release.config.js
CHANGED
|
@@ -1,23 +1,36 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Version: 0.1.0
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'@semantic-release/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Version: 0.1.0
|
|
3
|
+
* Description: Semantic Release configuration for CI/CD automation with changelog, versioning, GitHub releases, and npm publishing.
|
|
4
|
+
* Author: Ali Kahwaji
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
branches: ['main'],
|
|
9
|
+
repositoryUrl: 'https://github.com/DevilsDev/rag-pipeline-utils',
|
|
10
|
+
|
|
11
|
+
plugins: [
|
|
12
|
+
'@semantic-release/commit-analyzer',
|
|
13
|
+
'@semantic-release/release-notes-generator',
|
|
14
|
+
[
|
|
15
|
+
'@semantic-release/changelog',
|
|
16
|
+
{
|
|
17
|
+
changelogFile: 'CHANGELOG.md',
|
|
18
|
+
changelogTitle: '# Changelog',
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
[
|
|
22
|
+
'@semantic-release/npm',
|
|
23
|
+
{
|
|
24
|
+
npmPublish: true,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
[
|
|
28
|
+
'@semantic-release/git',
|
|
29
|
+
{
|
|
30
|
+
assets: ['package.json', 'package-lock.json', 'CHANGELOG.md'],
|
|
31
|
+
message: 'chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}',
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
'@semantic-release/github',
|
|
35
|
+
],
|
|
36
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File: scripts/banner-injector.js
|
|
3
|
+
* Description: Script to programmatically inject file-level banners into specified project files
|
|
4
|
+
* Author: Ali Kahwaji
|
|
5
|
+
* Version: 1.0.0
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import glob from 'glob';
|
|
11
|
+
|
|
12
|
+
const banners = {
|
|
13
|
+
'__tests__/unit/reranker/llm-reranker.test.js': `/**
|
|
14
|
+
* File: __tests__/unit/reranker/llm-reranker.test.js
|
|
15
|
+
* Description: Unit and integration tests with mocks for RAG pipeline
|
|
16
|
+
* Author: Ali Kahwaji
|
|
17
|
+
* Version: 1.0.4
|
|
18
|
+
*/\n\n`,
|
|
19
|
+
|
|
20
|
+
'__tests__/unit/reranker/reranker.snapshot.test.js': `/**
|
|
21
|
+
* File: __tests__/unit/reranker/reranker.snapshot.test.js
|
|
22
|
+
* Description: Snapshot tests for LLM reranker
|
|
23
|
+
* Author: Ali Kahwaji
|
|
24
|
+
* Version: 1.0.4
|
|
25
|
+
*/\n\n`,
|
|
26
|
+
|
|
27
|
+
'__tests__/unit/core/plugin-registry.test.js': `/**
|
|
28
|
+
* File: __tests__/unit/core/plugin-registry.test.js
|
|
29
|
+
* Description: Unit and integration tests with mocks for RAG pipeline
|
|
30
|
+
* Author: Ali Kahwaji
|
|
31
|
+
* Version: 1.0.4
|
|
32
|
+
*/\n\n`,
|
|
33
|
+
|
|
34
|
+
'__tests__/integration/config/load-config.test.js': `/**
|
|
35
|
+
* File: __tests__/integration/config/load-config.test.js
|
|
36
|
+
* Description: Unit and integration tests with mocks for RAG pipeline
|
|
37
|
+
* Author: Ali Kahwaji
|
|
38
|
+
* Version: 1.0.4
|
|
39
|
+
*/\n\n`,
|
|
40
|
+
|
|
41
|
+
'__tests__/integration/cli/config-flow.test.js': `/**
|
|
42
|
+
* File: __tests__/integration/cli/config-flow.test.js
|
|
43
|
+
* Description: Unit and integration tests with mocks for RAG pipeline
|
|
44
|
+
* Author: Ali Kahwaji
|
|
45
|
+
* Version: 1.0.4
|
|
46
|
+
*/\n\n`,
|
|
47
|
+
|
|
48
|
+
'src/mocks/pdf-loader.js': `/**
|
|
49
|
+
* File: src/mocks/pdf-loader.js
|
|
50
|
+
* Description: Unit and integration tests with mocks for RAG pipeline
|
|
51
|
+
* Author: Ali Kahwaji
|
|
52
|
+
* Version: 1.0.4
|
|
53
|
+
*/\n\n`,
|
|
54
|
+
|
|
55
|
+
'src/mocks/openai-embedder.js': `/**
|
|
56
|
+
* File: src/mocks/openai-embedder.js
|
|
57
|
+
* Description: Unit and integration tests with mocks for RAG pipeline
|
|
58
|
+
* Author: Ali Kahwaji
|
|
59
|
+
* Version: 1.0.4
|
|
60
|
+
*/\n\n`,
|
|
61
|
+
|
|
62
|
+
'src/mocks/pinecone-retriever.js': `/**
|
|
63
|
+
* File: src/mocks/pinecone-retriever.js
|
|
64
|
+
* Description: Unit and integration tests with mocks for RAG pipeline
|
|
65
|
+
* Author: Ali Kahwaji
|
|
66
|
+
* Version: 1.0.4
|
|
67
|
+
*/\n\n`
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
Object.entries(banners).forEach(([filePath, banner]) => {
|
|
71
|
+
const resolvedPath = path.resolve(filePath);
|
|
72
|
+
|
|
73
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
74
|
+
console.warn(`[SKIPPED] ${filePath} does not exist.`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const originalContent = fs.readFileSync(resolvedPath, 'utf-8');
|
|
79
|
+
|
|
80
|
+
// Skip if banner already present
|
|
81
|
+
if (originalContent.startsWith('/**')) {
|
|
82
|
+
console.log(`[SKIPPED] ${filePath} already contains a banner.`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const newContent = banner + originalContent;
|
|
87
|
+
fs.writeFileSync(resolvedPath, newContent, 'utf-8');
|
|
88
|
+
console.log(`[INJECTED] Banner added to ${filePath}`);
|
|
89
|
+
});
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version: 1.1.0
|
|
3
|
+
* Description: CI runner for linting, mock validation, testing and coverage
|
|
4
|
+
* Author: Ali Kahwaji
|
|
5
|
+
* File: scripts/ci-runner.js
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { execSync } from 'child_process';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { pathToFileURL } from 'url';
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
|
|
13
|
+
// Entry helpers
|
|
14
|
+
const ROOT = path.resolve();
|
|
15
|
+
const resolveScript = (relPath) => pathToFileURL(path.resolve(ROOT, relPath)).href;
|
|
16
|
+
|
|
17
|
+
const run = (label, command) => {
|
|
18
|
+
console.log(`\nš§ Running: ${label}`);
|
|
19
|
+
try {
|
|
20
|
+
execSync(command, { stdio: 'inherit', cwd: ROOT });
|
|
21
|
+
console.log(`ā
${label} passed`);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
console.error(`ā ${label} failed`);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const runDynamicModule = async (label, modulePath) => {
|
|
29
|
+
console.log(`\nš Validating: ${label}`);
|
|
30
|
+
try {
|
|
31
|
+
const mod = await import(resolveScript(modulePath));
|
|
32
|
+
if (typeof mod.default === 'function') await mod.default();
|
|
33
|
+
console.log(`ā
${label} passed`);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
console.error(`ā ${label} failed:\n${err.message}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
(async () => {
|
|
41
|
+
// Step 1: Lint
|
|
42
|
+
run('Lint', 'npx eslint . --ext .js,.ts');
|
|
43
|
+
|
|
44
|
+
// Step 2: Verify mocks for required interface methods
|
|
45
|
+
await runDynamicModule('Fixture Mock Interface Validation', 'scripts/verify-fixture-mocks.js');
|
|
46
|
+
|
|
47
|
+
// Step 3: Test and coverage
|
|
48
|
+
run('Unit + Integration Tests w/ Coverage', 'cross-env NODE_OPTIONS=--experimental-vm-modules jest --coverage');
|
|
49
|
+
|
|
50
|
+
console.log('\nš CI runner completed successfully.\n');
|
|
51
|
+
})();
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version: 1.0.0
|
|
3
|
+
* Description: Auto-repairs mock plugin fixtures for integration tests
|
|
4
|
+
* Author: Ali Kahwaji
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { mkdirSync, copyFileSync, existsSync } from 'fs';
|
|
8
|
+
import { resolve, join } from 'path';
|
|
9
|
+
|
|
10
|
+
const MOCKS = [
|
|
11
|
+
'pdf-loader.js',
|
|
12
|
+
'openai-embedder.js',
|
|
13
|
+
'pinecone-retriever.js',
|
|
14
|
+
'openai-llm.js'
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const SRC_FIXTURES = resolve('__tests__/fixtures/src/mocks');
|
|
18
|
+
const DEST_FIXTURES = resolve('__tests__/__temp__/cli-config-fallback/src/mocks');
|
|
19
|
+
|
|
20
|
+
mkdirSync(DEST_FIXTURES, { recursive: true });
|
|
21
|
+
|
|
22
|
+
MOCKS.forEach((file) => {
|
|
23
|
+
const src = join(SRC_FIXTURES, file);
|
|
24
|
+
const dest = join(DEST_FIXTURES, file);
|
|
25
|
+
if (!existsSync(src)) throw new Error(`[FIXTURE MISSING] ${src}`);
|
|
26
|
+
copyFileSync(src, dest);
|
|
27
|
+
console.log(`[COPIED] ${file}`);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
console.log('ā
Fixture mocks successfully repaired.');
|
package/scripts/setup.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Version: 1.1.0
|
|
3
|
+
* Description: Test setup script to ensure fixtures exist and validate mocks before running tests.
|
|
4
|
+
* Author: Ali Kahwaji
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import { execSync } from 'child_process';
|
|
11
|
+
|
|
12
|
+
// Resolve __dirname in ES module scope
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
const fixturePath = path.resolve(__dirname, '../__tests__/fixtures/sample.pdf');
|
|
17
|
+
|
|
18
|
+
// Ensure PDF test fixture
|
|
19
|
+
if (!fs.existsSync(fixturePath)) {
|
|
20
|
+
fs.mkdirSync(path.dirname(fixturePath), { recursive: true });
|
|
21
|
+
fs.writeFileSync(fixturePath, 'Dummy PDF content for test');
|
|
22
|
+
console.log('[setup] Created sample.pdf fixture');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Validate plugin fixture presence
|
|
26
|
+
try {
|
|
27
|
+
execSync('node ./scripts/verify-fixtures.js', { stdio: 'inherit' });
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error('[setup] Fixture verification failed. Please check missing mocks.');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// __tests__/setup/global.js
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
|
|
6
|
+
// __dirname polyfill for ESM
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
const pdfPath = path.resolve(__dirname, '../fixtures/sample.pdf');
|
|
11
|
+
|
|
12
|
+
// Ensure the fixtures directory exists
|
|
13
|
+
fs.mkdirSync(path.dirname(pdfPath), { recursive: true });
|
|
14
|
+
|
|
15
|
+
// Create a minimal valid PDF file if it doesn't exist
|
|
16
|
+
if (!fs.existsSync(pdfPath)) {
|
|
17
|
+
fs.writeFileSync(pdfPath, '%PDF-1.4\n%EOF');
|
|
18
|
+
}
|