@langchain/xai 1.1.1 → 1.2.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 (39) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/{chat_models.cjs → chat_models/completions.cjs} +6 -6
  3. package/dist/chat_models/completions.cjs.map +1 -0
  4. package/dist/{chat_models.d.cts → chat_models/completions.d.cts} +4 -4
  5. package/dist/chat_models/completions.d.cts.map +1 -0
  6. package/dist/{chat_models.d.ts → chat_models/completions.d.ts} +6 -6
  7. package/dist/chat_models/completions.d.ts.map +1 -0
  8. package/dist/{chat_models.js → chat_models/completions.js} +5 -5
  9. package/dist/chat_models/completions.js.map +1 -0
  10. package/dist/chat_models/index.cjs +2 -0
  11. package/dist/chat_models/index.d.ts +3 -0
  12. package/dist/chat_models/index.js +2 -0
  13. package/dist/chat_models/responses-types.d.cts +1148 -0
  14. package/dist/chat_models/responses-types.d.cts.map +1 -0
  15. package/dist/chat_models/responses-types.d.ts +1148 -0
  16. package/dist/chat_models/responses-types.d.ts.map +1 -0
  17. package/dist/chat_models/responses.cjs +228 -0
  18. package/dist/chat_models/responses.cjs.map +1 -0
  19. package/dist/chat_models/responses.d.cts +69 -0
  20. package/dist/chat_models/responses.d.cts.map +1 -0
  21. package/dist/chat_models/responses.d.ts +69 -0
  22. package/dist/chat_models/responses.d.ts.map +1 -0
  23. package/dist/chat_models/responses.js +227 -0
  24. package/dist/chat_models/responses.js.map +1 -0
  25. package/dist/converters/responses.cjs +168 -0
  26. package/dist/converters/responses.cjs.map +1 -0
  27. package/dist/converters/responses.js +164 -0
  28. package/dist/converters/responses.js.map +1 -0
  29. package/dist/index.cjs +8 -5
  30. package/dist/index.d.cts +4 -2
  31. package/dist/index.d.ts +5 -2
  32. package/dist/index.js +4 -2
  33. package/dist/live_search.cjs.map +1 -1
  34. package/dist/live_search.js.map +1 -1
  35. package/package.json +5 -6
  36. package/dist/chat_models.cjs.map +0 -1
  37. package/dist/chat_models.d.cts.map +0 -1
  38. package/dist/chat_models.d.ts.map +0 -1
  39. package/dist/chat_models.js.map +0 -1
