@yourgpt/llm-sdk 2.5.0 → 2.5.1-beta.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 (59) hide show
  1. package/dist/adapters/index.d.mts +4 -4
  2. package/dist/adapters/index.d.ts +4 -4
  3. package/dist/adapters/index.js +156 -13
  4. package/dist/adapters/index.mjs +156 -13
  5. package/dist/base-C58Dsr9p.d.ts +259 -0
  6. package/dist/base-tNgbBaSo.d.mts +259 -0
  7. package/dist/fallback/index.d.mts +4 -4
  8. package/dist/fallback/index.d.ts +4 -4
  9. package/dist/index.d.mts +8 -7
  10. package/dist/index.d.ts +8 -7
  11. package/dist/index.js +12 -0
  12. package/dist/index.mjs +12 -0
  13. package/dist/providers/anthropic/index.d.mts +3 -3
  14. package/dist/providers/anthropic/index.d.ts +3 -3
  15. package/dist/providers/anthropic/index.js +271 -195
  16. package/dist/providers/anthropic/index.mjs +271 -195
  17. package/dist/providers/azure/index.d.mts +3 -3
  18. package/dist/providers/azure/index.d.ts +3 -3
  19. package/dist/providers/azure/index.js +49 -1
  20. package/dist/providers/azure/index.mjs +49 -1
  21. package/dist/providers/fireworks/index.d.mts +1 -1
  22. package/dist/providers/fireworks/index.d.ts +1 -1
  23. package/dist/providers/fireworks/index.js +56 -0
  24. package/dist/providers/fireworks/index.mjs +56 -0
  25. package/dist/providers/google/index.d.mts +3 -3
  26. package/dist/providers/google/index.d.ts +3 -3
  27. package/dist/providers/google/index.js +252 -205
  28. package/dist/providers/google/index.mjs +252 -205
  29. package/dist/providers/ollama/index.d.mts +4 -4
  30. package/dist/providers/ollama/index.d.ts +4 -4
  31. package/dist/providers/ollama/index.js +10 -2
  32. package/dist/providers/ollama/index.mjs +10 -2
  33. package/dist/providers/openai/index.d.mts +3 -3
  34. package/dist/providers/openai/index.d.ts +3 -3
  35. package/dist/providers/openai/index.js +267 -214
  36. package/dist/providers/openai/index.mjs +267 -214
  37. package/dist/providers/openrouter/index.d.mts +3 -3
  38. package/dist/providers/openrouter/index.d.ts +3 -3
  39. package/dist/providers/openrouter/index.js +257 -204
  40. package/dist/providers/openrouter/index.mjs +257 -204
  41. package/dist/providers/togetherai/index.d.mts +3 -3
  42. package/dist/providers/togetherai/index.d.ts +3 -3
  43. package/dist/providers/togetherai/index.js +257 -204
  44. package/dist/providers/togetherai/index.mjs +257 -204
  45. package/dist/providers/xai/index.d.mts +3 -3
  46. package/dist/providers/xai/index.d.ts +3 -3
  47. package/dist/providers/xai/index.js +256 -208
  48. package/dist/providers/xai/index.mjs +256 -208
  49. package/dist/{types-D4YfrQJR.d.mts → types-B6dhnguR.d.mts} +1 -1
  50. package/dist/{types-DRqxMIjF.d.mts → types-BQ31QIsA.d.ts} +2 -1
  51. package/dist/{types-BctsnC3g.d.ts → types-BSSiJW2o.d.mts} +2 -1
  52. package/dist/{base-D-U61JaB.d.mts → types-BkQCSiIt.d.mts} +388 -213
  53. package/dist/{base-iGi9Va6Z.d.ts → types-BkQCSiIt.d.ts} +388 -213
  54. package/dist/{types-38yolWJn.d.ts → types-CCxPmkmK.d.ts} +1 -1
  55. package/dist/yourgpt/index.d.mts +1 -1
  56. package/dist/yourgpt/index.d.ts +1 -1
  57. package/package.json +1 -1
  58. package/dist/types-CR8mi9I0.d.mts +0 -417
  59. package/dist/types-CR8mi9I0.d.ts +0 -417
@@ -1,5 +1,234 @@
1
1
  'use strict';
2
2
 
