@absolutejs/ai 0.0.49 → 0.0.51
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 +127 -0
- package/dist/ai/client/index.js +30 -1
- package/dist/ai/client/index.js.map +5 -5
- package/dist/ai/index.js +1174 -92
- package/dist/ai/index.js.map +18 -16
- package/dist/ai/providers/anthropic.js +105 -26
- package/dist/ai/providers/anthropic.js.map +5 -5
- package/dist/ai/providers/gemini.js +37 -4
- package/dist/ai/providers/gemini.js.map +5 -5
- package/dist/ai/providers/ollama.js +7 -3
- package/dist/ai/providers/ollama.js.map +4 -4
- package/dist/ai/providers/openai.js +177 -36
- package/dist/ai/providers/openai.js.map +5 -5
- package/dist/ai/providers/openaiCompatible.js +177 -36
- package/dist/ai/providers/openaiCompatible.js.map +5 -5
- package/dist/ai/providers/openaiResponses.js +147 -33
- package/dist/ai/providers/openaiResponses.js.map +5 -5
- package/dist/ai/providers/openrouter.js +2607 -0
- package/dist/ai/providers/openrouter.js.map +18 -0
- package/dist/angular/ai/index.js +30 -1
- package/dist/angular/ai/index.js.map +5 -5
- package/dist/react/ai/index.js +30 -1
- package/dist/react/ai/index.js.map +5 -5
- package/dist/src/ai/client/actions.d.ts +53 -0
- package/dist/src/ai/errors/providerError.d.ts +3 -0
- package/dist/src/ai/generateAI.d.ts +4 -1
- package/dist/src/ai/index.d.ts +2 -0
- package/dist/src/ai/providers/openai.d.ts +7 -3
- package/dist/src/ai/providers/openaiResponses.d.ts +9 -4
- package/dist/src/ai/providers/openrouter.d.ts +157 -0
- package/dist/src/ai/providers/openrouterClient.d.ts +276 -0
- package/dist/src/ai/streamAIWithTools.d.ts +6 -0
- package/dist/svelte/ai/index.js +30 -1
- package/dist/svelte/ai/index.js.map +5 -5
- package/dist/types/ai.d.ts +116 -8
- package/dist/types/anthropic.d.ts +13 -5
- package/dist/vue/ai/index.js +30 -1
- package/dist/vue/ai/index.js.map +5 -5
- package/package.json +9 -2
|
@@ -6,7 +6,8 @@ var PROVIDER_STATUS_PAGES = {
|
|
|
6
6
|
anthropic: "https://status.claude.com",
|
|
7
7
|
gemini: "https://status.cloud.google.com",
|
|
8
8
|
google: "https://status.cloud.google.com",
|
|
9
|
-
openai: "https://status.openai.com"
|
|
9
|
+
openai: "https://status.openai.com",
|
|
10
|
+
openrouter: "https://status.openrouter.ai"
|
|
10
11
|
};
|
|
11
12
|
var RETRYABLE_STATUSES = new Set([
|
|
12
13
|
408,
|
|
@@ -42,6 +43,7 @@ class ProviderError extends Error {
|
|
|
42
43
|
status;
|
|
43
44
|
type;
|
|
44
45
|
retryable;
|
|
46
|
+
metadata;
|
|
45
47
|
statusPageUrl;
|
|
46
48
|
constructor(init) {
|
|
47
49
|
super(init.message, init.cause === undefined ? undefined : { cause: init.cause });
|
|
@@ -50,6 +52,7 @@ class ProviderError extends Error {
|
|
|
50
52
|
this.status = init.status ?? null;
|
|
51
53
|
this.type = init.type ?? null;
|
|
52
54
|
this.retryable = init.retryable;
|
|
55
|
+
this.metadata = init.metadata;
|
|
53
56
|
this.statusPageUrl = providerStatusPage(init.provider);
|
|
54
57
|
}
|
|
55
58
|
static fromResponse(provider, status, body, type) {
|
|
@@ -222,7 +225,8 @@ var withResilience = (provider, providerName = "unknown") => {
|
|
|
222
225
|
yield* attempt(params, attemptNo + 1);
|
|
223
226
|
return;
|
|
224
227
|
}
|
|
225
|
-
|
|
228
|
+
if (providerError.retryable)
|
|
229
|
+
noteFailure(providerName, providerError);
|
|
226
230
|
throw providerError;
|
|
227
231
|
}
|
|
228
232
|
};
|
|
@@ -456,7 +460,7 @@ var mapContentBlockToOpenAI = (block) => {
|
|
|
456
460
|
if (block.type === "image") {
|
|
457
461
|
return {
|
|
458
462
|
image_url: {
|
|
459
|
-
url: `data:${block.source.media_type};base64,${block.source.data}`
|
|
463
|
+
url: block.source.type === "url" ? block.source.url : `data:${block.source.media_type};base64,${block.source.data}`
|
|
460
464
|
},
|
|
461
465
|
type: "image_url"
|
|
462
466
|
};
|
|
@@ -464,12 +468,26 @@ var mapContentBlockToOpenAI = (block) => {
|
|
|
464
468
|
if (block.type === "document") {
|
|
465
469
|
return {
|
|
466
470
|
file: {
|
|
467
|
-
file_data: `data:${block.source.media_type};base64,${block.source.data}`,
|
|
471
|
+
file_data: block.source.type === "url" ? block.source.url : `data:${block.source.media_type};base64,${block.source.data}`,
|
|
468
472
|
filename: block.name ?? "document.pdf"
|
|
469
473
|
},
|
|
470
474
|
type: "file"
|
|
471
475
|
};
|
|
472
476
|
}
|
|
477
|
+
if (block.type === "audio") {
|
|
478
|
+
return {
|
|
479
|
+
input_audio: { data: block.source.data, format: block.source.format },
|
|
480
|
+
type: "input_audio"
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
if (block.type === "video") {
|
|
484
|
+
return {
|
|
485
|
+
type: "video_url",
|
|
486
|
+
video_url: {
|
|
487
|
+
url: block.source.type === "url" ? block.source.url : `data:${block.source.media_type};base64,${block.source.data}`
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
}
|
|
473
491
|
if (block.type === "text") {
|
|
474
492
|
return { text: block.content, type: "text" };
|
|
475
493
|
}
|
|
@@ -479,17 +497,20 @@ var mapOpenAIContent = (msg) => {
|
|
|
479
497
|
if (typeof msg.content === "string") {
|
|
480
498
|
return msg.content;
|
|
481
499
|
}
|
|
482
|
-
const hasMedia = msg.content.some((block) => block.type === "image" || block.type === "document");
|
|
500
|
+
const hasMedia = msg.content.some((block) => block.type === "image" || block.type === "document" || block.type === "audio" || block.type === "video");
|
|
483
501
|
if (!hasMedia) {
|
|
484
502
|
return null;
|
|
485
503
|
}
|
|
486
504
|
return msg.content.map(mapContentBlockToOpenAI).filter((mapped) => mapped !== null);
|
|
487
505
|
};
|
|
488
|
-
var buildRequestBody = (params) => {
|
|
506
|
+
var buildRequestBody = (params, capabilityModel = params.model) => {
|
|
489
507
|
const messages = convertToolResultMessages(params.messages.map((msg) => ({
|
|
490
508
|
content: mapOpenAIContent(msg),
|
|
491
509
|
role: msg.role
|
|
492
510
|
})), params);
|
|
511
|
+
if (params.systemPrompt) {
|
|
512
|
+
messages.unshift({ content: params.systemPrompt, role: "system" });
|
|
513
|
+
}
|
|
493
514
|
const body = {
|
|
494
515
|
messages,
|
|
495
516
|
model: params.model,
|
|
@@ -510,12 +531,12 @@ var buildRequestBody = (params) => {
|
|
|
510
531
|
body.parallel_tool_calls = params.parallelToolCalls;
|
|
511
532
|
}
|
|
512
533
|
}
|
|
513
|
-
if (isOpenAIReasoningModel(
|
|
534
|
+
if (isOpenAIReasoningModel(capabilityModel)) {
|
|
514
535
|
if (typeof params.maxTokens === "number") {
|
|
515
536
|
body.max_completion_tokens = params.maxTokens;
|
|
516
537
|
}
|
|
517
538
|
if (params.reasoning) {
|
|
518
|
-
const effort = openaiEffortValue(
|
|
539
|
+
const effort = openaiEffortValue(capabilityModel, params.reasoning);
|
|
519
540
|
if (effort)
|
|
520
541
|
body.reasoning_effort = effort;
|
|
521
542
|
}
|
|
@@ -576,8 +597,12 @@ var extractUsage = (parsedUsage) => {
|
|
|
576
597
|
const cached = parsedUsage.cached_tokens ?? 0;
|
|
577
598
|
return {
|
|
578
599
|
cacheReadInputTokens: cached,
|
|
600
|
+
cacheWriteInputTokens: parsedUsage.cache_write_tokens || undefined,
|
|
601
|
+
costCredits: parsedUsage.cost,
|
|
579
602
|
inputTokens: Math.max(0, prompt - cached),
|
|
580
|
-
outputTokens: parsedUsage.completion_tokens ?? 0
|
|
603
|
+
outputTokens: parsedUsage.completion_tokens ?? 0,
|
|
604
|
+
reasoningTokens: parsedUsage.reasoning_tokens || undefined,
|
|
605
|
+
upstreamInferenceCostCredits: parsedUsage.upstream_inference_cost || undefined
|
|
581
606
|
};
|
|
582
607
|
};
|
|
583
608
|
var resolveToolCallIndex = (toolCall) => {
|
|
@@ -629,9 +654,50 @@ var processDelta = function* (delta, pendingToolCalls) {
|
|
|
629
654
|
if (typeof delta.content === "string") {
|
|
630
655
|
yield { content: delta.content, type: "text" };
|
|
631
656
|
}
|
|
657
|
+
if (isRecord(delta.audio)) {
|
|
658
|
+
const audio = delta.audio;
|
|
659
|
+
if (typeof audio.data === "string" || typeof audio.transcript === "string") {
|
|
660
|
+
yield {
|
|
661
|
+
audioId: typeof audio.id === "string" ? audio.id : undefined,
|
|
662
|
+
data: typeof audio.data === "string" ? audio.data : "",
|
|
663
|
+
format: typeof audio.format === "string" ? audio.format : "pcm16",
|
|
664
|
+
transcript: typeof audio.transcript === "string" ? audio.transcript : undefined,
|
|
665
|
+
type: "audio"
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
}
|
|
632
669
|
if (isRecordArray(delta.tool_calls)) {
|
|
633
670
|
processToolCallDeltas(delta.tool_calls, pendingToolCalls);
|
|
634
671
|
}
|
|
672
|
+
if (Array.isArray(delta.annotations)) {
|
|
673
|
+
for (const annotation of delta.annotations) {
|
|
674
|
+
if (!isRecord(annotation) || annotation.type !== "url_citation")
|
|
675
|
+
continue;
|
|
676
|
+
const citation = isRecord(annotation.url_citation) ? annotation.url_citation : annotation;
|
|
677
|
+
if (typeof citation.url !== "string")
|
|
678
|
+
continue;
|
|
679
|
+
yield {
|
|
680
|
+
content: typeof citation.content === "string" ? citation.content : undefined,
|
|
681
|
+
endIndex: typeof citation.end_index === "number" ? citation.end_index : undefined,
|
|
682
|
+
startIndex: typeof citation.start_index === "number" ? citation.start_index : undefined,
|
|
683
|
+
title: typeof citation.title === "string" ? citation.title : undefined,
|
|
684
|
+
type: "citation",
|
|
685
|
+
url: citation.url
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
var narrowResponseMetadata = (parsed) => {
|
|
691
|
+
const providerMetadata = isRecord(parsed.openrouter_metadata) ? parsed.openrouter_metadata : undefined;
|
|
692
|
+
const generationId = typeof parsed.id === "string" ? parsed.id : undefined;
|
|
693
|
+
const model = typeof parsed.model === "string" ? parsed.model : undefined;
|
|
694
|
+
const serviceTier = typeof parsed.service_tier === "string" ? parsed.service_tier : undefined;
|
|
695
|
+
const selected = providerMetadata && isRecord(providerMetadata.endpoints) ? providerMetadata.endpoints.available : undefined;
|
|
696
|
+
const selectedEndpoint = Array.isArray(selected) ? selected.find((entry) => isRecord(entry) && entry.selected === true) : undefined;
|
|
697
|
+
const provider = isRecord(selectedEndpoint) && typeof selectedEndpoint.provider === "string" ? selectedEndpoint.provider : undefined;
|
|
698
|
+
if (!providerMetadata && !generationId && !model && !serviceTier)
|
|
699
|
+
return;
|
|
700
|
+
return { generationId, model, provider, providerMetadata, serviceTier };
|
|
635
701
|
};
|
|
636
702
|
var processChoice = function* (choice, pendingToolCalls) {
|
|
637
703
|
const delta = isRecord(choice.delta) ? choice.delta : null;
|
|
@@ -650,13 +716,25 @@ var narrowUsageRecord = (parsed) => {
|
|
|
650
716
|
const promptTokens = typeof usage.prompt_tokens === "number" ? usage.prompt_tokens : 0;
|
|
651
717
|
const completionTokens = typeof usage.completion_tokens === "number" ? usage.completion_tokens : 0;
|
|
652
718
|
const cachedTokens = isRecord(usage.prompt_tokens_details) && typeof usage.prompt_tokens_details.cached_tokens === "number" ? usage.prompt_tokens_details.cached_tokens : 0;
|
|
653
|
-
|
|
719
|
+
const cacheWriteTokens = isRecord(usage.prompt_tokens_details) && typeof usage.prompt_tokens_details.cache_write_tokens === "number" ? usage.prompt_tokens_details.cache_write_tokens : 0;
|
|
720
|
+
const reasoningTokens = isRecord(usage.completion_tokens_details) && typeof usage.completion_tokens_details.reasoning_tokens === "number" ? usage.completion_tokens_details.reasoning_tokens : 0;
|
|
721
|
+
const cost = typeof usage.cost === "number" ? usage.cost : undefined;
|
|
722
|
+
const upstreamInferenceCost = isRecord(usage.cost_details) && typeof usage.cost_details.upstream_inference_cost === "number" ? usage.cost_details.upstream_inference_cost : undefined;
|
|
723
|
+
const normalized = extractUsage({
|
|
724
|
+
cache_write_tokens: cacheWriteTokens,
|
|
654
725
|
cached_tokens: cachedTokens,
|
|
655
726
|
completion_tokens: completionTokens,
|
|
656
|
-
|
|
727
|
+
cost,
|
|
728
|
+
prompt_tokens: promptTokens,
|
|
729
|
+
reasoning_tokens: reasoningTokens,
|
|
730
|
+
upstream_inference_cost: upstreamInferenceCost
|
|
657
731
|
});
|
|
732
|
+
if (isRecord(usage.server_tool_use)) {
|
|
733
|
+
normalized.serverToolUse = Object.fromEntries(Object.entries(usage.server_tool_use).filter((entry) => typeof entry[1] === "number"));
|
|
734
|
+
}
|
|
735
|
+
return normalized;
|
|
658
736
|
};
|
|
659
|
-
var processSSELine = function* (line, pendingToolCalls,
|
|
737
|
+
var processSSELine = function* (line, pendingToolCalls, providerName) {
|
|
660
738
|
const trimmed = line.trim();
|
|
661
739
|
if (!trimmed || !trimmed.startsWith("data: ")) {
|
|
662
740
|
return;
|
|
@@ -664,7 +742,6 @@ var processSSELine = function* (line, pendingToolCalls, currentUsage) {
|
|
|
664
742
|
const data = trimmed.slice(SSE_DATA_PREFIX_LENGTH);
|
|
665
743
|
if (data === DONE_SENTINEL) {
|
|
666
744
|
yield* flushPendingToolCalls(pendingToolCalls);
|
|
667
|
-
yield { type: "done", usage: currentUsage };
|
|
668
745
|
return;
|
|
669
746
|
}
|
|
670
747
|
let parsed;
|
|
@@ -673,10 +750,28 @@ var processSSELine = function* (line, pendingToolCalls, currentUsage) {
|
|
|
673
750
|
} catch {
|
|
674
751
|
return;
|
|
675
752
|
}
|
|
753
|
+
if (isRecord(parsed.error)) {
|
|
754
|
+
const error = parsed.error;
|
|
755
|
+
const metadata2 = isRecord(error.metadata) ? error.metadata : undefined;
|
|
756
|
+
const status = typeof error.code === "number" ? error.code : null;
|
|
757
|
+
const type = metadata2 && typeof metadata2.error_type === "string" ? metadata2.error_type : typeof error.error_type === "string" ? error.error_type : null;
|
|
758
|
+
throw new ProviderError({
|
|
759
|
+
message: typeof error.message === "string" ? error.message : "OpenRouter stream failed",
|
|
760
|
+
metadata: metadata2,
|
|
761
|
+
provider: providerName,
|
|
762
|
+
retryable: status === 408 || status === 409 || status === 425 || status === 429 || status !== null && status >= 500,
|
|
763
|
+
status,
|
|
764
|
+
type
|
|
765
|
+
});
|
|
766
|
+
}
|
|
676
767
|
const usageUpdate = narrowUsageRecord(parsed);
|
|
677
768
|
if (usageUpdate) {
|
|
678
769
|
yield { type: "usage_update", usage: usageUpdate };
|
|
679
770
|
}
|
|
771
|
+
const metadata = narrowResponseMetadata(parsed);
|
|
772
|
+
if (metadata) {
|
|
773
|
+
yield { metadata, type: "response_metadata" };
|
|
774
|
+
}
|
|
680
775
|
const { choices } = parsed;
|
|
681
776
|
if (!isRecordArray(choices)) {
|
|
682
777
|
return;
|
|
@@ -685,21 +780,46 @@ var processSSELine = function* (line, pendingToolCalls, currentUsage) {
|
|
|
685
780
|
if (!firstChoice) {
|
|
686
781
|
return;
|
|
687
782
|
}
|
|
783
|
+
if (isRecord(firstChoice.error)) {
|
|
784
|
+
const error = firstChoice.error;
|
|
785
|
+
const metadata2 = isRecord(error.metadata) ? error.metadata : undefined;
|
|
786
|
+
const status = typeof error.code === "number" ? error.code : null;
|
|
787
|
+
throw new ProviderError({
|
|
788
|
+
message: typeof error.message === "string" ? error.message : "OpenRouter stream failed",
|
|
789
|
+
metadata: metadata2,
|
|
790
|
+
provider: providerName,
|
|
791
|
+
retryable: status === 429 || status !== null && status >= 500,
|
|
792
|
+
status,
|
|
793
|
+
type: metadata2 && typeof metadata2.error_type === "string" ? metadata2.error_type : null
|
|
794
|
+
});
|
|
795
|
+
}
|
|
688
796
|
yield* processChoice(firstChoice, pendingToolCalls);
|
|
689
797
|
};
|
|
690
798
|
var isUsageUpdate = (chunk) => chunk.type === "usage_update";
|
|
691
|
-
var collectYieldableChunks = (line, pendingToolCalls, usageRef) => {
|
|
692
|
-
const allChunks = Array.from(processSSELine(line, pendingToolCalls,
|
|
799
|
+
var collectYieldableChunks = (line, pendingToolCalls, usageRef, metadataRef, providerName) => {
|
|
800
|
+
const allChunks = Array.from(processSSELine(line, pendingToolCalls, providerName));
|
|
693
801
|
const usageChunks = allChunks.filter(isUsageUpdate);
|
|
694
802
|
const lastUsage = usageChunks.at(NOT_FOUND);
|
|
695
803
|
if (lastUsage) {
|
|
696
804
|
usageRef.current = lastUsage.usage;
|
|
697
805
|
}
|
|
698
|
-
|
|
806
|
+
const metadataChunks = allChunks.filter((chunk) => chunk.type === "response_metadata");
|
|
807
|
+
const lastMetadata = metadataChunks.at(NOT_FOUND);
|
|
808
|
+
if (lastMetadata && "metadata" in lastMetadata) {
|
|
809
|
+
metadataRef.current = {
|
|
810
|
+
...metadataRef.current,
|
|
811
|
+
...lastMetadata.metadata,
|
|
812
|
+
providerMetadata: {
|
|
813
|
+
...metadataRef.current?.providerMetadata,
|
|
814
|
+
...lastMetadata.metadata.providerMetadata
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
return allChunks.filter((chunk) => !isUsageUpdate(chunk) && chunk.type !== "response_metadata");
|
|
699
819
|
};
|
|
700
|
-
var processSSELines = function* (lines, pendingToolCalls, usageRef) {
|
|
820
|
+
var processSSELines = function* (lines, pendingToolCalls, usageRef, metadataRef, providerName) {
|
|
701
821
|
for (const line of lines) {
|
|
702
|
-
yield* collectYieldableChunks(line, pendingToolCalls, usageRef);
|
|
822
|
+
yield* collectYieldableChunks(line, pendingToolCalls, usageRef, metadataRef, providerName);
|
|
703
823
|
}
|
|
704
824
|
};
|
|
705
825
|
var processStreamValue = (value, decoder, state) => {
|
|
@@ -712,51 +832,67 @@ var processStreamValue = (value, decoder, state) => {
|
|
|
712
832
|
var drainReader = async function* (reader, decoder, state, signal) {
|
|
713
833
|
for (let result = await reader.read();!result.done && !signal?.aborted; result = await reader.read()) {
|
|
714
834
|
const lines = processStreamValue(result.value, decoder, state);
|
|
715
|
-
yield* processSSELines(lines, state.pendingToolCalls, state.usageRef);
|
|
835
|
+
yield* processSSELines(lines, state.pendingToolCalls, state.usageRef, state.metadataRef, state.providerName);
|
|
716
836
|
}
|
|
717
837
|
};
|
|
718
|
-
var parseSSEStream = async function* (body, signal) {
|
|
838
|
+
var parseSSEStream = async function* (body, initialMetadata, providerName = "openai", signal) {
|
|
719
839
|
const reader = body.getReader();
|
|
720
840
|
const decoder = new TextDecoder;
|
|
721
841
|
const state = {
|
|
722
842
|
buffer: "",
|
|
843
|
+
metadataRef: { current: initialMetadata },
|
|
723
844
|
pendingToolCalls: new Map,
|
|
845
|
+
providerName,
|
|
724
846
|
usageRef: { current: undefined }
|
|
725
847
|
};
|
|
726
848
|
try {
|
|
727
849
|
yield* drainReader(reader, decoder, state, signal);
|
|
728
|
-
yield {
|
|
850
|
+
yield {
|
|
851
|
+
metadata: state.metadataRef.current,
|
|
852
|
+
type: "done",
|
|
853
|
+
usage: state.usageRef.current
|
|
854
|
+
};
|
|
729
855
|
} finally {
|
|
730
856
|
reader.releaseLock();
|
|
731
857
|
}
|
|
732
858
|
};
|
|
733
|
-
var fetchOpenAIStream = async function* (baseUrl, apiKey, body, signal) {
|
|
859
|
+
var fetchOpenAIStream = async function* (baseUrl, apiKey, body, fetchImpl, headers, providerName, signal) {
|
|
734
860
|
const target = `${baseUrl}/v1/chat/completions`;
|
|
735
|
-
const
|
|
861
|
+
const requestHeaders = new Headers(headers);
|
|
862
|
+
requestHeaders.set("Authorization", `Bearer ${apiKey}`);
|
|
863
|
+
requestHeaders.set("Content-Type", "application/json");
|
|
864
|
+
const response = await fetchImpl(target, {
|
|
736
865
|
...h2IfHttps(target),
|
|
737
866
|
body: JSON.stringify(body),
|
|
738
|
-
headers:
|
|
739
|
-
Authorization: `Bearer ${apiKey}`,
|
|
740
|
-
"Content-Type": "application/json"
|
|
741
|
-
},
|
|
867
|
+
headers: requestHeaders,
|
|
742
868
|
method: "POST",
|
|
743
869
|
signal
|
|
744
870
|
});
|
|
745
871
|
if (!response.ok) {
|
|
746
872
|
const errorText = await response.text();
|
|
747
|
-
throw ProviderError.fromResponse(
|
|
873
|
+
throw ProviderError.fromResponse(providerName, response.status, errorText);
|
|
748
874
|
}
|
|
749
875
|
if (!response.body) {
|
|
750
876
|
throw new ProviderError({
|
|
751
|
-
message:
|
|
752
|
-
provider:
|
|
877
|
+
message: `${providerName} API returned no response body`,
|
|
878
|
+
provider: providerName,
|
|
753
879
|
retryable: true
|
|
754
880
|
});
|
|
755
881
|
}
|
|
756
|
-
yield* parseSSEStream(response.body,
|
|
882
|
+
yield* parseSSEStream(response.body, {
|
|
883
|
+
generationId: response.headers.get("X-Generation-Id") ?? undefined,
|
|
884
|
+
providerMetadata: {
|
|
885
|
+
cacheAge: response.headers.get("X-OpenRouter-Cache-Age") ?? undefined,
|
|
886
|
+
cacheSourceId: response.headers.get("X-OpenRouter-Cache-Source-Id") ?? undefined,
|
|
887
|
+
cacheStatus: response.headers.get("X-OpenRouter-Cache-Status") ?? undefined,
|
|
888
|
+
cacheTtl: response.headers.get("X-OpenRouter-Cache-TTL") ?? undefined
|
|
889
|
+
}
|
|
890
|
+
}, providerName, signal);
|
|
757
891
|
};
|
|
758
892
|
var openai = (config2) => {
|
|
759
893
|
const baseUrl = config2.baseUrl ?? DEFAULT_BASE_URL;
|
|
894
|
+
const fetchImpl = config2.fetch ?? globalThis.fetch;
|
|
895
|
+
const providerName = config2.providerName ?? "openai";
|
|
760
896
|
if (!config2.apiKey && !config2.tokenSource) {
|
|
761
897
|
throw new Error("openai() requires either apiKey or tokenSource");
|
|
762
898
|
}
|
|
@@ -766,19 +902,24 @@ var openai = (config2) => {
|
|
|
766
902
|
}
|
|
767
903
|
return config2.apiKey;
|
|
768
904
|
};
|
|
905
|
+
const resolveHeaders = async (params) => typeof config2.headers === "function" ? await config2.headers(params) : config2.headers ?? {};
|
|
769
906
|
return instrumentAIProvider({
|
|
770
907
|
stream: (params) => {
|
|
771
|
-
const
|
|
908
|
+
const openaiBody = buildRequestBody(params, config2.modelForCapabilities?.(params.model) ?? params.model);
|
|
909
|
+
const body = config2.transformRequestBody ? config2.transformRequestBody(openaiBody, params) : openaiBody;
|
|
772
910
|
return async function* () {
|
|
773
|
-
const apiKey = await
|
|
774
|
-
|
|
911
|
+
const [apiKey, headers] = await Promise.all([
|
|
912
|
+
resolveKey(),
|
|
913
|
+
resolveHeaders(params)
|
|
914
|
+
]);
|
|
915
|
+
yield* fetchOpenAIStream(baseUrl, apiKey, body, fetchImpl, headers, providerName, params.signal);
|
|
775
916
|
}();
|
|
776
917
|
}
|
|
777
|
-
},
|
|
918
|
+
}, providerName);
|
|
778
919
|
};
|
|
779
920
|
export {
|
|
780
921
|
openai
|
|
781
922
|
};
|
|
782
923
|
|
|
783
|
-
//# debugId=
|
|
924
|
+
//# debugId=89626FDD4663206064756E2164756E21
|
|
784
925
|
//# sourceMappingURL=openai.js.map
|