@ai-sdk/openai 4.0.42 → 4.0.44
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 +28 -0
- package/dist/index.js +146 -17
- package/dist/index.js.map +1 -1
- package/dist/internal/index.d.ts +17 -4
- package/dist/internal/index.js +145 -16
- package/dist/internal/index.js.map +1 -1
- package/docs/03-openai.mdx +58 -0
- package/package.json +4 -4
- package/src/chat/openai-chat-language-model.ts +1 -1
- package/src/responses/openai-responses-api.ts +15 -0
- package/src/responses/openai-responses-prepare-tools.ts +188 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @ai-sdk/openai
|
|
2
2
|
|
|
3
|
+
## 4.0.44
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e6087c9: fix: handle empty string tool call IDs
|
|
8
|
+
- Updated dependencies [e6087c9]
|
|
9
|
+
- @ai-sdk/provider-utils@5.0.28
|
|
10
|
+
|
|
11
|
+
## 4.0.43
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- a062795: fix(openai): support built-in and provider-defined tools in the Responses `allowedTools` option
|
|
16
|
+
|
|
17
|
+
`allowedTools` emitted every allow-list entry as `{ type: 'function', name }`, but OpenAI identifies
|
|
18
|
+
built-in tools by type. Allow-listing a declared provider-defined tool (web search, image generation,
|
|
19
|
+
MCP, custom, ...) therefore failed with `Tool choice '<name>' not found in 'tools' parameter`. Entries
|
|
20
|
+
are now derived from the declared tool, including the MCP server label and custom tool name.
|
|
21
|
+
|
|
22
|
+
Tools that OpenAI cannot allow-list (the tool search tool, deferred tools, and namespaced tools) are
|
|
23
|
+
dropped from the allow-list with a warning, and an error is thrown if that would leave the allow-list
|
|
24
|
+
empty rather than silently sending an unrestricted request.
|
|
25
|
+
|
|
26
|
+
Ambiguous names are now reported instead of resolved silently. A name that matches both a declared tool
|
|
27
|
+
and another tool's provider tool name resolves to the declared tool and warns; a provider tool name
|
|
28
|
+
shared by several tools in the same request (two MCP servers, for example) is dropped with a warning.
|
|
29
|
+
A name that matches no declared tool keeps its existing behavior and is now warned about.
|
|
30
|
+
|
|
3
31
|
## 4.0.42
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -1152,7 +1152,7 @@ var OpenAIChatLanguageModel = class _OpenAIChatLanguageModel {
|
|
|
1152
1152
|
};
|
|
1153
1153
|
}
|
|
1154
1154
|
async doGenerate(options) {
|
|
1155
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
1155
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1156
1156
|
const { args: body, warnings } = await this.getArgs(options);
|
|
1157
1157
|
const {
|
|
1158
1158
|
responseHeaders,
|
|
@@ -1181,12 +1181,12 @@ var OpenAIChatLanguageModel = class _OpenAIChatLanguageModel {
|
|
|
1181
1181
|
for (const toolCall of (_c = choice.message.tool_calls) != null ? _c : []) {
|
|
1182
1182
|
content.push({
|
|
1183
1183
|
type: "tool-call",
|
|
1184
|
-
toolCallId:
|
|
1184
|
+
toolCallId: toolCall.id || generateId(),
|
|
1185
1185
|
toolName: toolCall.function.name,
|
|
1186
1186
|
input: toolCall.function.arguments
|
|
1187
1187
|
});
|
|
1188
1188
|
}
|
|
1189
|
-
for (const annotation of (
|
|
1189
|
+
for (const annotation of (_d = choice.message.annotations) != null ? _d : []) {
|
|
1190
1190
|
content.push({
|
|
1191
1191
|
type: "source",
|
|
1192
1192
|
sourceType: "url",
|
|
@@ -1195,7 +1195,7 @@ var OpenAIChatLanguageModel = class _OpenAIChatLanguageModel {
|
|
|
1195
1195
|
title: annotation.url_citation.title
|
|
1196
1196
|
});
|
|
1197
1197
|
}
|
|
1198
|
-
const completionTokenDetails = (
|
|
1198
|
+
const completionTokenDetails = (_e = response.usage) == null ? void 0 : _e.completion_tokens_details;
|
|
1199
1199
|
const providerMetadata = { openai: {} };
|
|
1200
1200
|
if ((completionTokenDetails == null ? void 0 : completionTokenDetails.accepted_prediction_tokens) != null) {
|
|
1201
1201
|
providerMetadata.openai.acceptedPredictionTokens = completionTokenDetails == null ? void 0 : completionTokenDetails.accepted_prediction_tokens;
|
|
@@ -1203,14 +1203,14 @@ var OpenAIChatLanguageModel = class _OpenAIChatLanguageModel {
|
|
|
1203
1203
|
if ((completionTokenDetails == null ? void 0 : completionTokenDetails.rejected_prediction_tokens) != null) {
|
|
1204
1204
|
providerMetadata.openai.rejectedPredictionTokens = completionTokenDetails == null ? void 0 : completionTokenDetails.rejected_prediction_tokens;
|
|
1205
1205
|
}
|
|
1206
|
-
if (((
|
|
1206
|
+
if (((_f = choice.logprobs) == null ? void 0 : _f.content) != null) {
|
|
1207
1207
|
providerMetadata.openai.logprobs = choice.logprobs.content;
|
|
1208
1208
|
}
|
|
1209
1209
|
return {
|
|
1210
1210
|
content,
|
|
1211
1211
|
finishReason: {
|
|
1212
1212
|
unified: mapOpenAIFinishReason(choice.finish_reason),
|
|
1213
|
-
raw: (
|
|
1213
|
+
raw: (_g = choice.finish_reason) != null ? _g : void 0
|
|
1214
1214
|
},
|
|
1215
1215
|
usage: convertOpenAIChatUsage(response.usage),
|
|
1216
1216
|
request: { body },
|
|
@@ -5648,7 +5648,7 @@ async function prepareResponsesTools({
|
|
|
5648
5648
|
customProviderToolNames,
|
|
5649
5649
|
outputSchemaToolNames
|
|
5650
5650
|
}) {
|
|
5651
|
-
var _a, _b, _c;
|
|
5651
|
+
var _a, _b, _c, _d;
|
|
5652
5652
|
tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
|
|
5653
5653
|
const toolWarnings = [];
|
|
5654
5654
|
if (tools == null) {
|
|
@@ -5657,6 +5657,20 @@ async function prepareResponsesTools({
|
|
|
5657
5657
|
const openaiTools2 = [];
|
|
5658
5658
|
const namespaceTools = /* @__PURE__ */ new Map();
|
|
5659
5659
|
const resolvedCustomProviderToolNames = customProviderToolNames != null ? customProviderToolNames : /* @__PURE__ */ new Set();
|
|
5660
|
+
const allowedToolResolutions = /* @__PURE__ */ new Map();
|
|
5661
|
+
const allowedToolAliases = /* @__PURE__ */ new Map();
|
|
5662
|
+
const recordAllowedTool = (toolName, resolution, canonicalName) => {
|
|
5663
|
+
allowedToolResolutions.set(toolName, resolution);
|
|
5664
|
+
if (canonicalName == null || canonicalName === toolName) {
|
|
5665
|
+
return;
|
|
5666
|
+
}
|
|
5667
|
+
const existingAlias = allowedToolAliases.get(canonicalName);
|
|
5668
|
+
if (existingAlias == null) {
|
|
5669
|
+
allowedToolAliases.set(canonicalName, resolution);
|
|
5670
|
+
} else if (existingAlias !== "ambiguous" && !isSameAllowedTool(existingAlias, resolution)) {
|
|
5671
|
+
allowedToolAliases.set(canonicalName, "ambiguous");
|
|
5672
|
+
}
|
|
5673
|
+
};
|
|
5660
5674
|
for (const tool of tools) {
|
|
5661
5675
|
switch (tool.type) {
|
|
5662
5676
|
case "function": {
|
|
@@ -5689,9 +5703,24 @@ async function prepareResponsesTools({
|
|
|
5689
5703
|
}
|
|
5690
5704
|
namespaceTool.tools.push(openaiFunctionTool);
|
|
5691
5705
|
}
|
|
5706
|
+
recordAllowedTool(
|
|
5707
|
+
tool.name,
|
|
5708
|
+
namespace != null ? {
|
|
5709
|
+
supported: false,
|
|
5710
|
+
reason: "tools inside an OpenAI tool namespace are not visible to tool_choice.allowed_tools"
|
|
5711
|
+
} : (openaiOptions == null ? void 0 : openaiOptions.deferLoading) === true ? {
|
|
5712
|
+
supported: false,
|
|
5713
|
+
reason: "deferred tools are not visible to tool_choice.allowed_tools"
|
|
5714
|
+
} : {
|
|
5715
|
+
supported: true,
|
|
5716
|
+
entry: { type: "function", name: tool.name }
|
|
5717
|
+
},
|
|
5718
|
+
void 0
|
|
5719
|
+
);
|
|
5692
5720
|
break;
|
|
5693
5721
|
}
|
|
5694
5722
|
case "provider": {
|
|
5723
|
+
const openaiToolCountBefore = openaiTools2.length;
|
|
5695
5724
|
switch (tool.id) {
|
|
5696
5725
|
case "openai.file_search": {
|
|
5697
5726
|
const args = await validateTypes2({
|
|
@@ -5864,6 +5893,14 @@ async function prepareResponsesTools({
|
|
|
5864
5893
|
break;
|
|
5865
5894
|
}
|
|
5866
5895
|
}
|
|
5896
|
+
if (openaiTools2.length > openaiToolCountBefore) {
|
|
5897
|
+
const openaiTool = openaiTools2[openaiToolCountBefore];
|
|
5898
|
+
recordAllowedTool(
|
|
5899
|
+
tool.name,
|
|
5900
|
+
toAllowedToolResolution(openaiTool),
|
|
5901
|
+
toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(tool.name)
|
|
5902
|
+
);
|
|
5903
|
+
}
|
|
5867
5904
|
break;
|
|
5868
5905
|
}
|
|
5869
5906
|
default:
|
|
@@ -5875,18 +5912,63 @@ async function prepareResponsesTools({
|
|
|
5875
5912
|
}
|
|
5876
5913
|
}
|
|
5877
5914
|
if (allowedTools != null) {
|
|
5915
|
+
const allowedToolEntries = [];
|
|
5916
|
+
const droppedToolNames = [];
|
|
5917
|
+
for (const name of allowedTools.toolNames) {
|
|
5918
|
+
const directResolution = allowedToolResolutions.get(name);
|
|
5919
|
+
const resolution = directResolution != null ? directResolution : allowedToolAliases.get(name);
|
|
5920
|
+
if (directResolution != null && allowedToolAliases.has(name)) {
|
|
5921
|
+
toolWarnings.push({
|
|
5922
|
+
type: "unsupported",
|
|
5923
|
+
feature: `allowedTools entry "${name}"`,
|
|
5924
|
+
details: "this name is both a tool name and the provider tool name of another tool in this request; the tool with this name is allowed"
|
|
5925
|
+
});
|
|
5926
|
+
}
|
|
5927
|
+
if (resolution === "ambiguous") {
|
|
5928
|
+
toolWarnings.push({
|
|
5929
|
+
type: "unsupported",
|
|
5930
|
+
feature: `allowedTools entry "${name}"`,
|
|
5931
|
+
details: "several tools in this request share this provider tool name; use the tool name from the tools for this request instead"
|
|
5932
|
+
});
|
|
5933
|
+
droppedToolNames.push(name);
|
|
5934
|
+
continue;
|
|
5935
|
+
}
|
|
5936
|
+
if (resolution == null) {
|
|
5937
|
+
toolWarnings.push({
|
|
5938
|
+
type: "unsupported",
|
|
5939
|
+
feature: `allowedTools entry "${name}"`,
|
|
5940
|
+
details: "the tool is not part of the tools for this request and is sent as a function tool"
|
|
5941
|
+
});
|
|
5942
|
+
allowedToolEntries.push({
|
|
5943
|
+
type: "function",
|
|
5944
|
+
name: (_b = toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(name)) != null ? _b : name
|
|
5945
|
+
});
|
|
5946
|
+
continue;
|
|
5947
|
+
}
|
|
5948
|
+
if (!resolution.supported) {
|
|
5949
|
+
toolWarnings.push({
|
|
5950
|
+
type: "unsupported",
|
|
5951
|
+
feature: `allowedTools entry "${name}"`,
|
|
5952
|
+
details: `${resolution.reason}; the tool is removed from the allowed tools`
|
|
5953
|
+
});
|
|
5954
|
+
droppedToolNames.push(name);
|
|
5955
|
+
continue;
|
|
5956
|
+
}
|
|
5957
|
+
allowedToolEntries.push(resolution.entry);
|
|
5958
|
+
}
|
|
5959
|
+
if (allowedToolEntries.length === 0) {
|
|
5960
|
+
throw new UnsupportedFunctionalityError5({
|
|
5961
|
+
functionality: `allowedTools with only tools that cannot be allow-listed (${droppedToolNames.join(
|
|
5962
|
+
", "
|
|
5963
|
+
)})`
|
|
5964
|
+
});
|
|
5965
|
+
}
|
|
5878
5966
|
return {
|
|
5879
5967
|
tools: openaiTools2,
|
|
5880
5968
|
toolChoice: {
|
|
5881
5969
|
type: "allowed_tools",
|
|
5882
|
-
mode: (
|
|
5883
|
-
tools:
|
|
5884
|
-
var _a2;
|
|
5885
|
-
return {
|
|
5886
|
-
type: "function",
|
|
5887
|
-
name: (_a2 = toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(name)) != null ? _a2 : name
|
|
5888
|
-
};
|
|
5889
|
-
})
|
|
5970
|
+
mode: (_c = allowedTools.mode) != null ? _c : "auto",
|
|
5971
|
+
tools: allowedToolEntries
|
|
5890
5972
|
},
|
|
5891
5973
|
toolWarnings
|
|
5892
5974
|
};
|
|
@@ -5901,7 +5983,7 @@ async function prepareResponsesTools({
|
|
|
5901
5983
|
case "required":
|
|
5902
5984
|
return { tools: openaiTools2, toolChoice: type, toolWarnings };
|
|
5903
5985
|
case "tool": {
|
|
5904
|
-
const resolvedToolName = (
|
|
5986
|
+
const resolvedToolName = (_d = toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(toolChoice.toolName)) != null ? _d : toolChoice.toolName;
|
|
5905
5987
|
return {
|
|
5906
5988
|
tools: openaiTools2,
|
|
5907
5989
|
toolChoice: resolvedToolName === "code_interpreter" || resolvedToolName === "file_search" || resolvedToolName === "image_generation" || resolvedToolName === "web_search_preview" || resolvedToolName === "web_search" || resolvedToolName === "mcp" || resolvedToolName === "apply_patch" || resolvedToolName === "computer" || resolvedToolName === "programmatic_tool_calling" ? { type: resolvedToolName } : resolvedCustomProviderToolNames.has(resolvedToolName) ? { type: "custom", name: resolvedToolName } : { type: "function", name: resolvedToolName },
|
|
@@ -5916,6 +5998,53 @@ async function prepareResponsesTools({
|
|
|
5916
5998
|
}
|
|
5917
5999
|
}
|
|
5918
6000
|
}
|
|
6001
|
+
function allowedToolKey(entry) {
|
|
6002
|
+
switch (entry.type) {
|
|
6003
|
+
case "mcp":
|
|
6004
|
+
return `mcp:${entry.server_label}`;
|
|
6005
|
+
case "function":
|
|
6006
|
+
case "custom":
|
|
6007
|
+
return `${entry.type}:${entry.name}`;
|
|
6008
|
+
default:
|
|
6009
|
+
return entry.type;
|
|
6010
|
+
}
|
|
6011
|
+
}
|
|
6012
|
+
function isSameAllowedTool(a, b) {
|
|
6013
|
+
if (a.supported && b.supported) {
|
|
6014
|
+
return allowedToolKey(a.entry) === allowedToolKey(b.entry);
|
|
6015
|
+
}
|
|
6016
|
+
if (!a.supported && !b.supported) {
|
|
6017
|
+
return a.reason === b.reason;
|
|
6018
|
+
}
|
|
6019
|
+
return false;
|
|
6020
|
+
}
|
|
6021
|
+
function toAllowedToolResolution(tool) {
|
|
6022
|
+
switch (tool.type) {
|
|
6023
|
+
case "custom":
|
|
6024
|
+
return { supported: true, entry: { type: "custom", name: tool.name } };
|
|
6025
|
+
case "mcp":
|
|
6026
|
+
return {
|
|
6027
|
+
supported: true,
|
|
6028
|
+
entry: { type: "mcp", server_label: tool.server_label }
|
|
6029
|
+
};
|
|
6030
|
+
case "file_search":
|
|
6031
|
+
case "web_search":
|
|
6032
|
+
case "web_search_preview":
|
|
6033
|
+
case "image_generation":
|
|
6034
|
+
case "code_interpreter":
|
|
6035
|
+
case "computer":
|
|
6036
|
+
case "apply_patch":
|
|
6037
|
+
case "shell":
|
|
6038
|
+
case "local_shell":
|
|
6039
|
+
case "programmatic_tool_calling":
|
|
6040
|
+
return { supported: true, entry: { type: tool.type } };
|
|
6041
|
+
default:
|
|
6042
|
+
return {
|
|
6043
|
+
supported: false,
|
|
6044
|
+
reason: `OpenAI does not support ${tool.type} tools in tool_choice.allowed_tools`
|
|
6045
|
+
};
|
|
6046
|
+
}
|
|
6047
|
+
}
|
|
5919
6048
|
function prepareFunctionTool({
|
|
5920
6049
|
tool,
|
|
5921
6050
|
options
|
|
@@ -10031,7 +10160,7 @@ var OpenAISkills = class {
|
|
|
10031
10160
|
};
|
|
10032
10161
|
|
|
10033
10162
|
// src/version.ts
|
|
10034
|
-
var VERSION = true ? "4.0.
|
|
10163
|
+
var VERSION = true ? "4.0.44" : "0.0.0-test";
|
|
10035
10164
|
|
|
10036
10165
|
// src/openai-provider.ts
|
|
10037
10166
|
function createOpenAI(options = {}) {
|