3
+ // src/adapters/base.ts
4
+ function stringifyForDebug(value) {
5
+ return JSON.stringify(
6
+ value,
7
+ (_key, currentValue) => {
8
+ if (typeof currentValue === "bigint") {
9
+ return currentValue.toString();
10
+ }
11
+ if (currentValue instanceof Error) {
12
+ return {
13
+ name: currentValue.name,
14
+ message: currentValue.message,
15
+ stack: currentValue.stack
16
+ };
17
+ }
18
+ return currentValue;
19
+ },
20
+ 2
21
+ );
22
+ }
23
+ function logProviderPayload(provider, label, payload, enabled) {
24
+ if (!enabled) {
25
+ return;
26
+ }
27
+ if (label.toLowerCase().includes("stream ")) {
28
+ return;
29
+ }
30
+ try {
31
+ console.log(
32
+ `[llm-sdk:${provider}] ${label}
33
+ ${stringifyForDebug(payload)}`
34
+ );
35
+ } catch (error) {
36
+ console.log(
37
+ `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
38
+ error
39
+ );
40
+ }
41
+ }
42
+ function parameterToJsonSchema(param) {
43
+ const schema = {
44
+ type: param.type
45
+ };
46
+ if (param.description) {
47
+ schema.description = param.description;
48
+ }
49
+ if (param.enum) {
50
+ schema.enum = param.enum;
51
+ }
52
+ if (param.type === "array" && param.items) {
53
+ schema.items = parameterToJsonSchema(
54
+ param.items
55
+ );
56
+ }
57
+ if (param.type === "object" && param.properties) {
58
+ schema.properties = Object.fromEntries(
59
+ Object.entries(param.properties).map(([key, prop]) => [
60
+ key,
61
+ parameterToJsonSchema(
62
+ prop
63
+ )
64
+ ])
65
+ );
66
+ schema.additionalProperties = false;
67
+ }
68
+ return schema;
69
+ }
70
+ function normalizeObjectJsonSchema(schema) {
71
+ if (!schema || typeof schema !== "object") {
72
+ return {
73
+ type: "object",
74
+ properties: {},
75
+ required: [],
76
+ additionalProperties: false
77
+ };
78
+ }
79
+ const normalized = { ...schema };
80
+ const type = normalized.type;
81
+ if (type === "object") {
82
+ const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
83
+ normalized.properties = Object.fromEntries(
84
+ Object.entries(properties).map(([key, value]) => [
85
+ key,
86
+ normalizeObjectJsonSchema(value)
87
+ ])
88
+ );
89
+ const propertyKeys = Object.keys(properties);
90
+ const required = Array.isArray(normalized.required) ? normalized.required.filter(
91
+ (value) => typeof value === "string"
92
+ ) : [];
93
+ normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
94
+ if (normalized.additionalProperties === void 0) {
95
+ normalized.additionalProperties = false;
96
+ }
97
+ } else if (type === "array" && normalized.items && typeof normalized.items === "object") {
98
+ normalized.items = normalizeObjectJsonSchema(
99
+ normalized.items
100
+ );
101
+ }
102
+ return normalized;
103
+ }
104
+ function isOpenAIReasoningModel(modelId) {
105
+ if (!modelId) return false;
106
+ return /^(o1|o3|o4|gpt-5)/i.test(modelId);
107
+ }
108
+ function buildOpenAITokenParams(modelId, maxTokens, temperature) {
109
+ if (isOpenAIReasoningModel(modelId)) {
110
+ return { max_completion_tokens: maxTokens };
111
+ }
112
+ return { max_tokens: maxTokens, temperature };
113
+ }
114
+ function toOpenAIResponseFormat(rf) {
115
+ if (!rf) return void 0;
116
+ if (rf.type === "json_object") return { type: "json_object" };
117
+ return {
118
+ type: "json_schema",
119
+ json_schema: {
120
+ name: rf.json_schema.name,
121
+ schema: normalizeObjectJsonSchema(rf.json_schema.schema),
122
+ strict: rf.json_schema.strict ?? true
123
+ }
124
+ };
125
+ }
126
+ function toOpenAIResponsesTextFormat(rf) {
127
+ if (!rf || rf.type !== "json_schema") return void 0;
128
+ return {
129
+ type: "json_schema",
130
+ name: rf.json_schema.name,
131
+ schema: normalizeObjectJsonSchema(rf.json_schema.schema),
132
+ strict: rf.json_schema.strict ?? true
133
+ };
134
+ }
135
+ function formatTools(actions) {
136
+ return actions.map((action) => ({
137
+ type: "function",
138
+ function: {
139
+ name: action.name,
140
+ description: action.description,
141
+ parameters: {
142
+ type: "object",
143
+ properties: action.parameters ? Object.fromEntries(
144
+ Object.entries(action.parameters).map(([key, param]) => [
145
+ key,
146
+ parameterToJsonSchema(param)
147
+ ])
148
+ ) : {},
149
+ required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
150
+ additionalProperties: false
151
+ }
152
+ }
153
+ }));
154
+ }
155
+ function hasImageAttachments(message) {
156
+ const attachments = message.metadata?.attachments;
157
+ return attachments?.some((a) => a.type === "image") ?? false;
158
+ }
159
+ function attachmentToOpenAIImage(attachment) {
160
+ if (attachment.type !== "image") return null;
161
+ let imageUrl;
162
+ if (attachment.url) {
163
+ imageUrl = attachment.url;
164
+ } else if (attachment.data) {
165
+ imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
166
+ } else {
167
+ return null;
168
+ }
169
+ return {
170
+ type: "image_url",
171
+ image_url: {
172
+ url: imageUrl,
173
+ detail: "auto"
174
+ }
175
+ };
176
+ }
177
+ function messageToOpenAIContent(message) {
178
+ const attachments = message.metadata?.attachments;
179
+ const content = message.content ?? "";
180
+ if (!hasImageAttachments(message)) {
181
+ return content;
182
+ }
183
+ const blocks = [];
184
+ if (content) {
185
+ blocks.push({ type: "text", text: content });
186
+ }
187
+ if (attachments) {
188
+ for (const attachment of attachments) {
189
+ const imageBlock = attachmentToOpenAIImage(attachment);
190
+ if (imageBlock) {
191
+ blocks.push(imageBlock);
192
+ }
193
+ }
194
+ }
195
+ return blocks;
196
+ }
197
+ function formatMessagesForOpenAI(messages, systemPrompt) {
198
+ const formatted = [];
199
+ if (systemPrompt) {
200
+ formatted.push({ role: "system", content: systemPrompt });
201
+ }
202
+ for (const msg of messages) {
203
+ if (msg.role === "system") {
204
+ formatted.push({ role: "system", content: msg.content ?? "" });
205
+ } else if (msg.role === "user") {
206
+ formatted.push({
207
+ role: "user",
208
+ content: messageToOpenAIContent(msg)
209
+ });
210
+ } else if (msg.role === "assistant") {
211
+ const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
212
+ const assistantMsg = {
213
+ role: "assistant",
214
+ // Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
215
+ content: hasToolCalls ? msg.content || null : msg.content
216
+ };
217
+ if (hasToolCalls) {
218
+ assistantMsg.tool_calls = msg.tool_calls;
219
+ }
220
+ formatted.push(assistantMsg);
221
+ } else if (msg.role === "tool" && msg.tool_call_id) {
222
+ formatted.push({
223
+ role: "tool",
224
+ content: msg.content ?? "",
225
+ tool_call_id: msg.tool_call_id
226
+ });
227
+ }
228
+ }
229
+ return formatted;
230
+ }
231
+
3
232
  // src/providers/xai/provider.ts
4
233
  var XAI_MODELS = {
5
234
  // Grok 4.1 Fast (Latest - December 2025)
@@ -53,8 +282,8 @@ function xai(modelId, options = {}) {
53
282
  supportsVision: modelConfig.vision,
54
283
  supportsTools: modelConfig.tools,
55
284
  supportsStreaming: true,
56
- supportsJsonMode: false,
57
- // xAI doesn't support JSON mode yet
285
+ supportsJsonMode: true,
286
+ // OpenAI-compatible `response_format`
58
287
  supportsThinking: false,
59
288
  supportsPDF: false,
60
289
  maxTokens: modelConfig.maxTokens,
@@ -68,7 +297,8 @@ function xai(modelId, options = {}) {
68
297
  messages,
69
298
  tools: params.tools,
70
299
  temperature: params.temperature,
71
- max_tokens: params.maxTokens
300
+ max_tokens: params.maxTokens,
301
+ response_format: toOpenAIResponseFormat(params.responseFormat)
72
302
  });
73
303
  const choice = response.choices[0];
74
304
  const message = choice.message;
@@ -100,6 +330,7 @@ function xai(modelId, options = {}) {
100
330
  tools: params.tools,
101
331
  temperature: params.temperature,
102
332
  max_tokens: params.maxTokens,
333
+ response_format: toOpenAIResponseFormat(params.responseFormat),
103
334
  stream: true
104
335
  });
105
336
  let currentToolCall = null;
@@ -245,204 +476,6 @@ function generateToolCallId() {
245
476
  return generateId("call");
246
477
  }
247
478
 
248
- // src/adapters/base.ts
249
- function stringifyForDebug(value) {
250
- return JSON.stringify(
251
- value,
252
- (_key, currentValue) => {
253
- if (typeof currentValue === "bigint") {
254
- return currentValue.toString();
255
- }
256
- if (currentValue instanceof Error) {
257
- return {
258
- name: currentValue.name,
259
- message: currentValue.message,
260
- stack: currentValue.stack
261
- };
262
- }
263
- return currentValue;
264
- },
265
- 2
266
- );
267
- }
268
- function logProviderPayload(provider, label, payload, enabled) {
269
- if (!enabled) {
270
- return;
271
- }
272
- if (label.toLowerCase().includes("stream ")) {
273
- return;
274
- }
275
- try {
276
- console.log(
277
- `[llm-sdk:${provider}] ${label}
278
- ${stringifyForDebug(payload)}`
279
- );
280
- } catch (error) {
281
- console.log(
282
- `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
283
- error
284
- );
285
- }
286
- }
287
- function parameterToJsonSchema(param) {
288
- const schema = {
289
- type: param.type
290
- };
291
- if (param.description) {
292
- schema.description = param.description;
293
- }
294
- if (param.enum) {
295
- schema.enum = param.enum;
296
- }
297
- if (param.type === "array" && param.items) {
298
- schema.items = parameterToJsonSchema(
299
- param.items
300
- );
301
- }
302
- if (param.type === "object" && param.properties) {
303
- schema.properties = Object.fromEntries(
304
- Object.entries(param.properties).map(([key, prop]) => [
305
- key,
306
- parameterToJsonSchema(
307
- prop
308
- )
309
- ])
310
- );
311
- schema.additionalProperties = false;
312
- }
313
- return schema;
314
- }
315
- function normalizeObjectJsonSchema(schema) {
316
- if (!schema || typeof schema !== "object") {
317
- return {
318
- type: "object",
319
- properties: {},
320
- required: [],
321
- additionalProperties: false
322
- };
323
- }
324
- const normalized = { ...schema };
325
- const type = normalized.type;
326
- if (type === "object") {
327
- const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
328
- normalized.properties = Object.fromEntries(
329
- Object.entries(properties).map(([key, value]) => [
330
- key,
331
- normalizeObjectJsonSchema(value)
332
- ])
333
- );
334
- const propertyKeys = Object.keys(properties);
335
- const required = Array.isArray(normalized.required) ? normalized.required.filter(
336
- (value) => typeof value === "string"
337
- ) : [];
338
- normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
339
- if (normalized.additionalProperties === void 0) {
340
- normalized.additionalProperties = false;
341
- }
342
- } else if (type === "array" && normalized.items && typeof normalized.items === "object") {
343
- normalized.items = normalizeObjectJsonSchema(
344
- normalized.items
345
- );
346
- }
347
- return normalized;
348
- }
349
- function formatTools(actions) {
350
- return actions.map((action) => ({
351
- type: "function",
352
- function: {
353
- name: action.name,
354
- description: action.description,
355
- parameters: {
356
- type: "object",
357
- properties: action.parameters ? Object.fromEntries(
358
- Object.entries(action.parameters).map(([key, param]) => [
359
- key,
360
- parameterToJsonSchema(param)
361
- ])
362
- ) : {},
363
- required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
364
- additionalProperties: false
365
- }
366
- }
367
- }));
368
- }
369
- function hasImageAttachments(message) {
370
- const attachments = message.metadata?.attachments;
371
- return attachments?.some((a) => a.type === "image") ?? false;
372
- }
373
- function attachmentToOpenAIImage(attachment) {
374
- if (attachment.type !== "image") return null;
375
- let imageUrl;
376
- if (attachment.url) {
377
- imageUrl = attachment.url;
378
- } else if (attachment.data) {
379
- imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
380
- } else {
381
- return null;
382
- }
383
- return {
384
- type: "image_url",
385
- image_url: {
386
- url: imageUrl,
387
- detail: "auto"
388
- }
389
- };
390
- }
391
- function messageToOpenAIContent(message) {
392
- const attachments = message.metadata?.attachments;
393
- const content = message.content ?? "";
394
- if (!hasImageAttachments(message)) {
395
- return content;
396
- }
397
- const blocks = [];
398
- if (content) {
399
- blocks.push({ type: "text", text: content });
400
- }
401
- if (attachments) {
402
- for (const attachment of attachments) {
403
- const imageBlock = attachmentToOpenAIImage(attachment);
404
- if (imageBlock) {
405
- blocks.push(imageBlock);
406
- }
407
- }
408
- }
409
- return blocks;
410
- }
411
- function formatMessagesForOpenAI(messages, systemPrompt) {
412
- const formatted = [];
413
- if (systemPrompt) {
414
- formatted.push({ role: "system", content: systemPrompt });
415
- }
416
- for (const msg of messages) {
417
- if (msg.role === "system") {
418
- formatted.push({ role: "system", content: msg.content ?? "" });
419
- } else if (msg.role === "user") {
420
- formatted.push({
421
- role: "user",
422
- content: messageToOpenAIContent(msg)
423
- });
424
- } else if (msg.role === "assistant") {
425
- const hasToolCalls = msg.tool_calls && msg.tool_calls.length > 0;
426
- const assistantMsg = {
427
- role: "assistant",
428
- // Gemini/xAI (OpenAI-compatible) reject content: "" on assistant messages with tool_calls
429
- content: hasToolCalls ? msg.content || null : msg.content
430
- };
431
- if (hasToolCalls) {
432
- assistantMsg.tool_calls = msg.tool_calls;
433
- }
434
- formatted.push(assistantMsg);
435
- } else if (msg.role === "tool" && msg.tool_call_id) {
436
- formatted.push({
437
- role: "tool",
438
- content: msg.content ?? "",
439
- tool_call_id: msg.tool_call_id
440
- });
441
- }
442
- }
443
- return formatted;
444
- }
445
-
446
479
  // src/adapters/openai.ts
