@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.
Files changed (80) hide show
  1. package/README.md +401 -0
  2. package/__tests__/collection-manager.test.ts +332 -0
  3. package/__tests__/dependency-graph.test.ts +434 -0
  4. package/__tests__/enhanced-plugin-registry.test.ts +488 -0
  5. package/__tests__/plugin-registry.test.ts +368 -0
  6. package/__tests__/ruvector-bridge.test.ts +2429 -0
  7. package/__tests__/ruvector-integration.test.ts +1602 -0
  8. package/__tests__/ruvector-migrations.test.ts +1099 -0
  9. package/__tests__/ruvector-quantization.test.ts +846 -0
  10. package/__tests__/ruvector-streaming.test.ts +1088 -0
  11. package/__tests__/sdk.test.ts +325 -0
  12. package/__tests__/security.test.ts +348 -0
  13. package/__tests__/utils/ruvector-test-utils.ts +860 -0
  14. package/examples/plugin-creator/index.ts +636 -0
  15. package/examples/plugin-creator/plugin-creator.test.ts +312 -0
  16. package/examples/ruvector/README.md +288 -0
  17. package/examples/ruvector/attention-patterns.ts +394 -0
  18. package/examples/ruvector/basic-usage.ts +288 -0
  19. package/examples/ruvector/docker-compose.yml +75 -0
  20. package/examples/ruvector/gnn-analysis.ts +501 -0
  21. package/examples/ruvector/hyperbolic-hierarchies.ts +557 -0
  22. package/examples/ruvector/init-db.sql +119 -0
  23. package/examples/ruvector/quantization.ts +680 -0
  24. package/examples/ruvector/self-learning.ts +447 -0
  25. package/examples/ruvector/semantic-search.ts +576 -0
  26. package/examples/ruvector/streaming-large-data.ts +507 -0
  27. package/examples/ruvector/transactions.ts +594 -0
  28. package/examples/ruvector-plugins/hook-pattern-library.ts +486 -0
  29. package/examples/ruvector-plugins/index.ts +79 -0
  30. package/examples/ruvector-plugins/intent-router.ts +354 -0
  31. package/examples/ruvector-plugins/mcp-tool-optimizer.ts +424 -0
  32. package/examples/ruvector-plugins/reasoning-bank.ts +657 -0
  33. package/examples/ruvector-plugins/ruvector-plugins.test.ts +518 -0
  34. package/examples/ruvector-plugins/semantic-code-search.ts +498 -0
  35. package/examples/ruvector-plugins/shared/index.ts +20 -0
  36. package/examples/ruvector-plugins/shared/vector-utils.ts +257 -0
  37. package/examples/ruvector-plugins/sona-learning.ts +445 -0
  38. package/package.json +97 -0
  39. package/src/collections/collection-manager.ts +661 -0
  40. package/src/collections/index.ts +56 -0
  41. package/src/collections/official/index.ts +1040 -0
  42. package/src/core/base-plugin.ts +416 -0
  43. package/src/core/plugin-interface.ts +215 -0
  44. package/src/hooks/index.ts +685 -0
  45. package/src/index.ts +378 -0
  46. package/src/integrations/agentic-flow.ts +743 -0
  47. package/src/integrations/index.ts +88 -0
  48. package/src/integrations/ruvector/ARCHITECTURE.md +1245 -0
  49. package/src/integrations/ruvector/attention-advanced.ts +1040 -0
  50. package/src/integrations/ruvector/attention-executor.ts +782 -0
  51. package/src/integrations/ruvector/attention-mechanisms.ts +757 -0
  52. package/src/integrations/ruvector/attention.ts +1063 -0
  53. package/src/integrations/ruvector/gnn.ts +3050 -0
  54. package/src/integrations/ruvector/hyperbolic.ts +1948 -0
  55. package/src/integrations/ruvector/index.ts +394 -0
  56. package/src/integrations/ruvector/migrations/001_create_extension.sql +135 -0
  57. package/src/integrations/ruvector/migrations/002_create_vector_tables.sql +259 -0
  58. package/src/integrations/ruvector/migrations/003_create_indices.sql +328 -0
  59. package/src/integrations/ruvector/migrations/004_create_functions.sql +598 -0
  60. package/src/integrations/ruvector/migrations/005_create_attention_functions.sql +654 -0
  61. package/src/integrations/ruvector/migrations/006_create_gnn_functions.sql +728 -0
  62. package/src/integrations/ruvector/migrations/007_create_hyperbolic_functions.sql +762 -0
  63. package/src/integrations/ruvector/migrations/index.ts +35 -0
  64. package/src/integrations/ruvector/migrations/migrations.ts +647 -0
  65. package/src/integrations/ruvector/quantization.ts +2036 -0
  66. package/src/integrations/ruvector/ruvector-bridge.ts +2000 -0
  67. package/src/integrations/ruvector/self-learning.ts +2376 -0
  68. package/src/integrations/ruvector/streaming.ts +1737 -0
  69. package/src/integrations/ruvector/types.ts +1945 -0
  70. package/src/providers/index.ts +643 -0
  71. package/src/registry/dependency-graph.ts +568 -0
  72. package/src/registry/enhanced-plugin-registry.ts +994 -0
  73. package/src/registry/plugin-registry.ts +604 -0
  74. package/src/sdk/index.ts +563 -0
  75. package/src/security/index.ts +594 -0
  76. package/src/types/index.ts +446 -0
  77. package/src/workers/index.ts +700 -0
  78. package/tmp.json +0 -0
  79. package/tsconfig.json +25 -0
  80. 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;