@ai-sdk/openai-compatible 2.0.84 → 2.0.86
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 +17 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +62 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +67 -16
- package/dist/index.mjs.map +1 -1
- package/docs/index.mdx +5 -0
- package/package.json +2 -2
- package/src/chat/openai-compatible-chat-language-model.ts +2 -2
- package/src/image/openai-compatible-image-model.ts +82 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @ai-sdk/openai-compatible
|
|
2
2
|
|
|
3
|
+
## 2.0.86
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- b3c2bb4: fix(openai-compatible, groq, alibaba): put reasoning before text in doGenerate
|
|
8
|
+
|
|
9
|
+
## 2.0.85
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 5aa3086: feat(openai-compatible): support URL-based image responses
|
|
14
|
+
|
|
15
|
+
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.
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [5aa3086]
|
|
18
|
+
- @ai-sdk/provider-utils@4.0.61
|
|
19
|
+
|
|
3
20
|
## 2.0.84
|
|
4
21
|
|
|
5
22
|
### 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
|
@@ -594,7 +594,6 @@ var OpenAICompatibleChatLanguageModel = class {
|
|
|
594
594
|
});
|
|
595
595
|
}
|
|
596
596
|
const content = [];
|
|
597
|
-
content.push(...convertOpenAICompatibleContent(choice.message.content));
|
|
598
597
|
const reasoning = (_a = choice.message.reasoning_content) != null ? _a : choice.message.reasoning;
|
|
599
598
|
if (reasoning != null && reasoning.length > 0) {
|
|
600
599
|
content.push({
|
|
@@ -602,6 +601,7 @@ var OpenAICompatibleChatLanguageModel = class {
|
|
|
602
601
|
text: reasoning
|
|
603
602
|
});
|
|
604
603
|
}
|
|
604
|
+
content.push(...convertOpenAICompatibleContent(choice.message.content));
|
|
605
605
|
if (choice.message.tool_calls != null) {
|
|
606
606
|
for (const toolCall of choice.message.tool_calls) {
|
|
607
607
|
const thoughtSignature = (_c = (_b = toolCall.extra_content) == null ? void 0 : _b.google) == null ? void 0 : _c.thought_signature;
|
|
@@ -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
|
-
|
|
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
|
|
1630
|
-
|
|
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
|
|
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
|
|
1664
|
-
|
|
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
|
|
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(
|
|
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.
|
|
1757
|
+
var VERSION = true ? "2.0.86" : "0.0.0-test";
|
|
1712
1758
|
|
|
1713
1759
|
// src/openai-compatible-provider.ts
|
|
1714
1760
|
function createOpenAICompatible(options) {
|