447
480
  var OpenAIAdapter = class _OpenAIAdapter {
448
481
  constructor(config) {
@@ -557,6 +590,9 @@ var OpenAIAdapter = class _OpenAIAdapter {
557
590
  async completeWithResponses(request) {
558
591
  const client = await this.getClient();
559
592
  const openaiToolOptions = request.providerToolOptions?.openai;
593
+ const responsesTextFormat = toOpenAIResponsesTextFormat(
594
+ request.config?.responseFormat
595
+ );
560
596
  const payload = {
561
597
  model: request.config?.model || this.model,
562
598
  instructions: request.systemPrompt,
@@ -566,6 +602,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
566
602
  parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
567
603
  temperature: request.config?.temperature ?? this.config.temperature,
568
604
  max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
605
+ ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
569
606
  stream: false
570
607
  };
571
608
  logProviderPayload("openai", "request payload", payload, request.debug);
@@ -687,14 +724,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
687
724
  name: openaiToolOptions.toolChoice.name
688
725
  }
689
726
  } : openaiToolOptions?.toolChoice;
727
+ const modelIdForPayload = request.config?.model || this.model;
690
728
  const payload = {
691
- model: request.config?.model || this.model,
729
+ model: modelIdForPayload,
692
730
  messages,
693
731
  tools: tools.length > 0 ? tools : void 0,
694
732
  tool_choice: tools.length > 0 ? toolChoice : void 0,
695
733
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
696
- temperature: request.config?.temperature ?? this.config.temperature,
697
- max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
734
+ ...buildOpenAITokenParams(
735
+ modelIdForPayload,
736
+ request.config?.maxTokens ?? this.config.maxTokens,
737
+ request.config?.temperature ?? this.config.temperature
738
+ ),
739
+ response_format: toOpenAIResponseFormat(request.config?.responseFormat),
698
740
  stream: true,
699
741
  stream_options: { include_usage: true }
700
742
  };
@@ -836,14 +878,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
836
878
  name: openaiToolOptions.toolChoice.name
837
879
  }
838
880
  } : openaiToolOptions?.toolChoice;
