@yourgpt/llm-sdk 2.6.0-beta.0 → 2.6.0-beta.1

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 (55) hide show
  1. package/README.md +77 -0
  2. package/dist/adapters/index.d.mts +11 -13
  3. package/dist/adapters/index.d.ts +11 -13
  4. package/dist/adapters/index.js +255 -164
  5. package/dist/adapters/index.mjs +255 -164
  6. package/dist/{base-C58Dsr9p.d.ts → base-BdTpUAWI.d.ts} +2 -1
  7. package/dist/{base-tNgbBaSo.d.mts → base-CkeT7u-O.d.mts} +2 -1
  8. package/dist/fallback/index.d.mts +4 -4
  9. package/dist/fallback/index.d.ts +4 -4
  10. package/dist/fallback/index.js +75 -39
  11. package/dist/fallback/index.mjs +75 -39
  12. package/dist/index.d.mts +8 -7
  13. package/dist/index.d.ts +8 -7
  14. package/dist/index.js +75 -28
  15. package/dist/index.mjs +75 -28
  16. package/dist/providers/anthropic/index.d.mts +3 -3
  17. package/dist/providers/anthropic/index.d.ts +3 -3
  18. package/dist/providers/azure/index.d.mts +3 -3
  19. package/dist/providers/azure/index.d.ts +3 -3
  20. package/dist/providers/fireworks/index.d.mts +3 -3
  21. package/dist/providers/fireworks/index.d.ts +3 -3
  22. package/dist/providers/fireworks/index.js +255 -164
  23. package/dist/providers/fireworks/index.mjs +255 -164
  24. package/dist/providers/google/index.d.mts +3 -3
  25. package/dist/providers/google/index.d.ts +3 -3
  26. package/dist/providers/google/index.js +255 -164
  27. package/dist/providers/google/index.mjs +255 -164
  28. package/dist/providers/ollama/index.d.mts +4 -4
  29. package/dist/providers/ollama/index.d.ts +4 -4
  30. package/dist/providers/openai/index.d.mts +6 -23
  31. package/dist/providers/openai/index.d.ts +6 -23
  32. package/dist/providers/openai/index.js +656 -450
  33. package/dist/providers/openai/index.mjs +656 -450
  34. package/dist/providers/openrouter/index.d.mts +3 -3
  35. package/dist/providers/openrouter/index.d.ts +3 -3
  36. package/dist/providers/openrouter/index.js +255 -164
  37. package/dist/providers/openrouter/index.mjs +255 -164
  38. package/dist/providers/togetherai/index.d.mts +3 -3
  39. package/dist/providers/togetherai/index.d.ts +3 -3
  40. package/dist/providers/togetherai/index.js +255 -164
  41. package/dist/providers/togetherai/index.mjs +255 -164
  42. package/dist/providers/xai/index.d.mts +3 -3
  43. package/dist/providers/xai/index.d.ts +3 -3
  44. package/dist/providers/xai/index.js +255 -164
  45. package/dist/providers/xai/index.mjs +255 -164
  46. package/dist/{types-BkQCSiIt.d.mts → types-BW3csYo5.d.mts} +22 -1
  47. package/dist/{types-BkQCSiIt.d.ts → types-BW3csYo5.d.ts} +22 -1
  48. package/dist/{types-B6dhnguR.d.mts → types-BWRYIvl_.d.mts} +11 -4
  49. package/dist/{types-CCxPmkmK.d.ts → types-CpXcT-tY.d.ts} +11 -4
  50. package/dist/{types-BQ31QIsA.d.ts → types-DA54bSmX.d.ts} +3 -11
  51. package/dist/{types-BSSiJW2o.d.mts → types-NOswlhm9.d.mts} +3 -11
  52. package/dist/yourgpt/index.d.mts +1 -1
  53. package/dist/yourgpt/index.d.ts +1 -1
  54. package/package.json +115 -48
  55. package/LICENSE +0 -21
