sapper-iq 1.0.24 → 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.
- package/package.json +1 -1
- package/sapper.mjs +51 -9
package/package.json
CHANGED
package/sapper.mjs
CHANGED
|
@@ -11,6 +11,14 @@ import { dirname, join } from 'path';
|
|
|
11
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
12
12
|
const __dirname = dirname(__filename);
|
|
13
13
|
|
|
14
|
+
// Prevent process from exiting on unhandled errors
|
|
15
|
+
process.on('uncaughtException', (err) => {
|
|
16
|
+
console.error(chalk.red('\n❌ Uncaught exception:'), err.message);
|
|
17
|
+
});
|
|
18
|
+
process.on('unhandledRejection', (reason) => {
|
|
19
|
+
console.error(chalk.red('\n❌ Unhandled rejection:'), reason);
|
|
20
|
+
});
|
|
21
|
+
|
|
14
22
|
// Initialize versioning
|
|
15
23
|
let CURRENT_VERSION = "1.1.0";
|
|
16
24
|
try {
|
|
@@ -30,9 +38,19 @@ let rl = readline.createInterface({
|
|
|
30
38
|
});
|
|
31
39
|
|
|
32
40
|
async function safeQuestion(query) {
|
|
33
|
-
return new Promise((resolve) => {
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
34
42
|
process.stdout.write(query);
|
|
35
43
|
rl.once('line', (answer) => { resolve(answer.trim()); });
|
|
44
|
+
rl.once('close', () => {
|
|
45
|
+
// Readline was closed - recreate it and try again
|
|
46
|
+
recreateReadline();
|
|
47
|
+
resolve(''); // Return empty string to continue the loop
|
|
48
|
+
});
|
|
49
|
+
rl.once('error', (err) => {
|
|
50
|
+
console.error(chalk.red('Readline error:'), err.message);
|
|
51
|
+
recreateReadline();
|
|
52
|
+
resolve('');
|
|
53
|
+
});
|
|
36
54
|
});
|
|
37
55
|
}
|
|
38
56
|
|
|
@@ -46,16 +64,30 @@ function recreateReadline() {
|
|
|
46
64
|
});
|
|
47
65
|
}
|
|
48
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
|
+
|
|
49
74
|
const tools = {
|
|
50
75
|
read: (path) => {
|
|
51
76
|
try { return fs.readFileSync(path.trim(), 'utf8'); }
|
|
52
77
|
catch (error) { return `Error reading file: ${error.message}`; }
|
|
53
78
|
},
|
|
54
|
-
write: (path, content) => {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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.";
|
|
59
91
|
},
|
|
60
92
|
mkdir: (path) => {
|
|
61
93
|
try {
|
|
@@ -82,8 +114,18 @@ const tools = {
|
|
|
82
114
|
return "Command blocked by user.";
|
|
83
115
|
},
|
|
84
116
|
list: (path) => {
|
|
85
|
-
try {
|
|
86
|
-
|
|
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}`; }
|
|
87
129
|
}
|
|
88
130
|
};
|
|
89
131
|
|
|
@@ -240,7 +282,7 @@ WORKFLOW:
|
|
|
240
282
|
if (type.toLowerCase() === 'list') result = tools.list(path);
|
|
241
283
|
else if (type.toLowerCase() === 'read') result = tools.read(path);
|
|
242
284
|
else if (type.toLowerCase() === 'mkdir') result = tools.mkdir(path);
|
|
243
|
-
else if (type.toLowerCase() === 'write') result = tools.write(path, content);
|
|
285
|
+
else if (type.toLowerCase() === 'write') result = await tools.write(path, content);
|
|
244
286
|
else if (type.toLowerCase() === 'shell') result = await tools.shell(path);
|
|
245
287
|
|
|
246
288
|
messages.push({ role: 'user', content: `RESULT (${path}): ${result}` });
|