@langchain/openai 1.0.0-alpha.3 → 1.1.0

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 (139) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/azure/chat_models/common.cjs +130 -0
  3. package/dist/azure/chat_models/common.cjs.map +1 -0
  4. package/dist/azure/chat_models/common.d.cts +16 -0
  5. package/dist/azure/chat_models/common.d.cts.map +1 -0
  6. package/dist/azure/chat_models/common.d.ts +16 -0
  7. package/dist/azure/chat_models/common.d.ts.map +1 -0
  8. package/dist/azure/chat_models/common.js +124 -0
  9. package/dist/azure/chat_models/common.js.map +1 -0
  10. package/dist/azure/chat_models/completions.cjs +50 -0
  11. package/dist/azure/chat_models/completions.cjs.map +1 -0
  12. package/dist/azure/chat_models/completions.d.cts +29 -0
  13. package/dist/azure/chat_models/completions.d.cts.map +1 -0
  14. package/dist/azure/chat_models/completions.d.ts +29 -0
  15. package/dist/azure/chat_models/completions.d.ts.map +1 -0
  16. package/dist/azure/chat_models/completions.js +50 -0
  17. package/dist/azure/chat_models/completions.js.map +1 -0
  18. package/dist/azure/{chat_models.cjs → chat_models/index.cjs} +14 -214
  19. package/dist/azure/chat_models/index.cjs.map +1 -0
  20. package/dist/azure/{chat_models.d.ts → chat_models/index.d.cts} +6 -11
  21. package/dist/azure/chat_models/index.d.cts.map +1 -0
  22. package/dist/azure/{chat_models.d.cts → chat_models/index.d.ts} +6 -11
  23. package/dist/azure/chat_models/index.d.ts.map +1 -0
  24. package/dist/azure/{chat_models.js → chat_models/index.js} +6 -205
  25. package/dist/azure/chat_models/index.js.map +1 -0
  26. package/dist/azure/chat_models/responses.cjs +50 -0
  27. package/dist/azure/chat_models/responses.cjs.map +1 -0
  28. package/dist/azure/chat_models/responses.d.cts +29 -0
  29. package/dist/azure/chat_models/responses.d.cts.map +1 -0
  30. package/dist/azure/chat_models/responses.d.ts +29 -0
  31. package/dist/azure/chat_models/responses.d.ts.map +1 -0
  32. package/dist/azure/chat_models/responses.js +50 -0
  33. package/dist/azure/chat_models/responses.js.map +1 -0
  34. package/dist/chat_models/base.cjs +533 -0
  35. package/dist/chat_models/base.cjs.map +1 -0
  36. package/dist/chat_models/base.d.cts +272 -0
  37. package/dist/chat_models/base.d.cts.map +1 -0
  38. package/dist/chat_models/base.d.ts +272 -0
  39. package/dist/chat_models/base.d.ts.map +1 -0
  40. package/dist/chat_models/base.js +532 -0
  41. package/dist/chat_models/base.js.map +1 -0
  42. package/dist/chat_models/completions.cjs +258 -0
  43. package/dist/chat_models/completions.cjs.map +1 -0
  44. package/dist/chat_models/completions.d.cts +44 -0
  45. package/dist/chat_models/completions.d.cts.map +1 -0
  46. package/dist/chat_models/completions.d.ts +44 -0
  47. package/dist/chat_models/completions.d.ts.map +1 -0
  48. package/dist/chat_models/completions.js +257 -0
  49. package/dist/chat_models/completions.js.map +1 -0
  50. package/dist/chat_models/index.cjs +608 -0
  51. package/dist/chat_models/index.cjs.map +1 -0
  52. package/dist/chat_models/index.d.cts +593 -0
  53. package/dist/chat_models/index.d.cts.map +1 -0
  54. package/dist/chat_models/index.d.ts +593 -0
  55. package/dist/chat_models/index.d.ts.map +1 -0
  56. package/dist/chat_models/index.js +608 -0
  57. package/dist/chat_models/index.js.map +1 -0
  58. package/dist/chat_models/responses.cjs +189 -0
  59. package/dist/chat_models/responses.cjs.map +1 -0
  60. package/dist/chat_models/responses.d.cts +62 -0
  61. package/dist/chat_models/responses.d.cts.map +1 -0
  62. package/dist/chat_models/responses.d.ts +62 -0
  63. package/dist/chat_models/responses.d.ts.map +1 -0
  64. package/dist/chat_models/responses.js +188 -0
  65. package/dist/chat_models/responses.js.map +1 -0
  66. package/dist/converters/completions.cjs +603 -0
  67. package/dist/converters/completions.cjs.map +1 -0
  68. package/dist/converters/completions.js +599 -0
  69. package/dist/converters/completions.js.map +1 -0
  70. package/dist/converters/responses.cjs +892 -0
  71. package/dist/converters/responses.cjs.map +1 -0
  72. package/dist/converters/responses.js +889 -0
  73. package/dist/converters/responses.js.map +1 -0
  74. package/dist/index.cjs +14 -9
  75. package/dist/index.d.cts +9 -4
  76. package/dist/index.d.ts +9 -4
  77. package/dist/index.js +8 -4
  78. package/dist/langchain-core/dist/callbacks/base.d.ts +1 -0
  79. package/dist/langchain-core/dist/callbacks/manager.d.ts +2 -0
  80. package/dist/langchain-core/dist/language_models/base.d.ts +5 -0
  81. package/dist/langchain-core/dist/language_models/chat_models.d.cts +13 -0
  82. package/dist/langchain-core/dist/language_models/chat_models.d.cts.map +1 -0
  83. package/dist/langchain-core/dist/language_models/chat_models.d.ts +20 -0
  84. package/dist/langchain-core/dist/language_models/chat_models.d.ts.map +1 -0
  85. package/dist/langchain-core/dist/runnables/base.d.ts +7 -0
  86. package/dist/langchain-core/dist/runnables/graph.d.ts +1 -0
  87. package/dist/langchain-core/dist/runnables/types.d.ts +2 -0
  88. package/dist/langchain-core/dist/tools/types.d.ts +5 -0
  89. package/dist/langchain-core/dist/tracers/base.d.ts +2 -0
  90. package/dist/langchain-core/dist/tracers/event_stream.d.ts +1 -0
  91. package/dist/langchain-core/dist/tracers/log_stream.d.ts +3 -0
  92. package/dist/langchain-core/dist/utils/types/index.d.ts +1 -0
  93. package/dist/langchain-core/dist/utils/types/zod.d.ts +1 -0
  94. package/dist/llms.cjs +1 -1
  95. package/dist/llms.d.cts +1 -1
  96. package/dist/llms.js +1 -1
  97. package/dist/utils/errors.cjs +1 -1
  98. package/dist/utils/errors.cjs.map +1 -1
  99. package/dist/utils/errors.js +1 -1
  100. package/dist/utils/errors.js.map +1 -1
  101. package/dist/utils/misc.js +2 -2
  102. package/dist/utils/misc.js.map +1 -1
  103. package/dist/utils/output.cjs +0 -12
  104. package/dist/utils/output.cjs.map +1 -1
  105. package/dist/utils/output.js +1 -12
  106. package/dist/utils/output.js.map +1 -1
  107. package/dist/utils/prompts.cjs +2 -2
  108. package/dist/utils/prompts.cjs.map +1 -1
  109. package/dist/utils/prompts.d.cts +1 -0
  110. package/dist/utils/prompts.d.cts.map +1 -1
  111. package/dist/utils/prompts.d.ts +1 -0
  112. package/dist/utils/prompts.d.ts.map +1 -1
  113. package/dist/utils/prompts.js +2 -2
  114. package/dist/utils/prompts.js.map +1 -1
  115. package/package.json +10 -7
  116. package/dist/azure/chat_models.cjs.map +0 -1
  117. package/dist/azure/chat_models.d.cts.map +0 -1
  118. package/dist/azure/chat_models.d.ts.map +0 -1
  119. package/dist/azure/chat_models.js.map +0 -1
  120. package/dist/chat_models.cjs +0 -1967
  121. package/dist/chat_models.cjs.map +0 -1
  122. package/dist/chat_models.d.cts +0 -933
  123. package/dist/chat_models.d.cts.map +0 -1
  124. package/dist/chat_models.d.ts +0 -933
  125. package/dist/chat_models.d.ts.map +0 -1
  126. package/dist/chat_models.js +0 -1963
  127. package/dist/chat_models.js.map +0 -1
  128. package/dist/utils/message_inputs.cjs +0 -139
  129. package/dist/utils/message_inputs.cjs.map +0 -1
  130. package/dist/utils/message_inputs.d.cts +0 -9
  131. package/dist/utils/message_inputs.d.cts.map +0 -1
  132. package/dist/utils/message_inputs.d.ts +0 -9
  133. package/dist/utils/message_inputs.d.ts.map +0 -1
  134. package/dist/utils/message_inputs.js +0 -137
  135. package/dist/utils/message_inputs.js.map +0 -1
  136. package/dist/utils/standard.cjs +0 -315
  137. package/dist/utils/standard.cjs.map +0 -1
  138. package/dist/utils/standard.js +0 -313
  139. package/dist/utils/standard.js.map +0 -1