@@ -1,3 +1,54 @@
1
+ // src/core/openai-parameters.ts
2
+ function capabilities(model) {
3
+ const gpt = /^gpt-(\d+)(?:\.(\d+))?(?:-(.+))?$/i.exec(model);
4
+ const major = Number(gpt?.[1] ?? 0);
5
+ const minor = Number(gpt?.[2] ?? 0);
6
+ const chat = gpt?.[3]?.startsWith("chat") ?? false;
7
+ const reasoning = /^o\d+(?:-|$)/i.test(model) || major >= 5 && !chat;
8
+ const supportsNone = major === 5 && minor >= 1 && !chat || /^gpt-6-(?:sol|luna)(?:-\d{4}-\d{2}-\d{2})?$/i.test(model);
9
+ return { major, minor, reasoning, supportsNone };
10
+ }
11
+ function requiresOpenAIResponses(model, baseUrl, options = {}) {
12
+ if (options.parameterPolicy === "passthrough") return false;
13
+ const c = capabilities(model);
14
+ if (!c.reasoning || options.reasoningEffort === "none") return false;
15
+ if (!(c.major >= 6 || c.major === 5 && c.minor >= 4)) return false;
16
+ if (!baseUrl) return true;
17
+ try {
18
+ return new URL(baseUrl).hostname === "api.openai.com";
19
+ } catch {
20
+ return false;
21
+ }
22
+ }
23
+ function buildOpenAIParameters(model, maxTokens, temperature, options = {}, api = "chat") {
24
+ const c = capabilities(model ?? "");
25
+ const normalize = options.parameterPolicy !== "passthrough";
26
+ const effort = options.reasoningEffort;
27
+ if (normalize && c.reasoning && effort === "none" && !c.supportsNone) {
28
+ throw new Error(`${model} does not support reasoningEffort: none`);
29
+ }
30
+ if (normalize && c.major >= 6 && effort === "minimal") {
31
+ throw new Error(`${model} does not support reasoningEffort: minimal`);
32
+ }
33
+ const result = {
34
+ [api === "responses" ? "max_output_tokens" : normalize && c.reasoning ? "max_completion_tokens" : "max_tokens"]: maxTokens
35
+ };
36
+ if (effort !== void 0) {
37
+ if (api === "responses") result.reasoning = { effort };
38
+ else result.reasoning_effort = effort;
39
+ }
40
+ if (temperature !== void 0) {
41
+ if (!normalize || !c.reasoning || effort === "none" && c.supportsNone) {
42
+ result.temperature = temperature;
43
+ } else {
44
+ (options.onWarning ?? console.warn)(
45
+ `[llm-sdk] ${model}: omitted temperature because reasoning is enabled.`
46
+ );
47
+ }
48
+ }
49
+ return result;
50
+ }
51
+
1
52
  // src/adapters/base.ts
