@tanstack/openai-base 0.9.13 → 0.9.15

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.
Files changed (51) hide show
  1. package/dist/esm/adapters/chat-completions-text.d.ts +10 -0
  2. package/dist/esm/adapters/chat-completions-text.js +47 -1
  3. package/dist/esm/adapters/chat-completions-text.js.map +1 -1
  4. package/dist/esm/adapters/responses-text.js +1 -1
  5. package/dist/esm/index.js +1 -0
  6. package/dist/esm/tools/apply-patch-tool.js +3 -2
  7. package/dist/esm/tools/apply-patch-tool.js.map +1 -1
  8. package/dist/esm/tools/code-interpreter-tool.js +4 -3
  9. package/dist/esm/tools/code-interpreter-tool.js.map +1 -1
  10. package/dist/esm/tools/computer-use-tool.js +4 -3
  11. package/dist/esm/tools/computer-use-tool.js.map +1 -1
  12. package/dist/esm/tools/custom-tool.js +4 -3
  13. package/dist/esm/tools/custom-tool.js.map +1 -1
  14. package/dist/esm/tools/file-search-tool.js +4 -3
  15. package/dist/esm/tools/file-search-tool.js.map +1 -1
  16. package/dist/esm/tools/image-generation-tool.d.ts +2 -4
  17. package/dist/esm/tools/image-generation-tool.js +6 -7
  18. package/dist/esm/tools/image-generation-tool.js.map +1 -1
  19. package/dist/esm/tools/index.js +14 -0
  20. package/dist/esm/tools/local-shell-tool.js +3 -2
  21. package/dist/esm/tools/local-shell-tool.js.map +1 -1
  22. package/dist/esm/tools/mcp-tool.js +7 -6
  23. package/dist/esm/tools/mcp-tool.js.map +1 -1
  24. package/dist/esm/tools/openai-provider-tool.d.ts +20 -0
  25. package/dist/esm/tools/openai-provider-tool.js +49 -0
  26. package/dist/esm/tools/openai-provider-tool.js.map +1 -0
  27. package/dist/esm/tools/shell-tool.js +4 -3
  28. package/dist/esm/tools/shell-tool.js.map +1 -1
  29. package/dist/esm/tools/tool-converter.js +7 -18
  30. package/dist/esm/tools/tool-converter.js.map +1 -1
  31. package/dist/esm/tools/web-search-preview-tool.d.ts +1 -2
  32. package/dist/esm/tools/web-search-preview-tool.js +5 -5
  33. package/dist/esm/tools/web-search-preview-tool.js.map +1 -1
  34. package/dist/esm/tools/web-search-tool.d.ts +2 -4
  35. package/dist/esm/tools/web-search-tool.js +6 -7
  36. package/dist/esm/tools/web-search-tool.js.map +1 -1
  37. package/package.json +3 -3
  38. package/src/adapters/chat-completions-text.ts +65 -0
  39. package/src/tools/apply-patch-tool.ts +9 -5
  40. package/src/tools/code-interpreter-tool.ts +17 -8
  41. package/src/tools/computer-use-tool.ts +14 -7
  42. package/src/tools/custom-tool.ts +14 -7
  43. package/src/tools/file-search-tool.ts +14 -7
  44. package/src/tools/image-generation-tool.ts +19 -11
  45. package/src/tools/local-shell-tool.ts +9 -5
  46. package/src/tools/mcp-tool.ts +19 -9
  47. package/src/tools/openai-provider-tool.ts +72 -0
  48. package/src/tools/shell-tool.ts +17 -9
  49. package/src/tools/tool-converter.ts +28 -43
  50. package/src/tools/web-search-preview-tool.ts +17 -8
  51. package/src/tools/web-search-tool.ts +18 -10
@@ -1,3 +1,4 @@
1
+ import { getOpenAIProviderToolMetadata, openAIProviderTool } from "./openai-provider-tool.js";
1
2
  //#region src/tools/file-search-tool.ts
