@ai-sdk/openai-compatible 2.0.83 → 2.0.85

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/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @ai-sdk/openai-compatible
2
2
 
3
+ ## 2.0.85
4
+
5
+ ### Patch Changes
6
+
7
+ - 5aa3086: feat(openai-compatible): support URL-based image responses
8
+
9
+ Add opt-in URL validation and credential origin handling to `getFromApi` for URL-based image responses. Validate redirect targets, strip unsafe request headers, and drop credentials on cross-origin redirects while preserving existing unvalidated requests.
10
+
11
+ - Updated dependencies [5aa3086]
12
+ - @ai-sdk/provider-utils@4.0.61
13
+
14
+ ## 2.0.84
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [739e9f6]
19
+ - @ai-sdk/provider@3.0.19
20
+ - @ai-sdk/provider-utils@4.0.60
21
+
3
22
  ## 2.0.83
4
23
 
5
24
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -235,6 +235,7 @@ declare class OpenAICompatibleImageModel implements ImageModelV3 {
235
235
  constructor(modelId: OpenAICompatibleImageModelId, config: OpenAICompatibleImageModelConfig);
236
236
  private getArgs;
237
237
  doGenerate({ prompt, n, size, aspectRatio, seed, providerOptions, headers, abortSignal, files, mask, }: Parameters<ImageModelV3['doGenerate']>[0]): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>>;
238
+ private getImages;
238
239
  }
239
240
 
