sapper-iq 1.1.2 → 1.1.4

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 +31 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapper-iq",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
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
@@ -31,6 +31,19 @@ process.on('SIGINT', () => {
31
31
  setTimeout(() => { ctrlCCount = 0; }, 2000); // Reset after 2 seconds
32
32
  });
33
33
 
34
+ // Reset terminal state - fixes "ghost input" after shell commands or AI streaming
35
+ function resetTerminal() {
36
+ if (process.stdin.isTTY) {
37
+ try {
38
+ process.stdin.setRawMode(false); // Disable raw mode
39
+ process.stdin.pause(); // Pause the stream
40
+ process.stdin.resume(); // Resume to clear buffers
41
+ } catch (e) {
42
+ // Ignore errors if terminal is in weird state
43
+ }
44
+ }
45
+ }
46
+
34
47
  // Initialize versioning
35
48
  let CURRENT_VERSION = "1.1.0";
36
49
  try {
@@ -62,7 +75,7 @@ function recreateReadline() {
62
75
  }
63
76
 
64
77
  async function safeQuestion(query) {
65
- // Ensure we are ready to receive input
78
+ resetTerminal(); // Clear terminal state before asking
66
79
  if (rl.closed) recreateReadline();
67
80
 
68
81
  return new Promise((resolve) => {
@@ -136,11 +149,15 @@ const tools = {
136
149
  stdio: 'inherit', shell: useShell
137
150
  });
138
151
  proc.on('close', (code) => {
152
+ // Crucial: give control back to Node
153
+ if (process.stdin.isTTY) {
154
+ try { process.stdin.setRawMode(false); } catch (e) {}
155
+ }
139
156
  // Delay slightly to let terminal settle
140
157
  setTimeout(() => {
141
158
  recreateReadline();
142
159
  resolve(`Command completed with code ${code}`);
143
- }, 100);
160
+ }, 200);
144
161
  });
145
162
  });
146
163
  }
@@ -284,6 +301,13 @@ WORKFLOW:
284
301
  // Main conversation loop - never exits unless user types 'exit'
285
302
  while (true) {
286
303
  try {
304
+ // Context size warning - large context causes hangs
305
+ const contextSize = JSON.stringify(messages).length;
306
+ if (contextSize > 32000) {
307
+ console.log(chalk.red.bold('\n⚠️ WARNING: Context is very large (~' + Math.round(contextSize/1024) + 'KB). Sapper might hang.'));
308
+ console.log(chalk.yellow('👉 Suggestion: Type /prune to keep only the latest analysis.'));
309
+ }
310
+
287
311
  const input = await safeQuestion(chalk.blue.bold('\nIbrahim ➔ '));
288
312
 
289
313
  if (input.toLowerCase() === 'exit') process.exit();
@@ -382,6 +406,8 @@ WORKFLOW:
382
406
  // Prevent infinite tool loops
383
407
  if (toolRounds >= MAX_TOOL_ROUNDS) {
384
408
  console.log(chalk.yellow(`\n⚠️ Tool limit reached (${MAX_TOOL_ROUNDS} rounds). Stopping auto-execution.`));
409
+ console.log(chalk.gray('💡 Tip: Type /prune after analysis to reduce context size.'));
410
+ resetTerminal(); // Ensure terminal is responsive
385
411
  messages.push({
386
412
  role: 'user',
387
413
  content: 'STOP using tools now. You have enough information. Please provide your analysis based on what you have read.'
@@ -429,6 +455,9 @@ WORKFLOW:
429
455
  // Normal response - save and wait for next input
430
456
  fs.writeFileSync(CONTEXT_FILE, JSON.stringify(messages));
431
457
  active = false;
458
+ spinner.stop(); // Ensure spinner is dead
459
+ resetTerminal(); // Force terminal back to normal state
460
+ process.stdout.write('\n'); // Force newline to break out of stream mode
432
461
  }
433
462
  }
434
463
  }