@sparkleideas/plugins 3.0.0-alpha.10
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/README.md +401 -0
- package/__tests__/collection-manager.test.ts +332 -0
- package/__tests__/dependency-graph.test.ts +434 -0
- package/__tests__/enhanced-plugin-registry.test.ts +488 -0
- package/__tests__/plugin-registry.test.ts +368 -0
- package/__tests__/ruvector-bridge.test.ts +2429 -0
- package/__tests__/ruvector-integration.test.ts +1602 -0
- package/__tests__/ruvector-migrations.test.ts +1099 -0
- package/__tests__/ruvector-quantization.test.ts +846 -0
- package/__tests__/ruvector-streaming.test.ts +1088 -0
- package/__tests__/sdk.test.ts +325 -0
- package/__tests__/security.test.ts +348 -0
- package/__tests__/utils/ruvector-test-utils.ts +860 -0
- package/examples/plugin-creator/index.ts +636 -0
- package/examples/plugin-creator/plugin-creator.test.ts +312 -0
- package/examples/ruvector/README.md +288 -0
- package/examples/ruvector/attention-patterns.ts +394 -0
- package/examples/ruvector/basic-usage.ts +288 -0
- package/examples/ruvector/docker-compose.yml +75 -0
- package/examples/ruvector/gnn-analysis.ts +501 -0
- package/examples/ruvector/hyperbolic-hierarchies.ts +557 -0
- package/examples/ruvector/init-db.sql +119 -0
- package/examples/ruvector/quantization.ts +680 -0
- package/examples/ruvector/self-learning.ts +447 -0
- package/examples/ruvector/semantic-search.ts +576 -0
- package/examples/ruvector/streaming-large-data.ts +507 -0
- package/examples/ruvector/transactions.ts +594 -0
- package/examples/ruvector-plugins/hook-pattern-library.ts +486 -0
- package/examples/ruvector-plugins/index.ts +79 -0
- package/examples/ruvector-plugins/intent-router.ts +354 -0
- package/examples/ruvector-plugins/mcp-tool-optimizer.ts +424 -0
- package/examples/ruvector-plugins/reasoning-bank.ts +657 -0
- package/examples/ruvector-plugins/ruvector-plugins.test.ts +518 -0
- package/examples/ruvector-plugins/semantic-code-search.ts +498 -0
- package/examples/ruvector-plugins/shared/index.ts +20 -0
- package/examples/ruvector-plugins/shared/vector-utils.ts +257 -0
- package/examples/ruvector-plugins/sona-learning.ts +445 -0
- package/package.json +97 -0
- package/src/collections/collection-manager.ts +661 -0
- package/src/collections/index.ts +56 -0
- package/src/collections/official/index.ts +1040 -0
- package/src/core/base-plugin.ts +416 -0
- package/src/core/plugin-interface.ts +215 -0
- package/src/hooks/index.ts +685 -0
- package/src/index.ts +378 -0
- package/src/integrations/agentic-flow.ts +743 -0
- package/src/integrations/index.ts +88 -0
- package/src/integrations/ruvector/ARCHITECTURE.md +1245 -0
- package/src/integrations/ruvector/attention-advanced.ts +1040 -0
- package/src/integrations/ruvector/attention-executor.ts +782 -0
- package/src/integrations/ruvector/attention-mechanisms.ts +757 -0
- package/src/integrations/ruvector/attention.ts +1063 -0
- package/src/integrations/ruvector/gnn.ts +3050 -0
- package/src/integrations/ruvector/hyperbolic.ts +1948 -0
- package/src/integrations/ruvector/index.ts +394 -0
- package/src/integrations/ruvector/migrations/001_create_extension.sql +135 -0
- package/src/integrations/ruvector/migrations/002_create_vector_tables.sql +259 -0
- package/src/integrations/ruvector/migrations/003_create_indices.sql +328 -0
- package/src/integrations/ruvector/migrations/004_create_functions.sql +598 -0
- package/src/integrations/ruvector/migrations/005_create_attention_functions.sql +654 -0
- package/src/integrations/ruvector/migrations/006_create_gnn_functions.sql +728 -0
- package/src/integrations/ruvector/migrations/007_create_hyperbolic_functions.sql +762 -0
- package/src/integrations/ruvector/migrations/index.ts +35 -0
- package/src/integrations/ruvector/migrations/migrations.ts +647 -0
- package/src/integrations/ruvector/quantization.ts +2036 -0
- package/src/integrations/ruvector/ruvector-bridge.ts +2000 -0
- package/src/integrations/ruvector/self-learning.ts +2376 -0
- package/src/integrations/ruvector/streaming.ts +1737 -0
- package/src/integrations/ruvector/types.ts +1945 -0
- package/src/providers/index.ts +643 -0
- package/src/registry/dependency-graph.ts +568 -0
- package/src/registry/enhanced-plugin-registry.ts +994 -0
- package/src/registry/plugin-registry.ts +604 -0
- package/src/sdk/index.ts +563 -0
- package/src/security/index.ts +594 -0
- package/src/types/index.ts +446 -0
- package/src/workers/index.ts +700 -0
- package/tmp.json +0 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +23 -0
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
-- ============================================================================
|
|
2
|
+
-- Migration 004: Create Helper Functions
|
|
3
|
+
-- RuVector PostgreSQL Bridge - Claude Flow V3
|
|
4
|
+
--
|
|
5
|
+
-- Creates helper functions for vector operations, distance calculations,
|
|
6
|
+
-- batch inserts, and upserts.
|
|
7
|
+
-- Compatible with PostgreSQL 14+ and pgvector 0.5+
|
|
8
|
+
-- ============================================================================
|
|
9
|
+
|
|
10
|
+
BEGIN;
|
|
11
|
+
|
|
12
|
+
-- ----------------------------------------------------------------------------
|
|
13
|
+
-- Distance Calculation Functions
|
|
14
|
+
-- ----------------------------------------------------------------------------
|
|
15
|
+
|
|
16
|
+
-- Cosine distance (returns distance, not similarity)
|
|
17
|
+
CREATE OR REPLACE FUNCTION claude_flow.cosine_distance(
|
|
18
|
+
v1 vector,
|
|
19
|
+
v2 vector
|
|
20
|
+
) RETURNS REAL AS $$
|
|
21
|
+
BEGIN
|
|
22
|
+
RETURN 1.0 - (v1 <=> v2);
|
|
23
|
+
END;
|
|
24
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
25
|
+
|
|
26
|
+
-- Cosine similarity (1 - distance)
|
|
27
|
+
CREATE OR REPLACE FUNCTION claude_flow.cosine_similarity(
|
|
28
|
+
v1 vector,
|
|
29
|
+
v2 vector
|
|
30
|
+
) RETURNS REAL AS $$
|
|
31
|
+
BEGIN
|
|
32
|
+
RETURN 1.0 - (v1 <=> v2);
|
|
33
|
+
END;
|
|
34
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
35
|
+
|
|
36
|
+
-- Euclidean distance (L2)
|
|
37
|
+
CREATE OR REPLACE FUNCTION claude_flow.euclidean_distance(
|
|
38
|
+
v1 vector,
|
|
39
|
+
v2 vector
|
|
40
|
+
) RETURNS REAL AS $$
|
|
41
|
+
BEGIN
|
|
42
|
+
RETURN v1 <-> v2;
|
|
43
|
+
END;
|
|
44
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
45
|
+
|
|
46
|
+
-- Inner product (dot product)
|
|
47
|
+
CREATE OR REPLACE FUNCTION claude_flow.inner_product(
|
|
48
|
+
v1 vector,
|
|
49
|
+
v2 vector
|
|
50
|
+
) RETURNS REAL AS $$
|
|
51
|
+
BEGIN
|
|
52
|
+
RETURN v1 <#> v2;
|
|
53
|
+
END;
|
|
54
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
55
|
+
|
|
56
|
+
-- Manhattan distance (L1)
|
|
57
|
+
CREATE OR REPLACE FUNCTION claude_flow.manhattan_distance(
|
|
58
|
+
v1 REAL[],
|
|
59
|
+
v2 REAL[]
|
|
60
|
+
) RETURNS REAL AS $$
|
|
61
|
+
DECLARE
|
|
62
|
+
i INTEGER;
|
|
63
|
+
dist REAL := 0;
|
|
64
|
+
BEGIN
|
|
65
|
+
IF array_length(v1, 1) != array_length(v2, 1) THEN
|
|
66
|
+
RAISE EXCEPTION 'Vector dimensions must match';
|
|
67
|
+
END IF;
|
|
68
|
+
|
|
69
|
+
FOR i IN 1..array_length(v1, 1) LOOP
|
|
70
|
+
dist := dist + abs(v1[i] - v2[i]);
|
|
71
|
+
END LOOP;
|
|
72
|
+
|
|
73
|
+
RETURN dist;
|
|
74
|
+
END;
|
|
75
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
76
|
+
|
|
77
|
+
-- Chebyshev distance (L-infinity)
|
|
78
|
+
CREATE OR REPLACE FUNCTION claude_flow.chebyshev_distance(
|
|
79
|
+
v1 REAL[],
|
|
80
|
+
v2 REAL[]
|
|
81
|
+
) RETURNS REAL AS $$
|
|
82
|
+
DECLARE
|
|
83
|
+
i INTEGER;
|
|
84
|
+
max_diff REAL := 0;
|
|
85
|
+
diff REAL;
|
|
86
|
+
BEGIN
|
|
87
|
+
IF array_length(v1, 1) != array_length(v2, 1) THEN
|
|
88
|
+
RAISE EXCEPTION 'Vector dimensions must match';
|
|
89
|
+
END IF;
|
|
90
|
+
|
|
91
|
+
FOR i IN 1..array_length(v1, 1) LOOP
|
|
92
|
+
diff := abs(v1[i] - v2[i]);
|
|
93
|
+
IF diff > max_diff THEN
|
|
94
|
+
max_diff := diff;
|
|
95
|
+
END IF;
|
|
96
|
+
END LOOP;
|
|
97
|
+
|
|
98
|
+
RETURN max_diff;
|
|
99
|
+
END;
|
|
100
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
101
|
+
|
|
102
|
+
-- Minkowski distance (generalized)
|
|
103
|
+
CREATE OR REPLACE FUNCTION claude_flow.minkowski_distance(
|
|
104
|
+
v1 REAL[],
|
|
105
|
+
v2 REAL[],
|
|
106
|
+
p REAL DEFAULT 2.0
|
|
107
|
+
) RETURNS REAL AS $$
|
|
108
|
+
DECLARE
|
|
109
|
+
i INTEGER;
|
|
110
|
+
sum_val REAL := 0;
|
|
111
|
+
BEGIN
|
|
112
|
+
IF array_length(v1, 1) != array_length(v2, 1) THEN
|
|
113
|
+
RAISE EXCEPTION 'Vector dimensions must match';
|
|
114
|
+
END IF;
|
|
115
|
+
|
|
116
|
+
IF p <= 0 THEN
|
|
117
|
+
RAISE EXCEPTION 'p must be positive';
|
|
118
|
+
END IF;
|
|
119
|
+
|
|
120
|
+
FOR i IN 1..array_length(v1, 1) LOOP
|
|
121
|
+
sum_val := sum_val + power(abs(v1[i] - v2[i]), p);
|
|
122
|
+
END LOOP;
|
|
123
|
+
|
|
124
|
+
RETURN power(sum_val, 1.0 / p);
|
|
125
|
+
END;
|
|
126
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
127
|
+
|
|
128
|
+
-- ----------------------------------------------------------------------------
|
|
129
|
+
-- Vector Normalization Functions
|
|
130
|
+
-- ----------------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
-- L2 normalize a vector
|
|
133
|
+
CREATE OR REPLACE FUNCTION claude_flow.l2_normalize(
|
|
134
|
+
v REAL[]
|
|
135
|
+
) RETURNS REAL[] AS $$
|
|
136
|
+
DECLARE
|
|
137
|
+
norm REAL := 0;
|
|
138
|
+
i INTEGER;
|
|
139
|
+
result REAL[];
|
|
140
|
+
BEGIN
|
|
141
|
+
FOR i IN 1..array_length(v, 1) LOOP
|
|
142
|
+
norm := norm + v[i] * v[i];
|
|
143
|
+
END LOOP;
|
|
144
|
+
|
|
145
|
+
norm := sqrt(norm);
|
|
146
|
+
|
|
147
|
+
IF norm = 0 THEN
|
|
148
|
+
RETURN v;
|
|
149
|
+
END IF;
|
|
150
|
+
|
|
151
|
+
result := ARRAY[]::REAL[];
|
|
152
|
+
FOR i IN 1..array_length(v, 1) LOOP
|
|
153
|
+
result := array_append(result, v[i] / norm);
|
|
154
|
+
END LOOP;
|
|
155
|
+
|
|
156
|
+
RETURN result;
|
|
157
|
+
END;
|
|
158
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
159
|
+
|
|
160
|
+
-- Get vector magnitude (L2 norm)
|
|
161
|
+
CREATE OR REPLACE FUNCTION claude_flow.vector_magnitude(
|
|
162
|
+
v REAL[]
|
|
163
|
+
) RETURNS REAL AS $$
|
|
164
|
+
DECLARE
|
|
165
|
+
sum_sq REAL := 0;
|
|
166
|
+
i INTEGER;
|
|
167
|
+
BEGIN
|
|
168
|
+
FOR i IN 1..array_length(v, 1) LOOP
|
|
169
|
+
sum_sq := sum_sq + v[i] * v[i];
|
|
170
|
+
END LOOP;
|
|
171
|
+
|
|
172
|
+
RETURN sqrt(sum_sq);
|
|
173
|
+
END;
|
|
174
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
175
|
+
|
|
176
|
+
-- ----------------------------------------------------------------------------
|
|
177
|
+
-- Vector Arithmetic Functions
|
|
178
|
+
-- ----------------------------------------------------------------------------
|
|
179
|
+
|
|
180
|
+
-- Add two vectors
|
|
181
|
+
CREATE OR REPLACE FUNCTION claude_flow.vector_add(
|
|
182
|
+
v1 REAL[],
|
|
183
|
+
v2 REAL[]
|
|
184
|
+
) RETURNS REAL[] AS $$
|
|
185
|
+
DECLARE
|
|
186
|
+
i INTEGER;
|
|
187
|
+
result REAL[];
|
|
188
|
+
BEGIN
|
|
189
|
+
IF array_length(v1, 1) != array_length(v2, 1) THEN
|
|
190
|
+
RAISE EXCEPTION 'Vector dimensions must match';
|
|
191
|
+
END IF;
|
|
192
|
+
|
|
193
|
+
result := ARRAY[]::REAL[];
|
|
194
|
+
FOR i IN 1..array_length(v1, 1) LOOP
|
|
195
|
+
result := array_append(result, v1[i] + v2[i]);
|
|
196
|
+
END LOOP;
|
|
197
|
+
|
|
198
|
+
RETURN result;
|
|
199
|
+
END;
|
|
200
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
201
|
+
|
|
202
|
+
-- Subtract two vectors
|
|
203
|
+
CREATE OR REPLACE FUNCTION claude_flow.vector_subtract(
|
|
204
|
+
v1 REAL[],
|
|
205
|
+
v2 REAL[]
|
|
206
|
+
) RETURNS REAL[] AS $$
|
|
207
|
+
DECLARE
|
|
208
|
+
i INTEGER;
|
|
209
|
+
result REAL[];
|
|
210
|
+
BEGIN
|
|
211
|
+
IF array_length(v1, 1) != array_length(v2, 1) THEN
|
|
212
|
+
RAISE EXCEPTION 'Vector dimensions must match';
|
|
213
|
+
END IF;
|
|
214
|
+
|
|
215
|
+
result := ARRAY[]::REAL[];
|
|
216
|
+
FOR i IN 1..array_length(v1, 1) LOOP
|
|
217
|
+
result := array_append(result, v1[i] - v2[i]);
|
|
218
|
+
END LOOP;
|
|
219
|
+
|
|
220
|
+
RETURN result;
|
|
221
|
+
END;
|
|
222
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
223
|
+
|
|
224
|
+
-- Scale a vector
|
|
225
|
+
CREATE OR REPLACE FUNCTION claude_flow.vector_scale(
|
|
226
|
+
v REAL[],
|
|
227
|
+
scalar REAL
|
|
228
|
+
) RETURNS REAL[] AS $$
|
|
229
|
+
DECLARE
|
|
230
|
+
i INTEGER;
|
|
231
|
+
result REAL[];
|
|
232
|
+
BEGIN
|
|
233
|
+
result := ARRAY[]::REAL[];
|
|
234
|
+
FOR i IN 1..array_length(v, 1) LOOP
|
|
235
|
+
result := array_append(result, v[i] * scalar);
|
|
236
|
+
END LOOP;
|
|
237
|
+
|
|
238
|
+
RETURN result;
|
|
239
|
+
END;
|
|
240
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
241
|
+
|
|
242
|
+
-- Dot product of two vectors (as arrays)
|
|
243
|
+
CREATE OR REPLACE FUNCTION claude_flow.dot_product(
|
|
244
|
+
v1 REAL[],
|
|
245
|
+
v2 REAL[]
|
|
246
|
+
) RETURNS REAL AS $$
|
|
247
|
+
DECLARE
|
|
248
|
+
i INTEGER;
|
|
249
|
+
result REAL := 0;
|
|
250
|
+
BEGIN
|
|
251
|
+
IF array_length(v1, 1) != array_length(v2, 1) THEN
|
|
252
|
+
RAISE EXCEPTION 'Vector dimensions must match';
|
|
253
|
+
END IF;
|
|
254
|
+
|
|
255
|
+
FOR i IN 1..array_length(v1, 1) LOOP
|
|
256
|
+
result := result + v1[i] * v2[i];
|
|
257
|
+
END LOOP;
|
|
258
|
+
|
|
259
|
+
RETURN result;
|
|
260
|
+
END;
|
|
261
|
+
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
|
|
262
|
+
|
|
263
|
+
-- ----------------------------------------------------------------------------
|
|
264
|
+
-- Batch Insert Function
|
|
265
|
+
-- ----------------------------------------------------------------------------
|
|
266
|
+
|
|
267
|
+
-- Batch insert vectors with automatic deduplication
|
|
268
|
+
CREATE OR REPLACE FUNCTION claude_flow.batch_insert_vectors(
|
|
269
|
+
p_vectors JSONB -- Array of {embedding, metadata, namespace, collection, content, source}
|
|
270
|
+
) RETURNS TABLE (
|
|
271
|
+
id UUID,
|
|
272
|
+
inserted BOOLEAN,
|
|
273
|
+
error TEXT
|
|
274
|
+
) AS $$
|
|
275
|
+
DECLARE
|
|
276
|
+
v_record JSONB;
|
|
277
|
+
v_embedding vector;
|
|
278
|
+
v_id UUID;
|
|
279
|
+
v_hash TEXT;
|
|
280
|
+
BEGIN
|
|
281
|
+
FOR v_record IN SELECT * FROM jsonb_array_elements(p_vectors)
|
|
282
|
+
LOOP
|
|
283
|
+
BEGIN
|
|
284
|
+
-- Generate hash for deduplication
|
|
285
|
+
v_hash := md5(v_record->>'embedding');
|
|
286
|
+
|
|
287
|
+
-- Try to insert
|
|
288
|
+
INSERT INTO claude_flow.vectors (
|
|
289
|
+
embedding,
|
|
290
|
+
metadata,
|
|
291
|
+
namespace,
|
|
292
|
+
collection,
|
|
293
|
+
content,
|
|
294
|
+
source,
|
|
295
|
+
hash
|
|
296
|
+
) VALUES (
|
|
297
|
+
(v_record->>'embedding')::vector,
|
|
298
|
+
COALESCE(v_record->'metadata', '{}'::jsonb),
|
|
299
|
+
COALESCE(v_record->>'namespace', 'default'),
|
|
300
|
+
COALESCE(v_record->>'collection', 'default'),
|
|
301
|
+
v_record->>'content',
|
|
302
|
+
v_record->>'source',
|
|
303
|
+
v_hash
|
|
304
|
+
)
|
|
305
|
+
ON CONFLICT (namespace, collection, hash) DO NOTHING
|
|
306
|
+
RETURNING vectors.id INTO v_id;
|
|
307
|
+
|
|
308
|
+
IF v_id IS NOT NULL THEN
|
|
309
|
+
id := v_id;
|
|
310
|
+
inserted := TRUE;
|
|
311
|
+
error := NULL;
|
|
312
|
+
ELSE
|
|
313
|
+
-- Get existing ID
|
|
314
|
+
SELECT vectors.id INTO v_id
|
|
315
|
+
FROM claude_flow.vectors
|
|
316
|
+
WHERE vectors.namespace = COALESCE(v_record->>'namespace', 'default')
|
|
317
|
+
AND vectors.collection = COALESCE(v_record->>'collection', 'default')
|
|
318
|
+
AND vectors.hash = v_hash;
|
|
319
|
+
|
|
320
|
+
id := v_id;
|
|
321
|
+
inserted := FALSE;
|
|
322
|
+
error := 'Duplicate entry';
|
|
323
|
+
END IF;
|
|
324
|
+
|
|
325
|
+
RETURN NEXT;
|
|
326
|
+
|
|
327
|
+
EXCEPTION WHEN OTHERS THEN
|
|
328
|
+
id := NULL;
|
|
329
|
+
inserted := FALSE;
|
|
330
|
+
error := SQLERRM;
|
|
331
|
+
RETURN NEXT;
|
|
332
|
+
END;
|
|
333
|
+
END LOOP;
|
|
334
|
+
END;
|
|
335
|
+
$$ LANGUAGE plpgsql;
|
|
336
|
+
|
|
337
|
+
-- ----------------------------------------------------------------------------
|
|
338
|
+
-- Upsert Function
|
|
339
|
+
-- ----------------------------------------------------------------------------
|
|
340
|
+
|
|
341
|
+
-- Upsert a single vector
|
|
342
|
+
CREATE OR REPLACE FUNCTION claude_flow.upsert_vector(
|
|
343
|
+
p_embedding vector,
|
|
344
|
+
p_metadata JSONB DEFAULT '{}',
|
|
345
|
+
p_namespace TEXT DEFAULT 'default',
|
|
346
|
+
p_collection TEXT DEFAULT 'default',
|
|
347
|
+
p_content TEXT DEFAULT NULL,
|
|
348
|
+
p_source TEXT DEFAULT NULL,
|
|
349
|
+
p_id UUID DEFAULT NULL
|
|
350
|
+
) RETURNS UUID AS $$
|
|
351
|
+
DECLARE
|
|
352
|
+
v_id UUID;
|
|
353
|
+
v_hash TEXT;
|
|
354
|
+
BEGIN
|
|
355
|
+
-- Generate hash
|
|
356
|
+
v_hash := md5(p_embedding::text);
|
|
357
|
+
|
|
358
|
+
IF p_id IS NOT NULL THEN
|
|
359
|
+
-- Update by ID
|
|
360
|
+
UPDATE claude_flow.vectors
|
|
361
|
+
SET embedding = p_embedding,
|
|
362
|
+
metadata = p_metadata,
|
|
363
|
+
content = p_content,
|
|
364
|
+
source = p_source,
|
|
365
|
+
hash = v_hash,
|
|
366
|
+
version = version + 1
|
|
367
|
+
WHERE id = p_id
|
|
368
|
+
RETURNING id INTO v_id;
|
|
369
|
+
|
|
370
|
+
IF v_id IS NULL THEN
|
|
371
|
+
-- ID not found, insert new
|
|
372
|
+
INSERT INTO claude_flow.vectors (id, embedding, metadata, namespace, collection, content, source, hash)
|
|
373
|
+
VALUES (p_id, p_embedding, p_metadata, p_namespace, p_collection, p_content, p_source, v_hash)
|
|
374
|
+
RETURNING id INTO v_id;
|
|
375
|
+
END IF;
|
|
376
|
+
ELSE
|
|
377
|
+
-- Upsert by hash
|
|
378
|
+
INSERT INTO claude_flow.vectors (embedding, metadata, namespace, collection, content, source, hash)
|
|
379
|
+
VALUES (p_embedding, p_metadata, p_namespace, p_collection, p_content, p_source, v_hash)
|
|
380
|
+
ON CONFLICT (namespace, collection, hash) DO UPDATE
|
|
381
|
+
SET embedding = EXCLUDED.embedding,
|
|
382
|
+
metadata = EXCLUDED.metadata,
|
|
383
|
+
content = EXCLUDED.content,
|
|
384
|
+
source = EXCLUDED.source,
|
|
385
|
+
version = claude_flow.vectors.version + 1
|
|
386
|
+
RETURNING id INTO v_id;
|
|
387
|
+
END IF;
|
|
388
|
+
|
|
389
|
+
RETURN v_id;
|
|
390
|
+
END;
|
|
391
|
+
$$ LANGUAGE plpgsql;
|
|
392
|
+
|
|
393
|
+
-- Upsert embedding by namespace and name
|
|
394
|
+
CREATE OR REPLACE FUNCTION claude_flow.upsert_embedding(
|
|
395
|
+
p_namespace TEXT,
|
|
396
|
+
p_name TEXT,
|
|
397
|
+
p_embedding vector,
|
|
398
|
+
p_metadata JSONB DEFAULT '{}',
|
|
399
|
+
p_model TEXT DEFAULT NULL,
|
|
400
|
+
p_tags TEXT[] DEFAULT ARRAY[]::TEXT[],
|
|
401
|
+
p_importance REAL DEFAULT 0.5
|
|
402
|
+
) RETURNS UUID AS $$
|
|
403
|
+
DECLARE
|
|
404
|
+
v_id UUID;
|
|
405
|
+
BEGIN
|
|
406
|
+
INSERT INTO claude_flow.embeddings (namespace, name, embedding, dimensions, metadata, model, tags, importance)
|
|
407
|
+
VALUES (p_namespace, p_name, p_embedding, array_length((p_embedding::real[]), 1), p_metadata, p_model, p_tags, p_importance)
|
|
408
|
+
ON CONFLICT (namespace, name) DO UPDATE
|
|
409
|
+
SET embedding = EXCLUDED.embedding,
|
|
410
|
+
dimensions = EXCLUDED.dimensions,
|
|
411
|
+
metadata = EXCLUDED.metadata,
|
|
412
|
+
model = EXCLUDED.model,
|
|
413
|
+
tags = EXCLUDED.tags,
|
|
414
|
+
importance = EXCLUDED.importance
|
|
415
|
+
RETURNING id INTO v_id;
|
|
416
|
+
|
|
417
|
+
RETURN v_id;
|
|
418
|
+
END;
|
|
419
|
+
$$ LANGUAGE plpgsql;
|
|
420
|
+
|
|
421
|
+
-- ----------------------------------------------------------------------------
|
|
422
|
+
-- Search Functions
|
|
423
|
+
-- ----------------------------------------------------------------------------
|
|
424
|
+
|
|
425
|
+
-- K-nearest neighbors search with filters
|
|
426
|
+
CREATE OR REPLACE FUNCTION claude_flow.knn_search(
|
|
427
|
+
p_query vector,
|
|
428
|
+
p_k INTEGER DEFAULT 10,
|
|
429
|
+
p_namespace TEXT DEFAULT NULL,
|
|
430
|
+
p_collection TEXT DEFAULT NULL,
|
|
431
|
+
p_metric TEXT DEFAULT 'cosine',
|
|
432
|
+
p_threshold REAL DEFAULT NULL,
|
|
433
|
+
p_metadata_filter JSONB DEFAULT NULL
|
|
434
|
+
) RETURNS TABLE (
|
|
435
|
+
id UUID,
|
|
436
|
+
embedding vector,
|
|
437
|
+
metadata JSONB,
|
|
438
|
+
content TEXT,
|
|
439
|
+
distance REAL,
|
|
440
|
+
similarity REAL
|
|
441
|
+
) AS $$
|
|
442
|
+
BEGIN
|
|
443
|
+
RETURN QUERY
|
|
444
|
+
SELECT
|
|
445
|
+
v.id,
|
|
446
|
+
v.embedding,
|
|
447
|
+
v.metadata,
|
|
448
|
+
v.content,
|
|
449
|
+
CASE p_metric
|
|
450
|
+
WHEN 'cosine' THEN v.embedding <=> p_query
|
|
451
|
+
WHEN 'euclidean' THEN v.embedding <-> p_query
|
|
452
|
+
WHEN 'dot' THEN v.embedding <#> p_query
|
|
453
|
+
ELSE v.embedding <=> p_query
|
|
454
|
+
END AS distance,
|
|
455
|
+
CASE p_metric
|
|
456
|
+
WHEN 'cosine' THEN 1.0 - (v.embedding <=> p_query)
|
|
457
|
+
WHEN 'euclidean' THEN 1.0 / (1.0 + (v.embedding <-> p_query))
|
|
458
|
+
WHEN 'dot' THEN -(v.embedding <#> p_query)
|
|
459
|
+
ELSE 1.0 - (v.embedding <=> p_query)
|
|
460
|
+
END AS similarity
|
|
461
|
+
FROM claude_flow.vectors v
|
|
462
|
+
WHERE (p_namespace IS NULL OR v.namespace = p_namespace)
|
|
463
|
+
AND (p_collection IS NULL OR v.collection = p_collection)
|
|
464
|
+
AND (p_metadata_filter IS NULL OR v.metadata @> p_metadata_filter)
|
|
465
|
+
AND (v.expires_at IS NULL OR v.expires_at > NOW())
|
|
466
|
+
AND (p_threshold IS NULL OR
|
|
467
|
+
CASE p_metric
|
|
468
|
+
WHEN 'cosine' THEN (v.embedding <=> p_query) <= p_threshold
|
|
469
|
+
WHEN 'euclidean' THEN (v.embedding <-> p_query) <= p_threshold
|
|
470
|
+
WHEN 'dot' THEN -(v.embedding <#> p_query) >= p_threshold
|
|
471
|
+
ELSE TRUE
|
|
472
|
+
END)
|
|
473
|
+
ORDER BY
|
|
474
|
+
CASE p_metric
|
|
475
|
+
WHEN 'cosine' THEN v.embedding <=> p_query
|
|
476
|
+
WHEN 'euclidean' THEN v.embedding <-> p_query
|
|
477
|
+
WHEN 'dot' THEN v.embedding <#> p_query
|
|
478
|
+
ELSE v.embedding <=> p_query
|
|
479
|
+
END
|
|
480
|
+
LIMIT p_k;
|
|
481
|
+
END;
|
|
482
|
+
$$ LANGUAGE plpgsql STABLE;
|
|
483
|
+
|
|
484
|
+
-- ----------------------------------------------------------------------------
|
|
485
|
+
-- Cleanup Functions
|
|
486
|
+
-- ----------------------------------------------------------------------------
|
|
487
|
+
|
|
488
|
+
-- Delete expired vectors
|
|
489
|
+
CREATE OR REPLACE FUNCTION claude_flow.cleanup_expired_vectors()
|
|
490
|
+
RETURNS INTEGER AS $$
|
|
491
|
+
DECLARE
|
|
492
|
+
deleted_count INTEGER;
|
|
493
|
+
BEGIN
|
|
494
|
+
DELETE FROM claude_flow.vectors
|
|
495
|
+
WHERE expires_at IS NOT NULL AND expires_at < NOW();
|
|
496
|
+
|
|
497
|
+
GET DIAGNOSTICS deleted_count = ROW_COUNT;
|
|
498
|
+
RETURN deleted_count;
|
|
499
|
+
END;
|
|
500
|
+
$$ LANGUAGE plpgsql;
|
|
501
|
+
|
|
502
|
+
-- Cleanup old cache entries
|
|
503
|
+
CREATE OR REPLACE FUNCTION claude_flow.cleanup_caches(
|
|
504
|
+
p_max_age_hours INTEGER DEFAULT 24
|
|
505
|
+
) RETURNS TABLE (
|
|
506
|
+
attention_deleted INTEGER,
|
|
507
|
+
gnn_deleted INTEGER
|
|
508
|
+
) AS $$
|
|
509
|
+
DECLARE
|
|
510
|
+
v_attention_deleted INTEGER;
|
|
511
|
+
v_gnn_deleted INTEGER;
|
|
512
|
+
BEGIN
|
|
513
|
+
-- Cleanup attention cache
|
|
514
|
+
DELETE FROM claude_flow.attention_cache
|
|
515
|
+
WHERE (expires_at IS NOT NULL AND expires_at < NOW())
|
|
516
|
+
OR (last_accessed_at < NOW() - (p_max_age_hours || ' hours')::INTERVAL);
|
|
517
|
+
GET DIAGNOSTICS v_attention_deleted = ROW_COUNT;
|
|
518
|
+
|
|
519
|
+
-- Cleanup GNN cache
|
|
520
|
+
DELETE FROM claude_flow.gnn_cache
|
|
521
|
+
WHERE (expires_at IS NOT NULL AND expires_at < NOW())
|
|
522
|
+
OR (last_accessed_at < NOW() - (p_max_age_hours || ' hours')::INTERVAL);
|
|
523
|
+
GET DIAGNOSTICS v_gnn_deleted = ROW_COUNT;
|
|
524
|
+
|
|
525
|
+
attention_deleted := v_attention_deleted;
|
|
526
|
+
gnn_deleted := v_gnn_deleted;
|
|
527
|
+
RETURN NEXT;
|
|
528
|
+
END;
|
|
529
|
+
$$ LANGUAGE plpgsql;
|
|
530
|
+
|
|
531
|
+
-- ----------------------------------------------------------------------------
|
|
532
|
+
-- Statistics Functions
|
|
533
|
+
-- ----------------------------------------------------------------------------
|
|
534
|
+
|
|
535
|
+
-- Get collection statistics
|
|
536
|
+
CREATE OR REPLACE FUNCTION claude_flow.get_collection_stats(
|
|
537
|
+
p_collection_name TEXT DEFAULT NULL
|
|
538
|
+
) RETURNS TABLE (
|
|
539
|
+
collection_name TEXT,
|
|
540
|
+
namespace TEXT,
|
|
541
|
+
vector_count BIGINT,
|
|
542
|
+
avg_embedding_size REAL,
|
|
543
|
+
total_size_mb REAL,
|
|
544
|
+
oldest_entry TIMESTAMPTZ,
|
|
545
|
+
newest_entry TIMESTAMPTZ
|
|
546
|
+
) AS $$
|
|
547
|
+
BEGIN
|
|
548
|
+
RETURN QUERY
|
|
549
|
+
SELECT
|
|
550
|
+
c.name AS collection_name,
|
|
551
|
+
c.namespace,
|
|
552
|
+
COUNT(v.id) AS vector_count,
|
|
553
|
+
AVG(array_length((v.embedding::real[]), 1))::REAL AS avg_embedding_size,
|
|
554
|
+
(pg_total_relation_size('claude_flow.vectors') / 1024.0 / 1024.0)::REAL AS total_size_mb,
|
|
555
|
+
MIN(v.created_at) AS oldest_entry,
|
|
556
|
+
MAX(v.created_at) AS newest_entry
|
|
557
|
+
FROM claude_flow.collections c
|
|
558
|
+
LEFT JOIN claude_flow.vectors v ON v.collection = c.name AND v.namespace = c.namespace
|
|
559
|
+
WHERE p_collection_name IS NULL OR c.name = p_collection_name
|
|
560
|
+
GROUP BY c.name, c.namespace;
|
|
561
|
+
END;
|
|
562
|
+
$$ LANGUAGE plpgsql STABLE;
|
|
563
|
+
|
|
564
|
+
-- ----------------------------------------------------------------------------
|
|
565
|
+
-- Record migration
|
|
566
|
+
-- ----------------------------------------------------------------------------
|
|
567
|
+
INSERT INTO claude_flow.migrations (name, checksum)
|
|
568
|
+
VALUES ('004_create_functions', md5('004_create_functions'))
|
|
569
|
+
ON CONFLICT (name) DO NOTHING;
|
|
570
|
+
|
|
571
|
+
COMMIT;
|
|
572
|
+
|
|
573
|
+
-- ============================================================================
|
|
574
|
+
-- Rollback Script
|
|
575
|
+
-- ============================================================================
|
|
576
|
+
-- BEGIN;
|
|
577
|
+
-- DROP FUNCTION IF EXISTS claude_flow.get_collection_stats(TEXT);
|
|
578
|
+
-- DROP FUNCTION IF EXISTS claude_flow.cleanup_caches(INTEGER);
|
|
579
|
+
-- DROP FUNCTION IF EXISTS claude_flow.cleanup_expired_vectors();
|
|
580
|
+
-- DROP FUNCTION IF EXISTS claude_flow.knn_search(vector, INTEGER, TEXT, TEXT, TEXT, REAL, JSONB);
|
|
581
|
+
-- DROP FUNCTION IF EXISTS claude_flow.upsert_embedding(TEXT, TEXT, vector, JSONB, TEXT, TEXT[], REAL);
|
|
582
|
+
-- DROP FUNCTION IF EXISTS claude_flow.upsert_vector(vector, JSONB, TEXT, TEXT, TEXT, TEXT, UUID);
|
|
583
|
+
-- DROP FUNCTION IF EXISTS claude_flow.batch_insert_vectors(JSONB);
|
|
584
|
+
-- DROP FUNCTION IF EXISTS claude_flow.dot_product(REAL[], REAL[]);
|
|
585
|
+
-- DROP FUNCTION IF EXISTS claude_flow.vector_scale(REAL[], REAL);
|
|
586
|
+
-- DROP FUNCTION IF EXISTS claude_flow.vector_subtract(REAL[], REAL[]);
|
|
587
|
+
-- DROP FUNCTION IF EXISTS claude_flow.vector_add(REAL[], REAL[]);
|
|
588
|
+
-- DROP FUNCTION IF EXISTS claude_flow.vector_magnitude(REAL[]);
|
|
589
|
+
-- DROP FUNCTION IF EXISTS claude_flow.l2_normalize(REAL[]);
|
|
590
|
+
-- DROP FUNCTION IF EXISTS claude_flow.minkowski_distance(REAL[], REAL[], REAL);
|
|
591
|
+
-- DROP FUNCTION IF EXISTS claude_flow.chebyshev_distance(REAL[], REAL[]);
|
|
592
|
+
-- DROP FUNCTION IF EXISTS claude_flow.manhattan_distance(REAL[], REAL[]);
|
|
593
|
+
-- DROP FUNCTION IF EXISTS claude_flow.inner_product(vector, vector);
|
|
594
|
+
-- DROP FUNCTION IF EXISTS claude_flow.euclidean_distance(vector, vector);
|
|
595
|
+
-- DROP FUNCTION IF EXISTS claude_flow.cosine_similarity(vector, vector);
|
|
596
|
+
-- DROP FUNCTION IF EXISTS claude_flow.cosine_distance(vector, vector);
|
|
597
|
+
-- DELETE FROM claude_flow.migrations WHERE name = '004_create_functions';
|
|
598
|
+
-- COMMIT;
|