cozo-memory 1.0.7 β†’ 1.0.8

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.
@@ -1,789 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- /**
4
- * Interactive TUI for CozoDB Memory using Blessed
5
- * Full mouse and keyboard support with interactive menus
6
- */
7
- var __importDefault = (this && this.__importDefault) || function (mod) {
8
- return (mod && mod.__esModule) ? mod : { "default": mod };
9
- };
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- const blessed_1 = __importDefault(require("blessed"));
12
- const cli_commands_js_1 = require("./cli-commands.js");
13
- const cli = new cli_commands_js_1.CLICommands();
14
- // Create screen
15
- const screen = blessed_1.default.screen({
16
- smartCSR: true,
17
- mouse: true,
18
- title: 'CozoDB Memory TUI'
19
- });
20
- // Main container
21
- const container = blessed_1.default.box({
22
- parent: screen,
23
- width: '100%',
24
- height: '100%',
25
- style: {
26
- bg: 'black'
27
- }
28
- });
29
- // Header
30
- const header = blessed_1.default.box({
31
- parent: container,
32
- top: 0,
33
- left: 0,
34
- width: '100%',
35
- height: 3,
36
- content: '{center}{bold}🧠 CozoDB Memory - Interactive TUI{/bold}{/center}\n{center}Press ESC or q to quit | Use mouse or arrow keys{/center}',
37
- tags: true,
38
- style: {
39
- fg: 'white',
40
- bg: 'blue',
41
- bold: true
42
- }
43
- });
44
- // Main menu list
45
- const mainMenu = blessed_1.default.list({
46
- parent: container,
47
- top: 3,
48
- left: 0,
49
- width: '30%',
50
- height: '100%-3',
51
- label: ' Main Menu ',
52
- border: {
53
- type: 'line'
54
- },
55
- style: {
56
- border: {
57
- fg: 'cyan'
58
- },
59
- selected: {
60
- bg: 'blue',
61
- fg: 'white',
62
- bold: true
63
- },
64
- focus: {
65
- border: {
66
- fg: 'green'
67
- }
68
- }
69
- },
70
- keys: true,
71
- vi: true,
72
- mouse: true,
73
- items: [
74
- 'πŸ“Š System Health',
75
- 'πŸ“ˆ System Metrics',
76
- 'βž• Create Entity',
77
- 'πŸ” Search Memory',
78
- 'πŸ•ΈοΈ Graph Operations',
79
- 'πŸ’Ύ Export Data',
80
- 'πŸ“₯ Import Data',
81
- '❌ Exit'
82
- ]
83
- });
84
- // Content area
85
- const contentBox = blessed_1.default.box({
86
- parent: container,
87
- top: 3,
88
- left: '30%',
89
- width: '70%',
90
- height: '100%-3',
91
- label: ' Content ',
92
- border: {
93
- type: 'line'
94
- },
95
- style: {
96
- border: {
97
- fg: 'cyan'
98
- }
99
- },
100
- scrollable: true,
101
- alwaysScroll: true,
102
- mouse: true,
103
- keys: true,
104
- vi: true,
105
- scrollbar: {
106
- ch: 'β–ˆ',
107
- style: {
108
- fg: 'blue'
109
- }
110
- },
111
- tags: true
112
- });
113
- // Loading indicator
114
- const loading = blessed_1.default.loading({
115
- parent: screen,
116
- top: 'center',
117
- left: 'center',
118
- width: 30,
119
- height: 5,
120
- border: {
121
- type: 'line'
122
- },
123
- style: {
124
- border: {
125
- fg: 'yellow'
126
- }
127
- },
128
- hidden: true
129
- });
130
- // Initialize CLI
131
- let initialized = false;
132
- async function initCLI() {
133
- if (!initialized) {
134
- loading.load('Initializing...');
135
- screen.render();
136
- try {
137
- await cli.init();
138
- initialized = true;
139
- loading.stop();
140
- showContent('Welcome! Select an option from the menu.');
141
- }
142
- catch (error) {
143
- loading.stop();
144
- showError(error.message);
145
- }
146
- }
147
- }
148
- function showContent(content) {
149
- contentBox.setContent(content);
150
- screen.render();
151
- }
152
- function showError(message) {
153
- contentBox.setContent(`{red-fg}{bold}Error:{/bold} ${message}{/red-fg}`);
154
- screen.render();
155
- }
156
- function showJSON(data) {
157
- contentBox.setContent(JSON.stringify(data, null, 2));
158
- screen.render();
159
- }
160
- // System Health
161
- async function showSystemHealth() {
162
- loading.load('Loading health...');
163
- screen.render();
164
- try {
165
- const result = await cli.health();
166
- loading.stop();
167
- showContent(`{green-fg}{bold}System Health{/bold}{/green-fg}\n\n` +
168
- `Status: {green-fg}${result.status}{/green-fg}\n` +
169
- `Entities: {cyan-fg}${result.entities}{/cyan-fg}\n` +
170
- `Observations: {cyan-fg}${result.observations}{/cyan-fg}\n` +
171
- `Relationships: {cyan-fg}${result.relationships}{/cyan-fg}`);
172
- }
173
- catch (error) {
174
- loading.stop();
175
- showError(error.message);
176
- }
177
- }
178
- // System Metrics
179
- async function showSystemMetrics() {
180
- loading.load('Loading metrics...');
181
- screen.render();
182
- try {
183
- const result = await cli.metrics();
184
- loading.stop();
185
- showJSON(result);
186
- }
187
- catch (error) {
188
- loading.stop();
189
- showError(error.message);
190
- }
191
- }
192
- // Create Entity Form
193
- function showCreateEntityForm() {
194
- const form = blessed_1.default.form({
195
- parent: screen,
196
- top: 'center',
197
- left: 'center',
198
- width: 60,
199
- height: 16,
200
- border: {
201
- type: 'line'
202
- },
203
- style: {
204
- border: {
205
- fg: 'green'
206
- }
207
- },
208
- label: ' Create Entity ',
209
- keys: true,
210
- vi: true
211
- });
212
- blessed_1.default.text({
213
- parent: form,
214
- top: 1,
215
- left: 2,
216
- content: 'Name:'
217
- });
218
- const nameInput = blessed_1.default.textbox({
219
- parent: form,
220
- name: 'name',
221
- top: 2,
222
- left: 2,
223
- width: '90%',
224
- height: 1,
225
- inputOnFocus: true,
226
- border: {
227
- type: 'line'
228
- },
229
- style: {
230
- border: {
231
- fg: 'white'
232
- },
233
- focus: {
234
- border: {
235
- fg: 'yellow'
236
- }
237
- }
238
- }
239
- });
240
- blessed_1.default.text({
241
- parent: form,
242
- top: 4,
243
- left: 2,
244
- content: 'Type:'
245
- });
246
- const typeInput = blessed_1.default.textbox({
247
- parent: form,
248
- name: 'type',
249
- top: 5,
250
- left: 2,
251
- width: '90%',
252
- height: 1,
253
- inputOnFocus: true,
254
- border: {
255
- type: 'line'
256
- },
257
- style: {
258
- border: {
259
- fg: 'white'
260
- },
261
- focus: {
262
- border: {
263
- fg: 'yellow'
264
- }
265
- }
266
- }
267
- });
268
- const submitButton = blessed_1.default.button({
269
- parent: form,
270
- mouse: true,
271
- keys: true,
272
- shrink: true,
273
- padding: { left: 2, right: 2 },
274
- top: 8,
275
- left: 2,
276
- content: 'Create',
277
- style: {
278
- bg: 'green',
279
- fg: 'white',
280
- focus: {
281
- bg: 'yellow',
282
- fg: 'black'
283
- },
284
- hover: {
285
- bg: 'yellow',
286
- fg: 'black'
287
- }
288
- }
289
- });
290
- const cancelButton = blessed_1.default.button({
291
- parent: form,
292
- mouse: true,
293
- keys: true,
294
- shrink: true,
295
- padding: { left: 2, right: 2 },
296
- top: 8,
297
- left: 15,
298
- content: 'Cancel',
299
- style: {
300
- bg: 'red',
301
- fg: 'white',
302
- focus: {
303
- bg: 'yellow',
304
- fg: 'black'
305
- },
306
- hover: {
307
- bg: 'yellow',
308
- fg: 'black'
309
- }
310
- }
311
- });
312
- submitButton.on('press', async () => {
313
- const name = nameInput.getValue();
314
- const type = typeInput.getValue();
315
- if (!name || !type) {
316
- showError('Name and Type are required');
317
- form.destroy();
318
- screen.render();
319
- return;
320
- }
321
- form.destroy();
322
- loading.load('Creating entity...');
323
- screen.render();
324
- try {
325
- const result = await cli.createEntity(name, type);
326
- loading.stop();
327
- showContent(`{green-fg}{bold}Entity Created!{/bold}{/green-fg}\n\n` +
328
- `ID: {cyan-fg}${result.id}{/cyan-fg}\n` +
329
- `Name: {cyan-fg}${result.name}{/cyan-fg}\n` +
330
- `Type: {cyan-fg}${result.type}{/cyan-fg}\n` +
331
- `Created: {cyan-fg}${result.created_at_iso}{/cyan-fg}`);
332
- }
333
- catch (error) {
334
- loading.stop();
335
- showError(error.message);
336
- }
337
- });
338
- cancelButton.on('press', () => {
339
- form.destroy();
340
- screen.render();
341
- });
342
- form.key(['escape'], () => {
343
- form.destroy();
344
- screen.render();
345
- });
346
- nameInput.focus();
347
- screen.render();
348
- }
349
- // Search Form
350
- function showSearchForm() {
351
- const form = blessed_1.default.form({
352
- parent: screen,
353
- top: 'center',
354
- left: 'center',
355
- width: 60,
356
- height: 12,
357
- border: {
358
- type: 'line'
359
- },
360
- style: {
361
- border: {
362
- fg: 'green'
363
- }
364
- },
365
- label: ' Search Memory ',
366
- keys: true,
367
- vi: true
368
- });
369
- blessed_1.default.text({
370
- parent: form,
371
- top: 1,
372
- left: 2,
373
- content: 'Query:'
374
- });
375
- const queryInput = blessed_1.default.textbox({
376
- parent: form,
377
- name: 'query',
378
- top: 2,
379
- left: 2,
380
- width: '90%',
381
- height: 1,
382
- inputOnFocus: true,
383
- border: {
384
- type: 'line'
385
- },
386
- style: {
387
- border: {
388
- fg: 'white'
389
- },
390
- focus: {
391
- border: {
392
- fg: 'yellow'
393
- }
394
- }
395
- }
396
- });
397
- const submitButton = blessed_1.default.button({
398
- parent: form,
399
- mouse: true,
400
- keys: true,
401
- shrink: true,
402
- padding: { left: 2, right: 2 },
403
- top: 5,
404
- left: 2,
405
- content: 'Search',
406
- style: {
407
- bg: 'green',
408
- fg: 'white',
409
- focus: {
410
- bg: 'yellow',
411
- fg: 'black'
412
- },
413
- hover: {
414
- bg: 'yellow',
415
- fg: 'black'
416
- }
417
- }
418
- });
419
- const cancelButton = blessed_1.default.button({
420
- parent: form,
421
- mouse: true,
422
- keys: true,
423
- shrink: true,
424
- padding: { left: 2, right: 2 },
425
- top: 5,
426
- left: 15,
427
- content: 'Cancel',
428
- style: {
429
- bg: 'red',
430
- fg: 'white',
431
- focus: {
432
- bg: 'yellow',
433
- fg: 'black'
434
- },
435
- hover: {
436
- bg: 'yellow',
437
- fg: 'black'
438
- }
439
- }
440
- });
441
- submitButton.on('press', async () => {
442
- const query = queryInput.getValue();
443
- if (!query) {
444
- showError('Query is required');
445
- form.destroy();
446
- screen.render();
447
- return;
448
- }
449
- form.destroy();
450
- loading.load('Searching...');
451
- screen.render();
452
- try {
453
- const result = await cli.search(query, 10);
454
- loading.stop();
455
- showJSON(result);
456
- }
457
- catch (error) {
458
- loading.stop();
459
- showError(error.message);
460
- }
461
- });
462
- cancelButton.on('press', () => {
463
- form.destroy();
464
- screen.render();
465
- });
466
- form.key(['escape'], () => {
467
- form.destroy();
468
- screen.render();
469
- });
470
- queryInput.focus();
471
- screen.render();
472
- }
473
- // Graph Operations Menu
474
- function showGraphMenu() {
475
- const graphMenu = blessed_1.default.list({
476
- parent: screen,
477
- top: 'center',
478
- left: 'center',
479
- width: 50,
480
- height: 12,
481
- label: ' Graph Operations ',
482
- border: {
483
- type: 'line'
484
- },
485
- style: {
486
- border: {
487
- fg: 'green'
488
- },
489
- selected: {
490
- bg: 'blue',
491
- fg: 'white',
492
- bold: true
493
- }
494
- },
495
- keys: true,
496
- vi: true,
497
- mouse: true,
498
- items: [
499
- 'PageRank',
500
- 'Communities',
501
- 'Explore Graph',
502
- 'Back'
503
- ]
504
- });
505
- graphMenu.on('select', async (item) => {
506
- const text = item.getText();
507
- graphMenu.destroy();
508
- screen.render();
509
- if (text === 'Back') {
510
- return;
511
- }
512
- if (text === 'PageRank') {
513
- loading.load('Computing PageRank...');
514
- screen.render();
515
- try {
516
- const result = await cli.pagerank();
517
- loading.stop();
518
- showJSON(result);
519
- }
520
- catch (error) {
521
- loading.stop();
522
- showError(error.message);
523
- }
524
- }
525
- else if (text === 'Communities') {
526
- loading.load('Detecting communities...');
527
- screen.render();
528
- try {
529
- const result = await cli.communities();
530
- loading.stop();
531
- showJSON(result);
532
- }
533
- catch (error) {
534
- loading.stop();
535
- showError(error.message);
536
- }
537
- }
538
- else if (text === 'Explore Graph') {
539
- showExploreForm();
540
- }
541
- });
542
- graphMenu.key(['escape'], () => {
543
- graphMenu.destroy();
544
- screen.render();
545
- });
546
- graphMenu.focus();
547
- screen.render();
548
- }
549
- // Explore Graph Form
550
- function showExploreForm() {
551
- const form = blessed_1.default.form({
552
- parent: screen,
553
- top: 'center',
554
- left: 'center',
555
- width: 60,
556
- height: 12,
557
- border: {
558
- type: 'line'
559
- },
560
- style: {
561
- border: {
562
- fg: 'green'
563
- }
564
- },
565
- label: ' Explore Graph ',
566
- keys: true,
567
- vi: true
568
- });
569
- blessed_1.default.text({
570
- parent: form,
571
- top: 1,
572
- left: 2,
573
- content: 'Start Entity ID:'
574
- });
575
- const idInput = blessed_1.default.textbox({
576
- parent: form,
577
- name: 'id',
578
- top: 2,
579
- left: 2,
580
- width: '90%',
581
- height: 1,
582
- inputOnFocus: true,
583
- border: {
584
- type: 'line'
585
- },
586
- style: {
587
- border: {
588
- fg: 'white'
589
- },
590
- focus: {
591
- border: {
592
- fg: 'yellow'
593
- }
594
- }
595
- }
596
- });
597
- const submitButton = blessed_1.default.button({
598
- parent: form,
599
- mouse: true,
600
- keys: true,
601
- shrink: true,
602
- padding: { left: 2, right: 2 },
603
- top: 5,
604
- left: 2,
605
- content: 'Explore',
606
- style: {
607
- bg: 'green',
608
- fg: 'white',
609
- focus: {
610
- bg: 'yellow',
611
- fg: 'black'
612
- },
613
- hover: {
614
- bg: 'yellow',
615
- fg: 'black'
616
- }
617
- }
618
- });
619
- const cancelButton = blessed_1.default.button({
620
- parent: form,
621
- mouse: true,
622
- keys: true,
623
- shrink: true,
624
- padding: { left: 2, right: 2 },
625
- top: 5,
626
- left: 15,
627
- content: 'Cancel',
628
- style: {
629
- bg: 'red',
630
- fg: 'white',
631
- focus: {
632
- bg: 'yellow',
633
- fg: 'black'
634
- },
635
- hover: {
636
- bg: 'yellow',
637
- fg: 'black'
638
- }
639
- }
640
- });
641
- submitButton.on('press', async () => {
642
- const id = idInput.getValue();
643
- if (!id) {
644
- showError('Entity ID is required');
645
- form.destroy();
646
- screen.render();
647
- return;
648
- }
649
- form.destroy();
650
- loading.load('Exploring graph...');
651
- screen.render();
652
- try {
653
- const result = await cli.explore(id, undefined, 3);
654
- loading.stop();
655
- showJSON(result);
656
- }
657
- catch (error) {
658
- loading.stop();
659
- showError(error.message);
660
- }
661
- });
662
- cancelButton.on('press', () => {
663
- form.destroy();
664
- screen.render();
665
- });
666
- form.key(['escape'], () => {
667
- form.destroy();
668
- screen.render();
669
- });
670
- idInput.focus();
671
- screen.render();
672
- }
673
- // Export Menu
674
- function showExportMenu() {
675
- const exportMenu = blessed_1.default.list({
676
- parent: screen,
677
- top: 'center',
678
- left: 'center',
679
- width: 50,
680
- height: 10,
681
- label: ' Export Format ',
682
- border: {
683
- type: 'line'
684
- },
685
- style: {
686
- border: {
687
- fg: 'green'
688
- },
689
- selected: {
690
- bg: 'blue',
691
- fg: 'white',
692
- bold: true
693
- }
694
- },
695
- keys: true,
696
- vi: true,
697
- mouse: true,
698
- items: [
699
- 'JSON',
700
- 'Markdown',
701
- 'Obsidian ZIP',
702
- 'Back'
703
- ]
704
- });
705
- exportMenu.on('select', async (item) => {
706
- const text = item.getText();
707
- exportMenu.destroy();
708
- screen.render();
709
- if (text === 'Back') {
710
- return;
711
- }
712
- const format = text === 'JSON' ? 'json' : text === 'Markdown' ? 'markdown' : 'obsidian';
713
- loading.load(`Exporting as ${text}...`);
714
- screen.render();
715
- try {
716
- const result = await cli.exportMemory(format, {
717
- includeMetadata: true,
718
- includeRelationships: true,
719
- includeObservations: true
720
- });
721
- loading.stop();
722
- showContent(`{green-fg}{bold}Export Complete!{/bold}{/green-fg}\n\n` +
723
- `Format: {cyan-fg}${format}{/cyan-fg}\n` +
724
- `Entities: {cyan-fg}${result.stats.entities}{/cyan-fg}\n` +
725
- `Observations: {cyan-fg}${result.stats.observations}{/cyan-fg}\n` +
726
- `Relationships: {cyan-fg}${result.stats.relationships}{/cyan-fg}\n\n` +
727
- `{yellow-fg}Use CLI to save to file:{/yellow-fg}\n` +
728
- `cozo-memory export ${format} -o output.${format === 'obsidian' ? 'zip' : format}`);
729
- }
730
- catch (error) {
731
- loading.stop();
732
- showError(error.message);
733
- }
734
- });
735
- exportMenu.key(['escape'], () => {
736
- exportMenu.destroy();
737
- screen.render();
738
- });
739
- exportMenu.focus();
740
- screen.render();
741
- }
742
- // Import (placeholder)
743
- function showImportInfo() {
744
- showContent(`{cyan-fg}{bold}Import Data{/bold}{/cyan-fg}\n\n` +
745
- `Use the CLI to import data:\n\n` +
746
- `{yellow-fg}cozo-memory import file -i data.json -f cozo{/yellow-fg}\n\n` +
747
- `Supported formats:\n` +
748
- `β€’ cozo - Native format\n` +
749
- `β€’ mem0 - Mem0 format\n` +
750
- `β€’ memgpt - MemGPT format\n` +
751
- `β€’ markdown - Markdown files`);
752
- }
753
- // Main menu handler
754
- mainMenu.on('select', async (item) => {
755
- const text = item.getText();
756
- if (text.includes('Exit')) {
757
- process.exit(0);
758
- }
759
- else if (text.includes('System Health')) {
760
- await showSystemHealth();
761
- }
762
- else if (text.includes('System Metrics')) {
763
- await showSystemMetrics();
764
- }
765
- else if (text.includes('Create Entity')) {
766
- showCreateEntityForm();
767
- }
768
- else if (text.includes('Search Memory')) {
769
- showSearchForm();
770
- }
771
- else if (text.includes('Graph Operations')) {
772
- showGraphMenu();
773
- }
774
- else if (text.includes('Export Data')) {
775
- showExportMenu();
776
- }
777
- else if (text.includes('Import Data')) {
778
- showImportInfo();
779
- }
780
- });
781
- // Keyboard shortcuts
782
- screen.key(['escape', 'q', 'C-c'], () => {
783
- process.exit(0);
784
- });
785
- // Focus main menu by default
786
- mainMenu.focus();
787
- // Initialize and render
788
- initCLI();
789
- screen.render();