@langchain/openai 0.6.5 → 0.6.6

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.
@@ -19,17 +19,8 @@ const openai_js_1 = require("./utils/openai.cjs");
19
19
  const openai_format_fndef_js_1 = require("./utils/openai-format-fndef.cjs");
20
20
  const tools_js_1 = require("./utils/tools.cjs");
21
21
  const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
22
- function isBuiltInTool(tool) {
23
- return "type" in tool && tool.type !== "function";
24
- }
25
- function isBuiltInToolChoice(tool_choice) {
26
- return (tool_choice != null &&
27
- typeof tool_choice === "object" &&
28
- "type" in tool_choice &&
29
- tool_choice.type !== "function");
30
- }
31
22
  function isReasoningModel(model) {
32
- return model && /^o\d/.test(model);
23
+ return model && (/^o\d/.test(model) || model.startsWith("gpt-5"));
33
24
  }
34
25
  function isStructuredOutputMethodParams(x
35
26
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -327,6 +318,8 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
327
318
  "disableStreaming",
328
319
  "zdrEnabled",
329
320
  "reasoning",
321
+ "verbosity",
322
+ "promptCacheKey",
330
323
  ];
331
324
  }
332
325
  getLsParams(options) {
@@ -545,6 +538,17 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
545
538
  writable: true,
546
539
  value: void 0
547
540
  });
541
+ /**
542
+ * Used by OpenAI to cache responses for similar requests to optimize your cache
543
+ * hit rates.
544
+ * [Learn more](https://platform.openai.com/docs/guides/prompt-caching).
545
+ */
546
+ Object.defineProperty(this, "promptCacheKey", {
547
+ enumerable: true,
548
+ configurable: true,
549
+ writable: true,
550
+ value: void 0
551
+ });
548
552
  Object.defineProperty(this, "defaultOptions", {
549
553
  enumerable: true,
550
554
  configurable: true,
@@ -584,6 +588,7 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
584
588
  this.reasoning = fields?.reasoning;
585
589
  this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
586
590
  this.disableStreaming = fields?.disableStreaming ?? this.disableStreaming;
591
+ this.promptCacheKey = fields?.promptCacheKey ?? this.promptCacheKey;
587
592
  this.streaming = fields?.streaming ?? false;
588
593
  if (this.disableStreaming)
589
594
  this.streaming = false;
@@ -677,6 +682,9 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
677
682
  }
678
683
  // TODO: move to completions class
679
684
  _convertChatOpenAIToolToCompletionsTool(tool, fields) {
685
+ if ((0, tools_js_1.isCustomTool)(tool)) {
686
+ return (0, tools_js_1.convertResponsesCustomTool)(tool.metadata.customTool);
687
+ }
680
688
  if ((0, base_1.isOpenAITool)(tool)) {
681
689
  if (fields?.strict !== undefined) {
682
690
  return {
@@ -700,7 +708,7 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
700
708
  strict = this.supportsStrictToolCalling;
701
709
  }
702
710
  return this.withConfig({
703
- tools: tools.map((tool) => isBuiltInTool(tool)
711
+ tools: tools.map((tool) => (0, tools_js_1.isBuiltInTool)(tool)
704
712
  ? tool
705
713
  : this._convertChatOpenAIToolToCompletionsTool(tool, { strict })),
706
714
  ...kwargs,
@@ -1036,7 +1044,7 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1036
1044
  strict,
1037
1045
  })
1038
1046
  : undefined,
1039
- tool_choice: isBuiltInToolChoice(options?.tool_choice)
1047
+ tool_choice: (0, tools_js_1.isBuiltInToolChoice)(options?.tool_choice)
1040
1048
  ? options?.tool_choice
1041
1049
  : (() => {
1042
1050
  const formatted = (0, openai_js_1.formatToOpenAIToolChoice)(options?.tool_choice);
@@ -1082,6 +1090,7 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1082
1090
  })(),
1083
1091
  parallel_tool_calls: options?.parallel_tool_calls,
1084
1092
  max_output_tokens: this.maxTokens === -1 ? undefined : this.maxTokens,
1093
+ prompt_cache_key: options?.promptCacheKey ?? this.promptCacheKey,
1085
1094
  ...(this.zdrEnabled ? { store: false } : {}),
1086
1095
  ...this.modelKwargs,
1087
1096
  };
@@ -1244,6 +1253,15 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1244
1253
  else if (item.type === "reasoning") {
1245
1254
  additional_kwargs.reasoning = item;
1246
1255
  }
1256
+ else if (item.type === "custom_tool_call") {
1257
+ const parsed = (0, tools_js_1.parseCustomToolCall)(item);
1258
+ if (parsed) {
1259
+ tool_calls.push(parsed);
1260
+ }
1261
+ else {
1262
+ invalid_tool_calls.push((0, openai_tools_1.makeInvalidToolCall)(item, "Malformed custom tool call"));
1263
+ }
1264
+ }
1247
1265
  else {
1248
1266
  additional_kwargs.tool_outputs ??= [];
1249
1267
  additional_kwargs.tool_outputs.push(item);
@@ -1310,6 +1328,7 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1310
1328
  "mcp_list_tools",
1311
1329
  "mcp_approval_request",
1312
1330
  "image_generation_call",
1331
+ "custom_tool_call",
1313
1332
  ].includes(chunk.item.type)) {
1314
1333
  additional_kwargs.tool_outputs = [chunk.item];
1315
1334
  }
@@ -1451,6 +1470,14 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1451
1470
  call_id: toolMessage.tool_call_id,
1452
1471
  };
1453
1472
  }
1473
+ // Handle custom tool output
1474
+ if (toolMessage.metadata?.customTool) {
1475
+ return {
1476
+ type: "custom_tool_call_output",
1477
+ call_id: toolMessage.tool_call_id,
1478
+ output: toolMessage.content,
1479
+ };
1480
+ }
1454
1481
  return {
1455
1482
  type: "function_call_output",
1456
1483
  call_id: toolMessage.tool_call_id,
@@ -1489,41 +1516,54 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1489
1516
  { type: "refusal", refusal: additional_kwargs.refusal },
1490
1517
  ];
1491
1518
  }