@@ -0,0 +1,603 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const require_misc = require('../utils/misc.cjs');
3
+ const require_output = require('../utils/output.cjs');
4
+ const __langchain_core_output_parsers_openai_tools = require_rolldown_runtime.__toESM(require("@langchain/core/output_parsers/openai_tools"));
5
+ const __langchain_core_messages = require_rolldown_runtime.__toESM(require("@langchain/core/messages"));
6
+
7
+ //#region src/converters/completions.ts
8
+ /**
9
+ * @deprecated This converter is an internal detail of the OpenAI provider. Do not use it directly. This will be revisited in a future release.
10
+ */
11
+ const completionsApiContentBlockConverter = {
12
+ providerName: "ChatOpenAI",
13
+ fromStandardTextBlock(block) {
14
+ return {
15
+ type: "text",
16
+ text: block.text
17
+ };
18
+ },
19
+ fromStandardImageBlock(block) {
20
+ if (block.source_type === "url") return {
21
+ type: "image_url",
22
+ image_url: {
23
+ url: block.url,
24
+ ...block.metadata?.detail ? { detail: block.metadata.detail } : {}
25
+ }
26
+ };
27
+ if (block.source_type === "base64") {
28
+ const url = `data:${block.mime_type ?? ""};base64,${block.data}`;
29
+ return {
30
+ type: "image_url",
31
+ image_url: {
32
+ url,
33
+ ...block.metadata?.detail ? { detail: block.metadata.detail } : {}
34
+ }
35
+ };
36
+ }
37
+ throw new Error(`Image content blocks with source_type ${block.source_type} are not supported for ChatOpenAI`);
38
+ },
39
+ fromStandardAudioBlock(block) {
40
+ if (block.source_type === "url") {
41
+ const data = (0, __langchain_core_messages.parseBase64DataUrl)({ dataUrl: block.url });
42
+ if (!data) throw new Error(`URL audio blocks with source_type ${block.source_type} must be formatted as a data URL for ChatOpenAI`);
43
+ const rawMimeType = data.mime_type || block.mime_type || "";
44
+ let mimeType;
45
+ try {
46
+ mimeType = (0, __langchain_core_messages.parseMimeType)(rawMimeType);
47
+ } catch {
48
+ throw new Error(`Audio blocks with source_type ${block.source_type} must have mime type of audio/wav or audio/mp3`);
49
+ }
50
+ if (mimeType.type !== "audio" || mimeType.subtype !== "wav" && mimeType.subtype !== "mp3") throw new Error(`Audio blocks with source_type ${block.source_type} must have mime type of audio/wav or audio/mp3`);
51
+ return {
52
+ type: "input_audio",
53
+ input_audio: {
54
+ format: mimeType.subtype,
55
+ data: data.data
56
+ }
57
+ };
58
+ }
59
+ if (block.source_type === "base64") {
60
+ let mimeType;
61
+ try {
62
+ mimeType = (0, __langchain_core_messages.parseMimeType)(block.mime_type ?? "");
63
+ } catch {
64
+ throw new Error(`Audio blocks with source_type ${block.source_type} must have mime type of audio/wav or audio/mp3`);
65
+ }
66
+ if (mimeType.type !== "audio" || mimeType.subtype !== "wav" && mimeType.subtype !== "mp3") throw new Error(`Audio blocks with source_type ${block.source_type} must have mime type of audio/wav or audio/mp3`);
67
+ return {
68
+ type: "input_audio",
69
+ input_audio: {
70
+ format: mimeType.subtype,
71
+ data: block.data
72
+ }
73
+ };
74
+ }
75
+ throw new Error(`Audio content blocks with source_type ${block.source_type} are not supported for ChatOpenAI`);
76
+ },
77
+ fromStandardFileBlock(block) {
78
+ if (block.source_type === "url") {
79
+ const data = (0, __langchain_core_messages.parseBase64DataUrl)({ dataUrl: block.url });
80
+ if (!data) throw new Error(`URL file blocks with source_type ${block.source_type} must be formatted as a data URL for ChatOpenAI`);
81
+ return {
82
+ type: "file",
83
+ file: {
84
+ file_data: block.url,
85
+ ...block.metadata?.filename || block.metadata?.name ? { filename: block.metadata?.filename || block.metadata?.name } : {}
86
+ }
87
+ };
88
+ }
89
+ if (block.source_type === "base64") return {
90
+ type: "file",
91
+ file: {
92
+ file_data: `data:${block.mime_type ?? ""};base64,${block.data}`,
93
+ ...block.metadata?.filename || block.metadata?.name || block.metadata?.title ? { filename: block.metadata?.filename || block.metadata?.name || block.metadata?.title } : {}
94
+ }
95
+ };
96
+ if (block.source_type === "id") return {
97
+ type: "file",
98
+ file: { file_id: block.id }
99
+ };
100
+ throw new Error(`File content blocks with source_type ${block.source_type} are not supported for ChatOpenAI`);
101
+ }
102
+ };
103
+ /**
104
+ * Converts an OpenAI Chat Completions API message to a LangChain BaseMessage.
105
+ *
106
+ * This converter transforms messages from OpenAI's Chat Completions API format into
107
+ * LangChain's internal message representation, handling various message types and
108
+ * preserving metadata, tool calls, and other relevant information.
109
+ *
110
+ * @remarks
111
+ * The converter handles the following message roles:
112
+ * - `assistant`: Converted to {@link AIMessage} with support for tool calls, function calls,
113
+ * audio content, and multi-modal outputs
114
+ * - Other roles: Converted to generic {@link ChatMessage}
115
+ *
116
+ * For assistant messages, the converter:
117
+ * - Parses and validates tool calls, separating valid and invalid calls
118
+ * - Preserves function call information in additional_kwargs
119
+ * - Includes usage statistics and system fingerprint in response_metadata
120
+ * - Handles multi-modal content (text, images, audio)
121
+ * - Optionally includes the raw API response for debugging
122
+ *
123
+ * @param params - Conversion parameters
124
+ * @param params.message - The OpenAI chat completion message to convert
125
+ * @param params.rawResponse - The complete raw response from OpenAI's API, used to extract
126
+ * metadata like model name, usage statistics, and system fingerprint
127
+ * @param params.includeRawResponse - If true, includes the raw OpenAI response in the
128
+ * message's additional_kwargs under the `__raw_response` key. Useful for debugging
129
+ * or accessing provider-specific fields. Defaults to false.
130
+ *
131
+ * @returns A LangChain BaseMessage instance:
132
+ * - {@link AIMessage} for assistant messages with tool calls, metadata, and content
133
+ * - {@link ChatMessage} for all other message types
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const baseMessage = convertCompletionsMessageToBaseMessage({
138
+ * message: {
139
+ * role: "assistant",
140
+ * content: "Hello! How can I help you?",
141
+ * tool_calls: [
142
+ * {
143
+ * id: "call_123",
144
+ * type: "function",
145
+ * function: { name: "get_weather", arguments: '{"location":"NYC"}' }
146
+ * }
147
+ * ]
148
+ * },
149
+ * rawResponse: completionResponse,
150
+ * includeRawResponse: true
151
+ * });
152
+ * // Returns an AIMessage with parsed tool calls and metadata
153
+ * ```
154
+ *
155
+ * @throws {Error} If tool call parsing fails, the invalid tool call is captured in
156
+ * the `invalid_tool_calls` array rather than throwing an error
157
+ *
158
+ */
159
+ const convertCompletionsMessageToBaseMessage = ({ message, rawResponse, includeRawResponse }) => {
160
+ const rawToolCalls = message.tool_calls;
161
+ switch (message.role) {
162
+ case "assistant": {
163
+ const toolCalls = [];
164
+ const invalidToolCalls = [];
165
+ for (const rawToolCall of rawToolCalls ?? []) try {
166
+ toolCalls.push((0, __langchain_core_output_parsers_openai_tools.parseToolCall)(rawToolCall, { returnId: true }));
167
+ } catch (e) {
168
+ invalidToolCalls.push((0, __langchain_core_output_parsers_openai_tools.makeInvalidToolCall)(rawToolCall, e.message));
169
+ }
170
+ const additional_kwargs = {
171
+ function_call: message.function_call,
172
+ tool_calls: rawToolCalls
173
+ };
174
+ if (includeRawResponse !== void 0) additional_kwargs.__raw_response = rawResponse;
175
+ const response_metadata = {
176
+ model_provider: "openai",
177
+ model_name: rawResponse.model,
178
+ ...rawResponse.system_fingerprint ? {
179
+ usage: { ...rawResponse.usage },
180
+ system_fingerprint: rawResponse.system_fingerprint
181
+ } : {}
182
+ };
183
+ if (message.audio) additional_kwargs.audio = message.audio;
184
+ const content = require_output.handleMultiModalOutput(message.content || "", rawResponse.choices?.[0]?.message);
185
+ return new __langchain_core_messages.AIMessage({
186
+ content,
187
+ tool_calls: toolCalls,
188
+ invalid_tool_calls: invalidToolCalls,
189
+ additional_kwargs,
190
+ response_metadata,
191
+ id: rawResponse.id
192
+ });
193
+ }
194
+ default: return new __langchain_core_messages.ChatMessage(message.content || "", message.role ?? "unknown");
195
+ }
196
+ };
197
+ /**
198
+ * Converts an OpenAI Chat Completions API delta (streaming chunk) to a LangChain BaseMessageChunk.
199
+ *
200
+ * This converter is used during streaming responses to transform incremental updates from OpenAI's
201
+ * Chat Completions API into LangChain message chunks. It handles various message types, tool calls,
202
+ * function calls, audio content, and role-specific message chunk creation.
203
+ *
204
+ * @param params - Conversion parameters
205
+ * @param params.delta - The delta object from an OpenAI streaming chunk containing incremental
206
+ * message updates. May include content, role, tool_calls, function_call, audio, etc.
207
+ * @param params.rawResponse - The complete raw ChatCompletionChunk response from OpenAI,
208
+ * containing metadata like model info, usage stats, and the delta
209
+ * @param params.includeRawResponse - Optional flag to include the raw OpenAI response in the
210
+ * message chunk's additional_kwargs. Useful for debugging or accessing provider-specific data
211
+ * @param params.defaultRole - Optional default role to use if the delta doesn't specify one.
212
+ * Typically used to maintain role consistency across chunks in a streaming response
213
+ *
214
+ * @returns A BaseMessageChunk subclass appropriate for the message role:
215
+ * - HumanMessageChunk for "user" role
216
+ * - AIMessageChunk for "assistant" role (includes tool call chunks)
217
+ * - SystemMessageChunk for "system" or "developer" roles
218
+ * - FunctionMessageChunk for "function" role
219
+ * - ToolMessageChunk for "tool" role
220
+ * - ChatMessageChunk for any other role
221
+ *
222
+ * @example
223
+ * Basic streaming text chunk:
224
+ * ```typescript
225
+ * const chunk = convertCompletionsDeltaToBaseMessageChunk({
226
+ * delta: { role: "assistant", content: "Hello" },
227
+ * rawResponse: { id: "chatcmpl-123", model: "gpt-4", ... }
228
+ * });
229
+ * // Returns: AIMessageChunk with content "Hello"
230
+ * ```
231
+ *
232
+ * @example
233
+ * Streaming chunk with tool call:
234
+ * ```typescript
235
+ * const chunk = convertCompletionsDeltaToBaseMessageChunk({
236
+ * delta: {
237
+ * role: "assistant",
238
+ * tool_calls: [{
239
+ * index: 0,
240
+ * id: "call_123",
241
+ * function: { name: "get_weather", arguments: '{"location":' }
242
+ * }]
243
+ * },
244
+ * rawResponse: { id: "chatcmpl-123", ... }
245
+ * });
246
+ * // Returns: AIMessageChunk with tool_call_chunks containing partial tool call data
247
+ * ```
248
+ *
249
+ * @remarks
250
+ * - Tool calls are converted to ToolCallChunk objects with incremental data
251
+ * - Audio content includes the chunk index from the raw response
252
+ * - The "developer" role is mapped to SystemMessageChunk with a special marker
253
+ * - Response metadata includes model provider info and usage statistics
254
+ * - Function calls and tool calls are stored in additional_kwargs for compatibility
255
+ */
256
+ const convertCompletionsDeltaToBaseMessageChunk = ({ delta, rawResponse, includeRawResponse, defaultRole }) => {
257
+ const role = delta.role ?? defaultRole;
258
+ const content = delta.content ?? "";
259
+ let additional_kwargs;
260
+ if (delta.function_call) additional_kwargs = { function_call: delta.function_call };
261
+ else if (delta.tool_calls) additional_kwargs = { tool_calls: delta.tool_calls };
262
+ else additional_kwargs = {};
263
+ if (includeRawResponse) additional_kwargs.__raw_response = rawResponse;
264
+ if (delta.audio) additional_kwargs.audio = {
265
+ ...delta.audio,
266
+ index: rawResponse.choices[0].index
267
+ };
268
+ const response_metadata = {
269
+ model_provider: "openai",
270
+ usage: { ...rawResponse.usage }
271
+ };
272
+ if (role === "user") return new __langchain_core_messages.HumanMessageChunk({
273
+ content,
274
+ response_metadata
275
+ });
276
+ else if (role === "assistant") {
277
+ const toolCallChunks = [];
278
+ if (Array.isArray(delta.tool_calls)) for (const rawToolCall of delta.tool_calls) toolCallChunks.push({
279
+ name: rawToolCall.function?.name,
280
+ args: rawToolCall.function?.arguments,
281
+ id: rawToolCall.id,
282
+ index: rawToolCall.index,
283
+ type: "tool_call_chunk"
284
+ });
285
+ return new __langchain_core_messages.AIMessageChunk({
286
+ content,
287
+ tool_call_chunks: toolCallChunks,
288
+ additional_kwargs,
289
+ id: rawResponse.id,
290
+ response_metadata
291
+ });
292
+ } else if (role === "system") return new __langchain_core_messages.SystemMessageChunk({
293
+ content,
294
+ response_metadata
295
+ });
296
+ else if (role === "developer") return new __langchain_core_messages.SystemMessageChunk({
297
+ content,
298
+ response_metadata,
299
+ additional_kwargs: { __openai_role__: "developer" }
300
+ });
301
+ else if (role === "function") return new __langchain_core_messages.FunctionMessageChunk({
302
+ content,
303
+ additional_kwargs,
304
+ name: delta.name,
305
+ response_metadata
306
+ });
307
+ else if (role === "tool") return new __langchain_core_messages.ToolMessageChunk({
308
+ content,
309
+ additional_kwargs,
310
+ tool_call_id: delta.tool_call_id,
311
+ response_metadata
312
+ });
313
+ else return new __langchain_core_messages.ChatMessageChunk({
314
+ content,
315
+ role,
316
+ response_metadata
317
+ });
318
+ };
319
+ /**
320
+ * Converts a standard LangChain content block to an OpenAI Completions API content part.
321
+ *
322
+ * This converter transforms LangChain's standardized content blocks (image, audio, file)
323
+ * into the format expected by OpenAI's Chat Completions API. It handles various content
324
+ * types including images (URL or base64), audio (base64), and files (data or file ID).
325
+ *
326
+ * @param block - The standard content block to convert. Can be an image, audio, or file block.
327
+ *
328
+ * @returns An OpenAI Chat Completions content part object, or undefined if the block
329
+ * cannot be converted (e.g., missing required data).
330
+ *
331
+ * @example
332
+ * Image with URL:
333
+ * ```typescript
334
+ * const block = { type: "image", url: "https://example.com/image.jpg" };
335
+ * const part = convertStandardContentBlockToCompletionsContentPart(block);
336
+ * // Returns: { type: "image_url", image_url: { url: "https://example.com/image.jpg" } }
337
+ * ```
338
+ *
339
+ * @example
340
+ * Image with base64 data:
341
+ * ```typescript
342
+ * const block = { type: "image", data: "iVBORw0KGgo...", mimeType: "image/png" };
343
+ * const part = convertStandardContentBlockToCompletionsContentPart(block);
344
+ * // Returns: { type: "image_url", image_url: { url: "data:image/png;base64,iVBORw0KGgo..." } }
345
+ * ```
346
+ */
347
+ const convertStandardContentBlockToCompletionsContentPart = (block) => {
348
+ if (block.type === "image") {
349
+ if (block.url) return {
350
+ type: "image_url",
351
+ image_url: { url: block.url }
352
+ };
353
+ else if (block.data) return {
354
+ type: "image_url",
355
+ image_url: { url: `data:${block.mimeType};base64,${block.data}` }
356
+ };
357
+ }
358
+ if (block.type === "audio") {
359
+ if (block.data) {
360
+ const format = (0, __langchain_core_messages.iife)(() => {
361
+ const [, format$1] = block.mimeType.split("/");
362
+ if (format$1 === "wav" || format$1 === "mp3") return format$1;
363
+ return "wav";
364
+ });
365
+ return {
366
+ type: "input_audio",
367
+ input_audio: {
368
+ data: block.data.toString(),
369
+ format
370
+ }
371
+ };
372
+ }
373
+ }
374
+ if (block.type === "file") {
375
+ if (block.data) return {
376
+ type: "file",
377
+ file: { file_data: block.data.toString() }
378
+ };
379
+ if (block.fileId) return {
380
+ type: "file",
381
+ file: { file_id: block.fileId }
382
+ };
383
+ }
384
+ return void 0;
385
+ };
386
+ /**
387
+ * Converts a LangChain BaseMessage with standard content blocks to an OpenAI Chat Completions API message parameter.
388
+ *
389
+ * This converter transforms LangChain's standardized message format (using contentBlocks) into the format
390
+ * expected by OpenAI's Chat Completions API. It handles role mapping, content filtering, and multi-modal
391
+ * content conversion for various message types.
392
+ *
393
+ * @remarks
394
+ * The converter performs the following transformations:
395
+ * - Maps LangChain message roles to OpenAI API roles (user, assistant, system, developer, tool, function)
396
+ * - For reasoning models, automatically converts "system" role to "developer" role
397
+ * - Filters content blocks based on message role (most roles only include text blocks)
398
+ * - For user messages, converts multi-modal content blocks (images, audio, files) to OpenAI format
399
+ * - Preserves tool call IDs for tool messages and function names for function messages
400
+ *
401
+ * Role-specific behavior:
402
+ * - **developer**: Returns only text content blocks (used for reasoning models)
403
+ * - **system**: Returns only text content blocks
404
+ * - **assistant**: Returns only text content blocks
405
+ * - **tool**: Returns only text content blocks with tool_call_id preserved
406
+ * - **function**: Returns text content blocks joined as a single string with function name
407
+ * - **user** (default): Returns multi-modal content including text, images, audio, and files
408
+ *
409
+ * @param params - Conversion parameters
410
+ * @param params.message - The LangChain BaseMessage to convert. Must have contentBlocks property
411
+ * containing an array of standard content blocks (text, image, audio, file, etc.)
412
+ * @param params.model - Optional model name. Used to determine if special role mapping is needed
413
+ * (e.g., "system" -> "developer" for reasoning models like o1)
414
+ *
415
+ * @returns An OpenAI ChatCompletionMessageParam object formatted for the Chat Completions API.
416
+ * The structure varies by role:
417
+ * - Developer/System/Assistant: `{ role, content: TextBlock[] }`
418
+ * - Tool: `{ role: "tool", tool_call_id, content: TextBlock[] }`
419
+ * - Function: `{ role: "function", name, content: string }`
420
+ * - User: `{ role: "user", content: Array<TextPart | ImagePart | AudioPart | FilePart> }`
421
+ *
422
+ * @example
423
+ * Simple text message:
424
+ * ```typescript
425
+ * const message = new HumanMessage({
426
+ * content: [{ type: "text", text: "Hello!" }]
427
+ * });
428
+ * const param = convertStandardContentMessageToCompletionsMessage({ message });
429
+ * // Returns: { role: "user", content: [{ type: "text", text: "Hello!" }] }
430
+ * ```
431
+ *
432
+ * @example
433
+ * Multi-modal user message with image:
434
+ * ```typescript
435
+ * const message = new HumanMessage({
436
+ * content: [
437
+ * { type: "text", text: "What's in this image?" },
438
+ * { type: "image", url: "https://example.com/image.jpg" }
439
+ * ]
440
+ * });
441
+ * const param = convertStandardContentMessageToCompletionsMessage({ message });
442
+ * // Returns: {
443
+ * // role: "user",
444
+ * // content: [
445
+ * // { type: "text", text: "What's in this image?" },
446
+ * // { type: "image_url", image_url: { url: "https://example.com/image.jpg" } }
447
+ * // ]
448
+ * // }
449
+ * ```
450
+ */
451
+ const convertStandardContentMessageToCompletionsMessage = ({ message, model }) => {
452
+ let role = require_misc.messageToOpenAIRole(message);
453
+ if (role === "system" && require_misc.isReasoningModel(model)) role = "developer";
454
+ if (role === "developer") return {
455
+ role: "developer",
456
+ content: message.contentBlocks.filter((block) => block.type === "text")
457
+ };
458
+ else if (role === "system") return {
459
+ role: "system",
460
+ content: message.contentBlocks.filter((block) => block.type === "text")
461
+ };
462
+ else if (role === "assistant") return {
463
+ role: "assistant",
464
+ content: message.contentBlocks.filter((block) => block.type === "text")
465
+ };
466
+ else if (role === "tool" && __langchain_core_messages.ToolMessage.isInstance(message)) return {
467
+ role: "tool",
468
+ tool_call_id: message.tool_call_id,
469
+ content: message.contentBlocks.filter((block) => block.type === "text")
470
+ };
471
+ else if (role === "function") return {
472
+ role: "function",
473
+ name: message.name ?? "",
474
+ content: message.contentBlocks.filter((block) => block.type === "text").join("")
475
+ };
476
+ function* iterateUserContent(blocks) {
477
+ for (const block of blocks) {
478
+ if (block.type === "text") yield {
479
+ type: "text",
480
+ text: block.text
481
+ };
482
+ const data = convertStandardContentBlockToCompletionsContentPart(block);
483
+ if (data) yield data;
484
+ }
485
+ }
486
+ return {
487
+ role: "user",
488
+ content: Array.from(iterateUserContent(message.contentBlocks))
489
+ };
490
+ };
491
+ /**
492
+ * Converts an array of LangChain BaseMessages to OpenAI Chat Completions API message parameters.
493
+ *
494
+ * This converter transforms LangChain's internal message representation into the format required
495
+ * by OpenAI's Chat Completions API. It handles various message types, roles, content formats,
496
+ * tool calls, function calls, audio messages, and special model-specific requirements.
497
+ *
498
+ * @remarks
499
+ * The converter performs several key transformations:
500
+ * - Maps LangChain message types to OpenAI roles (user, assistant, system, tool, function, developer)
501
+ * - Converts standard content blocks (v1 format) using a specialized converter
502
+ * - Handles multimodal content including text, images, audio, and data blocks
503
+ * - Preserves tool calls and function calls with proper formatting
504
+ * - Applies model-specific role mappings (e.g., "system" → "developer" for reasoning models)
505
+ * - Splits audio messages into separate message parameters when needed
506
+ *
507
+ * @param params - Conversion parameters
508
+ * @param params.messages - Array of LangChain BaseMessages to convert. Can include any message
509
+ * type: HumanMessage, AIMessage, SystemMessage, ToolMessage, FunctionMessage, etc.
510
+ * @param params.model - Optional model name used to determine if special role mapping is needed.
511
+ * For reasoning models (o1, o3, etc.), "system" role is converted to "developer" role.
512
+ *
513
+ * @returns Array of ChatCompletionMessageParam objects formatted for OpenAI's Chat Completions API.
514
+ * Some messages may be split into multiple parameters (e.g., audio messages).
515
+ *
516
+ * @example
517
+ * Basic message conversion:
518
+ * ```typescript
519
+ * const messages = [
520
+ * new HumanMessage("What's the weather like?"),
521
+ * new AIMessage("Let me check that for you.")
522
+ * ];
523
+ *
524
+ * const params = convertMessagesToCompletionsMessageParams({
525
+ * messages,
526
+ * model: "gpt-4"
527
+ * });
528
+ * // Returns:
529
+ * // [
530
+ * // { role: "user", content: "What's the weather like?" },
531
+ * // { role: "assistant", content: "Let me check that for you." }
532
+ * // ]
533
+ * ```
534
+ *
535
+ * @example
536
+ * Message with tool calls:
537
+ * ```typescript
538
+ * const messages = [
539
+ * new AIMessage({
540
+ * content: "",
541
+ * tool_calls: [{
542
+ * id: "call_123",
543
+ * name: "get_weather",
544
+ * args: { location: "San Francisco" }
545
+ * }]
546
+ * })
547
+ * ];
548
+ *
549
+ * const params = convertMessagesToCompletionsMessageParams({ messages });
550
+ * // Returns:
551
+ * // [{
552
+ * // role: "assistant",
553
+ * // content: "",
554
+ * // tool_calls: [{
555
+ * // id: "call_123",
556
+ * // type: "function",
557
+ * // function: { name: "get_weather", arguments: '{"location":"San Francisco"}' }
558
+ * // }]
559
+ * // }]
560
+ * ```
561
+ */
562
+ const convertMessagesToCompletionsMessageParams = ({ messages, model }) => {
563
+ return messages.flatMap((message) => {
564
+ if ("output_version" in message.response_metadata && message.response_metadata?.output_version === "v1") return convertStandardContentMessageToCompletionsMessage({ message });
565
+ let role = require_misc.messageToOpenAIRole(message);
566
+ if (role === "system" && require_misc.isReasoningModel(model)) role = "developer";
567
+ const content = typeof message.content === "string" ? message.content : message.content.map((m) => {
568
+ if ((0, __langchain_core_messages.isDataContentBlock)(m)) return (0, __langchain_core_messages.convertToProviderContentBlock)(m, completionsApiContentBlockConverter);
569
+ return m;
570
+ });
571
+ const completionParam = {
572
+ role,
573
+ content
574
+ };
575
+ if (message.name != null) completionParam.name = message.name;
576
+ if (message.additional_kwargs.function_call != null) {
577
+ completionParam.function_call = message.additional_kwargs.function_call;
578
+ completionParam.content = "";
579
+ }
580
+ if (__langchain_core_messages.AIMessage.isInstance(message) && !!message.tool_calls?.length) {
581
+ completionParam.tool_calls = message.tool_calls.map(__langchain_core_output_parsers_openai_tools.convertLangChainToolCallToOpenAI);
582
+ completionParam.content = "";
583
+ } else {
584
+ if (message.additional_kwargs.tool_calls != null) completionParam.tool_calls = message.additional_kwargs.tool_calls;
585
+ if (__langchain_core_messages.ToolMessage.isInstance(message) && message.tool_call_id != null) completionParam.tool_call_id = message.tool_call_id;
586
+ }
587
+ if (message.additional_kwargs.audio && typeof message.additional_kwargs.audio === "object" && "id" in message.additional_kwargs.audio) {
588
+ const audioMessage = {
589
+ role: "assistant",
590
+ audio: { id: message.additional_kwargs.audio.id }
591
+ };
592
+ return [completionParam, audioMessage];
593
+ }
594
+ return completionParam;
595
+ });
596
+ };
597
+
598
+ //#endregion
599
+ exports.completionsApiContentBlockConverter = completionsApiContentBlockConverter;
600
+ exports.convertCompletionsDeltaToBaseMessageChunk = convertCompletionsDeltaToBaseMessageChunk;
601
+ exports.convertCompletionsMessageToBaseMessage = convertCompletionsMessageToBaseMessage;
602
+ exports.convertMessagesToCompletionsMessageParams = convertMessagesToCompletionsMessageParams;
603
+ //# sourceMappingURL=completions.cjs.map