@yourgpt/llm-sdk 2.1.3 → 2.1.4-alpha.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 (58) hide show
  1. package/README.md +59 -0
  2. package/dist/adapters/index.d.mts +9 -2
  3. package/dist/adapters/index.d.ts +9 -2
  4. package/dist/adapters/index.js +421 -19
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/adapters/index.mjs +421 -19
  7. package/dist/adapters/index.mjs.map +1 -1
  8. package/dist/index.d.mts +164 -11
  9. package/dist/index.d.ts +164 -11
  10. package/dist/index.js +638 -54
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +635 -55
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/providers/anthropic/index.d.mts +1 -1
  15. package/dist/providers/anthropic/index.d.ts +1 -1
  16. package/dist/providers/anthropic/index.js +95 -1
  17. package/dist/providers/anthropic/index.js.map +1 -1
  18. package/dist/providers/anthropic/index.mjs +95 -1
  19. package/dist/providers/anthropic/index.mjs.map +1 -1
  20. package/dist/providers/azure/index.d.mts +1 -1
  21. package/dist/providers/azure/index.d.ts +1 -1
  22. package/dist/providers/azure/index.js +51 -5
  23. package/dist/providers/azure/index.js.map +1 -1
  24. package/dist/providers/azure/index.mjs +51 -5
  25. package/dist/providers/azure/index.mjs.map +1 -1
  26. package/dist/providers/google/index.d.mts +1 -1
  27. package/dist/providers/google/index.d.ts +1 -1
  28. package/dist/providers/google/index.js +76 -0
  29. package/dist/providers/google/index.js.map +1 -1
  30. package/dist/providers/google/index.mjs +76 -0
  31. package/dist/providers/google/index.mjs.map +1 -1
  32. package/dist/providers/ollama/index.d.mts +2 -2
  33. package/dist/providers/ollama/index.d.ts +2 -2
  34. package/dist/providers/ollama/index.js +51 -8
  35. package/dist/providers/ollama/index.js.map +1 -1
  36. package/dist/providers/ollama/index.mjs +51 -8
  37. package/dist/providers/ollama/index.mjs.map +1 -1
  38. package/dist/providers/openai/index.d.mts +1 -1
  39. package/dist/providers/openai/index.d.ts +1 -1
  40. package/dist/providers/openai/index.js +301 -3
  41. package/dist/providers/openai/index.js.map +1 -1
  42. package/dist/providers/openai/index.mjs +301 -3
  43. package/dist/providers/openai/index.mjs.map +1 -1
  44. package/dist/providers/openrouter/index.d.mts +1 -1
  45. package/dist/providers/openrouter/index.d.ts +1 -1
  46. package/dist/providers/openrouter/index.js +301 -3
  47. package/dist/providers/openrouter/index.js.map +1 -1
  48. package/dist/providers/openrouter/index.mjs +301 -3
  49. package/dist/providers/openrouter/index.mjs.map +1 -1
  50. package/dist/providers/xai/index.d.mts +1 -1
  51. package/dist/providers/xai/index.d.ts +1 -1
  52. package/dist/providers/xai/index.js +51 -5
  53. package/dist/providers/xai/index.js.map +1 -1
  54. package/dist/providers/xai/index.mjs +51 -5
  55. package/dist/providers/xai/index.mjs.map +1 -1
  56. package/dist/{types-D20jKwJW.d.mts → types-COAOEe_y.d.mts} +68 -8
  57. package/dist/{types-D20jKwJW.d.ts → types-COAOEe_y.d.ts} +68 -8
  58. package/package.json +1 -1