1492
- input.push({
1493
- type: "message",
1494
- role: "assistant",
1495
- ...(lcMsg.id && !this.zdrEnabled && lcMsg.id.startsWith("msg_")
1496
- ? { id: lcMsg.id }
1497
- : {}),
1498
- content: typeof content === "string"
1499
- ? content
1500
- : content.flatMap((item) => {
1501
- if (item.type === "text") {
1502
- return {
1503
- type: "output_text",
1504
- text: item.text,
1505
- // @ts-expect-error TODO: add types for `annotations`
1506
- annotations: item.annotations ?? [],
1507
- };
1508
- }
1509
- if (item.type === "output_text" ||
1510
- item.type === "refusal") {
1511
- return item;
1512
- }
1513
- return [];
1514
- }),
1515
- });
1519
+ if (typeof content === "string" || content.length > 0) {
1520
+ input.push({
1521
+ type: "message",
1522
+ role: "assistant",
1523
+ ...(lcMsg.id && !this.zdrEnabled && lcMsg.id.startsWith("msg_")
1524
+ ? { id: lcMsg.id }
1525
+ : {}),
1526
+ content: typeof content === "string"
1527
+ ? content
1528
+ : content.flatMap((item) => {
1529
+ if (item.type === "text") {
1530
+ return {
1531
+ type: "output_text",
1532
+ text: item.text,
1533
+ // @ts-expect-error TODO: add types for `annotations`
1534
+ annotations: item.annotations ?? [],
1535
+ };
1536
+ }
1537
+ if (item.type === "output_text" ||
1538
+ item.type === "refusal") {
1539
+ return item;
1540
+ }
1541
+ return [];
1542
+ }),
1543
+ });
1544
+ }
1516
1545
  const functionCallIds = additional_kwargs?.[_FUNCTION_CALL_IDS_MAP_KEY];
1517
1546
  if ((0, messages_1.isAIMessage)(lcMsg) && !!lcMsg.tool_calls?.length) {
1518
- input.push(...lcMsg.tool_calls.map((toolCall) => ({
1519
- type: "function_call",
1520
- name: toolCall.name,
1521
- arguments: JSON.stringify(toolCall.args),
1522
- call_id: toolCall.id,
1523
- ...(this.zdrEnabled
1524
- ? { id: functionCallIds?.[toolCall.id] }
1525
- : {}),
1526
- })));
1547
+ input.push(...lcMsg.tool_calls.map((toolCall) => {
1548
+ if ((0, tools_js_1.isCustomToolCall)(toolCall)) {
1549
+ return {
1550
+ type: "custom_tool_call",
1551
+ id: toolCall.call_id,
1552
+ call_id: toolCall.id ?? "",
1553
+ input: toolCall.args.input,
1554
+ name: toolCall.name,
1555
+ };
1556
+ }
1557
+ return {
1558
+ type: "function_call",
1559
+ name: toolCall.name,
1560
+ arguments: JSON.stringify(toolCall.args),
1561
+ call_id: toolCall.id,
1562
+ ...(this.zdrEnabled
1563
+ ? { id: functionCallIds?.[toolCall.id] }
1564
+ : {}),
1565
+ };
1566
+ }));
1527
1567
  }
