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