@langchain/openai 0.5.12 → 0.5.14

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.
@@ -1,6 +1,42 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChatOpenAI = exports._convertMessagesToOpenAIParams = exports.messageToOpenAIRole = void 0;
36
+ exports.ChatOpenAI = void 0;
37
+ exports.messageToOpenAIRole = messageToOpenAIRole;
38
+ exports._convertMessagesToOpenAIParams = _convertMessagesToOpenAIParams;
39
+ const z4 = __importStar(require("zod/v4/core"));
4
40
  const openai_1 = require("openai");
5
41
  const messages_1 = require("@langchain/core/messages");
6
42
  const outputs_1 = require("@langchain/core/outputs");
@@ -10,8 +46,9 @@ const base_1 = require("@langchain/core/language_models/base");
10
46
  const runnables_1 = require("@langchain/core/runnables");
11
47
  const output_parsers_1 = require("@langchain/core/output_parsers");
12
48
  const openai_tools_1 = require("@langchain/core/output_parsers/openai_tools");
13
- const zod_to_json_schema_1 = require("zod-to-json-schema");
14
49
  const zod_1 = require("openai/helpers/zod");
50
+ const types_1 = require("@langchain/core/utils/types");
51
+ const json_schema_1 = require("@langchain/core/utils/json_schema");
15
52
  const azure_js_1 = require("./utils/azure.cjs");
16
53
  const openai_js_1 = require("./utils/openai.cjs");
17
54
  const openai_format_fndef_js_1 = require("./utils/openai-format-fndef.cjs");
@@ -49,7 +86,6 @@ function messageToOpenAIRole(message) {
49
86
  throw new Error(`Unknown message type: ${type}`);
50
87
  }
51
88
  }
