call-ai 0.7.0-dev-preview-10 → 0.7.0-dev-preview-12

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/dist/api.js +73 -53
  2. package/package.json +1 -1
package/dist/api.js CHANGED
@@ -63,64 +63,84 @@ function callAI(prompt, options = {}) {
63
63
  // Explicitly check for HTTP error status and log extensively
64
64
  console.log(`[callAI:${PACKAGE_VERSION}] Response.ok =`, response.ok);
65
65
  console.log(`[callAI:${PACKAGE_VERSION}] Response.status =`, response.status);
66
+ console.log(`[callAI:${PACKAGE_VERSION}] Response.statusText =`, response.statusText);
66
67
  console.log(`[callAI:${PACKAGE_VERSION}] Response.type =`, response.type);
67
- // Enhanced error handling with more debugging - MUST check !response.ok
68
- if (!response.ok) {
69
- console.log(`[callAI:${PACKAGE_VERSION}] Detected error response with status:`, response.status);
70
- if (options.debug) {
71
- console.error(`[callAI:${PACKAGE_VERSION}] HTTP Error:`, response.status, response.statusText, response.url);
72
- }
73
- // Check if this is an invalid model error
74
- console.log(`[callAI:${PACKAGE_VERSION}] Checking for invalid model error...`);
75
- let isInvalidModel = false;
76
- let errorData = null;
77
- try {
78
- const result = await checkForInvalidModelError(response.clone(), // Clone response since we'll need to read body twice
79
- model, false, options.skipRetry);
80
- isInvalidModel = result.isInvalidModel;
81
- errorData = result.errorData;
82
- console.log(`[callAI:${PACKAGE_VERSION}] Invalid model check result:`, isInvalidModel);
83
- }
84
- catch (checkError) {
85
- console.error(`[callAI:${PACKAGE_VERSION}] Error during invalid model check:`, checkError);
86
- }
87
- if (isInvalidModel && !options.skipRetry) {
88
- if (options.debug) {
89
- console.log(`[callAI:${PACKAGE_VERSION}] Retrying with fallback model: ${FALLBACK_MODEL}`);
68
+ // Double check for content-type to see if there's a mismatch in error response handling
69
+ const contentType = response.headers.get('content-type') || '';
70
+ console.log(`[callAI:${PACKAGE_VERSION}] Content-Type =`, contentType);
71
+ // Browser-compatible error handling - must check BOTH status code AND content-type
72
+ // Some browsers will report status 200 for SSE streams even when server returns 400
73
+ const hasHttpError = !response.ok || response.status >= 400;
74
+ const hasJsonError = contentType.includes('application/json');
75
+ if (hasHttpError || hasJsonError) {
76
+ console.log(`[callAI:${PACKAGE_VERSION}] ⚠️ Error detected - HTTP Status: ${response.status}, Content-Type: ${contentType}`);
77
+ // Handle the error with fallback model if appropriate
78
+ if (!options.skipRetry) {
79
+ const clonedResponse = response.clone();
80
+ let isInvalidModel = false;
81
+ try {
82
+ // Check if this is an invalid model error
83
+ const modelCheckResult = await checkForInvalidModelError(clonedResponse, model, false, options.skipRetry);
84
+ isInvalidModel = modelCheckResult.isInvalidModel;
85
+ if (isInvalidModel) {
86
+ if (options.debug) {
87
+ console.log(`[callAI:${PACKAGE_VERSION}] Retrying with fallback model: ${FALLBACK_MODEL}`);
88
+ }
89
+ // Retry with fallback model
90
+ return await callAI(prompt, { ...options, model: FALLBACK_MODEL });
91
+ }
92
+ }
93
+ catch (modelCheckError) {
94
+ console.error(`[callAI:${PACKAGE_VERSION}] Error during model check:`, modelCheckError);
95
+ // Continue with normal error handling
90
96
  }
91
- // Retry with fallback model - it will return a promise
92
- const result = await callAI(prompt, { ...options, model: FALLBACK_MODEL });
93
- return result;
94
97
  }
95
- // Get full error text from body
96
- console.log(`[callAI:${PACKAGE_VERSION}] Reading error response body...`);
97
- let errorText = "";
98
+ // Extract error details from response
98
99
  try {
99
- errorText = await response.text();
100
- console.log(`[callAI:${PACKAGE_VERSION}] Error response body:`, errorText);
100
+ // Try to get error details from the response body
101
+ const errorBody = await response.text();
102
+ console.log(`[callAI:${PACKAGE_VERSION}] Error body:`, errorBody);
103
+ try {
104
+ // Try to parse JSON error
105
+ const errorJson = JSON.parse(errorBody);
106
+ console.log(`[callAI:${PACKAGE_VERSION}] Parsed error:`, errorJson);
107
+ // Extract message from OpenRouter error format
108
+ const errorMessage = ((errorJson.error && typeof errorJson.error === 'object') ?
109
+ errorJson.error.message :
110
+ errorJson.error || errorJson.message ||
111
+ `API returned ${response.status}: ${response.statusText}`);
112
+ // Create error with standard format
113
+ const error = new Error(errorMessage);
114
+ // Add useful metadata
115
+ error.status = response.status;
116
+ error.statusText = response.statusText;
117
+ error.details = errorJson;
118
+ error.contentType = contentType;
119
+ throw error;
120
+ }
121
+ catch (jsonError) {
122
+ // If JSON parsing fails, throw a simpler error
123
+ console.log(`[callAI:${PACKAGE_VERSION}] JSON parse error:`, jsonError);
124
+ const error = new Error(`API error: ${response.status} ${response.statusText}`);
125
+ error.status = response.status;
126
+ error.statusText = response.statusText;
127
+ error.details = errorBody;
128
+ error.contentType = contentType;
129
+ throw error;
130
+ }
101
131
  }
102
- catch (error) {
103
- const textError = error;
104
- console.error(`[callAI:${PACKAGE_VERSION}] Error reading response body:`, textError);
105
- errorText = `Failed to read error details: ${textError.message || 'Unknown error'}`;
132
+ catch (responseError) {
133
+ if (responseError instanceof Error) {
134
+ // Re-throw if it's already properly formatted
135
+ throw responseError;
136
+ }
137
+ // Fallback error
138
+ const error = new Error(`API returned ${response.status}: ${response.statusText}`);
139
+ error.status = response.status;
140
+ error.statusText = response.statusText;
141
+ error.contentType = contentType;
142
+ throw error;
106
143
  }
107
- // Create a detailed error with status information
108
- console.log(`[callAI:${PACKAGE_VERSION}] Creating error object with status ${response.status}`);
109
- const errorMessage = `API returned error ${response.status}: ${response.statusText}`;
110
- const error = new Error(errorMessage);
111
- // Add extra properties for more context
112
- error.status = response.status;
113
- error.statusText = response.statusText;
114
- error.details = errorText;
115
- // Ensure this error is thrown and caught properly in the Promise chain
116
- console.error(`[callAI:${PACKAGE_VERSION}] THROWING API ERROR:`, {
117
- message: errorMessage,
118
- status: response.status,
119
- statusText: response.statusText,
120
- details: errorText
121
- });
122
- // This MUST throw the error from the promise
123
- return Promise.reject(error);
124
144
  }
125
145
  // Only if response is OK, create and return the streaming generator
126
146
  console.log(`[callAI:${PACKAGE_VERSION}] Response OK, creating streaming generator`);
@@ -362,7 +382,7 @@ async function callAINonStreaming(prompt, options = {}, isRetry = false) {
362
382
  const { endpoint, requestOptions, model, schemaStrategy } = prepareRequestParams(prompt, options);
363
383
  const response = await fetch(endpoint, requestOptions);
364
384
  // Handle HTTP errors, with potential fallback for invalid model
365
- if (!response.ok) {
385
+ if (!response.ok || response.status >= 400) {
366
386
  const { isInvalidModel } = await checkForInvalidModelError(response, model, isRetry, options.skipRetry);
367
387
  if (isInvalidModel) {
368
388
  // Retry with fallback model
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "call-ai",
3
- "version": "0.7.0-dev-preview-10",
3
+ "version": "0.7.0-dev-preview-12",
4
4
  "description": "Lightweight library for making AI API calls with streaming support",
5
5
  "main": "dist/index.js",
6
6
  "browser": "dist/index.js",