sapper-iq 1.0.25 → 1.0.26

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 (2) hide show
  1. package/package.json +1 -1
  2. package/sapper.mjs +32 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapper-iq",
3
- "version": "1.0.25",
3
+ "version": "1.0.26",
4
4
  "description": "AI-powered development assistant that executes commands and builds projects",
5
5
  "main": "sapper.mjs",
6
6
  "bin": {
package/sapper.mjs CHANGED
@@ -64,16 +64,30 @@ function recreateReadline() {
64
64
  });
65
65
  }
66
66
 
67
+ // Directories to ignore when listing files
68
+ const IGNORE_DIRS = new Set([
69
+ 'node_modules', '.git', '.svn', '.hg', 'dist', 'build',
70
+ '.next', '.nuxt', '__pycache__', '.cache', 'coverage',
71
+ '.idea', '.vscode', 'vendor', 'target', '.gradle'
72
+ ]);
73
+
67
74
  const tools = {
68
75
  read: (path) => {
69
76
  try { return fs.readFileSync(path.trim(), 'utf8'); }
70
77
  catch (error) { return `Error reading file: ${error.message}`; }
71
78
  },
72
- write: (path, content) => {
73
- try {
74
- fs.writeFileSync(path.trim(), content);
75
- return `Successfully saved changes to ${path}`;
76
- } catch (error) { return `Error writing file: ${error.message}`; }
79
+ write: async (path, content) => {
80
+ const trimmedPath = path.trim();
81
+ console.log(chalk.yellow.bold(`\n[WRITE] Sapper wants to write to: `) + chalk.white(trimmedPath));
82
+ console.log(chalk.gray(`Content preview (first 200 chars):\n${content?.substring(0, 200)}${content?.length > 200 ? '...' : ''}`));
83
+ const confirm = await safeQuestion(chalk.yellow('Allow write? (y/n): '));
84
+ if (confirm.toLowerCase() === 'y') {
85
+ try {
86
+ fs.writeFileSync(trimmedPath, content);
87
+ return `Successfully saved changes to ${trimmedPath}`;
88
+ } catch (error) { return `Error writing file: ${error.message}`; }
89
+ }
90
+ return "Write blocked by user.";
77
91
  },
78
92
  mkdir: (path) => {
79
93
  try {
@@ -100,8 +114,18 @@ const tools = {
100
114
  return "Command blocked by user.";
101
115
  },
102
116
  list: (path) => {
103
- try { return fs.readdirSync(path.trim() || '.').join('\n'); }
104
- catch (e) { return `Error: ${e.message}`; }
117
+ try {
118
+ const dir = path.trim() || '.';
119
+ const entries = fs.readdirSync(dir);
120
+ // Filter out ignored directories
121
+ const filtered = entries.filter(entry => {
122
+ if (IGNORE_DIRS.has(entry)) return false;
123
+ // Also skip hidden files/folders (starting with .) except current dir
124
+ if (entry.startsWith('.') && entry !== '.') return false;
125
+ return true;
126
+ });
127
+ return filtered.length > 0 ? filtered.join('\n') : '(empty or all files filtered)';
128
+ } catch (e) { return `Error: ${e.message}`; }
105
129
  }
106
130
  };
107
131
 
@@ -258,7 +282,7 @@ WORKFLOW:
258
282
  if (type.toLowerCase() === 'list') result = tools.list(path);
259
283
  else if (type.toLowerCase() === 'read') result = tools.read(path);
260
284
  else if (type.toLowerCase() === 'mkdir') result = tools.mkdir(path);
261
- else if (type.toLowerCase() === 'write') result = tools.write(path, content);
285
+ else if (type.toLowerCase() === 'write') result = await tools.write(path, content);
262
286
  else if (type.toLowerCase() === 'shell') result = await tools.shell(path);
263
287
 
264
288
  messages.push({ role: 'user', content: `RESULT (${path}): ${result}` });