@soulcraft/brainy 3.19.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.
@@ -0,0 +1,528 @@
1
+ /**
2
+ * 💬 Conversation CLI Commands
3
+ *
4
+ * CLI interface for infinite agent memory and conversation management
5
+ */
6
+ import inquirer from 'inquirer';
7
+ import chalk from 'chalk';
8
+ import ora from 'ora';
9
+ import * as fs from '../../universal/fs.js';
10
+ import * as path from '../../universal/path.js';
11
+ import { Brainy } from '../../brainy.js';
12
+ export const conversationCommand = {
13
+ command: 'conversation [action]',
14
+ describe: '💬 Conversation and context management',
15
+ builder: (yargs) => {
16
+ return yargs
17
+ .positional('action', {
18
+ describe: 'Conversation operation to perform',
19
+ type: 'string',
20
+ choices: ['setup', 'remove', 'search', 'context', 'thread', 'stats', 'export', 'import']
21
+ })
22
+ .option('conversation-id', {
23
+ describe: 'Conversation ID',
24
+ type: 'string',
25
+ alias: 'c'
26
+ })
27
+ .option('query', {
28
+ describe: 'Search query or context query',
29
+ type: 'string',
30
+ alias: 'q'
31
+ })
32
+ .option('role', {
33
+ describe: 'Filter by message role',
34
+ type: 'string',
35
+ choices: ['user', 'assistant', 'system', 'tool'],
36
+ alias: 'r'
37
+ })
38
+ .option('limit', {
39
+ describe: 'Maximum results',
40
+ type: 'number',
41
+ default: 10,
42
+ alias: 'l'
43
+ })
44
+ .option('format', {
45
+ describe: 'Output format',
46
+ type: 'string',
47
+ choices: ['json', 'table', 'text'],
48
+ default: 'table',
49
+ alias: 'f'
50
+ })
51
+ .option('output', {
52
+ describe: 'Output file path',
53
+ type: 'string',
54
+ alias: 'o'
55
+ })
56
+ .example('$0 conversation setup', 'Set up MCP server for Claude Code')
57
+ .example('$0 conversation search -q "authentication" -l 5', 'Search messages')
58
+ .example('$0 conversation context -q "how to implement JWT"', 'Get relevant context')
59
+ .example('$0 conversation thread -c conv_123', 'Get conversation thread')
60
+ .example('$0 conversation stats', 'Show conversation statistics');
61
+ },
62
+ handler: async (argv) => {
63
+ const action = argv.action || 'setup';
64
+ try {
65
+ switch (action) {
66
+ case 'setup':
67
+ await handleSetup(argv);
68
+ break;
69
+ case 'remove':
70
+ await handleRemove(argv);
71
+ break;
72
+ case 'search':
73
+ await handleSearch(argv);
74
+ break;
75
+ case 'context':
76
+ await handleContext(argv);
77
+ break;
78
+ case 'thread':
79
+ await handleThread(argv);
80
+ break;
81
+ case 'stats':
82
+ await handleStats(argv);
83
+ break;
84
+ case 'export':
85
+ await handleExport(argv);
86
+ break;
87
+ case 'import':
88
+ await handleImport(argv);
89
+ break;
90
+ default:
91
+ console.log(chalk.yellow(`Unknown action: ${action}`));
92
+ console.log('Run "brainy conversation --help" for usage information');
93
+ }
94
+ }
95
+ catch (error) {
96
+ console.error(chalk.red(`Error: ${error.message}`));
97
+ process.exit(1);
98
+ }
99
+ }
100
+ };
101
+ /**
102
+ * Handle setup command - Set up MCP server for Claude Code
103
+ */
104
+ async function handleSetup(argv) {
105
+ console.log(chalk.bold.cyan('\n🧠 Brainy Infinite Memory Setup\n'));
106
+ // Check for existing setup
107
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '~';
108
+ const brainyDir = path.join(homeDir, '.brainy-memory');
109
+ const dataDir = path.join(brainyDir, 'data');
110
+ const serverPath = path.join(brainyDir, 'mcp-server.js');
111
+ const configPath = path.join(homeDir, '.config', 'claude-code', 'mcp-servers.json');
112
+ // Check if already set up
113
+ if (await fs.exists(brainyDir)) {
114
+ const { overwrite } = await inquirer.prompt([
115
+ {
116
+ type: 'confirm',
117
+ name: 'overwrite',
118
+ message: 'Brainy memory setup already exists. Overwrite?',
119
+ default: false
120
+ }
121
+ ]);
122
+ if (!overwrite) {
123
+ console.log(chalk.yellow('Setup cancelled'));
124
+ return;
125
+ }
126
+ }
127
+ const spinner = ora('Creating Brainy memory directory...').start();
128
+ try {
129
+ // Create directories
130
+ await fs.mkdir(brainyDir, { recursive: true });
131
+ await fs.mkdir(dataDir, { recursive: true });
132
+ spinner.succeed('Created Brainy memory directory');
133
+ // Create MCP server script
134
+ spinner.start('Creating MCP server script...');
135
+ const serverScript = `#!/usr/bin/env node
136
+
137
+ /**
138
+ * Brainy Infinite Memory MCP Server
139
+ *
140
+ * This server provides conversation and context management
141
+ * for Claude Code through the Model Control Protocol (MCP).
142
+ */
143
+
144
+ import { Brainy } from '@soulcraft/brainy'
145
+ import { BrainyMCPService } from '@soulcraft/brainy'
146
+ import { MCPConversationToolset } from '@soulcraft/brainy'
147
+
148
+ async function main() {
149
+ try {
150
+ // Initialize Brainy with filesystem storage
151
+ const brain = new Brainy({
152
+ storage: {
153
+ type: 'filesystem',
154
+ path: '${dataDir.replace(/\\/g, '/')}'
155
+ },
156
+ silent: true // Suppress console output
157
+ })
158
+
159
+ await brain.init()
160
+
161
+ // Create MCP service
162
+ const mcpService = new BrainyMCPService(brain, {
163
+ enableAuth: false // Local usage, no auth needed
164
+ })
165
+
166
+ // Create conversation toolset
167
+ const conversationTools = new MCPConversationToolset(brain)
168
+ await conversationTools.init()
169
+
170
+ // Register conversation tools
171
+ const tools = await conversationTools.getAvailableTools()
172
+
173
+ console.error('🧠 Brainy Memory Server started')
174
+ console.error(\`📊 \${tools.length} conversation tools available\`)
175
+ console.error('✅ Ready for Claude Code integration')
176
+
177
+ // Handle MCP requests via stdio
178
+ process.stdin.on('data', async (data) => {
179
+ try {
180
+ const request = JSON.parse(data.toString())
181
+
182
+ // Route conversation tool requests
183
+ let response
184
+ if (request.toolName && request.toolName.startsWith('conversation_')) {
185
+ response = await conversationTools.handleRequest(request)
186
+ } else {
187
+ response = await mcpService.handleRequest(request)
188
+ }
189
+
190
+ // Write response to stdout
191
+ process.stdout.write(JSON.stringify(response) + '\\n')
192
+ } catch (error) {
193
+ console.error('Error handling request:', error)
194
+ }
195
+ })
196
+
197
+ // Handle shutdown gracefully
198
+ process.on('SIGINT', () => {
199
+ console.error('\\n🛑 Shutting down Brainy Memory Server')
200
+ process.exit(0)
201
+ })
202
+
203
+ } catch (error) {
204
+ console.error('Failed to start Brainy Memory Server:', error)
205
+ process.exit(1)
206
+ }
207
+ }
208
+
209
+ main()
210
+ `;
211
+ await fs.writeFile(serverPath, serverScript, 'utf8');
212
+ // Make executable on Unix systems
213
+ try {
214
+ await import('fs').then(fsModule => {
215
+ fsModule.promises.chmod(serverPath, 0o755).catch(() => { });
216
+ });
217
+ }
218
+ catch {
219
+ // Windows doesn't need chmod
220
+ }
221
+ spinner.succeed('Created MCP server script');
222
+ // Create Claude Code config
223
+ spinner.start('Configuring Claude Code...');
224
+ const configDir = path.dirname(configPath);
225
+ await fs.mkdir(configDir, { recursive: true });
226
+ let mcpConfig = {};
227
+ if (await fs.exists(configPath)) {
228
+ const existingConfig = await fs.readFile(configPath, 'utf8');
229
+ mcpConfig = JSON.parse(existingConfig);
230
+ }
231
+ mcpConfig['brainy-memory'] = {
232
+ command: 'node',
233
+ args: [serverPath],
234
+ env: {
235
+ NODE_ENV: 'production'
236
+ }
237
+ };
238
+ await fs.writeFile(configPath, JSON.stringify(mcpConfig, null, 2), 'utf8');
239
+ spinner.succeed('Configured Claude Code');
240
+ // Initialize Brainy database
241
+ spinner.start('Initializing Brainy database...');
242
+ const brain = new Brainy({
243
+ storage: {
244
+ type: 'filesystem',
245
+ options: {
246
+ path: dataDir
247
+ }
248
+ },
249
+ silent: true
250
+ });
251
+ await brain.init();
252
+ spinner.succeed('Initialized Brainy database');
253
+ // Success!
254
+ console.log(chalk.bold.green('\n✅ Setup complete!\n'));
255
+ console.log(chalk.cyan('📁 Memory storage:'), brainyDir);
256
+ console.log(chalk.cyan('🔧 MCP server:'), serverPath);
257
+ console.log(chalk.cyan('⚙️ Claude Code config:'), configPath);
258
+ console.log();
259
+ console.log(chalk.bold('🚀 Next steps:'));
260
+ console.log(' 1. Restart Claude Code to load the MCP server');
261
+ console.log(' 2. Start a new conversation - your history will be saved automatically!');
262
+ console.log(' 3. Claude will use past context to help you work faster');
263
+ console.log();
264
+ console.log(chalk.dim('Run "brainy conversation stats" to see your conversation statistics'));
265
+ }
266
+ catch (error) {
267
+ spinner.fail('Setup failed');
268
+ throw error;
269
+ }
270
+ }
271
+ /**
272
+ * Handle remove command - Remove MCP server and optionally data
273
+ */
274
+ async function handleRemove(argv) {
275
+ console.log(chalk.bold.cyan('\n🗑️ Brainy Infinite Memory Removal\n'));
276
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '~';
277
+ const brainyDir = path.join(homeDir, '.brainy-memory');
278
+ const configPath = path.join(homeDir, '.config', 'claude-code', 'mcp-servers.json');
279
+ // Check if setup exists
280
+ const brainyExists = await fs.exists(brainyDir);
281
+ const configExists = await fs.exists(configPath);
282
+ if (!brainyExists && !configExists) {
283
+ console.log(chalk.yellow('No Brainy memory setup found. Nothing to remove.'));
284
+ return;
285
+ }
286
+ // Show what will be removed
287
+ console.log(chalk.white('The following will be removed:'));
288
+ if (brainyExists) {
289
+ console.log(chalk.dim(` • ${brainyDir} (memory data and MCP server)`));
290
+ }
291
+ if (configExists) {
292
+ console.log(chalk.dim(` • MCP config entry in ${configPath}`));
293
+ }
294
+ console.log();
295
+ // Confirm removal
296
+ const { confirm } = await inquirer.prompt([
297
+ {
298
+ type: 'confirm',
299
+ name: 'confirm',
300
+ message: 'Are you sure you want to remove Brainy infinite memory?',
301
+ default: false
302
+ }
303
+ ]);
304
+ if (!confirm) {
305
+ console.log(chalk.yellow('Removal cancelled'));
306
+ return;
307
+ }
308
+ const spinner = ora('Removing Brainy memory setup...').start();
309
+ try {
310
+ // Remove Brainy directory
311
+ if (brainyExists) {
312
+ // Use Node.js fs for rm operation as universal fs doesn't have it
313
+ const nodefs = await import('fs');
314
+ await nodefs.promises.rm(brainyDir, { recursive: true, force: true });
315
+ spinner.text = 'Removed memory directory...';
316
+ }
317
+ // Remove MCP config entry
318
+ if (configExists) {
319
+ try {
320
+ const configContent = await fs.readFile(configPath, 'utf8');
321
+ const mcpConfig = JSON.parse(configContent);
322
+ if (mcpConfig['brainy-memory']) {
323
+ delete mcpConfig['brainy-memory'];
324
+ await fs.writeFile(configPath, JSON.stringify(mcpConfig, null, 2), 'utf8');
325
+ spinner.text = 'Removed MCP configuration...';
326
+ }
327
+ }
328
+ catch (error) {
329
+ // If config file is corrupted or empty, skip
330
+ spinner.warn('Could not update MCP config file');
331
+ }
332
+ }
333
+ spinner.succeed('Successfully removed Brainy infinite memory');
334
+ console.log();
335
+ console.log(chalk.bold('✅ Cleanup complete'));
336
+ console.log();
337
+ console.log(chalk.white('All conversation data and MCP configuration have been removed.'));
338
+ console.log(chalk.dim('Run "brainy conversation setup" to set up again.'));
339
+ console.log();
340
+ }
341
+ catch (error) {
342
+ spinner.fail('Removal failed');
343
+ console.error(chalk.red('Error:'), error.message);
344
+ throw error;
345
+ }
346
+ }
347
+ /**
348
+ * Handle search command - Search messages
349
+ */
350
+ async function handleSearch(argv) {
351
+ if (!argv.query) {
352
+ console.log(chalk.yellow('Query required. Use -q or --query'));
353
+ return;
354
+ }
355
+ const spinner = ora('Searching conversations...').start();
356
+ const brain = new Brainy();
357
+ await brain.init();
358
+ const conv = brain.conversation();
359
+ await conv.init();
360
+ const results = await conv.searchMessages({
361
+ query: argv.query,
362
+ limit: argv.limit || 10,
363
+ role: argv.role,
364
+ includeContent: true,
365
+ includeMetadata: true
366
+ });
367
+ spinner.succeed(`Found ${results.length} messages`);
368
+ if (results.length === 0) {
369
+ console.log(chalk.yellow('No messages found'));
370
+ return;
371
+ }
372
+ // Display results
373
+ console.log();
374
+ for (const result of results) {
375
+ console.log(chalk.bold.cyan(`${result.message.role}:`), result.snippet);
376
+ console.log(chalk.dim(` Score: ${result.score.toFixed(3)} | Conv: ${result.conversationId}`));
377
+ console.log();
378
+ }
379
+ }
380
+ /**
381
+ * Handle context command - Get relevant context
382
+ */
383
+ async function handleContext(argv) {
384
+ if (!argv.query) {
385
+ console.log(chalk.yellow('Query required. Use -q or --query'));
386
+ return;
387
+ }
388
+ const spinner = ora('Retrieving relevant context...').start();
389
+ const brain = new Brainy();
390
+ await brain.init();
391
+ const conv = brain.conversation();
392
+ await conv.init();
393
+ const context = await conv.getRelevantContext(argv.query, {
394
+ limit: argv.limit || 10,
395
+ includeArtifacts: true,
396
+ includeSimilarConversations: true
397
+ });
398
+ spinner.succeed(`Retrieved ${context.messages.length} relevant messages`);
399
+ if (context.messages.length === 0) {
400
+ console.log(chalk.yellow('No relevant context found'));
401
+ return;
402
+ }
403
+ // Display context
404
+ console.log();
405
+ console.log(chalk.bold('📊 Context Statistics:'));
406
+ console.log(chalk.dim(` Messages: ${context.messages.length}`));
407
+ console.log(chalk.dim(` Tokens: ${context.totalTokens}`));
408
+ console.log(chalk.dim(` Query time: ${context.metadata.queryTime}ms`));
409
+ console.log();
410
+ console.log(chalk.bold('💬 Relevant Messages:'));
411
+ for (const msg of context.messages) {
412
+ console.log();
413
+ console.log(chalk.cyan(`${msg.role} (score: ${msg.relevanceScore.toFixed(3)}):`));
414
+ console.log(msg.content.substring(0, 200) + (msg.content.length > 200 ? '...' : ''));
415
+ }
416
+ if (context.similarConversations && context.similarConversations.length > 0) {
417
+ console.log();
418
+ console.log(chalk.bold('🔗 Similar Conversations:'));
419
+ for (const conv of context.similarConversations) {
420
+ console.log(chalk.dim(` - ${conv.title || conv.id} (${conv.relevance.toFixed(2)})`));
421
+ }
422
+ }
423
+ }
424
+ /**
425
+ * Handle thread command - Get conversation thread
426
+ */
427
+ async function handleThread(argv) {
428
+ if (!argv.conversationId) {
429
+ console.log(chalk.yellow('Conversation ID required. Use -c or --conversation-id'));
430
+ return;
431
+ }
432
+ const spinner = ora('Loading conversation thread...').start();
433
+ const brain = new Brainy();
434
+ await brain.init();
435
+ const conv = brain.conversation();
436
+ await conv.init();
437
+ const thread = await conv.getConversationThread(argv.conversationId, {
438
+ includeArtifacts: true
439
+ });
440
+ spinner.succeed(`Loaded ${thread.messages.length} messages`);
441
+ // Display thread
442
+ console.log();
443
+ console.log(chalk.bold('📊 Thread Information:'));
444
+ console.log(chalk.dim(` Conversation: ${thread.id}`));
445
+ console.log(chalk.dim(` Messages: ${thread.metadata.messageCount}`));
446
+ console.log(chalk.dim(` Tokens: ${thread.metadata.totalTokens}`));
447
+ console.log(chalk.dim(` Started: ${new Date(thread.metadata.startTime).toLocaleString()}`));
448
+ console.log();
449
+ console.log(chalk.bold('💬 Messages:'));
450
+ for (const msg of thread.messages) {
451
+ console.log();
452
+ console.log(chalk.cyan(`${msg.role}:`), msg.content);
453
+ console.log(chalk.dim(` ${new Date(msg.createdAt).toLocaleString()}`));
454
+ }
455
+ }
456
+ /**
457
+ * Handle stats command - Show statistics
458
+ */
459
+ async function handleStats(argv) {
460
+ const spinner = ora('Calculating statistics...').start();
461
+ const brain = new Brainy();
462
+ await brain.init();
463
+ const conv = brain.conversation();
464
+ await conv.init();
465
+ const stats = await conv.getConversationStats();
466
+ spinner.succeed('Statistics calculated');
467
+ // Display stats
468
+ console.log();
469
+ console.log(chalk.bold.cyan('📊 Conversation Statistics\n'));
470
+ console.log(chalk.bold('Overall:'));
471
+ console.log(chalk.dim(` Conversations: ${stats.totalConversations}`));
472
+ console.log(chalk.dim(` Messages: ${stats.totalMessages}`));
473
+ console.log(chalk.dim(` Total Tokens: ${stats.totalTokens.toLocaleString()}`));
474
+ console.log(chalk.dim(` Avg Messages/Conversation: ${stats.averageMessagesPerConversation.toFixed(1)}`));
475
+ console.log(chalk.dim(` Avg Tokens/Message: ${stats.averageTokensPerMessage.toFixed(1)}`));
476
+ console.log();
477
+ if (Object.keys(stats.roles).length > 0) {
478
+ console.log(chalk.bold('By Role:'));
479
+ for (const [role, count] of Object.entries(stats.roles)) {
480
+ console.log(chalk.dim(` ${role}: ${count}`));
481
+ }
482
+ console.log();
483
+ }
484
+ if (Object.keys(stats.phases).length > 0) {
485
+ console.log(chalk.bold('By Phase:'));
486
+ for (const [phase, count] of Object.entries(stats.phases)) {
487
+ console.log(chalk.dim(` ${phase}: ${count}`));
488
+ }
489
+ }
490
+ }
491
+ /**
492
+ * Handle export command - Export conversation
493
+ */
494
+ async function handleExport(argv) {
495
+ if (!argv.conversationId) {
496
+ console.log(chalk.yellow('Conversation ID required. Use -c or --conversation-id'));
497
+ return;
498
+ }
499
+ const spinner = ora('Exporting conversation...').start();
500
+ const brain = new Brainy();
501
+ await brain.init();
502
+ const conv = brain.conversation();
503
+ await conv.init();
504
+ const exported = await conv.exportConversation(argv.conversationId);
505
+ const output = argv.output || `conversation_${argv.conversationId}.json`;
506
+ await fs.writeFile(output, JSON.stringify(exported, null, 2), 'utf8');
507
+ spinner.succeed(`Exported to ${output}`);
508
+ }
509
+ /**
510
+ * Handle import command - Import conversation
511
+ */
512
+ async function handleImport(argv) {
513
+ const inputFile = argv.output;
514
+ if (!inputFile) {
515
+ console.log(chalk.yellow('Input file required. Use -o or --output'));
516
+ return;
517
+ }
518
+ const spinner = ora('Importing conversation...').start();
519
+ const brain = new Brainy();
520
+ await brain.init();
521
+ const conv = brain.conversation();
522
+ await conv.init();
523
+ const data = JSON.parse(await fs.readFile(inputFile, 'utf8'));
524
+ const conversationId = await conv.importConversation(data);
525
+ spinner.succeed(`Imported as conversation ${conversationId}`);
526
+ }
527
+ export default conversationCommand;
528
+ //# sourceMappingURL=conversation.js.map
@@ -5,12 +5,13 @@
5
5
  */
