sapper-iq 1.1.30 → 1.1.32

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 +37 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapper-iq",
3
- "version": "1.1.30",
3
+ "version": "1.1.32",
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
@@ -1061,7 +1061,10 @@ TOOL SYNTAX:
1061
1061
  spinner.stop();
1062
1062
 
1063
1063
  let msg = '';
1064
- const MAX_RESPONSE_LENGTH = 29000; // Guard against infinite loops (increased for multi-file reads)
1064
+ const MAX_RESPONSE_LENGTH = 100000; // 100KB - allow long code generation
1065
+ let lastChunkTime = Date.now();
1066
+ let repetitionCount = 0;
1067
+ let lastContent = '';
1065
1068
  abortStream = false; // Reset abort flag before streaming
1066
1069
 
1067
1070
  console.log(chalk.magenta('┌─[') + chalk.white.bold('Sapper') + chalk.magenta(']'));
@@ -1077,9 +1080,27 @@ TOOL SYNTAX:
1077
1080
  process.stdout.write(content);
1078
1081
  msg += content;
1079
1082
 
1083
+ // Smart loop detection: check for repetitive content patterns
1084
+ if (msg.length > 10000) {
1085
+ const recentContent = msg.slice(-500);
1086
+ const previousContent = msg.slice(-1000, -500);
1087
+
1088
+ // If last 500 chars are very similar to previous 500, might be looping
1089
+ if (recentContent === previousContent) {
1090
+ repetitionCount++;
1091
+ if (repetitionCount > 3) {
1092
+ console.log(chalk.red('\n\n⚠️ REPETITIVE OUTPUT DETECTED: Stopping to prevent loop.'));
1093
+ break;
1094
+ }
1095
+ } else {
1096
+ repetitionCount = 0;
1097
+ }
1098
+ }
1099
+
1100
+ // Hard limit as final safety net
1080
1101
  if (msg.length > MAX_RESPONSE_LENGTH) {
1081
- console.log(chalk.red('\n\n⚠️ RESPONSE TOO LONG: Forcing stop to prevent infinite loop.'));
1082
- break;
1102
+ console.log(chalk.yellow('\n\n⚠️ Response very long (100KB+). Continuing... (Ctrl+C to stop)'));
1103
+ // Don't break - just warn. User can Ctrl+C if needed
1083
1104
  }
1084
1105
  }
1085
1106
  console.log();
@@ -1101,6 +1122,19 @@ TOOL SYNTAX:
1101
1122
  // Regex: supports both old format (path]content) and new format (path:::content)
1102
1123
  const toolMatches = [...msg.matchAll(/\[TOOL:(\w+)\]([^:\]]*?)(?:(?:::|\])([\s\S]*?))?\[\/TOOL\]/g)];
1103
1124
 
1125
+ // Check for unclosed tool calls (AI started a tool but didn't close it)
1126
+ const hasUnclosedTool = msg.includes('[TOOL:') && !msg.includes('[/TOOL]');
1127
+ if (hasUnclosedTool) {
1128
+ console.log(chalk.yellow('\n⚠️ Unclosed tool detected! AI forgot [/TOOL] closing tag.'));
1129
+ console.log(chalk.gray(' Asking AI to complete the tool call...\n'));
1130
+
1131
+ messages.push({
1132
+ role: 'user',
1133
+ content: 'ERROR: Your tool call is incomplete - you forgot to add [/TOOL] at the end. Please complete the tool call by providing the closing [/TOOL] tag. If you were writing a file, just output [/TOOL] to close it.'
1134
+ });
1135
+ continue; // Let AI respond with the closing tag
1136
+ }
1137
+
1104
1138
  // Debug mode: show what regex sees
1105
1139
  if (debugMode) {
1106
1140
  console.log(chalk.magenta('\n═══ DEBUG: REGEX ANALYSIS ═══'));