@ducci/jarvis 1.0.40 → 1.0.42

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ducci/jarvis",
3
- "version": "1.0.40",
3
+ "version": "1.0.42",
4
4
  "description": "A fully automated agent system that lives on a server.",
5
5
  "main": "./src/index.js",
6
6
  "type": "module",
@@ -50,6 +50,12 @@ async function callModel(client, model, messages, tools) {
50
50
  return await client.chat.completions.create(params);
51
51
  }
52
52
 
53
+ function isImageUnsupportedError(apiErrors) {
54
+ if (!apiErrors) return false;
55
+ return [apiErrors.primary?.message, apiErrors.fallback?.message]
56
+ .some(m => m?.toLowerCase().includes('image input'));
57
+ }
58
+
53
59
  function extractApiError(err, model) {
54
60
  return {
55
61
  model,
@@ -640,6 +646,22 @@ async function _runHandleChat(config, sessionId, userMessage, attachments = [])
640
646
  // windows). The synthetic note is sufficient context; tool results are preserved
641
647
  // in the JSONL log and accessible via read_session_log.
642
648
  if (finalStatus === 'model_error' || finalStatus === 'format_error') {
649
+ if (finalStatus === 'model_error' && isImageUnsupportedError(run.errorDetail)) {
650
+ finalResponse = 'This model does not support image input. Please switch to a multimodal model (e.g. claude-3.5-sonnet, gpt-4o) in settings.';
651
+ // Strip the image from the user message that caused the failure so it
652
+ // does not permanently break the session on every subsequent call.
653
+ // Replace with a text placeholder so the model knows a image was present.
654
+ for (let i = session.messages.length - 1; i >= 0; i--) {
655
+ const msg = session.messages[i];
656
+ if (msg.role === 'user' && Array.isArray(msg.content)) {
657
+ const textPart = msg.content.find(c => c.type === 'text')?.text || '';
658
+ msg.content = textPart
659
+ ? `${textPart}\n[image removed — model does not support image input]`
660
+ : '[image removed — model does not support image input]';
661
+ break;
662
+ }
663
+ }
664
+ }
643
665
  session.messages.splice(runStartIndex, session.messages.length - runStartIndex);
644
666
  const errorDetail = run.errorDetail ? ` Error detail: ${JSON.stringify(run.errorDetail)}` : '';
645
667
  session.messages.push({