@soulcraft/brainy 3.18.0 → 3.19.1

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 (39) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/README.md +52 -3
  3. package/bin/brainy.js +9 -2335
  4. package/dist/api/DataAPI.d.ts +1 -1
  5. package/dist/augmentations/cacheAugmentation.d.ts +1 -1
  6. package/dist/augmentations/metricsAugmentation.d.ts +20 -20
  7. package/dist/brainy.d.ts +19 -1
  8. package/dist/brainy.js +24 -0
  9. package/dist/brainyData.js +1 -2
  10. package/dist/cli/catalog.js +8 -12
  11. package/dist/cli/commands/conversation.d.ts +22 -0
  12. package/dist/cli/commands/conversation.js +528 -0
  13. package/dist/cli/commands/core.js +61 -17
  14. package/dist/cli/commands/neural.js +4 -5
  15. package/dist/cli/commands/types.d.ts +30 -0
  16. package/dist/cli/commands/types.js +194 -0
  17. package/dist/cli/commands/utility.js +2 -3
  18. package/dist/cli/index.js +44 -2
  19. package/dist/cli/interactive.d.ts +3 -3
  20. package/dist/cli/interactive.js +5 -5
  21. package/dist/conversation/conversationManager.d.ts +176 -0
  22. package/dist/conversation/conversationManager.js +666 -0
  23. package/dist/conversation/index.d.ts +8 -0
  24. package/dist/conversation/index.js +8 -0
  25. package/dist/conversation/types.d.ts +231 -0
  26. package/dist/conversation/types.js +8 -0
  27. package/dist/hnsw/hnswIndexOptimized.d.ts +1 -1
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.js +3 -0
  30. package/dist/mcp/brainyMCPBroadcast.d.ts +2 -2
  31. package/dist/mcp/brainyMCPBroadcast.js +1 -1
  32. package/dist/mcp/brainyMCPClient.js +8 -4
  33. package/dist/mcp/conversationTools.d.ts +88 -0
  34. package/dist/mcp/conversationTools.js +470 -0
  35. package/dist/neural/types.d.ts +2 -2
  36. package/dist/streaming/pipeline.d.ts +1 -1
  37. package/dist/types/mcpTypes.d.ts +7 -1
  38. package/dist/universal/fs.d.ts +24 -66
  39. package/package.json +2 -2