@@ -257,8 +257,49 @@ function generateId(prefix = "id") {
257
257
  function generateMessageId() {
258
258
  return generateId("msg");
259
259
  }
260
+ function generateToolCallId() {
261
+ return generateId("call");
262
+ }
260
263
 
261
264
  // src/adapters/base.ts
265
+ function stringifyForDebug(value) {
266
+ return JSON.stringify(
267
+ value,
268
+ (_key, currentValue) => {
269
+ if (typeof currentValue === "bigint") {
270
+ return currentValue.toString();
271
+ }
272
+ if (currentValue instanceof Error) {
273
+ return {
274
+ name: currentValue.name,
275
+ message: currentValue.message,
276
+ stack: currentValue.stack
277
+ };
278
+ }
279
+ return currentValue;
280
+ },
281
+ 2
282
+ );
283
+ }
284
+ function logProviderPayload(provider, label, payload, enabled) {
285
+ if (!enabled) {
286
+ return;
287
+ }
288
+ if (label.toLowerCase().includes("stream ")) {
289
+ return;
290
+ }
291
+ try {
292
+ console.log(
293
+ `[llm-sdk:${provider}] ${label}
294
+ ${stringifyForDebug(payload)}`
295
+ );
296
+ } catch (error) {
297
+ console.log(
298
+ `[llm-sdk:${provider}] ${label} (failed to stringify payload)`,
299
+ error
300
+ );
301
+ }
302
+ }
262
303
  function parameterToJsonSchema(param) {
263
304
  const schema = {
264
305
  type: param.type
@@ -283,9 +324,44 @@ function parameterToJsonSchema(param) {
283
324
  )
284
325
  ])
285
326
  );
327
+ schema.additionalProperties = false;
286
328
  }
287
329
  return schema;
288
330
  }
331
+ function normalizeObjectJsonSchema(schema) {
332
+ if (!schema || typeof schema !== "object") {
333
+ return {
334
+ type: "object",
335
+ properties: {},
336
+ required: [],
337
+ additionalProperties: false
338
+ };
339
+ }
340
+ const normalized = { ...schema };
341
+ const type = normalized.type;
342
+ if (type === "object") {
343
+ const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : {};
344
+ normalized.properties = Object.fromEntries(
345
+ Object.entries(properties).map(([key, value]) => [
346
+ key,
347
+ normalizeObjectJsonSchema(value)
348
+ ])
349
+ );
350
+ const propertyKeys = Object.keys(properties);
351
+ const required = Array.isArray(normalized.required) ? normalized.required.filter(
352
+ (value) => typeof value === "string"
353
+ ) : [];
354
+ normalized.required = Array.from(/* @__PURE__ */ new Set([...required, ...propertyKeys]));
355
+ if (normalized.additionalProperties === void 0) {
356
+ normalized.additionalProperties = false;
357
+ }
358
+ } else if (type === "array" && normalized.items && typeof normalized.items === "object") {
359
+ normalized.items = normalizeObjectJsonSchema(
360
+ normalized.items
361
+ );
362
+ }
363
+ return normalized;
364
+ }
289
365
  function formatTools(actions) {
290
366
  return actions.map((action) => ({
291
367
  type: "function",
@@ -300,7 +376,8 @@ function formatTools(actions) {
300
376
  parameterToJsonSchema(param)
301
377
  ])
302
378
  ) : {},
303
- required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : []
379
+ required: action.parameters ? Object.entries(action.parameters).filter(([, param]) => param.required).map(([key]) => key) : [],
380
+ additionalProperties: false
304
381
  }
305
382
  }
306
383
  }));
@@ -397,7 +474,152 @@ var OpenAIAdapter = class {
397
474
  }
398
475
  return this.client;
399
476
  }
