@rcrsr/rill-ext-pinecone 0.8.3 → 0.8.5
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/dist/index.d.ts +87 -3
- package/dist/index.js +633 -9
- package/package.json +10 -6
- package/dist/factory.d.ts +0 -26
- package/dist/factory.d.ts.map +0 -1
- package/dist/factory.js +0 -597
- package/dist/factory.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/types.d.ts +0 -63
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -6
- package/dist/types.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,633 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// src/factory.ts
|
|
2
|
+
import { Pinecone } from "@pinecone-database/pinecone";
|
|
3
|
+
import {
|
|
4
|
+
RuntimeError as RuntimeError4,
|
|
5
|
+
emitExtensionEvent as emitExtensionEvent3,
|
|
6
|
+
createVector
|
|
7
|
+
} from "@rcrsr/rill";
|
|
8
|
+
|
|
9
|
+
// ../../shared/ext-vector/dist/errors.js
|
|
10
|
+
import { RuntimeError } from "@rcrsr/rill";
|
|
11
|
+
function mapVectorError(provider, error) {
|
|
12
|
+
if (!(error instanceof Error)) {
|
|
13
|
+
return new RuntimeError("RILL-R004", `${provider}: unknown error`);
|
|
14
|
+
}
|
|
15
|
+
const message = error.message;
|
|
16
|
+
if (message.includes("401") || message.toLowerCase().includes("unauthorized")) {
|
|
17
|
+
return new RuntimeError("RILL-R004", `${provider}: authentication failed (401)`);
|
|
18
|
+
}
|
|
19
|
+
if (message.toLowerCase().includes("collection") && message.toLowerCase().includes("not found")) {
|
|
20
|
+
return new RuntimeError("RILL-R004", `${provider}: collection not found`);
|
|
21
|
+
}
|
|
22
|
+
if (message.includes("429") || message.toLowerCase().includes("rate limit")) {
|
|
23
|
+
return new RuntimeError("RILL-R004", `${provider}: rate limit exceeded`);
|
|
24
|
+
}
|
|
25
|
+
if (error.name === "AbortError" || message.toLowerCase().includes("timeout")) {
|
|
26
|
+
return new RuntimeError("RILL-R004", `${provider}: request timeout`);
|
|
27
|
+
}
|
|
28
|
+
if (message.toLowerCase().includes("dimension")) {
|
|
29
|
+
const match = message.match(/expected (\d+).*got (\d+)|(\d+).*?expected.*?(\d+)/i);
|
|
30
|
+
if (match) {
|
|
31
|
+
const expected = match[1] || match[4];
|
|
32
|
+
const actual = match[2] || match[3];
|
|
33
|
+
return new RuntimeError("RILL-R004", `${provider}: dimension mismatch (expected ${expected}, got ${actual})`);
|
|
34
|
+
}
|
|
35
|
+
return new RuntimeError("RILL-R004", `${provider}: dimension mismatch`);
|
|
36
|
+
}
|
|
37
|
+
if (message.toLowerCase().includes("already exists")) {
|
|
38
|
+
return new RuntimeError("RILL-R004", `${provider}: collection already exists`);
|
|
39
|
+
}
|
|
40
|
+
return new RuntimeError("RILL-R004", `${provider}: ${message}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ../../shared/ext-vector/dist/events.js
|
|
44
|
+
import { emitExtensionEvent } from "@rcrsr/rill";
|
|
45
|
+
async function withEventEmission(ctx, provider, operation, metadata, fn) {
|
|
46
|
+
const startTime = Date.now();
|
|
47
|
+
try {
|
|
48
|
+
const result = await fn();
|
|
49
|
+
const duration = Date.now() - startTime;
|
|
50
|
+
emitExtensionEvent(ctx, {
|
|
51
|
+
event: `${provider}:${operation}`,
|
|
52
|
+
subsystem: `extension:${provider}`,
|
|
53
|
+
duration,
|
|
54
|
+
...metadata
|
|
55
|
+
});
|
|
56
|
+
return result;
|
|
57
|
+
} catch (error) {
|
|
58
|
+
const duration = Date.now() - startTime;
|
|
59
|
+
const rillError = mapVectorError(provider, error);
|
|
60
|
+
emitExtensionEvent(ctx, {
|
|
61
|
+
event: `${provider}:error`,
|
|
62
|
+
subsystem: `extension:${provider}`,
|
|
63
|
+
error: rillError.message,
|
|
64
|
+
duration
|
|
65
|
+
});
|
|
66
|
+
throw rillError;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ../../shared/ext-vector/dist/batch.js
|
|
71
|
+
import { RuntimeError as RuntimeError2 } from "@rcrsr/rill";
|
|
72
|
+
|
|
73
|
+
// ../../shared/ext-vector/dist/disposal.js
|
|
74
|
+
import { RuntimeError as RuntimeError3 } from "@rcrsr/rill";
|
|
75
|
+
function createDisposalState(_provider) {
|
|
76
|
+
return { isDisposed: false };
|
|
77
|
+
}
|
|
78
|
+
function checkDisposed(state, provider) {
|
|
79
|
+
if (state.isDisposed) {
|
|
80
|
+
throw new RuntimeError3("RILL-R004", `${provider}: operation cancelled`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function dispose(state, cleanup) {
|
|
84
|
+
if (state.isDisposed) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (cleanup) {
|
|
88
|
+
try {
|
|
89
|
+
await cleanup();
|
|
90
|
+
} catch (error) {
|
|
91
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
92
|
+
console.warn(`Cleanup failed: ${message}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
state.isDisposed = true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ../../shared/ext-vector/dist/validation.js
|
|
99
|
+
function assertRequired(value, fieldName) {
|
|
100
|
+
if (value === void 0) {
|
|
101
|
+
throw new Error(`${fieldName} is required`);
|
|
102
|
+
}
|
|
103
|
+
if (value === null) {
|
|
104
|
+
throw new Error(`${fieldName} is required`);
|
|
105
|
+
}
|
|
106
|
+
if (value === "") {
|
|
107
|
+
throw new Error(`${fieldName} is required`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// ../../shared/ext-vector/dist/wrapper.js
|
|
112
|
+
import { emitExtensionEvent as emitExtensionEvent2 } from "@rcrsr/rill";
|
|
113
|
+
|
|
114
|
+
// src/factory.ts
|
|
115
|
+
function mapPineconeError(error) {
|
|
116
|
+
if (error instanceof Error) {
|
|
117
|
+
const message = error.message;
|
|
118
|
+
if (message.toLowerCase().includes("authentication")) {
|
|
119
|
+
return new RuntimeError4(
|
|
120
|
+
"RILL-R004",
|
|
121
|
+
"pinecone: authentication failed (401)"
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (message.toLowerCase().includes("index") && message.toLowerCase().includes("not found")) {
|
|
125
|
+
return new RuntimeError4("RILL-R004", "pinecone: collection not found");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return mapVectorError("pinecone", error);
|
|
129
|
+
}
|
|
130
|
+
function createPineconeExtension(config) {
|
|
131
|
+
assertRequired(config.apiKey, "apiKey");
|
|
132
|
+
assertRequired(config.index, "index");
|
|
133
|
+
const client = new Pinecone({
|
|
134
|
+
apiKey: config.apiKey
|
|
135
|
+
});
|
|
136
|
+
const factoryIndex = config.index;
|
|
137
|
+
const factoryNamespace = config.namespace ?? "";
|
|
138
|
+
const disposalState = createDisposalState("pinecone");
|
|
139
|
+
const dispose2 = async () => {
|
|
140
|
+
await dispose(disposalState);
|
|
141
|
+
};
|
|
142
|
+
const checkDisposed2 = () => {
|
|
143
|
+
checkDisposed(disposalState, "pinecone");
|
|
144
|
+
};
|
|
145
|
+
const convertMetadata = (input) => {
|
|
146
|
+
const result2 = {};
|
|
147
|
+
for (const [key, value] of Object.entries(input)) {
|
|
148
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
149
|
+
result2[key] = value;
|
|
150
|
+
} else {
|
|
151
|
+
result2[key] = String(value);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return result2;
|
|
155
|
+
};
|
|
156
|
+
const result = {
|
|
157
|
+
// IR-1: pinecone::upsert
|
|
158
|
+
upsert: {
|
|
159
|
+
params: [
|
|
160
|
+
{ name: "id", type: "string" },
|
|
161
|
+
{ name: "vector", type: "vector" },
|
|
162
|
+
{ name: "metadata", type: "dict", defaultValue: {} }
|
|
163
|
+
],
|
|
164
|
+
fn: async (args, ctx) => {
|
|
165
|
+
checkDisposed2();
|
|
166
|
+
const id = args[0];
|
|
167
|
+
const vector = args[1];
|
|
168
|
+
const metadataArg = args[2] ?? {};
|
|
169
|
+
const metadata = convertMetadata(metadataArg);
|
|
170
|
+
return withEventEmission(
|
|
171
|
+
ctx,
|
|
172
|
+
"pinecone",
|
|
173
|
+
"upsert",
|
|
174
|
+
{ id },
|
|
175
|
+
async () => {
|
|
176
|
+
const index = client.Index(factoryIndex);
|
|
177
|
+
await index.namespace(factoryNamespace).upsert([
|
|
178
|
+
{
|
|
179
|
+
id,
|
|
180
|
+
values: Array.from(vector.data),
|
|
181
|
+
metadata
|
|
182
|
+
}
|
|
183
|
+
]);
|
|
184
|
+
return {
|
|
185
|
+
id,
|
|
186
|
+
success: true
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
},
|
|
191
|
+
description: "Insert or update single vector with metadata",
|
|
192
|
+
returnType: "dict"
|
|
193
|
+
},
|
|
194
|
+
// IR-2: pinecone::upsert_batch
|
|
195
|
+
upsert_batch: {
|
|
196
|
+
params: [{ name: "items", type: "list" }],
|
|
197
|
+
fn: async (args, ctx) => {
|
|
198
|
+
const startTime = Date.now();
|
|
199
|
+
try {
|
|
200
|
+
checkDisposed2();
|
|
201
|
+
const items = args[0];
|
|
202
|
+
let succeeded = 0;
|
|
203
|
+
const index = client.Index(factoryIndex);
|
|
204
|
+
for (let i = 0; i < items.length; i++) {
|
|
205
|
+
const item = items[i];
|
|
206
|
+
if (!item || typeof item !== "object") {
|
|
207
|
+
const result2 = {
|
|
208
|
+
succeeded,
|
|
209
|
+
failed: `index ${i}`,
|
|
210
|
+
error: "invalid item structure"
|
|
211
|
+
};
|
|
212
|
+
const duration2 = Date.now() - startTime;
|
|
213
|
+
emitExtensionEvent3(ctx, {
|
|
214
|
+
event: "pinecone:upsert_batch",
|
|
215
|
+
subsystem: "extension:pinecone",
|
|
216
|
+
duration: duration2,
|
|
217
|
+
count: items.length,
|
|
218
|
+
succeeded
|
|
219
|
+
});
|
|
220
|
+
return result2;
|
|
221
|
+
}
|
|
222
|
+
const id = item["id"];
|
|
223
|
+
const vector = item["vector"];
|
|
224
|
+
const metadataArg = item["metadata"] ?? {};
|
|
225
|
+
const metadata = convertMetadata(metadataArg);
|
|
226
|
+
try {
|
|
227
|
+
await index.namespace(factoryNamespace).upsert([
|
|
228
|
+
{
|
|
229
|
+
id,
|
|
230
|
+
values: Array.from(vector.data),
|
|
231
|
+
metadata
|
|
232
|
+
}
|
|
233
|
+
]);
|
|
234
|
+
succeeded++;
|
|
235
|
+
} catch (error) {
|
|
236
|
+
const rillError = mapPineconeError(error);
|
|
237
|
+
const result2 = {
|
|
238
|
+
succeeded,
|
|
239
|
+
failed: id,
|
|
240
|
+
error: rillError.message
|
|
241
|
+
};
|
|
242
|
+
const duration2 = Date.now() - startTime;
|
|
243
|
+
emitExtensionEvent3(ctx, {
|
|
244
|
+
event: "pinecone:upsert_batch",
|
|
245
|
+
subsystem: "extension:pinecone",
|
|
246
|
+
duration: duration2,
|
|
247
|
+
count: items.length,
|
|
248
|
+
succeeded
|
|
249
|
+
});
|
|
250
|
+
return result2;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const duration = Date.now() - startTime;
|
|
254
|
+
emitExtensionEvent3(ctx, {
|
|
255
|
+
event: "pinecone:upsert_batch",
|
|
256
|
+
subsystem: "extension:pinecone",
|
|
257
|
+
duration,
|
|
258
|
+
count: items.length,
|
|
259
|
+
succeeded
|
|
260
|
+
});
|
|
261
|
+
return { succeeded };
|
|
262
|
+
} catch (error) {
|
|
263
|
+
const duration = Date.now() - startTime;
|
|
264
|
+
const rillError = mapPineconeError(error);
|
|
265
|
+
emitExtensionEvent3(ctx, {
|
|
266
|
+
event: "pinecone:error",
|
|
267
|
+
subsystem: "extension:pinecone",
|
|
268
|
+
error: rillError.message,
|
|
269
|
+
duration
|
|
270
|
+
});
|
|
271
|
+
throw rillError;
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
description: "Batch insert/update vectors",
|
|
275
|
+
returnType: "dict"
|
|
276
|
+
},
|
|
277
|
+
// IR-3: pinecone::search
|
|
278
|
+
search: {
|
|
279
|
+
params: [
|
|
280
|
+
{ name: "vector", type: "vector" },
|
|
281
|
+
{ name: "options", type: "dict", defaultValue: {} }
|
|
282
|
+
],
|
|
283
|
+
fn: async (args, ctx) => {
|
|
284
|
+
checkDisposed2();
|
|
285
|
+
const vector = args[0];
|
|
286
|
+
const options = args[1] ?? {};
|
|
287
|
+
const k = typeof options["k"] === "number" ? options["k"] : 10;
|
|
288
|
+
const filter = options["filter"] ?? {};
|
|
289
|
+
const scoreThreshold = typeof options["score_threshold"] === "number" ? options["score_threshold"] : void 0;
|
|
290
|
+
const startTime = Date.now();
|
|
291
|
+
try {
|
|
292
|
+
const index = client.Index(factoryIndex);
|
|
293
|
+
const searchRequest = {
|
|
294
|
+
vector: Array.from(vector.data),
|
|
295
|
+
topK: k,
|
|
296
|
+
includeMetadata: true
|
|
297
|
+
};
|
|
298
|
+
if (Object.keys(filter).length > 0) {
|
|
299
|
+
searchRequest.filter = filter;
|
|
300
|
+
}
|
|
301
|
+
const response = await index.namespace(factoryNamespace).query(searchRequest);
|
|
302
|
+
const results = (response.matches ?? []).map((hit) => {
|
|
303
|
+
const metadata = {};
|
|
304
|
+
if (hit.metadata) {
|
|
305
|
+
for (const [key, value] of Object.entries(hit.metadata)) {
|
|
306
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
307
|
+
metadata[key] = value;
|
|
308
|
+
} else {
|
|
309
|
+
metadata[key] = String(value);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return {
|
|
314
|
+
id: hit.id,
|
|
315
|
+
score: hit.score ?? 0,
|
|
316
|
+
metadata
|
|
317
|
+
};
|
|
318
|
+
});
|
|
319
|
+
let filtered = results;
|
|
320
|
+
if (scoreThreshold !== void 0 && Array.isArray(results)) {
|
|
321
|
+
filtered = results.filter(
|
|
322
|
+
(r) => (r["score"] ?? 0) >= scoreThreshold
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
const duration = Date.now() - startTime;
|
|
326
|
+
emitExtensionEvent3(ctx, {
|
|
327
|
+
event: "pinecone:search",
|
|
328
|
+
subsystem: "extension:pinecone",
|
|
329
|
+
duration,
|
|
330
|
+
result_count: Array.isArray(filtered) ? filtered.length : 0,
|
|
331
|
+
k
|
|
332
|
+
});
|
|
333
|
+
return filtered;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
const duration = Date.now() - startTime;
|
|
336
|
+
const rillError = mapPineconeError(error);
|
|
337
|
+
emitExtensionEvent3(ctx, {
|
|
338
|
+
event: "pinecone:error",
|
|
339
|
+
subsystem: "extension:pinecone",
|
|
340
|
+
error: rillError.message,
|
|
341
|
+
duration
|
|
342
|
+
});
|
|
343
|
+
throw rillError;
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
description: "Search k nearest neighbors",
|
|
347
|
+
returnType: "list"
|
|
348
|
+
},
|
|
349
|
+
// IR-4: pinecone::get
|
|
350
|
+
get: {
|
|
351
|
+
params: [{ name: "id", type: "string" }],
|
|
352
|
+
fn: async (args, ctx) => {
|
|
353
|
+
checkDisposed2();
|
|
354
|
+
const id = args[0];
|
|
355
|
+
return withEventEmission(
|
|
356
|
+
ctx,
|
|
357
|
+
"pinecone",
|
|
358
|
+
"get",
|
|
359
|
+
{ id },
|
|
360
|
+
async () => {
|
|
361
|
+
const index = client.Index(factoryIndex);
|
|
362
|
+
const response = await index.namespace(factoryNamespace).fetch([id]);
|
|
363
|
+
if (!response.records || response.records[id] === void 0) {
|
|
364
|
+
throw new RuntimeError4("RILL-R004", "pinecone: id not found");
|
|
365
|
+
}
|
|
366
|
+
const record = response.records[id];
|
|
367
|
+
const vectorData = record.values;
|
|
368
|
+
if (!vectorData || !Array.isArray(vectorData)) {
|
|
369
|
+
throw new RuntimeError4(
|
|
370
|
+
"RILL-R004",
|
|
371
|
+
"pinecone: invalid vector format"
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
const float32Data = new Float32Array(vectorData);
|
|
375
|
+
const vector = createVector(float32Data, factoryIndex);
|
|
376
|
+
return {
|
|
377
|
+
id,
|
|
378
|
+
vector,
|
|
379
|
+
metadata: record.metadata ?? {}
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
);
|
|
383
|
+
},
|
|
384
|
+
description: "Fetch vector by ID",
|
|
385
|
+
returnType: "dict"
|
|
386
|
+
},
|
|
387
|
+
// IR-5: pinecone::delete
|
|
388
|
+
delete: {
|
|
389
|
+
params: [{ name: "id", type: "string" }],
|
|
390
|
+
fn: async (args, ctx) => {
|
|
391
|
+
checkDisposed2();
|
|
392
|
+
const id = args[0];
|
|
393
|
+
return withEventEmission(
|
|
394
|
+
ctx,
|
|
395
|
+
"pinecone",
|
|
396
|
+
"delete",
|
|
397
|
+
{ id },
|
|
398
|
+
async () => {
|
|
399
|
+
const index = client.Index(factoryIndex);
|
|
400
|
+
const ns = factoryNamespace || "";
|
|
401
|
+
await index.namespace(ns).deleteOne(id);
|
|
402
|
+
return {
|
|
403
|
+
id,
|
|
404
|
+
deleted: true
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
},
|
|
409
|
+
description: "Delete vector by ID",
|
|
410
|
+
returnType: "dict"
|
|
411
|
+
},
|
|
412
|
+
// IR-6: pinecone::delete_batch
|
|
413
|
+
delete_batch: {
|
|
414
|
+
params: [{ name: "ids", type: "list" }],
|
|
415
|
+
fn: async (args, ctx) => {
|
|
416
|
+
const startTime = Date.now();
|
|
417
|
+
try {
|
|
418
|
+
checkDisposed2();
|
|
419
|
+
const ids = args[0];
|
|
420
|
+
let succeeded = 0;
|
|
421
|
+
const index = client.Index(factoryIndex);
|
|
422
|
+
for (let i = 0; i < ids.length; i++) {
|
|
423
|
+
const id = ids[i];
|
|
424
|
+
try {
|
|
425
|
+
await index.namespace(factoryNamespace).deleteOne(id);
|
|
426
|
+
succeeded++;
|
|
427
|
+
} catch (error) {
|
|
428
|
+
const rillError = mapPineconeError(error);
|
|
429
|
+
const result2 = {
|
|
430
|
+
succeeded,
|
|
431
|
+
failed: id,
|
|
432
|
+
error: rillError.message
|
|
433
|
+
};
|
|
434
|
+
const duration2 = Date.now() - startTime;
|
|
435
|
+
emitExtensionEvent3(ctx, {
|
|
436
|
+
event: "pinecone:delete_batch",
|
|
437
|
+
subsystem: "extension:pinecone",
|
|
438
|
+
duration: duration2,
|
|
439
|
+
count: ids.length,
|
|
440
|
+
succeeded
|
|
441
|
+
});
|
|
442
|
+
return result2;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
const duration = Date.now() - startTime;
|
|
446
|
+
emitExtensionEvent3(ctx, {
|
|
447
|
+
event: "pinecone:delete_batch",
|
|
448
|
+
subsystem: "extension:pinecone",
|
|
449
|
+
duration,
|
|
450
|
+
count: ids.length,
|
|
451
|
+
succeeded
|
|
452
|
+
});
|
|
453
|
+
return { succeeded };
|
|
454
|
+
} catch (error) {
|
|
455
|
+
const duration = Date.now() - startTime;
|
|
456
|
+
const rillError = mapPineconeError(error);
|
|
457
|
+
emitExtensionEvent3(ctx, {
|
|
458
|
+
event: "pinecone:error",
|
|
459
|
+
subsystem: "extension:pinecone",
|
|
460
|
+
error: rillError.message,
|
|
461
|
+
duration
|
|
462
|
+
});
|
|
463
|
+
throw rillError;
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
description: "Batch delete vectors",
|
|
467
|
+
returnType: "dict"
|
|
468
|
+
},
|
|
469
|
+
// IR-7: pinecone::count
|
|
470
|
+
count: {
|
|
471
|
+
params: [],
|
|
472
|
+
fn: async (_args, ctx) => {
|
|
473
|
+
checkDisposed2();
|
|
474
|
+
return withEventEmission(
|
|
475
|
+
ctx,
|
|
476
|
+
"pinecone",
|
|
477
|
+
"count",
|
|
478
|
+
{},
|
|
479
|
+
async () => {
|
|
480
|
+
const index = client.Index(factoryIndex);
|
|
481
|
+
const stats = await index.describeIndexStats();
|
|
482
|
+
const count = stats.namespaces?.[factoryNamespace]?.recordCount ?? 0;
|
|
483
|
+
return count;
|
|
484
|
+
}
|
|
485
|
+
);
|
|
486
|
+
},
|
|
487
|
+
description: "Return total vector count in collection",
|
|
488
|
+
returnType: "number"
|
|
489
|
+
},
|
|
490
|
+
// IR-8: pinecone::create_collection
|
|
491
|
+
create_collection: {
|
|
492
|
+
params: [
|
|
493
|
+
{ name: "name", type: "string" },
|
|
494
|
+
{ name: "options", type: "dict", defaultValue: {} }
|
|
495
|
+
],
|
|
496
|
+
fn: async (args, ctx) => {
|
|
497
|
+
checkDisposed2();
|
|
498
|
+
const name = args[0];
|
|
499
|
+
const options = args[1] ?? {};
|
|
500
|
+
const dimensions = options["dimensions"];
|
|
501
|
+
const distance = options["distance"] ?? "cosine";
|
|
502
|
+
if (!dimensions || typeof dimensions !== "number" || dimensions <= 0) {
|
|
503
|
+
throw new RuntimeError4(
|
|
504
|
+
"RILL-R004",
|
|
505
|
+
"pinecone: dimensions must be a positive integer"
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
return withEventEmission(
|
|
509
|
+
ctx,
|
|
510
|
+
"pinecone",
|
|
511
|
+
"create_collection",
|
|
512
|
+
{ name },
|
|
513
|
+
async () => {
|
|
514
|
+
let pineconeMetric;
|
|
515
|
+
if (distance === "cosine") {
|
|
516
|
+
pineconeMetric = "cosine";
|
|
517
|
+
} else if (distance === "euclidean") {
|
|
518
|
+
pineconeMetric = "euclidean";
|
|
519
|
+
} else {
|
|
520
|
+
pineconeMetric = "dotproduct";
|
|
521
|
+
}
|
|
522
|
+
await client.createIndex({
|
|
523
|
+
name,
|
|
524
|
+
dimension: dimensions,
|
|
525
|
+
metric: pineconeMetric,
|
|
526
|
+
spec: {
|
|
527
|
+
serverless: {
|
|
528
|
+
cloud: "aws",
|
|
529
|
+
region: "us-east-1"
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
return {
|
|
534
|
+
name,
|
|
535
|
+
created: true
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
);
|
|
539
|
+
},
|
|
540
|
+
description: "Create new vector collection",
|
|
541
|
+
returnType: "dict"
|
|
542
|
+
},
|
|
543
|
+
// IR-9: pinecone::delete_collection
|
|
544
|
+
delete_collection: {
|
|
545
|
+
params: [{ name: "name", type: "string" }],
|
|
546
|
+
fn: async (args, ctx) => {
|
|
547
|
+
checkDisposed2();
|
|
548
|
+
const name = args[0];
|
|
549
|
+
return withEventEmission(
|
|
550
|
+
ctx,
|
|
551
|
+
"pinecone",
|
|
552
|
+
"delete_collection",
|
|
553
|
+
{ name },
|
|
554
|
+
async () => {
|
|
555
|
+
await client.deleteIndex(name);
|
|
556
|
+
return {
|
|
557
|
+
name,
|
|
558
|
+
deleted: true
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
);
|
|
562
|
+
},
|
|
563
|
+
description: "Delete vector collection",
|
|
564
|
+
returnType: "dict"
|
|
565
|
+
},
|
|
566
|
+
// IR-10: pinecone::list_collections
|
|
567
|
+
list_collections: {
|
|
568
|
+
params: [],
|
|
569
|
+
fn: async (_args, ctx) => {
|
|
570
|
+
checkDisposed2();
|
|
571
|
+
return withEventEmission(
|
|
572
|
+
ctx,
|
|
573
|
+
"pinecone",
|
|
574
|
+
"list_collections",
|
|
575
|
+
{},
|
|
576
|
+
async () => {
|
|
577
|
+
const response = await client.listIndexes();
|
|
578
|
+
const names = response.indexes?.map((index) => index.name ?? "") ?? [];
|
|
579
|
+
return names;
|
|
580
|
+
}
|
|
581
|
+
);
|
|
582
|
+
},
|
|
583
|
+
description: "List all collection names",
|
|
584
|
+
returnType: "list"
|
|
585
|
+
},
|
|
586
|
+
// IR-11: pinecone::describe
|
|
587
|
+
describe: {
|
|
588
|
+
params: [],
|
|
589
|
+
fn: async (_args, ctx) => {
|
|
590
|
+
checkDisposed2();
|
|
591
|
+
return withEventEmission(
|
|
592
|
+
ctx,
|
|
593
|
+
"pinecone",
|
|
594
|
+
"describe",
|
|
595
|
+
{ name: factoryIndex },
|
|
596
|
+
async () => {
|
|
597
|
+
const index = client.Index(factoryIndex);
|
|
598
|
+
const stats = await index.describeIndexStats();
|
|
599
|
+
const indexInfo = await client.describeIndex(factoryIndex);
|
|
600
|
+
const dimensions = stats.dimension ?? 0;
|
|
601
|
+
const count = stats.namespaces?.[factoryNamespace]?.recordCount ?? 0;
|
|
602
|
+
let distance = "cosine";
|
|
603
|
+
const metric = indexInfo.metric;
|
|
604
|
+
if (metric === "cosine") {
|
|
605
|
+
distance = "cosine";
|
|
606
|
+
} else if (metric === "euclidean") {
|
|
607
|
+
distance = "euclidean";
|
|
608
|
+
} else if (metric === "dotproduct") {
|
|
609
|
+
distance = "dot";
|
|
610
|
+
}
|
|
611
|
+
return {
|
|
612
|
+
name: factoryIndex,
|
|
613
|
+
count,
|
|
614
|
+
dimensions,
|
|
615
|
+
distance
|
|
616
|
+
};
|
|
617
|
+
}
|
|
618
|
+
);
|
|
619
|
+
},
|
|
620
|
+
description: "Describe configured collection",
|
|
621
|
+
returnType: "dict"
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
result.dispose = dispose2;
|
|
625
|
+
return result;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// src/index.ts
|
|
629
|
+
var VERSION = "0.0.1";
|
|
630
|
+
export {
|
|
631
|
+
VERSION,
|
|
632
|
+
createPineconeExtension
|
|
633
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rcrsr/rill-ext-pinecone",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"description": "rill extension for Pinecone vector database integration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Andre Bremer",
|
|
@@ -17,10 +17,15 @@
|
|
|
17
17
|
"scripting"
|
|
18
18
|
],
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@rcrsr/rill": "^0.8.
|
|
20
|
+
"@rcrsr/rill": "^0.8.5"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@
|
|
23
|
+
"@types/node": "^25.2.3",
|
|
24
|
+
"dts-bundle-generator": "^9.5.1",
|
|
25
|
+
"tsup": "^8.5.0",
|
|
26
|
+
"undici-types": "^7.21.0",
|
|
27
|
+
"@rcrsr/rill": "^0.8.5",
|
|
28
|
+
"@rcrsr/rill-ext-vector-shared": "^0.0.1"
|
|
24
29
|
},
|
|
25
30
|
"files": [
|
|
26
31
|
"dist"
|
|
@@ -38,11 +43,10 @@
|
|
|
38
43
|
"access": "public"
|
|
39
44
|
},
|
|
40
45
|
"dependencies": {
|
|
41
|
-
"@pinecone-database/pinecone": "^3.0.3"
|
|
42
|
-
"@rcrsr/rill-ext-vector-shared": "^0.0.1"
|
|
46
|
+
"@pinecone-database/pinecone": "^3.0.3"
|
|
43
47
|
},
|
|
44
48
|
"scripts": {
|
|
45
|
-
"build": "
|
|
49
|
+
"build": "tsup && dts-bundle-generator --config dts-bundle-generator.config.cjs",
|
|
46
50
|
"test": "vitest run",
|
|
47
51
|
"typecheck": "tsc --noEmit",
|
|
48
52
|
"lint": "eslint --config ../../../eslint.config.js src/",
|
package/dist/factory.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Extension factory for Pinecone vector database integration.
|
|
3
|
-
* Creates extension instance with config validation and SDK lifecycle management.
|
|
4
|
-
*/
|
|
5
|
-
import { type ExtensionResult } from '@rcrsr/rill';
|
|
6
|
-
import type { PineconeConfig } from './types.js';
|
|
7
|
-
/**
|
|
8
|
-
* Create Pinecone extension instance.
|
|
9
|
-
* Validates configuration and returns host functions with cleanup.
|
|
10
|
-
*
|
|
11
|
-
* @param config - Extension configuration
|
|
12
|
-
* @returns ExtensionResult with 11 vector database functions and dispose
|
|
13
|
-
* @throws Error for invalid configuration (AC-10)
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* const ext = createPineconeExtension({
|
|
18
|
-
* apiKey: 'your-api-key',
|
|
19
|
-
* index: 'my-index',
|
|
20
|
-
* });
|
|
21
|
-
* // Use with rill runtime...
|
|
22
|
-
* await ext.dispose();
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export declare function createPineconeExtension(config: PineconeConfig): ExtensionResult;
|
|
26
|
-
//# sourceMappingURL=factory.d.ts.map
|