@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,312 @@
1
+ /**
2
+ * Plugin Creator Tests
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest';
6
+ import {
7
+ pluginCreatorPlugin,
8
+ generatePlugin,
9
+ generateToolCode,
10
+ generateHookCode,
11
+ generateWorkerCode,
12
+ generateAgentTypeCode,
13
+ PLUGIN_TEMPLATES,
14
+ type CreatePluginOptions,
15
+ } from './index.js';
16
+ import { HookEvent } from '../../src/types/index.js';
17
+
18
+ describe('Plugin Creator Plugin', () => {
19
+ describe('pluginCreatorPlugin', () => {
20
+ it('should have correct metadata', () => {
21
+ expect(pluginCreatorPlugin.metadata.name).toBe('plugin-creator');
22
+ expect(pluginCreatorPlugin.metadata.version).toBe('1.0.0');
23
+ expect(pluginCreatorPlugin.metadata.tags).toContain('meta');
24
+ });
25
+
26
+ it('should register MCP tools', () => {
27
+ const tools = pluginCreatorPlugin.registerMCPTools?.() ?? [];
28
+ expect(tools.length).toBeGreaterThan(0);
29
+
30
+ const toolNames = tools.map(t => t.name);
31
+ expect(toolNames).toContain('create-plugin');
32
+ expect(toolNames).toContain('list-plugin-templates');
33
+ expect(toolNames).toContain('generate-tool');
34
+ expect(toolNames).toContain('generate-hook');
35
+ expect(toolNames).toContain('generate-worker');
36
+ });
37
+
38
+ it('should register hooks', () => {
39
+ const hooks = pluginCreatorPlugin.registerHooks?.() ?? [];
40
+ expect(hooks.length).toBeGreaterThan(0);
41
+ expect(hooks[0].name).toBe('plugin-creator-logger');
42
+ });
43
+
44
+ it('should register workers', () => {
45
+ const workers = pluginCreatorPlugin.registerWorkers?.() ?? [];
46
+ expect(workers.length).toBeGreaterThan(0);
47
+ expect(workers[0].name).toBe('plugin-code-generator');
48
+ });
49
+ });
50
+
51
+ describe('PLUGIN_TEMPLATES', () => {
52
+ it('should have all expected templates', () => {
53
+ const templateNames = Object.keys(PLUGIN_TEMPLATES);
54
+ expect(templateNames).toContain('minimal');
55
+ expect(templateNames).toContain('tool-plugin');
56
+ expect(templateNames).toContain('hooks-plugin');
57
+ expect(templateNames).toContain('worker-plugin');
58
+ expect(templateNames).toContain('swarm-plugin');
59
+ expect(templateNames).toContain('full-featured');
60
+ expect(templateNames).toContain('security-focused');
61
+ });
62
+
63
+ it('should have valid template structures', () => {
64
+ for (const [name, template] of Object.entries(PLUGIN_TEMPLATES)) {
65
+ expect(template.name).toBeDefined();
66
+ expect(template.description).toBeDefined();
67
+ expect(template.category).toMatch(/^(tools|hooks|workers|swarm|full)$/);
68
+ expect(Array.isArray(template.features)).toBe(true);
69
+ }
70
+ });
71
+ });
72
+
73
+ describe('generatePlugin', () => {
74
+ it('should generate a minimal plugin', () => {
75
+ const result = generatePlugin({
76
+ name: 'test-plugin',
77
+ version: '1.0.0',
78
+ });
79
+
80
+ expect(result.plugin).toBeDefined();
81
+ expect(result.metadata.name).toBe('test-plugin');
82
+ expect(result.metadata.version).toBe('1.0.0');
83
+ expect(result.code).toContain("PluginBuilder('test-plugin'");
84
+ });
85
+
86
+ it('should generate a plugin with tools', () => {
87
+ const result = generatePlugin({
88
+ name: 'tools-test',
89
+ features: { tools: true },
90
+ toolNames: ['my-tool', 'another-tool'],
91
+ });
92
+
93
+ const tools = result.plugin.registerMCPTools?.() ?? [];
94
+ expect(tools.length).toBe(2);
95
+ expect(tools[0].name).toBe('my-tool');
96
+ expect(tools[1].name).toBe('another-tool');
97
+ expect(result.code).toContain('MCPToolBuilder');
98
+ });
99
+
100
+ it('should generate a plugin with hooks', () => {
101
+ const result = generatePlugin({
102
+ name: 'hooks-test',
103
+ features: { hooks: true },
104
+ hookEvents: [HookEvent.SessionStart, HookEvent.PostTaskComplete],
105
+ });
106
+
107
+ const hooks = result.plugin.registerHooks?.() ?? [];
108
+ expect(hooks.length).toBe(2);
109
+ expect(result.code).toContain('HookBuilder');
110
+ });
111
+
112
+ it('should generate a plugin with workers', () => {
113
+ const result = generatePlugin({
114
+ name: 'workers-test',
115
+ features: { workers: true },
116
+ workerTypes: ['coder', 'reviewer'],
117
+ });
118
+
119
+ const workers = result.plugin.registerWorkers?.() ?? [];
120
+ expect(workers.length).toBe(2);
121
+ expect(result.code).toContain('WorkerFactory');
122
+ });
123
+
124
+ it('should generate a plugin with swarm capabilities', () => {
125
+ const result = generatePlugin({
126
+ name: 'swarm-test',
127
+ features: { swarm: true },
128
+ agentTypes: ['coordinator', 'worker-agent'],
129
+ });
130
+
131
+ const agents = result.plugin.registerAgentTypes?.() ?? [];
132
+ expect(agents.length).toBe(2);
133
+ expect(result.code).toContain('AgentTypeDefinition');
134
+ });
135
+
136
+ it('should apply template features', () => {
137
+ const result = generatePlugin({
138
+ name: 'full-test',
139
+ template: 'full-featured',
140
+ });
141
+
142
+ const tools = result.plugin.registerMCPTools?.() ?? [];
143
+ const hooks = result.plugin.registerHooks?.() ?? [];
144
+ const workers = result.plugin.registerWorkers?.() ?? [];
145
+ const agents = result.plugin.registerAgentTypes?.() ?? [];
146
+
147
+ expect(tools.length).toBeGreaterThan(0);
148
+ expect(hooks.length).toBeGreaterThan(0);
149
+ expect(workers.length).toBeGreaterThan(0);
150
+ expect(agents.length).toBeGreaterThan(0);
151
+ });
152
+
153
+ it('should reject invalid plugin names', () => {
154
+ expect(() => generatePlugin({ name: 'Invalid Name' })).toThrow();
155
+ expect(() => generatePlugin({ name: '123-start' })).toThrow();
156
+ expect(() => generatePlugin({ name: 'ab' })).toThrow(); // Too short
157
+ });
158
+ });
159
+
160
+ describe('generateToolCode', () => {
161
+ it('should generate valid tool definition', () => {
162
+ const { definition, code } = generateToolCode('my-tool');
163
+
164
+ expect(definition.name).toBe('my-tool');
165
+ expect(definition.handler).toBeDefined();
166
+ expect(code).toContain('MCPToolBuilder');
167
+ expect(code).toContain('my-tool');
168
+ });
169
+
170
+ it('should sanitize invalid tool names', () => {
171
+ const { definition } = generateToolCode('Invalid Tool Name!');
172
+ expect(definition.name).toBe('custom-tool');
173
+ });
174
+
175
+ it('should create working handler', async () => {
176
+ const { definition } = generateToolCode('test-tool');
177
+ const result = await definition.handler({ input: 'test' });
178
+
179
+ expect(result.content).toBeDefined();
180
+ expect(result.content[0].type).toBe('text');
181
+ expect(result.content[0].text).toContain('test-tool');
182
+ });
183
+ });
184
+
185
+ describe('generateHookCode', () => {
186
+ it('should generate valid hook definition', () => {
187
+ const { definition, code } = generateHookCode(HookEvent.SessionStart);
188
+
189
+ expect(definition.event).toBe(HookEvent.SessionStart);
190
+ expect(definition.handler).toBeDefined();
191
+ expect(code).toContain('HookBuilder');
192
+ expect(code).toContain('SessionStart');
193
+ });
194
+
195
+ it('should create working handler', async () => {
196
+ const { definition } = generateHookCode(HookEvent.PostTaskComplete);
197
+ const result = await definition.handler({
198
+ event: HookEvent.PostTaskComplete,
199
+ data: { taskId: '123' },
200
+ timestamp: new Date(),
201
+ });
202
+
203
+ expect(result.success).toBe(true);
204
+ });
205
+ });
206
+
207
+ describe('generateWorkerCode', () => {
208
+ it('should generate valid worker definitions for known types', () => {
209
+ const types = ['coder', 'reviewer', 'tester', 'researcher', 'planner', 'coordinator', 'security', 'performance'];
210
+
211
+ for (const type of types) {
212
+ const { definition, code } = generateWorkerCode(type);
213
+
214
+ expect(definition.type).toBe(type);
215
+ expect(definition.name).toBe(`${type}-worker`);
216
+ expect(definition.capabilities.length).toBeGreaterThan(0);
217
+ expect(code).toContain('WorkerFactory');
218
+ }
219
+ });
220
+
221
+ it('should fallback to specialized for unknown types', () => {
222
+ const { definition, code } = generateWorkerCode('custom-type');
223
+
224
+ expect(definition.type).toBe('specialized');
225
+ expect(code).toContain('createSpecialized');
226
+ });
227
+ });
228
+
229
+ describe('generateAgentTypeCode', () => {
230
+ it('should generate valid agent type definition', () => {
231
+ const { definition, code } = generateAgentTypeCode('coordinator');
232
+
233
+ expect(definition.type).toBe('coordinator');
234
+ expect(definition.name).toBe('coordinator Agent');
235
+ expect(definition.model).toBe('claude-sonnet-4-20250514');
236
+ expect(code).toContain('AgentTypeDefinition');
237
+ });
238
+
239
+ it('should sanitize invalid agent type names', () => {
240
+ const { definition } = generateAgentTypeCode('Invalid Agent!');
241
+ expect(definition.type).toBe('custom-agent');
242
+ });
243
+ });
244
+ });
245
+
246
+ describe('MCP Tool Handlers', () => {
247
+ it('create-plugin tool should work', async () => {
248
+ const tools = pluginCreatorPlugin.registerMCPTools?.() ?? [];
249
+ const createTool = tools.find(t => t.name === 'create-plugin');
250
+
251
+ expect(createTool).toBeDefined();
252
+
253
+ const result = await createTool!.handler({
254
+ name: 'test-created-plugin',
255
+ version: '1.0.0',
256
+ template: 'tool-plugin',
257
+ });
258
+
259
+ expect(result.content[0].text).toContain('test-created-plugin');
260
+ expect(result.content[0].text).toContain('created successfully');
261
+ });
262
+
263
+ it('list-plugin-templates tool should work', async () => {
264
+ const tools = pluginCreatorPlugin.registerMCPTools?.() ?? [];
265
+ const listTool = tools.find(t => t.name === 'list-plugin-templates');
266
+
267
+ expect(listTool).toBeDefined();
268
+
269
+ const result = await listTool!.handler({});
270
+
271
+ expect(result.content[0].text).toContain('Available Plugin Templates');
272
+ expect(result.content[0].text).toContain('minimal');
273
+ expect(result.content[0].text).toContain('full-featured');
274
+ });
275
+
276
+ it('generate-tool tool should work', async () => {
277
+ const tools = pluginCreatorPlugin.registerMCPTools?.() ?? [];
278
+ const genTool = tools.find(t => t.name === 'generate-tool');
279
+
280
+ expect(genTool).toBeDefined();
281
+
282
+ const result = await genTool!.handler({ name: 'my-custom-tool' });
283
+
284
+ expect(result.content[0].text).toContain('Generated Tool');
285
+ expect(result.content[0].text).toContain('my-custom-tool');
286
+ expect(result.content[0].text).toContain('MCPToolBuilder');
287
+ });
288
+
289
+ it('generate-hook tool should work', async () => {
290
+ const tools = pluginCreatorPlugin.registerMCPTools?.() ?? [];
291
+ const genHook = tools.find(t => t.name === 'generate-hook');
292
+
293
+ expect(genHook).toBeDefined();
294
+
295
+ const result = await genHook!.handler({ event: HookEvent.SessionStart });
296
+
297
+ expect(result.content[0].text).toContain('Generated Hook');
298
+ expect(result.content[0].text).toContain('HookBuilder');
299
+ });
300
+
301
+ it('generate-worker tool should work', async () => {
302
+ const tools = pluginCreatorPlugin.registerMCPTools?.() ?? [];
303
+ const genWorker = tools.find(t => t.name === 'generate-worker');
304
+
305
+ expect(genWorker).toBeDefined();
306
+
307
+ const result = await genWorker!.handler({ type: 'coder' });
308
+
309
+ expect(result.content[0].text).toContain('Generated Worker');
310
+ expect(result.content[0].text).toContain('WorkerFactory');
311
+ });
312
+ });
@@ -0,0 +1,288 @@
1
+ # RuVector PostgreSQL Bridge Examples
2
+
3
+ Comprehensive examples demonstrating the RuVector PostgreSQL Bridge plugin features.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js 18+
8
+ - Docker and Docker Compose
9
+ - TypeScript / ts-node
10
+
11
+ ## Quick Start
12
+
13
+ ### 1. Start PostgreSQL with pgvector
14
+
15
+ ```bash
16
+ cd examples/ruvector
17
+ docker compose up -d
18
+ ```
19
+
20
+ This starts:
21
+ - PostgreSQL 16 with pgvector extension on port 5432
22
+ - Adminer (database UI) on port 8080
23
+
24
+ ### 2. Install Dependencies
25
+
26
+ ```bash
27
+ # From the plugins root directory
28
+ npm install
29
+ npm run build
30
+ ```
31
+
32
+ ### 3. Run Examples
33
+
34
+ ```bash
35
+ # Basic vector operations
36
+ npx ts-node examples/ruvector/basic-usage.ts
37
+
38
+ # Semantic code search
39
+ npx ts-node examples/ruvector/semantic-search.ts
40
+
41
+ # Attention mechanisms
42
+ npx ts-node examples/ruvector/attention-patterns.ts
43
+
44
+ # Graph neural networks
45
+ npx ts-node examples/ruvector/gnn-analysis.ts
46
+
47
+ # Hyperbolic embeddings
48
+ npx ts-node examples/ruvector/hyperbolic-hierarchies.ts
49
+
50
+ # Self-learning optimization
51
+ npx ts-node examples/ruvector/self-learning.ts
52
+
53
+ # Large-scale streaming
54
+ npx ts-node examples/ruvector/streaming-large-data.ts
55
+
56
+ # Quantization methods
57
+ npx ts-node examples/ruvector/quantization.ts
58
+
59
+ # Transaction patterns
60
+ npx ts-node examples/ruvector/transactions.ts
61
+ ```
62
+
63
+ ## Examples Overview
64
+
65
+ ### 1. basic-usage.ts
66
+
67
+ Getting started with RuVector PostgreSQL Bridge:
68
+ - Connecting to PostgreSQL
69
+ - Creating collections with HNSW indexes
70
+ - Inserting and searching vectors
71
+ - Batch operations
72
+ - Update and delete operations
73
+
74
+ **Expected output:**
75
+ ```
76
+ RuVector PostgreSQL Bridge - Basic Usage Example
77
+ ================================================
78
+
79
+ 1. Connecting to PostgreSQL...
80
+ Connected successfully!
81
+
82
+ 2. Creating collection "documents"...
83
+ Collection created!
84
+
85
+ 3. Inserting vectors...
86
+ Inserted: doc-1
87
+ ...
88
+ ```
89
+
90
+ ### 2. semantic-search.ts
91
+
92
+ Semantic code search implementation:
93
+ - Embedding code snippets
94
+ - Natural language queries
95
+ - Hybrid search (semantic + keyword)
96
+ - Relevance feedback / re-ranking
97
+
98
+ **Key concepts:**
99
+ - Code embeddings capture semantic meaning
100
+ - Natural language queries find relevant code
101
+ - Hybrid scoring combines multiple signals
102
+
103
+ ### 3. attention-patterns.ts
104
+
105
+ Using attention mechanisms:
106
+ - Multi-head attention
107
+ - Self-attention
108
+ - Cross-attention (encoder-decoder)
109
+ - Causal attention (autoregressive)
110
+ - Flash attention simulation
111
+ - KV cache for inference
112
+
113
+ **Key concepts:**
114
+ - Different attention patterns for different use cases
115
+ - Memory and compute optimizations
116
+ - SQL generation for PostgreSQL execution
117
+
118
+ ### 4. gnn-analysis.ts
119
+
120
+ Graph Neural Network analysis:
121
+ - Building code dependency graphs
122
+ - GCN (Graph Convolutional Network)
123
+ - GAT (Graph Attention Network)
124
+ - GraphSAGE for inductive learning
125
+ - Finding structurally similar modules
126
+
127
+ **Key concepts:**
128
+ - Code structure as a graph
129
+ - Learning from dependencies
130
+ - Structural similarity detection
131
+
132
+ ### 5. hyperbolic-hierarchies.ts
133
+
134
+ Hyperbolic embeddings for hierarchies:
135
+ - File tree embeddings
136
+ - Class inheritance hierarchies
137
+ - Poincare ball model
138
+ - Hierarchy-aware distances
139
+
140
+ **Key concepts:**
141
+ - Hyperbolic space captures hierarchies better
142
+ - Nodes closer to origin = higher in hierarchy
143
+ - Distance reflects tree structure
144
+
145
+ ### 6. self-learning.ts
146
+
147
+ Self-optimization features:
148
+ - Enabling the learning loop
149
+ - Query pattern recognition
150
+ - Auto-tuning HNSW parameters
151
+ - Anomaly detection
152
+ - EWC++ for preventing forgetting
153
+
154
+ **Key concepts:**
155
+ - Continuous learning from query patterns
156
+ - Automatic index optimization
157
+ - Pattern-based query prediction
158
+
159
+ ### 7. streaming-large-data.ts
160
+
161
+ Handling large datasets:
162
+ - Streaming millions of vectors
163
+ - Backpressure handling
164
+ - Progress monitoring
165
+ - Memory-efficient processing
166
+
167
+ **Key concepts:**
168
+ - Async generators for streaming
169
+ - Semaphore-based backpressure
170
+ - Concurrent batch processing
171
+
172
+ ### 8. quantization.ts
173
+
174
+ Memory optimization:
175
+ - Int8 scalar quantization (4x compression)
176
+ - Int4 scalar quantization (8x compression)
177
+ - Binary quantization (32x compression)
178
+ - Product Quantization (PQ)
179
+ - Recall vs compression trade-offs
180
+
181
+ **Key concepts:**
182
+ - Quantization reduces memory significantly
183
+ - Trade-off between compression and recall
184
+ - Different methods for different use cases
185
+
186
+ ### 9. transactions.ts
187
+
188
+ ACID operations:
189
+ - Multi-vector atomic updates
190
+ - Savepoint usage
191
+ - Error recovery patterns
192
+ - Optimistic locking
193
+
194
+ **Key concepts:**
195
+ - Transactions ensure consistency
196
+ - Savepoints for partial rollbacks
197
+ - Retry with exponential backoff
198
+
199
+ ## Configuration
200
+
201
+ ### Environment Variables
202
+
203
+ ```bash
204
+ # PostgreSQL connection
205
+ export POSTGRES_HOST=localhost
206
+ export POSTGRES_PORT=5432
207
+ export POSTGRES_DB=vectors
208
+ export POSTGRES_USER=postgres
209
+ export POSTGRES_PASSWORD=postgres
210
+ ```
211
+
212
+ ### Docker Compose Services
213
+
214
+ | Service | Port | Description |
215
+ |---------|------|-------------|
216
+ | postgres | 5432 | PostgreSQL 16 with pgvector |
217
+ | adminer | 8080 | Database management UI |
218
+
219
+ Access Adminer at http://localhost:8080:
220
+ - System: PostgreSQL
221
+ - Server: postgres
222
+ - Username: postgres
223
+ - Password: postgres
224
+ - Database: vectors
225
+
226
+ ## Troubleshooting
227
+
228
+ ### Connection Refused
229
+
230
+ Ensure PostgreSQL is running:
231
+ ```bash
232
+ docker compose ps
233
+ docker compose logs postgres
234
+ ```
235
+
236
+ ### Extension Not Found
237
+
238
+ The pgvector extension should be auto-created. Verify:
239
+ ```sql
240
+ SELECT * FROM pg_extension WHERE extname = 'vector';
241
+ ```
242
+
243
+ ### Out of Memory
244
+
245
+ For large datasets, adjust PostgreSQL memory settings in docker-compose.yml:
246
+ ```yaml
247
+ command: >
248
+ postgres
249
+ -c shared_buffers=512MB
250
+ -c work_mem=32MB
251
+ ```
252
+
253
+ ### Slow Searches
254
+
255
+ Ensure HNSW index exists:
256
+ ```sql
257
+ SELECT indexname FROM pg_indexes WHERE tablename = 'your_table';
258
+ ```
259
+
260
+ Tune search parameters:
261
+ ```sql
262
+ SET hnsw.ef_search = 100; -- Increase for better recall
263
+ ```
264
+
265
+ ## Performance Tips
266
+
267
+ 1. **Batch inserts** for bulk loading (1000+ vectors at a time)
268
+ 2. **Use HNSW indexes** for approximate nearest neighbor search
269
+ 3. **Tune ef_search** based on recall requirements
270
+ 4. **Consider quantization** for large datasets
271
+ 5. **Use connection pooling** for concurrent access
272
+
273
+ ## Cleanup
274
+
275
+ Stop and remove containers:
276
+ ```bash
277
+ docker compose down
278
+
279
+ # Remove data volumes too:
280
+ docker compose down -v
281
+ ```
282
+
283
+ ## Resources
284
+
285
+ - [pgvector Documentation](https://github.com/pgvector/pgvector)
286
+ - [RuVector Plugin Documentation](../../src/integrations/ruvector/README.md)
287
+ - [HNSW Algorithm Paper](https://arxiv.org/abs/1603.09320)
288
+ - [Poincare Embeddings Paper](https://arxiv.org/abs/1705.08039)