52
- exports.messageToOpenAIRole = messageToOpenAIRole;
53
89
  const completionsApiContentBlockConverter = {
54
90
  providerName: "ChatOpenAI",
55
91
  fromStandardTextBlock(block) {
@@ -138,7 +174,7 @@ const completionsApiContentBlockConverter = {
138
174
  return {
139
175
  type: "file",
140
176
  file: {
141
- file_data: block.url,
177
+ file_data: block.url, // formatted as base64 data URL
142
178
  ...(block.metadata?.filename || block.metadata?.name
143
179
  ? {
144
180
  filename: (block.metadata?.filename ||
@@ -230,7 +266,6 @@ function _convertMessagesToOpenAIParams(messages, model) {
230
266
  return completionParam;
231
267
  });
232
268
  }
233
- exports._convertMessagesToOpenAIParams = _convertMessagesToOpenAIParams;
234
269
  const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
235
270
  function _convertReasoningSummaryToOpenAIResponsesParams(reasoning) {
236
271
  // combine summary parts that have the the same index and then remove the indexes
@@ -252,12 +287,8 @@ function _convertReasoningSummaryToOpenAIResponsesParams(reasoning) {
252
287
  };
253
288
  }
254
289
  function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
255
- const lastAIMessage = messages.filter((m) => (0, messages_1.isAIMessage)(m)).pop();
256
- const lastAIMessageId = lastAIMessage?.response_metadata?.id;
257
- const newMessages = lastAIMessageId && lastAIMessageId.startsWith("resp_") && !zdrEnabled
258
- ? messages.slice(messages.indexOf(lastAIMessage) + 1)
259
- : messages;
260
- return newMessages.flatMap((lcMsg) => {
290
+ return messages.flatMap((lcMsg) => {
291
+ const additional_kwargs = lcMsg.additional_kwargs;
261
292
  let role = messageToOpenAIRole(lcMsg);
262
293
  if (role === "system" && isReasoningModel(model))
263
294
  role = "developer";
@@ -267,7 +298,7 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
267
298
  if (role === "tool") {
268
299
  const toolMessage = lcMsg;
269
300
  // Handle computer call output
270
- if (toolMessage.additional_kwargs?.type === "computer_call_output") {
301
+ if (additional_kwargs?.type === "computer_call_output") {
271
302
  const output = (() => {
272
303
  if (typeof toolMessage.content === "string") {
273
304
  return {
@@ -318,25 +349,19 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
318
349
  // otherwise, try to reconstruct the response from what we have
319
350
  const input = [];
320
351
  // reasoning items
321
- if (!zdrEnabled && lcMsg.additional_kwargs.reasoning != null) {
322
- const isReasoningItem = (item) => typeof item === "object" &&
323
- item != null &&
324
- "type" in item &&
325
- item.type === "reasoning";
326
- if (isReasoningItem(lcMsg.additional_kwargs.reasoning)) {
327
- const reasoningItem = _convertReasoningSummaryToOpenAIResponsesParams(lcMsg.additional_kwargs.reasoning);
328
- input.push(reasoningItem);
329
- }
352
+ if (additional_kwargs?.reasoning && !zdrEnabled) {
353
+ const reasoningItem = _convertReasoningSummaryToOpenAIResponsesParams(additional_kwargs.reasoning);
354
+ input.push(reasoningItem);
330
355
  }
331
356
  // ai content
332
357
  let { content } = lcMsg;
333
- if (lcMsg.additional_kwargs.refusal != null) {
358
+ if (additional_kwargs?.refusal) {
334
359
  if (typeof content === "string") {
335
360
  content = [{ type: "output_text", text: content, annotations: [] }];
336
361
  }
337
362
  content = [
338
363
  ...content,
339
- { type: "refusal", refusal: lcMsg.additional_kwargs.refusal },
364
+ { type: "refusal", refusal: additional_kwargs.refusal },
340
365
  ];
341
366
  }
342
367
  input.push({
@@ -360,10 +385,7 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
360
385
  return [];
361
386
  }),
362
387
  });
363
- // function tool calls and computer use tool calls
364
- const functionCallIds =
365
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
366
- lcMsg.additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY];
388
+ const functionCallIds = additional_kwargs?.[_FUNCTION_CALL_IDS_MAP_KEY];
367
389
  if ((0, messages_1.isAIMessage)(lcMsg) && !!lcMsg.tool_calls?.length) {
368
390
  input.push(...lcMsg.tool_calls.map((toolCall) => ({
369
391
  type: "function_call",
@@ -373,44 +395,64 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
373
395
  ...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
374
396
  })));
375
397
  }
376
- else if (lcMsg.additional_kwargs.tool_calls != null) {
377
- input.push(...lcMsg.additional_kwargs.tool_calls.map((toolCall) => ({
398
+ else if (additional_kwargs?.tool_calls) {
399
+ input.push(...additional_kwargs.tool_calls.map((toolCall) => ({
378
400
  type: "function_call",
379
401
  name: toolCall.function.name,
380
402
  call_id: toolCall.id,
381
- ...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
382
403
  arguments: toolCall.function.arguments,
404
+ ...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
383
405
  })));
384
406
  }
385
407
  const toolOutputs = lcMsg.response_metadata.output?.length
386
408
  ? lcMsg.response_metadata.output
387
- : lcMsg.additional_kwargs.tool_outputs;
388
- let computerCalls = [];
409
+ : additional_kwargs.tool_outputs;
410
+ const fallthroughCallTypes = [
411
+ "computer_call",
412
+ "mcp_call",
413
+ "code_interpreter_call",
414
+ "image_generation_call",
415
+ ];
389
416
  if (toolOutputs != null) {
390
417
  const castToolOutputs = toolOutputs;
391
- computerCalls = castToolOutputs?.filter((item) => item.type === "computer_call");
392
- if (computerCalls.length > 0)
393
- input.push(...computerCalls);
418
+ const fallthroughCalls = castToolOutputs?.filter((item) => fallthroughCallTypes.includes(item.type));
419
+ if (fallthroughCalls.length > 0)
420
+ input.push(...fallthroughCalls);
394
421
  }
395
422
  return input;
396
423
  }
397
- const content = typeof lcMsg.content === "string"
398
- ? lcMsg.content
399
- : lcMsg.content.flatMap((item) => {
424
+ if (role === "user" || role === "system" || role === "developer") {
425
+ if (typeof lcMsg.content === "string") {
426
+ return { type: "message", role, content: lcMsg.content };
427
+ }
428
+ const messages = [];
429
+ const content = lcMsg.content.flatMap((item) => {
430
+ if (item.type === "mcp_approval_response") {
431
+ messages.push({
432
+ type: "mcp_approval_response",
433
+ approval_request_id: item.approval_request_id,
434
+ approve: item.approve,
435
+ });
436
+ }
400
437
  if ((0, messages_1.isDataContentBlock)(item)) {
401
438
  return (0, messages_1.convertToProviderContentBlock)(item, completionsApiContentBlockConverter);
402
439
  }
403
440
  if (item.type === "text") {
404
- return { type: "input_text", text: item.text };
441
+ return {
442
+ type: "input_text",
443
+ text: item.text,
444
+ };
405
445
  }
406
446
  if (item.type === "image_url") {
407
- const image_url = typeof item.image_url === "string"
408
- ? item.image_url
409
- : item.image_url.url;
410
- const detail = typeof item.image_url === "string"
411
- ? "auto"
412
- : item.image_url.detail;
413
- return { type: "input_image", image_url, detail };
447
+ return {
448
+ type: "input_image",
449
+ image_url: typeof item.image_url === "string"
450
+ ? item.image_url
451
+ : item.image_url.url,
452
+ detail: typeof item.image_url === "string"
453
+ ? "auto"
454
+ : item.image_url.detail,
455
+ };
414
456
  }
415
457
  if (item.type === "input_text" ||
416
458
  item.type === "input_image" ||
@@ -419,8 +461,10 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
419
461
  }
420
462
  return [];
421
463
  });
422
- if (role === "user" || role === "system" || role === "developer") {
423
- return { type: "message", role, content };
464
+ if (content.length > 0) {
465
+ messages.push({ type: "message", role, content });
466
+ }
467
+ return messages;
424
468
  }
425
469
  console.warn(`Unsupported role found when converting to OpenAI Responses API: ${role}`);
426
470
  return [];
@@ -527,7 +571,7 @@ function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
527
571
  index: chunk.content_index,
528
572
  });
529
573
  }
530
- else if (chunk.type === "response.output_text.annotation.added") {
574
+ else if (chunk.type === "response.output_text_annotation.added") {
531
575
  content.push({
532
576
  type: "text",
533
577
  text: "",
@@ -553,9 +597,16 @@ function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
553
597
  };
554
598
  }
555
599
  else if (chunk.type === "response.output_item.done" &&
556
- (chunk.item.type === "web_search_call" ||
557
- chunk.item.type === "file_search_call" ||
558
- chunk.item.type === "computer_call")) {
600
+ [
601
+ "web_search_call",
602
+ "file_search_call",
603
+ "computer_call",
604
+ "code_interpreter_call",
605
+ "mcp_call",
606
+ "mcp_list_tools",
607
+ "mcp_approval_request",
608
+ "image_generation_call",
609
+ ].includes(chunk.item.type)) {
559
610
  additional_kwargs.tool_outputs = [chunk.item];
560
611
  }
561
612
  else if (chunk.type === "response.created") {
@@ -627,6 +678,11 @@ function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
627
678
  ],
628
679
  };
629
680
  }
681
+ else if (chunk.type === "response.image_generation_call.partial_image") {
682
+ // noop/fixme: retaining partial images in a message chunk means that _all_
683
+ // partial images get kept in history, so we don't do anything here.
684
+ return null;
685
+ }
630
686
  else {
631
687
  return null;
632
688
  }
@@ -653,6 +709,29 @@ function isBuiltInToolChoice(tool_choice) {
653
709
  "type" in tool_choice &&
654
710
  tool_choice.type !== "function");
655
711
  }
712
+ function _reduceChatOpenAIToolsForResponses(tools, fields) {
713
+ const reducedTools = [];
714
+ for (const tool of tools) {
715
+ if (isBuiltInTool(tool)) {
716
+ if (tool.type === "image_generation" && fields?.stream) {
717
+ // OpenAI sends a 400 error if partial_images is not set and we want to stream.
718
+ // We also set it to 1 since we don't support partial images yet.
719
+ tool.partial_images = 1;
720
+ }
721
+ reducedTools.push(tool);
722
+ }
723
+ else if ((0, base_1.isOpenAITool)(tool)) {
724
+ reducedTools.push({
725
+ type: "function",
726
+ name: tool.function.name,
727
+ parameters: tool.function.parameters,
728
+ description: tool.function.description,
729
+ strict: fields?.strict ?? null,
730
+ });
731
+ }
732
+ }
733
+ return reducedTools;
734
+ }
656
735
  function _convertChatOpenAIToolTypeToOpenAITool(tool, fields) {
657
736
  if ((0, base_1.isOpenAITool)(tool)) {
658
737
  if (fields?.strict !== undefined) {
@@ -1587,8 +1666,8 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1587
1666
  if (resFormat &&
1588
1667
  resFormat.type === "json_schema" &&
1589
1668
  resFormat.json_schema.schema &&
1590
- isZodSchema(resFormat.json_schema.schema)) {
1591
- return (0, zod_1.zodResponseFormat)(resFormat.json_schema.schema, resFormat.json_schema.name, {
1669
+ (0, types_1.isInteropZodSchema)(resFormat.json_schema.schema)) {
1670
+ return interopZodResponseFormat(resFormat.json_schema.schema, resFormat.json_schema.name, {
1592
1671
  description: resFormat.json_schema.description,
1593
1672
  });
1594
1673
  }
@@ -1646,25 +1725,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1646
1725
  truncation: options?.truncation,
1647
1726
  include: options?.include,
1648
1727
  tools: options?.tools?.length
1649
- ? options.tools
1650
- .map((tool) => {
1651
- if (isBuiltInTool(tool)) {
1652
- return tool;
1653
- }
1654
- else if ((0, base_1.isOpenAITool)(tool)) {
1655
- return {
1656
- type: "function",
1657
- name: tool.function.name,
1658
- parameters: tool.function.parameters,
1659
- description: tool.function.description,
1660
- strict,
1661
- };
1662
- }
1663
- else {
1664
- return null;
1665
- }
1728
+ ? _reduceChatOpenAIToolsForResponses(options.tools, {
1729
+ stream: this.streaming,
1730
+ strict,
1666
1731
  })
1667
- .filter((tool) => tool !== null)
1668
1732
  : undefined,
1669
1733
  tool_choice: isBuiltInToolChoice(options?.tool_choice)
1670
1734
  ? options?.tool_choice
@@ -1907,17 +1971,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1907
1971
  }
1908
1972
  async *_streamResponseChunks(messages, options, runManager) {
1909
1973
  if (this._useResponseApi(options)) {
1910
- const lastAIMessage = messages.filter((m) => (0, messages_1.isAIMessage)(m)).pop();
1911
- const lastAIMessageId = lastAIMessage?.response_metadata?.id;
1912
1974
  const streamIterable = await this.responseApiWithRetry({
1913
1975
  ...this.invocationParams(options, { streaming: true }),
1914
1976
  input: _convertMessagesToOpenAIResponsesParams(messages, this.model, this.zdrEnabled),
1915
1977
  stream: true,
1916
- ...(lastAIMessageId &&
1917
- lastAIMessageId.startsWith("resp_") &&
1918
- !this.zdrEnabled
1919
- ? { previous_response_id: lastAIMessageId }
1920
- : {}),
1921
1978
  }, options);
1922
1979
  for await (const data of streamIterable) {
1923
1980
  const chunk = _convertOpenAIResponsesDeltaToBaseMessageChunk(data);
@@ -2051,17 +2108,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2051
2108
  },
2052
2109
  };
2053
2110
  }
2054
- const lastAIMessage = messages.filter((m) => (0, messages_1.isAIMessage)(m)).pop();
2055
- const lastAIMessageId = lastAIMessage?.response_metadata?.id;
2056
2111
  const input = _convertMessagesToOpenAIResponsesParams(messages, this.model, this.zdrEnabled);
2057
2112
  const data = await this.responseApiWithRetry({
2058
2113
  input,
2059
2114
  ...invocationParams,
2060
- ...(lastAIMessageId &&
2061
- lastAIMessageId.startsWith("resp_") &&
2062
- !this.zdrEnabled
2063
- ? { previous_response_id: lastAIMessageId }
2064
- : {}),
2065
2115
  }, { signal: options?.signal, ...options?.options });
2066
2116
  return {
2067
2117
  generations: [
@@ -2371,7 +2421,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2371
2421
  const requestOptions = this._getClientOptions(options);
2372
2422
  return this.caller.call(async () => {
2373
2423
  try {
2374
- const res = await this.client.beta.chat.completions.parse(request, requestOptions);
2424
+ const res = await this.client.chat.completions.parse(request, requestOptions);
2375
2425
  return res;
2376
2426
  }
2377
2427
  catch (e) {
@@ -2458,15 +2508,21 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2458
2508
  console.warn(`[WARNING]: JSON Schema is not supported for model "${this.model}". Falling back to tool calling.`);
2459
2509
  }
2460
2510
  if (method === "jsonMode") {
2461
- llm = this.withConfig({
2462
- response_format: { type: "json_object" },
2463
- });
2464
- if (isZodSchema(schema)) {
2511
+ let outputFormatSchema;
2512
+ if ((0, types_1.isInteropZodSchema)(schema)) {
2465
2513
  outputParser = output_parsers_1.StructuredOutputParser.fromZodSchema(schema);
2514
+ outputFormatSchema = (0, json_schema_1.toJsonSchema)(schema);
2466
2515
  }
2467
2516
  else {
2468
2517
  outputParser = new output_parsers_1.JsonOutputParser();
2469
2518
  }
2519
+ llm = this.withConfig({
2520
+ response_format: { type: "json_object" },
2521
+ ls_structured_output_format: {
2522
+ kwargs: { method: "jsonMode" },
2523
+ schema: outputFormatSchema,
2524
+ },
2525
+ });
2470
2526
  }
2471
2527
  else if (method === "jsonSchema") {
2472
2528
  llm = this.withConfig({
@@ -2474,13 +2530,17 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2474
2530
  type: "json_schema",
2475
2531
  json_schema: {
2476
2532
  name: name ?? "extract",
2477
- description: schema.description,
2533
+ description: (0, types_1.getSchemaDescription)(schema),
2478
2534
  schema,
2479
2535
  strict: config?.strict,
2480
2536
  },
2481
2537
  },
2538
+ ls_structured_output_format: {
2539
+ kwargs: { method: "jsonSchema" },
2540
+ schema: (0, json_schema_1.toJsonSchema)(schema),
2541
+ },
2482
2542
  });
2483
- if (isZodSchema(schema)) {
2543
+ if ((0, types_1.isInteropZodSchema)(schema)) {
2484
2544
  const altParser = output_parsers_1.StructuredOutputParser.fromZodSchema(schema);
2485
2545
  outputParser = runnables_1.RunnableLambda.from((aiMessage) => {
2486
2546
  if ("parsed" in aiMessage.additional_kwargs) {
@@ -2496,8 +2556,8 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2496
2556
  else {
2497
2557
  let functionName = name ?? "extract";
2498
2558
  // Is function calling
2499
- if (isZodSchema(schema)) {
2500
- const asJsonSchema = (0, zod_to_json_schema_1.zodToJsonSchema)(schema);
2559
+ if ((0, types_1.isInteropZodSchema)(schema)) {
2560
+ const asJsonSchema = (0, json_schema_1.toJsonSchema)(schema);
2501
2561
  llm = this.withConfig({
2502
2562
  tools: [
2503
2563
  {
@@ -2515,6 +2575,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2515
2575
  name: functionName,
2516
2576
  },
2517
2577
  },
2578
+ ls_structured_output_format: {
2579
+ kwargs: { method: "functionCalling" },
2580
+ schema: asJsonSchema,
2581
+ },
2518
2582
  // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
2519
2583
  ...(config?.strict !== undefined ? { strict: config.strict } : {}),
2520
2584
  });
@@ -2553,6 +2617,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2553
2617
  name: functionName,
2554
2618
  },
2555
2619
  },
2620
+ ls_structured_output_format: {
2621
+ kwargs: { method: "functionCalling" },
2622
+ schema: (0, json_schema_1.toJsonSchema)(schema),
2623
+ },
2556
2624
  // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
2557
2625
  ...(config?.strict !== undefined ? { strict: config.strict } : {}),
2558
2626
  });
@@ -2579,12 +2647,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
2579
2647
  }
2580
2648
  }
2581
2649
  exports.ChatOpenAI = ChatOpenAI;
2582
- function isZodSchema(
2583
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
2584
- input) {
2585
- // Check for a characteristic method of Zod schemas
2586
- return typeof input?.parse === "function";
2587
- }
2588
2650
  function isStructuredOutputMethodParams(x
2589
2651
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
2590
2652
  ) {
@@ -2593,3 +2655,49 @@ function isStructuredOutputMethodParams(x
2593
2655
  typeof x.schema ===
2594
2656
  "object");
2595
2657
  }
2658
+ // inlined from openai/lib/parser.ts
2659
+ function makeParseableResponseFormat(response_format, parser) {
2660
+ const obj = { ...response_format };
2661
+ Object.defineProperties(obj, {
2662
+ $brand: {
2663
+ value: "auto-parseable-response-format",
2664
+ enumerable: false,
2665
+ },
2666
+ $parseRaw: {
2667
+ value: parser,
2668
+ enumerable: false,
2669
+ },
2670
+ });
2671
+ return obj;
2672
+ }
2673
+ function interopZodResponseFormat(zodSchema, name, props) {
2674
+ if ((0, types_1.isZodSchemaV3)(zodSchema)) {
2675
+ return (0, zod_1.zodResponseFormat)(zodSchema, name, props);
2676
+ }
2677
+ if ((0, types_1.isZodSchemaV4)(zodSchema)) {
2678
+ return makeParseableResponseFormat({
2679
+ type: "json_schema",
2680
+ json_schema: {
2681
+ ...props,
2682
+ name,
2683
+ strict: true,
2684
+ schema: z4.toJSONSchema(zodSchema, {
2685
+ cycles: "ref", // equivalent to nameStrategy: 'duplicate-ref'
2686
+ reused: "ref", // equivalent to $refStrategy: 'extract-to-root'
2687
+ override(ctx) {
2688
+ ctx.jsonSchema.title = name; // equivalent to `name` property
2689
+ // TODO: implement `nullableStrategy` patch-fix (zod doesn't support openApi3 json schema target)
2690
+ // TODO: implement `openaiStrictMode` patch-fix (where optional properties without `nullable` are not supported)
2691
+ },
2692
+ /// property equivalents from native `zodResponseFormat` fn
2693
+ // openaiStrictMode: true,
2694
+ // name,
2695
+ // nameStrategy: 'duplicate-ref',
2696
+ // $refStrategy: 'extract-to-root',
2697
+ // nullableStrategy: 'property',
2698
+ }),
2699
+ },
2700
+ }, (content) => z4.parse(zodSchema, JSON.parse(content)));
2701
+ }
2702
+ throw new Error("Unsupported schema response format");
2703
+ }
@@ -4,8 +4,8 @@ import { AIMessageChunk, type BaseMessage, ChatMessageChunk, FunctionMessageChun
4
4
  import { ChatGenerationChunk, type ChatResult } from "@langchain/core/outputs";
5
5
  import { BaseChatModel, type BindToolsInput, 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
- import { z } from "zod";
8
7
  import { Runnable } from "@langchain/core/runnables";
8
+ import { InteropZodType } from "@langchain/core/utils/types";
9
9
  import { type OpenAICallOptions, type OpenAIChatInput, type OpenAICoreRequestOptions, type ChatOpenAIResponseFormat } from "./types.js";
10
10
  import { OpenAIToolChoice } from "./utils/openai.js";
11
11
  export type { OpenAICallOptions, OpenAIChatInput };
@@ -841,17 +841,17 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
841
841
  * @param {OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming} request
842
842
  * @param {OpenAICoreRequestOptions | undefined} options
843
843
  */
844
- betaParsedCompletionWithRetry(request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming, options?: OpenAICoreRequestOptions): Promise<ReturnType<OpenAIClient["beta"]["chat"]["completions"]["parse"]>>;
844
+ betaParsedCompletionWithRetry(request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming, options?: OpenAICoreRequestOptions): Promise<ReturnType<OpenAIClient["chat"]["completions"]["parse"]>>;
845
845
  protected _getClientOptions(options: OpenAICoreRequestOptions | undefined): OpenAICoreRequestOptions;
846
846
  _llmType(): string;
847
847
  /** @ignore */
848
848
  _combineLLMOutput(...llmOutputs: OpenAILLMOutput[]): OpenAILLMOutput;
849
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
850
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
849
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
850
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
851
851
  raw: BaseMessage;
852
852
  parsed: RunOutput;
853
853
  }>;
854
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: z.ZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<boolean>): Runnable<BaseLanguageModelInput, RunOutput> | Runnable<BaseLanguageModelInput, {
854
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<boolean>): Runnable<BaseLanguageModelInput, RunOutput> | Runnable<BaseLanguageModelInput, {
855
855
  raw: BaseMessage;
856
856
  parsed: RunOutput;
857
857
  }>;