ruvector 0.2.12 → 0.2.14

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/bin/mcp-server.js CHANGED
@@ -428,7 +428,7 @@ class Intelligence {
428
428
  const server = new Server(
429
429
  {
430
430
  name: 'ruvector',
431
- version: '0.2.12',
431
+ version: '0.2.14',
432
432
  },
433
433
  {
434
434
  capabilities: {
@@ -3054,9 +3054,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3054
3054
  }
3055
3055
 
3056
3056
  case 'workers_create': {
3057
- const name = args.name;
3058
- const preset = args.preset || 'quick-scan';
3059
- const triggers = args.triggers;
3057
+ const name = sanitizeShellArg(args.name);
3058
+ const preset = sanitizeShellArg(args.preset || 'quick-scan');
3059
+ const triggers = args.triggers ? sanitizeShellArg(args.triggers) : null;
3060
+ if (!name) {
3061
+ return { content: [{ type: 'text', text: JSON.stringify({
3062
+ success: false,
3063
+ error: 'Invalid worker name'
3064
+ }, null, 2) }] };
3065
+ }
3060
3066
  try {
3061
3067
  let cmd = `npx agentic-flow@alpha workers create "${name}" --preset ${preset}`;
3062
3068
  if (triggers) cmd += ` --triggers "${triggers}"`;
@@ -4132,7 +4138,7 @@ async function main() {
4132
4138
  transport: 'sse',
4133
4139
  sessions: sessions.size,
4134
4140
  tools: 91,
4135
- version: '0.2.12'
4141
+ version: '0.2.13'
4136
4142
  }));
4137
4143
 
4138
4144
  } else {
@@ -0,0 +1,148 @@
1
+ /**
2
+ * AgentDB Fast - High-performance in-process alternative to AgentDB CLI
3
+ *
4
+ * The AgentDB CLI has ~2.3s startup overhead due to npx initialization.
5
+ * This module provides 50-200x faster operations by using in-process calls.
6
+ *
7
+ * Features:
8
+ * - In-memory episode storage with LRU eviction
9
+ * - Vector similarity search using @ruvector/core
10
+ * - Compatible API with AgentDB's episode/trajectory interfaces
11
+ */
12
+ /**
13
+ * Episode entry for trajectory storage
14
+ */
15
+ export interface Episode {
16
+ id: string;
17
+ state: number[];
18
+ action: string | number;
19
+ reward: number;
20
+ nextState: number[];
21
+ done: boolean;
22
+ metadata?: Record<string, any>;
23
+ timestamp?: number;
24
+ }
25
+ /**
26
+ * Trajectory (sequence of episodes)
27
+ */
28
+ export interface Trajectory {
29
+ id: string;
30
+ episodes: Episode[];
31
+ totalReward: number;
32
+ metadata?: Record<string, any>;
33
+ }
34
+ /**
35
+ * Search result for episode queries
36
+ */
37
+ export interface EpisodeSearchResult {
38
+ episode: Episode;
39
+ similarity: number;
40
+ trajectoryId?: string;
41
+ }
42
+ /**
43
+ * Fast in-memory AgentDB implementation
44
+ */
45
+ export declare class FastAgentDB {
46
+ private episodes;
47
+ private trajectories;
48
+ private vectorDb;
49
+ private dimensions;
50
+ private maxEpisodes;
51
+ private episodeOrder;
52
+ /**
53
+ * Create a new FastAgentDB instance
54
+ *
55
+ * @param dimensions - Vector dimensions for state embeddings
56
+ * @param maxEpisodes - Maximum episodes to store (LRU eviction)
57
+ */
58
+ constructor(dimensions?: number, maxEpisodes?: number);
59
+ /**
60
+ * Initialize the vector database
61
+ */
62
+ private initVectorDb;
63
+ /**
64
+ * Store an episode
65
+ *
66
+ * @param episode - Episode to store
67
+ * @returns Episode ID
68
+ */
69
+ storeEpisode(episode: Omit<Episode, 'id'> & {
70
+ id?: string;
71
+ }): Promise<string>;
72
+ /**
73
+ * Store multiple episodes in batch
74
+ */
75
+ storeEpisodes(episodes: (Omit<Episode, 'id'> & {
76
+ id?: string;
77
+ })[]): Promise<string[]>;
78
+ /**
79
+ * Retrieve an episode by ID
80
+ */
81
+ getEpisode(id: string): Promise<Episode | null>;
82
+ /**
83
+ * Search for similar episodes by state
84
+ *
85
+ * @param queryState - State vector to search for
86
+ * @param k - Number of results to return
87
+ * @returns Similar episodes sorted by similarity
88
+ */
89
+ searchByState(queryState: number[] | Float32Array, k?: number): Promise<EpisodeSearchResult[]>;
90
+ /**
91
+ * Fallback similarity search using brute-force cosine similarity
92
+ */
93
+ private fallbackSearch;
94
+ /**
95
+ * Compute cosine similarity between two vectors
96
+ */
97
+ private cosineSimilarity;
98
+ /**
99
+ * Store a trajectory (sequence of episodes)
100
+ */
101
+ storeTrajectory(episodes: (Omit<Episode, 'id'> & {
102
+ id?: string;
103
+ })[], metadata?: Record<string, any>): Promise<string>;
104
+ /**
105
+ * Get a trajectory by ID
106
+ */
107
+ getTrajectory(id: string): Promise<Trajectory | null>;
108
+ /**
109
+ * Get top trajectories by total reward
110
+ */
111
+ getTopTrajectories(k?: number): Promise<Trajectory[]>;
112
+ /**
113
+ * Sample random episodes (for experience replay)
114
+ */
115
+ sampleEpisodes(n: number): Promise<Episode[]>;
116
+ /**
117
+ * Get database statistics
118
+ */
119
+ getStats(): {
120
+ episodeCount: number;
121
+ trajectoryCount: number;
122
+ dimensions: number;
123
+ maxEpisodes: number;
124
+ vectorDbAvailable: boolean;
125
+ };
126
+ /**
127
+ * Clear all data
128
+ */
129
+ clear(): void;
130
+ /**
131
+ * Generate a unique ID
132
+ */
133
+ private generateId;
134
+ }
135
+ /**
136
+ * Create a fast AgentDB instance
137
+ */
138
+ export declare function createFastAgentDB(dimensions?: number, maxEpisodes?: number): FastAgentDB;
139
+ /**
140
+ * Get the default FastAgentDB instance
141
+ */
142
+ export declare function getDefaultAgentDB(): FastAgentDB;
143
+ declare const _default: {
144
+ FastAgentDB: typeof FastAgentDB;
145
+ createFastAgentDB: typeof createFastAgentDB;
146
+ getDefaultAgentDB: typeof getDefaultAgentDB;
147
+ };
148
+ export default _default;
@@ -0,0 +1,301 @@
1
+ "use strict";
2
+ /**
3
+ * AgentDB Fast - High-performance in-process alternative to AgentDB CLI
4
+ *
5
+ * The AgentDB CLI has ~2.3s startup overhead due to npx initialization.
6
+ * This module provides 50-200x faster operations by using in-process calls.
7
+ *
8
+ * Features:
9
+ * - In-memory episode storage with LRU eviction
10
+ * - Vector similarity search using @ruvector/core
11
+ * - Compatible API with AgentDB's episode/trajectory interfaces
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.FastAgentDB = void 0;
15
+ exports.createFastAgentDB = createFastAgentDB;
16
+ exports.getDefaultAgentDB = getDefaultAgentDB;
17
+ // Lazy load ruvector core
18
+ let coreModule = null;
19
+ function getCoreModule() {
20
+ if (coreModule)
21
+ return coreModule;
22
+ try {
23
+ coreModule = require('@ruvector/core');
24
+ return coreModule;
25
+ }
26
+ catch {
27
+ // Fallback to ruvector if core not available
28
+ try {
29
+ coreModule = require('ruvector');
30
+ return coreModule;
31
+ }
32
+ catch (e) {
33
+ throw new Error(`Neither @ruvector/core nor ruvector is available: ${e.message}`);
34
+ }
35
+ }
36
+ }
37
+ /**
38
+ * Fast in-memory AgentDB implementation
39
+ */
40
+ class FastAgentDB {
41
+ /**
42
+ * Create a new FastAgentDB instance
43
+ *
44
+ * @param dimensions - Vector dimensions for state embeddings
45
+ * @param maxEpisodes - Maximum episodes to store (LRU eviction)
46
+ */
47
+ constructor(dimensions = 128, maxEpisodes = 100000) {
48
+ this.episodes = new Map();
49
+ this.trajectories = new Map();
50
+ this.vectorDb = null;
51
+ this.episodeOrder = []; // For LRU eviction
52
+ this.dimensions = dimensions;
53
+ this.maxEpisodes = maxEpisodes;
54
+ }
55
+ /**
56
+ * Initialize the vector database
57
+ */
58
+ async initVectorDb() {
59
+ if (this.vectorDb)
60
+ return;
61
+ try {
62
+ const core = getCoreModule();
63
+ this.vectorDb = new core.VectorDB({
64
+ dimensions: this.dimensions,
65
+ distanceMetric: 'Cosine',
66
+ });
67
+ }
68
+ catch (e) {
69
+ // Vector DB not available, use fallback similarity
70
+ console.warn(`VectorDB not available, using fallback similarity: ${e.message}`);
71
+ }
72
+ }
73
+ /**
74
+ * Store an episode
75
+ *
76
+ * @param episode - Episode to store
77
+ * @returns Episode ID
78
+ */
79
+ async storeEpisode(episode) {
80
+ await this.initVectorDb();
81
+ const id = episode.id ?? this.generateId();
82
+ const fullEpisode = {
83
+ ...episode,
84
+ id,
85
+ timestamp: episode.timestamp ?? Date.now(),
86
+ };
87
+ // LRU eviction if needed
88
+ if (this.episodes.size >= this.maxEpisodes) {
89
+ const oldestId = this.episodeOrder.shift();
90
+ if (oldestId) {
91
+ this.episodes.delete(oldestId);
92
+ }
93
+ }
94
+ this.episodes.set(id, fullEpisode);
95
+ this.episodeOrder.push(id);
96
+ // Index in vector DB if available
97
+ if (this.vectorDb && fullEpisode.state.length === this.dimensions) {
98
+ try {
99
+ await this.vectorDb.insert({
100
+ id,
101
+ vector: new Float32Array(fullEpisode.state),
102
+ });
103
+ }
104
+ catch {
105
+ // Ignore indexing errors
106
+ }
107
+ }
108
+ return id;
109
+ }
110
+ /**
111
+ * Store multiple episodes in batch
112
+ */
113
+ async storeEpisodes(episodes) {
114
+ const ids = [];
115
+ for (const episode of episodes) {
116
+ const id = await this.storeEpisode(episode);
117
+ ids.push(id);
118
+ }
119
+ return ids;
120
+ }
121
+ /**
122
+ * Retrieve an episode by ID
123
+ */
124
+ async getEpisode(id) {
125
+ const episode = this.episodes.get(id);
126
+ if (episode) {
127
+ // Update LRU order
128
+ const idx = this.episodeOrder.indexOf(id);
129
+ if (idx > -1) {
130
+ this.episodeOrder.splice(idx, 1);
131
+ this.episodeOrder.push(id);
132
+ }
133
+ }
134
+ return episode ?? null;
135
+ }
136
+ /**
137
+ * Search for similar episodes by state
138
+ *
139
+ * @param queryState - State vector to search for
140
+ * @param k - Number of results to return
141
+ * @returns Similar episodes sorted by similarity
142
+ */
143
+ async searchByState(queryState, k = 10) {
144
+ await this.initVectorDb();
145
+ const query = Array.isArray(queryState) ? queryState : Array.from(queryState);
146
+ // Use vector DB if available
147
+ if (this.vectorDb && query.length === this.dimensions) {
148
+ try {
149
+ const results = await this.vectorDb.search({
150
+ vector: new Float32Array(query),
151
+ k,
152
+ });
153
+ return results
154
+ .map((r) => {
155
+ const episode = this.episodes.get(r.id);
156
+ if (!episode)
157
+ return null;
158
+ return {
159
+ episode,
160
+ similarity: 1 - r.score, // Convert distance to similarity
161
+ };
162
+ })
163
+ .filter((r) => r !== null);
164
+ }
165
+ catch {
166
+ // Fall through to fallback
167
+ }
168
+ }
169
+ // Fallback: brute-force cosine similarity
170
+ return this.fallbackSearch(query, k);
171
+ }
172
+ /**
173
+ * Fallback similarity search using brute-force cosine similarity
174
+ */
175
+ fallbackSearch(query, k) {
176
+ const results = [];
177
+ for (const episode of this.episodes.values()) {
178
+ if (episode.state.length !== query.length)
179
+ continue;
180
+ const similarity = this.cosineSimilarity(query, episode.state);
181
+ results.push({ episode, similarity });
182
+ }
183
+ return results
184
+ .sort((a, b) => b.similarity - a.similarity)
185
+ .slice(0, k);
186
+ }
187
+ /**
188
+ * Compute cosine similarity between two vectors
189
+ */
190
+ cosineSimilarity(a, b) {
191
+ let dotProduct = 0;
192
+ let normA = 0;
193
+ let normB = 0;
194
+ for (let i = 0; i < a.length; i++) {
195
+ dotProduct += a[i] * b[i];
196
+ normA += a[i] * a[i];
197
+ normB += b[i] * b[i];
198
+ }
199
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
200
+ return denom === 0 ? 0 : dotProduct / denom;
201
+ }
202
+ /**
203
+ * Store a trajectory (sequence of episodes)
204
+ */
205
+ async storeTrajectory(episodes, metadata) {
206
+ const trajectoryId = this.generateId();
207
+ const storedEpisodes = [];
208
+ let totalReward = 0;
209
+ for (const episode of episodes) {
210
+ const id = await this.storeEpisode(episode);
211
+ const stored = await this.getEpisode(id);
212
+ if (stored) {
213
+ storedEpisodes.push(stored);
214
+ totalReward += stored.reward;
215
+ }
216
+ }
217
+ const trajectory = {
218
+ id: trajectoryId,
219
+ episodes: storedEpisodes,
220
+ totalReward,
221
+ metadata,
222
+ };
223
+ this.trajectories.set(trajectoryId, trajectory);
224
+ return trajectoryId;
225
+ }
226
+ /**
227
+ * Get a trajectory by ID
228
+ */
229
+ async getTrajectory(id) {
230
+ return this.trajectories.get(id) ?? null;
231
+ }
232
+ /**
233
+ * Get top trajectories by total reward
234
+ */
235
+ async getTopTrajectories(k = 10) {
236
+ return Array.from(this.trajectories.values())
237
+ .sort((a, b) => b.totalReward - a.totalReward)
238
+ .slice(0, k);
239
+ }
240
+ /**
241
+ * Sample random episodes (for experience replay)
242
+ */
243
+ async sampleEpisodes(n) {
244
+ const allEpisodes = Array.from(this.episodes.values());
245
+ const sampled = [];
246
+ for (let i = 0; i < Math.min(n, allEpisodes.length); i++) {
247
+ const idx = Math.floor(Math.random() * allEpisodes.length);
248
+ sampled.push(allEpisodes[idx]);
249
+ }
250
+ return sampled;
251
+ }
252
+ /**
253
+ * Get database statistics
254
+ */
255
+ getStats() {
256
+ return {
257
+ episodeCount: this.episodes.size,
258
+ trajectoryCount: this.trajectories.size,
259
+ dimensions: this.dimensions,
260
+ maxEpisodes: this.maxEpisodes,
261
+ vectorDbAvailable: this.vectorDb !== null,
262
+ };
263
+ }
264
+ /**
265
+ * Clear all data
266
+ */
267
+ clear() {
268
+ this.episodes.clear();
269
+ this.trajectories.clear();
270
+ this.episodeOrder = [];
271
+ }
272
+ /**
273
+ * Generate a unique ID
274
+ */
275
+ generateId() {
276
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
277
+ }
278
+ }
279
+ exports.FastAgentDB = FastAgentDB;
280
+ /**
281
+ * Create a fast AgentDB instance
282
+ */
283
+ function createFastAgentDB(dimensions = 128, maxEpisodes = 100000) {
284
+ return new FastAgentDB(dimensions, maxEpisodes);
285
+ }
286
+ // Singleton instance for convenience
287
+ let defaultInstance = null;
288
+ /**
289
+ * Get the default FastAgentDB instance
290
+ */
291
+ function getDefaultAgentDB() {
292
+ if (!defaultInstance) {
293
+ defaultInstance = new FastAgentDB();
294
+ }
295
+ return defaultInstance;
296
+ }
297
+ exports.default = {
298
+ FastAgentDB,
299
+ createFastAgentDB,
300
+ getDefaultAgentDB,
301
+ };