@denizsvnc/ai-rag-engine 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -2
- package/README.md +66 -14
- package/dist/adapters/faq/local-faq.adapter.d.ts +2 -0
- package/dist/adapters/llm/fallback.adapter.d.ts +1 -0
- package/dist/adapters/rules/static-rules.adapter.d.ts +6 -1
- package/dist/adapters/vector/memory-vector.adapter.d.ts +2 -0
- package/dist/api/server.js +44 -6
- package/dist/core/queue/job-queue.interface.d.ts +7 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +54 -6
- package/dist/worker.js +3 -0
- package/docs/RELEASING.md +1 -1
- package/docs/USAGE.md +7 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
This file follows Semantic Versioning.
|
|
3
|
+
This file follows Semantic Versioning.
|
|
4
4
|
|
|
5
|
-
## 2.2.
|
|
5
|
+
## 2.2.2 — 2026-11-10
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Document Ingestion:** Resolved infinite decaying chunk loop in `DocumentIngestionService.chunkText` when `endIndex >= text.length`.
|
|
10
|
+
- **Security & Prompt Injection:** Resolved regex boundary and preposition issues in `InjectionDetector` for English DAN jailbreak attacks (`in DAN mode`) and Turkish Unicode word boundaries (`ş, ç`).
|
|
11
|
+
- **LLM Failover Logging:** Replaced generic `Object failed` error message in `FallbackLLMProvider` with dynamic provider, model, or constructor resolution.
|
|
12
|
+
- **Rules Adapter:** Extended `StaticRulesAdapter` to accept structured rule objects (`{ id, rule }`) alongside plain string arrays via polymorphic `RuleInput`.
|
|
13
|
+
- **Performance & SML Sharing:** Prevented redundant ONNX model downloads and duplicate memory footprint by sharing `SMLEngine` instances across `RAGEngine`, `LocalFaqAdapter`, and `MemoryVectorAdapter`.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Exported `JobStatusValues` constants in `job-queue.interface.ts` to prevent casing mismatches.
|
|
18
|
+
- Exported `RuleInput` type in root exports.
|
|
19
|
+
|
|
20
|
+
## 2.2.1 — 2026-11-10
|
|
21
|
+
|
|
22
|
+
### Documentation
|
|
23
|
+
|
|
24
|
+
- Updated `README.md`, `README_tr.md`, and `README_de.md` with verified, type-safe production examples featuring `GeminiAdapter`, `PostgresVectorAdapter`, `RedisCacheAdapter`, `LocalFaqAdapter`, and `SecurityConfig`.
|
|
25
|
+
- Removed legacy pre-publication disclaimers and streamlined installation documentation for live npm consumption.
|
|
26
|
+
|
|
27
|
+
## 2.2.0 — 2026-11-10
|
|
6
28
|
|
|
7
29
|
### Added
|
|
8
30
|
|
package/README.md
CHANGED
|
@@ -22,27 +22,14 @@
|
|
|
22
22
|
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
|
-
**Publication status:** prepared locally for `@denizsvnc/ai-rag-engine@2.2.0`; this is not a claim that it is already available on npm. Scope ownership and publication remain the maintainer's responsibility.
|
|
26
|
-
|
|
27
25
|
## Requirements and installation
|
|
28
26
|
|
|
29
27
|
ESM only. Node.js **22.14 or newer**; the compatibility matrix covers Node 22 and 24. TypeScript consumers should use TypeScript 5.8+ with NodeNext or Bundler resolution. Runtime applications do not need TypeScript or build tools.
|
|
30
28
|
|
|
31
|
-
After publication:
|
|
32
|
-
|
|
33
29
|
```sh
|
|
34
30
|
npm install @denizsvnc/ai-rag-engine
|
|
35
31
|
```
|
|
36
32
|
|
|
37
|
-
Before publication, install a locally built artifact:
|
|
38
|
-
|
|
39
|
-
```sh
|
|
40
|
-
npm ci
|
|
41
|
-
npm pack
|
|
42
|
-
# From a different project:
|
|
43
|
-
npm install /absolute/path/to/denizsvnc-ai-rag-engine-2.2.0.tgz
|
|
44
|
-
```
|
|
45
|
-
|
|
46
33
|
## Quick Start
|
|
47
34
|
|
|
48
35
|
This deterministic example needs no credentials, model download, HTTP server, or database. The provider and vector adapter are test doubles demonstrating the integration contract; use real adapters for application data.
|
|
@@ -75,6 +62,71 @@ const result = await engine.query('What is the return window?', {
|
|
|
75
62
|
console.log(result.answer); // Returns: 14 days.
|
|
76
63
|
```
|
|
77
64
|
|
|
65
|
+
### Production Example (Multi-Tenant with Gemini, pgvector & Redis)
|
|
66
|
+
|
|
67
|
+
For production applications with external LLMs, multi-tenant persistence, and distributed caching:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import {
|
|
71
|
+
RAGEngine,
|
|
72
|
+
GeminiAdapter,
|
|
73
|
+
PostgresVectorAdapter,
|
|
74
|
+
RedisCacheAdapter,
|
|
75
|
+
LocalFaqAdapter
|
|
76
|
+
} from '@denizsvnc/ai-rag-engine';
|
|
77
|
+
|
|
78
|
+
const engine = new RAGEngine({
|
|
79
|
+
// 1. LLM Provider (Gemini, OpenAI, Ollama, or Custom)
|
|
80
|
+
llmProvider: new GeminiAdapter(
|
|
81
|
+
process.env.GEMINI_API_KEY,
|
|
82
|
+
'gemini-1.5-flash'
|
|
83
|
+
),
|
|
84
|
+
|
|
85
|
+
// 2. Knowledge Retrieval & Semantic FAQ Matching
|
|
86
|
+
inputs: {
|
|
87
|
+
vectorStore: new PostgresVectorAdapter({
|
|
88
|
+
connectionString: process.env.DATABASE_URL,
|
|
89
|
+
tableName: 'enterprise_embeddings'
|
|
90
|
+
}),
|
|
91
|
+
faq: new LocalFaqAdapter({
|
|
92
|
+
filePath: './faq.json',
|
|
93
|
+
defaultMatchThreshold: 0.65
|
|
94
|
+
})
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
// 3. Distributed Cache & Security Guardrails
|
|
98
|
+
cache: {
|
|
99
|
+
enabled: true,
|
|
100
|
+
adapter: new RedisCacheAdapter({
|
|
101
|
+
url: process.env.REDIS_URL,
|
|
102
|
+
defaultTtlMs: 3600000 // 1 hour
|
|
103
|
+
})
|
|
104
|
+
},
|
|
105
|
+
security: {
|
|
106
|
+
enabled: true,
|
|
107
|
+
blockHighRiskInjections: true,
|
|
108
|
+
pii: {
|
|
109
|
+
enabled: true,
|
|
110
|
+
maskTCKN: true,
|
|
111
|
+
maskCreditCards: true,
|
|
112
|
+
maskEmails: true
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Query with tenant isolation & role-based access
|
|
118
|
+
const response = await engine.query('Q3 compliance audit summary', {
|
|
119
|
+
tenantId: 'tenant-acme',
|
|
120
|
+
userId: 'usr_8472',
|
|
121
|
+
roles: ['compliance_officer']
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
console.log(response.answer);
|
|
125
|
+
console.log('Intent:', response.intent);
|
|
126
|
+
console.log('Latency (ms):', response.latencyMs);
|
|
127
|
+
console.log('Sources:', response.sources);
|
|
128
|
+
```
|
|
129
|
+
|
|
78
130
|
Importing the SDK does not start a server, load `.env`, open Redis/PostgreSQL connections, download models, or change the Transformers global environment. Constructors and explicit initialization perform the operations described in [the usage guide](docs/USAGE.md).
|
|
79
131
|
|
|
80
132
|
## Capabilities and operational boundaries
|
|
@@ -96,7 +148,7 @@ Prompt filters and PII patterns are defenses with limitations, not guarantees of
|
|
|
96
148
|
- [Configuration, real providers, vectors, FAQ, tools and troubleshooting](docs/USAGE.md)
|
|
97
149
|
- [Versioning, manual publication and release checklist](docs/RELEASING.md)
|
|
98
150
|
- [Changelog](CHANGELOG.md)
|
|
99
|
-
- [Detailed
|
|
151
|
+
- [Detailed release-readiness report](docs/NPM_RELEASE_READINESS.md)
|
|
100
152
|
|
|
101
153
|
## Repository verification
|
|
102
154
|
|
|
@@ -16,6 +16,8 @@ export declare class LocalFaqAdapter implements IFAQAdapter {
|
|
|
16
16
|
private items;
|
|
17
17
|
private isLoaded;
|
|
18
18
|
constructor(options?: LocalFaqAdapterOptions);
|
|
19
|
+
setSMLEngine(engine: SMLEngine): void;
|
|
20
|
+
getSMLEngine(): SMLEngine;
|
|
19
21
|
/**
|
|
20
22
|
* Initializes the adapter by reading the JSON file and caching embeddings in RAM.
|
|
21
23
|
*/
|
|
@@ -6,5 +6,6 @@ export declare class FallbackLLMProvider implements ILLMProvider {
|
|
|
6
6
|
private providers;
|
|
7
7
|
private logFailover;
|
|
8
8
|
constructor(providers: ILLMProvider[], options?: FallbackProviderOptions);
|
|
9
|
+
private getProviderName;
|
|
9
10
|
generate(request: ILLMRequest): Promise<ILLMResponse>;
|
|
10
11
|
}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { IRulesAdapter } from '../../interfaces/rules.interface.js';
|
|
2
|
+
export type RuleInput = string | {
|
|
3
|
+
id?: string;
|
|
4
|
+
rule: string;
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
};
|
|
2
7
|
export declare class StaticRulesAdapter implements IRulesAdapter {
|
|
3
8
|
private rules;
|
|
4
|
-
constructor(rules
|
|
9
|
+
constructor(rules?: Array<RuleInput>);
|
|
5
10
|
getActiveRules(tenantId?: string): Promise<string[]>;
|
|
6
11
|
}
|
|
@@ -6,6 +6,8 @@ export declare class MemoryVectorAdapter implements IVectorStoreAdapter {
|
|
|
6
6
|
private documents;
|
|
7
7
|
private bm25Index;
|
|
8
8
|
constructor(smlEngine?: SMLEngine);
|
|
9
|
+
setSMLEngine(engine: SMLEngine): void;
|
|
10
|
+
getSMLEngine(): SMLEngine;
|
|
9
11
|
/**
|
|
10
12
|
* Adds documents to memory, computes their embeddings, and indexes them in BM25.
|
|
11
13
|
*/
|
package/dist/api/server.js
CHANGED
|
@@ -535,11 +535,11 @@ var InjectionDetector = class {
|
|
|
535
535
|
// 2. Jailbreaks, DAN modes, role hijacking
|
|
536
536
|
{
|
|
537
537
|
id: "JAILBREAK_MODE_EN",
|
|
538
|
-
regex: /\b(you\s+are\s+now|act\s+as|switch\s+to|enter)\s+(an?\s+)?(developer|dan|jailbreak|unrestricted|unfiltered|god)\s*(mode|persona|ai)?\b/i
|
|
538
|
+
regex: /\b(you\s+are\s+now|act\s+as|switch\s+to|enter)\s+(in\s+(an?\s+)?|an?\s+)?(developer|dan|jailbreak|unrestricted|unfiltered|god)\s*(mode|persona|ai)?\b/i
|
|
539
539
|
},
|
|
540
540
|
{
|
|
541
541
|
id: "JAILBREAK_MODE_TR",
|
|
542
|
-
regex:
|
|
542
|
+
regex: /(?:^|\s|[.,!?])(artık|şimdi)\s+(bir\s+)?(geliştirici|dan|kısıtlamasız|admin|jailbreak)\s+(modundasın|moduna\s+geç|olarak\s+davran)(?:$|\s|[.,!?])/i
|
|
543
543
|
},
|
|
544
544
|
{
|
|
545
545
|
id: "DISABLE_SAFETY_EN",
|
|
@@ -1565,6 +1565,9 @@ var DocumentIngestionService = class _DocumentIngestionService {
|
|
|
1565
1565
|
if (chunk.length > 0) {
|
|
1566
1566
|
chunks.push(chunk);
|
|
1567
1567
|
}
|
|
1568
|
+
if (endIndex >= text.length) {
|
|
1569
|
+
break;
|
|
1570
|
+
}
|
|
1568
1571
|
startIndex = Math.max(startIndex + 1, endIndex - overlap);
|
|
1569
1572
|
}
|
|
1570
1573
|
return chunks;
|
|
@@ -1945,6 +1948,12 @@ var MemoryVectorAdapter = class {
|
|
|
1945
1948
|
smlEngine;
|
|
1946
1949
|
documents = [];
|
|
1947
1950
|
bm25Index = new BM25Index();
|
|
1951
|
+
setSMLEngine(engine) {
|
|
1952
|
+
this.smlEngine = engine;
|
|
1953
|
+
}
|
|
1954
|
+
getSMLEngine() {
|
|
1955
|
+
return this.smlEngine;
|
|
1956
|
+
}
|
|
1948
1957
|
/**
|
|
1949
1958
|
* Adds documents to memory, computes their embeddings, and indexes them in BM25.
|
|
1950
1959
|
*/
|
|
@@ -2046,6 +2055,12 @@ var RAGEngine = class {
|
|
|
2046
2055
|
}
|
|
2047
2056
|
this.smlEngine = new SMLEngine({ modelName: config.smlConfig?.modelName });
|
|
2048
2057
|
const vectorStore = config.inputs?.vectorStore || new MemoryVectorAdapter(this.smlEngine);
|
|
2058
|
+
if (typeof vectorStore.setSMLEngine === "function") {
|
|
2059
|
+
vectorStore.setSMLEngine(this.smlEngine);
|
|
2060
|
+
}
|
|
2061
|
+
if (config.inputs?.faq && typeof config.inputs.faq.setSMLEngine === "function") {
|
|
2062
|
+
config.inputs.faq.setSMLEngine(this.smlEngine);
|
|
2063
|
+
}
|
|
2049
2064
|
this.config = {
|
|
2050
2065
|
...config,
|
|
2051
2066
|
inputs: {
|
|
@@ -2865,11 +2880,24 @@ var FallbackLLMProvider = class {
|
|
|
2865
2880
|
this.providers = providers;
|
|
2866
2881
|
this.logFailover = options?.logFailover ?? true;
|
|
2867
2882
|
}
|
|
2883
|
+
getProviderName(provider, index) {
|
|
2884
|
+
if (provider.name && typeof provider.name === "string") {
|
|
2885
|
+
return provider.name;
|
|
2886
|
+
}
|
|
2887
|
+
if (provider.model && typeof provider.model === "string") {
|
|
2888
|
+
const ctor = provider.constructor?.name && provider.constructor.name !== "Object" ? provider.constructor.name : "LLMProvider";
|
|
2889
|
+
return `${ctor}(${provider.model})`;
|
|
2890
|
+
}
|
|
2891
|
+
if (provider.constructor?.name && provider.constructor.name !== "Object") {
|
|
2892
|
+
return provider.constructor.name;
|
|
2893
|
+
}
|
|
2894
|
+
return `Provider#${index + 1}`;
|
|
2895
|
+
}
|
|
2868
2896
|
async generate(request) {
|
|
2869
2897
|
const failureErrors = [];
|
|
2870
2898
|
for (let i = 0; i < this.providers.length; i++) {
|
|
2871
2899
|
const provider = this.providers[i];
|
|
2872
|
-
const providerName = provider
|
|
2900
|
+
const providerName = this.getProviderName(provider, i);
|
|
2873
2901
|
try {
|
|
2874
2902
|
return await provider.generate(request);
|
|
2875
2903
|
} catch (error) {
|
|
@@ -2877,7 +2905,7 @@ var FallbackLLMProvider = class {
|
|
|
2877
2905
|
failureErrors.push({ providerName, error: errorMessage });
|
|
2878
2906
|
if (this.logFailover) {
|
|
2879
2907
|
const nextProvider = this.providers[i + 1];
|
|
2880
|
-
const nextName = nextProvider ? nextProvider
|
|
2908
|
+
const nextName = nextProvider ? this.getProviderName(nextProvider, i + 1) : "None";
|
|
2881
2909
|
console.warn(
|
|
2882
2910
|
`[FallbackLLMProvider] ${providerName} failed: "${errorMessage}". Failing over to next provider: ${nextName}`
|
|
2883
2911
|
);
|
|
@@ -3006,8 +3034,12 @@ var TieredLLMProvider = class _TieredLLMProvider {
|
|
|
3006
3034
|
// src/adapters/rules/static-rules.adapter.ts
|
|
3007
3035
|
var StaticRulesAdapter = class {
|
|
3008
3036
|
rules;
|
|
3009
|
-
constructor(rules) {
|
|
3010
|
-
this.rules = rules
|
|
3037
|
+
constructor(rules = []) {
|
|
3038
|
+
this.rules = rules.map((r) => {
|
|
3039
|
+
if (typeof r === "string") return r;
|
|
3040
|
+
if (r && typeof r === "object" && typeof r.rule === "string") return r.rule;
|
|
3041
|
+
return String(r);
|
|
3042
|
+
});
|
|
3011
3043
|
}
|
|
3012
3044
|
// Optional tenantId can be used for tenant-specific rules
|
|
3013
3045
|
async getActiveRules(tenantId) {
|
|
@@ -3029,6 +3061,12 @@ var LocalFaqAdapter = class {
|
|
|
3029
3061
|
this.smlEngine = options?.smlEngine || new SMLEngine();
|
|
3030
3062
|
this.defaultThreshold = options?.defaultMatchThreshold ?? 0.6;
|
|
3031
3063
|
}
|
|
3064
|
+
setSMLEngine(engine) {
|
|
3065
|
+
this.smlEngine = engine;
|
|
3066
|
+
}
|
|
3067
|
+
getSMLEngine() {
|
|
3068
|
+
return this.smlEngine;
|
|
3069
|
+
}
|
|
3032
3070
|
/**
|
|
3033
3071
|
* Initializes the adapter by reading the JSON file and caching embeddings in RAM.
|
|
3034
3072
|
*/
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export type JobStatus = 'pending' | 'queued' | 'processing' | 'completed' | 'failed';
|
|
2
|
+
export declare const JobStatusValues: {
|
|
3
|
+
readonly PENDING: 'pending';
|
|
4
|
+
readonly QUEUED: 'queued';
|
|
5
|
+
readonly PROCESSING: 'processing';
|
|
6
|
+
readonly COMPLETED: 'completed';
|
|
7
|
+
readonly FAILED: 'failed';
|
|
8
|
+
};
|
|
2
9
|
export interface Job<TData = any, TResult = any> {
|
|
3
10
|
attemptsMade?: number | undefined;
|
|
4
11
|
maxAttempts?: number | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export { OllamaAdapter, type OllamaConfig } from './adapters/llm/ollama.adapter.
|
|
|
39
39
|
export { FallbackLLMProvider, type FallbackProviderOptions } from './adapters/llm/fallback.adapter.js';
|
|
40
40
|
export { TieredLLMProvider, type TieredLLMConfig } from './adapters/llm/tiered.adapter.js';
|
|
41
41
|
export { MemoryVectorAdapter } from './adapters/vector/memory-vector.adapter.js';
|
|
42
|
-
export { StaticRulesAdapter } from './adapters/rules/static-rules.adapter.js';
|
|
42
|
+
export { StaticRulesAdapter, type RuleInput } from './adapters/rules/static-rules.adapter.js';
|
|
43
43
|
export { UrlFaqAdapter } from './adapters/faq/url-faq.adapter.js';
|
|
44
44
|
export { LocalFaqAdapter, type LocalFaqAdapterOptions } from './adapters/faq/local-faq.adapter.js';
|
|
45
45
|
export { RedisConfirmationNonceStore, MemoryConfirmationNonceStore, type ConfirmationNonceStore } from './core/security/nonce-store.js';
|
package/dist/index.js
CHANGED
|
@@ -531,11 +531,11 @@ var InjectionDetector = class {
|
|
|
531
531
|
// 2. Jailbreaks, DAN modes, role hijacking
|
|
532
532
|
{
|
|
533
533
|
id: "JAILBREAK_MODE_EN",
|
|
534
|
-
regex: /\b(you\s+are\s+now|act\s+as|switch\s+to|enter)\s+(an?\s+)?(developer|dan|jailbreak|unrestricted|unfiltered|god)\s*(mode|persona|ai)?\b/i
|
|
534
|
+
regex: /\b(you\s+are\s+now|act\s+as|switch\s+to|enter)\s+(in\s+(an?\s+)?|an?\s+)?(developer|dan|jailbreak|unrestricted|unfiltered|god)\s*(mode|persona|ai)?\b/i
|
|
535
535
|
},
|
|
536
536
|
{
|
|
537
537
|
id: "JAILBREAK_MODE_TR",
|
|
538
|
-
regex:
|
|
538
|
+
regex: /(?:^|\s|[.,!?])(artık|şimdi)\s+(bir\s+)?(geliştirici|dan|kısıtlamasız|admin|jailbreak)\s+(modundasın|moduna\s+geç|olarak\s+davran)(?:$|\s|[.,!?])/i
|
|
539
539
|
},
|
|
540
540
|
{
|
|
541
541
|
id: "DISABLE_SAFETY_EN",
|
|
@@ -1561,6 +1561,9 @@ var DocumentIngestionService = class _DocumentIngestionService {
|
|
|
1561
1561
|
if (chunk.length > 0) {
|
|
1562
1562
|
chunks.push(chunk);
|
|
1563
1563
|
}
|
|
1564
|
+
if (endIndex >= text.length) {
|
|
1565
|
+
break;
|
|
1566
|
+
}
|
|
1564
1567
|
startIndex = Math.max(startIndex + 1, endIndex - overlap);
|
|
1565
1568
|
}
|
|
1566
1569
|
return chunks;
|
|
@@ -1941,6 +1944,12 @@ var MemoryVectorAdapter = class {
|
|
|
1941
1944
|
smlEngine;
|
|
1942
1945
|
documents = [];
|
|
1943
1946
|
bm25Index = new BM25Index();
|
|
1947
|
+
setSMLEngine(engine) {
|
|
1948
|
+
this.smlEngine = engine;
|
|
1949
|
+
}
|
|
1950
|
+
getSMLEngine() {
|
|
1951
|
+
return this.smlEngine;
|
|
1952
|
+
}
|
|
1944
1953
|
/**
|
|
1945
1954
|
* Adds documents to memory, computes their embeddings, and indexes them in BM25.
|
|
1946
1955
|
*/
|
|
@@ -2042,6 +2051,12 @@ var RAGEngine = class {
|
|
|
2042
2051
|
}
|
|
2043
2052
|
this.smlEngine = new SMLEngine({ modelName: config.smlConfig?.modelName });
|
|
2044
2053
|
const vectorStore = config.inputs?.vectorStore || new MemoryVectorAdapter(this.smlEngine);
|
|
2054
|
+
if (typeof vectorStore.setSMLEngine === "function") {
|
|
2055
|
+
vectorStore.setSMLEngine(this.smlEngine);
|
|
2056
|
+
}
|
|
2057
|
+
if (config.inputs?.faq && typeof config.inputs.faq.setSMLEngine === "function") {
|
|
2058
|
+
config.inputs.faq.setSMLEngine(this.smlEngine);
|
|
2059
|
+
}
|
|
2045
2060
|
this.config = {
|
|
2046
2061
|
...config,
|
|
2047
2062
|
inputs: {
|
|
@@ -2708,6 +2723,15 @@ var RAGEvaluator = class {
|
|
|
2708
2723
|
}
|
|
2709
2724
|
};
|
|
2710
2725
|
|
|
2726
|
+
// src/core/queue/job-queue.interface.ts
|
|
2727
|
+
var JobStatusValues = {
|
|
2728
|
+
PENDING: "pending",
|
|
2729
|
+
QUEUED: "queued",
|
|
2730
|
+
PROCESSING: "processing",
|
|
2731
|
+
COMPLETED: "completed",
|
|
2732
|
+
FAILED: "failed"
|
|
2733
|
+
};
|
|
2734
|
+
|
|
2711
2735
|
// src/core/queue/bullmq-queue.ts
|
|
2712
2736
|
import { Queue, Worker, UnrecoverableError } from "bullmq";
|
|
2713
2737
|
import { Redis } from "ioredis";
|
|
@@ -3716,11 +3740,24 @@ var FallbackLLMProvider = class {
|
|
|
3716
3740
|
this.providers = providers;
|
|
3717
3741
|
this.logFailover = options?.logFailover ?? true;
|
|
3718
3742
|
}
|
|
3743
|
+
getProviderName(provider, index) {
|
|
3744
|
+
if (provider.name && typeof provider.name === "string") {
|
|
3745
|
+
return provider.name;
|
|
3746
|
+
}
|
|
3747
|
+
if (provider.model && typeof provider.model === "string") {
|
|
3748
|
+
const ctor = provider.constructor?.name && provider.constructor.name !== "Object" ? provider.constructor.name : "LLMProvider";
|
|
3749
|
+
return `${ctor}(${provider.model})`;
|
|
3750
|
+
}
|
|
3751
|
+
if (provider.constructor?.name && provider.constructor.name !== "Object") {
|
|
3752
|
+
return provider.constructor.name;
|
|
3753
|
+
}
|
|
3754
|
+
return `Provider#${index + 1}`;
|
|
3755
|
+
}
|
|
3719
3756
|
async generate(request) {
|
|
3720
3757
|
const failureErrors = [];
|
|
3721
3758
|
for (let i = 0; i < this.providers.length; i++) {
|
|
3722
3759
|
const provider = this.providers[i];
|
|
3723
|
-
const providerName = provider
|
|
3760
|
+
const providerName = this.getProviderName(provider, i);
|
|
3724
3761
|
try {
|
|
3725
3762
|
return await provider.generate(request);
|
|
3726
3763
|
} catch (error) {
|
|
@@ -3728,7 +3765,7 @@ var FallbackLLMProvider = class {
|
|
|
3728
3765
|
failureErrors.push({ providerName, error: errorMessage });
|
|
3729
3766
|
if (this.logFailover) {
|
|
3730
3767
|
const nextProvider = this.providers[i + 1];
|
|
3731
|
-
const nextName = nextProvider ? nextProvider
|
|
3768
|
+
const nextName = nextProvider ? this.getProviderName(nextProvider, i + 1) : "None";
|
|
3732
3769
|
console.warn(
|
|
3733
3770
|
`[FallbackLLMProvider] ${providerName} failed: "${errorMessage}". Failing over to next provider: ${nextName}`
|
|
3734
3771
|
);
|
|
@@ -3857,8 +3894,12 @@ var TieredLLMProvider = class _TieredLLMProvider {
|
|
|
3857
3894
|
// src/adapters/rules/static-rules.adapter.ts
|
|
3858
3895
|
var StaticRulesAdapter = class {
|
|
3859
3896
|
rules;
|
|
3860
|
-
constructor(rules) {
|
|
3861
|
-
this.rules = rules
|
|
3897
|
+
constructor(rules = []) {
|
|
3898
|
+
this.rules = rules.map((r) => {
|
|
3899
|
+
if (typeof r === "string") return r;
|
|
3900
|
+
if (r && typeof r === "object" && typeof r.rule === "string") return r.rule;
|
|
3901
|
+
return String(r);
|
|
3902
|
+
});
|
|
3862
3903
|
}
|
|
3863
3904
|
// Optional tenantId can be used for tenant-specific rules
|
|
3864
3905
|
async getActiveRules(tenantId) {
|
|
@@ -3915,6 +3956,12 @@ var LocalFaqAdapter = class {
|
|
|
3915
3956
|
this.smlEngine = options?.smlEngine || new SMLEngine();
|
|
3916
3957
|
this.defaultThreshold = options?.defaultMatchThreshold ?? 0.6;
|
|
3917
3958
|
}
|
|
3959
|
+
setSMLEngine(engine) {
|
|
3960
|
+
this.smlEngine = engine;
|
|
3961
|
+
}
|
|
3962
|
+
getSMLEngine() {
|
|
3963
|
+
return this.smlEngine;
|
|
3964
|
+
}
|
|
3918
3965
|
/**
|
|
3919
3966
|
* Initializes the adapter by reading the JSON file and caching embeddings in RAM.
|
|
3920
3967
|
*/
|
|
@@ -4474,6 +4521,7 @@ export {
|
|
|
4474
4521
|
IngestionWorker,
|
|
4475
4522
|
InjectionDetector,
|
|
4476
4523
|
InputSanitizer,
|
|
4524
|
+
JobStatusValues,
|
|
4477
4525
|
LocalFaqAdapter,
|
|
4478
4526
|
MemoryConfirmationNonceStore,
|
|
4479
4527
|
MemoryVectorAdapter,
|
package/dist/worker.js
CHANGED
|
@@ -1237,6 +1237,9 @@ var DocumentIngestionService = class _DocumentIngestionService {
|
|
|
1237
1237
|
if (chunk.length > 0) {
|
|
1238
1238
|
chunks.push(chunk);
|
|
1239
1239
|
}
|
|
1240
|
+
if (endIndex >= text.length) {
|
|
1241
|
+
break;
|
|
1242
|
+
}
|
|
1240
1243
|
startIndex = Math.max(startIndex + 1, endIndex - overlap);
|
|
1241
1244
|
}
|
|
1242
1245
|
return chunks;
|
package/docs/RELEASING.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Policy
|
|
4
4
|
|
|
5
|
-
The recommended first public version is **2.2.0**: the repository already identifies its preceding API as 2.1.0, and the new distribution includes durable ingestion and persistence.
|
|
5
|
+
The recommended first public version is **2.2.0**: the repository already identifies its preceding API as 2.1.0, and the new distribution includes durable ingestion and persistence. Version **2.2.0** is the official initial release published on npm under `@denizsvnc/ai-rag-engine`.
|
|
6
6
|
|
|
7
7
|
After the first public release, use patch releases for compatible fixes, minor releases for compatible features, and major releases for incompatible public API, security-contract or supported-runtime changes. Document security-driven breaks and migration paths. Never reuse a published version; do not silently modify artifacts after review.
|
|
8
8
|
|
package/docs/USAGE.md
CHANGED
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Runtime and module contract
|
|
4
4
|
|
|
5
|
-
Install `@denizsvnc/ai-rag-engine`
|
|
5
|
+
Install `@denizsvnc/ai-rag-engine` from npm:
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @denizsvnc/ai-rag-engine
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Use ESM (`"type": "module"` in the application). CommonJS `require()` is not a supported contract; CommonJS applications can use asynchronous `import()`. Node.js 22.14+ is required; Node 22/24 are the explicit test matrix. TypeScript 5.8+ is recommended; NodeNext and Bundler resolution are validated with strict checking. `skipLibCheck` is not required. Supported exports are the root API and `./package.json`; internal `dist/` paths are private. CLI commands are separate entry points.
|
|
6
12
|
|
|
7
13
|
The library never automatically loads `.env`. Applications may call `dotenv.config()` themselves. The server/worker/migration CLIs explicitly load `.env`. Importing the root library creates no server, connection, model download, or background worker. Native Transformers is imported lazily on the first embedding initialization.
|
|
8
14
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@denizsvnc/ai-rag-engine",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "TypeScript RAG engine with pluggable providers, local semantic routing, tenant-aware retrieval, and durable document ingestion.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|