477
+ shouldUseResponsesApi(request) {
478
+ return request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false && Array.isArray(request.toolDefinitions) && request.toolDefinitions.length > 0;
479
+ }
480
+ buildResponsesInput(request) {
481
+ const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI(request.messages, void 0);
482
+ const input = [];
483
+ for (const message of sourceMessages) {
484
+ if (message.role === "system") {
485
+ continue;
486
+ }
487
+ if (message.role === "assistant") {
488
+ const content = typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content : message.content ? JSON.stringify(message.content) : "";
489
+ if (content) {
490
+ input.push({
491
+ type: "message",
492
+ role: "assistant",
493
+ content
494
+ });
495
+ }
496
+ const toolCalls = Array.isArray(message.tool_calls) ? message.tool_calls : [];
497
+ for (const toolCall of toolCalls) {
498
+ input.push({
499
+ type: "function_call",
500
+ call_id: toolCall.id,
501
+ name: toolCall.function?.name,
502
+ arguments: toolCall.function?.arguments ?? "{}"
503
+ });
504
+ }
505
+ continue;
506
+ }
507
+ if (message.role === "tool") {
508
+ input.push({
509
+ type: "function_call_output",
510
+ call_id: message.tool_call_id,
511
+ output: typeof message.content === "string" ? message.content : JSON.stringify(message.content ?? null)
512
+ });
513
+ continue;
514
+ }
515
+ input.push({
516
+ type: "message",
517
+ role: message.role === "developer" ? "developer" : "user",
518
+ content: typeof message.content === "string" ? message.content : Array.isArray(message.content) ? message.content : JSON.stringify(message.content ?? "")
519
+ });
520
+ }
521
+ return input;
522
+ }
523
+ buildResponsesTools(tools) {
524
+ const nativeTools = tools.filter((tool) => tool.available !== false).map((tool) => ({
525
+ type: "function",
526
+ name: tool.name,
527
+ description: tool.description,
528
+ parameters: normalizeObjectJsonSchema(
529
+ tool.inputSchema ?? {
530
+ type: "object",
531
+ properties: {},
532
+ required: []
533
+ }
534
+ ),
535
+ strict: true,
536
+ defer_loading: tool.deferLoading === true
537
+ }));
538
+ return [{ type: "tool_search" }, ...nativeTools];
539
+ }
540
+ parseResponsesResult(response) {
541
+ const content = typeof response?.output_text === "string" ? response.output_text : "";
542
+ const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => ({
543
+ id: item.call_id ?? item.id ?? generateToolCallId(),
544
+ name: item.name,
545
+ args: (() => {
546
+ try {
547
+ return JSON.parse(item.arguments ?? "{}");
548
+ } catch {
549
+ return {};
550
+ }
551
+ })()
552
+ })) : [];
553
+ return {
554
+ content,
555
+ toolCalls,
556
+ usage: response?.usage ? {
557
+ promptTokens: response.usage.input_tokens ?? 0,
558
+ completionTokens: response.usage.output_tokens ?? 0,
559
+ totalTokens: response.usage.total_tokens ?? (response.usage.input_tokens ?? 0) + (response.usage.output_tokens ?? 0)
560
+ } : void 0,
561
+ rawResponse: response
562
+ };
563
+ }
564
+ async completeWithResponses(request) {
565
+ const client = await this.getClient();
566
+ const openaiToolOptions = request.providerToolOptions?.openai;
567
+ const payload = {
568
+ model: request.config?.model || this.model,
569
+ instructions: request.systemPrompt,
570
+ input: this.buildResponsesInput(request),
571
+ tools: this.buildResponsesTools(request.toolDefinitions ?? []),
572
+ tool_choice: openaiToolOptions?.toolChoice === "required" ? "required" : openaiToolOptions?.toolChoice === "auto" ? "auto" : void 0,
573
+ parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
574
+ temperature: request.config?.temperature ?? this.config.temperature,
575
+ max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
576
+ stream: false
577
+ };
578
+ logProviderPayload("openai", "request payload", payload, request.debug);
579
+ const response = await client.responses.create(payload);
580
+ logProviderPayload("openai", "response payload", response, request.debug);
581
+ return this.parseResponsesResult(response);
582
+ }
400
583
  async *stream(request) {
584
+ if (this.shouldUseResponsesApi(request)) {
585
+ const messageId2 = generateMessageId();
586
+ yield { type: "message:start", id: messageId2 };
587
+ try {
588
+ const result = await this.completeWithResponses(request);
589
+ if (result.content) {
590
+ yield { type: "message:delta", content: result.content };
591
+ }
592
+ for (const toolCall of result.toolCalls) {
593
+ yield {
594
+ type: "action:start",
595
+ id: toolCall.id,
596
+ name: toolCall.name
597
+ };
598
+ yield {
599
+ type: "action:args",
600
+ id: toolCall.id,
601
+ args: JSON.stringify(toolCall.args)
602
+ };
603
+ }
604
+ yield { type: "message:end" };
605
+ yield {
606
+ type: "done",
607
+ usage: result.usage ? {
608
+ prompt_tokens: result.usage.promptTokens,
609
+ completion_tokens: result.usage.completionTokens,
610
+ total_tokens: result.usage.totalTokens
611
+ } : void 0
612
+ };
613
+ return;
614
+ } catch (error) {
615
+ yield {
616
+ type: "error",
617
+ message: error instanceof Error ? error.message : "Unknown error",
618
+ code: "OPENAI_RESPONSES_ERROR"
619
+ };
620
+ return;
621
+ }
622
+ }
401
623
  const client = await this.getClient();
402
624
  let messages;
403
625
  if (request.rawMessages && request.rawMessages.length > 0) {
@@ -462,20 +684,32 @@ var OpenAIAdapter = class {
462
684
  const messageId = generateMessageId();
463
685
  yield { type: "message:start", id: messageId };
464
686
  try {
465
- const stream = await client.chat.completions.create({
687
+ const openaiToolOptions = request.providerToolOptions?.openai;
688
+ const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
689
+ type: "function",
690
+ function: {
691
+ name: openaiToolOptions.toolChoice.name
692
+ }
693
+ } : openaiToolOptions?.toolChoice;
694
+ const payload = {
466
695
  model: request.config?.model || this.model,
467
696
  messages,
468
697
  tools: tools.length > 0 ? tools : void 0,
698
+ tool_choice: tools.length > 0 ? toolChoice : void 0,
699
+ parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
469
700
  temperature: request.config?.temperature ?? this.config.temperature,
470
701
  max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
471
702
  stream: true,
472
703
  stream_options: { include_usage: true }
473
- });
704
+ };
705
+ logProviderPayload("openai", "request payload", payload, request.debug);
706
+ const stream = await client.chat.completions.create(payload);
474
707
  let currentToolCall = null;
475
708
  const collectedCitations = [];
476
709
  let citationIndex = 0;
477
710
  let usage;
478
711
  for await (const chunk of stream) {
712
+ logProviderPayload("openai", "stream chunk", chunk, request.debug);
479
713
  if (request.signal?.aborted) {
480
714
  break;
481
715
  }
@@ -557,6 +791,70 @@ var OpenAIAdapter = class {
557
791
  };
558
792
  }
559
793
  }
794
+ async complete(request) {
795
+ if (this.shouldUseResponsesApi(request)) {
796
+ return this.completeWithResponses(request);
797
+ }
798
+ const client = await this.getClient();
799
+ let messages;
800
+ if (request.rawMessages && request.rawMessages.length > 0) {
801
+ messages = request.rawMessages;
802
+ if (request.systemPrompt && !messages.some((message2) => message2.role === "system")) {
803
+ messages = [
804
+ { role: "system", content: request.systemPrompt },
805
+ ...messages
806
+ ];
807
+ }
808
+ } else {
809
+ messages = formatMessagesForOpenAI(
810
+ request.messages,
811
+ request.systemPrompt
812
+ );
813
+ }
814
+ const tools = request.actions?.length ? formatTools(request.actions) : [];
815
+ const openaiToolOptions = request.providerToolOptions?.openai;
816
+ const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
817
+ type: "function",
818
+ function: {
819
+ name: openaiToolOptions.toolChoice.name
820
+ }
821
+ } : openaiToolOptions?.toolChoice;
822
+ const payload = {
823
+ model: request.config?.model || this.model,
824
+ messages,
825
+ tools: tools.length > 0 ? tools : void 0,
826
+ tool_choice: tools.length > 0 ? toolChoice : void 0,
827
+ parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
828
+ temperature: request.config?.temperature ?? this.config.temperature,
829
+ max_tokens: request.config?.maxTokens ?? this.config.maxTokens,
830
+ stream: false
831
+ };
832
+ logProviderPayload("openai", "request payload", payload, request.debug);
833
+ const response = await client.chat.completions.create(payload);
834
+ logProviderPayload("openai", "response payload", response, request.debug);
835
+ const choice = response.choices?.[0];
836
+ const message = choice?.message;
837
+ return {
838
+ content: message?.content ?? "",
839
+ toolCalls: message?.tool_calls?.map((toolCall) => ({
840
+ id: toolCall.id ?? generateToolCallId(),
841
+ name: toolCall.function?.name ?? "",
842
+ args: (() => {
843
+ try {
844
+ return JSON.parse(toolCall.function?.arguments ?? "{}");
845
+ } catch {
846
+ return {};
847
+ }
848
+ })()
849
+ })) ?? [],
850
+ usage: response.usage ? {
851
+ promptTokens: response.usage.prompt_tokens,
852
+ completionTokens: response.usage.completion_tokens,
853
+ totalTokens: response.usage.total_tokens
854
+ } : void 0,
855
+ rawResponse: response
856
+ };
857
+ }
560
858
  };
561
859
  function extractDomain(url) {
562
860
  try {