240
241
  interface OpenAICompatibleProvider<CHAT_MODEL_IDS extends string = string, COMPLETION_MODEL_IDS extends string = string, EMBEDDING_MODEL_IDS extends string = string, IMAGE_MODEL_IDS extends string = string> extends Omit<ProviderV3, 'imageModel'> {
package/dist/index.d.ts CHANGED
@@ -235,6 +235,7 @@ declare class OpenAICompatibleImageModel implements ImageModelV3 {
235
235
  constructor(modelId: OpenAICompatibleImageModelId, config: OpenAICompatibleImageModelConfig);
236
236
  private getArgs;
237
237
  doGenerate({ prompt, n, size, aspectRatio, seed, providerOptions, headers, abortSignal, files, mask, }: Parameters<ImageModelV3['doGenerate']>[0]): Promise<Awaited<ReturnType<ImageModelV3['doGenerate']>>>;
238
+ private getImages;
238
239
  }
239
240
 
240
241
  interface OpenAICompatibleProvider<CHAT_MODEL_IDS extends string = string, COMPLETION_MODEL_IDS extends string = string, EMBEDDING_MODEL_IDS extends string = string, IMAGE_MODEL_IDS extends string = string> extends Omit<ProviderV3, 'imageModel'> {
package/dist/index.js CHANGED
@@ -1573,6 +1573,7 @@ var openaiTextEmbeddingResponseSchema = import_v47.z.object({
1573
1573
  });
1574
1574
 
1575
1575
  // src/image/openai-compatible-image-model.ts
1576
+ var import_provider6 = require("@ai-sdk/provider");
1576
1577
  var import_provider_utils5 = require("@ai-sdk/provider-utils");
1577
1578
  var import_v48 = require("zod/v4");
1578
1579
  var OpenAICompatibleImageModel = class {
@@ -1624,13 +1625,16 @@ var OpenAICompatibleImageModel = class {
1624
1625
  }
1625
1626
  const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
1626
1627
  const args = this.getArgs(providerOptions);
1627
- if (files != null && files.length > 0) {
1628
+ const isEditing = files != null && files.length > 0;
1629
+ const url = this.config.url({
1630
+ path: isEditing ? "/images/edits" : "/images/generations",
1631
+ modelId: this.modelId
1632
+ });
1633
+ const requestHeaders = (0, import_provider_utils5.combineHeaders)(this.config.headers(), headers);
1634
+ if (isEditing) {
1628
1635
  const { value: response2, responseHeaders: responseHeaders2 } = await (0, import_provider_utils5.postFormDataToApi)({
1629
- url: this.config.url({
1630
- path: "/images/edits",
1631
- modelId: this.modelId
1632
- }),
1633
- headers: (0, import_provider_utils5.combineHeaders)(this.config.headers(), headers),
1636
+ url,
1637
+ headers: requestHeaders,
1634
1638
  formData: (0, import_provider_utils5.convertToFormData)({
1635
1639
  model: this.modelId,
1636
1640
  prompt,
@@ -1650,7 +1654,11 @@ var OpenAICompatibleImageModel = class {
1650
1654
  fetch: this.config.fetch
1651
1655
  });
1652
1656
  return {
1653
- images: response2.data.map((item) => item.b64_json),
1657
+ images: await this.getImages(response2.data, {
1658
+ url,
1659
+ headers: requestHeaders,
1660
+ abortSignal
1661
+ }),
1654
1662
  warnings,
1655
1663
  response: {
1656
1664
  timestamp: currentDate,
@@ -1660,11 +1668,8 @@ var OpenAICompatibleImageModel = class {
1660
1668
  };
1661
1669
  }
1662
1670
  const { value: response, responseHeaders } = await (0, import_provider_utils5.postJsonToApi)({
1663
- url: this.config.url({
1664
- path: "/images/generations",
1665
- modelId: this.modelId
1666
- }),
1667
- headers: (0, import_provider_utils5.combineHeaders)(this.config.headers(), headers),
1671
+ url,
1672
+ headers: requestHeaders,
1668
1673
  body: {
1669
1674
  model: this.modelId,
1670
1675
  prompt,
@@ -1683,7 +1688,11 @@ var OpenAICompatibleImageModel = class {
1683
1688
  fetch: this.config.fetch
1684
1689
  });
1685
1690
  return {
1686
- images: response.data.map((item) => item.b64_json),
1691
+ images: await this.getImages(response.data, {
1692
+ url,
1693
+ headers: requestHeaders,
1694
+ abortSignal
1695
+ }),
1687
1696
  warnings,
1688
1697
  response: {
1689
1698
  timestamp: currentDate,
@@ -1692,9 +1701,46 @@ var OpenAICompatibleImageModel = class {
1692
1701
  }
1693
1702
  };
1694
1703
  }
1704
+ async getImages(data, options) {
1705
+ if (data.every((image) => image.b64_json != null)) {
1706
+ return data.map((image) => image.b64_json);
1707
+ }
1708
+ return Promise.all(
1709
+ data.map(async (image) => {
1710
+ if (image.b64_json != null) {
1711
+ return (0, import_provider_utils5.convertBase64ToUint8Array)(image.b64_json);
1712
+ }
1713
+ if (image.url == null) {
1714
+ throw new import_provider6.InvalidResponseDataError({
1715
+ data: image,
1716
+ message: "Expected url in the image response"
1717
+ });
1718
+ }
1719
+ const { value } = await (0, import_provider_utils5.getFromApi)({
1720
+ url: image.url,
1721
+ validateUrl: true,
1722
+ trustedOrigin: options.url,
1723
+ credentialedOrigin: options.url,
1724
+ headers: options.headers,
1725
+ abortSignal: options.abortSignal,
1726
+ fetch: this.config.fetch,
1727
+ successfulResponseHandler: (0, import_provider_utils5.createBinaryResponseHandler)(),
1728
+ failedResponseHandler: (0, import_provider_utils5.createStatusCodeErrorResponseHandler)()
1729
+ });
1730
+ return value;
1731
+ })
1732
+ );
1733
+ }
1695
1734
  };
1696
1735
  var openaiCompatibleImageResponseSchema = import_v48.z.object({
1697
- data: import_v48.z.array(import_v48.z.object({ b64_json: import_v48.z.string() }))
1736
+ data: import_v48.z.array(
1737
+ import_v48.z.object({
1738
+ b64_json: import_v48.z.string().nullish(),
1739
+ url: import_v48.z.string().nullish()
1740
+ }).refine((image) => image.b64_json != null || image.url != null, {
1741
+ message: "Expected b64_json or url in the image response"
1742
+ })
1743
+ )
1698
1744
  });
1699
1745
  async function fileToBlob(file) {
1700
1746
  if (file.type === "url") {
@@ -1708,7 +1754,7 @@ async function fileToBlob(file) {
1708
1754
  var import_provider_utils6 = require("@ai-sdk/provider-utils");
1709
1755
 
1710
1756
  // src/version.ts
1711
- var VERSION = true ? "2.0.83" : "0.0.0-test";
1757
+ var VERSION = true ? "2.0.85" : "0.0.0-test";
1712
1758
 
1713
1759
  // src/openai-compatible-provider.ts
1714
1760
  function createOpenAICompatible(options) {