2
3
  var validateMaxNumResults = (maxNumResults) => {
3
4
  if (maxNumResults !== void 0 && (maxNumResults < 1 || maxNumResults > 50)) throw new Error("max_num_results must be between 1 and 50.");
@@ -6,7 +7,7 @@ var validateMaxNumResults = (maxNumResults) => {
6
7
  * Converts a standard Tool to OpenAI FileSearchTool format
7
8
  */
8
9
  function convertFileSearchToolToAdapterFormat(tool) {
9
- const metadata = tool.metadata;
10
+ const metadata = getOpenAIProviderToolMetadata(tool);
10
11
  return {
11
12
  type: "file_search",
12
13
  vector_store_ids: metadata.vector_store_ids,
@@ -23,11 +24,11 @@ function convertFileSearchToolToAdapterFormat(tool) {
23
24
  */
24
25
  function fileSearchTool(toolData) {
25
26
  validateMaxNumResults(toolData.max_num_results);
26
- return {
27
+ return openAIProviderTool({
27
28
  name: "file_search",
28
29
  description: "Search files in vector stores",
29
30
  metadata: { ...toolData }
30
- };
31
+ }, "file_search");
31
32
  }
32
33
  //#endregion
33
34
  export { convertFileSearchToolToAdapterFormat, fileSearchTool, validateMaxNumResults };
@@ -1 +1 @@
1
- {"version":3,"file":"file-search-tool.js","names":[],"sources":["../../../src/tools/file-search-tool.ts"],"sourcesContent":["import type { FileSearchTool as FileSearchToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { FileSearchToolConfig }\n\nconst validateMaxNumResults = (maxNumResults: number | undefined) => {\n if (\n maxNumResults !== undefined &&\n (maxNumResults < 1 || maxNumResults > 50)\n ) {\n throw new Error('max_num_results must be between 1 and 50.')\n }\n}\n\n/** @deprecated Renamed to `FileSearchToolConfig`. Will be removed in a future release. */\nexport type FileSearchTool = FileSearchToolConfig\n\n/**\n * Converts a standard Tool to OpenAI FileSearchTool format\n */\nexport function convertFileSearchToolToAdapterFormat(\n tool: Tool,\n): FileSearchToolConfig {\n const metadata = tool.metadata as FileSearchToolConfig\n // Conditional spread: SDK's `FileSearchToolConfig` declares the\n // optional fields without `| undefined`, so we omit absent values\n // rather than passing them through as explicit `undefined`.\n return {\n type: 'file_search',\n vector_store_ids: metadata.vector_store_ids,\n ...(metadata.max_num_results !== undefined && {\n max_num_results: metadata.max_num_results,\n }),\n ...(metadata.ranking_options !== undefined && {\n ranking_options: metadata.ranking_options,\n }),\n ...(metadata.filters !== undefined && { filters: metadata.filters }),\n }\n}\n\n/**\n * Creates a standard Tool from FileSearchTool parameters.\n *\n * Validates max_num_results. Base (non-branded) factory; providers that need\n * branded return types should re-wrap in their own package.\n */\nexport function fileSearchTool(toolData: FileSearchToolConfig): Tool {\n validateMaxNumResults(toolData.max_num_results)\n return {\n name: 'file_search',\n description: 'Search files in vector stores',\n metadata: {\n ...toolData,\n },\n }\n}\n\nexport { validateMaxNumResults }\n"],"mappings":";AAKA,IAAM,yBAAyB,kBAAsC;CACnE,IACE,kBAAkB,KAAA,MACjB,gBAAgB,KAAK,gBAAgB,KAEtC,MAAM,IAAI,MAAM,2CAA2C;AAE/D;;;;AAQA,SAAgB,qCACd,MACsB;CACtB,MAAM,WAAW,KAAK;CAItB,OAAO;EACL,MAAM;EACN,kBAAkB,SAAS;EAC3B,GAAI,SAAS,oBAAoB,KAAA,KAAa,EAC5C,iBAAiB,SAAS,gBAC5B;EACA,GAAI,SAAS,oBAAoB,KAAA,KAAa,EAC5C,iBAAiB,SAAS,gBAC5B;EACA,GAAI,SAAS,YAAY,KAAA,KAAa,EAAE,SAAS,SAAS,QAAQ;CACpE;AACF;;;;;;;AAQA,SAAgB,eAAe,UAAsC;CACnE,sBAAsB,SAAS,eAAe;CAC9C,OAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU,EACR,GAAG,SACL;CACF;AACF"}
1
+ {"version":3,"file":"file-search-tool.js","names":[],"sources":["../../../src/tools/file-search-tool.ts"],"sourcesContent":["import {\n getOpenAIProviderToolMetadata,\n openAIProviderTool,\n} from './openai-provider-tool'\nimport type { FileSearchTool as FileSearchToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { FileSearchToolConfig }\n\nconst validateMaxNumResults = (maxNumResults: number | undefined) => {\n if (\n maxNumResults !== undefined &&\n (maxNumResults < 1 || maxNumResults > 50)\n ) {\n throw new Error('max_num_results must be between 1 and 50.')\n }\n}\n\n/** @deprecated Renamed to `FileSearchToolConfig`. Will be removed in a future release. */\nexport type FileSearchTool = FileSearchToolConfig\n\n/**\n * Converts a standard Tool to OpenAI FileSearchTool format\n */\nexport function convertFileSearchToolToAdapterFormat(\n tool: Tool,\n): FileSearchToolConfig {\n const metadata = getOpenAIProviderToolMetadata(tool) as FileSearchToolConfig\n // Conditional spread: SDK's `FileSearchToolConfig` declares the\n // optional fields without `| undefined`, so we omit absent values\n // rather than passing them through as explicit `undefined`.\n return {\n type: 'file_search',\n vector_store_ids: metadata.vector_store_ids,\n ...(metadata.max_num_results !== undefined && {\n max_num_results: metadata.max_num_results,\n }),\n ...(metadata.ranking_options !== undefined && {\n ranking_options: metadata.ranking_options,\n }),\n ...(metadata.filters !== undefined && { filters: metadata.filters }),\n }\n}\n\n/**\n * Creates a standard Tool from FileSearchTool parameters.\n *\n * Validates max_num_results. Base (non-branded) factory; providers that need\n * branded return types should re-wrap in their own package.\n */\nexport function fileSearchTool(toolData: FileSearchToolConfig): Tool {\n validateMaxNumResults(toolData.max_num_results)\n return openAIProviderTool(\n {\n name: 'file_search',\n description: 'Search files in vector stores',\n metadata: {\n ...toolData,\n },\n },\n 'file_search',\n )\n}\n\nexport { validateMaxNumResults }\n"],"mappings":";;AASA,IAAM,yBAAyB,kBAAsC;CACnE,IACE,kBAAkB,KAAA,MACjB,gBAAgB,KAAK,gBAAgB,KAEtC,MAAM,IAAI,MAAM,2CAA2C;AAE/D;;;;AAQA,SAAgB,qCACd,MACsB;CACtB,MAAM,WAAW,8BAA8B,IAAI;CAInD,OAAO;EACL,MAAM;EACN,kBAAkB,SAAS;EAC3B,GAAI,SAAS,oBAAoB,KAAA,KAAa,EAC5C,iBAAiB,SAAS,gBAC5B;EACA,GAAI,SAAS,oBAAoB,KAAA,KAAa,EAC5C,iBAAiB,SAAS,gBAC5B;EACA,GAAI,SAAS,YAAY,KAAA,KAAa,EAAE,SAAS,SAAS,QAAQ;CACpE;AACF;;;;;;;AAQA,SAAgB,eAAe,UAAsC;CACnE,sBAAsB,SAAS,eAAe;CAC9C,OAAO,mBACL;EACE,MAAM;EACN,aAAa;EACb,UAAU,EACR,GAAG,SACL;CACF,GACA,aACF;AACF"}
@@ -7,10 +7,8 @@ export type ImageGenerationTool = ImageGenerationToolConfig;
7
7
  declare const validatePartialImages: (value: number | undefined) => void;
8
8
  /**
9
9
  * Converts a standard Tool to OpenAI ImageGenerationTool format. Spread
10
- * `metadata` first, then force `type: 'image_generation'` last — otherwise a
11
- * `metadata.type` snuck in by a hand-built tool would shadow the literal and
12
- * the dispatcher (which routed by `tool.name`) would emit a tool whose
13
- * runtime `type` doesn't match `image_generation`.
10
+ * `metadata` first, then force `type: 'image_generation'` last so a stray
11
+ * `metadata.type` cannot shadow the wire discriminator.
14
12
  */
15
13
  export declare function convertImageGenerationToolToAdapterFormat(tool: Tool): ImageGenerationToolConfig;
16
14
  /**
@@ -1,17 +1,16 @@
1
+ import { getOpenAIProviderToolMetadata, openAIProviderTool } from "./openai-provider-tool.js";
1
2
  //#region src/tools/image-generation-tool.ts
2
3
  var validatePartialImages = (value) => {
3
4
  if (value !== void 0 && (value < 0 || value > 3)) throw new Error("partial_images must be between 0 and 3");
4
5
  };
5
6
  /**
6
7
  * Converts a standard Tool to OpenAI ImageGenerationTool format. Spread
7
- * `metadata` first, then force `type: 'image_generation'` last — otherwise a
8
- * `metadata.type` snuck in by a hand-built tool would shadow the literal and
9
- * the dispatcher (which routed by `tool.name`) would emit a tool whose
10
- * runtime `type` doesn't match `image_generation`.
8
+ * `metadata` first, then force `type: 'image_generation'` last so a stray
9
+ * `metadata.type` cannot shadow the wire discriminator.
11
10
  */
12
11
  function convertImageGenerationToolToAdapterFormat(tool) {
13
12
  return {
14
- ...tool.metadata,
13
+ ...getOpenAIProviderToolMetadata(tool),
15
14
  type: "image_generation"
16
15
  };
17
16
  }
@@ -23,11 +22,11 @@ function convertImageGenerationToolToAdapterFormat(tool) {
23
22
  */
24
23
  function imageGenerationTool(toolData) {
25
24
  validatePartialImages(toolData.partial_images);
26
- return {
25
+ return openAIProviderTool({
27
26
  name: "image_generation",
28
27
  description: "Generate images based on text descriptions",
29
28
  metadata: { ...toolData }
30
- };
29
+ }, "image_generation");
31
30
  }
32
31
  //#endregion
33
32
  export { convertImageGenerationToolToAdapterFormat, imageGenerationTool, validatePartialImages };
@@ -1 +1 @@
1
- {"version":3,"file":"image-generation-tool.js","names":[],"sources":["../../../src/tools/image-generation-tool.ts"],"sourcesContent":["import type { Tool as SDKTool } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\ntype ImageGenerationToolConfig = SDKTool.ImageGeneration\n\nexport type { ImageGenerationToolConfig }\n\n/** @deprecated Renamed to `ImageGenerationToolConfig`. Will be removed in a future release. */\nexport type ImageGenerationTool = ImageGenerationToolConfig\n\nconst validatePartialImages = (value: number | undefined) => {\n if (value !== undefined && (value < 0 || value > 3)) {\n throw new Error('partial_images must be between 0 and 3')\n }\n}\n\n/**\n * Converts a standard Tool to OpenAI ImageGenerationTool format. Spread\n * `metadata` first, then force `type: 'image_generation'` last — otherwise a\n * `metadata.type` snuck in by a hand-built tool would shadow the literal and\n * the dispatcher (which routed by `tool.name`) would emit a tool whose\n * runtime `type` doesn't match `image_generation`.\n */\nexport function convertImageGenerationToolToAdapterFormat(\n tool: Tool,\n): ImageGenerationToolConfig {\n const metadata = tool.metadata as Omit<ImageGenerationToolConfig, 'type'>\n return {\n ...metadata,\n type: 'image_generation',\n }\n}\n\n/**\n * Creates a standard Tool from ImageGenerationTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function imageGenerationTool(\n toolData: Omit<ImageGenerationToolConfig, 'type'>,\n): Tool {\n validatePartialImages(toolData.partial_images)\n return {\n name: 'image_generation',\n description: 'Generate images based on text descriptions',\n metadata: {\n ...toolData,\n },\n }\n}\n\nexport { validatePartialImages }\n"],"mappings":";AAUA,IAAM,yBAAyB,UAA8B;CAC3D,IAAI,UAAU,KAAA,MAAc,QAAQ,KAAK,QAAQ,IAC/C,MAAM,IAAI,MAAM,wCAAwC;AAE5D;;;;;;;;AASA,SAAgB,0CACd,MAC2B;CAE3B,OAAO;EACL,GAFe,KAAK;EAGpB,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,oBACd,UACM;CACN,sBAAsB,SAAS,cAAc;CAC7C,OAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU,EACR,GAAG,SACL;CACF;AACF"}
1
+ {"version":3,"file":"image-generation-tool.js","names":[],"sources":["../../../src/tools/image-generation-tool.ts"],"sourcesContent":["import {\n getOpenAIProviderToolMetadata,\n openAIProviderTool,\n} from './openai-provider-tool'\nimport type { Tool as SDKTool } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\ntype ImageGenerationToolConfig = SDKTool.ImageGeneration\n\nexport type { ImageGenerationToolConfig }\n\n/** @deprecated Renamed to `ImageGenerationToolConfig`. Will be removed in a future release. */\nexport type ImageGenerationTool = ImageGenerationToolConfig\n\nconst validatePartialImages = (value: number | undefined) => {\n if (value !== undefined && (value < 0 || value > 3)) {\n throw new Error('partial_images must be between 0 and 3')\n }\n}\n\n/**\n * Converts a standard Tool to OpenAI ImageGenerationTool format. Spread\n * `metadata` first, then force `type: 'image_generation'` last so a stray\n * `metadata.type` cannot shadow the wire discriminator.\n */\nexport function convertImageGenerationToolToAdapterFormat(\n tool: Tool,\n): ImageGenerationToolConfig {\n const metadata = getOpenAIProviderToolMetadata(tool) as Omit<\n ImageGenerationToolConfig,\n 'type'\n >\n return {\n ...metadata,\n type: 'image_generation',\n }\n}\n\n/**\n * Creates a standard Tool from ImageGenerationTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function imageGenerationTool(\n toolData: Omit<ImageGenerationToolConfig, 'type'>,\n): Tool {\n validatePartialImages(toolData.partial_images)\n return openAIProviderTool(\n {\n name: 'image_generation',\n description: 'Generate images based on text descriptions',\n metadata: {\n ...toolData,\n },\n },\n 'image_generation',\n )\n}\n\nexport { validatePartialImages }\n"],"mappings":";;AAcA,IAAM,yBAAyB,UAA8B;CAC3D,IAAI,UAAU,KAAA,MAAc,QAAQ,KAAK,QAAQ,IAC/C,MAAM,IAAI,MAAM,wCAAwC;AAE5D;;;;;;AAOA,SAAgB,0CACd,MAC2B;CAK3B,OAAO;EACL,GALe,8BAA8B,IAK1C;EACH,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,oBACd,UACM;CACN,sBAAsB,SAAS,cAAc;CAC7C,OAAO,mBACL;EACE,MAAM;EACN,aAAa;EACb,UAAU,EACR,GAAG,SACL;CACF,GACA,kBACF;AACF"}
@@ -0,0 +1,14 @@
1
+ import { applyPatchTool, convertApplyPatchToolToAdapterFormat } from "./apply-patch-tool.js";
2
+ import { codeInterpreterTool, convertCodeInterpreterToolToAdapterFormat } from "./code-interpreter-tool.js";
3
+ import { computerUseTool, convertComputerUseToolToAdapterFormat } from "./computer-use-tool.js";
4
+ import { convertCustomToolToAdapterFormat, customTool } from "./custom-tool.js";
5
+ import { convertFileSearchToolToAdapterFormat, fileSearchTool, validateMaxNumResults } from "./file-search-tool.js";
6
+ import { convertFunctionToolToAdapterFormat } from "./function-tool.js";
7
+ import { convertImageGenerationToolToAdapterFormat, imageGenerationTool, validatePartialImages } from "./image-generation-tool.js";
8
+ import { convertLocalShellToolToAdapterFormat, localShellTool } from "./local-shell-tool.js";
9
+ import { convertMCPToolToAdapterFormat, mcpTool, validateMCPtool } from "./mcp-tool.js";
10
+ import { convertShellToolToAdapterFormat, shellTool } from "./shell-tool.js";
11
+ import { convertWebSearchPreviewToolToAdapterFormat, webSearchPreviewTool } from "./web-search-preview-tool.js";
12
+ import { convertWebSearchToolToAdapterFormat, webSearchTool } from "./web-search-tool.js";
13
+ import { convertToolsToProviderFormat } from "./tool-converter.js";
14
+ export { applyPatchTool, codeInterpreterTool, computerUseTool, convertApplyPatchToolToAdapterFormat, convertCodeInterpreterToolToAdapterFormat, convertComputerUseToolToAdapterFormat, convertCustomToolToAdapterFormat, convertFileSearchToolToAdapterFormat, convertFunctionToolToAdapterFormat, convertImageGenerationToolToAdapterFormat, convertLocalShellToolToAdapterFormat, convertMCPToolToAdapterFormat, convertShellToolToAdapterFormat, convertToolsToProviderFormat, convertWebSearchPreviewToolToAdapterFormat, convertWebSearchToolToAdapterFormat, customTool, fileSearchTool, imageGenerationTool, localShellTool, mcpTool, shellTool, validateMCPtool, validateMaxNumResults, validatePartialImages, webSearchPreviewTool, webSearchTool };
@@ -1,3 +1,4 @@
1
+ import { openAIProviderTool } from "./openai-provider-tool.js";
1
2
  //#region src/tools/local-shell-tool.ts
2
3
  /**
3
4
  * Converts a standard Tool to OpenAI LocalShellTool format
@@ -12,11 +13,11 @@ function convertLocalShellToolToAdapterFormat(_tool) {
12
13
  * re-wrap this in their own package.
13
14
  */
14
15
  function localShellTool() {
15
- return {
16
+ return openAIProviderTool({
16
17
  name: "local_shell",
17
18
  description: "Execute local shell commands",
18
19
  metadata: {}
19
- };
20
+ }, "local_shell");
20
21
  }
21
22
  //#endregion
22
23
  export { convertLocalShellToolToAdapterFormat, localShellTool };
@@ -1 +1 @@
1
- {"version":3,"file":"local-shell-tool.js","names":[],"sources":["../../../src/tools/local-shell-tool.ts"],"sourcesContent":["import type { Tool as SDKTool } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\ntype LocalShellToolConfig = SDKTool.LocalShell\n\nexport type { LocalShellToolConfig }\n\n/** @deprecated Renamed to `LocalShellToolConfig`. Will be removed in a future release. */\nexport type LocalShellTool = LocalShellToolConfig\n\n/**\n * Converts a standard Tool to OpenAI LocalShellTool format\n */\nexport function convertLocalShellToolToAdapterFormat(\n _tool: Tool,\n): LocalShellToolConfig {\n return {\n type: 'local_shell',\n }\n}\n\n/**\n * Creates a standard Tool from LocalShellTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function localShellTool(): Tool {\n return {\n name: 'local_shell',\n description: 'Execute local shell commands',\n metadata: {},\n }\n}\n"],"mappings":";;;;AAaA,SAAgB,qCACd,OACsB;CACtB,OAAO,EACL,MAAM,cACR;AACF;;;;;;;AAQA,SAAgB,iBAAuB;CACrC,OAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU,CAAC;CACb;AACF"}
1
+ {"version":3,"file":"local-shell-tool.js","names":[],"sources":["../../../src/tools/local-shell-tool.ts"],"sourcesContent":["import { openAIProviderTool } from './openai-provider-tool'\nimport type { Tool as SDKTool } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\ntype LocalShellToolConfig = SDKTool.LocalShell\n\nexport type { LocalShellToolConfig }\n\n/** @deprecated Renamed to `LocalShellToolConfig`. Will be removed in a future release. */\nexport type LocalShellTool = LocalShellToolConfig\n\n/**\n * Converts a standard Tool to OpenAI LocalShellTool format\n */\nexport function convertLocalShellToolToAdapterFormat(\n _tool: Tool,\n): LocalShellToolConfig {\n return {\n type: 'local_shell',\n }\n}\n\n/**\n * Creates a standard Tool from LocalShellTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function localShellTool(): Tool {\n return openAIProviderTool(\n {\n name: 'local_shell',\n description: 'Execute local shell commands',\n metadata: {},\n },\n 'local_shell',\n )\n}\n"],"mappings":";;;;;AAcA,SAAgB,qCACd,OACsB;CACtB,OAAO,EACL,MAAM,cACR;AACF;;;;;;;AAQA,SAAgB,iBAAuB;CACrC,OAAO,mBACL;EACE,MAAM;EACN,aAAa;EACb,UAAU,CAAC;CACb,GACA,aACF;AACF"}
@@ -1,3 +1,4 @@
1
+ import { getOpenAIProviderToolMetadata, openAIProviderTool } from "./openai-provider-tool.js";
1
2
  //#region src/tools/mcp-tool.ts
2
3
  function validateMCPtool(tool) {
3
4
  if (!tool.server_url && !tool.connector_id) throw new Error("Either server_url or connector_id must be provided.");
@@ -7,12 +8,12 @@ function validateMCPtool(tool) {
7
8
  * Converts a standard Tool to OpenAI MCPTool format
8
9
  */
9
10
  function convertMCPToolToAdapterFormat(tool) {
10
- const mcpTool = {
11
- ...tool.metadata,
11
+ const convertedTool = {
12
+ ...getOpenAIProviderToolMetadata(tool),
12
13
  type: "mcp"
13
14
  };
14
- validateMCPtool(mcpTool);
15
- return mcpTool;
15
+ validateMCPtool(convertedTool);
16
+ return convertedTool;
16
17
  }
17
18
  /**
18
19
  * Creates a standard Tool from MCPTool parameters.
@@ -25,11 +26,11 @@ function mcpTool(toolData) {
25
26
  ...toolData,
26
27
  type: "mcp"
27
28
  });
28
- return {
29
+ return openAIProviderTool({
29
30
  name: "mcp",
30
31
  description: toolData.server_description || "",
31
32
  metadata: toolData
32
- };
33
+ }, "mcp");
33
34
  }
34
35
  //#endregion
35
36
  export { convertMCPToolToAdapterFormat, mcpTool, validateMCPtool };
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-tool.js","names":[],"sources":["../../../src/tools/mcp-tool.ts"],"sourcesContent":["import type { Tool as SDKTool } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\ntype MCPToolConfig = SDKTool.Mcp\n\nexport type { MCPToolConfig }\n\n/** @deprecated Renamed to `MCPToolConfig`. Will be removed in a future release. */\nexport type MCPTool = MCPToolConfig\n\nexport function validateMCPtool(tool: MCPToolConfig) {\n if (!tool.server_url && !tool.connector_id) {\n throw new Error('Either server_url or connector_id must be provided.')\n }\n if (tool.connector_id && tool.server_url) {\n throw new Error('Only one of server_url or connector_id can be provided.')\n }\n}\n\n/**\n * Converts a standard Tool to OpenAI MCPTool format\n */\nexport function convertMCPToolToAdapterFormat(tool: Tool): MCPToolConfig {\n const metadata = tool.metadata as Omit<MCPToolConfig, 'type'>\n\n const mcpTool: MCPToolConfig = {\n ...metadata,\n type: 'mcp',\n }\n\n validateMCPtool(mcpTool)\n return mcpTool\n}\n\n/**\n * Creates a standard Tool from MCPTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function mcpTool(toolData: Omit<MCPToolConfig, 'type'>): Tool {\n validateMCPtool({ ...toolData, type: 'mcp' })\n\n return {\n name: 'mcp',\n description: toolData.server_description || '',\n metadata: toolData,\n }\n}\n"],"mappings":";AAUA,SAAgB,gBAAgB,MAAqB;CACnD,IAAI,CAAC,KAAK,cAAc,CAAC,KAAK,cAC5B,MAAM,IAAI,MAAM,qDAAqD;CAEvE,IAAI,KAAK,gBAAgB,KAAK,YAC5B,MAAM,IAAI,MAAM,yDAAyD;AAE7E;;;;AAKA,SAAgB,8BAA8B,MAA2B;CAGvE,MAAM,UAAyB;EAC7B,GAHe,KAAK;EAIpB,MAAM;CACR;CAEA,gBAAgB,OAAO;CACvB,OAAO;AACT;;;;;;;AAQA,SAAgB,QAAQ,UAA6C;CACnE,gBAAgB;EAAE,GAAG;EAAU,MAAM;CAAM,CAAC;CAE5C,OAAO;EACL,MAAM;EACN,aAAa,SAAS,sBAAsB;EAC5C,UAAU;CACZ;AACF"}
1
+ {"version":3,"file":"mcp-tool.js","names":[],"sources":["../../../src/tools/mcp-tool.ts"],"sourcesContent":["import {\n getOpenAIProviderToolMetadata,\n openAIProviderTool,\n} from './openai-provider-tool'\nimport type { Tool as SDKTool } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\ntype MCPToolConfig = SDKTool.Mcp\n\nexport type { MCPToolConfig }\n\n/** @deprecated Renamed to `MCPToolConfig`. Will be removed in a future release. */\nexport type MCPTool = MCPToolConfig\n\nexport function validateMCPtool(tool: MCPToolConfig) {\n if (!tool.server_url && !tool.connector_id) {\n throw new Error('Either server_url or connector_id must be provided.')\n }\n if (tool.connector_id && tool.server_url) {\n throw new Error('Only one of server_url or connector_id can be provided.')\n }\n}\n\n/**\n * Converts a standard Tool to OpenAI MCPTool format\n */\nexport function convertMCPToolToAdapterFormat(tool: Tool): MCPToolConfig {\n const metadata = getOpenAIProviderToolMetadata(tool) as Omit<\n MCPToolConfig,\n 'type'\n >\n\n const convertedTool: MCPToolConfig = {\n ...metadata,\n type: 'mcp',\n }\n\n validateMCPtool(convertedTool)\n return convertedTool\n}\n\n/**\n * Creates a standard Tool from MCPTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function mcpTool(toolData: Omit<MCPToolConfig, 'type'>): Tool {\n validateMCPtool({ ...toolData, type: 'mcp' })\n\n return openAIProviderTool(\n {\n name: 'mcp',\n description: toolData.server_description || '',\n metadata: toolData,\n },\n 'mcp',\n )\n}\n"],"mappings":";;AAcA,SAAgB,gBAAgB,MAAqB;CACnD,IAAI,CAAC,KAAK,cAAc,CAAC,KAAK,cAC5B,MAAM,IAAI,MAAM,qDAAqD;CAEvE,IAAI,KAAK,gBAAgB,KAAK,YAC5B,MAAM,IAAI,MAAM,yDAAyD;AAE7E;;;;AAKA,SAAgB,8BAA8B,MAA2B;CAMvE,MAAM,gBAA+B;EACnC,GANe,8BAA8B,IAM1C;EACH,MAAM;CACR;CAEA,gBAAgB,aAAa;CAC7B,OAAO;AACT;;;;;;;AAQA,SAAgB,QAAQ,UAA6C;CACnE,gBAAgB;EAAE,GAAG;EAAU,MAAM;CAAM,CAAC;CAE5C,OAAO,mBACL;EACE,MAAM;EACN,aAAa,SAAS,sBAAsB;EAC5C,UAAU;CACZ,GACA,KACF;AACF"}
@@ -0,0 +1,20 @@
1
+ import { Tool } from '@tanstack/ai';
2
+ declare const OPENAI_PROVIDER_TOOL_KINDS: {
3
+ readonly apply_patch: "openai.apply_patch";
4
+ readonly code_interpreter: "openai.code_interpreter";
5
+ readonly computer_use: "openai.computer_use";
6
+ readonly custom: "openai.custom";
7
+ readonly file_search: "openai.file_search";
8
+ readonly image_generation: "openai.image_generation";
9
+ readonly local_shell: "openai.local_shell";
10
+ readonly mcp: "openai.mcp";
11
+ readonly shell: "openai.shell";
12
+ readonly web_search: "openai.web_search";
13
+ readonly web_search_preview: "openai.web_search_preview";
14
+ };
15
+ export type OpenAIProviderToolKind = keyof typeof OPENAI_PROVIDER_TOOL_KINDS;
16
+ export declare function openAIProviderTool(tool: Tool, toolKind: OpenAIProviderToolKind): Tool;
17
+ export declare function getOpenAIProviderToolKind(tool: Tool): OpenAIProviderToolKind | undefined;
18
+ /** Returns adapter metadata without the internal runtime discriminator. */
19
+ export declare function getOpenAIProviderToolMetadata(tool: Tool): Tool['metadata'];
20
+ export {};
@@ -0,0 +1,49 @@
1
+ //#region src/tools/openai-provider-tool.ts
2
+ var OPENAI_PROVIDER_TOOL_KINDS = {
3
+ apply_patch: "openai.apply_patch",
4
+ code_interpreter: "openai.code_interpreter",
5
+ computer_use: "openai.computer_use",
6
+ custom: "openai.custom",
7
+ file_search: "openai.file_search",
8
+ image_generation: "openai.image_generation",
9
+ local_shell: "openai.local_shell",
10
+ mcp: "openai.mcp",
11
+ shell: "openai.shell",
12
+ web_search: "openai.web_search",
13
+ web_search_preview: "openai.web_search_preview"
14
+ };
15
+ function openAIProviderTool(tool, toolKind) {
16
+ return {
17
+ ...tool,
18
+ metadata: {
19
+ ...tool.metadata,
20
+ __kind: OPENAI_PROVIDER_TOOL_KINDS[toolKind]
21
+ }
22
+ };
23
+ }
24
+ function getOpenAIProviderToolKind(tool) {
25
+ switch (tool.metadata?.["__kind"]) {
26
+ case "openai.apply_patch": return "apply_patch";
27
+ case "openai.code_interpreter": return "code_interpreter";
28
+ case "openai.computer_use": return "computer_use";
29
+ case "openai.custom": return "custom";
30
+ case "openai.file_search": return "file_search";
31
+ case "openai.image_generation": return "image_generation";
32
+ case "openai.local_shell": return "local_shell";
33
+ case "openai.mcp": return "mcp";
34
+ case "openai.shell": return "shell";
35
+ case "openai.web_search": return "web_search";
36
+ case "openai.web_search_preview": return "web_search_preview";
37
+ default: return;
38
+ }
39
+ }
40
+ /** Returns adapter metadata without the internal runtime discriminator. */
41
+ function getOpenAIProviderToolMetadata(tool) {
42
+ if (!tool.metadata) return;
43
+ const { __kind: _kind, ...metadata } = tool.metadata;
44
+ return metadata;
45
+ }
46
+ //#endregion
47
+ export { getOpenAIProviderToolKind, getOpenAIProviderToolMetadata, openAIProviderTool };
48
+
49
+ //# sourceMappingURL=openai-provider-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai-provider-tool.js","names":[],"sources":["../../../src/tools/openai-provider-tool.ts"],"sourcesContent":["import type { Tool } from '@tanstack/ai'\n\nconst OPENAI_PROVIDER_TOOL_KINDS = {\n apply_patch: 'openai.apply_patch',\n code_interpreter: 'openai.code_interpreter',\n computer_use: 'openai.computer_use',\n custom: 'openai.custom',\n file_search: 'openai.file_search',\n image_generation: 'openai.image_generation',\n local_shell: 'openai.local_shell',\n mcp: 'openai.mcp',\n shell: 'openai.shell',\n web_search: 'openai.web_search',\n web_search_preview: 'openai.web_search_preview',\n} as const\n\nexport type OpenAIProviderToolKind = keyof typeof OPENAI_PROVIDER_TOOL_KINDS\n\nexport function openAIProviderTool(\n tool: Tool,\n toolKind: OpenAIProviderToolKind,\n): Tool {\n return {\n ...tool,\n metadata: {\n ...tool.metadata,\n __kind: OPENAI_PROVIDER_TOOL_KINDS[toolKind],\n },\n }\n}\n\nexport function getOpenAIProviderToolKind(\n tool: Tool,\n): OpenAIProviderToolKind | undefined {\n const toolKind = tool.metadata?.['__kind']\n switch (toolKind) {\n case 'openai.apply_patch':\n return 'apply_patch'\n case 'openai.code_interpreter':\n return 'code_interpreter'\n case 'openai.computer_use':\n return 'computer_use'\n case 'openai.custom':\n return 'custom'\n case 'openai.file_search':\n return 'file_search'\n case 'openai.image_generation':\n return 'image_generation'\n case 'openai.local_shell':\n return 'local_shell'\n case 'openai.mcp':\n return 'mcp'\n case 'openai.shell':\n return 'shell'\n case 'openai.web_search':\n return 'web_search'\n case 'openai.web_search_preview':\n return 'web_search_preview'\n default:\n return undefined\n }\n}\n\n/** Returns adapter metadata without the internal runtime discriminator. */\nexport function getOpenAIProviderToolMetadata(tool: Tool): Tool['metadata'] {\n if (!tool.metadata) {\n return undefined\n }\n const { __kind: _kind, ...metadata } = tool.metadata\n void _kind\n return metadata\n}\n"],"mappings":";AAEA,IAAM,6BAA6B;CACjC,aAAa;CACb,kBAAkB;CAClB,cAAc;CACd,QAAQ;CACR,aAAa;CACb,kBAAkB;CAClB,aAAa;CACb,KAAK;CACL,OAAO;CACP,YAAY;CACZ,oBAAoB;AACtB;AAIA,SAAgB,mBACd,MACA,UACM;CACN,OAAO;EACL,GAAG;EACH,UAAU;GACR,GAAG,KAAK;GACR,QAAQ,2BAA2B;EACrC;CACF;AACF;AAEA,SAAgB,0BACd,MACoC;CAEpC,QADiB,KAAK,WAAW,WACjC;EACE,KAAK,sBACH,OAAO;EACT,KAAK,2BACH,OAAO;EACT,KAAK,uBACH,OAAO;EACT,KAAK,iBACH,OAAO;EACT,KAAK,sBACH,OAAO;EACT,KAAK,2BACH,OAAO;EACT,KAAK,sBACH,OAAO;EACT,KAAK,cACH,OAAO;EACT,KAAK,gBACH,OAAO;EACT,KAAK,qBACH,OAAO;EACT,KAAK,6BACH,OAAO;EACT,SACE;CACJ;AACF;;AAGA,SAAgB,8BAA8B,MAA8B;CAC1E,IAAI,CAAC,KAAK,UACR;CAEF,MAAM,EAAE,QAAQ,OAAO,GAAG,aAAa,KAAK;CAE5C,OAAO;AACT"}
@@ -1,10 +1,11 @@
1
+ import { getOpenAIProviderToolMetadata, openAIProviderTool } from "./openai-provider-tool.js";
1
2
  //#region src/tools/shell-tool.ts
2
3
  /**
3
4
  * Converts a standard Tool to OpenAI ShellTool format, preserving any
4
5
  * `environment` (container config + skills) stored in metadata.
5
6
  */
6
7
  function convertShellToolToAdapterFormat(tool) {
7
- const metadata = tool.metadata ?? {};
8
+ const metadata = getOpenAIProviderToolMetadata(tool) ?? {};
8
9
  return {
9
10
  type: "shell",
10
11
  ...metadata.environment !== void 0 && { environment: metadata.environment }
@@ -17,11 +18,11 @@ function convertShellToolToAdapterFormat(tool) {
17
18
  * re-wrap this in their own package.
18
19
  */
19
20
  function shellTool(config = {}) {
20
- return {
21
+ return openAIProviderTool({
21
22
  name: "shell",
22
23
  description: "Execute shell commands",
23
24
  metadata: { ...config.environment !== void 0 && { environment: config.environment } }
24
- };
25
+ }, "shell");
25
26
  }
26
27
  //#endregion
27
28
  export { convertShellToolToAdapterFormat, shellTool };
@@ -1 +1 @@
1
- {"version":3,"file":"shell-tool.js","names":[],"sources":["../../../src/tools/shell-tool.ts"],"sourcesContent":["import type { FunctionShellTool as ShellToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { ShellToolConfig }\n\n/** @deprecated Renamed to `ShellToolConfig`. Will be removed in a future release. */\nexport type ShellTool = ShellToolConfig\n\n/**\n * Config accepted by {@link shellTool}. `environment` mirrors the OpenAI\n * Responses API shell tool environment (e.g. `container_auto` + `skills`).\n * Typed via indexed access so it tracks the installed SDK without naming the\n * union members directly.\n */\nexport interface ShellToolFactoryConfig {\n environment?: NonNullable<ShellToolConfig['environment']>\n}\n\n/**\n * Converts a standard Tool to OpenAI ShellTool format, preserving any\n * `environment` (container config + skills) stored in metadata.\n */\nexport function convertShellToolToAdapterFormat(tool: Tool): ShellToolConfig {\n const metadata = (tool.metadata ?? {}) as ShellToolFactoryConfig\n return {\n type: 'shell',\n ...(metadata.environment !== undefined && {\n environment: metadata.environment,\n }),\n }\n}\n\n/**\n * Creates a standard Tool from ShellTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function shellTool(config: ShellToolFactoryConfig = {}): Tool {\n return {\n name: 'shell',\n description: 'Execute shell commands',\n metadata: {\n ...(config.environment !== undefined && {\n environment: config.environment,\n }),\n },\n }\n}\n"],"mappings":";;;;;AAsBA,SAAgB,gCAAgC,MAA6B;CAC3E,MAAM,WAAY,KAAK,YAAY,CAAC;CACpC,OAAO;EACL,MAAM;EACN,GAAI,SAAS,gBAAgB,KAAA,KAAa,EACxC,aAAa,SAAS,YACxB;CACF;AACF;;;;;;;AAQA,SAAgB,UAAU,SAAiC,CAAC,GAAS;CACnE,OAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU,EACR,GAAI,OAAO,gBAAgB,KAAA,KAAa,EACtC,aAAa,OAAO,YACtB,EACF;CACF;AACF"}
1
+ {"version":3,"file":"shell-tool.js","names":[],"sources":["../../../src/tools/shell-tool.ts"],"sourcesContent":["import {\n getOpenAIProviderToolMetadata,\n openAIProviderTool,\n} from './openai-provider-tool'\nimport type { FunctionShellTool as ShellToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { ShellToolConfig }\n\n/** @deprecated Renamed to `ShellToolConfig`. Will be removed in a future release. */\nexport type ShellTool = ShellToolConfig\n\n/**\n * Config accepted by {@link shellTool}. `environment` mirrors the OpenAI\n * Responses API shell tool environment (e.g. `container_auto` + `skills`).\n * Typed via indexed access so it tracks the installed SDK without naming the\n * union members directly.\n */\nexport interface ShellToolFactoryConfig {\n environment?: NonNullable<ShellToolConfig['environment']>\n}\n\n/**\n * Converts a standard Tool to OpenAI ShellTool format, preserving any\n * `environment` (container config + skills) stored in metadata.\n */\nexport function convertShellToolToAdapterFormat(tool: Tool): ShellToolConfig {\n const metadata = (getOpenAIProviderToolMetadata(tool) ??\n {}) as ShellToolFactoryConfig\n return {\n type: 'shell',\n ...(metadata.environment !== undefined && {\n environment: metadata.environment,\n }),\n }\n}\n\n/**\n * Creates a standard Tool from ShellTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function shellTool(config: ShellToolFactoryConfig = {}): Tool {\n return openAIProviderTool(\n {\n name: 'shell',\n description: 'Execute shell commands',\n metadata: {\n ...(config.environment !== undefined && {\n environment: config.environment,\n }),\n },\n },\n 'shell',\n )\n}\n"],"mappings":";;;;;;AA0BA,SAAgB,gCAAgC,MAA6B;CAC3E,MAAM,WAAY,8BAA8B,IAAI,KAClD,CAAC;CACH,OAAO;EACL,MAAM;EACN,GAAI,SAAS,gBAAgB,KAAA,KAAa,EACxC,aAAa,SAAS,YACxB;CACF;AACF;;;;;;;AAQA,SAAgB,UAAU,SAAiC,CAAC,GAAS;CACnE,OAAO,mBACL;EACE,MAAM;EACN,aAAa;EACb,UAAU,EACR,GAAI,OAAO,gBAAgB,KAAA,KAAa,EACtC,aAAa,OAAO,YACtB,EACF;CACF,GACA,OACF;AACF"}
@@ -1,3 +1,4 @@
1
+ import { getOpenAIProviderToolKind } from "./openai-provider-tool.js";
1
2
  import { convertApplyPatchToolToAdapterFormat } from "./apply-patch-tool.js";
2
3
  import { convertCodeInterpreterToolToAdapterFormat } from "./code-interpreter-tool.js";
3
4
  import { convertComputerUseToolToAdapterFormat } from "./computer-use-tool.js";
@@ -10,30 +11,19 @@ import { convertMCPToolToAdapterFormat } from "./mcp-tool.js";
10
11
  import { convertShellToolToAdapterFormat } from "./shell-tool.js";
11
12
  import { convertWebSearchPreviewToolToAdapterFormat } from "./web-search-preview-tool.js";
12
13
  import { convertWebSearchToolToAdapterFormat } from "./web-search-tool.js";
14
+ import { assertUniqueToolNames } from "@tanstack/ai/adapter-internals";
13
15
  //#region src/tools/tool-converter.ts
14
- var SPECIAL_TOOL_NAMES = /* @__PURE__ */ new Set([
15
- "apply_patch",
16
- "code_interpreter",
17
- "computer_use_preview",
18
- "file_search",
19
- "image_generation",
20
- "local_shell",
21
- "mcp",
22
- "shell",
23
- "web_search_preview",
24
- "web_search",
25
- "custom"
26
- ]);
27
16
  /**
28
17
  * Converts an array of standard Tools to OpenAI-specific format
29
18
  */
30
19
  function convertToolsToProviderFormat(tools) {
20
+ assertUniqueToolNames(tools);
31
21
  return tools.map((tool) => {
32
- const toolName = tool.name;
33
- if (SPECIAL_TOOL_NAMES.has(toolName)) switch (toolName) {
22
+ switch (getOpenAIProviderToolKind(tool)) {
34
23
  case "apply_patch": return convertApplyPatchToolToAdapterFormat(tool);
35
24
  case "code_interpreter": return convertCodeInterpreterToolToAdapterFormat(tool);
36
- case "computer_use_preview": return convertComputerUseToolToAdapterFormat(tool);
25
+ case "computer_use": return convertComputerUseToolToAdapterFormat(tool);
26
+ case "custom": return convertCustomToolToAdapterFormat(tool);
37
27
  case "file_search": return convertFileSearchToolToAdapterFormat(tool);
38
28
  case "image_generation": return convertImageGenerationToolToAdapterFormat(tool);
39
29
  case "local_shell": return convertLocalShellToolToAdapterFormat(tool);
@@ -41,9 +31,8 @@ function convertToolsToProviderFormat(tools) {
41
31
  case "shell": return convertShellToolToAdapterFormat(tool);
42
32
  case "web_search_preview": return convertWebSearchPreviewToolToAdapterFormat(tool);
43
33
  case "web_search": return convertWebSearchToolToAdapterFormat(tool);
44
- case "custom": return convertCustomToolToAdapterFormat(tool);
34
+ case void 0: return convertFunctionToolToAdapterFormat(tool);
45
35
  }
46
- return convertFunctionToolToAdapterFormat(tool);
47
36
  });
48
37
  }
49
38
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"tool-converter.js","names":[],"sources":["../../../src/tools/tool-converter.ts"],"sourcesContent":["import { convertApplyPatchToolToAdapterFormat } from './apply-patch-tool'\nimport { convertCodeInterpreterToolToAdapterFormat } from './code-interpreter-tool'\nimport { convertComputerUseToolToAdapterFormat } from './computer-use-tool'\nimport { convertCustomToolToAdapterFormat } from './custom-tool'\nimport { convertFileSearchToolToAdapterFormat } from './file-search-tool'\nimport { convertFunctionToolToAdapterFormat } from './function-tool'\nimport { convertImageGenerationToolToAdapterFormat } from './image-generation-tool'\nimport { convertLocalShellToolToAdapterFormat } from './local-shell-tool'\nimport { convertMCPToolToAdapterFormat } from './mcp-tool'\nimport { convertShellToolToAdapterFormat } from './shell-tool'\nimport { convertWebSearchPreviewToolToAdapterFormat } from './web-search-preview-tool'\nimport { convertWebSearchToolToAdapterFormat } from './web-search-tool'\nimport type { OpenAITool } from './index'\nimport type { Tool } from '@tanstack/ai'\n\nconst SPECIAL_TOOL_NAMES = new Set([\n 'apply_patch',\n 'code_interpreter',\n 'computer_use_preview',\n 'file_search',\n 'image_generation',\n 'local_shell',\n 'mcp',\n 'shell',\n 'web_search_preview',\n 'web_search',\n 'custom',\n])\n\n/**\n * Converts an array of standard Tools to OpenAI-specific format\n */\nexport function convertToolsToProviderFormat(\n tools: Array<Tool>,\n): Array<OpenAITool> {\n return tools.map((tool) => {\n const toolName = tool.name\n\n if (SPECIAL_TOOL_NAMES.has(toolName)) {\n switch (toolName) {\n case 'apply_patch':\n return convertApplyPatchToolToAdapterFormat(tool)\n case 'code_interpreter':\n return convertCodeInterpreterToolToAdapterFormat(tool)\n case 'computer_use_preview':\n return convertComputerUseToolToAdapterFormat(tool)\n case 'file_search':\n return convertFileSearchToolToAdapterFormat(tool)\n case 'image_generation':\n return convertImageGenerationToolToAdapterFormat(tool)\n case 'local_shell':\n return convertLocalShellToolToAdapterFormat(tool)\n case 'mcp':\n return convertMCPToolToAdapterFormat(tool)\n case 'shell':\n return convertShellToolToAdapterFormat(tool)\n case 'web_search_preview':\n return convertWebSearchPreviewToolToAdapterFormat(tool)\n case 'web_search':\n return convertWebSearchToolToAdapterFormat(tool)\n case 'custom':\n return convertCustomToolToAdapterFormat(tool)\n }\n }\n\n return convertFunctionToolToAdapterFormat(tool)\n })\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,IAAM,qCAAqB,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;;;;AAKD,SAAgB,6BACd,OACmB;CACnB,OAAO,MAAM,KAAK,SAAS;EACzB,MAAM,WAAW,KAAK;EAEtB,IAAI,mBAAmB,IAAI,QAAQ,GACjC,QAAQ,UAAR;GACE,KAAK,eACH,OAAO,qCAAqC,IAAI;GAClD,KAAK,oBACH,OAAO,0CAA0C,IAAI;GACvD,KAAK,wBACH,OAAO,sCAAsC,IAAI;GACnD,KAAK,eACH,OAAO,qCAAqC,IAAI;GAClD,KAAK,oBACH,OAAO,0CAA0C,IAAI;GACvD,KAAK,eACH,OAAO,qCAAqC,IAAI;GAClD,KAAK,OACH,OAAO,8BAA8B,IAAI;GAC3C,KAAK,SACH,OAAO,gCAAgC,IAAI;GAC7C,KAAK,sBACH,OAAO,2CAA2C,IAAI;GACxD,KAAK,cACH,OAAO,oCAAoC,IAAI;GACjD,KAAK,UACH,OAAO,iCAAiC,IAAI;EAChD;EAGF,OAAO,mCAAmC,IAAI;CAChD,CAAC;AACH"}
1
+ {"version":3,"file":"tool-converter.js","names":[],"sources":["../../../src/tools/tool-converter.ts"],"sourcesContent":["import { convertApplyPatchToolToAdapterFormat } from './apply-patch-tool'\nimport { convertCodeInterpreterToolToAdapterFormat } from './code-interpreter-tool'\nimport { convertComputerUseToolToAdapterFormat } from './computer-use-tool'\nimport { convertCustomToolToAdapterFormat } from './custom-tool'\nimport { convertFileSearchToolToAdapterFormat } from './file-search-tool'\nimport { convertFunctionToolToAdapterFormat } from './function-tool'\nimport { convertImageGenerationToolToAdapterFormat } from './image-generation-tool'\nimport { convertLocalShellToolToAdapterFormat } from './local-shell-tool'\nimport { convertMCPToolToAdapterFormat } from './mcp-tool'\nimport { getOpenAIProviderToolKind } from './openai-provider-tool'\nimport { convertShellToolToAdapterFormat } from './shell-tool'\nimport { convertWebSearchPreviewToolToAdapterFormat } from './web-search-preview-tool'\nimport { convertWebSearchToolToAdapterFormat } from './web-search-tool'\nimport type { OpenAITool } from './index'\nimport { assertUniqueToolNames } from '@tanstack/ai/adapter-internals'\nimport type { Tool } from '@tanstack/ai'\n\n/**\n * Converts an array of standard Tools to OpenAI-specific format\n */\nexport function convertToolsToProviderFormat(\n tools: Array<Tool>,\n): Array<OpenAITool> {\n assertUniqueToolNames(tools)\n return tools.map((tool) => {\n switch (getOpenAIProviderToolKind(tool)) {\n case 'apply_patch':\n return convertApplyPatchToolToAdapterFormat(tool)\n case 'code_interpreter':\n return convertCodeInterpreterToolToAdapterFormat(tool)\n case 'computer_use':\n return convertComputerUseToolToAdapterFormat(tool)\n case 'custom':\n return convertCustomToolToAdapterFormat(tool)\n case 'file_search':\n return convertFileSearchToolToAdapterFormat(tool)\n case 'image_generation':\n return convertImageGenerationToolToAdapterFormat(tool)\n case 'local_shell':\n return convertLocalShellToolToAdapterFormat(tool)\n case 'mcp':\n return convertMCPToolToAdapterFormat(tool)\n case 'shell':\n return convertShellToolToAdapterFormat(tool)\n case 'web_search_preview':\n return convertWebSearchPreviewToolToAdapterFormat(tool)\n case 'web_search':\n return convertWebSearchToolToAdapterFormat(tool)\n case undefined:\n return convertFunctionToolToAdapterFormat(tool)\n }\n })\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,SAAgB,6BACd,OACmB;CACnB,sBAAsB,KAAK;CAC3B,OAAO,MAAM,KAAK,SAAS;EACzB,QAAQ,0BAA0B,IAAI,GAAtC;GACE,KAAK,eACH,OAAO,qCAAqC,IAAI;GAClD,KAAK,oBACH,OAAO,0CAA0C,IAAI;GACvD,KAAK,gBACH,OAAO,sCAAsC,IAAI;GACnD,KAAK,UACH,OAAO,iCAAiC,IAAI;GAC9C,KAAK,eACH,OAAO,qCAAqC,IAAI;GAClD,KAAK,oBACH,OAAO,0CAA0C,IAAI;GACvD,KAAK,eACH,OAAO,qCAAqC,IAAI;GAClD,KAAK,OACH,OAAO,8BAA8B,IAAI;GAC3C,KAAK,SACH,OAAO,gCAAgC,IAAI;GAC7C,KAAK,sBACH,OAAO,2CAA2C,IAAI;GACxD,KAAK,cACH,OAAO,oCAAoC,IAAI;GACjD,KAAK,KAAA,GACH,OAAO,mCAAmC,IAAI;EAClD;CACF,CAAC;AACH"}
@@ -6,8 +6,7 @@ export type WebSearchPreviewTool = WebSearchPreviewToolConfig;
6
6
  /**
7
7
  * Converts a standard Tool to OpenAI WebSearchPreviewTool format. Force the
8
8
  * literal `type: 'web_search_preview'` instead of trusting `metadata.type`,
9
- * since a hand-authored tool with a missing or wrong `type` would emit a
10
- * malformed payload while the dispatcher already routed by `tool.name`.
9
+ * so a missing or wrong metadata type cannot produce a malformed payload.
11
10
  */
12
11
  export declare function convertWebSearchPreviewToolToAdapterFormat(tool: Tool): WebSearchPreviewToolConfig;
13
12
  /**
@@ -1,13 +1,13 @@
1
+ import { getOpenAIProviderToolMetadata, openAIProviderTool } from "./openai-provider-tool.js";
1
2
  //#region src/tools/web-search-preview-tool.ts
2
3
  /**
3
4
  * Converts a standard Tool to OpenAI WebSearchPreviewTool format. Force the
4
5
  * literal `type: 'web_search_preview'` instead of trusting `metadata.type`,
5
- * since a hand-authored tool with a missing or wrong `type` would emit a
6
- * malformed payload while the dispatcher already routed by `tool.name`.
6
+ * so a missing or wrong metadata type cannot produce a malformed payload.
7
7
  */
8
8
  function convertWebSearchPreviewToolToAdapterFormat(tool) {
9
9
  return {
10
- ...tool.metadata,
10
+ ...getOpenAIProviderToolMetadata(tool),
11
11
  type: "web_search_preview"
12
12
  };
13
13
  }
@@ -18,11 +18,11 @@ function convertWebSearchPreviewToolToAdapterFormat(tool) {
18
18
  * re-wrap this in their own package.
19
19
  */
20
20
  function webSearchPreviewTool(toolData) {
21
- return {
21
+ return openAIProviderTool({
22
22
  name: "web_search_preview",
23
23
  description: "Search the web (preview version)",
24
24
  metadata: toolData
25
- };
25
+ }, "web_search_preview");
26
26
  }
27
27
  //#endregion
28
28
  export { convertWebSearchPreviewToolToAdapterFormat, webSearchPreviewTool };
@@ -1 +1 @@
1
- {"version":3,"file":"web-search-preview-tool.js","names":[],"sources":["../../../src/tools/web-search-preview-tool.ts"],"sourcesContent":["import type { WebSearchPreviewTool as WebSearchPreviewToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { WebSearchPreviewToolConfig }\n\n/** @deprecated Renamed to `WebSearchPreviewToolConfig`. Will be removed in a future release. */\nexport type WebSearchPreviewTool = WebSearchPreviewToolConfig\n\n/**\n * Converts a standard Tool to OpenAI WebSearchPreviewTool format. Force the\n * literal `type: 'web_search_preview'` instead of trusting `metadata.type`,\n * since a hand-authored tool with a missing or wrong `type` would emit a\n * malformed payload while the dispatcher already routed by `tool.name`.\n */\nexport function convertWebSearchPreviewToolToAdapterFormat(\n tool: Tool,\n): WebSearchPreviewToolConfig {\n const metadata = tool.metadata as Omit<WebSearchPreviewToolConfig, 'type'>\n return {\n ...metadata,\n type: 'web_search_preview',\n }\n}\n\n/**\n * Creates a standard Tool from WebSearchPreviewTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function webSearchPreviewTool(\n toolData: WebSearchPreviewToolConfig,\n): Tool {\n return {\n name: 'web_search_preview',\n description: 'Search the web (preview version)',\n metadata: toolData,\n }\n}\n"],"mappings":";;;;;;;AAcA,SAAgB,2CACd,MAC4B;CAE5B,OAAO;EACL,GAFe,KAAK;EAGpB,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,qBACd,UACM;CACN,OAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU;CACZ;AACF"}
1
+ {"version":3,"file":"web-search-preview-tool.js","names":[],"sources":["../../../src/tools/web-search-preview-tool.ts"],"sourcesContent":["import {\n getOpenAIProviderToolMetadata,\n openAIProviderTool,\n} from './openai-provider-tool'\nimport type { WebSearchPreviewTool as WebSearchPreviewToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { WebSearchPreviewToolConfig }\n\n/** @deprecated Renamed to `WebSearchPreviewToolConfig`. Will be removed in a future release. */\nexport type WebSearchPreviewTool = WebSearchPreviewToolConfig\n\n/**\n * Converts a standard Tool to OpenAI WebSearchPreviewTool format. Force the\n * literal `type: 'web_search_preview'` instead of trusting `metadata.type`,\n * so a missing or wrong metadata type cannot produce a malformed payload.\n */\nexport function convertWebSearchPreviewToolToAdapterFormat(\n tool: Tool,\n): WebSearchPreviewToolConfig {\n const metadata = getOpenAIProviderToolMetadata(tool) as Omit<\n WebSearchPreviewToolConfig,\n 'type'\n >\n return {\n ...metadata,\n type: 'web_search_preview',\n }\n}\n\n/**\n * Creates a standard Tool from WebSearchPreviewTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function webSearchPreviewTool(\n toolData: WebSearchPreviewToolConfig,\n): Tool {\n return openAIProviderTool(\n {\n name: 'web_search_preview',\n description: 'Search the web (preview version)',\n metadata: toolData,\n },\n 'web_search_preview',\n )\n}\n"],"mappings":";;;;;;;AAiBA,SAAgB,2CACd,MAC4B;CAK5B,OAAO;EACL,GALe,8BAA8B,IAK1C;EACH,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,qBACd,UACM;CACN,OAAO,mBACL;EACE,MAAM;EACN,aAAa;EACb,UAAU;CACZ,GACA,oBACF;AACF"}
@@ -5,10 +5,8 @@ export type { WebSearchToolConfig };
5
5
  export type WebSearchTool = WebSearchToolConfig;
6
6
  /**
7
7
  * Converts a standard Tool to OpenAI WebSearchTool format. Spread `metadata`
8
- * first, then force `type: 'web_search'` last to keep the runtime `type`
9
- * matching the discriminator the dispatcher routed by — otherwise a tool
10
- * authored by hand with a different `metadata.type` would emit a malformed
11
- * payload.
8
+ * first, then force `type: 'web_search'` last so a different metadata type
9
+ * cannot produce a malformed payload.
12
10
  */
13
11
  export declare function convertWebSearchToolToAdapterFormat(tool: Tool): WebSearchToolConfig;
14
12
  /**
@@ -1,14 +1,13 @@
1
+ import { getOpenAIProviderToolMetadata, openAIProviderTool } from "./openai-provider-tool.js";
1
2
  //#region src/tools/web-search-tool.ts
2
3
  /**
3
4
  * Converts a standard Tool to OpenAI WebSearchTool format. Spread `metadata`
4
- * first, then force `type: 'web_search'` last to keep the runtime `type`
5
- * matching the discriminator the dispatcher routed by — otherwise a tool
6
- * authored by hand with a different `metadata.type` would emit a malformed
7
- * payload.
5
+ * first, then force `type: 'web_search'` last so a different metadata type
6
+ * cannot produce a malformed payload.
8
7
  */
9
8
  function convertWebSearchToolToAdapterFormat(tool) {
10
9
  return {
11
- ...tool.metadata,
10
+ ...getOpenAIProviderToolMetadata(tool),
12
11
  type: "web_search"
13
12
  };
14
13
  }
@@ -19,11 +18,11 @@ function convertWebSearchToolToAdapterFormat(tool) {
19
18
  * re-wrap this in their own package.
20
19
  */
21
20
  function webSearchTool(toolData) {
22
- return {
21
+ return openAIProviderTool({
23
22
  name: "web_search",
24
23
  description: "Search the web",
25
24
  metadata: toolData
26
- };
25
+ }, "web_search");
27
26
  }
28
27
  //#endregion
29
28
  export { convertWebSearchToolToAdapterFormat, webSearchTool };
@@ -1 +1 @@
1
- {"version":3,"file":"web-search-tool.js","names":[],"sources":["../../../src/tools/web-search-tool.ts"],"sourcesContent":["import type { WebSearchTool as WebSearchToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { WebSearchToolConfig }\n\n/** @deprecated Renamed to `WebSearchToolConfig`. Will be removed in a future release. */\nexport type WebSearchTool = WebSearchToolConfig\n\n/**\n * Converts a standard Tool to OpenAI WebSearchTool format. Spread `metadata`\n * first, then force `type: 'web_search'` last to keep the runtime `type`\n * matching the discriminator the dispatcher routed by — otherwise a tool\n * authored by hand with a different `metadata.type` would emit a malformed\n * payload.\n */\nexport function convertWebSearchToolToAdapterFormat(\n tool: Tool,\n): WebSearchToolConfig {\n const metadata = tool.metadata as Omit<WebSearchToolConfig, 'type'>\n return {\n ...metadata,\n type: 'web_search',\n }\n}\n\n/**\n * Creates a standard Tool from WebSearchTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function webSearchTool(toolData: WebSearchToolConfig): Tool {\n return {\n name: 'web_search',\n description: 'Search the web',\n metadata: toolData,\n }\n}\n"],"mappings":";;;;;;;;AAeA,SAAgB,oCACd,MACqB;CAErB,OAAO;EACL,GAFe,KAAK;EAGpB,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,cAAc,UAAqC;CACjE,OAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU;CACZ;AACF"}
1
+ {"version":3,"file":"web-search-tool.js","names":[],"sources":["../../../src/tools/web-search-tool.ts"],"sourcesContent":["import {\n getOpenAIProviderToolMetadata,\n openAIProviderTool,\n} from './openai-provider-tool'\nimport type { WebSearchTool as WebSearchToolConfig } from 'openai/resources/responses/responses'\nimport type { Tool } from '@tanstack/ai'\n\nexport type { WebSearchToolConfig }\n\n/** @deprecated Renamed to `WebSearchToolConfig`. Will be removed in a future release. */\nexport type WebSearchTool = WebSearchToolConfig\n\n/**\n * Converts a standard Tool to OpenAI WebSearchTool format. Spread `metadata`\n * first, then force `type: 'web_search'` last so a different metadata type\n * cannot produce a malformed payload.\n */\nexport function convertWebSearchToolToAdapterFormat(\n tool: Tool,\n): WebSearchToolConfig {\n const metadata = getOpenAIProviderToolMetadata(tool) as Omit<\n WebSearchToolConfig,\n 'type'\n >\n return {\n ...metadata,\n type: 'web_search',\n }\n}\n\n/**\n * Creates a standard Tool from WebSearchTool parameters.\n *\n * Base (non-branded) factory. Providers that need branded return types should\n * re-wrap this in their own package.\n */\nexport function webSearchTool(toolData: WebSearchToolConfig): Tool {\n return openAIProviderTool(\n {\n name: 'web_search',\n description: 'Search the web',\n metadata: toolData,\n },\n 'web_search',\n )\n}\n"],"mappings":";;;;;;;AAiBA,SAAgB,oCACd,MACqB;CAKrB,OAAO;EACL,GALe,8BAA8B,IAK1C;EACH,MAAM;CACR;AACF;;;;;;;AAQA,SAAgB,cAAc,UAAqC;CACjE,OAAO,mBACL;EACE,MAAM;EACN,aAAa;EACb,UAAU;CACZ,GACA,YACF;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/openai-base",
3
- "version": "0.9.13",
3
+ "version": "0.9.15",
4
4
  "description": "Shared OpenAI SDK base adapters for TanStack AI providers using Chat Completions and Responses APIs.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -47,13 +47,13 @@
47
47
  "@tanstack/ai-utils": "^0.4.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "@tanstack/ai": "^0.45.0"
50
+ "@tanstack/ai": "^0.46.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@vitest/coverage-v8": "4.1.10",
54
54
  "vite": "^8.2.1",
55
55
  "zod": "^4.2.0",
56
- "@tanstack/ai": "0.45.0"
56
+ "@tanstack/ai": "0.46.0"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "vite build",
@@ -115,6 +115,53 @@ export abstract class OpenAIBaseChatCompletionsTextAdapter<
115
115
  }
116
116
  }
117
117
 
118
+ const rejectedToolCall = this.extractRejectedToolCall(
119
+ rawEvent,
120
+ errorPayload.message,
121
+ )
122
+ if (rejectedToolCall) {
123
+ const toolCallId = generateId(this.name)
124
+ yield {
125
+ type: EventType.TOOL_CALL_START,
126
+ toolCallId,
127
+ toolCallName: rejectedToolCall.toolName,
128
+ toolName: rejectedToolCall.toolName,
129
+ parentMessageId: aguiState.messageId,
130
+ model: options.model,
131
+ timestamp: Date.now(),
132
+ }
133
+ yield {
134
+ type: EventType.TOOL_CALL_ARGS,
135
+ toolCallId,
136
+ delta: rejectedToolCall.arguments,
137
+ args: rejectedToolCall.arguments,
138
+ model: options.model,
139
+ timestamp: Date.now(),
140
+ }
141
+ yield {
142
+ type: EventType.TOOL_CALL_END,
143
+ toolCallId,
144
+ toolCallName: rejectedToolCall.toolName,
145
+ toolName: rejectedToolCall.toolName,
146
+ ...(rejectedToolCall.input !== undefined && {
147
+ input: rejectedToolCall.input,
148
+ }),
149
+ result: JSON.stringify({ error: rejectedToolCall.error }),
150
+ state: 'output-error',
151
+ model: options.model,
152
+ timestamp: Date.now(),
153
+ }
154
+ yield {
155
+ type: EventType.RUN_FINISHED,
156
+ runId: aguiState.runId,
157
+ threadId: aguiState.threadId,
158
+ model: options.model,
159
+ timestamp: Date.now(),
160
+ finishReason: 'tool_calls',
161
+ }
162
+ return
163
+ }
164
+
118
165
  // Emit AG-UI RUN_ERROR. Conditional `code` spread keeps the wire
119
166
  // shape spec-compliant under `exactOptionalPropertyTypes`: AG-UI's
120
167
  // `RunErrorEvent.code` is `string?` (absent vs explicit `undefined`
@@ -142,6 +189,24 @@ export abstract class OpenAIBaseChatCompletionsTextAdapter<
142
189
  }
143
190
  }
144
191
 
192
+ /**
193
+ * Extracts a rejected tool call from a provider error. Returned calls are
194
+ * emitted as non-executable `output-error` results so the model can repair them.
195
+ */
196
+ protected extractRejectedToolCall(
197
+ _rawEvent: unknown,
198
+ _fallbackMessage: string,
199
+ ):
200
+ | {
201
+ toolName: string
202
+ arguments: string
203
+ input?: unknown
204
+ error: string
205
+ }
206
+ | undefined {
207
+ return undefined
208
+ }
209
+
145
210
  /**
146
211
  * Generate structured output using the provider's JSON Schema response format.
147
212
  * Uses stream: false to get the complete response in one call.