@acmecloud/core 1.0.9 → 1.0.11

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.
@@ -280,30 +280,39 @@ export async function* runAgent(provider, modelName, messages, systemPrompt, abo
280
280
  yield { type: "messages", messages: currentMessages };
281
281
  return [];
282
282
  }
283
- else {
283
+ // Check if this is a content safety error (should not retry)
284
+ const errorMessage = err.message?.toLowerCase() || "";
285
+ const isContentSafetyError = errorMessage.includes("sensitive_words_detected") ||
286
+ errorMessage.includes("content_policy") ||
287
+ errorMessage.includes("safety") ||
288
+ errorMessage.includes("content_filter");
289
+ if (isContentSafetyError) {
290
+ // Content safety errors should not be retried - they won't succeed by retrying
284
291
  yield {
285
292
  type: "text",
286
- text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
293
+ text: `\n[Content Safety Error: ${err.message}]\n\nThis request triggered the content safety filter. Please modify your request to avoid sensitive topics and try again.\n`,
287
294
  };
288
- if (stepText.trim()) {
289
- currentMessages.push({ role: "assistant", content: stepText });
290
- }
291
- consecutiveErrors++;
292
- if (consecutiveErrors >= 3) {
293
- yield {
294
- type: "text",
295
- text: `\n[Fatal Error: Stream dropped ${consecutiveErrors} times consecutively. Halting agent to prevent infinite loops.]\n`,
296
- };
297
- yield { type: "messages", messages: currentMessages };
298
- return [];
299
- }
300
- currentMessages.push({
301
- role: "user",
302
- content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
303
- });
304
- await new Promise((resolve) => setTimeout(resolve, 2000));
305
- continue;
295
+ yield { type: "messages", messages: currentMessages };
296
+ return [];
306
297
  }
298
+ // For all other errors (network issues, timeout, server errors), auto-recover indefinitely
299
+ yield {
300
+ type: "text",
301
+ text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
302
+ };
303
+ if (stepText.trim()) {
304
+ currentMessages.push({ role: "assistant", content: stepText });
305
+ }
306
+ consecutiveErrors++;
307
+ // Add system message to prompt the model to continue
308
+ currentMessages.push({
309
+ role: "user",
310
+ content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
311
+ });
312
+ // Exponential backoff: 2s, 4s, 8s, max 30s
313
+ const delay = Math.min(2000 * Math.pow(2, Math.min(consecutiveErrors - 1, 3)), 30000);
314
+ await new Promise((resolve) => setTimeout(resolve, delay));
315
+ continue;
307
316
  }
