sapper-iq 1.0.20 → 1.0.22

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 +20 -11
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sapper-iq",
3
- "version": "1.0.20",
3
+ "version": "1.0.22",
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
@@ -166,8 +166,10 @@ WORKFLOW:
166
166
  }];
167
167
  }
168
168
 
169
- const ask = () => {
170
- safeQuestion(chalk.blue.bold('\nIbrahim ➔ ')).then(async (input) => {
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
@@ -190,7 +192,14 @@ WORKFLOW:
190
192
  if (stepMode) await safeQuestion(chalk.gray('[STEP] Press Enter to let AI think...'));
191
193
 
192
194
  spinner.start('Thinking...');
193
- const response = await ollama.chat({ model: selectedModel, messages, stream: true });
195
+ let response;
196
+ try {
197
+ response = await ollama.chat({ model: selectedModel, messages, stream: true });
198
+ } catch (ollamaError) {
199
+ spinner.stop();
200
+ console.error(chalk.red('\n❌ Ollama error:'), ollamaError.message);
201
+ return ask();
202
+ }
194
203
  spinner.stop();
195
204
 
196
205
  let msg = '';
@@ -202,7 +211,8 @@ WORKFLOW:
202
211
  console.log();
203
212
  messages.push({ role: 'assistant', content: msg });
204
213
 
205
- const toolMatches = [...msg.matchAll(/\[TOOL:(\w+)\]([^\]\n]+)(?:\]([\s\S]*?))?\[\/TOOL\]/g)];
214
+ // Fixed regex: .+? (non-greedy) stops correctly before [/TOOL]
215
+ const toolMatches = [...msg.matchAll(/\[TOOL:(\w+)\](.+?)(?:\]([\s\S]*?))?\[\/TOOL\]/g)];
206
216
 
207
217
  if (toolMatches.length > 0) {
208
218
  for (const match of toolMatches) {
@@ -220,30 +230,29 @@ WORKFLOW:
220
230
  }
221
231
  fs.writeFileSync(CONTEXT_FILE, JSON.stringify(messages));
222
232
 
223
- // Warn if reading many files at once
224
233
  if (toolMatches.length > 30) {
225
234
  console.log(chalk.yellow('\n⚠️ Reading 30+ files! This might take time.'));
226
235
  }
227
236
  } else {
228
237
  // No tools found - check if malformed command
229
238
  if (msg.includes('[TOOL:') && msg.includes('[/]')) {
230
- console.log(chalk.red('\n❌ Malformed tool command detected! Expected format: [TOOL:TYPE]path[/TOOL]'));
239
+ console.log(chalk.red('\n❌ Malformed tool command detected!'));
231
240
  messages.push({
232
241
  role: 'user',
233
242
  content: 'ERROR: Your tool command is malformed. Use [TOOL:TYPE]path]content[/TOOL] or [TOOL:TYPE]path[/TOOL]'
234
243
  });
235
244
  } else {
236
- // Normal response without tools - save context and wait for next input
245
+ // Normal response - save and wait for next input
237
246
  fs.writeFileSync(CONTEXT_FILE, JSON.stringify(messages));
238
247
  active = false;
239
248
  }
240
249
  }
241
250
  }
242
- ask();
243
- }).catch((error) => {
251
+ } catch (error) {
244
252
  console.error(chalk.red('\n❌ Error:'), error.message);
245
- ask(); // Continue despite error
246
- });
253
+ }
254
+ // ALWAYS call ask() again - keep the conversation going
255
+ ask();
247
256
  };
248
257
  ask();
249
258
  }