@@ -0,0 +1,470 @@
1
+ /**
2
+ * MCP Conversation Tools
3
+ *
4
+ * Exposes ConversationManager functionality through MCP for Claude Code integration.
5
+ * Provides 6 tools for infinite agent memory.
6
+ *
7
+ * REAL IMPLEMENTATION - Uses ConversationManager which uses real Brainy APIs
8
+ */
9
+ import { v4 as uuidv4 } from '../universal/uuid.js';
10
+ import { MCP_VERSION } from '../types/mcpTypes.js';
11
+ import { ConversationManager } from '../conversation/conversationManager.js';
12
+ /**
13
+ * MCP Conversation Toolset
14
+ *
15
+ * Provides conversation and context management tools for AI agents
16
+ */
17
+ export class MCPConversationToolset {
18
+ /**
19
+ * Create MCP Conversation Toolset
20
+ * @param brain Brainy instance
21
+ */
22
+ constructor(brain) {
23
+ this.brain = brain;
24
+ this.initialized = false;
25
+ this.conversationManager = new ConversationManager(brain);
26
+ }
27
+ /**
28
+ * Initialize the toolset
29
+ */
30
+ async init() {
31
+ if (this.initialized) {
32
+ return;
33
+ }
34
+ await this.conversationManager.init();
35
+ this.initialized = true;
36
+ }
37
+ /**
38
+ * Handle MCP tool execution request
39
+ * @param request MCP tool execution request
40
+ * @returns MCP response
41
+ */
42
+ async handleRequest(request) {
43
+ if (!this.initialized) {
44
+ await this.init();
45
+ }
46
+ try {
47
+ const { toolName, parameters } = request;
48
+ // Route to appropriate tool handler
49
+ switch (toolName) {
50
+ case 'conversation_save_message':
51
+ return await this.handleSaveMessage(request.requestId, parameters);
52
+ case 'conversation_get_context':
53
+ return await this.handleGetContext(request.requestId, parameters);
54
+ case 'conversation_search':
55
+ return await this.handleSearch(request.requestId, parameters);
56
+ case 'conversation_get_thread':
57
+ return await this.handleGetThread(request.requestId, parameters);
58
+ case 'conversation_save_artifact':
59
+ return await this.handleSaveArtifact(request.requestId, parameters);
60
+ case 'conversation_find_similar':
61
+ return await this.handleFindSimilar(request.requestId, parameters);
62
+ default:
63
+ return this.createErrorResponse(request.requestId, 'UNKNOWN_TOOL', `Unknown conversation tool: ${toolName}`);
64
+ }
65
+ }
66
+ catch (error) {
67
+ return this.createErrorResponse(request.requestId, 'INTERNAL_ERROR', error instanceof Error ? error.message : String(error));
68
+ }
69
+ }
70
+ /**
71
+ * Get available conversation tools
72
+ * @returns Array of MCP tool definitions
73
+ */
74
+ async getAvailableTools() {
75
+ return [
76
+ {
77
+ name: 'conversation_save_message',
78
+ description: 'Save a message to conversation history with automatic embedding and indexing',
79
+ parameters: {
80
+ type: 'object',
81
+ properties: {
82
+ content: {
83
+ type: 'string',
84
+ description: 'Message content'
85
+ },
86
+ role: {
87
+ type: 'string',
88
+ enum: ['user', 'assistant', 'system', 'tool'],
89
+ description: 'Message role'
90
+ },
91
+ conversationId: {
92
+ type: 'string',
93
+ description: 'Conversation ID (auto-generated if not provided)'
94
+ },
95
+ sessionId: {
96
+ type: 'string',
97
+ description: 'Session ID (optional)'
98
+ },
99
+ phase: {
100
+ type: 'string',
101
+ enum: [
102
+ 'understanding',
103
+ 'analysis',
104
+ 'planning',
105
+ 'implementation',
106
+ 'testing',
107
+ 'debugging',
108
+ 'refinement',
109
+ 'completed'
110
+ ],
111
+ description: 'Problem-solving phase'
112
+ },
113
+ confidence: {
114
+ type: 'number',
115
+ minimum: 0,
116
+ maximum: 1,
117
+ description: 'Confidence score (0-1)'
118
+ },
119
+ artifacts: {
120
+ type: 'array',
121
+ items: { type: 'string' },
122
+ description: 'Artifact IDs or paths'
123
+ },
124
+ toolsUsed: {
125
+ type: 'array',
126
+ items: { type: 'string' },
127
+ description: 'Names of tools used'
128
+ },
129
+ tags: {
130
+ type: 'array',
131
+ items: { type: 'string' },
132
+ description: 'Tags for categorization'
133
+ },
134
+ linkToPrevious: {
135
+ type: 'string',
136
+ description: 'ID of previous message to link'
137
+ }
138
+ },
139
+ required: ['content', 'role']
140
+ }
141
+ },
142
+ {
143
+ name: 'conversation_get_context',
144
+ description: 'Retrieve relevant context from conversation history using semantic search',
145
+ parameters: {
146
+ type: 'object',
147
+ properties: {
148
+ query: {
149
+ type: 'string',
150
+ description: 'Query string for context retrieval'
151
+ },
152
+ conversationId: {
153
+ type: 'string',
154
+ description: 'Limit to specific conversation'
155
+ },
156
+ limit: {
157
+ type: 'number',
158
+ description: 'Maximum messages to return (default: 10)',
159
+ default: 10
160
+ },
161
+ maxTokens: {
162
+ type: 'number',
163
+ description: 'Token budget for context (default: 50000)',
164
+ default: 50000
165
+ },
166
+ relevanceThreshold: {
167
+ type: 'number',
168
+ minimum: 0,
169
+ maximum: 1,
170
+ description: 'Minimum similarity score (default: 0.7)',
171
+ default: 0.7
172
+ },
173
+ role: {
174
+ oneOf: [
175
+ { type: 'string', enum: ['user', 'assistant', 'system', 'tool'] },
176
+ { type: 'array', items: { type: 'string' } }
177
+ ],
178
+ description: 'Filter by message role'
179
+ },
180
+ tags: {
181
+ type: 'array',
182
+ items: { type: 'string' },
183
+ description: 'Filter by tags'
184
+ },
185
+ includeArtifacts: {
186
+ type: 'boolean',
187
+ description: 'Include linked artifacts',
188
+ default: false
189
+ },
190
+ includeSimilarConversations: {
191
+ type: 'boolean',
192
+ description: 'Include similar past conversations',
193
+ default: false
194
+ }
195
+ },
196
+ required: ['query']
197
+ }
198
+ },
199
+ {
200
+ name: 'conversation_search',
201
+ description: 'Search messages semantically across all conversations',
202
+ parameters: {
203
+ type: 'object',
204
+ properties: {
205
+ query: {
206
+ type: 'string',
207
+ description: 'Search query'
208
+ },
209
+ limit: {
210
+ type: 'number',
211
+ description: 'Maximum results (default: 10)',
212
+ default: 10
213
+ },
214
+ conversationId: {
215
+ type: 'string',
216
+ description: 'Limit to specific conversation'
217
+ },
218
+ role: {
219
+ oneOf: [
220
+ { type: 'string', enum: ['user', 'assistant', 'system', 'tool'] },
221
+ { type: 'array', items: { type: 'string' } }
222
+ ],
223
+ description: 'Filter by role'
224
+ },
225
+ timeRange: {
226
+ type: 'object',
227
+ properties: {
228
+ start: { type: 'number', description: 'Start timestamp' },
229
+ end: { type: 'number', description: 'End timestamp' }
230
+ },
231
+ description: 'Time range filter'
232
+ }
233
+ },
234
+ required: ['query']
235
+ }
236
+ },
237
+ {
238
+ name: 'conversation_get_thread',
239
+ description: 'Get full conversation thread with all messages',
240
+ parameters: {
241
+ type: 'object',
242
+ properties: {
243
+ conversationId: {
244
+ type: 'string',
245
+ description: 'Conversation ID'
246
+ },
247
+ includeArtifacts: {
248
+ type: 'boolean',
249
+ description: 'Include linked artifacts',
250
+ default: false
251
+ }
252
+ },
253
+ required: ['conversationId']
254
+ }
255
+ },
256
+ {
257
+ name: 'conversation_save_artifact',
258
+ description: 'Save code/file artifact and link to conversation',
259
+ parameters: {
260
+ type: 'object',
261
+ properties: {
262
+ path: {
263
+ type: 'string',
264
+ description: 'VFS path for artifact'
265
+ },
266
+ content: {
267
+ type: 'string',
268
+ description: 'Artifact content'
269
+ },
270
+ conversationId: {
271
+ type: 'string',
272
+ description: 'Conversation ID'
273
+ },
274
+ messageId: {
275
+ type: 'string',
276
+ description: 'Message ID to link artifact to'
277
+ },
278
+ type: {
279
+ type: 'string',
280
+ enum: ['code', 'config', 'data', 'document', 'other'],
281
+ description: 'Artifact type'
282
+ },
283
+ language: {
284
+ type: 'string',
285
+ description: 'Programming language (for code artifacts)'
286
+ },
287
+ description: {
288
+ type: 'string',
289
+ description: 'Artifact description'
290
+ }
291
+ },
292
+ required: ['path', 'content', 'conversationId']
293
+ }
294
+ },
295
+ {
296
+ name: 'conversation_find_similar',
297
+ description: 'Find similar past conversations using semantic similarity',
298
+ parameters: {
299
+ type: 'object',
300
+ properties: {
301
+ conversationId: {
302
+ type: 'string',
303
+ description: 'Conversation ID to find similar to'
304
+ },
305
+ limit: {
306
+ type: 'number',
307
+ description: 'Maximum results (default: 5)',
308
+ default: 5
309
+ },
310
+ threshold: {
311
+ type: 'number',
312
+ minimum: 0,
313
+ maximum: 1,
314
+ description: 'Minimum similarity threshold (default: 0.7)',
315
+ default: 0.7
316
+ }
317
+ },
318
+ required: ['conversationId']
319
+ }
320
+ }
321
+ ];
322
+ }
323
+ /**
324
+ * Handle save_message tool
325
+ * REAL: Uses ConversationManager.saveMessage()
326
+ */
327
+ async handleSaveMessage(requestId, parameters) {
328
+ const { content, role, conversationId, sessionId, phase, confidence, artifacts, toolsUsed, tags, linkToPrevious } = parameters;
329
+ // Validate required parameters
330
+ if (!content || !role) {
331
+ return this.createErrorResponse(requestId, 'INVALID_PARAMETERS', 'Missing required parameters: content and role are required');
332
+ }
333
+ // Save message (REAL)
334
+ const messageId = await this.conversationManager.saveMessage(content, role, {
335
+ conversationId,
336
+ sessionId,
337
+ phase,
338
+ confidence,
339
+ artifacts,
340
+ toolsUsed,
341
+ tags,
342
+ linkToPrevious
343
+ });
344
+ return this.createSuccessResponse(requestId, {
345
+ messageId,
346
+ conversationId: conversationId || messageId.split('_')[0]
347
+ });
348
+ }
349
+ /**
350
+ * Handle get_context tool
351
+ * REAL: Uses ConversationManager.getRelevantContext()
352
+ */
353
+ async handleGetContext(requestId, parameters) {
354
+ const { query, ...options } = parameters;
355
+ if (!query) {
356
+ return this.createErrorResponse(requestId, 'INVALID_PARAMETERS', 'Missing required parameter: query');
357
+ }
358
+ // Get context (REAL)
359
+ const context = await this.conversationManager.getRelevantContext(query, options);
360
+ return this.createSuccessResponse(requestId, context);
361
+ }
362
+ /**
363
+ * Handle search tool
364
+ * REAL: Uses ConversationManager.searchMessages()
365
+ */
366
+ async handleSearch(requestId, parameters) {
367
+ const { query } = parameters;
368
+ if (!query) {
369
+ return this.createErrorResponse(requestId, 'INVALID_PARAMETERS', 'Missing required parameter: query');
370
+ }
371
+ // Search messages (REAL)
372
+ const results = await this.conversationManager.searchMessages(parameters);
373
+ return this.createSuccessResponse(requestId, {
374
+ results,
375
+ count: results.length
376
+ });
377
+ }
378
+ /**
379
+ * Handle get_thread tool
380
+ * REAL: Uses ConversationManager.getConversationThread()
381
+ */
382
+ async handleGetThread(requestId, parameters) {
383
+ const { conversationId, includeArtifacts = false } = parameters;
384
+ if (!conversationId) {
385
+ return this.createErrorResponse(requestId, 'INVALID_PARAMETERS', 'Missing required parameter: conversationId');
386
+ }
387
+ // Get thread (REAL)
388
+ const thread = await this.conversationManager.getConversationThread(conversationId, { includeArtifacts });
389
+ return this.createSuccessResponse(requestId, thread);
390
+ }
391
+ /**
392
+ * Handle save_artifact tool
393
+ * REAL: Uses ConversationManager.saveArtifact()
394
+ */
395
+ async handleSaveArtifact(requestId, parameters) {
396
+ const { path, content, conversationId, messageId, type, language, description } = parameters;
397
+ if (!path || !content || !conversationId) {
398
+ return this.createErrorResponse(requestId, 'INVALID_PARAMETERS', 'Missing required parameters: path, content, and conversationId are required');
399
+ }
400
+ // Save artifact (REAL)
401
+ const artifactId = await this.conversationManager.saveArtifact(path, content, {
402
+ conversationId,
403
+ messageId,
404
+ type,
405
+ language,
406
+ description
407
+ });
408
+ return this.createSuccessResponse(requestId, {
409
+ artifactId,
410
+ path
411
+ });
412
+ }
413
+ /**
414
+ * Handle find_similar tool
415
+ * REAL: Uses ConversationManager.findSimilarConversations()
416
+ */
417
+ async handleFindSimilar(requestId, parameters) {
418
+ const { conversationId, limit = 5, threshold = 0.7 } = parameters;
419
+ if (!conversationId) {
420
+ return this.createErrorResponse(requestId, 'INVALID_PARAMETERS', 'Missing required parameter: conversationId');
421
+ }
422
+ // Find similar (REAL)
423
+ const similar = await this.conversationManager.findSimilarConversations(conversationId, limit, threshold);
424
+ return this.createSuccessResponse(requestId, {
425
+ similar,
426
+ count: similar.length
427
+ });
428
+ }
429
+ /**
430
+ * Create success response
431
+ */
432
+ createSuccessResponse(requestId, data) {
433
+ return {
434
+ success: true,
435
+ requestId,
436
+ version: MCP_VERSION,
437
+ data
438
+ };
439
+ }
440
+ /**
441
+ * Create error response
442
+ */
443
+ createErrorResponse(requestId, code, message, details) {
444
+ return {
445
+ success: false,
446
+ requestId,
447
+ version: MCP_VERSION,
448
+ error: {
449
+ code,
450
+ message,
451
+ details
452
+ }
453
+ };
454
+ }
455
+ /**
456
+ * Generate request ID
457
+ */
458
+ generateRequestId() {
459
+ return uuidv4();
460
+ }
461
+ }
462
+ /**
463
+ * Create MCP conversation toolset
464
+ * @param brain Brainy instance
465
+ * @returns MCPConversationToolset instance
466
+ */
467
+ export function createConversationToolset(brain) {
468
+ return new MCPConversationToolset(brain);
469
+ }
470
+ //# sourceMappingURL=conversationTools.js.map
@@ -267,8 +267,8 @@ export interface StreamingBatch<T = SemanticCluster> {
267
267
  }