@@ -0,0 +1,227 @@
1
+ import { convertMessagesToResponsesInput, convertResponseToAIMessage, convertStreamEventToChunk, extractTextFromOutput } from "../converters/responses.js";
2
+ import { getEnvironmentVariable } from "@langchain/core/utils/env";
3
+ import { BaseChatModel } from "@langchain/core/language_models/chat_models";
4
+
5
+ //#region src/chat_models/responses.ts
6
+ /**
7
+ * xAI Responses API chat model integration.
8
+ *
9
+ * This class provides access to xAI's Responses API, which offers enhanced
10
+ * capabilities including built-in tools, reasoning, and search.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { ChatXAIResponses } from "@langchain/xai";
15
+ *
16
+ * const llm = new ChatXAIResponses({
17
+ * model: "grok-3",
18
+ * temperature: 0.7,
19
+ * });
20
+ *
21
+ * const result = await llm.invoke("What is the capital of France?");
22
+ * console.log(result.content);
23
+ * ```
24
+ */
25
+ var ChatXAIResponses = class extends BaseChatModel {
26
+ static lc_name() {
27
+ return "ChatXAIResponses";
28
+ }
29
+ lc_serializable = true;
30
+ lc_namespace = [
31
+ "langchain",
32
+ "chat_models",
33
+ "xai"
34
+ ];
35
+ get lc_secrets() {
36
+ return { apiKey: "XAI_API_KEY" };
37
+ }
38
+ get lc_aliases() {
39
+ return { apiKey: "xai_api_key" };
40
+ }
41
+ apiKey;
42
+ model;
43
+ streaming;
44
+ temperature;
45
+ topP;
46
+ maxOutputTokens;
47
+ store;
48
+ user;
49
+ baseURL;
50
+ searchParameters;
51
+ reasoning;
52
+ constructor(fields) {
53
+ super(fields ?? {});
54
+ const apiKey = fields?.apiKey ?? getEnvironmentVariable("XAI_API_KEY");
55
+ if (!apiKey) throw new Error(`xAI API key not found. Please set the XAI_API_KEY environment variable or provide the key in the "apiKey" field.`);
56
+ this.apiKey = apiKey;
57
+ this.model = fields?.model ?? "grok-3";
58
+ this.streaming = fields?.streaming ?? false;
59
+ this.temperature = fields?.temperature;
60
+ this.topP = fields?.topP;
61
+ this.maxOutputTokens = fields?.maxOutputTokens;
62
+ this.store = fields?.store;
63
+ this.user = fields?.user;
64
+ this.baseURL = fields?.baseURL ?? "https://api.x.ai/v1";
65
+ this.searchParameters = fields?.searchParameters;
66
+ this.reasoning = fields?.reasoning;
67
+ }
68
+ _llmType() {
69
+ return "xai-responses";
70
+ }
71
+ getLsParams(options) {
72
+ const params = super.getLsParams(options);
73
+ params.ls_provider = "xai";
74
+ params.ls_model_name = this.model;
75
+ params.ls_model_type = "chat";
76
+ params.ls_temperature = this.temperature;
77
+ params.ls_max_tokens = this.maxOutputTokens;
78
+ return params;
79
+ }
80
+ toJSON() {
81
+ const result = super.toJSON();
82
+ if ("kwargs" in result && typeof result.kwargs === "object" && result.kwargs != null) delete result.kwargs.apiKey;
83
+ return result;
84
+ }
85
+ invocationParams(options) {
86
+ return {
87
+ model: this.model,
88
+ temperature: this.temperature,
89
+ top_p: this.topP,
90
+ max_output_tokens: this.maxOutputTokens,
91
+ store: this.store,
92
+ user: this.user,
93
+ stream: this.streaming,
94
+ previous_response_id: options?.previous_response_id,
95
+ include: options?.include,
96
+ text: options?.text,
97
+ search_parameters: options?.search_parameters ?? this.searchParameters,
98
+ reasoning: options?.reasoning ?? this.reasoning,
99
+ tool_choice: options?.tool_choice,
100
+ parallel_tool_calls: options?.parallel_tool_calls
101
+ };
102
+ }
103
+ async _makeRequest(request) {
104
+ const url = `${this.baseURL}/responses`;
105
+ const headers = {
106
+ "Content-Type": "application/json",
107
+ Authorization: `Bearer ${this.apiKey}`
108
+ };
109
+ if (request.stream) return this._makeStreamingRequest(url, headers, request);
110
+ const response = await this.caller.call(async () => {
111
+ const res = await fetch(url, {
112
+ method: "POST",
113
+ headers,
114
+ body: JSON.stringify(request)
115
+ });
116
+ if (!res.ok) {
117
+ const errorBody = await res.text();
118
+ throw new Error(`xAI API error: ${res.status} ${res.statusText} - ${errorBody}`);
119
+ }
120
+ return res.json();
121
+ });
122
+ return response;
123
+ }
124
+ /**
125
+ * Makes a streaming request to the xAI Responses API.
126
+ */
127
+ async *_makeStreamingRequest(url, headers, request) {
128
+ const response = await this.caller.call(async () => {
129
+ const res = await fetch(url, {
130
+ method: "POST",
131
+ headers,
132
+ body: JSON.stringify(request)
133
+ });
134
+ if (!res.ok) {
135
+ const errorBody = await res.text();
136
+ throw new Error(`xAI API error: ${res.status} ${res.statusText} - ${errorBody}`);
137
+ }
138
+ return res;
139
+ });
140
+ const reader = response.body?.getReader();
141
+ if (!reader) throw new Error("No response body");
142
+ const decoder = new TextDecoder();
143
+ let buffer = "";
144
+ try {
145
+ while (true) {
146
+ const { done, value } = await reader.read();
147
+ if (done) break;
148
+ buffer += decoder.decode(value, { stream: true });
149
+ const lines = buffer.split("\n");
150
+ buffer = lines.pop() ?? "";
151
+ for (const line of lines) {
152
+ const trimmed = line.trim();
153
+ if (!trimmed || trimmed === "data: [DONE]") continue;
154
+ if (trimmed.startsWith("data: ")) try {
155
+ const data = JSON.parse(trimmed.slice(6));
156
+ yield data;
157
+ } catch {}
158
+ }
159
+ }
160
+ } finally {
161
+ reader.releaseLock();
162
+ }
163
+ }
164
+ async _generate(messages, options, runManager) {
165
+ const invocationParams = this.invocationParams(options);
166
+ const input = convertMessagesToResponsesInput(messages);
167
+ if (invocationParams.stream) {
168
+ const stream = this._streamResponseChunks(messages, options, runManager);
169
+ let finalChunk;
170
+ for await (const chunk of stream) {
171
+ chunk.message.response_metadata = {
172
+ ...chunk.generationInfo,
173
+ ...chunk.message.response_metadata
174
+ };
175
+ finalChunk = finalChunk?.concat(chunk) ?? chunk;
176
+ }
177
+ return {
178
+ generations: finalChunk ? [finalChunk] : [],
179
+ llmOutput: { estimatedTokenUsage: (finalChunk?.message)?.usage_metadata }
180
+ };
181
+ }
182
+ const response = await this._makeRequest({
183
+ input,
184
+ ...invocationParams,
185
+ stream: false
186
+ });
187
+ const aiMessage = convertResponseToAIMessage(response);
188
+ const text = extractTextFromOutput(response.output);
189
+ return {
190
+ generations: [{
191
+ text,
192
+ message: aiMessage
193
+ }],
194
+ llmOutput: {
195
+ id: response.id,
196
+ estimatedTokenUsage: response.usage ? {
197
+ promptTokens: response.usage.input_tokens,
198
+ completionTokens: response.usage.output_tokens,
199
+ totalTokens: response.usage.total_tokens
200
+ } : void 0
201
+ }
202
+ };
203
+ }
204
+ async *_streamResponseChunks(messages, options, runManager) {
205
+ const invocationParams = this.invocationParams(options);
206
+ const input = convertMessagesToResponsesInput(messages);
207
+ const streamIterable = await this._makeRequest({
208
+ input,
209
+ ...invocationParams,
210
+ stream: true
211
+ });
212
+ for await (const event of streamIterable) {
213
+ const chunk = convertStreamEventToChunk(event);
214
+ if (chunk) {
215
+ yield chunk;
216
+ await runManager?.handleLLMNewToken(chunk.text || "", {
217
+ prompt: 0,
218
+ completion: 0
219
+ });
220
+ }
221
+ }
222
+ }
223
+ };
224
+
225
+ //#endregion
226
+ export { ChatXAIResponses };
227
+ //# sourceMappingURL=responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.js","names":["fields?: ChatXAIResponsesInput","options: this[\"ParsedCallOptions\"]","options?: this[\"ParsedCallOptions\"]","request: XAIResponsesCreateParams","headers: Record<string, string>","url: string","messages: BaseMessage[]","runManager?: CallbackManagerForLLMRun","finalChunk: ChatGenerationChunk | undefined"],"sources":["../../src/chat_models/responses.ts"],"sourcesContent":["import { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport { AIMessage, BaseMessage } from \"@langchain/core/messages\";\nimport {\n BaseChatModel,\n type LangSmithParams,\n} from \"@langchain/core/language_models/chat_models\";\nimport { ChatGenerationChunk, type ChatResult } from \"@langchain/core/outputs\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\n\nimport type {\n ChatXAIResponsesCallOptions,\n ChatXAIResponsesInput,\n ChatXAIResponsesInvocationParams,\n XAIResponse,\n XAIResponsesCreateParams,\n XAIResponsesCreateParamsNonStreaming,\n XAIResponsesCreateParamsStreaming,\n XAIResponsesReasoning,\n XAIResponsesSearchParameters,\n XAIResponsesStreamEvent,\n} from \"./responses-types.js\";\n\nimport {\n convertMessagesToResponsesInput,\n convertResponseToAIMessage,\n convertStreamEventToChunk,\n extractTextFromOutput,\n} from \"../converters/responses.js\";\n\n// Re-export types for convenience\nexport type {\n ChatXAIResponsesCallOptions,\n ChatXAIResponsesInput,\n ChatXAIResponsesInvocationParams,\n};\n\n// ============================================================================\n// Main Class\n// ============================================================================\n\n/**\n * xAI Responses API chat model integration.\n *\n * This class provides access to xAI's Responses API, which offers enhanced\n * capabilities including built-in tools, reasoning, and search.\n *\n * @example\n * ```typescript\n * import { ChatXAIResponses } from \"@langchain/xai\";\n *\n * const llm = new ChatXAIResponses({\n * model: \"grok-3\",\n * temperature: 0.7,\n * });\n *\n * const result = await llm.invoke(\"What is the capital of France?\");\n * console.log(result.content);\n * ```\n */\nexport class ChatXAIResponses<\n CallOptions extends ChatXAIResponsesCallOptions = ChatXAIResponsesCallOptions,\n> extends BaseChatModel<CallOptions> {\n static lc_name() {\n return \"ChatXAIResponses\";\n }\n\n lc_serializable = true;\n\n lc_namespace = [\"langchain\", \"chat_models\", \"xai\"];\n\n get lc_secrets(): { [key: string]: string } | undefined {\n return {\n apiKey: \"XAI_API_KEY\",\n };\n }\n\n get lc_aliases(): { [key: string]: string } | undefined {\n return {\n apiKey: \"xai_api_key\",\n };\n }\n\n // -------------------------------------------------------------------------\n // Instance Properties\n // -------------------------------------------------------------------------\n\n apiKey: string;\n\n model: string;\n\n streaming: boolean;\n\n temperature?: number;\n\n topP?: number;\n\n maxOutputTokens?: number;\n\n store?: boolean;\n\n user?: string;\n\n baseURL: string;\n\n searchParameters?: XAIResponsesSearchParameters;\n\n reasoning?: XAIResponsesReasoning;\n\n // -------------------------------------------------------------------------\n // Constructor\n // -------------------------------------------------------------------------\n\n constructor(fields?: ChatXAIResponsesInput) {\n super(fields ?? {});\n\n const apiKey = fields?.apiKey ?? getEnvironmentVariable(\"XAI_API_KEY\");\n if (!apiKey) {\n throw new Error(\n `xAI API key not found. Please set the XAI_API_KEY environment variable or provide the key in the \"apiKey\" field.`\n );\n }\n\n this.apiKey = apiKey;\n this.model = fields?.model ?? \"grok-3\";\n this.streaming = fields?.streaming ?? false;\n this.temperature = fields?.temperature;\n this.topP = fields?.topP;\n this.maxOutputTokens = fields?.maxOutputTokens;\n this.store = fields?.store;\n this.user = fields?.user;\n this.baseURL = fields?.baseURL ?? \"https://api.x.ai/v1\";\n this.searchParameters = fields?.searchParameters;\n this.reasoning = fields?.reasoning;\n }\n\n // -------------------------------------------------------------------------\n // Metadata Methods\n // -------------------------------------------------------------------------\n\n _llmType(): string {\n return \"xai-responses\";\n }\n\n override getLsParams(options: this[\"ParsedCallOptions\"]): LangSmithParams {\n const params = super.getLsParams(options);\n params.ls_provider = \"xai\";\n params.ls_model_name = this.model;\n params.ls_model_type = \"chat\";\n params.ls_temperature = this.temperature;\n params.ls_max_tokens = this.maxOutputTokens;\n return params;\n }\n\n override toJSON(): Serialized {\n const result = super.toJSON();\n\n if (\n \"kwargs\" in result &&\n typeof result.kwargs === \"object\" &&\n result.kwargs != null\n ) {\n delete (result.kwargs as Record<string, unknown>).apiKey;\n }\n\n return result;\n }\n\n // -------------------------------------------------------------------------\n // Invocation Params\n // -------------------------------------------------------------------------\n\n invocationParams(\n options?: this[\"ParsedCallOptions\"]\n ): ChatXAIResponsesInvocationParams {\n return {\n model: this.model,\n temperature: this.temperature,\n top_p: this.topP,\n max_output_tokens: this.maxOutputTokens,\n store: this.store,\n user: this.user,\n stream: this.streaming,\n previous_response_id: options?.previous_response_id,\n include: options?.include,\n text: options?.text,\n search_parameters: options?.search_parameters ?? this.searchParameters,\n reasoning: options?.reasoning ?? this.reasoning,\n tool_choice: options?.tool_choice,\n parallel_tool_calls: options?.parallel_tool_calls,\n };\n }\n\n // -------------------------------------------------------------------------\n // API Call Methods\n // -------------------------------------------------------------------------\n\n /**\n * Makes a request to the xAI Responses API.\n */\n protected async _makeRequest(\n request: XAIResponsesCreateParamsNonStreaming\n ): Promise<XAIResponse>;\n\n protected async _makeRequest(\n request: XAIResponsesCreateParamsStreaming\n ): Promise<AsyncIterable<XAIResponsesStreamEvent>>;\n\n protected async _makeRequest(\n request: XAIResponsesCreateParams\n ): Promise<XAIResponse | AsyncIterable<XAIResponsesStreamEvent>> {\n const url = `${this.baseURL}/responses`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n };\n\n if (request.stream) {\n return this._makeStreamingRequest(url, headers, request);\n }\n\n const response = await this.caller.call(async () => {\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(request),\n });\n\n if (!res.ok) {\n const errorBody = await res.text();\n throw new Error(\n `xAI API error: ${res.status} ${res.statusText} - ${errorBody}`\n );\n }\n\n return res.json();\n });\n\n return response as XAIResponse;\n }\n\n /**\n * Makes a streaming request to the xAI Responses API.\n */\n protected async *_makeStreamingRequest(\n url: string,\n headers: Record<string, string>,\n request: XAIResponsesCreateParams\n ): AsyncIterable<XAIResponsesStreamEvent> {\n const response = await this.caller.call(async () => {\n const res = await fetch(url, {\n method: \"POST\",\n headers,\n body: JSON.stringify(request),\n });\n\n if (!res.ok) {\n const errorBody = await res.text();\n throw new Error(\n `xAI API error: ${res.status} ${res.statusText} - ${errorBody}`\n );\n }\n\n return res;\n });\n\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"No response body\");\n }\n\n const decoder = new TextDecoder();\n let buffer = \"\";\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed === \"data: [DONE]\") continue;\n\n if (trimmed.startsWith(\"data: \")) {\n try {\n const data = JSON.parse(trimmed.slice(6));\n yield data as XAIResponsesStreamEvent;\n } catch {\n // Skip invalid JSON\n }\n }\n }\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n // -------------------------------------------------------------------------\n // Generation Methods\n // -------------------------------------------------------------------------\n\n async _generate(\n messages: BaseMessage[],\n options: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const invocationParams = this.invocationParams(options);\n const input = convertMessagesToResponsesInput(messages);\n\n if (invocationParams.stream) {\n const stream = this._streamResponseChunks(messages, options, runManager);\n let finalChunk: ChatGenerationChunk | undefined;\n\n for await (const chunk of stream) {\n chunk.message.response_metadata = {\n ...chunk.generationInfo,\n ...chunk.message.response_metadata,\n };\n finalChunk = finalChunk?.concat(chunk) ?? chunk;\n }\n\n return {\n generations: finalChunk ? [finalChunk] : [],\n llmOutput: {\n estimatedTokenUsage: (finalChunk?.message as AIMessage | undefined)\n ?.usage_metadata,\n },\n };\n }\n\n const response = await this._makeRequest({\n input,\n ...invocationParams,\n stream: false,\n } as XAIResponsesCreateParamsNonStreaming);\n\n const aiMessage = convertResponseToAIMessage(response);\n const text = extractTextFromOutput(response.output);\n\n return {\n generations: [\n {\n text,\n message: aiMessage,\n },\n ],\n llmOutput: {\n id: response.id,\n estimatedTokenUsage: response.usage\n ? {\n promptTokens: response.usage.input_tokens,\n completionTokens: response.usage.output_tokens,\n totalTokens: response.usage.total_tokens,\n }\n : undefined,\n },\n };\n }\n\n async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this[\"ParsedCallOptions\"],\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const invocationParams = this.invocationParams(options);\n const input = convertMessagesToResponsesInput(messages);\n\n const streamIterable = await this._makeRequest({\n input,\n ...invocationParams,\n stream: true,\n } as XAIResponsesCreateParamsStreaming);\n\n for await (const event of streamIterable) {\n const chunk = convertStreamEventToChunk(event);\n if (chunk) {\n yield chunk;\n await runManager?.handleLLMNewToken(chunk.text || \"\", {\n prompt: 0,\n completion: 0,\n });\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,168 @@
1
+ const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
2
+ const __langchain_core_messages = require_rolldown_runtime.__toESM(require("@langchain/core/messages"));
3
+ const __langchain_core_outputs = require_rolldown_runtime.__toESM(require("@langchain/core/outputs"));
4
+
5
+ //#region src/converters/responses.ts
6
+ /**
7
+ * Converts a single LangChain BaseMessage to xAI Responses API input format.
8
+ *
9
+ * @param message - The LangChain message to convert
10
+ * @returns The xAI Responses API input item
11
+ */
12
+ function convertMessageToResponsesInput(message) {
13
+ if (message.type === "human") {
14
+ const content = typeof message.content === "string" ? message.content : message.content.map((part) => {
15
+ if (typeof part === "string") return {
16
+ type: "input_text",
17
+ text: part
18
+ };
19
+ if (part.type === "text") return {
20
+ type: "input_text",
21
+ text: part.text
22
+ };
23
+ if (part.type === "image_url") {
24
+ const imageUrlPart = part;
25
+ const imageUrl = typeof imageUrlPart.image_url === "string" ? imageUrlPart.image_url : imageUrlPart.image_url.url;
26
+ return {
27
+ type: "input_image",
28
+ image_url: imageUrl,
29
+ detail: "auto"
30
+ };
31
+ }
32
+ return {
33
+ type: "input_text",
34
+ text: ""
35
+ };
36
+ });
37
+ return {
38
+ role: "user",
39
+ content
40
+ };
41
+ }
42
+ if (message.type === "system") return {
43
+ role: "system",
44
+ content: typeof message.content === "string" ? message.content : message.content.map((part) => typeof part === "string" ? part : part.text || "").join("")
45
+ };
46
+ if (message.type === "ai") {
47
+ const aiMessage = message;
48
+ return {
49
+ type: "message",
50
+ role: "assistant",
51
+ text: typeof aiMessage.content === "string" ? aiMessage.content : ""
52
+ };
53
+ }
54
+ return {
55
+ role: "user",
56
+ content: typeof message.content === "string" ? message.content : JSON.stringify(message.content)
57
+ };
58
+ }
59
+ /**
60
+ * Converts an array of LangChain BaseMessages to xAI Responses API input format.
61
+ *
62
+ * @param messages - Array of LangChain messages to convert
63
+ * @returns Array of xAI Responses API input items
64
+ */
65
+ function convertMessagesToResponsesInput(messages) {
66
+ return messages.map(convertMessageToResponsesInput);
67
+ }
68
+ /**
69
+ * Converts xAI usage statistics to LangChain UsageMetadata format.
70
+ *
71
+ * @param usage - The xAI usage statistics
72
+ * @returns LangChain UsageMetadata object
73
+ */
74
+ function convertUsageToUsageMetadata(usage) {
75
+ return {
76
+ input_tokens: usage?.input_tokens ?? 0,
77
+ output_tokens: usage?.output_tokens ?? 0,
78
+ total_tokens: usage?.total_tokens ?? 0,
79
+ input_token_details: { ...usage?.input_tokens_details?.cached_tokens != null && { cache_read: usage.input_tokens_details.cached_tokens } },
80
+ output_token_details: { ...usage?.output_tokens_details?.reasoning_tokens != null && { reasoning: usage.output_tokens_details.reasoning_tokens } }
81
+ };
82
+ }
83
+ /**
84
+ * Extracts text content from xAI response output items.
85
+ *
86
+ * @param output - Array of xAI response output items
87
+ * @returns Concatenated text content
88
+ */
89
+ function extractTextFromOutput(output) {
90
+ const textParts = [];
91
+ for (const item of output) if (item.type === "message" && "content" in item) {
92
+ for (const contentItem of item.content) if (contentItem.type === "output_text") textParts.push(contentItem.text);
93
+ }
94
+ return textParts.join("");
95
+ }
96
+ /**
97
+ * Converts an xAI Response to a LangChain AIMessage.
98
+ *
99
+ * @param response - The xAI API response
100
+ * @returns LangChain AIMessage
101
+ */
102
+ function convertResponseToAIMessage(response) {
103
+ const text = extractTextFromOutput(response.output);
104
+ const responseMetadata = {
105
+ model_provider: "xai",
106
+ model: response.model,
107
+ created_at: response.created_at,
108
+ id: response.id,
109
+ status: response.status,
110
+ object: response.object
111
+ };
112
+ if (response.incomplete_details) responseMetadata.incomplete_details = response.incomplete_details;
113
+ return new __langchain_core_messages.AIMessage({
114
+ content: text,
115
+ usage_metadata: convertUsageToUsageMetadata(response.usage),
116
+ response_metadata: responseMetadata,
117
+ additional_kwargs: { ...response.reasoning && { reasoning: response.reasoning } }
118
+ });
119
+ }
120
+ /**
121
+ * Converts an xAI streaming event to a LangChain ChatGenerationChunk.
122
+ *
123
+ * @param event - The xAI streaming event
124
+ * @returns ChatGenerationChunk or null if the event doesn't produce a chunk
125
+ */
126
+ function convertStreamEventToChunk(event) {
127
+ const responseMetadata = { model_provider: "xai" };
128
+ if (event.type === "response.output_text.delta") return new __langchain_core_outputs.ChatGenerationChunk({
129
+ text: event.delta,
130
+ message: new __langchain_core_messages.AIMessageChunk({
131
+ content: event.delta,
132
+ response_metadata: responseMetadata
133
+ })
134
+ });
135
+ if (event.type === "response.created") {
136
+ responseMetadata.id = event.response.id;
137
+ responseMetadata.model = event.response.model;
138
+ return new __langchain_core_outputs.ChatGenerationChunk({
139
+ text: "",
140
+ message: new __langchain_core_messages.AIMessageChunk({
141
+ content: "",
142
+ response_metadata: responseMetadata
143
+ })
144
+ });
145
+ }
146
+ if (event.type === "response.completed") {
147
+ const aiMessage = convertResponseToAIMessage(event.response);
148
+ return new __langchain_core_outputs.ChatGenerationChunk({
149
+ text: "",
150
+ message: new __langchain_core_messages.AIMessageChunk({
151
+ content: "",
152
+ usage_metadata: aiMessage.usage_metadata,
153
+ response_metadata: {
154
+ ...responseMetadata,
155
+ ...aiMessage.response_metadata
156
+ }
157
+ })
158
+ });
159
+ }
160
+ return null;
161
+ }
162
+
163
+ //#endregion
164
+ exports.convertMessagesToResponsesInput = convertMessagesToResponsesInput;
165
+ exports.convertResponseToAIMessage = convertResponseToAIMessage;
166
+ exports.convertStreamEventToChunk = convertStreamEventToChunk;
167
+ exports.extractTextFromOutput = extractTextFromOutput;
168
+ //# sourceMappingURL=responses.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.cjs","names":["message: BaseMessage","messages: BaseMessage[]","usage: XAIResponsesUsage | null | undefined","output: XAIResponsesOutputItem[]","textParts: string[]","response: XAIResponse","responseMetadata: Record<string, unknown>","AIMessage","event: XAIResponsesStreamEvent","ChatGenerationChunk","AIMessageChunk"],"sources":["../../src/converters/responses.ts"],"sourcesContent":["import {\n AIMessage,\n AIMessageChunk,\n BaseMessage,\n type UsageMetadata,\n} from \"@langchain/core/messages\";\nimport { ChatGenerationChunk } from \"@langchain/core/outputs\";\n\nimport type {\n XAIResponse,\n XAIResponsesInputItem,\n XAIResponsesMessage,\n XAIResponsesOutputContent,\n XAIResponsesOutputItem,\n XAIResponsesStreamEvent,\n XAIResponsesUsage,\n} from \"../chat_models/responses-types.js\";\n\n// ============================================================================\n// Message Converters\n// ============================================================================\n\n/**\n * Converts a single LangChain BaseMessage to xAI Responses API input format.\n *\n * @param message - The LangChain message to convert\n * @returns The xAI Responses API input item\n */\nexport function convertMessageToResponsesInput(\n message: BaseMessage\n): XAIResponsesInputItem {\n if (message.type === \"human\") {\n const content =\n typeof message.content === \"string\"\n ? message.content\n : message.content.map((part) => {\n if (typeof part === \"string\") {\n return { type: \"input_text\" as const, text: part };\n }\n if (part.type === \"text\") {\n return { type: \"input_text\" as const, text: part.text };\n }\n if (part.type === \"image_url\") {\n const imageUrlPart = part as {\n type: \"image_url\";\n image_url: string | { url: string };\n };\n const imageUrl =\n typeof imageUrlPart.image_url === \"string\"\n ? imageUrlPart.image_url\n : imageUrlPart.image_url.url;\n return {\n type: \"input_image\" as const,\n image_url: imageUrl,\n detail: \"auto\" as const,\n };\n }\n return { type: \"input_text\" as const, text: \"\" };\n });\n\n return {\n role: \"user\",\n content,\n } as XAIResponsesMessage;\n }\n\n if (message.type === \"system\") {\n return {\n role: \"system\",\n content:\n typeof message.content === \"string\"\n ? message.content\n : message.content\n .map((part) =>\n typeof part === \"string\" ? part : part.text || \"\"\n )\n .join(\"\"),\n } as XAIResponsesMessage;\n }\n\n if (message.type === \"ai\") {\n const aiMessage = message as AIMessage;\n return {\n type: \"message\",\n role: \"assistant\",\n text: typeof aiMessage.content === \"string\" ? aiMessage.content : \"\",\n } as unknown as XAIResponsesInputItem;\n }\n\n // Default fallback\n return {\n role: \"user\",\n content:\n typeof message.content === \"string\"\n ? message.content\n : JSON.stringify(message.content),\n } as XAIResponsesMessage;\n}\n\n/**\n * Converts an array of LangChain BaseMessages to xAI Responses API input format.\n *\n * @param messages - Array of LangChain messages to convert\n * @returns Array of xAI Responses API input items\n */\nexport function convertMessagesToResponsesInput(\n messages: BaseMessage[]\n): XAIResponsesInputItem[] {\n return messages.map(convertMessageToResponsesInput);\n}\n\n// ============================================================================\n// Usage Converters\n// ============================================================================\n\n/**\n * Converts xAI usage statistics to LangChain UsageMetadata format.\n *\n * @param usage - The xAI usage statistics\n * @returns LangChain UsageMetadata object\n */\nexport function convertUsageToUsageMetadata(\n usage: XAIResponsesUsage | null | undefined\n): UsageMetadata {\n return {\n input_tokens: usage?.input_tokens ?? 0,\n output_tokens: usage?.output_tokens ?? 0,\n total_tokens: usage?.total_tokens ?? 0,\n input_token_details: {\n ...(usage?.input_tokens_details?.cached_tokens != null && {\n cache_read: usage.input_tokens_details.cached_tokens,\n }),\n },\n output_token_details: {\n ...(usage?.output_tokens_details?.reasoning_tokens != null && {\n reasoning: usage.output_tokens_details.reasoning_tokens,\n }),\n },\n };\n}\n\n// ============================================================================\n// Output Converters\n// ============================================================================\n\n/**\n * Extracts text content from xAI response output items.\n *\n * @param output - Array of xAI response output items\n * @returns Concatenated text content\n */\nexport function extractTextFromOutput(\n output: XAIResponsesOutputItem[]\n): string {\n const textParts: string[] = [];\n\n for (const item of output) {\n if (item.type === \"message\" && \"content\" in item) {\n for (const contentItem of item.content as XAIResponsesOutputContent[]) {\n if (contentItem.type === \"output_text\") {\n textParts.push(contentItem.text);\n }\n }\n }\n }\n\n return textParts.join(\"\");\n}\n\n/**\n * Converts an xAI Response to a LangChain AIMessage.\n *\n * @param response - The xAI API response\n * @returns LangChain AIMessage\n */\nexport function convertResponseToAIMessage(response: XAIResponse): AIMessage {\n const text = extractTextFromOutput(response.output);\n\n const responseMetadata: Record<string, unknown> = {\n model_provider: \"xai\",\n model: response.model,\n created_at: response.created_at,\n id: response.id,\n status: response.status,\n object: response.object,\n };\n\n if (response.incomplete_details) {\n responseMetadata.incomplete_details = response.incomplete_details;\n }\n\n return new AIMessage({\n content: text,\n usage_metadata: convertUsageToUsageMetadata(response.usage),\n response_metadata: responseMetadata,\n additional_kwargs: {\n ...(response.reasoning && { reasoning: response.reasoning }),\n },\n });\n}\n\n// ============================================================================\n// Streaming Converters\n// ============================================================================\n\n/**\n * Converts an xAI streaming event to a LangChain ChatGenerationChunk.\n *\n * @param event - The xAI streaming event\n * @returns ChatGenerationChunk or null if the event doesn't produce a chunk\n */\nexport function convertStreamEventToChunk(\n event: XAIResponsesStreamEvent\n): ChatGenerationChunk | null {\n const responseMetadata: Record<string, unknown> = {\n model_provider: \"xai\",\n };\n\n if (event.type === \"response.output_text.delta\") {\n return new ChatGenerationChunk({\n text: event.delta,\n message: new AIMessageChunk({\n content: event.delta,\n response_metadata: responseMetadata,\n }),\n });\n }\n\n if (event.type === \"response.created\") {\n responseMetadata.id = event.response.id;\n responseMetadata.model = event.response.model;\n return new ChatGenerationChunk({\n text: \"\",\n message: new AIMessageChunk({\n content: \"\",\n response_metadata: responseMetadata,\n }),\n });\n }\n\n if (event.type === \"response.completed\") {\n const aiMessage = convertResponseToAIMessage(event.response);\n return new ChatGenerationChunk({\n text: \"\",\n message: new AIMessageChunk({\n content: \"\",\n usage_metadata: aiMessage.usage_metadata,\n response_metadata: {\n ...responseMetadata,\n ...aiMessage.response_metadata,\n },\n }),\n });\n }\n\n return null;\n}\n"],"mappings":"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"}
@@ -0,0 +1,164 @@
1
+ import { AIMessage, AIMessageChunk } from "@langchain/core/messages";
2
+ import { ChatGenerationChunk } from "@langchain/core/outputs";
3
+
4
+ //#region src/converters/responses.ts
5
+ /**
6
+ * Converts a single LangChain BaseMessage to xAI Responses API input format.
7
+ *
8
+ * @param message - The LangChain message to convert
9
+ * @returns The xAI Responses API input item
10
+ */
11
+ function convertMessageToResponsesInput(message) {
12
+ if (message.type === "human") {
13
+ const content = typeof message.content === "string" ? message.content : message.content.map((part) => {
14
+ if (typeof part === "string") return {
15
+ type: "input_text",
16
+ text: part
17
+ };
18
+ if (part.type === "text") return {
19
+ type: "input_text",
20
+ text: part.text
21
+ };
22
+ if (part.type === "image_url") {
23
+ const imageUrlPart = part;
24
+ const imageUrl = typeof imageUrlPart.image_url === "string" ? imageUrlPart.image_url : imageUrlPart.image_url.url;
25
+ return {
26
+ type: "input_image",
27
+ image_url: imageUrl,
28
+ detail: "auto"
29
+ };
30
+ }
31
+ return {
32
+ type: "input_text",
33
+ text: ""
34
+ };
35
+ });
36
+ return {
37
+ role: "user",
38
+ content
39
+ };
40
+ }
41
+ if (message.type === "system") return {
42
+ role: "system",
43
+ content: typeof message.content === "string" ? message.content : message.content.map((part) => typeof part === "string" ? part : part.text || "").join("")
44
+ };
45
+ if (message.type === "ai") {
46
+ const aiMessage = message;
47
+ return {
48
+ type: "message",
49
+ role: "assistant",
50
+ text: typeof aiMessage.content === "string" ? aiMessage.content : ""
51
+ };
52
+ }
53
+ return {
54
+ role: "user",
55
+ content: typeof message.content === "string" ? message.content : JSON.stringify(message.content)
56
+ };
57
+ }
58
+ /**
59
+ * Converts an array of LangChain BaseMessages to xAI Responses API input format.
60
+ *
61
+ * @param messages - Array of LangChain messages to convert
62
+ * @returns Array of xAI Responses API input items
63
+ */
64
+ function convertMessagesToResponsesInput(messages) {
65
+ return messages.map(convertMessageToResponsesInput);
66
+ }
67
+ /**
68
+ * Converts xAI usage statistics to LangChain UsageMetadata format.
69
+ *
70
+ * @param usage - The xAI usage statistics
71
+ * @returns LangChain UsageMetadata object
72
+ */
73
+ function convertUsageToUsageMetadata(usage) {
74
+ return {
75
+ input_tokens: usage?.input_tokens ?? 0,
76
+ output_tokens: usage?.output_tokens ?? 0,
77
+ total_tokens: usage?.total_tokens ?? 0,
78
+ input_token_details: { ...usage?.input_tokens_details?.cached_tokens != null && { cache_read: usage.input_tokens_details.cached_tokens } },
79
+ output_token_details: { ...usage?.output_tokens_details?.reasoning_tokens != null && { reasoning: usage.output_tokens_details.reasoning_tokens } }
80
+ };
81
+ }
82
+ /**
83
+ * Extracts text content from xAI response output items.
84
+ *
85
+ * @param output - Array of xAI response output items
86
+ * @returns Concatenated text content
87
+ */
88
+ function extractTextFromOutput(output) {
89
+ const textParts = [];
90
+ for (const item of output) if (item.type === "message" && "content" in item) {
91
+ for (const contentItem of item.content) if (contentItem.type === "output_text") textParts.push(contentItem.text);
92
+ }
93
+ return textParts.join("");
94
+ }
95
+ /**
96
+ * Converts an xAI Response to a LangChain AIMessage.
97
+ *
98
+ * @param response - The xAI API response
99
+ * @returns LangChain AIMessage
100
+ */
101
+ function convertResponseToAIMessage(response) {
102
+ const text = extractTextFromOutput(response.output);
103
+ const responseMetadata = {
104
+ model_provider: "xai",
105
+ model: response.model,
106
+ created_at: response.created_at,
107
+ id: response.id,
108
+ status: response.status,
109
+ object: response.object
110
+ };
111
+ if (response.incomplete_details) responseMetadata.incomplete_details = response.incomplete_details;
112
+ return new AIMessage({
113
+ content: text,
114
+ usage_metadata: convertUsageToUsageMetadata(response.usage),
115
+ response_metadata: responseMetadata,
116
+ additional_kwargs: { ...response.reasoning && { reasoning: response.reasoning } }
117
+ });
118
+ }
119
+ /**
120
+ * Converts an xAI streaming event to a LangChain ChatGenerationChunk.
121
+ *
122
+ * @param event - The xAI streaming event
123
+ * @returns ChatGenerationChunk or null if the event doesn't produce a chunk
124
+ */
125
+ function convertStreamEventToChunk(event) {
126
+ const responseMetadata = { model_provider: "xai" };
127
+ if (event.type === "response.output_text.delta") return new ChatGenerationChunk({
128
+ text: event.delta,
129
+ message: new AIMessageChunk({
130
+ content: event.delta,
131
+ response_metadata: responseMetadata
132
+ })
133
+ });
134
+ if (event.type === "response.created") {
135
+ responseMetadata.id = event.response.id;
136
+ responseMetadata.model = event.response.model;
137
+ return new ChatGenerationChunk({
138
+ text: "",
139
+ message: new AIMessageChunk({
140
+ content: "",
141
+ response_metadata: responseMetadata
142
+ })
143
+ });
144
+ }
145
+ if (event.type === "response.completed") {
146
+ const aiMessage = convertResponseToAIMessage(event.response);
147
+ return new ChatGenerationChunk({
148
+ text: "",
149
+ message: new AIMessageChunk({
150
+ content: "",
151
+ usage_metadata: aiMessage.usage_metadata,
152
+ response_metadata: {
153
+ ...responseMetadata,
154
+ ...aiMessage.response_metadata
155
+ }
156
+ })
157
+ });
158
+ }
159
+ return null;
160
+ }
161
+
162
+ //#endregion
163
+ export { convertMessagesToResponsesInput, convertResponseToAIMessage, convertStreamEventToChunk, extractTextFromOutput };
164
+ //# sourceMappingURL=responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.js","names":["message: BaseMessage","messages: BaseMessage[]","usage: XAIResponsesUsage | null | undefined","output: XAIResponsesOutputItem[]","textParts: string[]","response: XAIResponse","responseMetadata: Record<string, unknown>","event: XAIResponsesStreamEvent"],"sources":["../../src/converters/responses.ts"],"sourcesContent":["import {\n AIMessage,\n AIMessageChunk,\n BaseMessage,\n type UsageMetadata,\n} from \"@langchain/core/messages\";\nimport { ChatGenerationChunk } from \"@langchain/core/outputs\";\n\nimport type {\n XAIResponse,\n XAIResponsesInputItem,\n XAIResponsesMessage,\n XAIResponsesOutputContent,\n XAIResponsesOutputItem,\n XAIResponsesStreamEvent,\n XAIResponsesUsage,\n} from \"../chat_models/responses-types.js\";\n\n// ============================================================================\n// Message Converters\n// ============================================================================\n\n/**\n * Converts a single LangChain BaseMessage to xAI Responses API input format.\n *\n * @param message - The LangChain message to convert\n * @returns The xAI Responses API input item\n */\nexport function convertMessageToResponsesInput(\n message: BaseMessage\n): XAIResponsesInputItem {\n if (message.type === \"human\") {\n const content =\n typeof message.content === \"string\"\n ? message.content\n : message.content.map((part) => {\n if (typeof part === \"string\") {\n return { type: \"input_text\" as const, text: part };\n }\n if (part.type === \"text\") {\n return { type: \"input_text\" as const, text: part.text };\n }\n if (part.type === \"image_url\") {\n const imageUrlPart = part as {\n type: \"image_url\";\n image_url: string | { url: string };\n };\n const imageUrl =\n typeof imageUrlPart.image_url === \"string\"\n ? imageUrlPart.image_url\n : imageUrlPart.image_url.url;\n return {\n type: \"input_image\" as const,\n image_url: imageUrl,\n detail: \"auto\" as const,\n };\n }\n return { type: \"input_text\" as const, text: \"\" };\n });\n\n return {\n role: \"user\",\n content,\n } as XAIResponsesMessage;\n }\n\n if (message.type === \"system\") {\n return {\n role: \"system\",\n content:\n typeof message.content === \"string\"\n ? message.content\n : message.content\n .map((part) =>\n typeof part === \"string\" ? part : part.text || \"\"\n )\n .join(\"\"),\n } as XAIResponsesMessage;\n }\n\n if (message.type === \"ai\") {\n const aiMessage = message as AIMessage;\n return {\n type: \"message\",\n role: \"assistant\",\n text: typeof aiMessage.content === \"string\" ? aiMessage.content : \"\",\n } as unknown as XAIResponsesInputItem;\n }\n\n // Default fallback\n return {\n role: \"user\",\n content:\n typeof message.content === \"string\"\n ? message.content\n : JSON.stringify(message.content),\n } as XAIResponsesMessage;\n}\n\n/**\n * Converts an array of LangChain BaseMessages to xAI Responses API input format.\n *\n * @param messages - Array of LangChain messages to convert\n * @returns Array of xAI Responses API input items\n */\nexport function convertMessagesToResponsesInput(\n messages: BaseMessage[]\n): XAIResponsesInputItem[] {\n return messages.map(convertMessageToResponsesInput);\n}\n\n// ============================================================================\n// Usage Converters\n// ============================================================================\n\n/**\n * Converts xAI usage statistics to LangChain UsageMetadata format.\n *\n * @param usage - The xAI usage statistics\n * @returns LangChain UsageMetadata object\n */\nexport function convertUsageToUsageMetadata(\n usage: XAIResponsesUsage | null | undefined\n): UsageMetadata {\n return {\n input_tokens: usage?.input_tokens ?? 0,\n output_tokens: usage?.output_tokens ?? 0,\n total_tokens: usage?.total_tokens ?? 0,\n input_token_details: {\n ...(usage?.input_tokens_details?.cached_tokens != null && {\n cache_read: usage.input_tokens_details.cached_tokens,\n }),\n },\n output_token_details: {\n ...(usage?.output_tokens_details?.reasoning_tokens != null && {\n reasoning: usage.output_tokens_details.reasoning_tokens,\n }),\n },\n };\n}\n\n// ============================================================================\n// Output Converters\n// ============================================================================\n\n/**\n * Extracts text content from xAI response output items.\n *\n * @param output - Array of xAI response output items\n * @returns Concatenated text content\n */\nexport function extractTextFromOutput(\n output: XAIResponsesOutputItem[]\n): string {\n const textParts: string[] = [];\n\n for (const item of output) {\n if (item.type === \"message\" && \"content\" in item) {\n for (const contentItem of item.content as XAIResponsesOutputContent[]) {\n if (contentItem.type === \"output_text\") {\n textParts.push(contentItem.text);\n }\n }\n }\n }\n\n return textParts.join(\"\");\n}\n\n/**\n * Converts an xAI Response to a LangChain AIMessage.\n *\n * @param response - The xAI API response\n * @returns LangChain AIMessage\n */\nexport function convertResponseToAIMessage(response: XAIResponse): AIMessage {\n const text = extractTextFromOutput(response.output);\n\n const responseMetadata: Record<string, unknown> = {\n model_provider: \"xai\",\n model: response.model,\n created_at: response.created_at,\n id: response.id,\n status: response.status,\n object: response.object,\n };\n\n if (response.incomplete_details) {\n responseMetadata.incomplete_details = response.incomplete_details;\n }\n\n return new AIMessage({\n content: text,\n usage_metadata: convertUsageToUsageMetadata(response.usage),\n response_metadata: responseMetadata,\n additional_kwargs: {\n ...(response.reasoning && { reasoning: response.reasoning }),\n },\n });\n}\n\n// ============================================================================\n// Streaming Converters\n// ============================================================================\n\n/**\n * Converts an xAI streaming event to a LangChain ChatGenerationChunk.\n *\n * @param event - The xAI streaming event\n * @returns ChatGenerationChunk or null if the event doesn't produce a chunk\n */\nexport function convertStreamEventToChunk(\n event: XAIResponsesStreamEvent\n): ChatGenerationChunk | null {\n const responseMetadata: Record<string, unknown> = {\n model_provider: \"xai\",\n };\n\n if (event.type === \"response.output_text.delta\") {\n return new ChatGenerationChunk({\n text: event.delta,\n message: new AIMessageChunk({\n content: event.delta,\n response_metadata: responseMetadata,\n }),\n });\n }\n\n if (event.type === \"response.created\") {\n responseMetadata.id = event.response.id;\n responseMetadata.model = event.response.model;\n return new ChatGenerationChunk({\n text: \"\",\n message: new AIMessageChunk({\n content: \"\",\n response_metadata: responseMetadata,\n }),\n });\n }\n\n if (event.type === \"response.completed\") {\n const aiMessage = convertResponseToAIMessage(event.response);\n return new ChatGenerationChunk({\n text: \"\",\n message: new AIMessageChunk({\n content: \"\",\n usage_metadata: aiMessage.usage_metadata,\n response_metadata: {\n ...responseMetadata,\n ...aiMessage.response_metadata,\n },\n }),\n });\n }\n\n return null;\n}\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,6 +1,9 @@
1
- const require_chat_models = require('./chat_models.cjs');
2
- const require_index = require('./tools/index.cjs');
1
+ const require_completions = require('./chat_models/completions.cjs');
2
+ const require_responses = require('./chat_models/responses.cjs');
3
+ require('./chat_models/index.cjs');
4
+ const require_index$1 = require('./tools/index.cjs');
3
5
 
4
- exports.ChatXAI = require_chat_models.ChatXAI;
5
- exports.isXAIBuiltInTool = require_chat_models.isXAIBuiltInTool;
6
- exports.tools = require_index.tools;
6
+ exports.ChatXAI = require_completions.ChatXAI;
7
+ exports.ChatXAIResponses = require_responses.ChatXAIResponses;
8
+ exports.isXAIBuiltInTool = require_completions.isXAIBuiltInTool;
9
+ exports.tools = require_index$1.tools;