2
53
  function stringifyForDebug(value) {
3
54
  return JSON.stringify(
@@ -104,16 +155,6 @@ function normalizeObjectJsonSchema(schema) {
104
155
  }
105
156
  return normalized;
106
157
  }
107
- function isOpenAIReasoningModel(modelId) {
108
- if (!modelId) return false;
109
- return /^(o1|o3|o4|gpt-5)/i.test(modelId);
110
- }
111
- function buildOpenAITokenParams(modelId, maxTokens, temperature) {
112
- if (isOpenAIReasoningModel(modelId)) {
113
- return { max_completion_tokens: maxTokens };
114
- }
115
- return { max_tokens: maxTokens, temperature };
116
- }
117
158
  function toOpenAIResponseFormat(rf) {
118
159
  if (!rf) return void 0;
119
160
  if (rf.type === "json_object") return { type: "json_object" };
@@ -493,6 +534,28 @@ async function searchOpenRouterModels(query, apiKey) {
493
534
  );
494
535
  }
495
536
 
537
+ // src/core/provider-error.ts
538
+ function providerErrorEvent(error, code) {
539
+ const details = error ?? {};
540
+ const event = {
541
+ type: "error",
542
+ message: error instanceof Error ? error.message : String(error),
543
+ code,
544
+ ...typeof details.status === "number" ? { status: details.status } : {},
545
+ ...typeof details.code === "string" ? { providerCode: details.code } : {},
546
+ ...typeof details.param === "string" ? { param: details.param } : {},
547
+ ...typeof details.request_id === "string" ? { requestId: details.request_id } : {}
548
+ };
549
+ Object.defineProperty(event, "cause", { value: error, enumerable: false });
550
+ return event;
551
+ }
552
+ function throwIfAborted(signal) {
553
+ if (!signal?.aborted) return;
554
+ const error = new Error("The operation was aborted");
555
+ error.name = "AbortError";
556
+ throw error;
557
+ }
558
+
496
559
  // src/core/utils.ts
497
560
  function generateId(prefix = "id") {
498
561
  return `${prefix}_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
@@ -524,39 +587,38 @@ var OpenAIAdapter = class _OpenAIAdapter {
524
587
  const { default: OpenAI } = await import('openai');
525
588
  this.client = new OpenAI({
526
589
  apiKey: this.config.apiKey,
527
- baseURL: this.config.baseUrl
590
+ baseURL: this.config.baseUrl,
591
+ organization: this.config.organization,
592
+ defaultHeaders: this.config.headers
528
593
  });
529
594
  }
530
595
  return this.client;
531
596
  }
597
+ parameterOptions(request) {
598
+ return {
599
+ ...this.config,
600
+ reasoningEffort: request.config?.reasoningEffort ?? this.config.reasoningEffort
601
+ };
602
+ }
603
+ toolDefinitions(request) {
604
+ if (request.toolDefinitions?.length) return request.toolDefinitions;
605
+ return formatTools(request.actions ?? []).map((tool) => ({
606
+ name: tool.function.name,
607
+ description: tool.function.description ?? "",
608
+ location: "server",
609
+ inputSchema: tool.function.parameters
610
+ }));
611
+ }
532
612
  shouldUseResponsesApi(request) {
533
- const hasTools = Array.isArray(request.toolDefinitions) && request.toolDefinitions.length > 0;
534
- if (!hasTools) return false;
535
- if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false) {
613
+ if (this.toolDefinitions(request).length === 0) return false;
614
+ if (request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true && request.providerToolOptions.openai.nativeToolSearch.useResponsesApi !== false)
536
615
  return true;
537
- }
538
- return this.requiresResponsesApiForTools(
539
- request.config?.model || this.model
616
+ return requiresOpenAIResponses(
617
+ request.config?.model || this.model,
618
+ this.config.baseUrl,
619
+ this.parameterOptions(request)
540
620
  );
541
621
  }
542
- /**
543
- * Whether this model rejects function tools on /v1/chat/completions.
544
- *
545
- * Applies to OpenAI proper only — the adapter is reused for OpenAI-compatible
546
- * providers (Azure, xAI, Google, Fireworks) whose endpoints have no such
547
- * restriction and may not implement /v1/responses at all.
548
- */
549
- requiresResponsesApiForTools(modelId) {
550
- if (!modelId) return false;
551
- if (!/^gpt-5\.(?:[4-9]|\d{2,})/i.test(modelId)) return false;
552
- const baseUrl = this.config.baseUrl;
553
- if (!baseUrl) return true;
554
- try {
555
- return new URL(baseUrl).hostname === "api.openai.com";
556
- } catch {
557
- return false;
558
- }
559
- }
560
622
  /**
561
623
  * Convert one message's content to Responses content parts.
562
624
  *
@@ -587,7 +649,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
587
649
  });
588
650
  }
589
651
  buildResponsesInput(request) {
590
- const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? request.rawMessages : formatMessagesForOpenAI(request.messages, void 0);
652
+ const sourceMessages = request.rawMessages && request.rawMessages.length > 0 ? this.formatRawMessages(request.rawMessages) : formatMessagesForOpenAI(request.messages, void 0);
591
653
  const input = [];
592
654
  for (const message of sourceMessages) {
593
655
  if (message.role === "system") {
@@ -637,6 +699,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
637
699
  }
638
700
  return input;
639
701
  }
702
+ /** Preserve Copilot screenshot attachments on every OpenAI transport. */
703
+ formatRawMessages(messages) {
704
+ return messages.map((message) => {
705
+ const { attachments, ...rest } = message;
706
+ let content = message.content;
707
+ if (message.role === "assistant" && Array.isArray(message.tool_calls) && message.tool_calls.length > 0 && content === "") {
708
+ content = null;
709
+ }
710
+ if (Array.isArray(attachments) && attachments.length > 0) {
711
+ const images = attachments.filter((attachment) => attachment && typeof attachment === "object").map(
712
+ (attachment) => attachmentToOpenAIImage(attachment)
713
+ ).filter((image) => image !== null);
714
+ if (images.length > 0) {
715
+ const parts = Array.isArray(content) ? content : content ? [{ type: "text", text: content }] : [];
716
+ content = [...parts, ...images];
717
+ }
718
+ }
719
+ return { ...rest, content };
720
+ });
721
+ }
640
722
  /**
641
723
  * Build the web_search tool for the Responses API, or undefined when web
642
724
  * search is off.
@@ -718,13 +800,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
718
800
  const toolCalls = Array.isArray(response?.output) ? response.output.filter((item) => item?.type === "function_call").map((item) => ({
719
801
  id: item.call_id ?? item.id ?? generateToolCallId(),
720
802
  name: item.name,
721
- args: (() => {
722
- try {
723
- return JSON.parse(item.arguments ?? "{}");
724
- } catch {
725
- return {};
726
- }
727
- })()
803
+ args: JSON.parse(item.arguments ?? "{}")
728
804
  })) : [];
729
805
  return {
730
806
  content,
@@ -748,18 +824,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
748
824
  instructions: request.systemPrompt,
749
825
  input: this.buildResponsesInput(request),
750
826
  tools: this.buildResponsesTools(
751
- request.toolDefinitions ?? [],
827
+ this.toolDefinitions(request),
752
828
  request.providerToolOptions?.openai?.nativeToolSearch?.enabled === true,
753
829
  this.buildResponsesWebSearchTool(request)
754
830
  ),
755
- tool_choice: openaiToolOptions?.toolChoice === "required" ? "required" : openaiToolOptions?.toolChoice === "auto" ? "auto" : void 0,
831
+ tool_choice: openaiToolOptions?.toolChoice,
756
832
  parallel_tool_calls: openaiToolOptions?.parallelToolCalls,
757
- // Reasoning models reject `temperature` outright — sending it would swap one
758
- // 400 for another. isOpenAIReasoningModel already encodes that family test.
759
- ...isOpenAIReasoningModel(modelIdForPayload) ? {} : {
760
- temperature: request.config?.temperature ?? this.config.temperature
761
- },
762
- max_output_tokens: request.config?.maxTokens ?? this.config.maxTokens,
833
+ ...buildOpenAIParameters(
834
+ modelIdForPayload,
835
+ request.config?.maxTokens ?? this.config.maxTokens,
836
+ request.config?.temperature ?? this.config.temperature,
837
+ this.parameterOptions(request),
838
+ "responses"
839
+ ),
763
840
  ...responsesTextFormat ? { text: { format: responsesTextFormat } } : {},
764
841
  stream
765
842
  };
@@ -767,10 +844,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
767
844
  }
768
845
  async completeWithResponses(request) {
769
846
  const client = await this.getClient();
847
+ throwIfAborted(request.signal);
770
848
  const payload = this.buildResponsesPayload(request, false);
771
849
  logProviderPayload("openai", "request payload", payload, request.debug);
772
- const response = await client.responses.create(payload);
850
+ if (!client.responses?.create)
851
+ throw new Error(
852
+ "This OpenAI client does not support Responses; install an openai version with Responses support."
853
+ );
854
+ const response = await client.responses.create(payload, {
855
+ signal: request.signal
856
+ });
857
+ throwIfAborted(request.signal);
773
858
  logProviderPayload("openai", "response payload", response, request.debug);
859
+ if (response.status && response.status !== "completed") {
860
+ throw Object.assign(
861
+ new Error(
862
+ response.error?.message ?? `Responses request ${response.status}`
863
+ ),
864
+ response.error
865
+ );
866
+ }
774
867
  return this.parseResponsesResult(response);
775
868
  }
776
869
  /**
@@ -788,13 +881,26 @@ var OpenAIAdapter = class _OpenAIAdapter {
788
881
  */
789
882
  async *streamWithResponses(request) {
790
883
  const client = await this.getClient();
884
+ throwIfAborted(request.signal);
791
885
  const payload = this.buildResponsesPayload(request, true);
792
886
  logProviderPayload("openai", "request payload", payload, request.debug);
793
- const stream = await client.responses.create(payload);
887
+ if (!client.responses?.create)
888
+ throw new Error(
889
+ "This OpenAI client does not support Responses; install an openai version with Responses support."
890
+ );
891
+ const stream = await client.responses.create(payload, {
892
+ signal: request.signal
893
+ });
794
894
  const toolCalls = /* @__PURE__ */ new Map();
795
895
  let usage;
796
896
  const citations = [];
897
+ let completed = false;
797
898
  function* flushToolCalls() {
899
+ for (const call of toolCalls.values()) {
900
+ if (!call.name)
901
+ throw new Error("Responses tool call is missing its name");
902
+ JSON.parse(call.arguments || "{}");
903
+ }
798
904
  for (const call of toolCalls.values()) {
799
905
  yield { type: "action:start", id: call.id, name: call.name };
800
906
  yield { type: "action:args", id: call.id, args: call.arguments };
@@ -803,7 +909,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
803
909
  toolCalls.clear();
804
910
  }
805
911
  for await (const event of stream) {
806
- if (request.signal?.aborted) break;
912
+ throwIfAborted(request.signal);
807
913
  logProviderPayload("openai", "stream chunk", event, request.debug);
808
914
  const index = event?.output_index ?? 0;
809
915
  switch (event?.type) {
@@ -833,8 +939,8 @@ var OpenAIAdapter = class _OpenAIAdapter {
833
939
  }
834
940
  break;
835
941
  }
836
- case "response.completed":
837
- case "response.incomplete": {
942
+ case "response.completed": {
943
+ completed = true;
838
944
  const found = this.collectResponsesCitations(
839
945
  event.response?.output,
840
946
  citations.length
@@ -850,13 +956,27 @@ var OpenAIAdapter = class _OpenAIAdapter {
850
956
  }
851
957
  break;
852
958
  }
853
- case "error":
854
- case "response.failed":
959
+ case "response.incomplete":
855
960
  throw new Error(
856
- event.message ?? event.response?.error?.message ?? "Responses stream failed"
961
+ `Responses stream incomplete: ${event.response?.incomplete_details?.reason ?? "unknown reason"}`
857
962
  );
963
+ case "error":
964
+ case "response.failed": {
965
+ const details = event.response?.error ?? event;
966
+ throw Object.assign(
967
+ new Error(details.message ?? "Responses stream failed"),
968
+ {
969
+ code: details.code,
970
+ param: details.param,
971
+ status: details.status
972
+ }
973
+ );
974
+ }
858
975
  }
859
976
  }
977
+ throwIfAborted(request.signal);
978
+ if (!completed)
979
+ throw new Error("Responses stream ended without a completed response");
860
980
  yield* flushToolCalls();
861
981
  if (citations.length > 0) {
862
982
  yield { type: "citation", citations: deduplicateCitations(citations) };
@@ -865,6 +985,7 @@ var OpenAIAdapter = class _OpenAIAdapter {
865
985
  yield { type: "done", usage };
866
986
  }
867
987
  async *stream(request) {
988
+ throwIfAborted(request.signal);
868
989
  if (this.shouldUseResponsesApi(request)) {
869
990
  const messageId2 = generateMessageId();
870
991
  yield { type: "message:start", id: messageId2 };
@@ -872,47 +993,14 @@ var OpenAIAdapter = class _OpenAIAdapter {
872
993
  yield* this.streamWithResponses(request);
873
994
  return;
874
995
  } catch (error) {
875
- yield {
876
- type: "error",
877
- message: error instanceof Error ? error.message : "Unknown error",
878
- code: "OPENAI_RESPONSES_ERROR"
879
- };
996
+ yield providerErrorEvent(error, "OPENAI_RESPONSES_ERROR");
880
997
  return;
881
998
  }
882
999
  }
883
1000
  const client = await this.getClient();
884
1001
  let messages;
885
1002
  if (request.rawMessages && request.rawMessages.length > 0) {
886
- const processedMessages = request.rawMessages.map((msg) => {
887
- if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
888
- return { ...msg, content: null };
889
- }
890
- const hasAttachments = msg.attachments && Array.isArray(msg.attachments) && msg.attachments.length > 0;
891
- if (hasAttachments) {
892
- const content = [];
893
- if (msg.content) {
894
- content.push({ type: "text", text: msg.content });
895
- }
896
- for (const attachment of msg.attachments) {
897
- if (attachment.type === "image") {
898
- let imageUrl;
899
- if (attachment.url) {
900
- imageUrl = attachment.url;
901
- } else if (attachment.data) {
902
- imageUrl = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType || "image/png"};base64,${attachment.data}`;
903
- } else {
904
- continue;
905
- }
906
- content.push({
907
- type: "image_url",
908
- image_url: { url: imageUrl, detail: "auto" }
909
- });
910
- }
911
- }
912
- return { ...msg, content, attachments: void 0 };
913
- }
914
- return msg;
915
- });
1003
+ const processedMessages = this.formatRawMessages(request.rawMessages);
916
1004
  if (request.systemPrompt) {
917
1005
  const hasSystem = processedMessages.some((m) => m.role === "system");
918
1006
  if (!hasSystem) {
@@ -932,7 +1020,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
932
1020
  request.systemPrompt
933
1021
  );
934
1022
  }