6
6
  import chalk from 'chalk';
7
7
  import ora from 'ora';
8
- import { readFileSync, writeFileSync } from 'fs';
9
- import { BrainyData } from '../../brainyData.js';
8
+ import { readFileSync, writeFileSync } from 'node:fs';
9
+ import { Brainy } from '../../brainy.js';
10
+ import { BrainyTypes, NounType } from '../../index.js';
10
11
  let brainyInstance = null;
11
12
  const getBrainy = async () => {
12
13
  if (!brainyInstance) {
13
- brainyInstance = new BrainyData();
14
+ brainyInstance = new Brainy();
14
15
  await brainyInstance.init();
15
16
  }
16
17
  return brainyInstance;
@@ -41,11 +42,36 @@ export const coreCommands = {
41
42
  if (options.id) {
42
43
  metadata.id = options.id;
43
44
  }
45
+ // Determine noun type
46
+ let nounType;
44
47
  if (options.type) {
45
- metadata.type = options.type;
48
+ // Validate provided type
49
+ if (!BrainyTypes.isValidNoun(options.type)) {
50
+ spinner.fail(`Invalid noun type: ${options.type}`);
51
+ console.log(chalk.dim('Run "brainy types --noun" to see valid types'));
52
+ process.exit(1);
53
+ }
54
+ nounType = options.type;
46
55
  }
47
- // Smart detection by default
48
- const result = await brain.add(text, metadata);
56
+ else {
57
+ // Use AI to suggest type
58
+ spinner.text = 'Detecting type with AI...';
59
+ const suggestion = await BrainyTypes.suggestNoun(typeof text === 'string' ? { content: text, ...metadata } : text);
60
+ if (suggestion.confidence < 0.6) {
61
+ spinner.fail('Could not determine type with confidence');
62
+ console.log(chalk.yellow(`Suggestion: ${suggestion.type} (${(suggestion.confidence * 100).toFixed(1)}%)`));
63
+ console.log(chalk.dim('Use --type flag to specify explicitly'));
64
+ process.exit(1);
65
+ }
66
+ nounType = suggestion.type;
67
+ spinner.text = `Using detected type: ${nounType}`;
68
+ }
69
+ // Add with explicit type
70
+ const result = await brain.add({
71
+ data: text,
72
+ type: nounType,
73
+ metadata
74
+ });
49
75
  spinner.succeed('Added successfully');
50
76
  if (!options.json) {
51
77
  console.log(chalk.green(`✓ Added with ID: ${result}`));
@@ -88,7 +114,7 @@ export const coreCommands = {
88
114
  process.exit(1);
89
115
  }
90
116
  }
91
- const results = await brain.search(query, searchOptions.limit, searchOptions);
117
+ const results = await brain.search(query, searchOptions.limit);
92
118
  spinner.succeed(`Found ${results.length} results`);
93
119
  if (!options.json) {
94
120
  if (results.length === 0) {
@@ -100,8 +126,8 @@ export const coreCommands = {
100
126
  if (result.score !== undefined) {
101
127
  console.log(chalk.dim(` Similarity: ${(result.score * 100).toFixed(1)}%`));
102
128
  }
103
- if (result.metadata) {
104
- console.log(chalk.dim(` Metadata: ${JSON.stringify(result.metadata)}`));
129
+ if (result.entity && result.entity.metadata) {
130
+ console.log(chalk.dim(` Metadata: ${JSON.stringify(result.entity.metadata)}`));
105
131
  }
106
132
  });
107
133
  }
@@ -136,8 +162,8 @@ export const coreCommands = {
136
162
  console.log(chalk.cyan('\nItem Details:'));
137
163
  console.log(` ID: ${item.id}`);
138
164
  console.log(` Content: ${item.content || 'N/A'}`);
139
- if (item.metadata) {
140
- console.log(` Metadata: ${JSON.stringify(item.metadata, null, 2)}`);
165
+ if (item.entity && item.entity.metadata) {
166
+ console.log(` Metadata: ${JSON.stringify(item.entity.metadata, null, 2)}`);
141
167
  }
142
168
  if (options.withConnections) {
143
169
  // Get verbs/relationships
@@ -182,7 +208,12 @@ export const coreCommands = {
182
208
  metadata.weight = parseFloat(options.weight);
183
209
  }
184
210
  // Create the relationship
185
- const result = await brain.addVerb(source, target, verb, metadata);
211
+ const result = await brain.relate({
212
+ from: source,
213
+ to: target,
214
+ type: verb,
215
+ metadata
216
+ });
186
217
  spinner.succeed('Relationship created');
187
218
  if (!options.json) {
188
219
  console.log(chalk.green(`✓ Created relationship with ID: ${result}`));
@@ -245,15 +276,28 @@ export const coreCommands = {
245
276
  for (let i = 0; i < items.length; i += batchSize) {
246
277
  const batch = items.slice(i, i + batchSize);
247
278
  for (const item of batch) {
279
+ let content;
280
+ let metadata = {};
248
281
  if (typeof item === 'string') {
249
- await brain.add(item);
282
+ content = item;
250
283
  }
251
284
  else if (item.content || item.text) {
252
- await brain.add(item.content || item.text, item.metadata || item);
285
+ content = item.content || item.text;
286
+ metadata = item.metadata || item;
253
287
  }
254
288
  else {
255
- await brain.add(JSON.stringify(item), { originalData: item });
289
+ content = JSON.stringify(item);
290
+ metadata = { originalData: item };
256
291
  }
292
+ // Use AI to detect type for each item
293
+ const suggestion = await BrainyTypes.suggestNoun(typeof content === 'string' ? { content, ...metadata } : content);
294
+ // Use suggested type or default to Content if low confidence
295
+ const nounType = suggestion.confidence >= 0.5 ? suggestion.type : NounType.Content;
296
+ await brain.add({
297
+ data: content,
298
+ type: nounType,
299
+ metadata
300
+ });
257
301
  imported++;
258
302
  }
259
303
  spinner.text = `Imported ${imported}/${items.length} items...`;
@@ -283,7 +327,8 @@ export const coreCommands = {
283
327
  const brain = await getBrainy();
284
328
  const format = options.format || 'json';
285
329
  // Export all data
286
- const data = await brain.export({ format: 'json' });
330
+ const dataApi = await brain.data();
331
+ const data = await dataApi.export({ format: 'json' });
287
332
  let output = '';
288
333
  switch (format) {
289
334
  case 'json':
@@ -345,4 +390,3 @@ export const coreCommands = {
345
390
  }
346
391
  }
347
392
  };
348
- //# sourceMappingURL=core.js.map