roguelike-cli 1.0.0 → 1.1.0

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/dist/ai/claude.js CHANGED
@@ -106,6 +106,7 @@ async function generateSchemaWithAI(input, config, signal, history) {
106
106
  return {
107
107
  title: parsed.title || 'schema',
108
108
  content: schemaContent,
109
+ format: parsed.format || 'block',
109
110
  };
110
111
  }
111
112
  catch (error) {
@@ -41,6 +41,58 @@ const child_process_1 = require("child_process");
41
41
  const storage_1 = require("../storage/storage");
42
42
  const nodeConfig_1 = require("../storage/nodeConfig");
43
43
  const claude_1 = require("../ai/claude");
44
+ // Parse tree ASCII art and create folder structure
45
+ function createFoldersFromTree(rootPath, treeContent) {
46
+ // Create root folder
47
+ if (!fs.existsSync(rootPath)) {
48
+ fs.mkdirSync(rootPath, { recursive: true });
49
+ }
50
+ // Parse tree lines
51
+ const lines = treeContent.split('\n');
52
+ const stack = [{ path: rootPath, indent: -1 }];
53
+ for (const line of lines) {
54
+ // Skip empty lines
55
+ if (!line.trim())
56
+ continue;
57
+ // Extract node name from tree line
58
+ // Patterns: "├── Name", "└── Name", "│ ├── Name", etc.
59
+ const match = line.match(/^([\s│]*)[├└]──\s*(.+)$/);
60
+ if (!match)
61
+ continue;
62
+ const prefix = match[1];
63
+ let nodeName = match[2].trim();
64
+ // Calculate indent level (each │ or space block = 1 level)
65
+ const indent = Math.floor(prefix.replace(/│/g, ' ').length / 4);
66
+ // Clean node name - remove extra info in parentheses, brackets
67
+ nodeName = nodeName.replace(/\s*\([^)]*\)\s*/g, '').trim();
68
+ nodeName = nodeName.replace(/\s*\[[^\]]*\]\s*/g, '').trim();
69
+ // Create safe folder name
70
+ const safeName = nodeName
71
+ .toLowerCase()
72
+ .replace(/[^a-z0-9]+/g, '-')
73
+ .replace(/^-+|-+$/g, '');
74
+ if (!safeName)
75
+ continue;
76
+ // Pop stack until we find parent
77
+ while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
78
+ stack.pop();
79
+ }
80
+ const parentPath = stack[stack.length - 1].path;
81
+ const folderPath = path.join(parentPath, safeName);
82
+ // Create folder
83
+ if (!fs.existsSync(folderPath)) {
84
+ fs.mkdirSync(folderPath, { recursive: true });
85
+ }
86
+ // Create node config
87
+ (0, nodeConfig_1.writeNodeConfig)(folderPath, {
88
+ name: nodeName,
89
+ createdAt: new Date().toISOString(),
90
+ updatedAt: new Date().toISOString(),
91
+ });
92
+ // Push to stack
93
+ stack.push({ path: folderPath, indent });
94
+ }
95
+ }
44
96
  // Global session state
45
97
  exports.sessionState = {
46
98
  pending: null,
@@ -485,18 +537,31 @@ Examples:
485
537
  www.rlc.rocks`
486
538
  });
487
539
  }
488
- // Save command - save pending schema to .rlc.schema file
540
+ // Save command - save pending schema/todo
489
541
  if (command === 'save') {
490
542
  if (!exports.sessionState.pending) {
491
543
  return wrapResult({ output: 'Nothing to save. Create a schema first.' });
492
544
  }
493
- const schemaPath = (0, nodeConfig_1.saveSchemaFile)(currentPath, exports.sessionState.pending.title, exports.sessionState.pending.content);
494
- const relativePath = path.relative(config.storagePath, schemaPath);
495
- const filename = path.basename(schemaPath);
496
- // Clear session
497
- exports.sessionState.pending = null;
498
- exports.sessionState.history = [];
499
- return wrapResult({ output: `Saved: ${filename}` });
545
+ const pending = exports.sessionState.pending;
546
+ const safeName = pending.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
547
+ if (pending.format === 'tree') {
548
+ // Create folder structure from tree ASCII art
549
+ const rootPath = path.join(currentPath, safeName);
550
+ createFoldersFromTree(rootPath, pending.content);
551
+ // Clear session
552
+ exports.sessionState.pending = null;
553
+ exports.sessionState.history = [];
554
+ return wrapResult({ output: `Created todo folder: ${safeName}/` });
555
+ }
556
+ else {
557
+ // Save as .rlc.schema file
558
+ const schemaPath = (0, nodeConfig_1.saveSchemaFile)(currentPath, pending.title, pending.content);
559
+ const filename = path.basename(schemaPath);
560
+ // Clear session
561
+ exports.sessionState.pending = null;
562
+ exports.sessionState.history = [];
563
+ return wrapResult({ output: `Saved: ${filename}` });
564
+ }
500
565
  }
501
566
  // Cancel command - discard pending schema
502
567
  if (command === 'cancel') {
@@ -539,13 +604,17 @@ www.rlc.rocks`
539
604
  exports.sessionState.pending = {
540
605
  title: schema.title,
541
606
  content: schema.content,
607
+ format: schema.format,
542
608
  tree: schema.tree
543
609
  };
544
610
  // Add assistant response to history
545
611
  exports.sessionState.history.push({ role: 'assistant', content: schema.content });
546
- const filename = schema.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
612
+ const safeName = schema.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
613
+ const saveHint = schema.format === 'tree'
614
+ ? `[Type "save" to create folder ${safeName}/, or refine with more instructions]`
615
+ : `[Type "save" to save as ${safeName}.rlc.schema, or refine with more instructions]`;
547
616
  return wrapResult({
548
- output: `\n${schema.content}\n\n[Type "save" to save as ${filename}.rlc.schema, or refine with more instructions]`
617
+ output: `\n${schema.content}\n\n${saveHint}`
549
618
  });
550
619
  }