1528
1568
  else if (additional_kwargs?.tool_calls) {
1529
1569
  input.push(...additional_kwargs.tool_calls.map((toolCall) => ({
@@ -1626,7 +1666,7 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1626
1666
  _reduceChatOpenAITools(tools, fields) {
1627
1667
  const reducedTools = [];
1628
1668
  for (const tool of tools) {
1629
- if (isBuiltInTool(tool)) {
1669
+ if ((0, tools_js_1.isBuiltInTool)(tool)) {
1630
1670
  if (tool.type === "image_generation" && fields?.stream) {
1631
1671
  // OpenAI sends a 400 error if partial_images is not set and we want to stream.
1632
1672
  // We also set it to 1 since we don't support partial images yet.
@@ -1643,6 +1683,9 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1643
1683
  strict: fields?.strict ?? null,
1644
1684
  });
1645
1685
  }
1686
+ else if ((0, tools_js_1.isOpenAICustomTool)(tool)) {
1687
+ reducedTools.push((0, tools_js_1.convertCompletionsCustomTool)(tool));
1688
+ }
1646
1689
  }
1647
1690
  return reducedTools;
1648
1691
  }
@@ -1700,6 +1743,7 @@ class ChatOpenAICompletions extends BaseChatOpenAI {
1700
1743
  ? { modalities: this.modalities || options?.modalities }
1701
1744
  : {}),
1702
1745
  ...this.modelKwargs,
1746
+ prompt_cache_key: options?.promptCacheKey ?? this.promptCacheKey,
1703
1747
  };
1704
1748
  if (options?.prediction !== undefined) {
1705
1749
  params.prediction = options.prediction;
@@ -1947,6 +1991,7 @@ class ChatOpenAICompletions extends BaseChatOpenAI {
1947
1991
  return await this.client.chat.completions.parse(request, clientOptions);
1948
1992
  }
1949
1993
  else {
1994
+ console.log("request", request);
1950
1995
  return await this.client.chat.completions.create(request, clientOptions);
1951
1996
  }
1952
1997
  }
@@ -2669,14 +2714,18 @@ class ChatOpenAI extends BaseChatOpenAI {
2669
2714
  this.completions = fields?.completions ?? new ChatOpenAICompletions(fields);
2670
2715
  }
2671
2716
  _useResponsesApi(options) {
2672
- const usesBuiltInTools = options?.tools?.some(isBuiltInTool);
2717
+ const usesBuiltInTools = options?.tools?.some(tools_js_1.isBuiltInTool);
2673
2718
  const hasResponsesOnlyKwargs = options?.previous_response_id != null ||
2674
2719
  options?.text != null ||
2675
2720
  options?.truncation != null ||
2676
2721
  options?.include != null ||
2677
2722
  options?.reasoning?.summary != null ||
2678
2723
  this.reasoning?.summary != null;
2679
- return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs;
2724
+ const hasCustomTools = options?.tools?.some(tools_js_1.isOpenAICustomTool);
2725
+ return (this.useResponsesApi ||
2726
+ usesBuiltInTools ||
2727
+ hasResponsesOnlyKwargs ||
2728
+ hasCustomTools);
2680
2729
  }
2681
2730
  getLsParams(options) {
2682
2731
  const optionsWithDefaults = this._combineCallOptions(options);
@@ -2,16 +2,13 @@ import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
2
2
  import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
3
3
  import { AIMessageChunk, type BaseMessage, ChatMessageChunk, FunctionMessageChunk, HumanMessageChunk, SystemMessageChunk, ToolMessageChunk } from "@langchain/core/messages";
4
4
  import { ChatGenerationChunk, type ChatGeneration, type ChatResult } from "@langchain/core/outputs";
5
- import { BaseChatModel, type BindToolsInput, type LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
5
+ import { BaseChatModel, type LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
6
6
  import { type BaseFunctionCallOptions, type BaseLanguageModelInput, type StructuredOutputMethodOptions } from "@langchain/core/language_models/base";
7
7
  import { Runnable } from "@langchain/core/runnables";
8
- import type { ResponseFormatText, ResponseFormatJSONObject, ResponseFormatJSONSchema } from "openai/resources/shared";
9
8
  import { InteropZodType } from "@langchain/core/utils/types";
10
- import { type OpenAICallOptions, type OpenAIChatInput, type OpenAICoreRequestOptions, type ChatOpenAIResponseFormat, ChatOpenAIReasoningSummary } from "./types.js";
9
+ import { type OpenAICallOptions, type OpenAIChatInput, type OpenAICoreRequestOptions, type ChatOpenAIResponseFormat, ChatOpenAIReasoningSummary, ResponseFormatConfiguration } from "./types.js";
11
10
  import { OpenAIToolChoice } from "./utils/openai.js";
12
- type ResponsesTool = NonNullable<OpenAIClient.Responses.ResponseCreateParams["tools"]>[number];
13
- type ResponsesToolChoice = NonNullable<OpenAIClient.Responses.ResponseCreateParams["tool_choice"]>;
14
- type ChatOpenAIToolType = BindToolsInput | OpenAIClient.Chat.ChatCompletionTool | ResponsesTool;
11
+ import { ChatOpenAIToolType, ResponsesTool, ResponsesToolChoice } from "./utils/tools.js";
15
12
  interface OpenAILLMOutput {
16
13
  tokenUsage: {
17
14
  completionTokens?: number;
@@ -112,6 +109,12 @@ export interface BaseChatOpenAICallOptions extends OpenAICallOptions, BaseFuncti
112
109
  * Specifies the service tier for prioritization and latency optimization.
113
110
  */
114
111
  service_tier?: OpenAIClient.Chat.ChatCompletionCreateParams["service_tier"];
112
+ /**
113
+ * Used by OpenAI to cache responses for similar requests to optimize your cache
114
+ * hit rates. Replaces the `user` field.
115
+ * [Learn more](https://platform.openai.com/docs/guides/prompt-caching).
116
+ */
117
+ promptCacheKey?: string;
115
118
  }
116
119
  export interface BaseChatOpenAIFields extends Partial<OpenAIChatInput>, BaseChatModelParams {
117
120
  /**
@@ -170,6 +173,12 @@ export declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAIC
170
173
  * Specifies the service tier for prioritization and latency optimization.
171
174
  */
172
175
  service_tier?: OpenAIClient.Chat.ChatCompletionCreateParams["service_tier"];
176
+ /**
177
+ * Used by OpenAI to cache responses for similar requests to optimize your cache
178
+ * hit rates.
179
+ * [Learn more](https://platform.openai.com/docs/guides/prompt-caching).
180
+ */
181
+ promptCacheKey: string;
173
182
  protected defaultOptions: CallOptions;
174
183
  _llmType(): string;
175
184
  static lc_name(): string;
@@ -201,7 +210,7 @@ export declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAIC
201
210
  * Returns an openai compatible response format from a set of options
202
211
  * @internal
203
212
  */
204
- protected _getResponseFormat(resFormat?: CallOptions["response_format"]): ResponseFormatText | ResponseFormatJSONObject | ResponseFormatJSONSchema | undefined;
213
+ protected _getResponseFormat(resFormat?: CallOptions["response_format"]): ResponseFormatConfiguration | undefined;
205
214
  protected _combineCallOptions(additionalOptions?: this["ParsedCallOptions"]): this["ParsedCallOptions"];
206
215
  /** @internal */
207
216
  _getClientOptions(options: OpenAICoreRequestOptions | undefined): OpenAICoreRequestOptions;
@@ -882,7 +891,7 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
882
891
  protected completions: ChatOpenAICompletions;
883
892
  get lc_serializable_keys(): string[];
884
893
  constructor(fields?: ChatOpenAIFields | undefined);
885
- protected _useResponsesApi(options: this["ParsedCallOptions"] | undefined): boolean;
894
+ protected _useResponsesApi(options: this["ParsedCallOptions"] | undefined): boolean | undefined;
886
895
  getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
887
896
  invocationParams(options?: this["ParsedCallOptions"]): ChatResponsesInvocationParams | ChatCompletionsInvocationParams;
888
897
  /** @ignore */
@@ -3,7 +3,7 @@ import { AIMessage, AIMessageChunk, ChatMessage, ChatMessageChunk, FunctionMessa
3
3
  import { ChatGenerationChunk, } from "@langchain/core/outputs";
4
4
  import { getEnvironmentVariable } from "@langchain/core/utils/env";
5
5
  import { BaseChatModel, } from "@langchain/core/language_models/chat_models";
6
- import { isOpenAITool, } from "@langchain/core/language_models/base";
6
+ import { isOpenAITool as isOpenAIFunctionTool, } from "@langchain/core/language_models/base";
7
7
  import { RunnableLambda, RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables";
8
8
  import { JsonOutputParser, StructuredOutputParser, } from "@langchain/core/output_parsers";
9
9
  import { JsonOutputKeyToolsParser, convertLangChainToolCallToOpenAI, makeInvalidToolCall, parseToolCall, } from "@langchain/core/output_parsers/openai_tools";
@@ -12,19 +12,10 @@ import { toJsonSchema } from "@langchain/core/utils/json_schema";
12
12
  import { getEndpoint } from "./utils/azure.js";
13
13
  import { formatToOpenAIToolChoice, interopZodResponseFormat, wrapOpenAIClientError, } from "./utils/openai.js";
14
14
  import { formatFunctionDefinitions, } from "./utils/openai-format-fndef.js";
15
- import { _convertToOpenAITool } from "./utils/tools.js";
15
+ import { _convertToOpenAITool, convertCompletionsCustomTool, convertResponsesCustomTool, isBuiltInTool, isBuiltInToolChoice, isCustomTool, isCustomToolCall, isOpenAICustomTool, parseCustomToolCall, } from "./utils/tools.js";
16
16
  const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
17
- function isBuiltInTool(tool) {
18
- return "type" in tool && tool.type !== "function";
19
- }
20
- function isBuiltInToolChoice(tool_choice) {
21
- return (tool_choice != null &&
22
- typeof tool_choice === "object" &&
23
- "type" in tool_choice &&
24
- tool_choice.type !== "function");
25
- }
26
17
  function isReasoningModel(model) {
27
- return model && /^o\d/.test(model);
18
+ return model && (/^o\d/.test(model) || model.startsWith("gpt-5"));
28
19
  }
29
20
  function isStructuredOutputMethodParams(x
30
21
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -322,6 +313,8 @@ export class BaseChatOpenAI extends BaseChatModel {
322
313
  "disableStreaming",
323
314
  "zdrEnabled",
324
315
  "reasoning",
316
+ "verbosity",
317
+ "promptCacheKey",
325
318
  ];
326
319
  }
327
320
  getLsParams(options) {
@@ -540,6 +533,17 @@ export class BaseChatOpenAI extends BaseChatModel {
540
533
  writable: true,
541
534
  value: void 0
542
535
  });
536
+ /**
537
+ * Used by OpenAI to cache responses for similar requests to optimize your cache
538
+ * hit rates.
539
+ * [Learn more](https://platform.openai.com/docs/guides/prompt-caching).
540
+ */
541
+ Object.defineProperty(this, "promptCacheKey", {
542
+ enumerable: true,
543
+ configurable: true,
544
+ writable: true,
545
+ value: void 0
546
+ });
543
547
  Object.defineProperty(this, "defaultOptions", {
544
548
  enumerable: true,
545
549
  configurable: true,
@@ -579,6 +583,7 @@ export class BaseChatOpenAI extends BaseChatModel {
579
583
  this.reasoning = fields?.reasoning;
580
584
  this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
581
585
  this.disableStreaming = fields?.disableStreaming ?? this.disableStreaming;
586
+ this.promptCacheKey = fields?.promptCacheKey ?? this.promptCacheKey;
582
587
  this.streaming = fields?.streaming ?? false;
583
588
  if (this.disableStreaming)
584
589
  this.streaming = false;
@@ -672,7 +677,10 @@ export class BaseChatOpenAI extends BaseChatModel {
672
677
  }
673
678
  // TODO: move to completions class
674
679
  _convertChatOpenAIToolToCompletionsTool(tool, fields) {
675
- if (isOpenAITool(tool)) {
680
+ if (isCustomTool(tool)) {
681
+ return convertResponsesCustomTool(tool.metadata.customTool);
682
+ }
683
+ if (isOpenAIFunctionTool(tool)) {
676
684
  if (fields?.strict !== undefined) {
677
685
  return {
678
686
  ...tool,
@@ -1076,6 +1084,7 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1076
1084
  })(),
1077
1085
  parallel_tool_calls: options?.parallel_tool_calls,
1078
1086
  max_output_tokens: this.maxTokens === -1 ? undefined : this.maxTokens,
1087
+ prompt_cache_key: options?.promptCacheKey ?? this.promptCacheKey,
1079
1088
  ...(this.zdrEnabled ? { store: false } : {}),
1080
1089
  ...this.modelKwargs,
1081
1090
  };
@@ -1238,6 +1247,15 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1238
1247
  else if (item.type === "reasoning") {
1239
1248
  additional_kwargs.reasoning = item;
1240
1249
  }
1250
+ else if (item.type === "custom_tool_call") {
1251
+ const parsed = parseCustomToolCall(item);
1252
+ if (parsed) {
1253
+ tool_calls.push(parsed);
1254
+ }
1255
+ else {
1256
+ invalid_tool_calls.push(makeInvalidToolCall(item, "Malformed custom tool call"));
1257
+ }
1258
+ }
1241
1259
  else {
1242
1260
  additional_kwargs.tool_outputs ??= [];
1243
1261
  additional_kwargs.tool_outputs.push(item);
@@ -1304,6 +1322,7 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1304
1322
  "mcp_list_tools",
1305
1323
  "mcp_approval_request",
1306
1324
  "image_generation_call",
1325
+ "custom_tool_call",
1307
1326
  ].includes(chunk.item.type)) {
1308
1327
  additional_kwargs.tool_outputs = [chunk.item];
1309
1328
  }
@@ -1445,6 +1464,14 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1445
1464
  call_id: toolMessage.tool_call_id,
1446
1465
  };
1447
1466
  }
1467
+ // Handle custom tool output
1468
+ if (toolMessage.metadata?.customTool) {
1469
+ return {
1470
+ type: "custom_tool_call_output",
1471
+ call_id: toolMessage.tool_call_id,
1472
+ output: toolMessage.content,
1473
+ };
1474
+ }
1448
1475
  return {
1449
1476
  type: "function_call_output",
1450
1477
  call_id: toolMessage.tool_call_id,
@@ -1483,41 +1510,54 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1483
1510
  { type: "refusal", refusal: additional_kwargs.refusal },
1484
1511
  ];
1485
1512
  }
1486
- input.push({
1487
- type: "message",
1488
- role: "assistant",
1489
- ...(lcMsg.id && !this.zdrEnabled && lcMsg.id.startsWith("msg_")
1490
- ? { id: lcMsg.id }
1491
- : {}),
1492
- content: typeof content === "string"
1493
- ? content
1494
- : content.flatMap((item) => {
1495
- if (item.type === "text") {
1496
- return {
1497
- type: "output_text",
1498
- text: item.text,
1499
- // @ts-expect-error TODO: add types for `annotations`
1500
- annotations: item.annotations ?? [],
1501
- };
1502
- }
1503
- if (item.type === "output_text" ||
1504
- item.type === "refusal") {
1505
- return item;
1506
- }
1507
- return [];
1508
- }),
1509
- });
1513
+ if (typeof content === "string" || content.length > 0) {
1514
+ input.push({
1515
+ type: "message",
1516
+ role: "assistant",
1517
+ ...(lcMsg.id && !this.zdrEnabled && lcMsg.id.startsWith("msg_")
1518
+ ? { id: lcMsg.id }
1519
+ : {}),
1520
+ content: typeof content === "string"
1521
+ ? content
1522
+ : content.flatMap((item) => {
1523
+ if (item.type === "text") {
1524
+ return {
1525
+ type: "output_text",
1526
+ text: item.text,
1527
+ // @ts-expect-error TODO: add types for `annotations`
1528
+ annotations: item.annotations ?? [],
1529
+ };
1530
+ }
1531
+ if (item.type === "output_text" ||
1532
+ item.type === "refusal") {
1533
+ return item;
1534
+ }
1535
+ return [];
1536
+ }),
1537
+ });
1538
+ }
1510
1539
  const functionCallIds = additional_kwargs?.[_FUNCTION_CALL_IDS_MAP_KEY];
1511
1540
  if (isAIMessage(lcMsg) && !!lcMsg.tool_calls?.length) {
1512
- input.push(...lcMsg.tool_calls.map((toolCall) => ({
1513
- type: "function_call",
1514
- name: toolCall.name,
1515
- arguments: JSON.stringify(toolCall.args),
1516
- call_id: toolCall.id,
1517
- ...(this.zdrEnabled
1518
- ? { id: functionCallIds?.[toolCall.id] }
1519
- : {}),
1520
- })));
1541
+ input.push(...lcMsg.tool_calls.map((toolCall) => {
1542
+ if (isCustomToolCall(toolCall)) {
1543
+ return {
1544
+ type: "custom_tool_call",
1545
+ id: toolCall.call_id,
1546
+ call_id: toolCall.id ?? "",
1547
+ input: toolCall.args.input,
1548
+ name: toolCall.name,
1549
+ };
1550
+ }
1551
+ return {
1552
+ type: "function_call",
1553
+ name: toolCall.name,
1554
+ arguments: JSON.stringify(toolCall.args),
1555
+ call_id: toolCall.id,
1556
+ ...(this.zdrEnabled
1557
+ ? { id: functionCallIds?.[toolCall.id] }
1558
+ : {}),
1559
+ };
1560
+ }));
1521
1561
  }
1522
1562
  else if (additional_kwargs?.tool_calls) {
1523
1563
  input.push(...additional_kwargs.tool_calls.map((toolCall) => ({
@@ -1628,7 +1668,7 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1628
1668
  }
1629
1669
  reducedTools.push(tool);
1630
1670
  }
1631
- else if (isOpenAITool(tool)) {
1671
+ else if (isOpenAIFunctionTool(tool)) {
1632
1672
  reducedTools.push({
1633
1673
  type: "function",
1634
1674
  name: tool.function.name,
@@ -1637,6 +1677,9 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1637
1677
  strict: fields?.strict ?? null,
1638
1678
  });
1639
1679
  }
1680
+ else if (isOpenAICustomTool(tool)) {
1681
+ reducedTools.push(convertCompletionsCustomTool(tool));
1682
+ }
1640
1683
  }
1641
1684
  return reducedTools;
1642
1685
  }
@@ -1693,6 +1736,7 @@ export class ChatOpenAICompletions extends BaseChatOpenAI {
1693
1736
  ? { modalities: this.modalities || options?.modalities }
1694
1737
  : {}),
1695
1738
  ...this.modelKwargs,
1739
+ prompt_cache_key: options?.promptCacheKey ?? this.promptCacheKey,
1696
1740
  };
1697
1741
  if (options?.prediction !== undefined) {
1698
1742
  params.prediction = options.prediction;
@@ -1940,6 +1984,7 @@ export class ChatOpenAICompletions extends BaseChatOpenAI {
1940
1984
  return await this.client.chat.completions.parse(request, clientOptions);
1941
1985
  }
1942
1986
  else {
1987
+ console.log("request", request);
1943
1988
  return await this.client.chat.completions.create(request, clientOptions);
1944
1989
  }
1945
1990
  }
@@ -2668,7 +2713,11 @@ export class ChatOpenAI extends BaseChatOpenAI {
2668
2713
  options?.include != null ||
2669
2714
  options?.reasoning?.summary != null ||
2670
2715
  this.reasoning?.summary != null;
2671
- return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs;
2716
+ const hasCustomTools = options?.tools?.some(isOpenAICustomTool);
2717
+ return (this.useResponsesApi ||
2718
+ usesBuiltInTools ||
2719
+ hasResponsesOnlyKwargs ||
2720
+ hasCustomTools);
2672
2721
  }
2673
2722
  getLsParams(options) {
2674
2723
  const optionsWithDefaults = this._combineCallOptions(options);
package/dist/index.cjs CHANGED
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.convertPromptToOpenAI = exports.toFile = exports.OpenAIClient = void 0;
17
+ exports.customTool = exports.convertPromptToOpenAI = exports.toFile = exports.OpenAIClient = void 0;
18
18
  var openai_1 = require("openai");
19
19
  Object.defineProperty(exports, "OpenAIClient", { enumerable: true, get: function () { return openai_1.OpenAI; } });
20
20
  Object.defineProperty(exports, "toFile", { enumerable: true, get: function () { return openai_1.toFile; } });
@@ -30,3 +30,5 @@ __exportStar(require("./utils/azure.cjs"), exports);
30
30
  __exportStar(require("./tools/index.cjs"), exports);
31
31
  var prompts_js_1 = require("./utils/prompts.cjs");
32
32
  Object.defineProperty(exports, "convertPromptToOpenAI", { enumerable: true, get: function () { return prompts_js_1.convertPromptToOpenAI; } });
33
+ var custom_js_1 = require("./tools/custom.cjs");
34
+ Object.defineProperty(exports, "customTool", { enumerable: true, get: function () { return custom_js_1.customTool; } });
package/dist/index.d.ts CHANGED
@@ -10,3 +10,4 @@ export * from "./utils/openai.js";
10
10
  export * from "./utils/azure.js";
11
11
  export * from "./tools/index.js";
12
12
  export { convertPromptToOpenAI } from "./utils/prompts.js";
13
+ export { customTool } from "./tools/custom.js";
package/dist/index.js CHANGED
@@ -10,3 +10,4 @@ export * from "./utils/openai.js";
10
10
  export * from "./utils/azure.js";
11
11
  export * from "./tools/index.js";
12
12
  export { convertPromptToOpenAI } from "./utils/prompts.js";
13
+ export { customTool } from "./tools/custom.js";
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.customTool = customTool;
4
+ const runnables_1 = require("@langchain/core/runnables");
5
+ const singletons_1 = require("@langchain/core/singletons");
6
+ const tools_1 = require("@langchain/core/tools");
7
+ function customTool(func, fields) {
8
+ return new tools_1.DynamicTool({
9
+ ...fields,
10
+ description: "",
11
+ metadata: {
12
+ customTool: fields,
13
+ },
14
+ func: async (input, runManager, config) => new Promise((resolve, reject) => {
15
+ const childConfig = (0, runnables_1.patchConfig)(config, {
16
+ callbacks: runManager?.getChild(),
17
+ });
18
+ void singletons_1.AsyncLocalStorageProviderSingleton.runWithConfig((0, runnables_1.pickRunnableConfigKeys)(childConfig), async () => {
19
+ try {
20
+ resolve(func(input, childConfig));
21
+ }
22
+ catch (e) {
23
+ reject(e);
24
+ }
25
+ });
26
+ }),
27
+ });
28
+ }
@@ -0,0 +1,5 @@
1
+ import { RunnableFunc } from "@langchain/core/runnables";
2
+ import { DynamicTool, ToolRunnableConfig } from "@langchain/core/tools";
3
+ import OpenAI from "openai";
4
+ export type CustomToolFields = Omit<OpenAI.Responses.CustomTool, "type">;
5
+ export declare function customTool(func: RunnableFunc<string, string, ToolRunnableConfig>, fields: CustomToolFields): DynamicTool<string>;
@@ -0,0 +1,25 @@
1
+ import { patchConfig, pickRunnableConfigKeys, } from "@langchain/core/runnables";
2
+ import { AsyncLocalStorageProviderSingleton } from "@langchain/core/singletons";
3
+ import { DynamicTool } from "@langchain/core/tools";
4
+ export function customTool(func, fields) {
5
+ return new DynamicTool({
6
+ ...fields,
7
+ description: "",
8
+ metadata: {
9
+ customTool: fields,
10
+ },
11
+ func: async (input, runManager, config) => new Promise((resolve, reject) => {
12
+ const childConfig = patchConfig(config, {
13
+ callbacks: runManager?.getChild(),
14
+ });
15
+ void AsyncLocalStorageProviderSingleton.runWithConfig(pickRunnableConfigKeys(childConfig), async () => {
16
+ try {
17
+ resolve(func(input, childConfig));
18
+ }
19
+ catch (e) {
20
+ reject(e);
21
+ }
22
+ });
23
+ }),
24
+ });
25
+ }
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { OpenAI as OpenAIClient } from "openai";
2
- import type { ResponseFormatText, ResponseFormatJSONObject, ResponseFormatJSONSchema } from "openai/resources/shared";
2
+ import type { ResponseFormatText, ResponseFormatJSONObject, ResponseFormatJSONSchema, ResponseFormatTextPython, ResponseFormatTextGrammar } from "openai/resources/shared";
3
3
  import { TiktokenModel } from "js-tiktoken/lite";
4
4
  import type { BaseLanguageModelCallOptions } from "@langchain/core/language_models/base";
5
5
  import { InteropZodObject } from "@langchain/core/utils/types";
@@ -76,6 +76,8 @@ export declare interface OpenAIBaseInput {
76
76
  * `OPENAI_API_KEY` environment variable.
77
77
  */
78
78
  apiKey?: string;
79
+ /** The verbosity of the model's response. */
80
+ verbosity: "low" | "medium" | "high";
79
81
  }
80
82
  export type OpenAICoreRequestOptions = OpenAIClient.RequestOptions;
81
83
  export interface OpenAICallOptions extends BaseLanguageModelCallOptions {
@@ -154,6 +156,12 @@ export interface OpenAIChatInput extends OpenAIBaseInput {
154
156
  * Specifies the service tier for prioritization and latency optimization.
155
157
  */
156
158
  service_tier?: OpenAIClient.Responses.ResponseCreateParams["service_tier"];
159
+ /**
160
+ * Used by OpenAI to cache responses for similar requests to optimize your cache
161
+ * hit rates. Replaces the `user` field.
162
+ * [Learn more](https://platform.openai.com/docs/guides/prompt-caching).
163
+ */
164
+ promptCacheKey?: string;
157
165
  }
158
166
  export interface AzureOpenAIInput {
159
167
  /**
@@ -241,4 +249,5 @@ export type ChatOpenAIReasoningSummary = Omit<OpenAIClient.Responses.ResponseRea
241
249
  index?: number;
242
250
  }>;
243
251
  };
244
- export type ChatOpenAIResponseFormat = ResponseFormatText | ResponseFormatJSONObject | ChatOpenAIResponseFormatJSONSchema;
252
+ export type ChatOpenAIResponseFormat = ResponseFormatText | ResponseFormatJSONObject | ResponseFormatTextGrammar | ResponseFormatTextPython | ChatOpenAIResponseFormatJSONSchema;
253
+ export type ResponseFormatConfiguration = ResponseFormatText | ResponseFormatJSONObject | ResponseFormatJSONSchema;
@@ -1,6 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports._convertToOpenAITool = _convertToOpenAITool;
4
+ exports.isBuiltInTool = isBuiltInTool;
5
+ exports.isBuiltInToolChoice = isBuiltInToolChoice;
6
+ exports.isCustomTool = isCustomTool;
7
+ exports.isOpenAICustomTool = isOpenAICustomTool;
8
+ exports.parseCustomToolCall = parseCustomToolCall;
9
+ exports.isCustomToolCall = isCustomToolCall;
10
+ exports.convertCompletionsCustomTool = convertCompletionsCustomTool;
11
+ exports.convertResponsesCustomTool = convertResponsesCustomTool;
4
12
  const function_calling_1 = require("@langchain/core/utils/function_calling");
5
13
  const openai_js_1 = require("./openai.cjs");
6
14
  /**
@@ -24,8 +32,113 @@ tool, fields) {
24
32
  else {
25
33
  toolDef = tool;
26
34
  }
27
- if (fields?.strict !== undefined) {
35
+ if (toolDef.type === "function" && fields?.strict !== undefined) {
28
36
  toolDef.function.strict = fields.strict;
29
37
  }
30
38
  return toolDef;
31
39
  }
40
+ function isBuiltInTool(tool) {
41
+ return "type" in tool && tool.type !== "function" && tool.type !== "custom";
42
+ }
43
+ function isBuiltInToolChoice(tool_choice) {
44
+ return (tool_choice != null &&
45
+ typeof tool_choice === "object" &&
46
+ "type" in tool_choice &&
47
+ tool_choice.type !== "function");
48
+ }
49
+ function isCustomTool(tool) {
50
+ return (typeof tool === "object" &&
51
+ tool !== null &&
52
+ "metadata" in tool &&
53
+ typeof tool.metadata === "object" &&
54
+ tool.metadata !== null &&
55
+ "customTool" in tool.metadata &&
56
+ typeof tool.metadata.customTool === "object" &&
57
+ tool.metadata.customTool !== null);
58
+ }
59
+ function isOpenAICustomTool(tool) {
60
+ return ("type" in tool &&
61
+ tool.type === "custom" &&
62
+ "custom" in tool &&
63
+ typeof tool.custom === "object" &&
64
+ tool.custom !== null);
65
+ }
66
+ function parseCustomToolCall(
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ rawToolCall) {
69
+ if (rawToolCall.type !== "custom_tool_call") {
70
+ return undefined;
71
+ }
72
+ return {
73
+ ...rawToolCall,
74
+ type: "tool_call",
75
+ call_id: rawToolCall.id,
76
+ id: rawToolCall.call_id,
77
+ name: rawToolCall.name,
78
+ isCustomTool: true,
79
+ args: {
80
+ input: rawToolCall.input,
81
+ },
82
+ };
83
+ }
84
+ function isCustomToolCall(toolCall) {
85
+ return (toolCall.type === "tool_call" &&
86
+ "isCustomTool" in toolCall &&
87
+ toolCall.isCustomTool === true);
88
+ }
89
+ function convertCompletionsCustomTool(tool) {
90
+ const getFormat = () => {
91
+ if (!tool.custom.format) {
92
+ return undefined;
93
+ }
94
+ if (tool.custom.format.type === "grammar") {
95
+ return {
96
+ type: "grammar",
97
+ definition: tool.custom.format.grammar.definition,
98
+ syntax: tool.custom.format.grammar.syntax,
99
+ };
100
+ }
101
+ if (tool.custom.format.type === "text") {
102
+ return {
103
+ type: "text",
104
+ };
105
+ }
106
+ return undefined;
107
+ };
108
+ return {
109
+ type: "custom",
110
+ name: tool.custom.name,
111
+ description: tool.custom.description,
112
+ format: getFormat(),
113
+ };
114
+ }
115
+ function convertResponsesCustomTool(tool) {
116
+ const getFormat = () => {
117
+ if (!tool.format) {
118
+ return undefined;
119
+ }
120
+ if (tool.format.type === "grammar") {
121
+ return {
122
+ type: "grammar",
123
+ grammar: {
124
+ definition: tool.format.definition,
125
+ syntax: tool.format.syntax,
126
+ },
127
+ };
128
+ }
129
+ if (tool.format.type === "text") {
130
+ return {
131
+ type: "text",
132
+ };
133
+ }
134
+ return undefined;
135
+ };
136
+ return {
137
+ type: "custom",
138
+ custom: {
139
+ name: tool.name,
140
+ description: tool.description,
141
+ format: getFormat(),
142
+ },
143
+ };
144
+ }
@@ -1,5 +1,11 @@
1
1
  import { OpenAI as OpenAIClient } from "openai";
2
+ import { ToolCall } from "@langchain/core/messages/tool";
2
3
  import { BindToolsInput } from "@langchain/core/language_models/chat_models";
4
+ import { DynamicTool } from "@langchain/core/tools";
5
+ import { OpenAIToolChoice } from "./openai.js";
6
+ export type ResponsesTool = NonNullable<OpenAIClient.Responses.ResponseCreateParams["tools"]>[number];
7
+ export type ResponsesToolChoice = NonNullable<OpenAIClient.Responses.ResponseCreateParams["tool_choice"]>;
8
+ export type ChatOpenAIToolType = BindToolsInput | OpenAIClient.Chat.ChatCompletionTool | ResponsesTool;
3
9
  /**
4
10
  * Formats a tool in either OpenAI format, or LangChain structured tool format
5
11
  * into an OpenAI tool format. If the tool is already in OpenAI format, return without
@@ -18,3 +24,21 @@ export declare function _convertToOpenAITool(tool: BindToolsInput, fields?: {
18
24
  */
19
25
  strict?: boolean;
20
26
  }): OpenAIClient.ChatCompletionTool;
27
+ export declare function isBuiltInTool(tool: ChatOpenAIToolType): tool is ResponsesTool;
28
+ export declare function isBuiltInToolChoice(tool_choice: OpenAIToolChoice | ResponsesToolChoice | undefined): tool_choice is ResponsesToolChoice;
29
+ export type CustomToolCall = ToolCall & {
30
+ call_id: string;
31
+ isCustomTool: true;
32
+ };
33
+ type LangchainCustomTool = DynamicTool<string> & {
34
+ metadata: {
35
+ customTool: OpenAIClient.Responses.CustomTool;
36
+ };
37
+ };
38
+ export declare function isCustomTool(tool: unknown): tool is LangchainCustomTool;
39
+ export declare function isOpenAICustomTool(tool: ChatOpenAIToolType): tool is OpenAIClient.Chat.ChatCompletionCustomTool;
40
+ export declare function parseCustomToolCall(rawToolCall: Record<string, any>): CustomToolCall | undefined;
41
+ export declare function isCustomToolCall(toolCall: ToolCall): toolCall is CustomToolCall;
42
+ export declare function convertCompletionsCustomTool(tool: OpenAIClient.Chat.ChatCompletionCustomTool): OpenAIClient.Responses.CustomTool;
43
+ export declare function convertResponsesCustomTool(tool: OpenAIClient.Responses.CustomTool): OpenAIClient.Chat.ChatCompletionCustomTool;
44
+ export {};
@@ -21,8 +21,113 @@ tool, fields) {
21
21
  else {
22
22
  toolDef = tool;
23
23
  }
24
- if (fields?.strict !== undefined) {
24
+ if (toolDef.type === "function" && fields?.strict !== undefined) {
25
25
  toolDef.function.strict = fields.strict;
26
26
  }
27
27
  return toolDef;
28
28
  }
29
+ export function isBuiltInTool(tool) {
30
+ return "type" in tool && tool.type !== "function" && tool.type !== "custom";
31
+ }
32
+ export function isBuiltInToolChoice(tool_choice) {
33
+ return (tool_choice != null &&
34
+ typeof tool_choice === "object" &&
35
+ "type" in tool_choice &&
36
+ tool_choice.type !== "function");
37
+ }
38
+ export function isCustomTool(tool) {
39
+ return (typeof tool === "object" &&
40
+ tool !== null &&
41
+ "metadata" in tool &&
42
+ typeof tool.metadata === "object" &&
43
+ tool.metadata !== null &&
44
+ "customTool" in tool.metadata &&
45
+ typeof tool.metadata.customTool === "object" &&
46
+ tool.metadata.customTool !== null);
47
+ }
48
+ export function isOpenAICustomTool(tool) {
49
+ return ("type" in tool &&
50
+ tool.type === "custom" &&
51
+ "custom" in tool &&
52
+ typeof tool.custom === "object" &&
53
+ tool.custom !== null);
54
+ }
55
+ export function parseCustomToolCall(
56
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
+ rawToolCall) {
58
+ if (rawToolCall.type !== "custom_tool_call") {
59
+ return undefined;
60
+ }
61
+ return {
62
+ ...rawToolCall,
63
+ type: "tool_call",
64
+ call_id: rawToolCall.id,
65
+ id: rawToolCall.call_id,
66
+ name: rawToolCall.name,
67
+ isCustomTool: true,
68
+ args: {
69
+ input: rawToolCall.input,
70
+ },
71
+ };
72
+ }
73
+ export function isCustomToolCall(toolCall) {
74
+ return (toolCall.type === "tool_call" &&
75
+ "isCustomTool" in toolCall &&
76
+ toolCall.isCustomTool === true);
77
+ }
78
+ export function convertCompletionsCustomTool(tool) {
79
+ const getFormat = () => {
80
+ if (!tool.custom.format) {
81
+ return undefined;
82
+ }
83
+ if (tool.custom.format.type === "grammar") {
84
+ return {
85
+ type: "grammar",
86
+ definition: tool.custom.format.grammar.definition,
87
+ syntax: tool.custom.format.grammar.syntax,
88
+ };
89
+ }
90
+ if (tool.custom.format.type === "text") {
91
+ return {
92
+ type: "text",
93
+ };
94
+ }
95
+ return undefined;
96
+ };
97
+ return {
98
+ type: "custom",
99
+ name: tool.custom.name,
100
+ description: tool.custom.description,
101
+ format: getFormat(),
102
+ };
103
+ }
104
+ export function convertResponsesCustomTool(tool) {
105
+ const getFormat = () => {
106
+ if (!tool.format) {
107
+ return undefined;
108
+ }
109
+ if (tool.format.type === "grammar") {
110
+ return {
111
+ type: "grammar",
112
+ grammar: {
113
+ definition: tool.format.definition,
114
+ syntax: tool.format.syntax,
115
+ },
116
+ };
117
+ }
118
+ if (tool.format.type === "text") {
119
+ return {
120
+ type: "text",
121
+ };
122
+ }
123
+ return undefined;
124
+ };
125
+ return {
126
+ type: "custom",
127
+ custom: {
128
+ name: tool.name,
129
+ description: tool.description,
130
+ format: getFormat(),
131
+ },
132
+ };
133
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -40,7 +40,7 @@
40
40
  "zod": "^3.25.32"
41
41
  },
42
42
  "peerDependencies": {
43
- "@langchain/core": ">=0.3.58 <0.4.0"
43
+ "@langchain/core": ">=0.3.68 <0.4.0"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@azure/identity": "^4.2.1",