@langchain/openai 1.6.3 → 1.7.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @langchain/openai
2
2
 
3
+ ## 1.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#11986](https://github.com/langchain-ai/langchainjs/pull/11986) [`2caf64d`](https://github.com/langchain-ai/langchainjs/commit/2caf64da3f02730f3cd2aab0c15de6eab41a01da) Thanks [@richardscarrott](https://github.com/richardscarrott)! - feat: stream tool-call args as `tool-call-delta` slices
8
+
9
+ Tool-call and server-tool-call args now stream as `tool-call-delta` events, which carry only the new slice of the args, instead of `block-delta` snapshots of the args so far. A large tool call now costs about the same bytes on the wire as the same length of text.
10
+
11
+ - This covers the compat bridge (any model that only implements `_streamResponseChunks`), the OpenAI-compatible converter (OpenAI Completions, Groq, Mistral, IBM, OpenRouter, Perplexity, DeepSeek, Fireworks, Together AI and xAI Completions), OpenAI and xAI Responses, Anthropic (client and server tool calls) and Bedrock Converse. Google and Ollama still send one complete snapshot per call.
12
+ - A tool call's `id`, `name` and `index` go on `content-block-start`, which carries no args. An `id` or `name` that arrives later reaches consumers on `content-block-finish`.
13
+ - If you read raw events and their `block-delta` `fields.args` mid-stream, or write agent stream transformers that do, read `tool-call-delta` instead. `await stream`, `.toolCalls` and the assembled message are unchanged.
14
+ - Upgrade your clients first. Older clients mishandle `tool-call-delta`. You need `@langchain/langgraph-sdk` 1.12.6 or later; `@langchain/react`, `@langchain/vue`, `@langchain/svelte` or `@langchain/angular` 1.2.6 or later; and `langchain-core` 1.6.13 or later for Python clients.
15
+ - To hold back, pin `@langchain/core` below 1.3.0. That also keeps you on `@langchain/openai`, `@langchain/anthropic`, `@langchain/aws` and `@langchain/xai` versions that send snapshots.
16
+
3
17
  ## 1.6.3
4
18
 
5
19
  ### Patch Changes
@@ -275,7 +275,7 @@ var BaseChatOpenAI = class extends _langchain_core_language_models_chat_models.B
275
275
  if (fields?.supportsStrictToolCalling !== void 0) this.supportsStrictToolCalling = fields.supportsStrictToolCalling;
276
276
  if (fields?.service_tier !== void 0) this.service_tier = fields.service_tier;
277
277
  this.zdrEnabled = fields?.zdrEnabled ?? false;
278
- this._addVersion("@langchain/openai", "1.6.3");
278
+ this._addVersion("@langchain/openai", "1.7.0");
279
279
  }
