sapper-iq 1.0.21 → 1.0.23
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 +35 -13
package/package.json
CHANGED
package/sapper.mjs
CHANGED
|
@@ -166,8 +166,10 @@ WORKFLOW:
|
|
|
166
166
|
}];
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
const ask = () => {
|
|
170
|
-
|
|
169
|
+
const ask = async () => {
|
|
170
|
+
try {
|
|
171
|
+
const input = await safeQuestion(chalk.blue.bold('\nIbrahim ➔ '));
|
|
172
|
+
|
|
171
173
|
if (input.toLowerCase() === 'exit') process.exit();
|
|
172
174
|
|
|
173
175
|
// Handle reset command
|
|
@@ -180,17 +182,27 @@ WORKFLOW:
|
|
|
180
182
|
role: 'system',
|
|
181
183
|
content: messages[0].content // Keep system prompt
|
|
182
184
|
}];
|
|
183
|
-
return ask();
|
|
185
|
+
return await ask();
|
|
184
186
|
}
|
|
185
187
|
|
|
186
188
|
messages.push({ role: 'user', content: input });
|
|
187
189
|
|
|
190
|
+
let toolRounds = 0; // Prevent infinite loops
|
|
191
|
+
const MAX_TOOL_ROUNDS = 5;
|
|
192
|
+
|
|
188
193
|
let active = true;
|
|
189
194
|
while (active) {
|
|
190
195
|
if (stepMode) await safeQuestion(chalk.gray('[STEP] Press Enter to let AI think...'));
|
|
191
196
|
|
|
192
197
|
spinner.start('Thinking...');
|
|
193
|
-
|
|
198
|
+
let response;
|
|
199
|
+
try {
|
|
200
|
+
response = await ollama.chat({ model: selectedModel, messages, stream: true });
|
|
201
|
+
} catch (ollamaError) {
|
|
202
|
+
spinner.stop();
|
|
203
|
+
console.error(chalk.red('\n❌ Ollama error:'), ollamaError.message);
|
|
204
|
+
return await ask();
|
|
205
|
+
}
|
|
194
206
|
spinner.stop();
|
|
195
207
|
|
|
196
208
|
let msg = '';
|
|
@@ -203,10 +215,21 @@ WORKFLOW:
|
|
|
203
215
|
messages.push({ role: 'assistant', content: msg });
|
|
204
216
|
|
|
205
217
|
// Fixed regex: .+? (non-greedy) stops correctly before [/TOOL]
|
|
206
|
-
// Old regex [^\]\n]+ was broken - it stopped at ] which is at END of [/TOOL]
|
|
207
218
|
const toolMatches = [...msg.matchAll(/\[TOOL:(\w+)\](.+?)(?:\]([\s\S]*?))?\[\/TOOL\]/g)];
|
|
208
219
|
|
|
209
220
|
if (toolMatches.length > 0) {
|
|
221
|
+
toolRounds++;
|
|
222
|
+
|
|
223
|
+
// Prevent infinite tool loops
|
|
224
|
+
if (toolRounds >= MAX_TOOL_ROUNDS) {
|
|
225
|
+
console.log(chalk.yellow(`\n⚠️ Tool limit reached (${MAX_TOOL_ROUNDS} rounds). Stopping auto-execution.`));
|
|
226
|
+
messages.push({
|
|
227
|
+
role: 'user',
|
|
228
|
+
content: 'STOP using tools now. You have enough information. Please provide your analysis based on what you have read.'
|
|
229
|
+
});
|
|
230
|
+
continue; // Let AI respond without tools
|
|
231
|
+
}
|
|
232
|
+
|
|
210
233
|
for (const match of toolMatches) {
|
|
211
234
|
const [_, type, path, content] = match;
|
|
212
235
|
console.log(chalk.cyan(`\n[ACTION] ${type} -> ${path}`));
|
|
@@ -222,32 +245,31 @@ WORKFLOW:
|
|
|
222
245
|
}
|
|
223
246
|
fs.writeFileSync(CONTEXT_FILE, JSON.stringify(messages));
|
|
224
247
|
|
|
225
|
-
// Warn if reading many files at once
|
|
226
248
|
if (toolMatches.length > 30) {
|
|
227
249
|
console.log(chalk.yellow('\n⚠️ Reading 30+ files! This might take time.'));
|
|
228
250
|
}
|
|
229
251
|
} else {
|
|
230
252
|
// No tools found - check if malformed command
|
|
231
253
|
if (msg.includes('[TOOL:') && msg.includes('[/]')) {
|
|
232
|
-
console.log(chalk.red('\n❌ Malformed tool command detected!
|
|
254
|
+
console.log(chalk.red('\n❌ Malformed tool command detected!'));
|
|
233
255
|
messages.push({
|
|
234
256
|
role: 'user',
|
|
235
257
|
content: 'ERROR: Your tool command is malformed. Use [TOOL:TYPE]path]content[/TOOL] or [TOOL:TYPE]path[/TOOL]'
|
|
236
258
|
});
|
|
237
259
|
} else {
|
|
238
|
-
// Normal response
|
|
260
|
+
// Normal response - save and wait for next input
|
|
239
261
|
fs.writeFileSync(CONTEXT_FILE, JSON.stringify(messages));
|
|
240
262
|
active = false;
|
|
241
263
|
}
|
|
242
264
|
}
|
|
243
265
|
}
|
|
244
|
-
|
|
245
|
-
}).catch((error) => {
|
|
266
|
+
} catch (error) {
|
|
246
267
|
console.error(chalk.red('\n❌ Error:'), error.message);
|
|
247
|
-
|
|
248
|
-
|
|
268
|
+
}
|
|
269
|
+
// ALWAYS call ask() again with await - keep the conversation going
|
|
270
|
+
await ask();
|
|
249
271
|
};
|
|
250
|
-
ask();
|
|
272
|
+
await ask();
|
|
251
273
|
}
|
|
252
274
|
|
|
253
275
|
runSapper();
|