268
268
  export declare class NeuralAPIError extends Error {
269
269
  code: string;
270
- context?: Record<string, any> | undefined;
271
- constructor(message: string, code: string, context?: Record<string, any> | undefined);
270
+ context?: Record<string, any>;
271
+ constructor(message: string, code: string, context?: Record<string, any>);
272
272
  }
273
273
  export declare class ClusteringError extends NeuralAPIError {
274
274
  constructor(message: string, context?: Record<string, any>);
@@ -43,7 +43,7 @@ export declare class Pipeline<T = any> {
43
43
  private running;
44
44
  private abortController?;
45
45
  private metrics;
46
- constructor(brainyInstance?: (Brainy | Brainy<any>) | undefined);
46
+ constructor(brainyInstance?: Brainy | Brainy<any>);
47
47
  /**
48
48
  * Add a data source
49
49
  */
@@ -102,10 +102,16 @@ export interface MCPTool {
102
102
  parameters: {
103
103
  type: 'object';
104
104
  properties: Record<string, {
105
- type: string;
105
+ type?: string;
106
106
  description: string;
107
107
  enum?: string[];
108
108
  required?: boolean;
109
+ minimum?: number;
110
+ maximum?: number;
111
+ default?: any;
112
+ items?: any;
113
+ oneOf?: any[];
114
+ [key: string]: any;
109
115
  }>;
110
116
  required: string[];
111
117
  };
@@ -28,74 +28,32 @@ export interface UniversalFS {
28
28
  }>;
29
29
  access(path: string, mode?: number): Promise<void>;
30
30
  }
31
- export declare const readFile: (path: string, encoding?: string) => Promise<string>;
32
- export declare const writeFile: (path: string, data: string, encoding?: string) => Promise<void>;
33
- export declare const mkdir: (path: string, options?: {
34
- recursive?: boolean;
35
- }) => Promise<void>;
36
- export declare const exists: (path: string) => Promise<boolean>;
37
- export declare const readdir: {
38
- (path: string): Promise<string[]>;
39
- (path: string, options: {
40
- withFileTypes: true;
41
- }): Promise<{
42
- name: string;
43
- isDirectory(): boolean;
44
- isFile(): boolean;
45
- }[]>;
46
- };
47
- export declare const unlink: (path: string) => Promise<void>;
48
- export declare const stat: (path: string) => Promise<{
49
- isFile(): boolean;
50
- isDirectory(): boolean;
51
- }>;
52
- export declare const access: (path: string, mode?: number) => Promise<void>;
31
+ export declare const readFile: any;
32
+ export declare const writeFile: any;
33
+ export declare const mkdir: any;
34
+ export declare const exists: any;
35
+ export declare const readdir: any;
36
+ export declare const unlink: any;
37
+ export declare const stat: any;
38
+ export declare const access: any;
53
39
  declare const _default: {
54
- readFile: (path: string, encoding?: string) => Promise<string>;
55
- writeFile: (path: string, data: string, encoding?: string) => Promise<void>;
56
- mkdir: (path: string, options?: {
57
- recursive?: boolean;
58
- }) => Promise<void>;
59
- exists: (path: string) => Promise<boolean>;
60
- readdir: {
61
- (path: string): Promise<string[]>;
62
- (path: string, options: {
63
- withFileTypes: true;
64
- }): Promise<{
65
- name: string;
66
- isDirectory(): boolean;
67
- isFile(): boolean;
68
- }[]>;
69
- };
70
- unlink: (path: string) => Promise<void>;
71
- stat: (path: string) => Promise<{
72
- isFile(): boolean;
73
- isDirectory(): boolean;
74
- }>;
75
- access: (path: string, mode?: number) => Promise<void>;
40
+ readFile: any;
41
+ writeFile: any;
42
+ mkdir: any;
43
+ exists: any;
44
+ readdir: any;
45
+ unlink: any;
46
+ stat: any;
47
+ access: any;
76
48
  };
77
49
  export default _default;
78
50
  export declare const promises: {
79
- readFile: (path: string, encoding?: string) => Promise<string>;
80
- writeFile: (path: string, data: string, encoding?: string) => Promise<void>;
81
- mkdir: (path: string, options?: {
82
- recursive?: boolean;
83
- }) => Promise<void>;
84
- exists: (path: string) => Promise<boolean>;
85
- readdir: {
86
- (path: string): Promise<string[]>;
87
- (path: string, options: {
88
- withFileTypes: true;
89
- }): Promise<{
90
- name: string;
91
- isDirectory(): boolean;
92
- isFile(): boolean;
93
- }[]>;
94
- };
95
- unlink: (path: string) => Promise<void>;
96
- stat: (path: string) => Promise<{
97
- isFile(): boolean;
98
- isDirectory(): boolean;
99
- }>;
100
- access: (path: string, mode?: number) => Promise<void>;
51
+ readFile: any;
52
+ writeFile: any;
53
+ mkdir: any;
54
+ exists: any;
55
+ readdir: any;
56
+ unlink: any;
57
+ stat: any;
58
+ access: any;
101
59
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soulcraft/brainy",
3
- "version": "3.18.0",
3
+ "version": "3.19.1",
4
4
  "description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. 31 nouns × 40 verbs for infinite expressiveness.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -55,7 +55,7 @@
55
55
  "node": "22.x"
56
56
  },
57
57
  "scripts": {
58
- "build": "npm run build:patterns:if-needed && tsc",
58
+ "build": "npm run build:patterns:if-needed && tsc && tsc -p tsconfig.cli.json",
59
59
  "build:patterns": "tsx scripts/buildEmbeddedPatterns.ts",
60
60
  "build:patterns:if-needed": "node scripts/check-patterns.cjs || npm run build:patterns",
61
61
  "build:patterns:force": "npm run build:patterns",