@gullabs/xai 0.5.0 → 0.5.1

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/README.md CHANGED
@@ -169,7 +169,7 @@ xAI's own `/v1/models` listing surfaces `grok-4.5-latest` and `grok-build-latest
169
169
  - `serviceTier: 'priority'` → `service_tier: 'priority'` (`grok-4.6` only)
170
170
  - `output.jsonSchema` → `text.format: { type: 'json_schema', name, schema, strict: true }`
171
171
  - Usage: `usage.input_tokens` → `inputTokens`, `usage.output_tokens` → `outputTokens` (both already GROSS on xAI, unlike Gemini's sub-field summation); numeric extras (`num_sources_used`, `cost_in_usd_ticks`, etc.) surface into `usage.details` under their raw names, and the full raw payload is always in `usage.raw`
172
- - Errors: xAI's Responses API returns **HTTP 400 (not 401) for an invalid API key**. `classifyXaiError` special-cases the exact structured error-body signature (`code: 'invalid-argument'` with message prefix `"Incorrect API key provided"`, taken verbatim from a recorded live fixture) and reclassifies it as `invalid_auth`. It only inspects the STRUCTURED parsed error body — never free-form `Error.message` text — so a 400 that merely _mentions_ an API key (e.g. a schema-validation error echoing user content) stays `bad_request`. Any other 400, `429`→`rate_limited`, `5xx`→`server`, and timeouts fall through to `@gullabs/core`'s generic `classifyError`.
172
+ - Errors: HTTP status is a hint. `classifyXaiError` inspects the STRUCTURED parsed body only — never free-form `Error.message`. Two recorded overlays: HTTP **400** whose body starts with `"Incorrect API key provided"` (prefix only; the SDK may drop `code`) → `invalid_auth`; HTTP **403** whose body starts with `"Content violates usage guidelines"` (e.g. `SAFETY_CHECK_TYPE_*`) → `content_filter`. A bare 403 without that body stays `invalid_auth`. Any other 400, `429`→`rate_limited`, `5xx`→`server`, and timeouts fall through to `@gullabs/core`'s generic `classifyError`.
173
173
 
174
174
  ## Learn more
175
175
 
package/dist/index.cjs CHANGED
@@ -173,6 +173,11 @@ function isXaiAuthFailureBody(rawErr) {
173
173
  const text = extractXaiErrorBodyText(rawErr);
174
174
  return text !== void 0 && text.startsWith(XAI_AUTH_ERROR_MESSAGE_PREFIX);
175
175
  }
176
+ var XAI_SAFETY_CHECK_MESSAGE_PREFIX = "Content violates usage guidelines";
177
+ function isXaiSafetyCheckBody(rawErr) {
178
+ const text = extractXaiErrorBodyText(rawErr);
179
+ return text !== void 0 && text.startsWith(XAI_SAFETY_CHECK_MESSAGE_PREFIX);
180
+ }
176
181
  var XAI_TRANSPORT_ERROR_PATTERN = /connection error|econnreset|econnrefused|etimedout|eai_again|epipe|socket hang up|fetch failed/i;
177
182
  function matchesXaiTransportSignature(err) {
178
183
  if (!(err instanceof Error)) return false;
@@ -211,6 +216,16 @@ function classifyXaiError(rawErr) {
211
216
  cause: base.cause ?? rawErr
212
217
  });
213
218
  }
219
+ if (base.httpStatus === 403 && isXaiSafetyCheckBody(rawErr)) {
220
+ const bodyText = extractXaiErrorBodyText(rawErr);
221
+ return new core.LlmError(bodyText ?? base.message, {
222
+ kind: "content_filter",
223
+ retryable: false,
224
+ httpStatus: base.httpStatus,
225
+ provider: "xai",
226
+ cause: base.cause ?? rawErr
227
+ });
228
+ }
214
229
  if (base.kind === "unknown" && isXaiTransportError(rawErr)) {
215
230
  return new core.LlmError(base.message, {
216
231
  kind: "server",