935
- const tools = request.actions?.length ? formatTools(request.actions) : [];
1023
+ const tools = request.toolDefinitions?.length ? request.toolDefinitions.filter((tool) => tool.available !== false).map((tool) => ({
1024
+ type: "function",
1025
+ function: {
1026
+ name: tool.name,
1027
+ description: tool.description,
1028
+ parameters: normalizeObjectJsonSchema(
1029
+ tool.inputSchema
1030
+ )
1031
+ }
1032
+ })) : formatTools(request.actions ?? []);
936
1033
  const webSearchConfig = request.webSearch ?? this.config.webSearch;
937
1034
  if (webSearchConfig) {
938
1035
  const webSearchTool = {
@@ -961,26 +1058,28 @@ var OpenAIAdapter = class _OpenAIAdapter {
961
1058
  tools: tools.length > 0 ? tools : void 0,
962
1059
  tool_choice: tools.length > 0 ? toolChoice : void 0,
963
1060
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
964
- ...buildOpenAITokenParams(
1061
+ ...buildOpenAIParameters(
965
1062
  modelIdForPayload,
966
1063
  request.config?.maxTokens ?? this.config.maxTokens,
967
- request.config?.temperature ?? this.config.temperature
1064
+ request.config?.temperature ?? this.config.temperature,
1065
+ this.parameterOptions(request)
968
1066
  ),
969
1067
  response_format: toOpenAIResponseFormat(request.config?.responseFormat),
970
1068
  stream: true,
971
1069
  stream_options: { include_usage: true }
972
1070
  };
973
1071
  logProviderPayload("openai", "request payload", payload, request.debug);
974
- const stream = await client.chat.completions.create(payload);
975
- let currentToolCall = null;
1072
+ const stream = await client.chat.completions.create(payload, {
1073
+ signal: request.signal
1074
+ });
1075
+ const toolCalls = /* @__PURE__ */ new Map();
1076
+ let finishReason;
976
1077
  const collectedCitations = [];
977
1078
  let citationIndex = 0;
978
1079
  let usage;
979
1080
  for await (const chunk of stream) {
980
1081
  logProviderPayload("openai", "stream chunk", chunk, request.debug);
981
- if (request.signal?.aborted) {
982
- break;
983
- }
1082
+ throwIfAborted(request.signal);
984
1083
  const delta = chunk.choices[0]?.delta;
985
1084
  const choice = chunk.choices[0];
986
1085
  if (delta?.content) {
@@ -1003,38 +1102,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
1003
1102
  }
1004
1103
  }
1005
1104
  }
1006
- if (delta?.tool_calls) {
1007
- for (const toolCall of delta.tool_calls) {
1008
- if (toolCall.id) {
1009
- if (currentToolCall) {
1010
- yield {
1011
- type: "action:args",
1012
- id: currentToolCall.id,
1013
- args: currentToolCall.arguments
1014
- };
1015
- yield {
1016
- type: "action:end",
1017
- id: currentToolCall.id,
1018
- name: currentToolCall.name
1019
- };
1020
- }
1021
- const tcExtraContent = toolCall.extra_content;
1022
- currentToolCall = {
1023
- id: toolCall.id,
1024
- name: toolCall.function?.name || "",
1025
- arguments: toolCall.function?.arguments || "",
1026
- ...tcExtraContent ? { extra_content: tcExtraContent } : {}
1027
- };
1028
- yield {
1029
- type: "action:start",
1030
- id: currentToolCall.id,
1031
- name: currentToolCall.name,
1032
- ...currentToolCall.extra_content ? { extra_content: currentToolCall.extra_content } : {}
1033
- };
1034
- } else if (currentToolCall && toolCall.function?.arguments) {
1035
- currentToolCall.arguments += toolCall.function.arguments;
1036
- }
1037
- }
1105
+ for (const part of delta?.tool_calls ?? []) {
1106
+ const index = part.index ?? 0;
1107
+ const call = toolCalls.get(index) ?? {
1108
+ id: "",
1109
+ name: "",
1110
+ arguments: ""
1111
+ };
1112
+ if (part.id) call.id = part.id;
1113
+ if (part.function?.name) call.name += part.function.name;
1114
+ if (part.function?.arguments)
1115
+ call.arguments += part.function.arguments;
1116
+ if (part.extra_content) call.extra_content = part.extra_content;
1117
+ toolCalls.set(index, call);
1038
1118
  }
1039
1119
  if (chunk.usage) {
1040
1120
  usage = {
@@ -1043,21 +1123,28 @@ var OpenAIAdapter = class _OpenAIAdapter {
1043
1123
  total_tokens: chunk.usage.total_tokens
1044
1124
  };
1045
1125
  }
1046
- if (choice?.finish_reason) {
1047
- if (currentToolCall) {
1048
- yield {
1049
- type: "action:args",
1050
- id: currentToolCall.id,
1051
- args: currentToolCall.arguments
1052
- };
1053
- yield {
1054
- type: "action:end",
1055
- id: currentToolCall.id,
1056
- name: currentToolCall.name
1057
- };
1058
- currentToolCall = null;
1059
- }
1060
- }
1126
+ if (choice?.finish_reason) finishReason = choice.finish_reason;
1127
+ }
1128
+ throwIfAborted(request.signal);
1129
+ if (!finishReason)
1130
+ throw new Error("OpenAI stream ended without a finish reason");
1131
+ if (toolCalls.size && !["tool_calls", "function_call"].includes(finishReason)) {
1132
+ throw new Error("OpenAI stream ended with incomplete tool calls");
1133
+ }
1134
+ for (const call of toolCalls.values()) {
1135
+ if (!call.id || !call.name)
1136
+ throw new Error("OpenAI stream contains an incomplete tool call");
1137
+ JSON.parse(call.arguments || "{}");
1138
+ }
1139
+ for (const call of toolCalls.values()) {
1140
+ yield {
1141
+ type: "action:start",
1142
+ id: call.id,
1143
+ name: call.name,
1144
+ ...call.extra_content ? { extra_content: call.extra_content } : {}
1145
+ };
1146
+ yield { type: "action:args", id: call.id, args: call.arguments };
1147
+ yield { type: "action:end", id: call.id, name: call.name };
1061
1148
  }
1062
1149
  if (collectedCitations.length > 0) {
1063
1150
  const uniqueCitations = deduplicateCitations(collectedCitations);
@@ -1066,26 +1153,18 @@ var OpenAIAdapter = class _OpenAIAdapter {
1066
1153
  yield { type: "message:end" };
1067
1154
  yield { type: "done", usage };
1068
1155
  } catch (error) {
1069
- yield {
1070
- type: "error",
1071
- message: error instanceof Error ? error.message : "Unknown error",
1072
- code: `${this.provider.toUpperCase()}_ERROR`
1073
- };
1156
+ yield providerErrorEvent(error, `${this.provider.toUpperCase()}_ERROR`);
1074
1157
  }
1075
1158
  }
1076
1159
  async complete(request) {
1160
+ throwIfAborted(request.signal);
1077
1161
  if (this.shouldUseResponsesApi(request)) {
1078
1162
  return this.completeWithResponses(request);
1079
1163
  }
1080
1164
  const client = await this.getClient();
1081
1165
  let messages;
1082
1166
  if (request.rawMessages && request.rawMessages.length > 0) {
1083
- const sanitized = request.rawMessages.map((msg) => {
1084
- if (msg.role === "assistant" && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0 && msg.content === "") {
1085
- return { ...msg, content: null };
1086
- }
1087
- return msg;
1088
- });
1167
+ const sanitized = this.formatRawMessages(request.rawMessages);
1089
1168
  if (request.systemPrompt && !sanitized.some((message2) => message2.role === "system")) {
1090
1169
  messages = [
1091
1170
  { role: "system", content: request.systemPrompt },
@@ -1100,7 +1179,16 @@ var OpenAIAdapter = class _OpenAIAdapter {
1100
1179
  request.systemPrompt
1101
1180
  );
1102
1181
  }
1103
- const tools = request.actions?.length ? formatTools(request.actions) : [];
1182
+ const tools = request.toolDefinitions?.length ? request.toolDefinitions.filter((tool) => tool.available !== false).map((tool) => ({
1183
+ type: "function",
1184
+ function: {
1185
+ name: tool.name,
1186
+ description: tool.description,
1187
+ parameters: normalizeObjectJsonSchema(
1188
+ tool.inputSchema
1189
+ )
1190
+ }
1191
+ })) : formatTools(request.actions ?? []);
1104
1192
  const openaiToolOptions = request.providerToolOptions?.openai;
1105
1193
  const toolChoice = openaiToolOptions?.toolChoice && typeof openaiToolOptions.toolChoice === "object" ? {
1106
1194
  type: "function",
@@ -1115,16 +1203,19 @@ var OpenAIAdapter = class _OpenAIAdapter {
1115
1203
  tools: tools.length > 0 ? tools : void 0,
1116
1204
  tool_choice: tools.length > 0 ? toolChoice : void 0,
1117
1205
  parallel_tool_calls: tools.length > 0 ? openaiToolOptions?.parallelToolCalls : void 0,
1118
- ...buildOpenAITokenParams(
1206
+ ...buildOpenAIParameters(
1119
1207
  modelIdForCompletePayload,
1120
1208
  request.config?.maxTokens ?? this.config.maxTokens,
1121
- request.config?.temperature ?? this.config.temperature
1209
+ request.config?.temperature ?? this.config.temperature,
1210
+ this.parameterOptions(request)
1122
1211
  ),
1123
1212
  response_format: toOpenAIResponseFormat(request.config?.responseFormat),
1124
1213
  stream: false
1125
1214
  };
1126
1215
  logProviderPayload("openai", "request payload", payload, request.debug);
1127
- const response = await client.chat.completions.create(payload);
1216
+ const response = await client.chat.completions.create(payload, {
1217
+ signal: request.signal
1218
+ });
1128
1219
  logProviderPayload("openai", "response payload", response, request.debug);
1129
1220
  const choice = response.choices?.[0];
1130
1221
  const message = choice?.message;
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-BkQCSiIt.mjs';
2
- import { A as AIProvider } from '../../types-BSSiJW2o.mjs';
1
+ import { L as LanguageModel } from '../../types-BW3csYo5.mjs';
2
+ import { A as AIProvider } from '../../types-NOswlhm9.mjs';
3
3
  import 'zod';
4
- import '../../base-tNgbBaSo.mjs';
4
+ import '../../base-CkeT7u-O.mjs';
5
5
 
6
6
  /**
7
7
  * Together AI Provider
@@ -1,7 +1,7 @@
1
- import { L as LanguageModel } from '../../types-BkQCSiIt.js';
2
- import { A as AIProvider } from '../../types-BQ31QIsA.js';
1
+ import { L as LanguageModel } from '../../types-BW3csYo5.js';
2
+ import { A as AIProvider } from '../../types-DA54bSmX.js';
3
3
  import 'zod';
4
- import '../../base-C58Dsr9p.js';
4
+ import '../../base-BdTpUAWI.js';
5
5
 
6
6
  /**
7
7
  * Together AI Provider