881
+ const modelIdForCompletePayload = request.config?.model || this.model;
839
882
  const payload = {
840
- model: request.config?.model || this.model,
883
+ model: modelIdForCompletePayload,
841
884
  messages,
842
885
  tools: tools.length > 0 ? tools : void 0,
843
886
  tool_choice: tools.length > 0 ? toolChoice : void 0,
844
887
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
845
- temperature: request.config?.temperature ?? this.config.temperature,
846
- max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
888
+ ...buildOpenAITokenParams(
889
+ modelIdForCompletePayload,
890
+ request.config?.maxTokens ?? this.config.maxTokens,
891
+ request.config?.temperature ?? this.config.temperature
892
+ ),
893
+ response_format: toOpenAIResponseFormat(request.config?.responseFormat),
847
894
  stream: false
848
895
  };
849
896
  logProviderPayload("openai", "request payload", payload, request.debug);
@@ -1039,7 +1086,8 @@ function createXAI(config = {}) {
1039
1086
  supportsVideo: false,
1040
1087
  maxTokens: model.maxTokens,
1041
1088
  supportedImageTypes: model.vision ? ["image/png", "image/jpeg", "image/gif", "image/webp"] : [],
1042
- supportsJsonMode: false,
1089
+ // xAI accepts OpenAI-compatible `response_format` on grok-2-1212+.
1090
+ supportsJsonMode: true,
1043
1091
  supportsSystemMessages: true
1044
1092
  };
1045
1093
  };