280
280
  /**
281
281
  * Returns backwards compatible reasoning parameters from constructor params and call options
@@ -275,7 +275,7 @@ var BaseChatOpenAI = class extends BaseChatModel {
275
275
  if (fields?.supportsStrictToolCalling !== void 0) this.supportsStrictToolCalling = fields.supportsStrictToolCalling;
276
276
  if (fields?.service_tier !== void 0) this.service_tier = fields.service_tier;
277
277
  this.zdrEnabled = fields?.zdrEnabled ?? false;
278
- this._addVersion("@langchain/openai", "1.6.3");
278
+ this._addVersion("@langchain/openai", "1.7.0");
279
279
  }
280
280
  /**
281
281
  * Returns backwards compatible reasoning parameters from constructor params and call options
package/dist/llms.cjs CHANGED
@@ -82,7 +82,7 @@ var OpenAI = class extends _langchain_core_language_models_llms.BaseLLM {
82
82
  clientConfig;
83
83
  constructor(fields) {
84
84
  super(fields ?? {});
85
- this._addVersion("@langchain/openai", "1.6.3");
85
+ this._addVersion("@langchain/openai", "1.7.0");
86
86
  this.openAIApiKey = fields?.apiKey ?? fields?.openAIApiKey ?? (0, _langchain_core_utils_env.getEnvironmentVariable)("OPENAI_API_KEY");
87
87
  this.apiKey = this.openAIApiKey;
88
88
  this.organization = fields?.configuration?.organization ?? (0, _langchain_core_utils_env.getEnvironmentVariable)("OPENAI_ORGANIZATION");
package/dist/llms.js CHANGED
@@ -82,7 +82,7 @@ var OpenAI$2 = class extends BaseLLM {
82
82
  clientConfig;
83
83
  constructor(fields) {
84
84
  super(fields ?? {});
85
- this._addVersion("@langchain/openai", "1.6.3");
85
+ this._addVersion("@langchain/openai", "1.7.0");
86
86
  this.openAIApiKey = fields?.apiKey ?? fields?.openAIApiKey ?? getEnvironmentVariable("OPENAI_API_KEY");
87
87
  this.apiKey = this.openAIApiKey;
88
88
  this.organization = fields?.configuration?.organization ?? getEnvironmentVariable("OPENAI_ORGANIZATION");
@@ -127,30 +127,24 @@ async function* convertOpenAIResponsesStream(source, options = {}) {
127
127
  index: event.output_index,
128
128
  ...isCustom ? { isCustomTool: true } : {}
129
129
  });
130
- if (isNew) yield {
131
- event: "content-block-start",
132
- index,
133
- content: {
134
- type: "tool_call_chunk",
135
- id: event.item.call_id,
136
- name: event.item.name,
137
- args: initialArgs,
138
- index: event.output_index
139
- }
140
- };
141
- if (initialArgs) {
142
- const acc = blockAccumulators.get(index);
130
+ if (isNew) {
143
131
  yield {
132
+ event: "content-block-start",
133
+ index,
134
+ content: {
135
+ type: "tool_call_chunk",
136
+ id: event.item.call_id,
137
+ name: event.item.name,
138
+ args: "",
139
+ index: event.output_index
140
+ }
141
+ };
142
+ if (initialArgs) yield {
144
143
  event: "content-block-delta",
145
144
  index,
146
145
  delta: {
147
- type: "block-delta",
148
- fields: {
149
- type: "tool_call_chunk",
150
- ...acc.id != null ? { id: acc.id } : {},
151
- ...acc.name != null ? { name: acc.name } : {},
152
- args: acc.args
153
- }
146
+ type: "tool-call-delta",
147
+ args: initialArgs
154
148
  }
155
149
  };
156
150
  }
@@ -173,21 +167,18 @@ async function* convertOpenAIResponsesStream(source, options = {}) {
173
167
  index: event.output_index
174
168
  }
175
169
  };
176
- const acc = blockAccumulators.get(index);
177
- acc.args = (acc.args ?? "") + event.delta;
178
- yield {
179
- event: "content-block-delta",
180
- index,
181
- delta: {
182
- type: "block-delta",
183
- fields: {
184
- type: "tool_call_chunk",
185
- ...acc.id != null ? { id: acc.id } : {},
186
- ...acc.name != null ? { name: acc.name } : {},
187
- args: acc.args
170
+ if (event.delta) {
171
+ const acc = blockAccumulators.get(index);
172
+ acc.args = (acc.args ?? "") + event.delta;
173
+ yield {
174
+ event: "content-block-delta",
175
+ index,
176
+ delta: {
177
+ type: "tool-call-delta",
178
+ args: event.delta
188
179
  }
189
- }
190
- };
180
+ };
181
+ }
191
182
  continue;
192
183
  }
193
184
  if (event.type === "response.output_item.done" && (event.item.type === "function_call" || event.item.type === "custom_tool_call")) {
@@ -1 +1 @@
1
- {"version":3,"file":"responses_stream_events.cjs","names":["finalizeContentBlock","convertResponsesUsageToUsageMetadata"],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (initialArgs) {\n const acc = blockAccumulators.get(index)!;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"responses_stream_events.cjs","names":["finalizeContentBlock","convertResponsesUsageToUsageMetadata"],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n // The initial args go out once, as the call's first slice.\n if (initialArgs) {\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"tool-call-delta\" as const, args: initialArgs },\n };\n }\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (event.delta) {\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"tool-call-delta\" as const, args: event.delta },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":"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"}
@@ -127,30 +127,24 @@ async function* convertOpenAIResponsesStream(source, options = {}) {
127
127
  index: event.output_index,
128
128
  ...isCustom ? { isCustomTool: true } : {}
129
129
  });
130
- if (isNew) yield {
131
- event: "content-block-start",
132
- index,
133
- content: {
134
- type: "tool_call_chunk",
135
- id: event.item.call_id,
136
- name: event.item.name,
137
- args: initialArgs,
138
- index: event.output_index
139
- }
140
- };
141
- if (initialArgs) {
142
- const acc = blockAccumulators.get(index);
130
+ if (isNew) {
143
131
  yield {
132
+ event: "content-block-start",
133
+ index,
134
+ content: {
135
+ type: "tool_call_chunk",
136
+ id: event.item.call_id,
137
+ name: event.item.name,
138
+ args: "",
139
+ index: event.output_index
140
+ }
141
+ };
142
+ if (initialArgs) yield {
144
143
  event: "content-block-delta",
145
144
  index,
146
145
  delta: {
147
- type: "block-delta",
148
- fields: {
149
- type: "tool_call_chunk",
150
- ...acc.id != null ? { id: acc.id } : {},
151
- ...acc.name != null ? { name: acc.name } : {},
152
- args: acc.args
153
- }
146
+ type: "tool-call-delta",
147
+ args: initialArgs
154
148
  }
155
149
  };
156
150
  }
@@ -173,21 +167,18 @@ async function* convertOpenAIResponsesStream(source, options = {}) {
173
167
  index: event.output_index
174
168
  }
175
169
  };
176
- const acc = blockAccumulators.get(index);
177
- acc.args = (acc.args ?? "") + event.delta;
178
- yield {
179
- event: "content-block-delta",
180
- index,
181
- delta: {
182
- type: "block-delta",
183
- fields: {
184
- type: "tool_call_chunk",
185
- ...acc.id != null ? { id: acc.id } : {},
186
- ...acc.name != null ? { name: acc.name } : {},
187
- args: acc.args
170
+ if (event.delta) {
171
+ const acc = blockAccumulators.get(index);
172
+ acc.args = (acc.args ?? "") + event.delta;
173
+ yield {
174
+ event: "content-block-delta",
175
+ index,
176
+ delta: {
177
+ type: "tool-call-delta",
178
+ args: event.delta
188
179
  }
189
- }
190
- };
180
+ };
181
+ }
191
182
  continue;
192
183
  }
193
184
  if (event.type === "response.output_item.done" && (event.item.type === "function_call" || event.item.type === "custom_tool_call")) {
@@ -1 +1 @@
1
- {"version":3,"file":"responses_stream_events.js","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (initialArgs) {\n const acc = blockAccumulators.get(index)!;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: {\n type: \"block-delta\" as const,\n fields: {\n type: \"tool_call_chunk\",\n ...(acc.id != null ? { id: acc.id } : {}),\n ...(acc.name != null ? { name: acc.name } : {}),\n args: acc.args,\n },\n },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"responses_stream_events.js","names":[],"sources":["../../src/utils/responses_stream_events.ts"],"sourcesContent":["/**\n * Converts OpenAI Responses API stream events into LangChain ChatModelStreamEvents.\n *\n * @module\n */\n\nimport { OpenAI as OpenAIClient } from \"openai\";\nimport { finalizeContentBlock } from \"@langchain/core/language_models/compat\";\nimport type {\n ChatModelStreamEvent,\n FinishReason,\n} from \"@langchain/core/language_models/event\";\nimport type { ContentBlock, UsageMetadata } from \"@langchain/core/messages\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\n\nexport interface ConvertOpenAIResponsesStreamOptions {\n streamUsage?: boolean;\n provider?: string;\n}\n\ntype RawEvent = OpenAIClient.Responses.ResponseStreamEvent;\ntype BlockKey =\n | `text:${number}:${number}`\n | `reasoning:${number}:${number}`\n | `tool:${number}`;\n\nexport async function* convertOpenAIResponsesStream(\n source: AsyncIterable<RawEvent>,\n options: ConvertOpenAIResponsesStreamOptions = {}\n): AsyncGenerator<ChatModelStreamEvent> {\n const shouldStreamUsage = options.streamUsage ?? true;\n const provider = options.provider ?? \"openai\";\n\n const blockAccumulators = new Map<\n number,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, any>\n >();\n const blockKeyToIndex = new Map<BlockKey, number>();\n let nextBlockIndex = 0;\n let messageStarted = false;\n let messageId: string | undefined;\n let usageSnapshot: UsageMetadata | undefined;\n let finishReason: FinishReason | undefined;\n let responseMetadata: Record<string, unknown> | undefined;\n const finalizedBlockIndices = new Set<number>();\n\n const getOrCreateBlockIndex = (\n key: BlockKey,\n initial: Record<string, unknown>\n ): { index: number; isNew: boolean } => {\n const existing = blockKeyToIndex.get(key);\n if (existing !== undefined) {\n return { index: existing, isNew: false };\n }\n const index = nextBlockIndex++;\n blockKeyToIndex.set(key, index);\n blockAccumulators.set(index, { ...initial });\n return { index, isNew: true };\n };\n\n const ensureMessageStart = function* () {\n if (!messageStarted) {\n messageStarted = true;\n yield {\n event: \"message-start\" as const,\n id: messageId,\n };\n }\n };\n\n const finalizeBlock = function* (index: number) {\n if (finalizedBlockIndices.has(index)) {\n return;\n }\n const acc = blockAccumulators.get(index);\n if (!acc) {\n return;\n }\n finalizedBlockIndices.add(index);\n yield {\n event: \"content-block-finish\" as const,\n index,\n content: finalizeContentBlock(acc as ContentBlock),\n };\n };\n\n for await (const event of source) {\n if (event.type === \"response.created\") {\n messageId = event.response.id;\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: \"response.created\",\n payload: { model: event.response.model, id: event.response.id },\n };\n continue;\n }\n\n if (event.type === \"response.output_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `text:${event.output_index}:${event.content_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"text\",\n text: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"text\", text: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.text = (acc.text ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"text-delta\" as const, text: event.delta },\n };\n continue;\n }\n\n if (event.type === \"response.reasoning_summary_text.delta\") {\n yield* ensureMessageStart();\n const key: BlockKey = `reasoning:${event.output_index}:${event.summary_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"reasoning\",\n reasoning: \"\",\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: { type: \"reasoning\", reasoning: \"\" } as ContentBlock,\n };\n }\n const acc = blockAccumulators.get(index)!;\n acc.reasoning = (acc.reasoning ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"reasoning-delta\" as const, reasoning: event.delta },\n };\n continue;\n }\n\n if (\n event.type === \"response.output_item.added\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const isCustom = event.item.type === \"custom_tool_call\";\n const initialArgs =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: initialArgs,\n index: event.output_index,\n ...(isCustom ? { isCustomTool: true } : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n // The initial args go out once, as the call's first slice.\n if (initialArgs) {\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"tool-call-delta\" as const, args: initialArgs },\n };\n }\n }\n continue;\n }\n\n if (\n event.type === \"response.function_call_arguments.delta\" ||\n event.type === \"response.custom_tool_call_input.delta\"\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n ...(event.type === \"response.custom_tool_call_input.delta\"\n ? { isCustomTool: true }\n : {}),\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n args: \"\",\n index: event.output_index,\n } as ContentBlock,\n };\n }\n if (event.delta) {\n const acc = blockAccumulators.get(index)!;\n acc.args = (acc.args ?? \"\") + event.delta;\n yield {\n event: \"content-block-delta\" as const,\n index,\n delta: { type: \"tool-call-delta\" as const, args: event.delta },\n };\n }\n continue;\n }\n\n if (\n event.type === \"response.output_item.done\" &&\n (event.item.type === \"function_call\" ||\n event.item.type === \"custom_tool_call\")\n ) {\n yield* ensureMessageStart();\n const key: BlockKey = `tool:${event.output_index}`;\n const args =\n event.item.type === \"function_call\"\n ? (event.item.arguments ?? \"\")\n : (event.item.input ?? \"\");\n const { index, isNew } = getOrCreateBlockIndex(key, {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n });\n if (isNew) {\n yield {\n event: \"content-block-start\" as const,\n index,\n content: {\n type: \"tool_call_chunk\",\n id: event.item.call_id,\n name: event.item.name,\n args,\n index: event.output_index,\n } as ContentBlock,\n };\n } else {\n const acc = blockAccumulators.get(index)!;\n acc.args = args;\n acc.id = event.item.call_id;\n acc.name = event.item.name;\n }\n yield* finalizeBlock(index);\n continue;\n }\n\n if (\n event.type === \"response.completed\" ||\n event.type === \"response.incomplete\"\n ) {\n yield* ensureMessageStart();\n messageId = event.response.id;\n finishReason = mapResponseStatusToFinishReason(\n event.response.status,\n event.type\n );\n responseMetadata = {\n model_provider: provider,\n id: event.response.id,\n model: event.response.model,\n status: event.response.status,\n };\n if (shouldStreamUsage && event.response.usage) {\n usageSnapshot = convertResponsesUsageToUsageMetadata(\n event.response.usage\n );\n yield { event: \"usage\" as const, usage: usageSnapshot };\n }\n continue;\n }\n\n if (event.type === \"response.image_generation_call.partial_image\") {\n continue;\n }\n\n yield* ensureMessageStart();\n yield {\n event: \"provider\" as const,\n provider,\n name: event.type,\n payload: event,\n };\n }\n\n if (!messageStarted) {\n yield { event: \"message-start\" as const };\n }\n\n for (const [index] of blockAccumulators) {\n if (!finalizedBlockIndices.has(index)) {\n yield* finalizeBlock(index);\n }\n }\n\n yield {\n event: \"message-finish\" as const,\n reason: finishReason,\n ...(usageSnapshot ? { usage: usageSnapshot } : {}),\n ...(responseMetadata ? { responseMetadata } : {}),\n };\n}\n\nfunction mapResponseStatusToFinishReason(\n status: string | undefined,\n eventType: \"response.completed\" | \"response.incomplete\"\n): FinishReason {\n if (eventType === \"response.incomplete\") {\n return \"length\";\n }\n if (status === \"completed\") {\n return \"stop\";\n }\n if (status === \"incomplete\") {\n return \"length\";\n }\n return \"stop\";\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "1.6.3",
3
+ "version": "1.7.0",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "author": "LangChain",
6
6
  "license": "MIT",
@@ -19,7 +19,7 @@
19
19
  "zod": "^3.25.76 || ^4"
20
20
  },
21
21
  "peerDependencies": {
22
- "@langchain/core": "^1.2.20"
22
+ "@langchain/core": "^1.3.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@azure/identity": "^4.13.3",
@@ -33,7 +33,7 @@
33
33
  "typescript": "~7.0.2",
34
34
  "vitest": "^5.0.2",
35
35
  "zod-to-json-schema": "^3.25.2",
36
- "@langchain/core": "^1.2.20",
36
+ "@langchain/core": "^1.3.0",
37
37
  "@langchain/standard-tests": "0.0.23",
38
38
  "@langchain/tsconfig": "0.0.1"
39
39
  },