@ai-sdk/openai 3.0.97 → 3.0.98
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 +20 -0
- package/dist/index.js +138 -11
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +138 -11
- package/dist/index.mjs.map +1 -1
- package/dist/internal/index.js +137 -10
- package/dist/internal/index.js.map +1 -1
- package/dist/internal/index.mjs +137 -10
- package/dist/internal/index.mjs.map +1 -1
- package/docs/03-openai.mdx +57 -0
- package/package.json +1 -1
- package/src/responses/openai-responses-api.ts +15 -0
- package/src/responses/openai-responses-prepare-tools.ts +186 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @ai-sdk/openai
|
|
2
2
|
|
|
3
|
+
## 3.0.98
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 91880b9: fix(openai): support built-in and provider-defined tools in the Responses `allowedTools` option
|
|
8
|
+
|
|
9
|
+
`allowedTools` emitted every allow-list entry as `{ type: 'function', name }`, but OpenAI identifies
|
|
10
|
+
built-in tools by type. Allow-listing a declared provider-defined tool (web search, image generation,
|
|
11
|
+
MCP, custom, ...) therefore failed with `Tool choice '<name>' not found in 'tools' parameter`. Entries
|
|
12
|
+
are now derived from the declared tool, including the MCP server label and custom tool name.
|
|
13
|
+
|
|
14
|
+
Tools that OpenAI cannot allow-list (the tool search tool, deferred tools, and namespaced tools) are
|
|
15
|
+
dropped from the allow-list with a warning, and an error is thrown if that would leave the allow-list
|
|
16
|
+
empty rather than silently sending an unrestricted request.
|
|
17
|
+
|
|
18
|
+
Ambiguous names are now reported instead of resolved silently. A name that matches both a declared tool
|
|
19
|
+
and another tool's provider tool name resolves to the declared tool and warns; a provider tool name
|
|
20
|
+
shared by several tools in the same request (two MCP servers, for example) is dropped with a warning.
|
|
21
|
+
A name that matches no declared tool keeps its existing behavior and is now warned about.
|
|
22
|
+
|
|
3
23
|
## 3.0.97
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -4888,7 +4888,7 @@ async function prepareResponsesTools({
|
|
|
4888
4888
|
toolNameMapping,
|
|
4889
4889
|
customProviderToolNames
|
|
4890
4890
|
}) {
|
|
4891
|
-
var _a, _b, _c;
|
|
4891
|
+
var _a, _b, _c, _d;
|
|
4892
4892
|
tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
|
|
4893
4893
|
const toolWarnings = [];
|
|
4894
4894
|
if (tools == null) {
|
|
@@ -4897,6 +4897,20 @@ async function prepareResponsesTools({
|
|
|
4897
4897
|
const openaiTools2 = [];
|
|
4898
4898
|
const namespaceTools = /* @__PURE__ */ new Map();
|
|
4899
4899
|
const resolvedCustomProviderToolNames = customProviderToolNames != null ? customProviderToolNames : /* @__PURE__ */ new Set();
|
|
4900
|
+
const allowedToolResolutions = /* @__PURE__ */ new Map();
|
|
4901
|
+
const allowedToolAliases = /* @__PURE__ */ new Map();
|
|
4902
|
+
const recordAllowedTool = (toolName, resolution, canonicalName) => {
|
|
4903
|
+
allowedToolResolutions.set(toolName, resolution);
|
|
4904
|
+
if (canonicalName == null || canonicalName === toolName) {
|
|
4905
|
+
return;
|
|
4906
|
+
}
|
|
4907
|
+
const existingAlias = allowedToolAliases.get(canonicalName);
|
|
4908
|
+
if (existingAlias == null) {
|
|
4909
|
+
allowedToolAliases.set(canonicalName, resolution);
|
|
4910
|
+
} else if (existingAlias !== "ambiguous" && !isSameAllowedTool(existingAlias, resolution)) {
|
|
4911
|
+
allowedToolAliases.set(canonicalName, "ambiguous");
|
|
4912
|
+
}
|
|
4913
|
+
};
|
|
4900
4914
|
for (const tool of tools) {
|
|
4901
4915
|
switch (tool.type) {
|
|
4902
4916
|
case "function": {
|
|
@@ -4926,9 +4940,24 @@ async function prepareResponsesTools({
|
|
|
4926
4940
|
}
|
|
4927
4941
|
namespaceTool.tools.push(openaiFunctionTool);
|
|
4928
4942
|
}
|
|
4943
|
+
recordAllowedTool(
|
|
4944
|
+
tool.name,
|
|
4945
|
+
namespace != null ? {
|
|
4946
|
+
supported: false,
|
|
4947
|
+
reason: "tools inside an OpenAI tool namespace are not visible to tool_choice.allowed_tools"
|
|
4948
|
+
} : (openaiOptions == null ? void 0 : openaiOptions.deferLoading) === true ? {
|
|
4949
|
+
supported: false,
|
|
4950
|
+
reason: "deferred tools are not visible to tool_choice.allowed_tools"
|
|
4951
|
+
} : {
|
|
4952
|
+
supported: true,
|
|
4953
|
+
entry: { type: "function", name: tool.name }
|
|
4954
|
+
},
|
|
4955
|
+
void 0
|
|
4956
|
+
);
|
|
4929
4957
|
break;
|
|
4930
4958
|
}
|
|
4931
4959
|
case "provider": {
|
|
4960
|
+
const openaiToolCountBefore = openaiTools2.length;
|
|
4932
4961
|
switch (tool.id) {
|
|
4933
4962
|
case "openai.file_search": {
|
|
4934
4963
|
const args = await (0, import_provider_utils29.validateTypes)({
|
|
@@ -5089,6 +5118,14 @@ async function prepareResponsesTools({
|
|
|
5089
5118
|
break;
|
|
5090
5119
|
}
|
|
5091
5120
|
}
|
|
5121
|
+
if (openaiTools2.length > openaiToolCountBefore) {
|
|
5122
|
+
const openaiTool = openaiTools2[openaiToolCountBefore];
|
|
5123
|
+
recordAllowedTool(
|
|
5124
|
+
tool.name,
|
|
5125
|
+
toAllowedToolResolution(openaiTool),
|
|
5126
|
+
toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(tool.name)
|
|
5127
|
+
);
|
|
5128
|
+
}
|
|
5092
5129
|
break;
|
|
5093
5130
|
}
|
|
5094
5131
|
default:
|
|
@@ -5100,18 +5137,63 @@ async function prepareResponsesTools({
|
|
|
5100
5137
|
}
|
|
5101
5138
|
}
|
|
5102
5139
|
if (allowedTools != null) {
|
|
5140
|
+
const allowedToolEntries = [];
|
|
5141
|
+
const droppedToolNames = [];
|
|
5142
|
+
for (const name of allowedTools.toolNames) {
|
|
5143
|
+
const directResolution = allowedToolResolutions.get(name);
|
|
5144
|
+
const resolution = directResolution != null ? directResolution : allowedToolAliases.get(name);
|
|
5145
|
+
if (directResolution != null && allowedToolAliases.has(name)) {
|
|
5146
|
+
toolWarnings.push({
|
|
5147
|
+
type: "unsupported",
|
|
5148
|
+
feature: `allowedTools entry "${name}"`,
|
|
5149
|
+
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"
|
|
5150
|
+
});
|
|
5151
|
+
}
|
|
5152
|
+
if (resolution === "ambiguous") {
|
|
5153
|
+
toolWarnings.push({
|
|
5154
|
+
type: "unsupported",
|
|
5155
|
+
feature: `allowedTools entry "${name}"`,
|
|
5156
|
+
details: "several tools in this request share this provider tool name; use the tool name from the tools for this request instead"
|
|
5157
|
+
});
|
|
5158
|
+
droppedToolNames.push(name);
|
|
5159
|
+
continue;
|
|
5160
|
+
}
|
|
5161
|
+
if (resolution == null) {
|
|
5162
|
+
toolWarnings.push({
|
|
5163
|
+
type: "unsupported",
|
|
5164
|
+
feature: `allowedTools entry "${name}"`,
|
|
5165
|
+
details: "the tool is not part of the tools for this request and is sent as a function tool"
|
|
5166
|
+
});
|
|
5167
|
+
allowedToolEntries.push({
|
|
5168
|
+
type: "function",
|
|
5169
|
+
name: (_b = toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(name)) != null ? _b : name
|
|
5170
|
+
});
|
|
5171
|
+
continue;
|
|
5172
|
+
}
|
|
5173
|
+
if (!resolution.supported) {
|
|
5174
|
+
toolWarnings.push({
|
|
5175
|
+
type: "unsupported",
|
|
5176
|
+
feature: `allowedTools entry "${name}"`,
|
|
5177
|
+
details: `${resolution.reason}; the tool is removed from the allowed tools`
|
|
5178
|
+
});
|
|
5179
|
+
droppedToolNames.push(name);
|
|
5180
|
+
continue;
|
|
5181
|
+
}
|
|
5182
|
+
allowedToolEntries.push(resolution.entry);
|
|
5183
|
+
}
|
|
5184
|
+
if (allowedToolEntries.length === 0) {
|
|
5185
|
+
throw new import_provider8.UnsupportedFunctionalityError({
|
|
5186
|
+
functionality: `allowedTools with only tools that cannot be allow-listed (${droppedToolNames.join(
|
|
5187
|
+
", "
|
|
5188
|
+
)})`
|
|
5189
|
+
});
|
|
5190
|
+
}
|
|
5103
5191
|
return {
|
|
5104
5192
|
tools: openaiTools2,
|
|
5105
5193
|
toolChoice: {
|
|
5106
5194
|
type: "allowed_tools",
|
|
5107
|
-
mode: (
|
|
5108
|
-
tools:
|
|
5109
|
-
var _a2;
|
|
5110
|
-
return {
|
|
5111
|
-
type: "function",
|
|
5112
|
-
name: (_a2 = toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(name)) != null ? _a2 : name
|
|
5113
|
-
};
|
|
5114
|
-
})
|
|
5195
|
+
mode: (_c = allowedTools.mode) != null ? _c : "auto",
|
|
5196
|
+
tools: allowedToolEntries
|
|
5115
5197
|
},
|
|
5116
5198
|
toolWarnings
|
|
5117
5199
|
};
|
|
@@ -5126,7 +5208,7 @@ async function prepareResponsesTools({
|
|
|
5126
5208
|
case "required":
|
|
5127
5209
|
return { tools: openaiTools2, toolChoice: type, toolWarnings };
|
|
5128
5210
|
case "tool": {
|
|
5129
|
-
const resolvedToolName = (
|
|
5211
|
+
const resolvedToolName = (_d = toolNameMapping == null ? void 0 : toolNameMapping.toProviderToolName(toolChoice.toolName)) != null ? _d : toolChoice.toolName;
|
|
5130
5212
|
return {
|
|
5131
5213
|
tools: openaiTools2,
|
|
5132
5214
|
toolChoice: resolvedToolName === "code_interpreter" || resolvedToolName === "file_search" || resolvedToolName === "image_generation" || resolvedToolName === "web_search_preview" || resolvedToolName === "web_search" || resolvedToolName === "mcp" || resolvedToolName === "apply_patch" ? { type: resolvedToolName } : resolvedCustomProviderToolNames.has(resolvedToolName) ? { type: "custom", name: resolvedToolName } : { type: "function", name: resolvedToolName },
|
|
@@ -5141,6 +5223,51 @@ async function prepareResponsesTools({
|
|
|
5141
5223
|
}
|
|
5142
5224
|
}
|
|
5143
5225
|
}
|
|
5226
|
+
function allowedToolKey(entry) {
|
|
5227
|
+
switch (entry.type) {
|
|
5228
|
+
case "mcp":
|
|
5229
|
+
return `mcp:${entry.server_label}`;
|
|
5230
|
+
case "function":
|
|
5231
|
+
case "custom":
|
|
5232
|
+
return `${entry.type}:${entry.name}`;
|
|
5233
|
+
default:
|
|
5234
|
+
return entry.type;
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5237
|
+
function isSameAllowedTool(a, b) {
|
|
5238
|
+
if (a.supported && b.supported) {
|
|
5239
|
+
return allowedToolKey(a.entry) === allowedToolKey(b.entry);
|
|
5240
|
+
}
|
|
5241
|
+
if (!a.supported && !b.supported) {
|
|
5242
|
+
return a.reason === b.reason;
|
|
5243
|
+
}
|
|
5244
|
+
return false;
|
|
5245
|
+
}
|
|
5246
|
+
function toAllowedToolResolution(tool) {
|
|
5247
|
+
switch (tool.type) {
|
|
5248
|
+
case "custom":
|
|
5249
|
+
return { supported: true, entry: { type: "custom", name: tool.name } };
|
|
5250
|
+
case "mcp":
|
|
5251
|
+
return {
|
|
5252
|
+
supported: true,
|
|
5253
|
+
entry: { type: "mcp", server_label: tool.server_label }
|
|
5254
|
+
};
|
|
5255
|
+
case "file_search":
|
|
5256
|
+
case "web_search":
|
|
5257
|
+
case "web_search_preview":
|
|
5258
|
+
case "image_generation":
|
|
5259
|
+
case "code_interpreter":
|
|
5260
|
+
case "apply_patch":
|
|
5261
|
+
case "shell":
|
|
5262
|
+
case "local_shell":
|
|
5263
|
+
return { supported: true, entry: { type: tool.type } };
|
|
5264
|
+
default:
|
|
5265
|
+
return {
|
|
5266
|
+
supported: false,
|
|
5267
|
+
reason: `OpenAI does not support ${tool.type} tools in tool_choice.allowed_tools`
|
|
5268
|
+
};
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5144
5271
|
function prepareFunctionTool({
|
|
5145
5272
|
tool,
|
|
5146
5273
|
options
|
|
@@ -7357,7 +7484,7 @@ var OpenAITranscriptionModel = class {
|
|
|
7357
7484
|
};
|
|
7358
7485
|
|
|
7359
7486
|
// src/version.ts
|
|
7360
|
-
var VERSION = true ? "3.0.
|
|
7487
|
+
var VERSION = true ? "3.0.98" : "0.0.0-test";
|
|
7361
7488
|
|
|
7362
7489
|
// src/openai-provider.ts
|
|
7363
7490
|
function createOpenAI(options = {}) {
|