308
317
  if (collectedToolCalls.length === 0) {
309
318
  const parseText = stepText
@@ -412,6 +421,7 @@ export async function* runAgent(provider, modelName, messages, systemPrompt, abo
412
421
  }
413
422
  if (collectedToolCalls.length === 0) {
414
423
  if (!stepText.trim()) {
424
+ // Empty response - retry a few times
415
425
  consecutiveErrors++;
416
426
  if (consecutiveErrors < 3) {
417
427
  yield {
@@ -435,9 +445,17 @@ export async function* runAgent(provider, modelName, messages, systemPrompt, abo
435
445
  return [];
436
446
  }
437
447
  }
448
+ // Model returned text but no tool calls
449
+ // This is normal - the model might be providing explanation or asking for clarification
450
+ // Add the response to history and continue the loop to let model continue working
438
451
  currentMessages.push({ role: "assistant", content: stepText });
439
- yield { type: "messages", messages: currentMessages };
440
- return [];
452
+ // Add a system prompt to encourage the model to continue if task is not complete
453
+ currentMessages.push({
454
+ role: "user",
455
+ content: `[System] You provided some output but did not complete the task. Please continue working on the task or explain what you need from the user. If you need to use tools, please do so now.`,
456
+ });
457
+ // Continue the loop instead of returning
458
+ continue;
441
459
  }
442
460
  yield { type: "text", text: "\n" };
443
461
  const toolSummary = collectedToolResults
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acmecloud/core",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "exports": {
@@ -362,34 +362,51 @@ export async function* runAgent(
362
362
  yield { type: "text", text: "\n[Aborted by user]\n" };
363
363
  yield { type: "messages", messages: currentMessages };
364
364
  return [];
365
- } else {
365
+ }
366
+
367
+ // Check if this is a content safety error (should not retry)
368
+ const errorMessage = err.message?.toLowerCase() || "";
369
+ const isContentSafetyError =
370
+ errorMessage.includes("sensitive_words_detected") ||
371
+ errorMessage.includes("content_policy") ||
372
+ errorMessage.includes("safety") ||
373
+ errorMessage.includes("content_filter");
374
+
375
+ if (isContentSafetyError) {
376
+ // Content safety errors should not be retried - they won't succeed by retrying
366
377
  yield {
367
378
  type: "text",
368
- text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
379
+ text: `\n[Content Safety Error: ${err.message}]\n\nThis request triggered the content safety filter. Please modify your request to avoid sensitive topics and try again.\n`,
369
380
  };
381
+ yield { type: "messages", messages: currentMessages };
382
+ return [];
383
+ }
370
384
 
371
- if (stepText.trim()) {
372
- currentMessages.push({ role: "assistant", content: stepText });
373
- }
385
+ // For all other errors (network issues, timeout, server errors), auto-recover indefinitely
386
+ yield {
387
+ type: "text",
388
+ text: `\n[Error: ${err.message}]\n[Auto-recovering from stream drop...]\n`,
389
+ };
374
390
 
375
- consecutiveErrors++;
376
- if (consecutiveErrors >= 3) {
377
- yield {
378
- type: "text",
379
- text: `\n[Fatal Error: Stream dropped ${consecutiveErrors} times consecutively. Halting agent to prevent infinite loops.]\n`,
380
- };
381
- yield { type: "messages", messages: currentMessages };
382
- return [];
383
- }
391
+ if (stepText.trim()) {
392
+ currentMessages.push({ role: "assistant", content: stepText });
393
+ }
384
394
 
385
- currentMessages.push({
386
- role: "user",
387
- content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
388
- });
395
+ consecutiveErrors++;
389
396
 
390
- await new Promise((resolve) => setTimeout(resolve, 2000));
391
- continue;
392
- }
397
+ // Add system message to prompt the model to continue
398
+ currentMessages.push({
399
+ role: "user",
400
+ content: `[System Error: The network stream disconnected prematurely with error: ${err.message || err}. Please carefully analyze the incomplete text you just generated, and continue your thought or tool execution precisely from where it was cut off without repeating yourself.]`,
401
+ });
402
+
403
+ // Exponential backoff: 2s, 4s, 8s, max 30s
404
+ const delay = Math.min(
405
+ 2000 * Math.pow(2, Math.min(consecutiveErrors - 1, 3)),
406
+ 30000,
407
+ );
408
+ await new Promise((resolve) => setTimeout(resolve, delay));
409
+ continue;
393
410
  }
394
411
 
395
412
  if (collectedToolCalls.length === 0) {
@@ -511,6 +528,7 @@ export async function* runAgent(
511
528
 
512
529
  if (collectedToolCalls.length === 0) {
513
530
  if (!stepText.trim()) {
531
+ // Empty response - retry a few times
514
532
  consecutiveErrors++;
515
533
  if (consecutiveErrors < 3) {
516
534
  yield {
@@ -534,9 +552,19 @@ export async function* runAgent(
534
552
  }
535
553
  }
536
554
 
555
+ // Model returned text but no tool calls
556
+ // This is normal - the model might be providing explanation or asking for clarification
557
+ // Add the response to history and continue the loop to let model continue working
537
558
  currentMessages.push({ role: "assistant", content: stepText });
538
- yield { type: "messages", messages: currentMessages };
539
- return [];
559
+
560
+ // Add a system prompt to encourage the model to continue if task is not complete
561
+ currentMessages.push({
562
+ role: "user",
563
+ content: `[System] You provided some output but did not complete the task. Please continue working on the task or explain what you need from the user. If you need to use tools, please do so now.`,
564
+ });
565
+
566
+ // Continue the loop instead of returning
567
+ continue;
540
568
  }
541
569
 
542
570
  yield { type: "text", text: "\n" };