551
620
  return wrapResult({ output: 'Could not generate schema. Make sure API key is set.' });
@@ -17,7 +17,6 @@ const ASCII_ART = [
17
17
  '',
18
18
  '╔═════════════════════════╗',
19
19
  '║ Roguelike CLI v1.0 ║',
20
- '║ www.rlc.rocks ║',
21
20
  '╚═════════════════════════╝',
22
21
  '',
23
22
  ' Commands: ls, cd, mkdir, open, cp, mv, rm, tree, pwd, clean',
@@ -26,6 +25,8 @@ const ASCII_ART = [
26
25
  ' Workflow: <description> -> refine -> save',
27
26
  ' init - setup, config - settings, help - examples',
28
27
  '',
28
+ ' www.rlc.rocks',
29
+ '',
29
30
  ' Ready...',
30
31
  '',
31
32
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "roguelike-cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "AI-powered interactive terminal for creating schemas and todo lists",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/ai/claude.ts CHANGED
@@ -4,6 +4,7 @@ import { Config } from '../config/config';
4
4
  export interface GeneratedSchema {
5
5
  title: string;
6
6
  content: string;
7
+ format: 'block' | 'tree';
7
8
  tree?: any[];
8
9
  }
9
10
 
@@ -130,6 +131,7 @@ export async function generateSchemaWithAI(
130
131
  return {
131
132
  title: parsed.title || 'schema',
132
133
  content: schemaContent,
134
+ format: parsed.format || 'block',
133
135
  };
134
136
  } catch (error: any) {
135
137
  console.error('AI Error:', error.message);
@@ -3,9 +3,72 @@ import * as fs from 'fs';
3
3
  import { execSync } from 'child_process';
4
4
  import { Config } from '../config/config';
5
5
  import { listSchemas, navigateToNode, getTree } from '../storage/storage';
6
- import { saveSchemaFile } from '../storage/nodeConfig';
6
+ import { saveSchemaFile, writeNodeConfig } from '../storage/nodeConfig';
7
7
  import { generateSchemaWithAI } from '../ai/claude';
8
8
 
9
+ // Parse tree ASCII art and create folder structure
10
+ function createFoldersFromTree(rootPath: string, treeContent: string): void {
11
+ // Create root folder
12
+ if (!fs.existsSync(rootPath)) {
13
+ fs.mkdirSync(rootPath, { recursive: true });
14
+ }
15
+
16
+ // Parse tree lines
17
+ const lines = treeContent.split('\n');
18
+ const stack: { path: string; indent: number }[] = [{ path: rootPath, indent: -1 }];
19
+
20
+ for (const line of lines) {
21
+ // Skip empty lines
22
+ if (!line.trim()) continue;
23
+
24
+ // Extract node name from tree line
25
+ // Patterns: "├── Name", "└── Name", "│ ├── Name", etc.
26
+ const match = line.match(/^([\s│]*)[├└]──\s*(.+)$/);
27
+ if (!match) continue;
28
+
29
+ const prefix = match[1];
30
+ let nodeName = match[2].trim();
31
+
32
+ // Calculate indent level (each │ or space block = 1 level)
33
+ const indent = Math.floor(prefix.replace(/│/g, ' ').length / 4);
34
+
35
+ // Clean node name - remove extra info in parentheses, brackets
36
+ nodeName = nodeName.replace(/\s*\([^)]*\)\s*/g, '').trim();
37
+ nodeName = nodeName.replace(/\s*\[[^\]]*\]\s*/g, '').trim();
38
+
39
+ // Create safe folder name
40
+ const safeName = nodeName
41
+ .toLowerCase()
42
+ .replace(/[^a-z0-9]+/g, '-')
43
+ .replace(/^-+|-+$/g, '');
44
+
45
+ if (!safeName) continue;
46
+
47
+ // Pop stack until we find parent
48
+ while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
49
+ stack.pop();
50
+ }
51
+
52
+ const parentPath = stack[stack.length - 1].path;
53
+ const folderPath = path.join(parentPath, safeName);
54
+
55
+ // Create folder
56
+ if (!fs.existsSync(folderPath)) {
57
+ fs.mkdirSync(folderPath, { recursive: true });
58
+ }
59
+
60
+ // Create node config
61
+ writeNodeConfig(folderPath, {
62
+ name: nodeName,
63
+ createdAt: new Date().toISOString(),
64
+ updatedAt: new Date().toISOString(),
65
+ });
66
+
67
+ // Push to stack
68
+ stack.push({ path: folderPath, indent });
69
+ }
70
+ }
71
+
9
72
  export interface CommandResult {
10
73
  output?: string;
11
74
  newPath?: string;
@@ -16,6 +79,7 @@ export interface CommandResult {
16
79
  export interface PendingSchema {
17
80
  title: string;
18
81
  content: string;
82
+ format: 'block' | 'tree';
19
83
  tree?: any[];
20
84
  }
21
85
 
@@ -533,25 +597,40 @@ www.rlc.rocks`
533
597
  });
534
598
  }
535
599
 
536
- // Save command - save pending schema to .rlc.schema file
600
+ // Save command - save pending schema/todo
537
601
  if (command === 'save') {
538
602
  if (!sessionState.pending) {
539
603
  return wrapResult({ output: 'Nothing to save. Create a schema first.' });
540
604
  }
541
605
 
542
- const schemaPath = saveSchemaFile(
543
- currentPath,
544
- sessionState.pending.title,
545
- sessionState.pending.content
546
- );
547
- const relativePath = path.relative(config.storagePath, schemaPath);
548
- const filename = path.basename(schemaPath);
549
-
550
- // Clear session
551
- sessionState.pending = null;
552
- sessionState.history = [];
606
+ const pending = sessionState.pending;
607
+ const safeName = pending.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
553
608
 
554
- return wrapResult({ output: `Saved: ${filename}` });
609
+ if (pending.format === 'tree') {
610
+ // Create folder structure from tree ASCII art
611
+ const rootPath = path.join(currentPath, safeName);
612
+ createFoldersFromTree(rootPath, pending.content);
613
+
614
+ // Clear session
615
+ sessionState.pending = null;
616
+ sessionState.history = [];
617
+
618
+ return wrapResult({ output: `Created todo folder: ${safeName}/` });
619
+ } else {
620
+ // Save as .rlc.schema file
621
+ const schemaPath = saveSchemaFile(
622
+ currentPath,
623
+ pending.title,
624
+ pending.content
625
+ );
626
+ const filename = path.basename(schemaPath);
627
+
628
+ // Clear session
629
+ sessionState.pending = null;
630
+ sessionState.history = [];
631
+
632
+ return wrapResult({ output: `Saved: ${filename}` });
633
+ }
555
634
  }
556
635
 
557
636
  // Cancel command - discard pending schema
@@ -607,16 +686,21 @@ www.rlc.rocks`
607
686
  sessionState.pending = {
608
687
  title: schema.title,
609
688
  content: schema.content,
689
+ format: schema.format,
610
690
  tree: schema.tree
611
691
  };
612
692
 
613
693
  // Add assistant response to history
614
694
  sessionState.history.push({ role: 'assistant', content: schema.content });
615
695
 
616
- const filename = schema.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
696
+ const safeName = schema.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
697
+
698
+ const saveHint = schema.format === 'tree'
699
+ ? `[Type "save" to create folder ${safeName}/, or refine with more instructions]`
700
+ : `[Type "save" to save as ${safeName}.rlc.schema, or refine with more instructions]`;
617
701
 
618
702
  return wrapResult({
619
- output: `\n${schema.content}\n\n[Type "save" to save as ${filename}.rlc.schema, or refine with more instructions]`
703
+ output: `\n${schema.content}\n\n${saveHint}`
620
704
  });
621
705
  }
622
706
 
@@ -15,7 +15,6 @@ const ASCII_ART = [
15
15
  '',
16
16
  '╔═════════════════════════╗',
17
17
  '║ Roguelike CLI v1.0 ║',
18
- '║ www.rlc.rocks ║',
19
18
  '╚═════════════════════════╝',
20
19
  '',
21
20
  ' Commands: ls, cd, mkdir, open, cp, mv, rm, tree, pwd, clean',
@@ -24,6 +23,8 @@ const ASCII_ART = [
24
23
  ' Workflow: <description> -> refine -> save',
25
24
  ' init - setup, config - settings, help - examples',
26
25
  '',
26
+ ' www.rlc.rocks',
27
+ '',
27
28
  ' Ready...',
28
29
  '',
29
30
  ];