@retrivora-ai/rag-engine 2.1.7 → 2.2.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.
@@ -4,19 +4,19 @@ import { BaseVectorProvider } from './BaseVectorProvider';
4
4
  import { VectorMatch, UpsertDocument } from '../../types';
5
5
  import { IProviderValidator, IProviderHealthChecker, HealthCheckResult } from '../../core/ProviderInterfaces';
6
6
  import { ValidationError } from '../../core/ConfigValidator';
7
+ import { ConfigFetcher } from '../../core/ConfigFetcher';
7
8
 
8
9
  /**
9
10
  * PineconeProvider — Pinecone vector database implementation.
10
11
  */
11
12
  export class PineconeProvider extends BaseVectorProvider {
12
13
  private client!: Pinecone;
13
- private readonly apiKey: string;
14
+ private apiKey: string;
14
15
 
15
16
  constructor(config: VectorDBConfig) {
16
17
  super(config);
17
- const opts = config.options as Record<string, string>;
18
- if (!opts.apiKey) throw new Error('[PineconeProvider] options.apiKey is required');
19
- this.apiKey = opts.apiKey;
18
+ const opts = (config.options || {}) as Record<string, string>;
19
+ this.apiKey = opts.apiKey || process.env.PINECONE_API_KEY || '';
20
20
  }
21
21
 
22
22
  static getValidator(): IProviderValidator {
@@ -24,12 +24,17 @@ export class PineconeProvider extends BaseVectorProvider {
24
24
  validate(config: Record<string, unknown>): ValidationError[] {
25
25
  const errors: ValidationError[] = [];
26
26
  const opts = (config.options || {}) as Record<string, unknown>;
27
+ const hasLicenseKey = Boolean(
28
+ config.licenseKey ||
29
+ process.env.RETRIVORA_LICENSE_KEY ||
30
+ process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY
31
+ );
27
32
 
28
- if (!opts.apiKey) {
33
+ if (!opts.apiKey && !hasLicenseKey) {
29
34
  errors.push({
30
35
  field: 'vectorDb.options.apiKey',
31
- message: 'Pinecone API key is required',
32
- suggestion: 'Set PINECONE_API_KEY environment variable',
36
+ message: 'Pinecone API key is required when RETRIVORA_LICENSE_KEY is not set',
37
+ suggestion: 'Set PINECONE_API_KEY environment variable or supply RETRIVORA_LICENSE_KEY for keyless vector storage',
33
38
  severity: 'error',
34
39
  });
35
40
  }
@@ -78,23 +83,55 @@ export class PineconeProvider extends BaseVectorProvider {
78
83
  }
79
84
 
80
85
  async initialize(): Promise<void> {
81
- this.client = new Pinecone({ apiKey: this.apiKey });
82
- const indexes = await this.client.listIndexes();
83
- const names = indexes.indexes?.map((i) => i.name) ?? [];
84
- if (!names.includes(this.indexName)) {
85
- throw new Error(
86
- `[PineconeProvider] Index "${this.indexName}" not found. Available: ${names.join(', ')}`
87
- );
86
+ if (this.client) return;
87
+
88
+ let key = this.apiKey || process.env.PINECONE_API_KEY || '';
89
+
90
+ if (!key) {
91
+ const projectId = process.env.RAG_PROJECT_ID || process.env.NEXT_PUBLIC_RAG_PROJECT_ID || 'my-rag-app';
92
+ const licenseKey = process.env.RETRIVORA_LICENSE_KEY || process.env.NEXT_PUBLIC_RETRIVORA_LICENSE_KEY;
93
+
94
+ const remoteConfig = await ConfigFetcher.fetchRemoteVectorConfig(projectId, licenseKey);
95
+ if (remoteConfig?.apiKey) {
96
+ key = remoteConfig.apiKey;
97
+ this.apiKey = key;
98
+ if (remoteConfig.indexName) {
99
+ this.indexName = remoteConfig.indexName;
100
+ }
101
+ }
102
+ }
103
+
104
+ if (!key) {
105
+ console.warn('[PineconeProvider] Warning: No Pinecone API key available locally or remotely.');
106
+ return;
107
+ }
108
+
109
+ this.client = new Pinecone({ apiKey: key });
110
+ try {
111
+ const indexes = await this.client.listIndexes();
112
+ const names = indexes.indexes?.map((i) => i.name) ?? [];
113
+ if (!names.includes(this.indexName)) {
114
+ console.warn(`[PineconeProvider] Target index "${this.indexName}" not listed. Proceeding with configured index name.`);
115
+ }
116
+ } catch (err) {
117
+ console.warn('[PineconeProvider] List index verification warning:', err instanceof Error ? err.message : String(err));
88
118
  }
89
119
  }
90
120
 
91
- private index(namespace?: string) {
121
+ private async getActiveIndex(namespace?: string) {
122
+ if (!this.client) {
123
+ await this.initialize();
124
+ }
125
+ if (!this.client) {
126
+ throw new Error('[PineconeProvider] Cannot execute vector operation: Pinecone client failed to initialize.');
127
+ }
92
128
  const idx = this.client.index(this.indexName);
93
129
  return namespace ? idx.namespace(namespace) : idx.namespace('');
94
130
  }
95
131
 
96
132
  async upsert(doc: UpsertDocument, namespace?: string): Promise<void> {
97
- await this.index(namespace).upsert({
133
+ const targetIdx = await this.getActiveIndex(namespace);
134
+ await targetIdx.upsert({
98
135
  records: [{
99
136
  id: String(doc.id),
100
137
  values: doc.vector,
@@ -104,6 +141,7 @@ export class PineconeProvider extends BaseVectorProvider {
104
141
  }
105
142
 
106
143
  async batchUpsert(docs: UpsertDocument[], namespace?: string): Promise<void> {
144
+ const targetIdx = await this.getActiveIndex(namespace);
107
145
  const BATCH = 100;
108
146
  for (let i = 0; i < docs.length; i += BATCH) {
109
147
  const records = docs.slice(i, i + BATCH).map((d) => ({
@@ -111,7 +149,7 @@ export class PineconeProvider extends BaseVectorProvider {
111
149
  values: d.vector,
112
150
  metadata: { content: d.content, ...(d.metadata ?? {}) } as RecordMetadata,
113
151
  }));
114
- await this.index(namespace).upsert({ records });
152
+ await targetIdx.upsert({ records });
115
153
  }
116
154
  }
117
155
 
@@ -121,8 +159,9 @@ export class PineconeProvider extends BaseVectorProvider {
121
159
  namespace?: string,
122
160
  filter?: Record<string, unknown>
123
161
  ): Promise<VectorMatch[]> {
162
+ const targetIdx = await this.getActiveIndex(namespace);
124
163
  const pineconeFilter = this.sanitizeFilter(filter);
125
- const result = await this.index(namespace).query({
164
+ const result = await targetIdx.query({
126
165
  vector,
127
166
  topK,
128
167
  includeMetadata: true,
@@ -137,15 +176,19 @@ export class PineconeProvider extends BaseVectorProvider {
137
176
  }
138
177
 
139
178
  async delete(id: string | number, namespace?: string): Promise<void> {
140
- await this.index(namespace).deleteOne({ id: String(id) });
179
+ const targetIdx = await this.getActiveIndex(namespace);
180
+ await targetIdx.deleteOne({ id: String(id) });
141
181
  }
142
182
 
143
183
  async deleteNamespace(namespace: string): Promise<void> {
144
- await this.client.index(this.indexName).namespace(namespace).deleteAll();
184
+ const targetIdx = await this.getActiveIndex(namespace);
185
+ await targetIdx.deleteAll();
145
186
  }
146
187
 
147
188
  async ping(): Promise<boolean> {
148
189
  try {
190
+ if (!this.client) await this.initialize();
191
+ if (!this.client) return false;
149
192
  await this.client.listIndexes();
150
193
  return true;
151
194
  } catch {